summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-team Robot2018-01-14 02:26:14 -0600
committerandroid-build-team Robot2018-01-14 02:26:14 -0600
commit920b274fd5ad9d79ffbec1d820f91f703b4d276e (patch)
tree21e4f99d52c6d8ae507625cc07557362254169aa
parenteaffd4a2a652305877545cc8d8c46d5e25b0ad3e (diff)
parentb7008f8d49920594ce28dbeb36057394816d1c59 (diff)
downloadplatform-system-libvintf-920b274fd5ad9d79ffbec1d820f91f703b4d276e.tar.gz
platform-system-libvintf-920b274fd5ad9d79ffbec1d820f91f703b4d276e.tar.xz
platform-system-libvintf-920b274fd5ad9d79ffbec1d820f91f703b4d276e.zip
Snap for 4545621 from b7008f8d49920594ce28dbeb36057394816d1c59 to pi-release
Change-Id: Ifd6e5d95557869080270084b84045bf13dd5c2d8
-rw-r--r--Android.bp19
-rw-r--r--AssembleVintf.cpp (renamed from assemble_vintf.cpp)451
-rw-r--r--CompatibilityMatrix.cpp128
-rw-r--r--HalManifest.cpp85
-rw-r--r--assemble_vintf_main.cpp137
-rw-r--r--include-test/vintf/AssembleVintf.h63
-rw-r--r--include/vintf/CompatibilityMatrix.h22
-rw-r--r--include/vintf/HalManifest.h12
-rw-r--r--include/vintf/MatrixKernel.h2
-rw-r--r--include/vintf/Named.h32
-rw-r--r--include/vintf/Sepolicy.h4
-rw-r--r--include/vintf/VendorNdk.h48
-rw-r--r--include/vintf/Vndk.h9
-rw-r--r--include/vintf/parse_string.h10
-rw-r--r--parse_string.cpp3
-rw-r--r--parse_xml.cpp53
-rw-r--r--test/Android.bp7
-rw-r--r--test/AssembleVintfTest.cpp360
-rw-r--r--test/LibVintfTest.cpp115
-rw-r--r--utils.h13
20 files changed, 1247 insertions, 326 deletions
diff --git a/Android.bp b/Android.bp
index 2fd9eef..fea4d38 100644
--- a/Android.bp
+++ b/Android.bp
@@ -105,6 +105,20 @@ cc_binary_host {
105 ], 105 ],
106} 106}
107 107
108cc_library_static {
109 name: "libassemblevintf",
110 host_supported: true,
111 defaults: ["libvintf-defaults"],
112 shared_libs: [
113 "libvintf",
114 "libbase",
115 ],
116 srcs: [
117 "AssembleVintf.cpp",
118 ],
119 export_include_dirs: ["include-test"],
120}
121
108cc_binary_host { 122cc_binary_host {
109 name: "assemble_vintf", 123 name: "assemble_vintf",
110 defaults: ["libvintf-defaults"], 124 defaults: ["libvintf-defaults"],
@@ -112,8 +126,11 @@ cc_binary_host {
112 "libvintf", 126 "libvintf",
113 "libbase", 127 "libbase",
114 ], 128 ],
129 static_libs: [
130 "libassemblevintf",
131 ],
115 srcs: [ 132 srcs: [
116 "assemble_vintf.cpp" 133 "assemble_vintf_main.cpp"
117 ], 134 ],
118} 135}
119 136
diff --git a/assemble_vintf.cpp b/AssembleVintf.cpp
index 0aa79fd..e19096e 100644
--- a/assemble_vintf.cpp
+++ b/AssembleVintf.cpp
@@ -14,22 +14,24 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include <getopt.h>
18#include <stdlib.h> 17#include <stdlib.h>
19#include <unistd.h> 18#include <unistd.h>
20 19
21#include <fstream> 20#include <fstream>
22#include <iostream> 21#include <iostream>
23#include <unordered_map>
24#include <sstream> 22#include <sstream>
25#include <string> 23#include <string>
24#include <unordered_map>
26 25
27#include <android-base/file.h> 26#include <android-base/file.h>
28#include <android-base/parseint.h> 27#include <android-base/parseint.h>
28#include <android-base/strings.h>
29 29
30#include <vintf/AssembleVintf.h>
30#include <vintf/KernelConfigParser.h> 31#include <vintf/KernelConfigParser.h>
31#include <vintf/parse_string.h> 32#include <vintf/parse_string.h>
32#include <vintf/parse_xml.h> 33#include <vintf/parse_xml.h>
34#include "utils.h"
33 35
34#define BUFFER_SIZE sysconf(_SC_PAGESIZE) 36#define BUFFER_SIZE sysconf(_SC_PAGESIZE)
35 37
@@ -58,16 +60,27 @@ class NamedIstream {
58/** 60/**
59 * Slurps the device manifest file and add build time flag to it. 61 * Slurps the device manifest file and add build time flag to it.
60 */ 62 */
61class AssembleVintf { 63class AssembleVintfImpl : public AssembleVintf {
62 using Condition = std::unique_ptr<KernelConfig>; 64 using Condition = std::unique_ptr<KernelConfig>;
63 using ConditionedConfig = std::pair<Condition, std::vector<KernelConfig> /* configs */>; 65 using ConditionedConfig = std::pair<Condition, std::vector<KernelConfig> /* configs */>;
64 66
65 public: 67 public:
66 template<typename T> 68 void setFakeEnv(const std::string& key, const std::string& value) { mFakeEnv[key] = value; }
67 static bool getFlag(const std::string& key, T* value) { 69
68 const char *envValue = getenv(key.c_str()); 70 std::string getEnv(const std::string& key) const {
69 if (envValue == NULL) { 71 auto it = mFakeEnv.find(key);
70 std::cerr << "Warning: " << key << " is missing, defaulted to " << (*value) 72 if (it != mFakeEnv.end()) {
73 return it->second;
74 }
75 const char* envValue = getenv(key.c_str());
76 return envValue != nullptr ? std::string(envValue) : std::string();
77 }
78
79 template <typename T>
80 bool getFlag(const std::string& key, T* value) const {
81 std::string envValue = getEnv(key);
82 if (envValue.empty()) {
83 std::cerr << "Warning: " << key << " is missing, defaulted to " << (*value) << "."
71 << std::endl; 84 << std::endl;
72 return true; 85 return true;
73 } 86 }
@@ -83,15 +96,15 @@ class AssembleVintf {
83 * Set *out to environment variable if *out is not a dummy value (i.e. default constructed). 96 * Set *out to environment variable if *out is not a dummy value (i.e. default constructed).
84 */ 97 */
85 template <typename T> 98 template <typename T>
86 bool getFlagIfUnset(const std::string& envKey, T* out) { 99 bool getFlagIfUnset(const std::string& envKey, T* out) const {
87 bool hasExistingValue = !(*out == T{}); 100 bool hasExistingValue = !(*out == T{});
88 101
89 bool hasEnvValue = false; 102 bool hasEnvValue = false;
90 T envValue; 103 T envValue;
91 const char* envCValue = getenv(envKey.c_str()); 104 std::string envStrValue = getEnv(envKey);
92 if (envCValue != nullptr) { 105 if (!envStrValue.empty()) {
93 if (!parse(envCValue, &envValue)) { 106 if (!parse(envStrValue, &envValue)) {
94 std::cerr << "Cannot parse " << envCValue << "." << std::endl; 107 std::cerr << "Cannot parse " << envValue << "." << std::endl;
95 return false; 108 return false;
96 } 109 }
97 hasEnvValue = true; 110 hasEnvValue = true;
@@ -113,13 +126,10 @@ class AssembleVintf {
113 return true; 126 return true;
114 } 127 }
115 128
116 static bool getBooleanFlag(const char* key) { 129 bool getBooleanFlag(const std::string& key) const { return getEnv(key) == std::string("true"); }
117 const char* envValue = getenv(key);
118 return envValue != nullptr && strcmp(envValue, "true") == 0;
119 }
120 130
121 static size_t getIntegerFlag(const char* key, size_t defaultValue = 0) { 131 size_t getIntegerFlag(const std::string& key, size_t defaultValue = 0) const {
122 std::string envValue = getenv(key); 132 std::string envValue = getEnv(key);
123 if (envValue.empty()) { 133 if (envValue.empty()) {
124 return defaultValue; 134 return defaultValue;
125 } 135 }
@@ -141,18 +151,6 @@ class AssembleVintf {
141 return ::android::base::Basename(path) == gBaseConfig; 151 return ::android::base::Basename(path) == gBaseConfig;
142 } 152 }
143 153
144 static Level convertFromApiLevel(size_t apiLevel) {
145 if (apiLevel < 26) {
146 return Level::LEGACY;
147 } else if (apiLevel == 26) {
148 return Level::O;
149 } else if (apiLevel == 27) {
150 return Level::O_MR1;
151 } else {
152 return Level::UNSPECIFIED;
153 }
154 }
155
156 // nullptr on any error, otherwise the condition. 154 // nullptr on any error, otherwise the condition.
157 static Condition generateCondition(const std::string& path) { 155 static Condition generateCondition(const std::string& path) {
158 std::string fname = ::android::base::Basename(path); 156 std::string fname = ::android::base::Basename(path);
@@ -185,14 +183,10 @@ class AssembleVintf {
185 return std::make_unique<KernelConfig>(std::move(sub), Tristate::YES); 183 return std::make_unique<KernelConfig>(std::move(sub), Tristate::YES);
186 } 184 }
187 185
188 static bool parseFileForKernelConfigs(const std::string& path, std::vector<KernelConfig>* out) { 186 static bool parseFileForKernelConfigs(std::basic_istream<char>& stream,
189 std::ifstream ifs{path}; 187 std::vector<KernelConfig>* out) {
190 if (!ifs.is_open()) {
191 std::cerr << "File '" << path << "' does not exist or cannot be read." << std::endl;
192 return false;
193 }
194 KernelConfigParser parser(true /* processComments */, true /* relaxedFormat */); 188 KernelConfigParser parser(true /* processComments */, true /* relaxedFormat */);
195 std::string content = read(ifs); 189 std::string content = read(stream);
196 status_t err = parser.process(content.c_str(), content.size()); 190 status_t err = parser.process(content.c_str(), content.size());
197 if (err != OK) { 191 if (err != OK) {
198 std::cerr << parser.error(); 192 std::cerr << parser.error();
@@ -217,35 +211,32 @@ class AssembleVintf {
217 return true; 211 return true;
218 } 212 }
219 213
220 static bool parseFilesForKernelConfigs(const std::string& path, 214 static bool parseFilesForKernelConfigs(std::vector<NamedIstream>* streams,
221 std::vector<ConditionedConfig>* out) { 215 std::vector<ConditionedConfig>* out) {
222 out->clear(); 216 out->clear();
223 ConditionedConfig commonConfig; 217 ConditionedConfig commonConfig;
224 bool foundCommonConfig = false; 218 bool foundCommonConfig = false;
225 bool ret = true; 219 bool ret = true;
226 char *pathIter; 220
227 char *modPath = new char[path.length() + 1]; 221 for (auto& namedStream : *streams) {
228 strcpy(modPath, path.c_str()); 222 if (isCommonConfig(namedStream.name())) {
229 pathIter = strtok(modPath, ":"); 223 ret &= parseFileForKernelConfigs(namedStream.stream(), &commonConfig.second);
230 while (ret && pathIter != NULL) {
231 if (isCommonConfig(pathIter)) {
232 ret &= parseFileForKernelConfigs(pathIter, &commonConfig.second);
233 foundCommonConfig = true; 224 foundCommonConfig = true;
234 } else { 225 } else {
235 Condition condition = generateCondition(pathIter); 226 Condition condition = generateCondition(namedStream.name());
236 ret &= (condition != nullptr); 227 ret &= (condition != nullptr);
237 228
238 std::vector<KernelConfig> kernelConfigs; 229 std::vector<KernelConfig> kernelConfigs;
239 if ((ret &= parseFileForKernelConfigs(pathIter, &kernelConfigs))) 230 if ((ret &= parseFileForKernelConfigs(namedStream.stream(), &kernelConfigs)))
240 out->emplace_back(std::move(condition), std::move(kernelConfigs)); 231 out->emplace_back(std::move(condition), std::move(kernelConfigs));
241 } 232 }
242 pathIter = strtok(NULL, ":");
243 } 233 }
244 delete[] modPath;
245 234
246 if (!foundCommonConfig) { 235 if (!foundCommonConfig) {
247 std::cerr << "No android-base.cfg is found in these paths: '" << path << "'" 236 std::cerr << "No android-base.cfg is found in these paths:" << std::endl;
248 << std::endl; 237 for (auto& namedStream : *streams) {
238 std::cerr << " " << namedStream.name() << std::endl;
239 }
249 } 240 }
250 ret &= foundCommonConfig; 241 ret &= foundCommonConfig;
251 // first element is always common configs (no conditions). 242 // first element is always common configs (no conditions).
@@ -253,36 +244,26 @@ class AssembleVintf {
253 return ret; 244 return ret;
254 } 245 }
255 246
256 static std::string getFileNameFromPath(std::string path) { 247 std::basic_ostream<char>& out() const { return mOutRef == nullptr ? std::cout : *mOutRef; }
257 auto idx = path.find_last_of("\\/");
258 if (idx != std::string::npos) {
259 path.erase(0, idx + 1);
260 }
261 return path;
262 }
263
264 std::basic_ostream<char>& out() const {
265 return mOutFileRef == nullptr ? std::cout : *mOutFileRef;
266 }
267 248
268 template <typename S> 249 template <typename S>
269 using Schemas = std::vector<std::pair<std::string, S>>; 250 using Schemas = std::vector<Named<S>>;
270 using HalManifests = Schemas<HalManifest>; 251 using HalManifests = Schemas<HalManifest>;
271 using CompatibilityMatrices = Schemas<CompatibilityMatrix>; 252 using CompatibilityMatrices = Schemas<CompatibilityMatrix>;
272 253
273 bool assembleHalManifest(HalManifests* halManifests) { 254 bool assembleHalManifest(HalManifests* halManifests) {
274 std::string error; 255 std::string error;
275 HalManifest* halManifest = &halManifests->front().second; 256 HalManifest* halManifest = &halManifests->front().object;
276 for (auto it = halManifests->begin() + 1; it != halManifests->end(); ++it) { 257 for (auto it = halManifests->begin() + 1; it != halManifests->end(); ++it) {
277 const std::string& path = it->first; 258 const std::string& path = it->name;
278 HalManifest& halToAdd = it->second; 259 HalManifest& halToAdd = it->object;
279 260
280 if (halToAdd.level() != Level::UNSPECIFIED) { 261 if (halToAdd.level() != Level::UNSPECIFIED) {
281 if (halManifest->level() == Level::UNSPECIFIED) { 262 if (halManifest->level() == Level::UNSPECIFIED) {
282 halManifest->mLevel = halToAdd.level(); 263 halManifest->mLevel = halToAdd.level();
283 } else if (halManifest->level() != halToAdd.level()) { 264 } else if (halManifest->level() != halToAdd.level()) {
284 std::cerr << "Inconsistent FCM Version in HAL manifests:" << std::endl 265 std::cerr << "Inconsistent FCM Version in HAL manifests:" << std::endl
285 << " File '" << halManifests->front().first << "' has level " 266 << " File '" << halManifests->front().name << "' has level "
286 << halManifest->level() << std::endl 267 << halManifest->level() << std::endl
287 << " File '" << path << "' has level " << halToAdd.level() 268 << " File '" << path << "' has level " << halToAdd.level()
288 << std::endl; 269 << std::endl;
@@ -308,6 +289,15 @@ class AssembleVintf {
308 } 289 }
309 } 290 }
310 291
292 if (halManifest->mType == SchemaType::FRAMEWORK) {
293 for (auto&& v : base::Split(getEnv("PROVIDED_VNDK_VERSIONS"), " ")) {
294 v = base::Trim(v);
295 if (!v.empty()) {
296 halManifest->framework.mVendorNdks.emplace_back(std::move(v));
297 }
298 }
299 }
300
311 if (mOutputMatrix) { 301 if (mOutputMatrix) {
312 CompatibilityMatrix generatedMatrix = halManifest->generateCompatibleMatrix(); 302 CompatibilityMatrix generatedMatrix = halManifest->generateCompatibleMatrix();
313 if (!halManifest->checkCompatibility(generatedMatrix, &error)) { 303 if (!halManifest->checkCompatibility(generatedMatrix, &error)) {
@@ -327,9 +317,9 @@ class AssembleVintf {
327 } 317 }
328 out().flush(); 318 out().flush();
329 319
330 if (mCheckFile.is_open()) { 320 if (mCheckFile != nullptr) {
331 CompatibilityMatrix checkMatrix; 321 CompatibilityMatrix checkMatrix;
332 if (!gCompatibilityMatrixConverter(&checkMatrix, read(mCheckFile))) { 322 if (!gCompatibilityMatrixConverter(&checkMatrix, read(*mCheckFile))) {
333 std::cerr << "Cannot parse check file as a compatibility matrix: " 323 std::cerr << "Cannot parse check file as a compatibility matrix: "
334 << gCompatibilityMatrixConverter.lastError() << std::endl; 324 << gCompatibilityMatrixConverter.lastError() << std::endl;
335 return false; 325 return false;
@@ -344,9 +334,9 @@ class AssembleVintf {
344 } 334 }
345 335
346 bool assembleFrameworkCompatibilityMatrixKernels(CompatibilityMatrix* matrix) { 336 bool assembleFrameworkCompatibilityMatrixKernels(CompatibilityMatrix* matrix) {
347 for (const auto& pair : mKernels) { 337 for (auto& pair : mKernels) {
348 std::vector<ConditionedConfig> conditionedConfigs; 338 std::vector<ConditionedConfig> conditionedConfigs;
349 if (!parseFilesForKernelConfigs(pair.second, &conditionedConfigs)) { 339 if (!parseFilesForKernelConfigs(&pair.second, &conditionedConfigs)) {
350 return false; 340 return false;
351 } 341 }
352 for (ConditionedConfig& conditionedConfig : conditionedConfigs) { 342 for (ConditionedConfig& conditionedConfig : conditionedConfigs) {
@@ -374,7 +364,7 @@ class AssembleVintf {
374 if (shippingApiLevel) { 364 if (shippingApiLevel) {
375 std::cerr << "Warning: Shipping FCM Version is inferred from Shipping API level. " 365 std::cerr << "Warning: Shipping FCM Version is inferred from Shipping API level. "
376 << "Declare Shipping FCM Version in device manifest directly." << std::endl; 366 << "Declare Shipping FCM Version in device manifest directly." << std::endl;
377 manifest->mLevel = convertFromApiLevel(shippingApiLevel); 367 manifest->mLevel = details::convertFromApiLevel(shippingApiLevel);
378 if (manifest->mLevel == Level::UNSPECIFIED) { 368 if (manifest->mLevel == Level::UNSPECIFIED) {
379 std::cerr << "Error: Shipping FCM Version cannot be inferred from Shipping API " 369 std::cerr << "Error: Shipping FCM Version cannot be inferred from Shipping API "
380 << "level " << shippingApiLevel << "." 370 << "level " << shippingApiLevel << "."
@@ -400,8 +390,8 @@ class AssembleVintf {
400 Level getLowestFcmVersion(const CompatibilityMatrices& matrices) { 390 Level getLowestFcmVersion(const CompatibilityMatrices& matrices) {
401 Level ret = Level::UNSPECIFIED; 391 Level ret = Level::UNSPECIFIED;
402 for (const auto& e : matrices) { 392 for (const auto& e : matrices) {
403 if (ret == Level::UNSPECIFIED || ret > e.second.level()) { 393 if (ret == Level::UNSPECIFIED || ret > e.object.level()) {
404 ret = e.second.level(); 394 ret = e.object.level();
405 } 395 }
406 } 396 }
407 return ret; 397 return ret;
@@ -410,19 +400,29 @@ class AssembleVintf {
410 bool assembleCompatibilityMatrix(CompatibilityMatrices* matrices) { 400 bool assembleCompatibilityMatrix(CompatibilityMatrices* matrices) {
411 std::string error; 401 std::string error;
412 CompatibilityMatrix* matrix = nullptr; 402 CompatibilityMatrix* matrix = nullptr;
413 KernelSepolicyVersion kernelSepolicyVers;
414 Version sepolicyVers;
415 std::unique_ptr<HalManifest> checkManifest; 403 std::unique_ptr<HalManifest> checkManifest;
416 if (matrices->front().second.mType == SchemaType::DEVICE) { 404 if (matrices->front().object.mType == SchemaType::DEVICE) {
417 matrix = &matrices->front().second; 405 matrix = &matrices->front().object;
406
407 auto vndkVersion = base::Trim(getEnv("REQUIRED_VNDK_VERSION"));
408 if (!vndkVersion.empty()) {
409 auto& valueInMatrix = matrix->device.mVendorNdk;
410 if (!valueInMatrix.version().empty() && valueInMatrix.version() != vndkVersion) {
411 std::cerr << "Hard-coded <vendor-ndk> version in device compatibility matrix ("
412 << matrices->front().name << "), '" << valueInMatrix.version()
413 << "', does not match value inferred "
414 << "from BOARD_VNDK_VERSION '" << vndkVersion << "'" << std::endl;
415 return false;
416 }
417 valueInMatrix = VendorNdk{std::move(vndkVersion)};
418 }
418 } 419 }
419 420
420 if (matrices->front().second.mType == SchemaType::FRAMEWORK) { 421 if (matrices->front().object.mType == SchemaType::FRAMEWORK) {
421 Level deviceLevel = Level::UNSPECIFIED; 422 Level deviceLevel = Level::UNSPECIFIED;
422 std::vector<std::string> fileList; 423 if (mCheckFile != nullptr) {
423 if (mCheckFile.is_open()) {
424 checkManifest = std::make_unique<HalManifest>(); 424 checkManifest = std::make_unique<HalManifest>();
425 if (!gHalManifestConverter(checkManifest.get(), read(mCheckFile))) { 425 if (!gHalManifestConverter(checkManifest.get(), read(*mCheckFile))) {
426 std::cerr << "Cannot parse check file as a HAL manifest: " 426 std::cerr << "Cannot parse check file as a HAL manifest: "
427 << gHalManifestConverter.lastError() << std::endl; 427 << gHalManifestConverter.lastError() << std::endl;
428 return false; 428 return false;
@@ -436,55 +436,39 @@ class AssembleVintf {
436 deviceLevel = getLowestFcmVersion(*matrices); 436 deviceLevel = getLowestFcmVersion(*matrices);
437 } 437 }
438 438
439 for (auto& e : *matrices) { 439 if (deviceLevel == Level::UNSPECIFIED) {
440 if (e.second.level() == deviceLevel) { 440 // building empty.xml
441 fileList.push_back(e.first); 441 matrix = &matrices->front().object;
442 matrix = &e.second; 442 } else {
443 } 443 matrix = CompatibilityMatrix::combine(deviceLevel, matrices, &error);
444 } 444 if (matrix == nullptr) {
445 if (matrix == nullptr) { 445 std::cerr << error << std::endl;
446 std::cerr << "FATAL ERROR: cannot find matrix with level '" << deviceLevel << "'"
447 << std::endl;
448 return false;
449 }
450 for (auto& e : *matrices) {
451 if (e.second.level() <= deviceLevel) {
452 continue;
453 }
454 fileList.push_back(e.first);
455 if (!matrix->addAllHalsAsOptional(&e.second, &error)) {
456 std::cerr << "File \"" << e.first << "\" cannot be added: " << error
457 << ". See <hal> with the same name "
458 << "in previously parsed files or previously declared in this file."
459 << std::endl;
460 return false; 446 return false;
461 } 447 }
462 } 448 }
463 449
464 if (!getFlag("BOARD_SEPOLICY_VERS", &sepolicyVers)) {
465 return false;
466 }
467 if (!getFlag("POLICYVERS", &kernelSepolicyVers)) {
468 return false;
469 }
470
471 if (!assembleFrameworkCompatibilityMatrixKernels(matrix)) { 450 if (!assembleFrameworkCompatibilityMatrixKernels(matrix)) {
472 return false; 451 return false;
473 } 452 }
474 453
475 matrix->framework.mSepolicy = 454 // set sepolicy.sepolicy-version to BOARD_SEPOLICY_VERS when none is specified.
476 Sepolicy(kernelSepolicyVers, {{sepolicyVers.majorVer, sepolicyVers.minorVer}}); 455 std::vector<VersionRange>* sepolicyVrs =
477 456 &matrix->framework.mSepolicy.mSepolicyVersionRanges;
478 Version avbMetaVersion; 457 VersionRange sepolicyVr;
479 if (!getFlag("FRAMEWORK_VBMETA_VERSION", &avbMetaVersion)) { 458 if (!sepolicyVrs->empty()) sepolicyVr = sepolicyVrs->front();
480 return false; 459 if (getFlagIfUnset("BOARD_SEPOLICY_VERS", &sepolicyVr)) {
460 *sepolicyVrs = {{sepolicyVr}};
481 } 461 }
482 matrix->framework.mAvbMetaVersion = avbMetaVersion; 462
463 getFlagIfUnset("POLICYVERS", &matrix->framework.mSepolicy.mKernelSepolicyVersion);
464 getFlagIfUnset("FRAMEWORK_VBMETA_VERSION", &matrix->framework.mAvbMetaVersion);
483 465
484 out() << "<!--" << std::endl; 466 out() << "<!--" << std::endl;
485 out() << " Input:" << std::endl; 467 out() << " Input:" << std::endl;
486 for (const auto& path : fileList) { 468 for (const auto& e : *matrices) {
487 out() << " " << getFileNameFromPath(path) << std::endl; 469 if (!e.name.empty()) {
470 out() << " " << base::Basename(e.name) << std::endl;
471 }
488 } 472 }
489 out() << "-->" << std::endl; 473 out() << "-->" << std::endl;
490 } 474 }
@@ -533,7 +517,7 @@ class AssembleVintf {
533 return assemble(&schemas) ? SUCCESS : FAIL_AND_EXIT; 517 return assemble(&schemas) ? SUCCESS : FAIL_AND_EXIT;
534 } 518 }
535 519
536 bool assemble() { 520 bool assemble() override {
537 using std::placeholders::_1; 521 using std::placeholders::_1;
538 if (mInFiles.empty()) { 522 if (mInFiles.empty()) {
539 std::cerr << "Missing input file." << std::endl; 523 std::cerr << "Missing input file." << std::endl;
@@ -541,14 +525,14 @@ class AssembleVintf {
541 } 525 }
542 526
543 auto status = tryAssemble(gHalManifestConverter, "manifest", 527 auto status = tryAssemble(gHalManifestConverter, "manifest",
544 std::bind(&AssembleVintf::assembleHalManifest, this, _1)); 528 std::bind(&AssembleVintfImpl::assembleHalManifest, this, _1));
545 if (status == SUCCESS) return true; 529 if (status == SUCCESS) return true;
546 if (status == FAIL_AND_EXIT) return false; 530 if (status == FAIL_AND_EXIT) return false;
547 531
548 resetInFiles(); 532 resetInFiles();
549 533
550 status = tryAssemble(gCompatibilityMatrixConverter, "compatibility matrix", 534 status = tryAssemble(gCompatibilityMatrixConverter, "compatibility matrix",
551 std::bind(&AssembleVintf::assembleCompatibilityMatrix, this, _1)); 535 std::bind(&AssembleVintfImpl::assembleCompatibilityMatrix, this, _1));
552 if (status == SUCCESS) return true; 536 if (status == SUCCESS) return true;
553 if (status == FAIL_AND_EXIT) return false; 537 if (status == FAIL_AND_EXIT) return false;
554 538
@@ -560,22 +544,30 @@ class AssembleVintf {
560 return false; 544 return false;
561 } 545 }
562 546
563 bool openOutFile(const char* path) { 547 std::ostream& setOutputStream(Ostream&& out) override {
564 mOutFileRef = std::make_unique<std::ofstream>(); 548 mOutRef = std::move(out);
565 mOutFileRef->open(path); 549 return *mOutRef;
566 return mOutFileRef->is_open();
567 } 550 }
568 551
569 bool openInFile(const char* path) { 552 std::istream& addInputStream(const std::string& name, Istream&& in) override {
570 auto s = std::make_unique<std::ifstream>(path); 553 auto it = mInFiles.emplace(mInFiles.end(), name, std::move(in));
571 if (!s->is_open()) return false; 554 return it->stream();
572 mInFiles.emplace(mInFiles.end(), std::string{path}, std::move(s)); 555 }
573 return true; 556
557 std::istream& setCheckInputStream(Istream&& in) override {
558 mCheckFile = std::move(in);
559 return *mCheckFile;
574 } 560 }
575 561
576 bool openCheckFile(const char* path) { 562 bool hasKernelVersion(const Version& kernelVer) const override {
577 mCheckFile.open(path); 563 return mKernels.find(kernelVer) != mKernels.end();
578 return mCheckFile.is_open(); 564 }
565
566 std::istream& addKernelConfigInputStream(const Version& kernelVer, const std::string& name,
567 Istream&& in) override {
568 auto&& kernel = mKernels[kernelVer];
569 auto it = kernel.emplace(kernel.end(), name, std::move(in));
570 return it->stream();
579 } 571 }
580 572
581 void resetInFiles() { 573 void resetInFiles() {
@@ -585,169 +577,76 @@ class AssembleVintf {
585 } 577 }
586 } 578 }
587 579
588 void setOutputMatrix() { mOutputMatrix = true; } 580 void setOutputMatrix() override { mOutputMatrix = true; }
589 581
590 bool setHalsOnly() { 582 bool setHalsOnly() override {
591 if (mSerializeFlags) return false; 583 if (mSerializeFlags) return false;
592 mSerializeFlags |= SerializeFlag::HALS_ONLY; 584 mSerializeFlags |= SerializeFlag::HALS_ONLY;
593 return true; 585 return true;
594 } 586 }
595 587
596 bool setNoHals() { 588 bool setNoHals() override {
597 if (mSerializeFlags) return false; 589 if (mSerializeFlags) return false;
598 mSerializeFlags |= SerializeFlag::NO_HALS; 590 mSerializeFlags |= SerializeFlag::NO_HALS;
599 return true; 591 return true;
600 } 592 }
601 593
602 bool addKernel(const std::string& kernelArg) {
603 auto ind = kernelArg.find(':');
604 if (ind == std::string::npos) {
605 std::cerr << "Unrecognized --kernel option '" << kernelArg << "'" << std::endl;
606 return false;
607 }
608 std::string kernelVerStr{kernelArg.begin(), kernelArg.begin() + ind};
609 std::string kernelConfigPath{kernelArg.begin() + ind + 1, kernelArg.end()};
610 Version kernelVer;
611 if (!parse(kernelVerStr, &kernelVer)) {
612 std::cerr << "Unrecognized kernel version '" << kernelVerStr << "'" << std::endl;
613 return false;
614 }
615 if (mKernels.find(kernelVer) != mKernels.end()) {
616 std::cerr << "Multiple --kernel for " << kernelVer << " is specified." << std::endl;
617 return false;
618 }
619 mKernels[kernelVer] = kernelConfigPath;
620 return true;
621 }
622
623 private: 594 private:
624 std::vector<NamedIstream> mInFiles; 595 std::vector<NamedIstream> mInFiles;
625 std::unique_ptr<std::ofstream> mOutFileRef; 596 Ostream mOutRef;
626 std::ifstream mCheckFile; 597 Istream mCheckFile;
627 bool mOutputMatrix = false; 598 bool mOutputMatrix = false;
628 SerializeFlags mSerializeFlags = SerializeFlag::EVERYTHING; 599 SerializeFlags mSerializeFlags = SerializeFlag::EVERYTHING;
629 std::map<Version, std::string> mKernels; 600 std::map<Version, std::vector<NamedIstream>> mKernels;
601 std::map<std::string, std::string> mFakeEnv;
630}; 602};
631 603
632} // namespace vintf 604bool AssembleVintf::openOutFile(const std::string& path) {
633} // namespace android 605 return static_cast<std::ofstream&>(setOutputStream(std::make_unique<std::ofstream>(path)))
634 606 .is_open();
635void help() {
636 std::cerr << "assemble_vintf: Checks if a given manifest / matrix file is valid and \n"
637 " fill in build-time flags into the given file.\n"
638 "assemble_vintf -h\n"
639 " Display this help text.\n"
640 "assemble_vintf -i <input file>[:<input file>[...]] [-o <output file>] [-m]\n"
641 " [-c [<check file>]]\n"
642 " Fill in build-time flags into the given file.\n"
643 " -i <input file>[:<input file>[...]]\n"
644 " A list of input files. Format is automatically detected for the\n"
645 " first file, and the remaining files must have the same format.\n"
646 " Files other than the first file should only have <hal> defined;\n"
647 " other entries are ignored.\n"
648 " -o <output file>\n"
649 " Optional output file. If not specified, write to stdout.\n"
650 " -m\n"
651 " a compatible compatibility matrix is\n"
652 " generated instead; for example, given a device manifest,\n"
653 " a framework compatibility matrix is generated. This flag\n"
654 " is ignored when input is a compatibility matrix.\n"
655 " -c [<check file>]\n"
656 " After writing the output file, check compatibility between\n"
657 " output file and check file.\n"
658 " If -c is set but the check file is not specified, a warning\n"
659 " message is written to stderr. Return 0.\n"
660 " If the check file is specified but is not compatible, an error\n"
661 " message is written to stderr. Return 1.\n"
662 " --kernel=<version>:<android-base.cfg>[:<android-base-arch.cfg>[...]]\n"
663 " Add a kernel entry to framework compatibility matrix.\n"
664 " Ignored for other input format.\n"
665 " <version> has format: 3.18\n"
666 " <android-base.cfg> is the location of android-base.cfg\n"
667 " <android-base-arch.cfg> is the location of an optional\n"
668 " arch-specific config fragment, more than one may be specified\n"
669 " -l, --hals-only\n"
670 " Output has only <hal> entries. Cannot be used with -n.\n"
671 " -n, --no-hals\n"
672 " Output has no <hal> entries (but all other entries).\n"
673 " Cannot be used with -l.\n";
674} 607}
675 608
676int main(int argc, char **argv) { 609bool AssembleVintf::openInFile(const std::string& path) {
677 const struct option longopts[] = {{"kernel", required_argument, NULL, 'k'}, 610 return static_cast<std::ifstream&>(addInputStream(path, std::make_unique<std::ifstream>(path)))
678 {"hals-only", no_argument, NULL, 'l'}, 611 .is_open();
679 {"no-hals", no_argument, NULL, 'n'}, 612}
680 {0, 0, 0, 0}};
681
682 std::string outFilePath;
683 ::android::vintf::AssembleVintf assembleVintf;
684 int res;
685 int optind;
686 while ((res = getopt_long(argc, argv, "hi:o:mc:nl", longopts, &optind)) >= 0) {
687 switch (res) {
688 case 'i': {
689 char* inFilePath = strtok(optarg, ":");
690 while (inFilePath != NULL) {
691 if (!assembleVintf.openInFile(inFilePath)) {
692 std::cerr << "Failed to open " << optarg << std::endl;
693 return 1;
694 }
695 inFilePath = strtok(NULL, ":");
696 }
697 } break;
698
699 case 'o': {
700 outFilePath = optarg;
701 if (!assembleVintf.openOutFile(optarg)) {
702 std::cerr << "Failed to open " << optarg << std::endl;
703 return 1;
704 }
705 } break;
706
707 case 'm': {
708 assembleVintf.setOutputMatrix();
709 } break;
710
711 case 'c': {
712 if (strlen(optarg) != 0) {
713 if (!assembleVintf.openCheckFile(optarg)) {
714 std::cerr << "Failed to open " << optarg << std::endl;
715 return 1;
716 }
717 } else {
718 std::cerr << "WARNING: no compatibility check is done on "
719 << (outFilePath.empty() ? "output" : outFilePath) << std::endl;
720 }
721 } break;
722
723 case 'k': {
724 if (!assembleVintf.addKernel(optarg)) {
725 std::cerr << "ERROR: Unrecognized --kernel argument." << std::endl;
726 return 1;
727 }
728 } break;
729
730 case 'l': {
731 if (!assembleVintf.setHalsOnly()) {
732 return 1;
733 }
734 } break;
735 613
736 case 'n': { 614bool AssembleVintf::openCheckFile(const std::string& path) {
737 if (!assembleVintf.setNoHals()) { 615 return static_cast<std::ifstream&>(setCheckInputStream(std::make_unique<std::ifstream>(path)))
738 return 1; 616 .is_open();
739 } 617}
740 } break;
741 618
742 case 'h': 619bool AssembleVintf::addKernel(const std::string& kernelArg) {
743 default: { 620 auto tokens = base::Split(kernelArg, ":");
744 help(); 621 if (tokens.size() <= 1) {
745 return 1; 622 std::cerr << "Unrecognized --kernel option '" << kernelArg << "'" << std::endl;
746 } break; 623 return false;
624 }
625 Version kernelVer;
626 if (!parse(tokens.front(), &kernelVer)) {
627 std::cerr << "Unrecognized kernel version '" << tokens.front() << "'" << std::endl;
628 return false;
629 }
630 if (hasKernelVersion(kernelVer)) {
631 std::cerr << "Multiple --kernel for " << kernelVer << " is specified." << std::endl;
632 return false;
633 }
634 for (auto it = tokens.begin() + 1; it != tokens.end(); ++it) {
635 bool opened =
636 static_cast<std::ifstream&>(
637 addKernelConfigInputStream(kernelVer, *it, std::make_unique<std::ifstream>(*it)))
638 .is_open();
639 if (!opened) {
640 std::cerr << "Cannot open file '" << *it << "'." << std::endl;
641 return false;
747 } 642 }
748 } 643 }
644 return true;
645}
749 646
750 bool success = assembleVintf.assemble(); 647std::unique_ptr<AssembleVintf> AssembleVintf::newInstance() {
751 648 return std::make_unique<AssembleVintfImpl>();
752 return success ? 0 : 1;
753} 649}
650
651} // namespace vintf
652} // namespace android
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index 1e7d542..8331f78 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -21,6 +21,9 @@
21#include "parse_string.h" 21#include "parse_string.h"
22#include "utils.h" 22#include "utils.h"
23 23
24#include <iostream>
25#include "parse_xml.h"
26
24namespace android { 27namespace android {
25namespace vintf { 28namespace vintf {
26 29
@@ -159,12 +162,135 @@ bool CompatibilityMatrix::addAllXmlFilesAsOptional(CompatibilityMatrix* other, s
159bool operator==(const CompatibilityMatrix &lft, const CompatibilityMatrix &rgt) { 162bool operator==(const CompatibilityMatrix &lft, const CompatibilityMatrix &rgt) {
160 return lft.mType == rgt.mType && lft.mLevel == rgt.mLevel && lft.mHals == rgt.mHals && 163 return lft.mType == rgt.mType && lft.mLevel == rgt.mLevel && lft.mHals == rgt.mHals &&
161 lft.mXmlFiles == rgt.mXmlFiles && 164 lft.mXmlFiles == rgt.mXmlFiles &&
162 (lft.mType != SchemaType::DEVICE || (lft.device.mVndk == rgt.device.mVndk)) && 165 (lft.mType != SchemaType::DEVICE ||
166 (
167#pragma clang diagnostic push
168#pragma clang diagnostic ignored "-Wdeprecated-declarations"
169 lft.device.mVndk == rgt.device.mVndk &&
170#pragma clang diagnostic pop
171 lft.device.mVendorNdk == rgt.device.mVendorNdk)) &&
163 (lft.mType != SchemaType::FRAMEWORK || 172 (lft.mType != SchemaType::FRAMEWORK ||
164 (lft.framework.mKernels == rgt.framework.mKernels && 173 (lft.framework.mKernels == rgt.framework.mKernels &&
165 lft.framework.mSepolicy == rgt.framework.mSepolicy && 174 lft.framework.mSepolicy == rgt.framework.mSepolicy &&
166 lft.framework.mAvbMetaVersion == rgt.framework.mAvbMetaVersion)); 175 lft.framework.mAvbMetaVersion == rgt.framework.mAvbMetaVersion));
167} 176}
168 177
178// Find compatibility_matrix.empty.xml (which has unspecified level) and use it
179// as a base matrix.
180CompatibilityMatrix* CompatibilityMatrix::findOrInsertBaseMatrix(
181 std::vector<Named<CompatibilityMatrix>>* matrices, std::string* error) {
182 bool multipleFound = false;
183 CompatibilityMatrix* matrix = nullptr;
184 for (auto& e : *matrices) {
185 if (e.object.level() == Level::UNSPECIFIED) {
186 if (!e.object.mHals.empty()) {
187 if (error) {
188 *error = "Error: File \"" + e.name + "\" should not contain " + "HAL elements.";
189 }
190 return nullptr;
191 }
192
193 if (!e.object.mXmlFiles.empty()) {
194 if (error) {
195 *error =
196 "Error: File \"" + e.name + "\" should not contain " + "XML File elements.";
197 }
198 return nullptr;
199 }
200
201 if (matrix != nullptr) {
202 multipleFound = true;
203 }
204
205 matrix = &e.object;
206 // continue to detect multiple files with "unspecified" levels
207 }
208 }
209
210 if (multipleFound) {
211 if (error) {
212 *error =
213 "Error: multiple framework compatibility matrix files have "
214 "unspecified level; there should only be one such file.\n";
215 for (auto& e : *matrices) {
216 if (e.object.level() == Level::UNSPECIFIED) {
217 *error += " " + e.name + "\n";
218 }
219 }
220 }
221 return nullptr;
222 }
223
224 if (matrix == nullptr) {
225 matrix = &matrices->emplace(matrices->end())->object;
226 matrix->mType = SchemaType::FRAMEWORK;
227 matrix->mLevel = Level::UNSPECIFIED;
228 }
229
230 return matrix;
231}
232
233CompatibilityMatrix* CompatibilityMatrix::combine(Level deviceLevel,
234 std::vector<Named<CompatibilityMatrix>>* matrices,
235 std::string* error) {
236 if (deviceLevel == Level::UNSPECIFIED) {
237 if (error) {
238 *error = "Error: device level is unspecified.";
239 }
240 return nullptr;
241 }
242
243 CompatibilityMatrix* matrix = findOrInsertBaseMatrix(matrices, error);
244 if (matrix == nullptr) {
245 return nullptr;
246 }
247
248 matrix->mLevel = deviceLevel;
249
250 for (auto& e : *matrices) {
251 if (&e.object != matrix && e.object.level() == deviceLevel) {
252 if (!matrix->addAllHals(&e.object, error)) {
253 if (error) {
254 *error = "File \"" + e.name + "\" cannot be added: HAL " + *error +
255 " has a conflict.";
256 }
257 return nullptr;
258 }
259
260 if (!matrix->addAllXmlFiles(&e.object, error)) {
261 if (error) {
262 *error = "File \"" + e.name + "\" cannot be added: XML File entry " + *error +
263 " has a conflict.";
264 }
265 return nullptr;
266 }
267 }
268 }
269
270 for (auto& e : *matrices) {
271 if (&e.object != matrix && e.object.level() != Level::UNSPECIFIED &&
272 e.object.level() > deviceLevel) {
273 if (!matrix->addAllHalsAsOptional(&e.object, error)) {
274 if (error) {
275 *error = "File \"" + e.name + "\" cannot be added: " + *error +
276 ". See <hal> with the same name " +
277 "in previously parsed files or previously declared in this file.";
278 }
279 return nullptr;
280 }
281
282 if (!matrix->addAllXmlFilesAsOptional(&e.object, error)) {
283 if (error) {
284 *error = "File \"" + e.name + "\" cannot be added: XML File entry " + *error +
285 " has a conflict.";
286 }
287 return nullptr;
288 }
289 }
290 }
291
292 return matrix;
293}
294
169} // namespace vintf 295} // namespace vintf
170} // namespace android 296} // namespace android
diff --git a/HalManifest.cpp b/HalManifest.cpp
index cd4302f..45816f6 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -213,6 +213,47 @@ std::vector<std::string> HalManifest::checkIncompatibility(const CompatibilityMa
213 return incompatible; 213 return incompatible;
214} 214}
215 215
216static bool checkVendorNdkCompatibility(const VendorNdk& matVendorNdk,
217 const std::vector<VendorNdk>& manifestVendorNdk,
218 std::string* error) {
219 // For pre-P vendor images, device compatibility matrix does not specify <vendor-ndk>
220 // tag. Ignore the check for these devices.
221 if (matVendorNdk.version().empty()) {
222 return true;
223 }
224 for (const auto& vndk : manifestVendorNdk) {
225 if (vndk.version() != matVendorNdk.version()) {
226 continue;
227 }
228 // version matches, check libraries
229 std::vector<std::string> diff;
230 std::set_difference(matVendorNdk.libraries().begin(), matVendorNdk.libraries().end(),
231 vndk.libraries().begin(), vndk.libraries().end(),
232 std::inserter(diff, diff.begin()));
233 if (!diff.empty()) {
234 if (error != nullptr) {
235 *error = "Vndk libs incompatible for version " + matVendorNdk.version() +
236 ". These libs are not in framework manifest:";
237 for (const auto& name : diff) {
238 *error += " " + name;
239 }
240 }
241 return false;
242 }
243 return true;
244 }
245
246 // no match is found.
247 if (error != nullptr) {
248 *error = "Vndk version " + matVendorNdk.version() + " is not supported. " +
249 "Supported versions in framework manifest are:";
250 for (const auto& vndk : manifestVendorNdk) {
251 *error += " " + vndk.version();
252 }
253 }
254 return false;
255}
256
216bool HalManifest::checkCompatibility(const CompatibilityMatrix &mat, std::string *error) const { 257bool HalManifest::checkCompatibility(const CompatibilityMatrix &mat, std::string *error) const {
217 if (mType == mat.mType) { 258 if (mType == mat.mType) {
218 if (error != nullptr) { 259 if (error != nullptr) {
@@ -233,37 +274,9 @@ bool HalManifest::checkCompatibility(const CompatibilityMatrix &mat, std::string
233 return false; 274 return false;
234 } 275 }
235 if (mType == SchemaType::FRAMEWORK) { 276 if (mType == SchemaType::FRAMEWORK) {
236 // TODO(b/36400653) enable this. It is disabled since vndk is not yet defined. 277 if (!checkVendorNdkCompatibility(mat.device.mVendorNdk, framework.mVendorNdks, error)) {
237#ifdef VINTF_CHECK_VNDK 278 return false;
238 bool match = false;
239 const auto &matVndk = mat.device.mVndk;
240 for (const auto &vndk : framework.mVndks) {
241 if (!vndk.mVersionRange.in(matVndk.mVersionRange)) {
242 continue;
243 }
244 // version matches, check libaries
245 std::vector<std::string> diff;
246 std::set_difference(matVndk.mLibraries.begin(), matVndk.mLibraries.end(),
247 vndk.mLibraries.begin(), vndk.mLibraries.end(),
248 std::inserter(diff, diff.begin()))
249 if (!diff.empty()) {
250 if (error != nullptr) {
251 *error = "Vndk libs incompatible.";
252 for (const auto &name : diff) {
253 *error += " " + name;
254 }
255 }
256 return false;
257 }
258 match = true;
259 break;
260 }
261 if (!match) {
262 if (error != nullptr) {
263 *error = "Vndk version " + to_string(matVndk.mVersionRange) + " is not supported.";
264 }
265 } 279 }
266#endif
267 } else if (mType == SchemaType::DEVICE) { 280 } else if (mType == SchemaType::DEVICE) {
268 bool match = false; 281 bool match = false;
269 for (const auto &range : mat.framework.mSepolicy.sepolicyVersions()) { 282 for (const auto &range : mat.framework.mSepolicy.sepolicyVersions()) {
@@ -332,9 +345,9 @@ const Version &HalManifest::sepolicyVersion() const {
332 return device.mSepolicyVersion; 345 return device.mSepolicyVersion;
333} 346}
334 347
335const std::vector<Vndk> &HalManifest::vndks() const { 348const std::vector<VendorNdk>& HalManifest::vendorNdks() const {
336 CHECK(mType == SchemaType::FRAMEWORK); 349 CHECK(mType == SchemaType::FRAMEWORK);
337 return framework.mVndks; 350 return framework.mVendorNdks;
338} 351}
339 352
340std::string HalManifest::getXmlFilePath(const std::string& xmlFileName, 353std::string HalManifest::getXmlFilePath(const std::string& xmlFileName,
@@ -360,7 +373,13 @@ bool operator==(const HalManifest &lft, const HalManifest &rgt) {
360 lft.mXmlFiles == rgt.mXmlFiles && 373 lft.mXmlFiles == rgt.mXmlFiles &&
361 (lft.mType != SchemaType::DEVICE || 374 (lft.mType != SchemaType::DEVICE ||
362 (lft.device.mSepolicyVersion == rgt.device.mSepolicyVersion)) && 375 (lft.device.mSepolicyVersion == rgt.device.mSepolicyVersion)) &&
363 (lft.mType != SchemaType::FRAMEWORK || (lft.framework.mVndks == rgt.framework.mVndks)); 376 (lft.mType != SchemaType::FRAMEWORK ||
377 (
378#pragma clang diagnostic push
379#pragma clang diagnostic ignored "-Wdeprecated-declarations"
380 lft.framework.mVndks == rgt.framework.mVndks &&
381#pragma clang diagnostic pop
382 lft.framework.mVendorNdks == rgt.framework.mVendorNdks));
364} 383}
365 384
366} // namespace vintf 385} // namespace vintf
diff --git a/assemble_vintf_main.cpp b/assemble_vintf_main.cpp
new file mode 100644
index 0000000..45e6dc2
--- /dev/null
+++ b/assemble_vintf_main.cpp
@@ -0,0 +1,137 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <getopt.h>
18
19#include <iostream>
20
21#include <android-base/strings.h>
22#include <vintf/AssembleVintf.h>
23#include "utils.h"
24
25void help() {
26 std::cerr << "assemble_vintf: Checks if a given manifest / matrix file is valid and \n"
27 " fill in build-time flags into the given file.\n"
28 "assemble_vintf -h\n"
29 " Display this help text.\n"
30 "assemble_vintf -i <input file>[:<input file>[...]] [-o <output file>] [-m]\n"
31 " [-c [<check file>]]\n"
32 " Fill in build-time flags into the given file.\n"
33 " -i <input file>[:<input file>[...]]\n"
34 " A list of input files. Format is automatically detected for the\n"
35 " first file, and the remaining files must have the same format.\n"
36 " Files other than the first file should only have <hal> defined;\n"
37 " other entries are ignored.\n"
38 " -o <output file>\n"
39 " Optional output file. If not specified, write to stdout.\n"
40 " -m\n"
41 " a compatible compatibility matrix is\n"
42 " generated instead; for example, given a device manifest,\n"
43 " a framework compatibility matrix is generated. This flag\n"
44 " is ignored when input is a compatibility matrix.\n"
45 " -c [<check file>]\n"
46 " After writing the output file, check compatibility between\n"
47 " output file and check file.\n"
48 " If -c is set but the check file is not specified, a warning\n"
49 " message is written to stderr. Return 0.\n"
50 " If the check file is specified but is not compatible, an error\n"
51 " message is written to stderr. Return 1.\n"
52 " --kernel=<version>:<android-base.cfg>[:<android-base-arch.cfg>[...]]\n"
53 " Add a kernel entry to framework compatibility matrix.\n"
54 " Ignored for other input format.\n"
55 " <version> has format: 3.18\n"
56 " <android-base.cfg> is the location of android-base.cfg\n"
57 " <android-base-arch.cfg> is the location of an optional\n"
58 " arch-specific config fragment, more than one may be specified\n"
59 " -l, --hals-only\n"
60 " Output has only <hal> entries. Cannot be used with -n.\n"
61 " -n, --no-hals\n"
62 " Output has no <hal> entries (but all other entries).\n"
63 " Cannot be used with -l.\n";
64}
65
66int main(int argc, char** argv) {
67 using namespace ::android::vintf;
68 const struct option longopts[] = {{"kernel", required_argument, NULL, 'k'},
69 {"hals-only", no_argument, NULL, 'l'},
70 {"no-hals", no_argument, NULL, 'n'},
71 {0, 0, 0, 0}};
72
73 std::string outFilePath;
74 auto assembleVintf = AssembleVintf::newInstance();
75 int res;
76 int optind;
77 while ((res = getopt_long(argc, argv, "hi:o:mc:nl", longopts, &optind)) >= 0) {
78 switch (res) {
79 case 'i': {
80 for (const auto& inFilePath : ::android::base::Split(optarg, ":")) {
81 if (!assembleVintf->openInFile(inFilePath.c_str())) {
82 std::cerr << "Failed to open " << inFilePath << std::endl;
83 return 1;
84 }
85 }
86 } break;
87
88 case 'o': {
89 outFilePath = optarg;
90 if (!assembleVintf->openOutFile(optarg)) {
91 std::cerr << "Failed to open " << optarg << std::endl;
92 return 1;
93 }
94 } break;
95
96 case 'm': {
97 assembleVintf->setOutputMatrix();
98 } break;
99
100 case 'c': {
101 if (!assembleVintf->openCheckFile(optarg)) {
102 std::cerr << "Failed to open " << optarg << std::endl;
103 return 1;
104 }
105 } break;
106
107 case 'k': {
108 if (!assembleVintf->addKernel(optarg)) {
109 std::cerr << "ERROR: Unrecognized --kernel argument." << std::endl;
110 return 1;
111 }
112 } break;
113
114 case 'l': {
115 if (!assembleVintf->setHalsOnly()) {
116 return 1;
117 }
118 } break;
119
120 case 'n': {
121 if (!assembleVintf->setNoHals()) {
122 return 1;
123 }
124 } break;
125
126 case 'h':
127 default: {
128 help();
129 return 1;
130 } break;
131 }
132 }
133
134 bool success = assembleVintf->assemble();
135
136 return success ? 0 : 1;
137}
diff --git a/include-test/vintf/AssembleVintf.h b/include-test/vintf/AssembleVintf.h
new file mode 100644
index 0000000..1b457eb
--- /dev/null
+++ b/include-test/vintf/AssembleVintf.h
@@ -0,0 +1,63 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_VINTF_ASSEMBLE_VINTF_H
18#define ANDROID_VINTF_ASSEMBLE_VINTF_H
19
20#include <fstream>
21#include <iostream>
22#include <memory>
23#include <string>
24#include <vector>
25
26#include <vintf/Version.h>
27
28namespace android {
29namespace vintf {
30
31class AssembleVintf {
32 public:
33 using Ostream = std::unique_ptr<std::ostream>;
34 using Istream = std::unique_ptr<std::istream>;
35
36 static std::unique_ptr<AssembleVintf> newInstance();
37
38 virtual ~AssembleVintf() = default;
39 virtual bool setHalsOnly() = 0;
40 virtual bool setNoHals() = 0;
41 virtual void setOutputMatrix() = 0;
42 virtual bool assemble() = 0;
43
44 bool openOutFile(const std::string& path);
45 bool openInFile(const std::string& path);
46 bool openCheckFile(const std::string& path);
47 bool addKernel(const std::string& kernelArg);
48
49 virtual std::ostream& setOutputStream(Ostream&&) = 0;
50 virtual std::istream& addInputStream(const std::string& name, Istream&&) = 0;
51 virtual std::istream& setCheckInputStream(Istream&&) = 0;
52 virtual std::istream& addKernelConfigInputStream(const Version& kernelVer,
53 const std::string& name, Istream&& in) = 0;
54 virtual void setFakeEnv(const std::string& key, const std::string& value) = 0;
55
56 protected:
57 virtual bool hasKernelVersion(const Version&) const = 0;
58 virtual std::string getEnv(const std::string& key) const = 0;
59};
60
61} // namespace vintf
62} // namespace android
63#endif // ANDROID_VINTF_ASSEMBLE_VINTF_H
diff --git a/include/vintf/CompatibilityMatrix.h b/include/vintf/CompatibilityMatrix.h
index bfb4dbf..e3432a0 100644
--- a/include/vintf/CompatibilityMatrix.h
+++ b/include/vintf/CompatibilityMatrix.h
@@ -27,8 +27,10 @@
27#include "MapValueIterator.h" 27#include "MapValueIterator.h"
28#include "MatrixHal.h" 28#include "MatrixHal.h"
29#include "MatrixKernel.h" 29#include "MatrixKernel.h"
30#include "Named.h"
30#include "SchemaType.h" 31#include "SchemaType.h"
31#include "Sepolicy.h" 32#include "Sepolicy.h"
33#include "VendorNdk.h"
32#include "Vndk.h" 34#include "Vndk.h"
33#include "XmlFileGroup.h" 35#include "XmlFileGroup.h"
34 36
@@ -73,12 +75,25 @@ struct CompatibilityMatrix : public HalGroup<MatrixHal>, public XmlFileGroup<Mat
73 75
74 status_t fetchAllInformation(const std::string& path, std::string* error = nullptr); 76 status_t fetchAllInformation(const std::string& path, std::string* error = nullptr);
75 77
78 // Combine a subset of "matrices". For each CompatibilityMatrix in matrices,
79 // - If level() == UNSPECIFIED, use it as the base matrix (for non-HAL, non-XML-file
80 // requirements).
81 // - If level() < deviceLevel, ignore
82 // - If level() == deviceLevel, all HAL versions and XML files are added as is
83 // (optionality is kept)
84 // - If level() > deviceLevel, all HAL versions and XML files are added as optional.
85 static CompatibilityMatrix* combine(Level deviceLevel,
86 std::vector<Named<CompatibilityMatrix>>* matrices,
87 std::string* error);
88 static CompatibilityMatrix* findOrInsertBaseMatrix(
89 std::vector<Named<CompatibilityMatrix>>* matrices, std::string* error);
90
76 friend struct HalManifest; 91 friend struct HalManifest;
77 friend struct RuntimeInfo; 92 friend struct RuntimeInfo;
78 friend struct CompatibilityMatrixConverter; 93 friend struct CompatibilityMatrixConverter;
79 friend struct LibVintfTest; 94 friend struct LibVintfTest;
80 friend class VintfObject; 95 friend class VintfObject;
81 friend class AssembleVintf; 96 friend class AssembleVintfImpl;
82 friend bool operator==(const CompatibilityMatrix &, const CompatibilityMatrix &); 97 friend bool operator==(const CompatibilityMatrix &, const CompatibilityMatrix &);
83 98
84 SchemaType mType; 99 SchemaType mType;
@@ -93,7 +108,12 @@ struct CompatibilityMatrix : public HalGroup<MatrixHal>, public XmlFileGroup<Mat
93 108
94 // entries only for device compatibility matrix. 109 // entries only for device compatibility matrix.
95 struct { 110 struct {
111#pragma clang diagnostic push
112#pragma clang diagnostic ignored "-Wdeprecated-declarations"
96 Vndk mVndk; 113 Vndk mVndk;
114#pragma clang diagnostic pop
115
116 VendorNdk mVendorNdk;
97 } device; 117 } device;
98}; 118};
99 119
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index cc64201..f458753 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -28,6 +28,7 @@
28#include "ManifestHal.h" 28#include "ManifestHal.h"
29#include "MapValueIterator.h" 29#include "MapValueIterator.h"
30#include "SchemaType.h" 30#include "SchemaType.h"
31#include "VendorNdk.h"
31#include "Version.h" 32#include "Version.h"
32#include "Vndk.h" 33#include "Vndk.h"
33#include "XmlFileGroup.h" 34#include "XmlFileGroup.h"
@@ -101,9 +102,9 @@ struct HalManifest : public HalGroup<ManifestHal>, public XmlFileGroup<ManifestX
101 // Abort if type != device. 102 // Abort if type != device.
102 const Version &sepolicyVersion() const; 103 const Version &sepolicyVersion() const;
103 104
104 // framework.mVndks. Assume type == framework. 105 // framework.mVendorNdks. Assume type == framework.
105 // Abort if type != framework. 106 // Abort if type != framework.
106 const std::vector<Vndk> &vndks() const; 107 const std::vector<VendorNdk>& vendorNdks() const;
107 108
108 // If the corresponding <xmlfile> with the given version exists, 109 // If the corresponding <xmlfile> with the given version exists,
109 // - Return the overridden <path> if it is present, 110 // - Return the overridden <path> if it is present,
@@ -122,7 +123,7 @@ struct HalManifest : public HalGroup<ManifestHal>, public XmlFileGroup<ManifestX
122 private: 123 private:
123 friend struct HalManifestConverter; 124 friend struct HalManifestConverter;
124 friend class VintfObject; 125 friend class VintfObject;
125 friend class AssembleVintf; 126 friend class AssembleVintfImpl;
126 friend struct LibVintfTest; 127 friend struct LibVintfTest;
127 friend std::string dump(const HalManifest &vm); 128 friend std::string dump(const HalManifest &vm);
128 friend bool operator==(const HalManifest &lft, const HalManifest &rgt); 129 friend bool operator==(const HalManifest &lft, const HalManifest &rgt);
@@ -147,7 +148,12 @@ struct HalManifest : public HalGroup<ManifestHal>, public XmlFileGroup<ManifestX
147 148
148 // entries for framework hal manifest only 149 // entries for framework hal manifest only
149 struct { 150 struct {
151#pragma clang diagnostic push
152#pragma clang diagnostic ignored "-Wdeprecated-declarations"
150 std::vector<Vndk> mVndks; 153 std::vector<Vndk> mVndks;
154#pragma clang diagnostic pop
155
156 std::vector<VendorNdk> mVendorNdks;
151 } framework; 157 } framework;
152}; 158};
153 159
diff --git a/include/vintf/MatrixKernel.h b/include/vintf/MatrixKernel.h
index f0990a8..cee7e32 100644
--- a/include/vintf/MatrixKernel.h
+++ b/include/vintf/MatrixKernel.h
@@ -58,7 +58,7 @@ struct MatrixKernel {
58 private: 58 private:
59 friend struct MatrixKernelConverter; 59 friend struct MatrixKernelConverter;
60 friend struct MatrixKernelConditionsConverter; 60 friend struct MatrixKernelConditionsConverter;
61 friend class AssembleVintf; 61 friend class AssembleVintfImpl;
62 62
63 KernelVersion mMinLts; 63 KernelVersion mMinLts;
64 std::vector<KernelConfig> mConfigs; 64 std::vector<KernelConfig> mConfigs;
diff --git a/include/vintf/Named.h b/include/vintf/Named.h
new file mode 100644
index 0000000..eacb70b
--- /dev/null
+++ b/include/vintf/Named.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_VINTF_NAMED_H
18#define ANDROID_VINTF_NAMED_H
19
20#include <string>
21
22template <typename T>
23struct Named {
24 std::string name;
25 T object;
26
27 Named() = default;
28 Named(const std::string& n, const T& o) : name(n), object(o) {}
29 Named(std::string&& n, T&& o) : name(std::move(n)), object(std::move(o)) {}
30};
31
32#endif // ANDROID_VINTF_NAMED_H
diff --git a/include/vintf/Sepolicy.h b/include/vintf/Sepolicy.h
index 698cab0..09b9c97 100644
--- a/include/vintf/Sepolicy.h
+++ b/include/vintf/Sepolicy.h
@@ -43,7 +43,9 @@ struct Sepolicy {
43 inline const std::vector<VersionRange> &sepolicyVersions() const { 43 inline const std::vector<VersionRange> &sepolicyVersions() const {
44 return mSepolicyVersionRanges; 44 return mSepolicyVersionRanges;
45 } 45 }
46private: 46
47 private:
48 friend class AssembleVintfImpl;
47 friend struct SepolicyConverter; 49 friend struct SepolicyConverter;
48 KernelSepolicyVersion mKernelSepolicyVersion; 50 KernelSepolicyVersion mKernelSepolicyVersion;
49 std::vector<VersionRange> mSepolicyVersionRanges; 51 std::vector<VersionRange> mSepolicyVersionRanges;
diff --git a/include/vintf/VendorNdk.h b/include/vintf/VendorNdk.h
new file mode 100644
index 0000000..3d86570
--- /dev/null
+++ b/include/vintf/VendorNdk.h
@@ -0,0 +1,48 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_VINTF_VENDOR_NDK_H
18#define ANDROID_VINTF_VENDOR_NDK_H
19
20#include <set>
21#include <string>
22
23namespace android {
24namespace vintf {
25
26class VendorNdk {
27 public:
28 VendorNdk() = default;
29 VendorNdk(std::string&& version) : mVersion(std::move(version)) {}
30 VendorNdk(std::string&& version, std::set<std::string>&& libs)
31 : mVersion(std::move(version)), mLibraries(std::move(libs)) {}
32 VendorNdk(const std::string& version) : mVersion(version) {}
33 VendorNdk(const std::string& version, const std::set<std::string>& libs)
34 : mVersion(version), mLibraries(libs) {}
35 bool operator==(const VendorNdk& other) const { return version() == other.version(); }
36 const std::string& version() const { return mVersion; }
37 const std::set<std::string>& libraries() const { return mLibraries; }
38
39 private:
40 friend struct VendorNdkConverter;
41 std::string mVersion;
42 std::set<std::string> mLibraries;
43};
44
45} // namespace vintf
46} // namespace android
47
48#endif // ANDROID_VINTF_VENDOR_NDK_H
diff --git a/include/vintf/Vndk.h b/include/vintf/Vndk.h
index a7d2f51..05fcac9 100644
--- a/include/vintf/Vndk.h
+++ b/include/vintf/Vndk.h
@@ -24,7 +24,8 @@
24namespace android { 24namespace android {
25namespace vintf { 25namespace vintf {
26 26
27struct VndkVersionRange { 27// deprecated. Kept here for libvintf backwards compatibility.
28struct [[deprecated]] VndkVersionRange {
28 29
29 VndkVersionRange() : VndkVersionRange(0u, 0u, 0u) {} 30 VndkVersionRange() : VndkVersionRange(0u, 0u, 0u) {}
30 VndkVersionRange(size_t s, size_t v, size_t p) 31 VndkVersionRange(size_t s, size_t v, size_t p)
@@ -40,7 +41,8 @@ struct VndkVersionRange {
40 size_t patchMax; 41 size_t patchMax;
41}; 42};
42 43
43struct Vndk { 44// deprecated. Kept here for libvintf backwards compatibility.
45struct [[deprecated]] Vndk {
44 46
45 const VndkVersionRange &versionRange() const { return mVersionRange; } 47 const VndkVersionRange &versionRange() const { return mVersionRange; }
46 const std::set<std::string> &libraries() const { return mLibraries; } 48 const std::set<std::string> &libraries() const { return mLibraries; }
@@ -56,10 +58,13 @@ private:
56 std::set<std::string> mLibraries; 58 std::set<std::string> mLibraries;
57}; 59};
58 60
61[[deprecated]]
59inline bool operator==(const VndkVersionRange &lft, const VndkVersionRange &rgt) { 62inline bool operator==(const VndkVersionRange &lft, const VndkVersionRange &rgt) {
60 return lft.sdk == rgt.sdk && lft.vndk == rgt.vndk && 63 return lft.sdk == rgt.sdk && lft.vndk == rgt.vndk &&
61 lft.patchMin == rgt.patchMin && lft.patchMax == rgt.patchMax; 64 lft.patchMin == rgt.patchMin && lft.patchMax == rgt.patchMax;
62} 65}
66
67[[deprecated]]
63inline bool operator==(const Vndk &lft, const Vndk &rgt) { 68inline bool operator==(const Vndk &lft, const Vndk &rgt) {
64 return lft.mVersionRange == rgt.mVersionRange && 69 return lft.mVersionRange == rgt.mVersionRange &&
65 lft.mLibraries == rgt.mLibraries; 70 lft.mLibraries == rgt.mLibraries;
diff --git a/include/vintf/parse_string.h b/include/vintf/parse_string.h
index 00844d7..0bb554a 100644
--- a/include/vintf/parse_string.h
+++ b/include/vintf/parse_string.h
@@ -39,7 +39,12 @@ std::ostream& operator<<(std::ostream& os, Level l);
39std::ostream &operator<<(std::ostream &os, const ManifestHal &hal); 39std::ostream &operator<<(std::ostream &os, const ManifestHal &hal);
40std::ostream &operator<<(std::ostream &os, const Version &ver); 40std::ostream &operator<<(std::ostream &os, const Version &ver);
41std::ostream &operator<<(std::ostream &os, const VersionRange &vr); 41std::ostream &operator<<(std::ostream &os, const VersionRange &vr);
42
43#pragma clang diagnostic push
44#pragma clang diagnostic ignored "-Wdeprecated-declarations"
42std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr); 45std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr);
46#pragma clang diagnostic pop
47
43std::ostream &operator<<(std::ostream &os, const KernelVersion &ver); 48std::ostream &operator<<(std::ostream &os, const KernelVersion &ver);
44std::ostream &operator<<(std::ostream &os, const TransportArch &ta); 49std::ostream &operator<<(std::ostream &os, const TransportArch &ta);
45std::ostream &operator<<(std::ostream &os, const ManifestHal &hal); 50std::ostream &operator<<(std::ostream &os, const ManifestHal &hal);
@@ -65,7 +70,12 @@ bool parse(const std::string& s, Level* l);
65bool parse(const std::string &s, KernelSepolicyVersion *ksv); 70bool parse(const std::string &s, KernelSepolicyVersion *ksv);
66bool parse(const std::string &s, Version *ver); 71bool parse(const std::string &s, Version *ver);
67bool parse(const std::string &s, VersionRange *vr); 72bool parse(const std::string &s, VersionRange *vr);
73
74#pragma clang diagnostic push
75#pragma clang diagnostic ignored "-Wdeprecated-declarations"
68bool parse(const std::string &s, VndkVersionRange *vr); 76bool parse(const std::string &s, VndkVersionRange *vr);
77#pragma clang diagnostic pop
78
69bool parse(const std::string &s, KernelVersion *ver); 79bool parse(const std::string &s, KernelVersion *ver);
70// if return true, ta->isValid() must be true. 80// if return true, ta->isValid() must be true.
71bool parse(const std::string &s, TransportArch *ta); 81bool parse(const std::string &s, TransportArch *ta);
diff --git a/parse_string.cpp b/parse_string.cpp
index 7e23f5f..6b6e9a0 100644
--- a/parse_string.cpp
+++ b/parse_string.cpp
@@ -258,6 +258,8 @@ std::ostream &operator<<(std::ostream &os, const VersionRange &vr) {
258 return os << vr.minVer() << "-" << vr.maxMinor; 258 return os << vr.minVer() << "-" << vr.maxMinor;
259} 259}
260 260
261#pragma clang diagnostic push
262#pragma clang diagnostic ignored "-Wdeprecated-declarations"
261bool parse(const std::string &s, VndkVersionRange *vr) { 263bool parse(const std::string &s, VndkVersionRange *vr) {
262 std::vector<std::string> v = SplitString(s, '-'); 264 std::vector<std::string> v = SplitString(s, '-');
263 if (v.size() != 1 && v.size() != 2) { 265 if (v.size() != 1 && v.size() != 2) {
@@ -287,6 +289,7 @@ std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr) {
287 } 289 }
288 return os; 290 return os;
289} 291}
292#pragma clang diagnostic pop
290 293
291bool parse(const std::string &s, KernelVersion *kernelVersion) { 294bool parse(const std::string &s, KernelVersion *kernelVersion) {
292 std::vector<std::string> v = SplitString(s, '.'); 295 std::vector<std::string> v = SplitString(s, '.');
diff --git a/parse_xml.cpp b/parse_xml.cpp
index 3df7e19..9a09eae 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -696,10 +696,13 @@ struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
696}; 696};
697const SepolicyConverter sepolicyConverter{}; 697const SepolicyConverter sepolicyConverter{};
698 698
699[[deprecated]]
699const XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"}; 700const XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
701
702const XmlTextConverter<std::string> vndkVersionConverter{"version"};
700const XmlTextConverter<std::string> vndkLibraryConverter{"library"}; 703const XmlTextConverter<std::string> vndkLibraryConverter{"library"};
701 704
702struct VndkConverter : public XmlNodeConverter<Vndk> { 705struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
703 std::string elementName() const override { return "vndk"; } 706 std::string elementName() const override { return "vndk"; }
704 void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override { 707 void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
705 appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d)); 708 appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
@@ -714,8 +717,26 @@ struct VndkConverter : public XmlNodeConverter<Vndk> {
714 } 717 }
715}; 718};
716 719
720[[deprecated]]
717const VndkConverter vndkConverter{}; 721const VndkConverter vndkConverter{};
718 722
723struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
724 std::string elementName() const override { return "vendor-ndk"; }
725 void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
726 appendChild(root, vndkVersionConverter(object.mVersion, d));
727 appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
728 }
729 bool buildObject(VendorNdk* object, NodeType* root) const override {
730 if (!parseChild(root, vndkVersionConverter, &object->mVersion) ||
731 !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) {
732 return false;
733 }
734 return true;
735 }
736};
737
738const VendorNdkConverter vendorNdkConverter{};
739
719struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> { 740struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
720 std::string elementName() const override { return "sepolicy"; } 741 std::string elementName() const override { return "sepolicy"; }
721 void mutateNode(const Version &m, NodeType *root, DocType *d) const override { 742 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
@@ -769,7 +790,12 @@ struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
769 } 790 }
770 } else if (m.mType == SchemaType::FRAMEWORK) { 791 } else if (m.mType == SchemaType::FRAMEWORK) {
771 if (!(flags & SerializeFlag::NO_VNDK)) { 792 if (!(flags & SerializeFlag::NO_VNDK)) {
793#pragma clang diagnostic push
794#pragma clang diagnostic ignored "-Wdeprecated-declarations"
772 appendChildren(root, vndkConverter, m.framework.mVndks, d); 795 appendChildren(root, vndkConverter, m.framework.mVndks, d);
796#pragma clang diagnostic pop
797
798 appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
773 } 799 }
774 } 800 }
775 801
@@ -799,6 +825,8 @@ struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
799 return false; 825 return false;
800 } 826 }
801 } else if (object->mType == SchemaType::FRAMEWORK) { 827 } else if (object->mType == SchemaType::FRAMEWORK) {
828#pragma clang diagnostic push
829#pragma clang diagnostic ignored "-Wdeprecated-declarations"
802 if (!parseChildren(root, vndkConverter, &object->framework.mVndks)) { 830 if (!parseChildren(root, vndkConverter, &object->framework.mVndks)) {
803 return false; 831 return false;
804 } 832 }
@@ -809,6 +837,11 @@ struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
809 return false; 837 return false;
810 } 838 }
811 } 839 }
840#pragma clang diagnostic pop
841
842 if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks)) {
843 return false;
844 }
812 } 845 }
813 for (auto &&hal : hals) { 846 for (auto &&hal : hals) {
814 std::string description{hal.name}; 847 std::string description{hal.name};
@@ -901,7 +934,16 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri
901 } 934 }
902 } else if (m.mType == SchemaType::DEVICE) { 935 } else if (m.mType == SchemaType::DEVICE) {
903 if (!(flags & SerializeFlag::NO_VNDK)) { 936 if (!(flags & SerializeFlag::NO_VNDK)) {
904 appendChild(root, vndkConverter(m.device.mVndk, d)); 937#pragma clang diagnostic push
938#pragma clang diagnostic ignored "-Wdeprecated-declarations"
939 if (!(m.device.mVndk == Vndk{})) {
940 appendChild(root, vndkConverter(m.device.mVndk, d));
941 }
942#pragma clang diagnostic pop
943
944 if (!(m.device.mVendorNdk == VendorNdk{})) {
945 appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
946 }
905 } 947 }
906 } 948 }
907 949
@@ -944,9 +986,16 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri
944 } else if (object->mType == SchemaType::DEVICE) { 986 } else if (object->mType == SchemaType::DEVICE) {
945 // <vndk> can be missing because it can be determined at build time, not hard-coded 987 // <vndk> can be missing because it can be determined at build time, not hard-coded
946 // in the XML file. 988 // in the XML file.
989#pragma clang diagnostic push
990#pragma clang diagnostic ignored "-Wdeprecated-declarations"
947 if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk)) { 991 if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk)) {
948 return false; 992 return false;
949 } 993 }
994#pragma clang diagnostic pop
995
996 if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk)) {
997 return false;
998 }
950 } 999 }
951 1000
952 if (!kMetaVersion.minorAtLeast(version)) { 1001 if (!kMetaVersion.minorAtLeast(version)) {
diff --git a/test/Android.bp b/test/Android.bp
index 5c9fc43..607d452 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -18,6 +18,7 @@ cc_test {
18 host_supported: true, 18 host_supported: true,
19 gtest: false, 19 gtest: false,
20 srcs: [ 20 srcs: [
21 "AssembleVintfTest.cpp",
21 "LibVintfTest.cpp", 22 "LibVintfTest.cpp",
22 ], 23 ],
23 24
@@ -27,11 +28,15 @@ cc_test {
27 "liblog", 28 "liblog",
28 "libvintf", 29 "libvintf",
29 ], 30 ],
30 static_libs: ["libgtest"], 31 static_libs: [
32 "libgtest",
33 "libassemblevintf",
34 ],
31 35
32 cflags: [ 36 cflags: [
33 "-O0", 37 "-O0",
34 "-g", 38 "-g",
39 "-Wno-deprecated-declarations",
35 ], 40 ],
36 target: { 41 target: {
37 host: { 42 host: {
diff --git a/test/AssembleVintfTest.cpp b/test/AssembleVintfTest.cpp
new file mode 100644
index 0000000..53a1d0d
--- /dev/null
+++ b/test/AssembleVintfTest.cpp
@@ -0,0 +1,360 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AssembleVintfTest"
18
19#include <android-base/logging.h>
20#include <gtest/gtest.h>
21#include <vintf/AssembleVintf.h>
22#include <vintf/parse_string.h>
23
24namespace android {
25namespace vintf {
26
27static bool In(const std::string& sub, const std::string& str) {
28 return str.find(sub) != std::string::npos;
29}
30#define EXPECT_IN(sub, str) EXPECT_TRUE(In((sub), (str))) << (str);
31
32class AssembleVintfTest : public ::testing::Test {
33 public:
34 virtual void SetUp() override {
35 mInstance = AssembleVintf::newInstance();
36 auto s = makeStream("");
37 mOutputStream = s.get();
38 mInstance->setOutputStream(std::move(s));
39 }
40 virtual void TearDown() override { mInstance = nullptr; }
41
42 const std::unique_ptr<AssembleVintf>& getInstance() { return mInstance; }
43
44 std::string getOutput() { return mOutputStream->str(); }
45
46 void resetOutput() { mOutputStream->str(""); }
47
48 void setFakeEnvs(const std::map<std::string, std::string>& envs) {
49 for (const auto& pair : envs) {
50 getInstance()->setFakeEnv(pair.first, pair.second);
51 }
52 }
53
54 void addInput(const std::string& name, const std::string& s) {
55 getInstance()->addInputStream(name, makeStream(s));
56 }
57
58 std::unique_ptr<std::stringstream> makeStream(const std::string& s) {
59 return std::make_unique<std::stringstream>(s);
60 }
61
62 std::unique_ptr<AssembleVintf> mInstance;
63 // do not own this object.
64 std::stringstream* mOutputStream;
65};
66
67TEST_F(AssembleVintfTest, FrameworkMatrixEmpty) {
68 std::string xmlEmpty = "<compatibility-matrix version=\"1.0\" type=\"framework\" />";
69 std::string kernel318 = "CONFIG_FOO=y\n";
70 std::string kernel318_64 = "CONFIG_BAR=y\n";
71 std::string kernel44 = "# CONFIG_FOO is not set\n";
72 std::string kernel44_64 = "CONFIG_BAR=y\n";
73
74 addInput("compatibility_matrix.empty.xml", xmlEmpty);
75 setFakeEnvs({
76 {"POLICYVERS", "30"},
77 {"BOARD_SEPOLICY_VERS", "10000.0"},
78 {"FRAMEWORK_VBMETA_VERSION", "1.0"},
79 });
80 getInstance()->addKernelConfigInputStream({3, 18}, "android-base.cfg", makeStream(kernel318));
81 getInstance()->addKernelConfigInputStream({3, 18}, "android-base-arm64.cfg",
82 makeStream(kernel318_64));
83 getInstance()->addKernelConfigInputStream({4, 4}, "android-base.cfg", makeStream(kernel44));
84 getInstance()->addKernelConfigInputStream({4, 4}, "android-base-arm64.cfg",
85 makeStream(kernel44_64));
86
87 EXPECT_TRUE(getInstance()->assemble());
88
89 EXPECT_IN(
90 "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
91 " <kernel version=\"3.18.0\">\n"
92 " <config>\n"
93 " <key>CONFIG_FOO</key>\n"
94 " <value type=\"tristate\">y</value>\n"
95 " </config>\n"
96 " </kernel>\n"
97 " <kernel version=\"3.18.0\">\n"
98 " <conditions>\n"
99 " <config>\n"
100 " <key>CONFIG_ARM64</key>\n"
101 " <value type=\"tristate\">y</value>\n"
102 " </config>\n"
103 " </conditions>\n"
104 " <config>\n"
105 " <key>CONFIG_BAR</key>\n"
106 " <value type=\"tristate\">y</value>\n"
107 " </config>\n"
108 " </kernel>\n"
109 " <kernel version=\"4.4.0\">\n"
110 " <config>\n"
111 " <key>CONFIG_FOO</key>\n"
112 " <value type=\"tristate\">n</value>\n"
113 " </config>\n"
114 " </kernel>\n"
115 " <kernel version=\"4.4.0\">\n"
116 " <conditions>\n"
117 " <config>\n"
118 " <key>CONFIG_ARM64</key>\n"
119 " <value type=\"tristate\">y</value>\n"
120 " </config>\n"
121 " </conditions>\n"
122 " <config>\n"
123 " <key>CONFIG_BAR</key>\n"
124 " <value type=\"tristate\">y</value>\n"
125 " </config>\n"
126 " </kernel>\n"
127 " <sepolicy>\n"
128 " <kernel-sepolicy-version>30</kernel-sepolicy-version>\n"
129 " <sepolicy-version>10000.0</sepolicy-version>\n"
130 " </sepolicy>\n"
131 " <avb>\n"
132 " <vbmeta-version>1.0</vbmeta-version>\n"
133 " </avb>\n"
134 "</compatibility-matrix>\n",
135 getOutput());
136}
137
138TEST_F(AssembleVintfTest, FrameworkMatrix) {
139 std::string tail =
140 " <kernel version=\"3.18.0\">\n"
141 " <config>\n"
142 " <key>CONFIG_FOO</key>\n"
143 " <value type=\"tristate\">y</value>\n"
144 " </config>\n"
145 " </kernel>\n"
146 " <sepolicy>\n"
147 " <kernel-sepolicy-version>30</kernel-sepolicy-version>\n"
148 " <sepolicy-version>10000.0</sepolicy-version>\n"
149 " </sepolicy>\n"
150 " <avb>\n"
151 " <vbmeta-version>1.0</vbmeta-version>\n"
152 " </avb>\n"
153 "</compatibility-matrix>\n";
154
155 std::string xmlEmpty = "<compatibility-matrix version=\"1.0\" type=\"framework\">\n" + tail;
156
157 std::string xml1 =
158 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n"
159 " <hal format=\"hidl\" optional=\"true\">\n"
160 " <name>android.hardware.foo</name>\n"
161 " <version>1.0</version>\n"
162 " <interface>\n"
163 " <name>IFoo</name>\n"
164 " <instance>default</instance>\n"
165 " </interface>\n"
166 " </hal>\n"
167 "</compatibility-matrix>\n";
168
169 std::string xml2 =
170 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"2\">\n"
171 " <hal format=\"hidl\" optional=\"true\">\n"
172 " <name>android.hardware.foo</name>\n"
173 " <version>1.0-1</version>\n"
174 " <interface>\n"
175 " <name>IFoo</name>\n"
176 " <instance>default</instance>\n"
177 " </interface>\n"
178 " </hal>\n"
179 "</compatibility-matrix>\n";
180
181 std::string xml3 =
182 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"3\">\n"
183 " <hal format=\"hidl\" optional=\"false\">\n"
184 " <name>android.hardware.foo</name>\n"
185 " <version>2.0</version>\n"
186 " <interface>\n"
187 " <name>IFoo</name>\n"
188 " <instance>default</instance>\n"
189 " </interface>\n"
190 " </hal>\n"
191 "</compatibility-matrix>\n";
192
193 auto manifest = [](size_t level) {
194 return "<manifest version=\"1.0\" type=\"device\" target-level=\"" + std::to_string(level) +
195 "\">\n" +
196 " <hal format=\"hidl\">\n"
197 " <name>android.hardware.foo</name>\n"
198 " <version>1.1</version>\n"
199 " <transport>hwbinder</transport>\n"
200 " <interface>\n"
201 " <name>IFoo</name>\n"
202 " <instance>default</instance>\n"
203 " </interface>\n"
204 " </hal>\n"
205 " <hal format=\"hidl\">\n"
206 " <name>android.hardware.foo</name>\n"
207 " <version>2.0</version>\n"
208 " <transport>hwbinder</transport>\n"
209 " <interface>\n"
210 " <name>IFoo</name>\n"
211 " <instance>default</instance>\n"
212 " </interface>\n"
213 " </hal>\n"
214 " <sepolicy>\n"
215 " <version>10000.0</version>\n"
216 " </sepolicy>\n"
217 "</manifest>\n";
218 };
219
220 addInput("compatibility_matrix.1.xml", xml1);
221 addInput("compatibility_matrix.2.xml", xml2);
222 addInput("compatibility_matrix.3.xml", xml3);
223 addInput("compatibility_matrix.empty.xml", xmlEmpty);
224 getInstance()->setFakeEnv("PRODUCT_ENFORCE_VINTF_MANIFEST", "true");
225
226 resetOutput();
227 getInstance()->setCheckInputStream(makeStream(manifest(1)));
228 EXPECT_TRUE(getInstance()->assemble());
229 EXPECT_IN(
230 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n"
231 " <hal format=\"hidl\" optional=\"true\">\n"
232 " <name>android.hardware.foo</name>\n"
233 " <version>1.0-1</version>\n"
234 " <interface>\n"
235 " <name>IFoo</name>\n"
236 " <instance>default</instance>\n"
237 " </interface>\n"
238 " </hal>\n"
239 " <hal format=\"hidl\" optional=\"true\">\n"
240 " <name>android.hardware.foo</name>\n"
241 " <version>2.0</version>\n"
242 " <interface>\n"
243 " <name>IFoo</name>\n"
244 " <instance>default</instance>\n"
245 " </interface>\n"
246 " </hal>\n" +
247 tail,
248 getOutput());
249
250 resetOutput();
251 getInstance()->setCheckInputStream(makeStream(manifest(2)));
252 EXPECT_TRUE(getInstance()->assemble());
253 EXPECT_IN(
254 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"2\">\n"
255 " <hal format=\"hidl\" optional=\"true\">\n"
256 " <name>android.hardware.foo</name>\n"
257 " <version>1.0-1</version>\n"
258 " <interface>\n"
259 " <name>IFoo</name>\n"
260 " <instance>default</instance>\n"
261 " </interface>\n"
262 " </hal>\n"
263 " <hal format=\"hidl\" optional=\"true\">\n"
264 " <name>android.hardware.foo</name>\n"
265 " <version>2.0</version>\n"
266 " <interface>\n"
267 " <name>IFoo</name>\n"
268 " <instance>default</instance>\n"
269 " </interface>\n"
270 " </hal>\n" +
271 tail,
272 getOutput());
273
274 resetOutput();
275 getInstance()->setCheckInputStream(makeStream(manifest(3)));
276 EXPECT_TRUE(getInstance()->assemble());
277 EXPECT_IN(
278 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"3\">\n"
279 " <hal format=\"hidl\" optional=\"false\">\n"
280 " <name>android.hardware.foo</name>\n"
281 " <version>2.0</version>\n"
282 " <interface>\n"
283 " <name>IFoo</name>\n"
284 " <instance>default</instance>\n"
285 " </interface>\n"
286 " </hal>\n" +
287 tail,
288 getOutput());
289}
290
291TEST_F(AssembleVintfTest, MatrixVendorNdk) {
292 addInput("compatibility_matrix.xml",
293 "<compatibility-matrix version=\"1.0\" type=\"device\"/>\n");
294 getInstance()->setFakeEnv("REQUIRED_VNDK_VERSION", "P");
295 EXPECT_TRUE(getInstance()->assemble());
296 EXPECT_IN(
297 "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
298 " <vendor-ndk>\n"
299 " <version>P</version>\n"
300 " </vendor-ndk>\n"
301 "</compatibility-matrix>\n",
302 getOutput());
303}
304
305TEST_F(AssembleVintfTest, ManifestVendorNdk) {
306 addInput("manifest.xml", "<manifest version=\"1.0\" type=\"framework\"/>\n");
307 getInstance()->setFakeEnv("PROVIDED_VNDK_VERSIONS", "P 26 27 ");
308 EXPECT_TRUE(getInstance()->assemble());
309 EXPECT_IN(
310 "<manifest version=\"1.0\" type=\"framework\">\n"
311 " <vendor-ndk>\n"
312 " <version>P</version>\n"
313 " </vendor-ndk>\n"
314 " <vendor-ndk>\n"
315 " <version>26</version>\n"
316 " </vendor-ndk>\n"
317 " <vendor-ndk>\n"
318 " <version>27</version>\n"
319 " </vendor-ndk>\n"
320 "</manifest>\n",
321 getOutput());
322}
323
324TEST_F(AssembleVintfTest, VendorNdkCheckEmpty) {
325 addInput("manifest.xml", "<manifest version=\"1.0\" type=\"framework\"/>\n");
326 getInstance()->setFakeEnv("PROVIDED_VNDK_VERSIONS", "P 26 27 ");
327
328 std::string matrix = "<compatibility-matrix version=\"1.0\" type=\"device\"/>\n";
329 getInstance()->setCheckInputStream(makeStream(matrix));
330 EXPECT_TRUE(getInstance()->assemble());
331}
332
333TEST_F(AssembleVintfTest, VendorNdkCheckIncompat) {
334 addInput("manifest.xml", "<manifest version=\"1.0\" type=\"framework\"/>\n");
335 getInstance()->setFakeEnv("PROVIDED_VNDK_VERSIONS", "P 26 27 ");
336 std::string matrix =
337 "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
338 " <vendor-ndk>\n"
339 " <version>O</version>\n"
340 " </vendor-ndk>\n"
341 "</compatibility-matrix>\n";
342 getInstance()->setCheckInputStream(makeStream(matrix));
343 EXPECT_FALSE(getInstance()->assemble());
344}
345
346TEST_F(AssembleVintfTest, VendorNdkCheckCompat) {
347 addInput("manifest.xml", "<manifest version=\"1.0\" type=\"framework\"/>\n");
348 getInstance()->setFakeEnv("PROVIDED_VNDK_VERSIONS", "P 26 27 ");
349 std::string matrix =
350 "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
351 " <vendor-ndk>\n"
352 " <version>27</version>\n"
353 " </vendor-ndk>\n"
354 "</compatibility-matrix>\n";
355 getInstance()->setCheckInputStream(makeStream(matrix));
356 EXPECT_TRUE(getInstance()->assemble());
357}
358
359} // namespace vintf
360} // namespace android
diff --git a/test/LibVintfTest.cpp b/test/LibVintfTest.cpp
index af2bc67..1c2536d 100644
--- a/test/LibVintfTest.cpp
+++ b/test/LibVintfTest.cpp
@@ -39,12 +39,13 @@ extern const XmlConverter<KernelConfigTypedValue> &gKernelConfigTypedValueConver
39extern const XmlConverter<HalManifest> &gHalManifestConverter; 39extern const XmlConverter<HalManifest> &gHalManifestConverter;
40extern const XmlConverter<CompatibilityMatrix> &gCompatibilityMatrixConverter; 40extern const XmlConverter<CompatibilityMatrix> &gCompatibilityMatrixConverter;
41 41
42#ifdef LIBVINTF_HOST 42static bool In(const std::string& sub, const std::string& str) {
43static bool Contains(const std::string& str, const std::string& sub) {
44 return str.find(sub) != std::string::npos; 43 return str.find(sub) != std::string::npos;
45} 44}
46#define EXPECT_CONTAINS(str, sub) \ 45#define EXPECT_IN(sub, str) EXPECT_TRUE(In((sub), (str))) << (str);
47 EXPECT_TRUE(Contains((str), (sub))) << "Cannot find \"" << (sub) << "\" in \"" << (str) << "\"" 46
47#ifdef LIBVINTF_HOST
48#define EXPECT_CONTAINS(str, sub) EXPECT_IN(sub, str);
48#endif 49#endif
49 50
50struct LibVintfTest : public ::testing::Test { 51struct LibVintfTest : public ::testing::Test {
@@ -2282,6 +2283,112 @@ TEST_F(LibVintfTest, AddOptionalXmlFile) {
2282 "</compatibility-matrix>\n"); 2283 "</compatibility-matrix>\n");
2283} 2284}
2284 2285
2286TEST_F(LibVintfTest, VendorNdk) {
2287 CompatibilityMatrix cm;
2288 std::string error;
2289 std::string xml;
2290
2291 xml =
2292 "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
2293 " <vendor-ndk>\n"
2294 " <version>P</version>\n"
2295 " <library>libbase.so</library>\n"
2296 " <library>libjpeg.so</library>\n"
2297 " </vendor-ndk>\n"
2298 "</compatibility-matrix>\n";
2299 EXPECT_TRUE(gCompatibilityMatrixConverter(&cm, xml))
2300 << gCompatibilityMatrixConverter.lastError();
2301 EXPECT_EQ(xml, gCompatibilityMatrixConverter(cm));
2302
2303 {
2304 HalManifest manifest;
2305 xml =
2306 "<manifest version=\"1.0\" type=\"framework\">\n"
2307 " <vendor-ndk>\n"
2308 " <version>27</version>\n"
2309 " <library>libbase.so</library>\n"
2310 " <library>libjpeg.so</library>\n"
2311 " </vendor-ndk>\n"
2312 " <vendor-ndk>\n"
2313 " <version>P</version>\n"
2314 " <library>libbase.so</library>\n"
2315 " <library>libjpeg.so</library>\n"
2316 " <library>libtinyxml2.so</library>\n"
2317 " </vendor-ndk>\n"
2318 "</manifest>\n";
2319
2320 EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
2321 EXPECT_EQ(xml, gHalManifestConverter(manifest));
2322 EXPECT_TRUE(manifest.checkCompatibility(cm, &error)) << error;
2323 }
2324
2325 {
2326 HalManifest manifest;
2327 xml =
2328 "<manifest version=\"1.0\" type=\"framework\">\n"
2329 " <vendor-ndk>\n"
2330 " <version>27</version>\n"
2331 " <library>libbase.so</library>\n"
2332 " <library>libjpeg.so</library>\n"
2333 " </vendor-ndk>\n"
2334 "</manifest>\n";
2335
2336 EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
2337 EXPECT_EQ(xml, gHalManifestConverter(manifest));
2338 EXPECT_FALSE(manifest.checkCompatibility(cm, &error));
2339 EXPECT_IN("Vndk version P is not supported.", error);
2340 }
2341
2342 {
2343 HalManifest manifest;
2344 xml =
2345 "<manifest version=\"1.0\" type=\"framework\">\n"
2346 " <vendor-ndk>\n"
2347 " <version>P</version>\n"
2348 " <library>libbase.so</library>\n"
2349 " </vendor-ndk>\n"
2350 "</manifest>\n";
2351
2352 EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
2353 EXPECT_EQ(xml, gHalManifestConverter(manifest));
2354 EXPECT_FALSE(manifest.checkCompatibility(cm, &error));
2355 EXPECT_IN("Vndk libs incompatible for version P.", error);
2356 EXPECT_IN("libjpeg.so", error);
2357 }
2358}
2359
2360TEST_F(LibVintfTest, MissingVendorNdkInMatrix) {
2361 CompatibilityMatrix cm;
2362 std::string xml;
2363 std::string error;
2364
2365 xml = "<compatibility-matrix version=\"1.0\" type=\"device\"/>\n";
2366 EXPECT_TRUE(gCompatibilityMatrixConverter(&cm, xml))
2367 << gCompatibilityMatrixConverter.lastError();
2368
2369 {
2370 HalManifest manifest;
2371 xml = "<manifest version=\"1.0\" type=\"framework\"/>\n";
2372 EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
2373
2374 EXPECT_TRUE(manifest.checkCompatibility(cm, &error)) << error;
2375 }
2376
2377 {
2378 HalManifest manifest;
2379 xml =
2380 "<manifest version=\"1.0\" type=\"framework\">\n"
2381 " <vendor-ndk>\n"
2382 " <version>P</version>\n"
2383 " <library>libbase.so</library>\n"
2384 " </vendor-ndk>\n"
2385 "</manifest>\n";
2386 EXPECT_TRUE(gHalManifestConverter(&manifest, xml)) << gHalManifestConverter.lastError();
2387
2388 EXPECT_TRUE(manifest.checkCompatibility(cm, &error)) << error;
2389 }
2390}
2391
2285} // namespace vintf 2392} // namespace vintf
2286} // namespace android 2393} // namespace android
2287 2394
diff --git a/utils.h b/utils.h
index dce03b3..5f28b6d 100644
--- a/utils.h
+++ b/utils.h
@@ -107,6 +107,19 @@ class ObjectFactory {
107}; 107};
108extern ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory; 108extern ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory;
109 109
110// TODO(b/70628538): Do not infer from Shipping API level.
111inline Level convertFromApiLevel(size_t apiLevel) {
112 if (apiLevel < 26) {
113 return Level::LEGACY;
114 } else if (apiLevel == 26) {
115 return Level::O;
116 } else if (apiLevel == 27) {
117 return Level::O_MR1;
118 } else {
119 return Level::UNSPECIFIED;
120 }
121}
122
110} // namespace details 123} // namespace details
111} // namespace vintf 124} // namespace vintf
112} // namespace android 125} // namespace android