Merge "Add releasetools_test to TEST_MAPPING."
diff --git a/AssembleVintf.cpp b/AssembleVintf.cpp
index a954acd..71ea1bc 100644
--- a/AssembleVintf.cpp
+++ b/AssembleVintf.cpp
@@ -47,10 +47,12 @@
// It takes ownership on the istream.
class NamedIstream {
public:
+ NamedIstream() = default;
NamedIstream(const std::string& name, std::unique_ptr<std::istream>&& stream)
: mName(name), mStream(std::move(stream)) {}
const std::string& name() const { return mName; }
std::istream& stream() { return *mStream; }
+ bool hasStream() { return mStream != nullptr; }
private:
std::string mName;
@@ -294,18 +296,16 @@
return true;
}
- template <typename S>
- using Schemas = std::vector<Named<S>>;
- using HalManifests = Schemas<HalManifest>;
- using CompatibilityMatrices = Schemas<CompatibilityMatrix>;
+ using HalManifests = std::vector<HalManifest>;
+ using CompatibilityMatrices = std::vector<CompatibilityMatrix>;
template <typename M>
- void outputInputs(const Schemas<M>& inputs) {
+ void outputInputs(const std::vector<M>& inputs) {
out() << "<!--" << std::endl;
out() << " Input:" << std::endl;
for (const auto& e : inputs) {
- if (!e.name.empty()) {
- out() << " " << base::Basename(e.name) << std::endl;
+ if (!e.fileName().empty()) {
+ out() << " " << base::Basename(e.fileName()) << std::endl;
}
}
out() << "-->" << std::endl;
@@ -364,17 +364,17 @@
bool assembleHalManifest(HalManifests* halManifests) {
std::string error;
- HalManifest* halManifest = &halManifests->front().object;
+ HalManifest* halManifest = &halManifests->front();
for (auto it = halManifests->begin() + 1; it != halManifests->end(); ++it) {
- const std::string& path = it->name;
- HalManifest& manifestToAdd = it->object;
+ const std::string& path = it->fileName();
+ HalManifest& manifestToAdd = *it;
if (manifestToAdd.level() != Level::UNSPECIFIED) {
if (halManifest->level() == Level::UNSPECIFIED) {
halManifest->mLevel = manifestToAdd.level();
} else if (halManifest->level() != manifestToAdd.level()) {
std::cerr << "Inconsistent FCM Version in HAL manifests:" << std::endl
- << " File '" << halManifests->front().name << "' has level "
+ << " File '" << halManifests->front().fileName() << "' has level "
<< halManifest->level() << std::endl
<< " File '" << path << "' has level " << manifestToAdd.level()
<< std::endl;
@@ -435,9 +435,10 @@
}
out().flush();
- if (mCheckFile != nullptr) {
+ if (mCheckFile.hasStream()) {
CompatibilityMatrix checkMatrix;
- if (!gCompatibilityMatrixConverter(&checkMatrix, read(*mCheckFile), &error)) {
+ checkMatrix.setFileName(mCheckFile.name());
+ if (!gCompatibilityMatrixConverter(&checkMatrix, read(mCheckFile.stream()), &error)) {
std::cerr << "Cannot parse check file as a compatibility matrix: " << error
<< std::endl;
return false;
@@ -516,8 +517,8 @@
Level getLowestFcmVersion(const CompatibilityMatrices& matrices) {
Level ret = Level::UNSPECIFIED;
for (const auto& e : matrices) {
- if (ret == Level::UNSPECIFIED || ret > e.object.level()) {
- ret = e.object.level();
+ if (ret == Level::UNSPECIFIED || ret > e.level()) {
+ ret = e.level();
}
}
return ret;
@@ -529,15 +530,16 @@
std::unique_ptr<HalManifest> checkManifest;
std::unique_ptr<CompatibilityMatrix> builtMatrix;
- if (mCheckFile != nullptr) {
+ if (mCheckFile.hasStream()) {
checkManifest = std::make_unique<HalManifest>();
- if (!gHalManifestConverter(checkManifest.get(), read(*mCheckFile), &error)) {
+ checkManifest->setFileName(mCheckFile.name());
+ if (!gHalManifestConverter(checkManifest.get(), read(mCheckFile.stream()), &error)) {
std::cerr << "Cannot parse check file as a HAL manifest: " << error << std::endl;
return false;
}
}
- if (matrices->front().object.mType == SchemaType::DEVICE) {
+ if (matrices->front().mType == SchemaType::DEVICE) {
builtMatrix = CompatibilityMatrix::combineDeviceMatrices(matrices, &error);
matrix = builtMatrix.get();
@@ -551,7 +553,7 @@
auto& valueInMatrix = matrix->device.mVendorNdk;
if (!valueInMatrix.version().empty() && valueInMatrix.version() != vndkVersion) {
std::cerr << "Hard-coded <vendor-ndk> version in device compatibility matrix ("
- << matrices->front().name << "), '" << valueInMatrix.version()
+ << matrices->front().fileName() << "), '" << valueInMatrix.version()
<< "', does not match value inferred "
<< "from BOARD_VNDK_VERSION '" << vndkVersion << "'" << std::endl;
return false;
@@ -564,7 +566,7 @@
}
}
- if (matrices->front().object.mType == SchemaType::FRAMEWORK) {
+ if (matrices->front().mType == SchemaType::FRAMEWORK) {
Level deviceLevel =
checkManifest != nullptr ? checkManifest->level() : Level::UNSPECIFIED;
if (deviceLevel == Level::UNSPECIFIED) {
@@ -638,17 +640,19 @@
template <typename Schema, typename AssembleFunc>
AssembleStatus tryAssemble(const XmlConverter<Schema>& converter, const std::string& schemaName,
AssembleFunc assemble, std::string* error) {
- Schemas<Schema> schemas;
+ std::vector<Schema> schemas;
Schema schema;
+ schema.setFileName(mInFiles.front().name());
if (!converter(&schema, read(mInFiles.front().stream()), error)) {
return TRY_NEXT;
}
auto firstType = schema.type();
- schemas.emplace_back(mInFiles.front().name(), std::move(schema));
+ schemas.emplace_back(std::move(schema));
for (auto it = mInFiles.begin() + 1; it != mInFiles.end(); ++it) {
Schema additionalSchema;
const std::string& fileName = it->name();
+ additionalSchema.setFileName(fileName);
if (!converter(&additionalSchema, read(it->stream()), error)) {
std::cerr << "File \"" << fileName << "\" is not a valid " << firstType << " "
<< schemaName << " (but the first file is a valid " << firstType << " "
@@ -662,7 +666,7 @@
return FAIL_AND_EXIT;
}
- schemas.emplace_back(fileName, std::move(additionalSchema));
+ schemas.emplace_back(std::move(additionalSchema));
}
return assemble(&schemas) ? SUCCESS : FAIL_AND_EXIT;
}
@@ -707,9 +711,9 @@
return it->stream();
}
- std::istream& setCheckInputStream(Istream&& in) override {
- mCheckFile = std::move(in);
- return *mCheckFile;
+ std::istream& setCheckInputStream(const std::string& name, Istream&& in) override {
+ mCheckFile = NamedIstream(name, std::move(in));
+ return mCheckFile.stream();
}
bool hasKernelVersion(const KernelVersion& kernelVer) const override {
@@ -763,7 +767,7 @@
private:
std::vector<NamedIstream> mInFiles;
Ostream mOutRef;
- Istream mCheckFile;
+ NamedIstream mCheckFile;
bool mOutputMatrix = false;
bool mHasSetHalsOnlyFlag = false;
SerializeFlags::Type mSerializeFlags = SerializeFlags::EVERYTHING;
@@ -783,7 +787,8 @@
}
bool AssembleVintf::openCheckFile(const std::string& path) {
- return static_cast<std::ifstream&>(setCheckInputStream(std::make_unique<std::ifstream>(path)))
+ return static_cast<std::ifstream&>(
+ setCheckInputStream(path, std::make_unique<std::ifstream>(path)))
.is_open();
}
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index a2ef873..8ca2dbd 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -31,6 +31,20 @@
using details::mergeField;
+bool CompatibilityMatrix::add(MatrixHal&& halToAdd, std::string*) {
+ CHECK(addInternal(std::move(halToAdd)) != nullptr);
+ return true;
+}
+
+bool CompatibilityMatrix::addAllHals(CompatibilityMatrix* other, std::string*) {
+ std::string internalError;
+ for (auto& pair : other->mHals) {
+ CHECK(add(std::move(pair.second), &internalError)) << internalError;
+ }
+ other->mHals.clear();
+ return true;
+}
+
bool CompatibilityMatrix::addKernel(MatrixKernel&& kernel, std::string* error) {
if (mType != SchemaType::FRAMEWORK) {
if (error) {
@@ -303,6 +317,7 @@
}
bool operator==(const CompatibilityMatrix &lft, const CompatibilityMatrix &rgt) {
+ // ignore fileName().
return lft.mType == rgt.mType && lft.mLevel == rgt.mLevel && lft.mHals == rgt.mHals &&
lft.mXmlFiles == rgt.mXmlFiles &&
(lft.mType != SchemaType::DEVICE ||
@@ -320,12 +335,12 @@
}
std::unique_ptr<CompatibilityMatrix> CompatibilityMatrix::combine(
- Level deviceLevel, std::vector<Named<CompatibilityMatrix>>* matrices, std::string* error) {
+ Level deviceLevel, std::vector<CompatibilityMatrix>* matrices, std::string* error) {
// Check type.
for (const auto& e : *matrices) {
- if (e.object.type() != SchemaType::FRAMEWORK) {
+ if (e.type() != SchemaType::FRAMEWORK) {
if (error) {
- *error = "File \"" + e.name + "\" is not a framework compatibility matrix.";
+ *error = "File \"" + e.fileName() + "\" is not a framework compatibility matrix.";
return nullptr;
}
}
@@ -333,15 +348,15 @@
// Matrices with unspecified (empty) level are auto-filled with deviceLevel.
for (auto& e : *matrices) {
- if (e.object.level() == Level::UNSPECIFIED) {
- e.object.mLevel = deviceLevel;
+ if (e.level() == Level::UNSPECIFIED) {
+ e.mLevel = deviceLevel;
}
}
// Add from low to high FCM version so that optional <kernel> requirements are added correctly.
// See comment in addAllAsOptional.
std::sort(matrices->begin(), matrices->end(),
- [](const auto& x, const auto& y) { return x.object.level() < y.object.level(); });
+ [](const auto& x, const auto& y) { return x.level() < y.level(); });
auto baseMatrix = std::make_unique<CompatibilityMatrix>();
baseMatrix->mLevel = deviceLevel;
@@ -349,31 +364,31 @@
std::vector<std::string> parsedFiles;
for (auto& e : *matrices) {
- if (e.object.level() < deviceLevel) {
+ if (e.level() < deviceLevel) {
continue;
}
bool success = false;
- if (e.object.level() == deviceLevel) {
+ if (e.level() == deviceLevel) {
success = baseMatrix->addAll(&e, error);
} else {
success = baseMatrix->addAllAsOptional(&e, error);
}
if (!success) {
if (error) {
- *error = "Conflict when merging \"" + e.name + "\": " + *error + "\n" +
+ *error = "Conflict when merging \"" + e.fileName() + "\": " + *error + "\n" +
"Previous files:\n" + base::Join(parsedFiles, "\n");
}
return nullptr;
}
- parsedFiles.push_back(e.name);
+ parsedFiles.push_back(e.fileName());
}
return baseMatrix;
}
std::unique_ptr<CompatibilityMatrix> CompatibilityMatrix::combineDeviceMatrices(
- std::vector<Named<CompatibilityMatrix>>* matrices, std::string* error) {
+ std::vector<CompatibilityMatrix>* matrices, std::string* error) {
auto baseMatrix = std::make_unique<CompatibilityMatrix>();
baseMatrix->mType = SchemaType::DEVICE;
@@ -382,36 +397,34 @@
bool success = baseMatrix->addAll(&e, error);
if (!success) {
if (error) {
- *error = "Conflict when merging \"" + e.name + "\": " + *error + "\n" +
+ *error = "Conflict when merging \"" + e.fileName() + "\": " + *error + "\n" +
"Previous files:\n" + base::Join(parsedFiles, "\n");
}
return nullptr;
}
- parsedFiles.push_back(e.name);
+ parsedFiles.push_back(e.fileName());
}
return baseMatrix;
}
-bool CompatibilityMatrix::addAll(Named<CompatibilityMatrix>* inputMatrix, std::string* error) {
- if (!addAllHals(&inputMatrix->object, error) || !addAllXmlFiles(&inputMatrix->object, error) ||
- !addAllKernels(&inputMatrix->object, error) || !addSepolicy(&inputMatrix->object, error) ||
- !addAvbMetaVersion(&inputMatrix->object, error) || !addVndk(&inputMatrix->object, error) ||
- !addVendorNdk(&inputMatrix->object, error) || !addSystemSdk(&inputMatrix->object, error)) {
+bool CompatibilityMatrix::addAll(CompatibilityMatrix* inputMatrix, std::string* error) {
+ if (!addAllHals(inputMatrix, error) || !addAllXmlFiles(inputMatrix, error) ||
+ !addAllKernels(inputMatrix, error) || !addSepolicy(inputMatrix, error) ||
+ !addAvbMetaVersion(inputMatrix, error) || !addVndk(inputMatrix, error) ||
+ !addVendorNdk(inputMatrix, error) || !addSystemSdk(inputMatrix, error)) {
if (error) {
- *error = "File \"" + inputMatrix->name + "\" cannot be added: " + *error + ".";
+ *error = "File \"" + inputMatrix->fileName() + "\" cannot be added: " + *error + ".";
}
return false;
}
return true;
}
-bool CompatibilityMatrix::addAllAsOptional(Named<CompatibilityMatrix>* inputMatrix,
- std::string* error) {
- if (!addAllHalsAsOptional(&inputMatrix->object, error) ||
- !addAllXmlFilesAsOptional(&inputMatrix->object, error) ||
- !addAllKernels(&inputMatrix->object, error)) {
+bool CompatibilityMatrix::addAllAsOptional(CompatibilityMatrix* inputMatrix, std::string* error) {
+ if (!addAllHalsAsOptional(inputMatrix, error) ||
+ !addAllXmlFilesAsOptional(inputMatrix, error) || !addAllKernels(inputMatrix, error)) {
if (error) {
- *error = "File \"" + inputMatrix->name + "\" cannot be added: " + *error;
+ *error = "File \"" + inputMatrix->fileName() + "\" cannot be added: " + *error;
}
return false;
}
diff --git a/HalManifest.cpp b/HalManifest.cpp
index 9118773..3fcbc22 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -41,27 +41,50 @@
using details::mergeField;
// Check <version> tag for all <hal> with the same name.
-bool HalManifest::shouldAdd(const ManifestHal& hal) const {
- if (!hal.isValid()) {
+bool HalManifest::shouldAdd(const ManifestHal& hal, std::string* error) const {
+ if (!hal.isValid(error)) {
+ if (error) {
+ error->insert(0, "HAL '" + hal.name + "' is not valid: ");
+ if (!hal.fileName().empty()) {
+ error->insert(0, "For file " + hal.fileName() + ": ");
+ }
+ }
return false;
}
if (hal.isOverride()) {
return true;
}
auto existingHals = mHals.equal_range(hal.name);
- std::set<size_t> existingMajorVersions;
+ std::map<size_t, std::tuple<const ManifestHal*, Version>> existing;
for (auto it = existingHals.first; it != existingHals.second; ++it) {
- for (const auto& v : it->second.versions) {
+ const ManifestHal& existingHal = it->second;
+ for (const auto& v : existingHal.versions) {
// Assume integrity on existingHals, so no check on emplace().second
- existingMajorVersions.insert(v.majorVer);
+ existing.emplace(v.majorVer, std::make_tuple(&existingHal, v));
}
}
+ bool success = true;
for (const auto& v : hal.versions) {
- if (!existingMajorVersions.emplace(v.majorVer).second /* no insertion */) {
- return false;
+ auto&& [existingIt, inserted] = existing.emplace(v.majorVer, std::make_tuple(&hal, v));
+ if (inserted) {
+ continue;
+ }
+ success = false;
+ if (error) {
+ auto&& [existingHal, existingVersion] = existingIt->second;
+ *error = "Conflicting major version: " + to_string(existingVersion);
+ if (!existingHal->fileName().empty()) {
+ *error += " (from " + existingHal->fileName() + ")";
+ }
+ *error += " vs. " + to_string(v);
+ if (!hal.fileName().empty()) {
+ *error += " (from " + hal.fileName() + ")";
+ }
+ *error +=
+ ". Check whether or not multiple modules providing the same HAL are installed.";
}
}
- return true;
+ return success;
}
// Remove elements from "list" if p(element) returns true.
@@ -90,7 +113,7 @@
});
}
-bool HalManifest::add(ManifestHal&& halToAdd) {
+bool HalManifest::add(ManifestHal&& halToAdd, std::string* error) {
if (halToAdd.isOverride()) {
if (halToAdd.isDisabledHal()) {
// Special syntax when there are no instances at all. Remove all existing HALs
@@ -103,7 +126,25 @@
}
}
- return HalGroup::add(std::move(halToAdd));
+ if (!shouldAdd(halToAdd, error)) {
+ return false;
+ }
+
+ CHECK(addInternal(std::move(halToAdd)) != nullptr);
+ return true;
+}
+
+bool HalManifest::addAllHals(HalManifest* other, std::string* error) {
+ for (auto& pair : other->mHals) {
+ if (!add(std::move(pair.second), error)) {
+ if (error) {
+ error->insert(0, "HAL \"" + pair.first + "\" has a conflict: ");
+ }
+ return false;
+ }
+ }
+ other->mHals.clear();
+ return true;
}
bool HalManifest::shouldAddXmlFile(const ManifestXmlFile& xmlFile) const {
@@ -465,6 +506,7 @@
}
bool operator==(const HalManifest &lft, const HalManifest &rgt) {
+ // ignore fileName().
return lft.mType == rgt.mType && lft.mLevel == rgt.mLevel && lft.mHals == rgt.mHals &&
lft.mXmlFiles == rgt.mXmlFiles &&
(lft.mType != SchemaType::DEVICE ||
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/ManifestHal.cpp b/ManifestHal.cpp
index 3a2a1c0..3fdc6e2 100644
--- a/ManifestHal.cpp
+++ b/ManifestHal.cpp
@@ -24,18 +24,33 @@
namespace android {
namespace vintf {
-bool ManifestHal::isValid() const {
- std::unordered_set<size_t> existing;
- for (const auto &v : versions) {
- if (existing.find(v.majorVer) != existing.end()) {
- return false;
- }
- existing.insert(v.majorVer);
+bool ManifestHal::isValid(std::string* error) const {
+ if (error) {
+ error->clear();
}
- return transportArch.isValid();
+
+ bool success = true;
+ std::map<size_t, Version> existing;
+ for (const auto &v : versions) {
+ auto&& [it, inserted] = existing.emplace(v.majorVer, v);
+ if (inserted) {
+ continue;
+ }
+ success = false;
+ if (error) {
+ *error += "Duplicated major version: " + to_string(v) + " vs. " + to_string(it->second);
+ }
+ }
+ std::string transportArchError;
+ if (!transportArch.isValid(&transportArchError)) {
+ success = false;
+ if (error) *error += transportArchError;
+ }
+ return success;
}
bool ManifestHal::operator==(const ManifestHal &other) const {
+ // ignore fileName().
if (format != other.format)
return false;
if (name != other.name)
diff --git a/TransportArch.cpp b/TransportArch.cpp
index 7fb63c3..19c1dcd 100644
--- a/TransportArch.cpp
+++ b/TransportArch.cpp
@@ -17,6 +17,8 @@
#include "TransportArch.h"
+#include "parse_string.h"
+
namespace android {
namespace vintf {
@@ -24,14 +26,30 @@
return transport == Transport::EMPTY && arch == Arch::ARCH_EMPTY;
}
-bool TransportArch::isValid() const {
+bool TransportArch::isValid(std::string* error) const {
+ if (error) {
+ error->clear();
+ }
+
switch (transport) {
case Transport::EMPTY: // fallthrough
case Transport::HWBINDER:
- return arch == Arch::ARCH_EMPTY;
+ if (arch == Arch::ARCH_EMPTY) {
+ return true;
+ }
+ if (error) {
+ *error += "Transport " + to_string(transport) + " requires empty arch attribute";
+ }
+ return false;
case Transport::PASSTHROUGH:
- return arch != Arch::ARCH_EMPTY;
+ if (arch != Arch::ARCH_EMPTY) {
+ return true;
+ }
+ if (error) {
+ *error += "Passthrough HALs requires arch attribute";
+ }
+ return false;
}
}
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 2611a56..c6ee42d 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -48,20 +48,24 @@
#endif
template <typename T, typename F>
-static std::shared_ptr<const T> Get(
- LockedSharedPtr<T> *ptr,
- bool skipCache,
- const F &fetchAllInformation) {
+static std::shared_ptr<const T> Get(const char* id, LockedSharedPtr<T>* ptr, bool skipCache,
+ const F& fetchAllInformation) {
std::unique_lock<std::mutex> _lock(ptr->mutex);
if (skipCache || !ptr->fetchedOnce) {
+ LOG(INFO) << id << ": Reading VINTF information.";
ptr->object = std::make_unique<T>();
std::string error;
status_t status = fetchAllInformation(ptr->object.get(), &error);
- if (status != OK) {
- LOG(WARNING) << status << " VINTF parse error: " << error;
+ if (status == OK) {
+ ptr->fetchedOnce = true;
+ LOG(INFO) << id << ": Successfully processed VINTF information";
+ } else {
+ // Doubled because a malformed error std::string might cause us to
+ // lose the status.
+ LOG(ERROR) << id << ": status from fetching VINTF information: " << status;
+ LOG(ERROR) << id << ": " << status << " VINTF parse error: " << error;
ptr->object = nullptr; // frees the old object
}
- ptr->fetchedOnce = true;
}
return ptr->object;
}
@@ -100,7 +104,7 @@
}
std::shared_ptr<const HalManifest> VintfObject::getDeviceHalManifest(bool skipCache) {
- return Get(&mDeviceManifest, skipCache,
+ return Get(__func__, &mDeviceManifest, skipCache,
std::bind(&VintfObject::fetchDeviceHalManifest, this, _1, _2));
}
@@ -109,7 +113,7 @@
}
std::shared_ptr<const HalManifest> VintfObject::getFrameworkHalManifest(bool skipCache) {
- return Get(&mFrameworkManifest, skipCache,
+ return Get(__func__, &mFrameworkManifest, skipCache,
std::bind(&VintfObject::fetchFrameworkHalManifest, this, _1, _2));
}
@@ -119,7 +123,8 @@
std::shared_ptr<const CompatibilityMatrix> VintfObject::getDeviceCompatibilityMatrix(
bool skipCache) {
- return Get(&mDeviceMatrix, skipCache, std::bind(&VintfObject::fetchDeviceMatrix, this, _1, _2));
+ return Get(__func__, &mDeviceMatrix, skipCache,
+ std::bind(&VintfObject::fetchDeviceMatrix, this, _1, _2));
}
std::shared_ptr<const CompatibilityMatrix> VintfObject::GetFrameworkCompatibilityMatrix(bool skipCache) {
@@ -134,13 +139,13 @@
std::unique_lock<std::mutex> _lock(mFrameworkCompatibilityMatrixMutex);
auto combined =
- Get(&mCombinedFrameworkMatrix, skipCache,
+ Get(__func__, &mCombinedFrameworkMatrix, skipCache,
std::bind(&VintfObject::getCombinedFrameworkMatrix, this, deviceManifest, _1, _2));
if (combined != nullptr) {
return combined;
}
- return Get(&mFrameworkMatrix, skipCache,
+ return Get(__func__, &mFrameworkMatrix, skipCache,
std::bind(&CompatibilityMatrix::fetchAllInformation, _1, getFileSystem().get(),
kSystemLegacyMatrix, _2));
}
@@ -148,7 +153,7 @@
status_t VintfObject::getCombinedFrameworkMatrix(
const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out,
std::string* error) {
- std::vector<Named<CompatibilityMatrix>> matrixFragments;
+ std::vector<CompatibilityMatrix> matrixFragments;
auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, error);
if (matrixFragmentsStatus != OK) {
return matrixFragmentsStatus;
@@ -177,8 +182,8 @@
if (deviceLevel == Level::UNSPECIFIED) {
// Cannot infer FCM version. Combine all matrices by assuming
// Shipping FCM Version == min(all supported FCM Versions in the framework)
- for (auto&& pair : matrixFragments) {
- Level fragmentLevel = pair.object.level();
+ for (auto&& fragment : matrixFragments) {
+ Level fragmentLevel = fragment.level();
if (fragmentLevel != Level::UNSPECIFIED && deviceLevel > fragmentLevel) {
deviceLevel = fragmentLevel;
}
@@ -221,7 +226,7 @@
if (!manifest->addAll(&fragmentManifest, error)) {
if (error) {
- error->insert(0, "Cannot add manifest fragment " + directory + file + ":");
+ error->insert(0, "Cannot add manifest fragment " + directory + file + ": ");
}
return UNKNOWN_ERROR;
}
@@ -426,24 +431,24 @@
}
}
-status_t VintfObject::getOneMatrix(const std::string& path, Named<CompatibilityMatrix>* out,
+status_t VintfObject::getOneMatrix(const std::string& path, CompatibilityMatrix* out,
std::string* error) {
std::string content;
status_t status = getFileSystem()->fetch(path, &content, error);
if (status != OK) {
return status;
}
- if (!gCompatibilityMatrixConverter(&out->object, content, error)) {
+ if (!gCompatibilityMatrixConverter(out, content, error)) {
if (error) {
error->insert(0, "Cannot parse " + path + ": ");
}
return BAD_VALUE;
}
- out->name = path;
+ out->setFileName(path);
return OK;
}
-status_t VintfObject::getAllFrameworkMatrixLevels(std::vector<Named<CompatibilityMatrix>>* results,
+status_t VintfObject::getAllFrameworkMatrixLevels(std::vector<CompatibilityMatrix>* results,
std::string* error) {
std::vector<std::string> dirs = {
kSystemVintfDir,
@@ -461,7 +466,7 @@
}
for (const std::string& fileName : fileNames) {
std::string path = dir + fileName;
- Named<CompatibilityMatrix> namedMatrix;
+ CompatibilityMatrix namedMatrix;
std::string matrixError;
status_t matrixStatus = getOneMatrix(path, &namedMatrix, &matrixError);
if (matrixStatus != OK) {
@@ -819,7 +824,7 @@
int32_t VintfObject::checkDeprecation(const ListInstances& listInstances,
const std::vector<HidlInterfaceMetadata>& hidlMetadata,
std::string* error) {
- std::vector<Named<CompatibilityMatrix>> matrixFragments;
+ std::vector<CompatibilityMatrix> matrixFragments;
auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, error);
if (matrixFragmentsStatus != OK) {
return matrixFragmentsStatus;
@@ -843,8 +848,8 @@
const CompatibilityMatrix* targetMatrix = nullptr;
for (const auto& namedMatrix : matrixFragments) {
- if (namedMatrix.object.level() == deviceLevel) {
- targetMatrix = &namedMatrix.object;
+ if (namedMatrix.level() == deviceLevel) {
+ targetMatrix = &namedMatrix;
}
}
if (targetMatrix == nullptr) {
@@ -864,11 +869,10 @@
// Matrices with unspecified level are considered "current".
bool isDeprecated = false;
for (const auto& namedMatrix : matrixFragments) {
- if (namedMatrix.object.level() == Level::UNSPECIFIED) continue;
- if (namedMatrix.object.level() >= deviceLevel) continue;
+ if (namedMatrix.level() == Level::UNSPECIFIED) continue;
+ if (namedMatrix.level() >= deviceLevel) continue;
- const auto& oldMatrix = namedMatrix.object;
- for (const MatrixHal& hal : oldMatrix.getHals()) {
+ for (const MatrixHal& hal : namedMatrix.getHals()) {
if (IsHalDeprecated(hal, *targetMatrix, listInstances, childrenMap, error)) {
isDeprecated = true;
}
@@ -924,7 +928,7 @@
}
android::base::Result<bool> VintfObject::hasFrameworkCompatibilityMatrixExtensions() {
- std::vector<Named<CompatibilityMatrix>> matrixFragments;
+ std::vector<CompatibilityMatrix> matrixFragments;
std::string error;
status_t status = getAllFrameworkMatrixLevels(&matrixFragments, &error);
if (status != OK) {
@@ -933,17 +937,16 @@
}
for (const auto& namedMatrix : matrixFragments) {
// Returns true if product matrix exists.
- if (android::base::StartsWith(namedMatrix.name, kProductVintfDir)) {
+ if (android::base::StartsWith(namedMatrix.fileName(), kProductVintfDir)) {
return true;
}
// Returns true if system_ext matrix exists.
- if (android::base::StartsWith(namedMatrix.name, kSystemExtVintfDir)) {
+ if (android::base::StartsWith(namedMatrix.fileName(), kSystemExtVintfDir)) {
return true;
}
// Returns true if device system matrix exists.
- if (android::base::StartsWith(namedMatrix.name, kSystemVintfDir) &&
- namedMatrix.object.level() == Level::UNSPECIFIED &&
- !namedMatrix.object.getHals().empty()) {
+ if (android::base::StartsWith(namedMatrix.fileName(), kSystemVintfDir) &&
+ namedMatrix.level() == Level::UNSPECIFIED && !namedMatrix.getHals().empty()) {
return true;
}
}
diff --git a/check_vintf.cpp b/check_vintf.cpp
index d38d136..bdbbf5b 100644
--- a/check_vintf.cpp
+++ b/check_vintf.cpp
@@ -199,6 +199,7 @@
return nullptr;
}
auto ret = std::make_unique<T>();
+ ret->setFileName(path);
if (!converter(ret.get(), xml, &error)) {
LOG(ERROR) << "Cannot parse '" << path << "': " << error;
return nullptr;
diff --git a/include-test/vintf/AssembleVintf.h b/include-test/vintf/AssembleVintf.h
index 56b4811..03c49fb 100644
--- a/include-test/vintf/AssembleVintf.h
+++ b/include-test/vintf/AssembleVintf.h
@@ -49,7 +49,7 @@
virtual std::ostream& setOutputStream(Ostream&&) = 0;
virtual std::istream& addInputStream(const std::string& name, Istream&&) = 0;
- virtual std::istream& setCheckInputStream(Istream&&) = 0;
+ virtual std::istream& setCheckInputStream(const std::string& name, Istream&&) = 0;
virtual std::istream& addKernelConfigInputStream(const KernelVersion& kernelVer,
const std::string& name, Istream&& in) = 0;
virtual void setFakeEnv(const std::string& key, const std::string& value) = 0;
diff --git a/include/vintf/CompatibilityMatrix.h b/include/vintf/CompatibilityMatrix.h
index 6bb8fe6..b598037 100644
--- a/include/vintf/CompatibilityMatrix.h
+++ b/include/vintf/CompatibilityMatrix.h
@@ -30,19 +30,21 @@
#include "MatrixHal.h"
#include "MatrixInstance.h"
#include "MatrixKernel.h"
-#include "Named.h"
#include "SchemaType.h"
#include "Sepolicy.h"
#include "SystemSdk.h"
#include "VendorNdk.h"
#include "Vndk.h"
+#include "WithFileName.h"
#include "XmlFileGroup.h"
namespace android {
namespace vintf {
// Compatibility matrix defines what hardware does the framework requires.
-struct CompatibilityMatrix : public HalGroup<MatrixHal>, public XmlFileGroup<MatrixXmlFile> {
+struct CompatibilityMatrix : public HalGroup<MatrixHal>,
+ public XmlFileGroup<MatrixXmlFile>,
+ public WithFileName {
// Create a framework compatibility matrix.
CompatibilityMatrix() : mType(SchemaType::FRAMEWORK) {}
@@ -62,6 +64,10 @@
std::string getVendorNdkVersion() const;
+ bool add(MatrixHal&&, std::string* error = nullptr) override;
+ // Move all hals from another CompatibilityMatrix to this.
+ bool addAllHals(CompatibilityMatrix* other, std::string* error = nullptr);
+
protected:
bool forEachInstanceOfVersion(
HalFormat format, const std::string& package, const Version& expectVersion,
@@ -69,7 +75,7 @@
private:
// Add everything in inputMatrix to "this" as requirements.
- bool addAll(Named<CompatibilityMatrix>* inputMatrix, std::string* error);
+ bool addAll(CompatibilityMatrix* inputMatrix, std::string* error);
// Add all <kernel> from other to "this". Error if there is a conflict.
bool addAllKernels(CompatibilityMatrix* other, std::string* error);
@@ -93,7 +99,7 @@
bool addSystemSdk(CompatibilityMatrix* other, std::string* error);
// Add everything in inputMatrix to "this" as optional.
- bool addAllAsOptional(Named<CompatibilityMatrix>* inputMatrix, std::string* error);
+ bool addAllAsOptional(CompatibilityMatrix* inputMatrix, std::string* error);
// Add all HALs as optional HALs from "other". This function moves MatrixHal objects
// from "other".
@@ -114,12 +120,13 @@
// with lower level()
// - <sepolicy>, <avb><vbmeta-version> is ignored
// Return the combined matrix, nullptr if any error (e.g. conflict of information).
- static std::unique_ptr<CompatibilityMatrix> combine(
- Level deviceLevel, std::vector<Named<CompatibilityMatrix>>* matrices, std::string* error);
+ static std::unique_ptr<CompatibilityMatrix> combine(Level deviceLevel,
+ std::vector<CompatibilityMatrix>* matrices,
+ std::string* error);
// Combine a set of device compatibility matrices.
static std::unique_ptr<CompatibilityMatrix> combineDeviceMatrices(
- std::vector<Named<CompatibilityMatrix>>* matrices, std::string* error);
+ std::vector<CompatibilityMatrix>* matrices, std::string* error);
status_t fetchAllInformation(const FileSystem* fileSystem, const std::string& path,
std::string* error = nullptr);
diff --git a/include/vintf/HalGroup.h b/include/vintf/HalGroup.h
index db87cec..ba0d418 100644
--- a/include/vintf/HalGroup.h
+++ b/include/vintf/HalGroup.h
@@ -35,22 +35,9 @@
public:
virtual ~HalGroup() {}
- // Move all hals from another HalGroup to this.
- bool addAllHals(HalGroup* other, std::string* error = nullptr) {
- for (auto& pair : other->mHals) {
- if (!add(std::move(pair.second))) {
- if (error) {
- *error = "HAL \"" + pair.first + "\" has a conflict.";
- }
- return false;
- }
- }
- other->mHals.clear();
- return true;
- }
// Add an hal to this HalGroup so that it can be constructed programatically.
- virtual bool add(Hal&& hal) { return addInternal(std::move(hal)) != nullptr; }
+ virtual bool add(Hal&& hal, std::string* error = nullptr) = 0;
protected:
// Get all hals with the given name (e.g "android.hardware.camera").
@@ -186,9 +173,6 @@
// The component name looks like: android.hardware.foo
std::multimap<std::string, Hal> mHals;
- // override this to filter for add.
- virtual bool shouldAdd(const Hal&) const { return true; }
-
// Return an iterable to all Hal objects. Call it as follows:
// for (const auto& e : vm.getHals()) { }
ConstMultiMapValueIterable<std::string, Hal> getHals() const { return iterateValues(mHals); }
@@ -210,10 +194,8 @@
return &(it->second);
}
+ // Helper for "add(Hal)". Returns pointer to inserted object. Never null.
Hal* addInternal(Hal&& hal) {
- if (!shouldAdd(hal)) {
- return nullptr;
- }
std::string name = hal.getName();
auto it = mHals.emplace(std::move(name), std::move(hal)); // always succeeds
return &it->second;
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index 41298f0..04489c2 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -39,6 +39,7 @@
#include "VendorNdk.h"
#include "Version.h"
#include "Vndk.h"
+#include "WithFileName.h"
#include "XmlFileGroup.h"
namespace android {
@@ -55,13 +56,17 @@
// A HalManifest is reported by the hardware and query-able from
// framework code. This is the API for the framework.
-struct HalManifest : public HalGroup<ManifestHal>, public XmlFileGroup<ManifestXmlFile> {
+struct HalManifest : public HalGroup<ManifestHal>,
+ public XmlFileGroup<ManifestXmlFile>,
+ public WithFileName {
public:
// Construct a device HAL manifest.
HalManifest() : mType(SchemaType::DEVICE) {}
- bool add(ManifestHal&& hal) override;
+ bool add(ManifestHal&& hal, std::string* error = nullptr) override;
+ // Move all hals from another HalManifest to this.
+ bool addAllHals(HalManifest* other, std::string* error = nullptr);
// Given a component name (e.g. "android.hardware.camera"),
// return getHal(name)->transport if the component exist and v exactly matches
@@ -142,7 +147,7 @@
protected:
// Check before add()
- bool shouldAdd(const ManifestHal& toAdd) const override;
+ bool shouldAdd(const ManifestHal& toAdd, std::string* error) const;
bool shouldAddXmlFile(const ManifestXmlFile& toAdd) const override;
bool forEachInstanceOfVersion(
@@ -227,7 +232,6 @@
} framework;
};
-
} // namespace vintf
} // namespace android
diff --git a/include/vintf/ManifestHal.h b/include/vintf/ManifestHal.h
index 3a798a8..f40566a 100644
--- a/include/vintf/ManifestHal.h
+++ b/include/vintf/ManifestHal.h
@@ -30,12 +30,13 @@
#include "ManifestInstance.h"
#include "TransportArch.h"
#include "Version.h"
+#include "WithFileName.h"
namespace android {
namespace vintf {
// A component of HalManifest.
-struct ManifestHal {
+struct ManifestHal : public WithFileName {
using InstanceType = ManifestInstance;
ManifestHal() = default;
@@ -80,7 +81,7 @@
// Whether this hal is a valid one. Note that an empty ManifestHal
// (constructed via ManifestHal()) is valid.
- bool isValid() const;
+ bool isValid(std::string* error = nullptr) const;
// Return all versions mentioned by <version>s and <fqname>s.
void appendAllVersions(std::set<Version>* ret) const;
diff --git a/include/vintf/Named.h b/include/vintf/Named.h
deleted file mode 100644
index eacb70b..0000000
--- a/include/vintf/Named.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_VINTF_NAMED_H
-#define ANDROID_VINTF_NAMED_H
-
-#include <string>
-
-template <typename T>
-struct Named {
- std::string name;
- T object;
-
- Named() = default;
- Named(const std::string& n, const T& o) : name(n), object(o) {}
- Named(std::string&& n, T&& o) : name(std::move(n)), object(std::move(o)) {}
-};
-
-#endif // ANDROID_VINTF_NAMED_H
diff --git a/include/vintf/TransportArch.h b/include/vintf/TransportArch.h
index 51630de..8e892e8 100644
--- a/include/vintf/TransportArch.h
+++ b/include/vintf/TransportArch.h
@@ -52,7 +52,7 @@
// <transport arch="32+64">passthrough</transport>
// <transport>hwbinder</transport>
// Element doesn't exist
- bool isValid() const;
+ bool isValid(std::string* error = nullptr) const;
};
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index fa25669..4fb19bd 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -32,7 +32,6 @@
#include "FileSystem.h"
#include "HalManifest.h"
#include "Level.h"
-#include "Named.h"
#include "ObjectFactory.h"
#include "PropertyFetcher.h"
#include "RuntimeInfo.h"
@@ -308,9 +307,9 @@
private:
status_t getCombinedFrameworkMatrix(const std::shared_ptr<const HalManifest>& deviceManifest,
CompatibilityMatrix* out, std::string* error = nullptr);
- status_t getAllFrameworkMatrixLevels(std::vector<Named<CompatibilityMatrix>>* out,
+ status_t getAllFrameworkMatrixLevels(std::vector<CompatibilityMatrix>* out,
std::string* error = nullptr);
- status_t getOneMatrix(const std::string& path, Named<CompatibilityMatrix>* out,
+ status_t getOneMatrix(const std::string& path, CompatibilityMatrix* out,
std::string* error = nullptr);
status_t addDirectoryManifests(const std::string& directory, HalManifest* manifests,
std::string* error = nullptr);
diff --git a/include/vintf/WithFileName.h b/include/vintf/WithFileName.h
new file mode 100644
index 0000000..beed3e2
--- /dev/null
+++ b/include/vintf/WithFileName.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+
+namespace android::vintf {
+
+// WithFileName is a class that attaches a name to an object.
+// The name is often the file name or path of the source file where the object
+// is deserialized from. The name is used for informational and debugging
+// purposes. It is not retained when the object is serialized.
+// It is not meant to be used as an identifier of the object:
+// - there may be duplicated names;
+// - name may be empty.
+struct WithFileName {
+ WithFileName() = default;
+ WithFileName(const std::string& fileName) : mFileName(fileName) {}
+ const std::string& fileName() const { return mFileName; }
+ void setFileName(std::string&& fileName) { mFileName = std::move(fileName); }
+ void setFileName(const std::string& fileName) { mFileName = fileName; }
+
+ private:
+ std::string mFileName;
+};
+
+} // namespace android::vintf
diff --git a/parse_xml.cpp b/parse_xml.cpp
index e42f9f7..704ee8d 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -464,10 +464,7 @@
!parseText(root, &object->transport, error)) {
return false;
}
- if (!object->isValid()) {
- *error = "transport == " + ::android::vintf::to_string(object->transport) +
- " and arch == " + ::android::vintf::to_string(object->arch) +
- " is not a valid combination.";
+ if (!object->isValid(error)) {
return false;
}
return true;
@@ -760,7 +757,7 @@
object->format);
} break;
}
- if (!object->transportArch.isValid()) return false;
+ if (!object->transportArch.isValid(error)) return false;
object->interfaces.clear();
for (auto &&interface : interfaces) {
@@ -772,8 +769,8 @@
return false;
}
}
- if (!object->isValid()) {
- *error = "'" + object->name + "' is not a valid Manifest HAL.";
+ if (!object->isValid(error)) {
+ error->insert(0, "'" + object->name + "' is not a valid Manifest HAL: ");
return false;
}
// Do not check for target-side libvintf to avoid restricting upgrade accidentally.
@@ -1033,11 +1030,18 @@
return false;
}
- std::vector<ManifestHal> hals;
- if (!parseAttr(root, "type", &object->mType, error) ||
- !parseChildren(root, manifestHalConverter, &hals, error)) {
+ if (!parseAttr(root, "type", &object->mType, error)) {
return false;
}
+
+ std::vector<ManifestHal> hals;
+ if (!parseChildren(root, manifestHalConverter, &hals, error)) {
+ return false;
+ }
+ for (auto&& hal : hals) {
+ hal.setFileName(object->fileName());
+ }
+
if (object->mType == SchemaType::DEVICE) {
// tags for device hal manifest only.
// <sepolicy> can be missing because it can be determined at build time, not hard-coded
diff --git a/test/AssembleVintfTest.cpp b/test/AssembleVintfTest.cpp
index 584bb48..75c32f7 100644
--- a/test/AssembleVintfTest.cpp
+++ b/test/AssembleVintfTest.cpp
@@ -235,7 +235,7 @@
getInstance()->setFakeEnv("PRODUCT_ENFORCE_VINTF_MANIFEST", "true");
resetOutput();
- getInstance()->setCheckInputStream(makeStream(manifest(1)));
+ getInstance()->setCheckInputStream("check.xml", makeStream(manifest(1)));
EXPECT_TRUE(getInstance()->assemble());
EXPECT_IN(
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"1\">\n"
@@ -253,7 +253,7 @@
getOutput());
resetOutput();
- getInstance()->setCheckInputStream(makeStream(manifest(2)));
+ getInstance()->setCheckInputStream("check.xml", makeStream(manifest(2)));
EXPECT_TRUE(getInstance()->assemble());
EXPECT_IN(
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"2\">\n"
@@ -271,7 +271,7 @@
getOutput());
resetOutput();
- getInstance()->setCheckInputStream(makeStream(manifest(3)));
+ getInstance()->setCheckInputStream("check.xml", makeStream(manifest(3)));
EXPECT_TRUE(getInstance()->assemble());
EXPECT_IN(
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"3\">\n"
@@ -326,7 +326,7 @@
getInstance()->setFakeEnv("PROVIDED_VNDK_VERSIONS", "P 26 27 ");
std::string matrix = "<compatibility-matrix " + kMetaVersionStr + " type=\"device\"/>\n";
- getInstance()->setCheckInputStream(makeStream(matrix));
+ getInstance()->setCheckInputStream("check.xml", makeStream(matrix));
EXPECT_TRUE(getInstance()->assemble());
}
@@ -339,7 +339,7 @@
" <version>O</version>\n"
" </vendor-ndk>\n"
"</compatibility-matrix>\n";
- getInstance()->setCheckInputStream(makeStream(matrix));
+ getInstance()->setCheckInputStream("check.xml", makeStream(matrix));
EXPECT_FALSE(getInstance()->assemble());
}
@@ -352,7 +352,7 @@
" <version>27</version>\n"
" </vendor-ndk>\n"
"</compatibility-matrix>\n";
- getInstance()->setCheckInputStream(makeStream(matrix));
+ getInstance()->setCheckInputStream("check.xml", makeStream(matrix));
EXPECT_TRUE(getInstance()->assemble());
}
@@ -408,7 +408,7 @@
{"PLATFORM_SEPOLICY_COMPAT_VERSIONS", "26.0 27.0"},
{"FRAMEWORK_VBMETA_VERSION", "1.0"},
{"PRODUCT_ENFORCE_VINTF_MANIFEST", "true"}});
- getInstance()->setCheckInputStream(makeStream(gEmptyOutManifest));
+ getInstance()->setCheckInputStream("check.xml", makeStream(gEmptyOutManifest));
addInput("compatibility_matrix.empty.xml",
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\">\n"
@@ -452,7 +452,7 @@
{"PLATFORM_SEPOLICY_COMPAT_VERSIONS", "26.0 27.0"},
{"FRAMEWORK_VBMETA_VERSION", "1.0"},
{"PRODUCT_ENFORCE_VINTF_MANIFEST", "true"}});
- getInstance()->setCheckInputStream(makeStream(gEmptyOutManifest));
+ getInstance()->setCheckInputStream("check.xml", makeStream(gEmptyOutManifest));
addInput("compatibility_matrix.empty.xml",
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\">\n"
@@ -475,7 +475,7 @@
{"PLATFORM_SEPOLICY_COMPAT_VERSIONS", "26.0 27.0"},
{"FRAMEWORK_VBMETA_VERSION", "1.0"},
{"PRODUCT_ENFORCE_VINTF_MANIFEST", "true"}});
- getInstance()->setCheckInputStream(makeStream(gEmptyOutManifest));
+ getInstance()->setCheckInputStream("check.xml", makeStream(gEmptyOutManifest));
addInput("compatibility_matrix.foobar.xml",
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\">\n"
@@ -656,7 +656,7 @@
" </config>\n"
" </kernel>\n"
"</compatibility-matrix>\n");
- getInstance()->setCheckInputStream(makeStream(
+ getInstance()->setCheckInputStream("check.xml", makeStream(
"<manifest " + kMetaVersionStr + " type=\"device\" target-level=\"1\">\n"
" <kernel target-level=\"1\" version=\"3.18.0\"/>\n"
" <sepolicy>\n"
@@ -675,7 +675,7 @@
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"1\">\n"
" <kernel version=\"3.18.0\" level=\"1\"/>\n"
"</compatibility-matrix>\n");
- getInstance()->setCheckInputStream(makeStream(
+ getInstance()->setCheckInputStream("check.xml", makeStream(
"<manifest " + kMetaVersionStr + " type=\"device\" target-level=\"1\">\n"
" <kernel target-level=\"1\"/>\n"
" <sepolicy>\n"
diff --git a/test/LibVintfTest.cpp b/test/LibVintfTest.cpp
index fac2306..6d56ba6 100644
--- a/test/LibVintfTest.cpp
+++ b/test/LibVintfTest.cpp
@@ -3242,13 +3242,6 @@
" </hal>\n"
"</manifest>\n";
ASSERT_TRUE(gHalManifestConverter(&manifest, xml, &error)) << error;
- EXPECT_IN(
- "android.hardware.foo:\n"
- " required: @1.1::IFoo/custom\n"
- " provided: \n"
- " @1.0::IFoo/custom\n"
- " @1.0::IFoo/default",
- error);
}
}
@@ -3547,6 +3540,39 @@
EXPECT_EQ(xml2, gHalManifestConverter(manifest1));
}
+TEST_F(LibVintfTest, ManifestAddAllConflictMajorVersion) {
+ std::string head =
+ "<manifest " + kMetaVersionStr + " type=\"device\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <version>";
+ std::string tail =
+ "</version>\n"
+ " <interface>\n"
+ " <name>IFoo</name>\n"
+ " </interface>\n"
+ " </hal>\n"
+ "</manifest>\n";
+
+ std::string xml1 = head + "1.0" + tail;
+ std::string xml2 = head + "1.1" + tail;
+
+ std::string error;
+ HalManifest manifest1;
+ manifest1.setFileName("1.xml");
+ ASSERT_TRUE(gHalManifestConverter(&manifest1, xml1, &error)) << error;
+ HalManifest manifest2;
+ manifest2.setFileName("2.xml");
+ ASSERT_TRUE(gHalManifestConverter(&manifest2, xml2, &error)) << error;
+
+ ASSERT_FALSE(manifest1.addAll(&manifest2, &error));
+
+ EXPECT_IN("android.hardware.foo", error);
+ EXPECT_IN("1.0 (from 1.xml)", error);
+ EXPECT_IN("1.1 (from 2.xml)", error);
+}
+
TEST_F(LibVintfTest, ManifestAddAllConflictLevel) {
std::string xml1 = "<manifest " + kMetaVersionStr + " type=\"device\" target-level=\"2\" />\n";
std::string xml2 = "<manifest " + kMetaVersionStr + " type=\"device\" target-level=\"3\" />\n";
@@ -3945,33 +3971,32 @@
struct FrameworkCompatibilityMatrixCombineTest : public LibVintfTest {
virtual void SetUp() override {
- matrices = {
- {"compatibility_matrix.1_1.xml", CompatibilityMatrix{}},
- {"compatibility_matrix.1_2.xml", CompatibilityMatrix{}},
- };
+ matrices.resize(2);
+ matrices[0].setFileName("compatibility_matrix.1_1.xml");
+ matrices[1].setFileName("compatibility_matrix.1_2.xml");
}
// Access to private methods.
std::unique_ptr<CompatibilityMatrix> combine(Level deviceLevel,
- std::vector<Named<CompatibilityMatrix>>* matrices,
+ std::vector<CompatibilityMatrix>* matrices,
std::string* error) {
return CompatibilityMatrix::combine(deviceLevel, matrices, error);
}
- std::vector<Named<CompatibilityMatrix>> matrices;
+ std::vector<CompatibilityMatrix> matrices;
std::string error;
};
// Combining framework compatibility matrix with conflicting minlts fails
TEST_F(FrameworkCompatibilityMatrixCombineTest, ConflictMinlts) {
ASSERT_TRUE(gCompatibilityMatrixConverter(
- &matrices[0].object,
+ &matrices[0],
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"1\">\n"
" <kernel version=\"3.18.5\" />\n"
"</compatibility-matrix>\n",
&error))
<< error;
ASSERT_TRUE(gCompatibilityMatrixConverter(
- &matrices[1].object,
+ &matrices[1],
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"1\">\n"
" <kernel version=\"3.18.6\" />\n"
"</compatibility-matrix>\n",
@@ -4007,14 +4032,14 @@
" </kernel>\n";
ASSERT_TRUE(gCompatibilityMatrixConverter(
- &matrices[0].object,
+ &matrices[0],
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"1\">\n"
" <kernel version=\"3.18.5\" />\n" +
conditionedKernel + "</compatibility-matrix>\n",
&error))
<< error;
ASSERT_TRUE(gCompatibilityMatrixConverter(
- &matrices[1].object,
+ &matrices[1],
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"1\">\n" + simpleKernel +
"</compatibility-matrix>\n",
&error))
@@ -4031,7 +4056,7 @@
// Combining framework compatibility matrix with conflicting sepolicy fails
TEST_F(FrameworkCompatibilityMatrixCombineTest, ConflictSepolicy) {
ASSERT_TRUE(gCompatibilityMatrixConverter(
- &matrices[0].object,
+ &matrices[0],
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"1\">\n"
" <sepolicy>\n"
" <kernel-sepolicy-version>30</kernel-sepolicy-version>\n"
@@ -4040,7 +4065,7 @@
&error))
<< error;
ASSERT_TRUE(gCompatibilityMatrixConverter(
- &matrices[1].object,
+ &matrices[1],
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"1\">\n"
" <sepolicy>\n"
" <kernel-sepolicy-version>29</kernel-sepolicy-version>\n"
@@ -4057,7 +4082,7 @@
// Combining framework compatibility matrix with conflicting avb fails
TEST_F(FrameworkCompatibilityMatrixCombineTest, ConflictAvb) {
ASSERT_TRUE(gCompatibilityMatrixConverter(
- &matrices[0].object,
+ &matrices[0],
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"1\">\n"
" <avb>\n"
" <vbmeta-version>1.1</vbmeta-version>\n"
@@ -4066,7 +4091,7 @@
&error))
<< error;
ASSERT_TRUE(gCompatibilityMatrixConverter(
- &matrices[1].object,
+ &matrices[1],
"<compatibility-matrix " + kMetaVersionStr + " type=\"framework\" level=\"1\">\n"
" <avb>\n"
" <vbmeta-version>1.0</vbmeta-version>\n"
@@ -4105,9 +4130,9 @@
std::string hidlOptional = std::string(hidl).replace(hidl.find("false"), 5, "true");
std::string error;
{
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0].object, head1 + aidl + tail, &error))
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0], head1 + aidl + tail, &error))
<< error;
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1].object, head1 + hidl + tail, &error))
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1], head1 + hidl + tail, &error))
<< error;
auto combined = combine(Level{1}, &matrices, &error);
@@ -4118,9 +4143,9 @@
EXPECT_IN(hidl, combinedXml);
}
{
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0].object, head1 + aidl + tail, &error))
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0], head1 + aidl + tail, &error))
<< error;
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1].object, head2 + hidl + tail, &error))
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1], head2 + hidl + tail, &error))
<< error;
auto combined = combine(Level{1}, &matrices, &error);
@@ -4131,9 +4156,9 @@
EXPECT_IN(hidlOptional, combinedXml);
}
{
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0].object, head2 + aidl + tail, &error))
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0], head2 + aidl + tail, &error))
<< error;
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1].object, head1 + hidl + tail, &error))
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1], head1 + hidl + tail, &error))
<< error;
auto combined = combine(Level{1}, &matrices, &error);
@@ -4147,18 +4172,17 @@
struct DeviceCompatibilityMatrixCombineTest : public LibVintfTest {
virtual void SetUp() override {
- matrices = {
- {"compatibility_matrix.1.xml", CompatibilityMatrix{}},
- {"compatibility_matrix.2.xml", CompatibilityMatrix{}},
- };
+ matrices.resize(2);
+ matrices[0].setFileName("compatibility_matrix.1.xml");
+ matrices[1].setFileName("compatibility_matrix.2.xml");
}
// Access to private methods.
- std::unique_ptr<CompatibilityMatrix> combine(std::vector<Named<CompatibilityMatrix>>* matrices,
+ std::unique_ptr<CompatibilityMatrix> combine(std::vector<CompatibilityMatrix>* matrices,
std::string* error) {
return CompatibilityMatrix::combineDeviceMatrices(matrices, error);
}
- std::vector<Named<CompatibilityMatrix>> matrices;
+ std::vector<CompatibilityMatrix> matrices;
std::string error;
};
@@ -4183,9 +4207,9 @@
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"};
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0].object, head + halFoo + tail, &error))
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0], head + halFoo + tail, &error))
<< error;
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1].object, head + halBar + tail, &error))
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1], head + halBar + tail, &error))
<< error;
auto combined = combine(&matrices, &error);
@@ -4209,8 +4233,8 @@
" <version>Q</version>\n"
" </vendor-ndk>\n"
"</compatibility-matrix>\n"};
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0].object, vendorNdkP, &error)) << error;
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1].object, vendorNdkQ, &error)) << error;
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0], vendorNdkP, &error)) << error;
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1], vendorNdkQ, &error)) << error;
auto combined = combine(&matrices, &error);
ASSERT_EQ(nullptr, combined) << gCompatibilityMatrixConverter(*combined);
@@ -4237,9 +4261,9 @@
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n";
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0].object, head + aidl + tail, &error))
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[0], head + aidl + tail, &error))
<< error;
- ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1].object, head + hidl + tail, &error))
+ ASSERT_TRUE(gCompatibilityMatrixConverter(&matrices[1], head + hidl + tail, &error))
<< error;
auto combined = combine(&matrices, &error);
diff --git a/utils.h b/utils.h
index 5378b67..83cb874 100644
--- a/utils.h
+++ b/utils.h
@@ -33,6 +33,12 @@
template <typename T>
status_t fetchAllInformation(const FileSystem* fileSystem, const std::string& path,
const XmlConverter<T>& converter, T* outObject, std::string* error) {
+ if (outObject->fileName().empty()) {
+ outObject->setFileName(path);
+ } else {
+ outObject->setFileName(outObject->fileName() + ":" + path);
+ }
+
std::string info;
status_t result = fileSystem->fetch(path, &info, error);
diff --git a/xsd/compatibilityMatrix/Android.bp b/xsd/compatibilityMatrix/Android.bp
index 2df3460..1741495 100644
--- a/xsd/compatibilityMatrix/Android.bp
+++ b/xsd/compatibilityMatrix/Android.bp
@@ -14,8 +14,13 @@
// limitations under the License.
//
+filegroup {
+ name: "compatibility_matrix_schema",
+ srcs: ["compatibility_matrix.xsd"],
+}
+
xsd_config {
name: "compatibility_matrix",
- srcs: ["compatibility_matrix.xsd"],
+ srcs: [":compatibility_matrix_schema"],
package_name: "compatibility.matrix",
}
diff --git a/xsd/compatibilityMatrix/api/current.txt b/xsd/compatibilityMatrix/api/current.txt
index a326dd1..f3a255a 100644
--- a/xsd/compatibilityMatrix/api/current.txt
+++ b/xsd/compatibilityMatrix/api/current.txt
@@ -71,8 +71,10 @@
ctor public Kernel();
method public compatibility.matrix.Kernel.Conditions getConditions();
method public java.util.List<compatibility.matrix.Config> getConfig();
+ method public String getLevel();
method public String getVersion();
method public void setConditions(compatibility.matrix.Kernel.Conditions);
+ method public void setLevel(String);
method public void setVersion(String);
}
diff --git a/xsd/compatibilityMatrix/compatibility_matrix.xsd b/xsd/compatibilityMatrix/compatibility_matrix.xsd
index b8c9fa5..8ccb6b2 100644
--- a/xsd/compatibilityMatrix/compatibility_matrix.xsd
+++ b/xsd/compatibilityMatrix/compatibility_matrix.xsd
@@ -64,6 +64,7 @@
<xs:element name="config" type="config" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="version" type="xs:string"/>
+ <xs:attribute name="level" type="xs:string"/>
</xs:complexType>
<xs:complexType name="config">
<xs:sequence>