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 "libvintf" 18 #include <android-base/logging.h> 19 20 #include "HalManifest.h" 21 22 #include <dirent.h> 23 24 #include <mutex> 25 #include <set> 26 27 #include <android-base/strings.h> 28 29 #include "CompatibilityMatrix.h" 30 #include "constants-private.h" 31 #include "constants.h" 32 #include "parse_string.h" 33 #include "parse_xml.h" 34 #include "utils.h" 35 36 namespace android { 37 namespace vintf { 38 39 using details::Instances; 40 using details::InstancesOfVersion; 41 using details::mergeField; 42 43 // Check <version> tag for all <hal> with the same name. 44 bool HalManifest::shouldAdd(const ManifestHal& hal, std::string* error) const { 45 if (!hal.isValid(error)) { 46 if (error) { 47 error->insert(0, "HAL '" + hal.name + "' is not valid: "); 48 if (!hal.fileName().empty()) { 49 error->insert(0, "For file " + hal.fileName() + ": "); 50 } 51 } 52 return false; 53 } 54 if (hal.isOverride()) { 55 return true; 56 } 57 return addingConflictingMajorVersion(hal, error); 58 } 59 60 bool HalManifest::addingConflictingMajorVersion(const ManifestHal& hal, std::string* error) const { 61 // Skip checking for AIDL HALs because they all contain kFakeAidlMajorVersion. 62 if (hal.format == HalFormat::AIDL) { 63 return true; 64 } 65 66 auto existingHals = mHals.equal_range(hal.name); 67 std::map<size_t, std::tuple<const ManifestHal*, Version>> existing; 68 for (auto it = existingHals.first; it != existingHals.second; ++it) { 69 const ManifestHal& existingHal = it->second; 70 for (const auto& v : existingHal.versions) { 71 // Assume integrity on existingHals, so no check on emplace().second 72 existing.emplace(v.majorVer, std::make_tuple(&existingHal, v)); 73 } 74 } 75 bool success = true; 76 for (const auto& v : hal.versions) { 77 auto&& [existingIt, inserted] = existing.emplace(v.majorVer, std::make_tuple(&hal, v)); 78 if (inserted) { 79 continue; 80 } 81 success = false; 82 if (error) { 83 auto&& [existingHal, existingVersion] = existingIt->second; 84 *error = "Conflicting major version: " + to_string(existingVersion); 85 if (!existingHal->fileName().empty()) { 86 *error += " (from " + existingHal->fileName() + ")"; 87 } 88 *error += " vs. " + to_string(v); 89 if (!hal.fileName().empty()) { 90 *error += " (from " + hal.fileName() + ")"; 91 } 92 *error += 93 ". Check whether or not multiple modules providing the same HAL are installed."; 94 } 95 } 96 return success; 97 } 98 99 // Remove elements from "list" if p(element) returns true. 100 template <typename List, typename Predicate> 101 static void removeIf(List& list, Predicate predicate) { 102 for (auto it = list.begin(); it != list.end();) { 103 if (predicate(*it)) { 104 it = list.erase(it); 105 } else { 106 ++it; 107 } 108 } 109 } 110 111 void HalManifest::removeHals(const std::string& name, size_t majorVer) { 112 removeIf(mHals, [&name, majorVer](auto& existingHalPair) { 113 auto& existingHal = existingHalPair.second; 114 if (existingHal.name != name) { 115 return false; 116 } 117 auto& existingVersions = existingHal.versions; 118 removeIf(existingVersions, [majorVer](const auto& existingVersion) { 119 return existingVersion.majorVer == majorVer; 120 }); 121 return existingVersions.empty(); 122 }); 123 } 124 125 bool HalManifest::add(ManifestHal&& halToAdd, std::string* error) { 126 if (halToAdd.isOverride()) { 127 if (halToAdd.isDisabledHal()) { 128 // Special syntax when there are no instances at all. Remove all existing HALs 129 // with the given name. 130 mHals.erase(halToAdd.name); 131 } 132 // If there are <version> tags, remove all existing major versions that causes a conflict. 133 for (const Version& versionToAdd : halToAdd.versions) { 134 removeHals(halToAdd.name, versionToAdd.majorVer); 135 } 136 } 137 138 if (!shouldAdd(halToAdd, error)) { 139 return false; 140 } 141 142 CHECK(addInternal(std::move(halToAdd)) != nullptr); 143 return true; 144 } 145 146 bool HalManifest::addAllHals(HalManifest* other, std::string* error) { 147 for (auto& pair : other->mHals) { 148 if (!add(std::move(pair.second), error)) { 149 if (error) { 150 error->insert(0, "HAL \"" + pair.first + "\" has a conflict: "); 151 } 152 return false; 153 } 154 } 155 other->mHals.clear(); 156 return true; 157 } 158 159 bool HalManifest::shouldAddXmlFile(const ManifestXmlFile& xmlFile) const { 160 auto existingXmlFiles = getXmlFiles(xmlFile.name()); 161 for (auto it = existingXmlFiles.first; it != existingXmlFiles.second; ++it) { 162 if (xmlFile.version() == it->second.version()) { 163 return false; 164 } 165 } 166 return true; 167 } 168 169 std::set<std::string> HalManifest::getHalNames() const { 170 std::set<std::string> names{}; 171 for (const auto &hal : mHals) { 172 names.insert(hal.first); 173 } 174 return names; 175 } 176 177 std::set<std::string> HalManifest::getHalNamesAndVersions() const { 178 std::set<std::string> names{}; 179 forEachInstance([&names](const ManifestInstance& e) { 180 switch (e.format()) { 181 case HalFormat::HIDL: 182 [[fallthrough]]; 183 case HalFormat::NATIVE: 184 names.insert(toFQNameString(e.package(), e.version())); 185 break; 186 case HalFormat::AIDL: 187 names.insert(e.package()); 188 break; 189 } 190 return true; 191 }); 192 return names; 193 } 194 195 Transport HalManifest::getHidlTransport(const std::string& package, const Version& v, 196 const std::string& interfaceName, 197 const std::string& instanceName) const { 198 Transport transport{Transport::EMPTY}; 199 forEachInstanceOfInterface(HalFormat::HIDL, package, v, interfaceName, [&](const auto& e) { 200 if (e.instance() == instanceName) { 201 transport = e.transport(); 202 } 203 return transport == Transport::EMPTY; // if not found, continue 204 }); 205 if (transport == Transport::EMPTY) { 206 LOG(DEBUG) << "HalManifest::getHidlTransport(" << mType << "): Cannot find " 207 << toFQNameString(package, v, interfaceName, instanceName); 208 } 209 return transport; 210 } 211 212 bool HalManifest::forEachInstanceOfVersion( 213 HalFormat format, const std::string& package, const Version& expectVersion, 214 const std::function<bool(const ManifestInstance&)>& func) const { 215 for (const ManifestHal* hal : getHals(package)) { 216 bool cont = hal->forEachInstance([&](const ManifestInstance& manifestInstance) { 217 if (manifestInstance.format() == format && 218 manifestInstance.version().minorAtLeast(expectVersion)) { 219 return func(manifestInstance); 220 } 221 return true; 222 }); 223 if (!cont) return false; 224 } 225 return true; 226 } 227 228 // indent = 2, {"foo"} => "foo" 229 // indent = 2, {"foo", "bar"} => "\n foo\n bar"; 230 template <typename Container> 231 void multilineIndent(std::ostream& os, size_t indent, const Container& lines) { 232 if (lines.size() == 1) { 233 os << *lines.begin(); 234 return; 235 } 236 for (const auto& line : lines) { 237 os << "\n"; 238 for (size_t i = 0; i < indent; ++i) os << " "; 239 os << line; 240 } 241 } 242 243 // For each hal in mat, there must be a hal in manifest that supports this. 244 std::vector<std::string> HalManifest::checkIncompatibleHals(const CompatibilityMatrix& mat) const { 245 std::vector<std::string> ret; 246 for (const MatrixHal &matrixHal : mat.getHals()) { 247 if (matrixHal.optional) { 248 continue; 249 } 250 251 std::set<FqInstance> manifestInstances; 252 std::set<std::string> manifestInstanceDesc; 253 std::set<Version> versions; 254 for (const ManifestHal* manifestHal : getHals(matrixHal.name)) { 255 manifestHal->forEachInstance([&](const auto& manifestInstance) { 256 manifestInstances.insert(manifestInstance.getFqInstance()); 257 manifestInstanceDesc.insert(manifestInstance.descriptionWithoutPackage()); 258 return true; 259 }); 260 manifestHal->appendAllVersions(&versions); 261 } 262 263 if (!matrixHal.isCompatible(manifestInstances, versions)) { 264 std::ostringstream oss; 265 oss << matrixHal.name << ":\n required: "; 266 multilineIndent(oss, 8, android::vintf::expandInstances(matrixHal)); 267 oss << "\n provided: "; 268 if (manifestInstances.empty()) { 269 multilineIndent(oss, 8, versions); 270 } else { 271 multilineIndent(oss, 8, manifestInstanceDesc); 272 } 273 274 ret.insert(ret.end(), oss.str()); 275 } 276 } 277 return ret; 278 } 279 280 std::set<std::string> HalManifest::checkUnusedHals( 281 const CompatibilityMatrix& mat, const std::vector<HidlInterfaceMetadata>& hidlMetadata) const { 282 std::multimap<std::string, std::string> childrenMap; 283 for (const auto& child : hidlMetadata) { 284 for (const auto& parent : child.inherited) { 285 childrenMap.emplace(parent, child.name); 286 } 287 } 288 289 std::set<std::string> ret; 290 291 forEachInstance([&ret, &mat, &childrenMap](const auto& manifestInstance) { 292 if (mat.matchInstance(manifestInstance.format(), manifestInstance.package(), 293 manifestInstance.version(), manifestInstance.interface(), 294 manifestInstance.instance())) { 295 // manifestInstance exactly matches an instance in |mat|. 296 return true; 297 } 298 // For HIDL instances, If foo@2.0 inherits from foo@1.0, manifest may contain both, but 299 // matrix may contain only 2.0 if 1.0 is considered deprecated. Hence, if manifestInstance 300 // is 1.0, check all its children in the matrix too. 301 // If there is at least one match, do not consider it unused. 302 if (manifestInstance.format() == HalFormat::HIDL) { 303 auto range = 304 childrenMap.equal_range(manifestInstance.getFqInstance().getFqName().string()); 305 for (auto it = range.first; it != range.second; ++it) { 306 FQName fqName; 307 CHECK(fqName.setTo(it->second)); 308 if (mat.matchInstance(manifestInstance.format(), fqName.package(), 309 fqName.getVersion(), fqName.name(), 310 manifestInstance.instance())) { 311 return true; 312 } 313 } 314 } 315 316 // If no match is found, consider it unused. 317 ret.insert(manifestInstance.description()); 318 return true; 319 }); 320 321 return ret; 322 } 323 324 static bool checkVendorNdkCompatibility(const VendorNdk& matVendorNdk, 325 const std::vector<VendorNdk>& manifestVendorNdk, 326 std::string* error) { 327 // For pre-P vendor images, device compatibility matrix does not specify <vendor-ndk> 328 // tag. Ignore the check for these devices. 329 if (matVendorNdk.version().empty()) { 330 return true; 331 } 332 for (const auto& vndk : manifestVendorNdk) { 333 if (vndk.version() != matVendorNdk.version()) { 334 continue; 335 } 336 // version matches, check libraries 337 std::vector<std::string> diff; 338 std::set_difference(matVendorNdk.libraries().begin(), matVendorNdk.libraries().end(), 339 vndk.libraries().begin(), vndk.libraries().end(), 340 std::inserter(diff, diff.begin())); 341 if (!diff.empty()) { 342 if (error != nullptr) { 343 *error = "Vndk libs incompatible for version " + matVendorNdk.version() + 344 ". These libs are not in framework manifest:"; 345 for (const auto& name : diff) { 346 *error += " " + name; 347 } 348 } 349 return false; 350 } 351 return true; 352 } 353 354 // no match is found. 355 if (error != nullptr) { 356 *error = "Vndk version " + matVendorNdk.version() + " is not supported. " + 357 "Supported versions in framework manifest are: ["; 358 for (const auto& vndk : manifestVendorNdk) { 359 *error += " " + vndk.version(); 360 } 361 *error += "]"; 362 } 363 return false; 364 } 365 366 static bool checkSystemSdkCompatibility(const SystemSdk& matSystemSdk, 367 const SystemSdk& manifestSystemSdk, std::string* error) { 368 SystemSdk notSupported = matSystemSdk.removeVersions(manifestSystemSdk); 369 if (!notSupported.empty()) { 370 if (error) { 371 *error = 372 "The following System SDK versions are required by device " 373 "compatibility matrix but not supported by the framework manifest: [" + 374 base::Join(notSupported.versions(), ", ") + "]. Supported versions are: [" + 375 base::Join(manifestSystemSdk.versions(), ", ") + "]."; 376 } 377 return false; 378 } 379 return true; 380 } 381 382 bool HalManifest::checkCompatibility(const CompatibilityMatrix& mat, std::string* error, 383 CheckFlags::Type flags) const { 384 if (mType == mat.mType) { 385 if (error != nullptr) { 386 *error = "Wrong type; checking " + to_string(mType) + " manifest against " 387 + to_string(mat.mType) + " compatibility matrix"; 388 } 389 return false; 390 } 391 auto incompatibleHals = checkIncompatibleHals(mat); 392 if (!incompatibleHals.empty()) { 393 if (error != nullptr) { 394 *error = "HALs incompatible."; 395 if (mat.level() != Level::UNSPECIFIED) 396 *error += " Matrix level = " + to_string(mat.level()) + "."; 397 if (level() != Level::UNSPECIFIED) 398 *error += " Manifest level = " + to_string(level()) + "."; 399 *error += " The following requirements are not met:\n"; 400 for (const auto& e : incompatibleHals) { 401 *error += e + "\n"; 402 } 403 } 404 return false; 405 } 406 if (mType == SchemaType::FRAMEWORK) { 407 if (!checkVendorNdkCompatibility(mat.device.mVendorNdk, framework.mVendorNdks, error)) { 408 return false; 409 } 410 411 if (!checkSystemSdkCompatibility(mat.device.mSystemSdk, framework.mSystemSdk, error)) { 412 return false; 413 } 414 } else if (mType == SchemaType::DEVICE) { 415 bool sepolicyMatch = false; 416 for (const auto &range : mat.framework.mSepolicy.sepolicyVersions()) { 417 if (range.supportedBy(device.mSepolicyVersion)) { 418 sepolicyMatch = true; 419 break; 420 } 421 } 422 if (!sepolicyMatch) { 423 if (error != nullptr) { 424 *error = "Sepolicy version " + to_string(device.mSepolicyVersion) 425 + " doesn't satisify the requirements."; 426 } 427 return false; 428 } 429 430 // Not using inferredKernelLevel() to preserve the legacy behavior if <kernel> does not have 431 // level attribute. 432 // Note that shouldCheckKernelCompatibility() only returns true on host, because the 433 // on-device HalManifest does not have kernel version set. On the device, kernel information 434 // is retrieved from RuntimeInfo. 435 Level kernelTagLevel = kernel()->level(); 436 if (flags.isKernelEnabled() && shouldCheckKernelCompatibility() && 437 kernel() 438 ->getMatchedKernelRequirements(mat.framework.mKernels, kernelTagLevel, error) 439 .empty()) { 440 return false; 441 } 442 } 443 444 return true; 445 } 446 447 bool HalManifest::shouldCheckKernelCompatibility() const { 448 return kernel().has_value() && kernel()->version() != KernelVersion{}; 449 } 450 451 CompatibilityMatrix HalManifest::generateCompatibleMatrix(bool optional) const { 452 CompatibilityMatrix matrix; 453 454 std::set<std::tuple<HalFormat, std::string, Version, std::string, std::string>> instances; 455 456 forEachInstance([&matrix, &instances, optional](const ManifestInstance& e) { 457 auto&& [it, added] = 458 instances.emplace(e.format(), e.package(), e.version(), e.interface(), e.instance()); 459 if (!added) { 460 return true; 461 } 462 463 matrix.add(MatrixHal{ 464 .format = e.format(), 465 .name = e.package(), 466 .versionRanges = {VersionRange{e.version().majorVer, e.version().minorVer}}, 467 .optional = optional, 468 .interfaces = {{e.interface(), HalInterface{e.interface(), {e.instance()}}}}}); 469 return true; 470 }); 471 if (mType == SchemaType::FRAMEWORK) { 472 matrix.mType = SchemaType::DEVICE; 473 // VNDK does not need to be added for compatibility 474 } else if (mType == SchemaType::DEVICE) { 475 matrix.mType = SchemaType::FRAMEWORK; 476 matrix.framework.mSepolicy = Sepolicy(0u /* kernelSepolicyVersion */, 477 {{device.mSepolicyVersion.majorVer, device.mSepolicyVersion.minorVer}}); 478 } 479 480 return matrix; 481 } 482 483 status_t HalManifest::fetchAllInformation(const FileSystem* fileSystem, const std::string& path, 484 std::string* error) { 485 return details::fetchAllInformation(fileSystem, path, this, error); 486 } 487 488 SchemaType HalManifest::type() const { 489 return mType; 490 } 491 492 void HalManifest::setType(SchemaType type) { 493 mType = type; 494 } 495 496 Level HalManifest::level() const { 497 return mLevel; 498 } 499 500 Version HalManifest::getMetaVersion() const { 501 return kMetaVersion; 502 } 503 504 const Version &HalManifest::sepolicyVersion() const { 505 CHECK(mType == SchemaType::DEVICE); 506 return device.mSepolicyVersion; 507 } 508 509 const std::vector<VendorNdk>& HalManifest::vendorNdks() const { 510 CHECK(mType == SchemaType::FRAMEWORK); 511 return framework.mVendorNdks; 512 } 513 514 std::string HalManifest::getXmlFilePath(const std::string& xmlFileName, 515 const Version& version) const { 516 using std::literals::string_literals::operator""s; 517 auto range = getXmlFiles(xmlFileName); 518 for (auto it = range.first; it != range.second; ++it) { 519 const ManifestXmlFile& manifestXmlFile = it->second; 520 if (manifestXmlFile.version() == version) { 521 if (!manifestXmlFile.overriddenPath().empty()) { 522 return manifestXmlFile.overriddenPath(); 523 } 524 return "/"s + (type() == SchemaType::DEVICE ? "vendor" : "system") + "/etc/" + 525 xmlFileName + "_V" + std::to_string(version.majorVer) + "_" + 526 std::to_string(version.minorVer) + ".xml"; 527 } 528 } 529 return ""; 530 } 531 532 bool operator==(const HalManifest &lft, const HalManifest &rgt) { 533 // ignore fileName(). 534 return lft.mType == rgt.mType && lft.mLevel == rgt.mLevel && lft.mHals == rgt.mHals && 535 lft.mXmlFiles == rgt.mXmlFiles && 536 (lft.mType != SchemaType::DEVICE || 537 (lft.device.mSepolicyVersion == rgt.device.mSepolicyVersion && 538 lft.device.mKernel == rgt.device.mKernel)) && 539 (lft.mType != SchemaType::FRAMEWORK || 540 ( 541 #pragma clang diagnostic push 542 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 543 lft.framework.mVndks == rgt.framework.mVndks && 544 #pragma clang diagnostic pop 545 lft.framework.mVendorNdks == rgt.framework.mVendorNdks && 546 lft.framework.mSystemSdk == rgt.framework.mSystemSdk)); 547 } 548 549 // Alternative to forEachInstance if you just need a set of instance names instead. 550 std::set<std::string> HalManifest::getInstances(HalFormat format, const std::string& package, 551 const Version& version, 552 const std::string& interfaceName) const { 553 std::set<std::string> ret; 554 (void)forEachInstanceOfInterface(format, package, version, interfaceName, 555 [&ret](const auto& e) { 556 ret.insert(e.instance()); 557 return true; 558 }); 559 return ret; 560 } 561 562 // Return whether instance is in getInstances(...). 563 bool HalManifest::hasInstance(HalFormat format, const std::string& package, const Version& version, 564 const std::string& interfaceName, const std::string& instance) const { 565 bool found = false; 566 (void)forEachInstanceOfInterface(format, package, version, interfaceName, 567 [&found, &instance](const auto& e) { 568 found |= (instance == e.instance()); 569 return !found; // if not found, continue 570 }); 571 return found; 572 } 573 std::set<std::string> HalManifest::getHidlInstances(const std::string& package, 574 const Version& version, 575 const std::string& interfaceName) const { 576 return getInstances(HalFormat::HIDL, package, version, interfaceName); 577 } 578 579 std::set<std::string> HalManifest::getAidlInstances(const std::string& package, 580 const std::string& interfaceName) const { 581 return getAidlInstances(package, 0, interfaceName); 582 } 583 584 std::set<std::string> HalManifest::getAidlInstances(const std::string& package, size_t version, 585 const std::string& interfaceName) const { 586 return getInstances(HalFormat::AIDL, package, {details::kFakeAidlMajorVersion, version}, 587 interfaceName); 588 } 589 590 bool HalManifest::hasHidlInstance(const std::string& package, const Version& version, 591 const std::string& interfaceName, 592 const std::string& instance) const { 593 return hasInstance(HalFormat::HIDL, package, version, interfaceName, instance); 594 } 595 596 bool HalManifest::hasAidlInstance(const std::string& package, const std::string& interface, 597 const std::string& instance) const { 598 return hasAidlInstance(package, 0, interface, instance); 599 } 600 601 bool HalManifest::hasAidlInstance(const std::string& package, size_t version, 602 const std::string& interface, const std::string& instance) const { 603 return hasInstance(HalFormat::AIDL, package, {details::kFakeAidlMajorVersion, version}, 604 interface, instance); 605 } 606 607 bool HalManifest::insertInstance(const FqInstance& fqInstance, Transport transport, Arch arch, 608 HalFormat format, std::string* error) { 609 for (ManifestHal& hal : getHals()) { 610 if (hal.name == fqInstance.getPackage() && hal.format == format && 611 hal.transport() == transport && hal.arch() == arch) { 612 return hal.insertInstance(fqInstance, error); 613 } 614 } 615 616 ManifestHal hal; 617 hal.name = fqInstance.getPackage(); 618 hal.format = format; 619 hal.transportArch = TransportArch(transport, arch); 620 if (!hal.insertInstance(fqInstance, error)) return false; 621 return add(std::move(hal)); 622 } 623 624 bool HalManifest::empty() const { 625 HalManifest emptyManifest; 626 emptyManifest.setType(type()); 627 return (*this) == emptyManifest; 628 } 629 630 const std::optional<KernelInfo>& HalManifest::kernel() const { 631 return device.mKernel; 632 } 633 634 bool HalManifest::mergeKernel(std::optional<KernelInfo>* other, std::string* error) { 635 if (!other->has_value()) { 636 return true; 637 } 638 639 if (device.mKernel.has_value()) { 640 if (!device.mKernel->merge(&**other, error)) { 641 return false; 642 } 643 } else { 644 device.mKernel = std::move(*other); 645 } 646 647 *other = std::nullopt; 648 return true; 649 } 650 651 bool HalManifest::addAll(HalManifest* other, std::string* error) { 652 if (type() != other->type()) { 653 if (error) { 654 *error = "Cannot add a " + to_string(other->type()) + " manifest to a " + 655 to_string(type()) + " manifest"; 656 } 657 return false; 658 } 659 660 if (!addAllHals(other, error)) { 661 return false; 662 } 663 664 if (!addAllXmlFiles(other, error)) { 665 return false; 666 } 667 668 if (!mergeField(&mLevel, &other->mLevel, Level::UNSPECIFIED)) { 669 if (error) { 670 *error = "Conflicting target-level: " + to_string(level()) + " vs. " + 671 to_string(other->level()); 672 } 673 return false; 674 } 675 676 if (type() == SchemaType::DEVICE) { 677 if (!mergeField(&device.mSepolicyVersion, &other->device.mSepolicyVersion)) { 678 if (error) { 679 *error = "Conflicting sepolicy version: " + to_string(sepolicyVersion()) + " vs. " + 680 to_string(other->sepolicyVersion()); 681 } 682 return false; 683 } 684 685 if (!mergeKernel(&other->device.mKernel, error)) { 686 return false; 687 } 688 } else if (type() == SchemaType::FRAMEWORK) { 689 #pragma clang diagnostic push 690 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 691 framework.mVndks.insert(framework.mVndks.end(), other->framework.mVndks.begin(), 692 other->framework.mVndks.end()); 693 other->framework.mVndks.clear(); 694 #pragma clang diagnostic pop 695 696 framework.mVendorNdks.insert(framework.mVendorNdks.end(), 697 other->framework.mVendorNdks.begin(), 698 other->framework.mVendorNdks.end()); 699 other->framework.mVendorNdks.clear(); 700 701 framework.mSystemSdk.addAll(&other->framework.mSystemSdk); 702 } else { 703 LOG(FATAL) << "unknown SchemaType: " 704 << static_cast<std::underlying_type_t<SchemaType>>(type()); 705 } 706 707 if (!other->empty()) { 708 if (error) { 709 *error = 710 "Cannot add another manifest because it contains extraneous entries that " 711 "are not recognized."; 712 } 713 return false; 714 } 715 716 return true; 717 } 718 719 Level HalManifest::inferredKernelLevel() const { 720 if (kernel().has_value()) { 721 if (kernel()->level() != Level::UNSPECIFIED) { 722 return kernel()->level(); 723 } 724 } 725 // As a special case, for devices launching with R and above, also infer from <manifest>.level. 726 // Devices launching before R may leave kernel level unspecified to use legacy kernel 727 // matching behavior; see KernelInfo::getMatchedKernelRequirements. 728 if (level() >= Level::R) { 729 return level(); 730 } 731 return Level::UNSPECIFIED; 732 } 733 734 } // namespace vintf 735 } // namespace android 736