upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
403
android/system/libvintf/HalManifest.cpp
Normal file
403
android/system/libvintf/HalManifest.cpp
Normal file
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "libvintf"
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "HalManifest.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
|
||||
#include "parse_string.h"
|
||||
#include "parse_xml.h"
|
||||
#include "utils.h"
|
||||
#include "CompatibilityMatrix.h"
|
||||
|
||||
namespace android {
|
||||
namespace vintf {
|
||||
|
||||
constexpr Version HalManifest::kVersion;
|
||||
|
||||
// Check <version> tag for all <hal> with the same name.
|
||||
bool HalManifest::shouldAdd(const ManifestHal& hal) const {
|
||||
if (!hal.isValid()) {
|
||||
return false;
|
||||
}
|
||||
auto existingHals = mHals.equal_range(hal.name);
|
||||
std::set<size_t> existingMajorVersions;
|
||||
for (auto it = existingHals.first; it != existingHals.second; ++it) {
|
||||
for (const auto& v : it->second.versions) {
|
||||
// Assume integrity on existingHals, so no check on emplace().second
|
||||
existingMajorVersions.insert(v.majorVer);
|
||||
}
|
||||
}
|
||||
for (const auto& v : hal.versions) {
|
||||
if (!existingMajorVersions.emplace(v.majorVer).second /* no insertion */) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HalManifest::shouldAddXmlFile(const ManifestXmlFile& xmlFile) const {
|
||||
auto existingXmlFiles = getXmlFiles(xmlFile.name());
|
||||
for (auto it = existingXmlFiles.first; it != existingXmlFiles.second; ++it) {
|
||||
if (xmlFile.version() == it->second.version()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<std::string> HalManifest::getHalNames() const {
|
||||
std::set<std::string> names{};
|
||||
for (const auto &hal : mHals) {
|
||||
names.insert(hal.first);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
std::set<std::string> HalManifest::getHalNamesAndVersions() const {
|
||||
std::set<std::string> names{};
|
||||
for (const auto &hal : getHals()) {
|
||||
for (const auto &version : hal.versions) {
|
||||
names.insert(hal.name + "@" + to_string(version));
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
std::set<std::string> HalManifest::getInterfaceNames(const std::string &name) const {
|
||||
std::set<std::string> interfaceNames{};
|
||||
for (const ManifestHal *hal : getHals(name)) {
|
||||
for (const auto &iface : hal->interfaces) {
|
||||
interfaceNames.insert(iface.first);
|
||||
}
|
||||
}
|
||||
return interfaceNames;
|
||||
}
|
||||
|
||||
std::vector<const ManifestHal *> HalManifest::getHals(const std::string &name) const {
|
||||
std::vector<const ManifestHal *> ret;
|
||||
auto range = mHals.equal_range(name);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
ret.push_back(&it->second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::vector<ManifestHal *> HalManifest::getHals(const std::string &name) {
|
||||
std::vector<ManifestHal *> ret;
|
||||
auto range = mHals.equal_range(name);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
ret.push_back(&it->second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Transport HalManifest::getTransport(const std::string &package, const Version &v,
|
||||
const std::string &interfaceName, const std::string &instanceName) const {
|
||||
|
||||
for (const ManifestHal *hal : getHals(package)) {
|
||||
bool found = false;
|
||||
for (auto& ver : hal->versions) {
|
||||
if (ver.majorVer == v.majorVer && ver.minorVer >= v.minorVer) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot find "
|
||||
<< to_string(v) << " in supported versions of " << package;
|
||||
continue;
|
||||
}
|
||||
auto it = hal->interfaces.find(interfaceName);
|
||||
if (it == hal->interfaces.end()) {
|
||||
LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot find interface '"
|
||||
<< interfaceName << "' in " << package << "@" << to_string(v);
|
||||
continue;
|
||||
}
|
||||
const auto &instances = it->second.instances;
|
||||
if (instances.find(instanceName) == instances.end()) {
|
||||
LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot find instance '"
|
||||
<< instanceName << "' in "
|
||||
<< package << "@" << to_string(v) << "::" << interfaceName;
|
||||
continue;
|
||||
}
|
||||
return hal->transportArch.transport;
|
||||
}
|
||||
LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot get transport for "
|
||||
<< package << "@" << v << "::" << interfaceName << "/" << instanceName;
|
||||
return Transport::EMPTY;
|
||||
|
||||
}
|
||||
|
||||
ConstMultiMapValueIterable<std::string, ManifestHal> HalManifest::getHals() const {
|
||||
return HalGroup<ManifestHal>::getHals();
|
||||
}
|
||||
|
||||
std::set<Version> HalManifest::getSupportedVersions(const std::string &name) const {
|
||||
std::set<Version> ret;
|
||||
for (const ManifestHal *hal : getHals(name)) {
|
||||
ret.insert(hal->versions.begin(), hal->versions.end());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::set<std::string> HalManifest::getInstances(
|
||||
const std::string &halName, const std::string &interfaceName) const {
|
||||
std::set<std::string> ret;
|
||||
for (const ManifestHal *hal : getHals(halName)) {
|
||||
auto it = hal->interfaces.find(interfaceName);
|
||||
if (it != hal->interfaces.end()) {
|
||||
ret.insert(it->second.instances.begin(), it->second.instances.end());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool HalManifest::hasInstance(const std::string &halName,
|
||||
const std::string &interfaceName, const std::string &instanceName) const {
|
||||
const auto &instances = getInstances(halName, interfaceName);
|
||||
return instances.find(instanceName) != instances.end();
|
||||
}
|
||||
|
||||
using InstancesOfVersion = std::map<std::string /* interface */,
|
||||
std::set<std::string /* instance */>>;
|
||||
using Instances = std::map<Version, InstancesOfVersion>;
|
||||
|
||||
static bool satisfyVersion(const MatrixHal& matrixHal, const Version& manifestHalVersion) {
|
||||
for (const VersionRange &matrixVersionRange : matrixHal.versionRanges) {
|
||||
// If Compatibility Matrix says 2.5-2.7, the "2.7" is purely informational;
|
||||
// the framework can work with all 2.5-2.infinity.
|
||||
if (matrixVersionRange.supportedBy(manifestHalVersion)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if matrixHal.interfaces is a subset of instancesOfVersion
|
||||
static bool satisfyAllInstances(const MatrixHal& matrixHal,
|
||||
const InstancesOfVersion &instancesOfVersion) {
|
||||
for (const auto& matrixHalInterfacePair : matrixHal.interfaces) {
|
||||
const std::string& interface = matrixHalInterfacePair.first;
|
||||
auto it = instancesOfVersion.find(interface);
|
||||
if (it == instancesOfVersion.end()) {
|
||||
return false;
|
||||
}
|
||||
const std::set<std::string>& manifestInterfaceInstances = it->second;
|
||||
const std::set<std::string>& matrixInterfaceInstances =
|
||||
matrixHalInterfacePair.second.instances;
|
||||
if (!std::includes(manifestInterfaceInstances.begin(), manifestInterfaceInstances.end(),
|
||||
matrixInterfaceInstances.begin(), matrixInterfaceInstances.end())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HalManifest::isCompatible(const MatrixHal& matrixHal) const {
|
||||
Instances instances;
|
||||
// Do the cross product version x interface x instance and sort them,
|
||||
// because interfaces / instances can span in multiple HALs.
|
||||
// This is efficient for small <hal> entries.
|
||||
for (const ManifestHal* manifestHal : getHals(matrixHal.name)) {
|
||||
for (const Version& manifestHalVersion : manifestHal->versions) {
|
||||
instances[manifestHalVersion] = {};
|
||||
for (const auto& halInterfacePair : manifestHal->interfaces) {
|
||||
const std::string& interface = halInterfacePair.first;
|
||||
const auto& toAdd = halInterfacePair.second.instances;
|
||||
instances[manifestHalVersion][interface].insert(toAdd.begin(), toAdd.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto& instanceMapPair : instances) {
|
||||
const Version& manifestHalVersion = instanceMapPair.first;
|
||||
const InstancesOfVersion& instancesOfVersion = instanceMapPair.second;
|
||||
if (!satisfyVersion(matrixHal, manifestHalVersion)) {
|
||||
continue;
|
||||
}
|
||||
if (!satisfyAllInstances(matrixHal, instancesOfVersion)) {
|
||||
continue;
|
||||
}
|
||||
return true; // match!
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// For each hal in mat, there must be a hal in manifest that supports this.
|
||||
std::vector<std::string> HalManifest::checkIncompatibility(const CompatibilityMatrix &mat,
|
||||
bool includeOptional) const {
|
||||
std::vector<std::string> incompatible;
|
||||
for (const MatrixHal &matrixHal : mat.getHals()) {
|
||||
if (!includeOptional && matrixHal.optional) {
|
||||
continue;
|
||||
}
|
||||
// don't check optional; put it in the incompatibility list as well.
|
||||
if (!isCompatible(matrixHal)) {
|
||||
incompatible.push_back(matrixHal.name);
|
||||
}
|
||||
}
|
||||
return incompatible;
|
||||
}
|
||||
|
||||
bool HalManifest::checkCompatibility(const CompatibilityMatrix &mat, std::string *error) const {
|
||||
if (mType == mat.mType) {
|
||||
if (error != nullptr) {
|
||||
*error = "Wrong type; checking " + to_string(mType) + " manifest against "
|
||||
+ to_string(mat.mType) + " compatibility matrix";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> incompatibleHals =
|
||||
checkIncompatibility(mat, false /* includeOptional */);
|
||||
if (!incompatibleHals.empty()) {
|
||||
if (error != nullptr) {
|
||||
*error = "HALs incompatible.";
|
||||
for (const auto &name : incompatibleHals) {
|
||||
*error += " " + name;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (mType == SchemaType::FRAMEWORK) {
|
||||
// TODO(b/36400653) enable this. It is disabled since vndk is not yet defined.
|
||||
#ifdef VINTF_CHECK_VNDK
|
||||
bool match = false;
|
||||
const auto &matVndk = mat.device.mVndk;
|
||||
for (const auto &vndk : framework.mVndks) {
|
||||
if (!vndk.mVersionRange.in(matVndk.mVersionRange)) {
|
||||
continue;
|
||||
}
|
||||
// version matches, check libaries
|
||||
std::vector<std::string> diff;
|
||||
std::set_difference(matVndk.mLibraries.begin(), matVndk.mLibraries.end(),
|
||||
vndk.mLibraries.begin(), vndk.mLibraries.end(),
|
||||
std::inserter(diff, diff.begin()))
|
||||
if (!diff.empty()) {
|
||||
if (error != nullptr) {
|
||||
*error = "Vndk libs incompatible.";
|
||||
for (const auto &name : diff) {
|
||||
*error += " " + name;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
if (!match) {
|
||||
if (error != nullptr) {
|
||||
*error = "Vndk version " + to_string(matVndk.mVersionRange) + " is not supported.";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if (mType == SchemaType::DEVICE) {
|
||||
bool match = false;
|
||||
for (const auto &range : mat.framework.mSepolicy.sepolicyVersions()) {
|
||||
if (range.supportedBy(device.mSepolicyVersion)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
if (error != nullptr) {
|
||||
*error = "Sepolicy version " + to_string(device.mSepolicyVersion)
|
||||
+ " doesn't satisify the requirements.";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CompatibilityMatrix HalManifest::generateCompatibleMatrix() const {
|
||||
CompatibilityMatrix matrix;
|
||||
|
||||
for (const ManifestHal &manifestHal : getHals()) {
|
||||
MatrixHal matrixHal{
|
||||
.format = manifestHal.format,
|
||||
.name = manifestHal.name,
|
||||
.optional = true,
|
||||
.interfaces = manifestHal.interfaces
|
||||
};
|
||||
for (const Version &manifestVersion : manifestHal.versions) {
|
||||
matrixHal.versionRanges.push_back({manifestVersion.majorVer, manifestVersion.minorVer});
|
||||
}
|
||||
matrix.add(std::move(matrixHal));
|
||||
}
|
||||
if (mType == SchemaType::FRAMEWORK) {
|
||||
matrix.mType = SchemaType::DEVICE;
|
||||
// VNDK does not need to be added for compatibility
|
||||
} else if (mType == SchemaType::DEVICE) {
|
||||
matrix.mType = SchemaType::FRAMEWORK;
|
||||
matrix.framework.mSepolicy = Sepolicy(0u /* kernelSepolicyVersion */,
|
||||
{{device.mSepolicyVersion.majorVer, device.mSepolicyVersion.minorVer}});
|
||||
}
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
status_t HalManifest::fetchAllInformation(const std::string &path) {
|
||||
return details::fetchAllInformation(path, gHalManifestConverter, this);
|
||||
}
|
||||
|
||||
SchemaType HalManifest::type() const {
|
||||
return mType;
|
||||
}
|
||||
|
||||
const Version &HalManifest::sepolicyVersion() const {
|
||||
CHECK(mType == SchemaType::DEVICE);
|
||||
return device.mSepolicyVersion;
|
||||
}
|
||||
|
||||
const std::vector<Vndk> &HalManifest::vndks() const {
|
||||
CHECK(mType == SchemaType::FRAMEWORK);
|
||||
return framework.mVndks;
|
||||
}
|
||||
|
||||
std::string HalManifest::getXmlFilePath(const std::string& xmlFileName,
|
||||
const Version& version) const {
|
||||
using std::literals::string_literals::operator""s;
|
||||
auto range = getXmlFiles(xmlFileName);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
const ManifestXmlFile& manifestXmlFile = it->second;
|
||||
if (manifestXmlFile.version() == version) {
|
||||
if (!manifestXmlFile.overriddenPath().empty()) {
|
||||
return manifestXmlFile.overriddenPath();
|
||||
}
|
||||
return "/"s + (type() == SchemaType::DEVICE ? "vendor" : "system") + "/etc/" +
|
||||
xmlFileName + "_V" + std::to_string(version.majorVer) + "_" +
|
||||
std::to_string(version.minorVer) + ".xml";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool operator==(const HalManifest &lft, const HalManifest &rgt) {
|
||||
return lft.mType == rgt.mType && lft.mHals == rgt.mHals && lft.mXmlFiles == rgt.mXmlFiles &&
|
||||
(lft.mType != SchemaType::DEVICE ||
|
||||
(lft.device.mSepolicyVersion == rgt.device.mSepolicyVersion)) &&
|
||||
(lft.mType != SchemaType::FRAMEWORK || (lft.framework.mVndks == rgt.framework.mVndks));
|
||||
}
|
||||
|
||||
} // namespace vintf
|
||||
} // namespace android
|
Loading…
Add table
Add a link
Reference in a new issue