1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "VintfObject.h" 18 19 #include <dirent.h> 20 21 #include <algorithm> 22 #include <functional> 23 #include <memory> 24 #include <mutex> 25 26 #include <aidl/metadata.h> 27 #include <android-base/logging.h> 28 #include <android-base/result.h> 29 #include <android-base/strings.h> 30 #include <hidl/metadata.h> 31 32 #include "CompatibilityMatrix.h" 33 #include "constants-private.h" 34 #include "parse_string.h" 35 #include "parse_xml.h" 36 #include "utils.h" 37 38 using std::placeholders::_1; 39 using std::placeholders::_2; 40 using std::string_literals::operator""s; 41 42 namespace android { 43 namespace vintf { 44 45 using namespace details; 46 47 #ifdef LIBVINTF_TARGET 48 static constexpr bool kIsTarget = true; 49 #else 50 static constexpr bool kIsTarget = false; 51 #endif 52 53 template <typename T, typename F> 54 static std::shared_ptr<const T> Get(const char* id, LockedSharedPtr<T>* ptr, 55 const F& fetchAllInformation) { 56 std::unique_lock<std::mutex> _lock(ptr->mutex); 57 if (!ptr->fetchedOnce) { 58 LOG(INFO) << id << ": Reading VINTF information."; 59 ptr->object = std::make_unique<T>(); 60 std::string error; 61 status_t status = fetchAllInformation(ptr->object.get(), &error); 62 if (status == OK) { 63 ptr->fetchedOnce = true; 64 LOG(INFO) << id << ": Successfully processed VINTF information"; 65 } else { 66 // Doubled because a malformed error std::string might cause us to 67 // lose the status. 68 LOG(ERROR) << id << ": status from fetching VINTF information: " << status; 69 LOG(ERROR) << id << ": " << status << " VINTF parse error: " << error; 70 ptr->object = nullptr; // frees the old object 71 } 72 } 73 return ptr->object; 74 } 75 76 static std::unique_ptr<FileSystem> createDefaultFileSystem() { 77 std::unique_ptr<FileSystem> fileSystem; 78 if (kIsTarget) { 79 fileSystem = std::make_unique<details::FileSystemImpl>(); 80 } else { 81 fileSystem = std::make_unique<details::FileSystemNoOp>(); 82 } 83 return fileSystem; 84 } 85 86 static std::unique_ptr<PropertyFetcher> createDefaultPropertyFetcher() { 87 std::unique_ptr<PropertyFetcher> propertyFetcher; 88 if (kIsTarget) { 89 propertyFetcher = std::make_unique<details::PropertyFetcherImpl>(); 90 } else { 91 propertyFetcher = std::make_unique<details::PropertyFetcherNoOp>(); 92 } 93 return propertyFetcher; 94 } 95 96 std::shared_ptr<VintfObject> VintfObject::GetInstance() { 97 static details::LockedSharedPtr<VintfObject> sInstance{}; 98 std::unique_lock<std::mutex> lock(sInstance.mutex); 99 if (sInstance.object == nullptr) { 100 sInstance.object = std::shared_ptr<VintfObject>(VintfObject::Builder().build().release()); 101 } 102 return sInstance.object; 103 } 104 105 std::shared_ptr<const HalManifest> VintfObject::GetDeviceHalManifest() { 106 return GetInstance()->getDeviceHalManifest(); 107 } 108 109 std::shared_ptr<const HalManifest> VintfObject::getDeviceHalManifest() { 110 return Get(__func__, &mDeviceManifest, 111 std::bind(&VintfObject::fetchDeviceHalManifest, this, _1, _2)); 112 } 113 114 std::shared_ptr<const HalManifest> VintfObject::GetFrameworkHalManifest() { 115 return GetInstance()->getFrameworkHalManifest(); 116 } 117 118 std::shared_ptr<const HalManifest> VintfObject::getFrameworkHalManifest() { 119 return Get(__func__, &mFrameworkManifest, 120 std::bind(&VintfObject::fetchFrameworkHalManifest, this, _1, _2)); 121 } 122 123 std::shared_ptr<const CompatibilityMatrix> VintfObject::GetDeviceCompatibilityMatrix() { 124 return GetInstance()->getDeviceCompatibilityMatrix(); 125 } 126 127 std::shared_ptr<const CompatibilityMatrix> VintfObject::getDeviceCompatibilityMatrix() { 128 return Get(__func__, &mDeviceMatrix, std::bind(&VintfObject::fetchDeviceMatrix, this, _1, _2)); 129 } 130 131 std::shared_ptr<const CompatibilityMatrix> VintfObject::GetFrameworkCompatibilityMatrix() { 132 return GetInstance()->getFrameworkCompatibilityMatrix(); 133 } 134 135 std::shared_ptr<const CompatibilityMatrix> VintfObject::getFrameworkCompatibilityMatrix() { 136 // To avoid deadlock, get device manifest before any locks. 137 auto deviceManifest = getDeviceHalManifest(); 138 139 std::unique_lock<std::mutex> _lock(mFrameworkCompatibilityMatrixMutex); 140 141 auto combined = 142 Get(__func__, &mCombinedFrameworkMatrix, 143 std::bind(&VintfObject::getCombinedFrameworkMatrix, this, deviceManifest, _1, _2)); 144 if (combined != nullptr) { 145 return combined; 146 } 147 148 return Get(__func__, &mFrameworkMatrix, 149 std::bind(&CompatibilityMatrix::fetchAllInformation, _1, getFileSystem().get(), 150 kSystemLegacyMatrix, _2)); 151 } 152 153 status_t VintfObject::getCombinedFrameworkMatrix( 154 const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out, 155 std::string* error) { 156 std::vector<CompatibilityMatrix> matrixFragments; 157 auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, error); 158 if (matrixFragmentsStatus != OK) { 159 return matrixFragmentsStatus; 160 } 161 if (matrixFragments.empty()) { 162 if (error && error->empty()) { 163 *error = "Cannot get framework matrix for each FCM version for unknown error."; 164 } 165 return NAME_NOT_FOUND; 166 } 167 168 Level deviceLevel = Level::UNSPECIFIED; 169 170 if (deviceManifest != nullptr) { 171 deviceLevel = deviceManifest->level(); 172 } 173 174 // TODO(b/70628538): Do not infer from Shipping API level. 175 if (deviceLevel == Level::UNSPECIFIED) { 176 auto shippingApi = getPropertyFetcher()->getUintProperty("ro.product.first_api_level", 0u); 177 if (shippingApi != 0u) { 178 deviceLevel = details::convertFromApiLevel(shippingApi); 179 } 180 } 181 182 if (deviceLevel == Level::UNSPECIFIED) { 183 // Cannot infer FCM version. Combine all matrices by assuming 184 // Shipping FCM Version == min(all supported FCM Versions in the framework) 185 for (auto&& fragment : matrixFragments) { 186 Level fragmentLevel = fragment.level(); 187 if (fragmentLevel != Level::UNSPECIFIED && deviceLevel > fragmentLevel) { 188 deviceLevel = fragmentLevel; 189 } 190 } 191 } 192 193 if (deviceLevel == Level::UNSPECIFIED) { 194 // None of the fragments specify any FCM version. Should never happen except 195 // for inconsistent builds. 196 if (error) { 197 *error = "No framework compatibility matrix files under "s + kSystemVintfDir + 198 " declare FCM version."; 199 } 200 return NAME_NOT_FOUND; 201 } 202 203 auto combined = CompatibilityMatrix::combine(deviceLevel, &matrixFragments, error); 204 if (combined == nullptr) { 205 return BAD_VALUE; 206 } 207 *out = std::move(*combined); 208 return OK; 209 } 210 211 // Load and combine all of the manifests in a directory 212 status_t VintfObject::addDirectoryManifests(const std::string& directory, HalManifest* manifest, 213 std::string* error) { 214 std::vector<std::string> fileNames; 215 status_t err = getFileSystem()->listFiles(directory, &fileNames, error); 216 // if the directory isn't there, that's okay 217 if (err == NAME_NOT_FOUND) return OK; 218 if (err != OK) return err; 219 220 for (const std::string& file : fileNames) { 221 // Only adds HALs because all other things are added by libvintf 222 // itself for now. 223 HalManifest fragmentManifest; 224 err = fetchOneHalManifest(directory + file, &fragmentManifest, error); 225 if (err != OK) return err; 226 227 if (!manifest->addAll(&fragmentManifest, error)) { 228 if (error) { 229 error->insert(0, "Cannot add manifest fragment " + directory + file + ": "); 230 } 231 return UNKNOWN_ERROR; 232 } 233 } 234 235 return OK; 236 } 237 238 // Priority for loading vendor manifest: 239 // 1. Vendor manifest + device fragments + ODM manifest (optional) + odm fragments 240 // 2. Vendor manifest + device fragments 241 // 3. ODM manifest (optional) + odm fragments 242 // 4. /vendor/manifest.xml (legacy, no fragments) 243 // where: 244 // A + B means unioning <hal> tags from A and B. If B declares an override, then this takes priority 245 // over A. 246 status_t VintfObject::fetchDeviceHalManifest(HalManifest* out, std::string* error) { 247 HalManifest vendorManifest; 248 status_t vendorStatus = fetchVendorHalManifest(&vendorManifest, error); 249 if (vendorStatus != OK && vendorStatus != NAME_NOT_FOUND) { 250 return vendorStatus; 251 } 252 253 if (vendorStatus == OK) { 254 *out = std::move(vendorManifest); 255 status_t fragmentStatus = addDirectoryManifests(kVendorManifestFragmentDir, out, error); 256 if (fragmentStatus != OK) { 257 return fragmentStatus; 258 } 259 } 260 261 HalManifest odmManifest; 262 status_t odmStatus = fetchOdmHalManifest(&odmManifest, error); 263 if (odmStatus != OK && odmStatus != NAME_NOT_FOUND) { 264 return odmStatus; 265 } 266 267 if (vendorStatus == OK) { 268 if (odmStatus == OK) { 269 if (!out->addAll(&odmManifest, error)) { 270 if (error) { 271 error->insert(0, "Cannot add ODM manifest :"); 272 } 273 return UNKNOWN_ERROR; 274 } 275 } 276 return addDirectoryManifests(kOdmManifestFragmentDir, out, error); 277 } 278 279 // vendorStatus != OK, "out" is not changed. 280 if (odmStatus == OK) { 281 *out = std::move(odmManifest); 282 return addDirectoryManifests(kOdmManifestFragmentDir, out, error); 283 } 284 285 // Use legacy /vendor/manifest.xml 286 return out->fetchAllInformation(getFileSystem().get(), kVendorLegacyManifest, error); 287 } 288 289 // Priority: 290 // 1. if {vendorSku} is defined, /vendor/etc/vintf/manifest_{vendorSku}.xml 291 // 2. /vendor/etc/vintf/manifest.xml 292 // where: 293 // {vendorSku} is the value of ro.boot.product.vendor.sku 294 status_t VintfObject::fetchVendorHalManifest(HalManifest* out, std::string* error) { 295 status_t status; 296 297 std::string vendorSku; 298 vendorSku = getPropertyFetcher()->getProperty("ro.boot.product.vendor.sku", ""); 299 300 if (!vendorSku.empty()) { 301 status = 302 fetchOneHalManifest(kVendorVintfDir + "manifest_"s + vendorSku + ".xml", out, error); 303 if (status == OK || status != NAME_NOT_FOUND) { 304 return status; 305 } 306 } 307 308 status = fetchOneHalManifest(kVendorManifest, out, error); 309 if (status == OK || status != NAME_NOT_FOUND) { 310 return status; 311 } 312 313 return NAME_NOT_FOUND; 314 } 315 316 // "out" is written to iff return status is OK. 317 // Priority: 318 // 1. if {sku} is defined, /odm/etc/vintf/manifest_{sku}.xml 319 // 2. /odm/etc/vintf/manifest.xml 320 // 3. if {sku} is defined, /odm/etc/manifest_{sku}.xml 321 // 4. /odm/etc/manifest.xml 322 // where: 323 // {sku} is the value of ro.boot.product.hardware.sku 324 status_t VintfObject::fetchOdmHalManifest(HalManifest* out, std::string* error) { 325 status_t status; 326 327 std::string productModel; 328 productModel = getPropertyFetcher()->getProperty("ro.boot.product.hardware.sku", ""); 329 330 if (!productModel.empty()) { 331 status = 332 fetchOneHalManifest(kOdmVintfDir + "manifest_"s + productModel + ".xml", out, error); 333 if (status == OK || status != NAME_NOT_FOUND) { 334 return status; 335 } 336 } 337 338 status = fetchOneHalManifest(kOdmManifest, out, error); 339 if (status == OK || status != NAME_NOT_FOUND) { 340 return status; 341 } 342 343 if (!productModel.empty()) { 344 status = fetchOneHalManifest(kOdmLegacyVintfDir + "manifest_"s + productModel + ".xml", out, 345 error); 346 if (status == OK || status != NAME_NOT_FOUND) { 347 return status; 348 } 349 } 350 351 status = fetchOneHalManifest(kOdmLegacyManifest, out, error); 352 if (status == OK || status != NAME_NOT_FOUND) { 353 return status; 354 } 355 356 return NAME_NOT_FOUND; 357 } 358 359 // Fetch one manifest.xml file. "out" is written to iff return status is OK. 360 // Returns NAME_NOT_FOUND if file is missing. 361 status_t VintfObject::fetchOneHalManifest(const std::string& path, HalManifest* out, 362 std::string* error) { 363 HalManifest ret; 364 status_t status = ret.fetchAllInformation(getFileSystem().get(), path, error); 365 if (status == OK) { 366 *out = std::move(ret); 367 } 368 return status; 369 } 370 371 status_t VintfObject::fetchDeviceMatrix(CompatibilityMatrix* out, std::string* error) { 372 CompatibilityMatrix etcMatrix; 373 if (etcMatrix.fetchAllInformation(getFileSystem().get(), kVendorMatrix, error) == OK) { 374 *out = std::move(etcMatrix); 375 return OK; 376 } 377 return out->fetchAllInformation(getFileSystem().get(), kVendorLegacyMatrix, error); 378 } 379 380 // Priority: 381 // 1. /system/etc/vintf/manifest.xml 382 // + /system/etc/vintf/manifest/*.xml if they exist 383 // + /product/etc/vintf/manifest.xml if it exists 384 // + /product/etc/vintf/manifest/*.xml if they exist 385 // 2. (deprecated) /system/manifest.xml 386 status_t VintfObject::fetchUnfilteredFrameworkHalManifest(HalManifest* out, std::string* error) { 387 auto systemEtcStatus = fetchOneHalManifest(kSystemManifest, out, error); 388 if (systemEtcStatus == OK) { 389 auto dirStatus = addDirectoryManifests(kSystemManifestFragmentDir, out, error); 390 if (dirStatus != OK) { 391 return dirStatus; 392 } 393 394 std::vector<std::pair<const char*, const char*>> extensions{ 395 {kProductManifest, kProductManifestFragmentDir}, 396 {kSystemExtManifest, kSystemExtManifestFragmentDir}, 397 }; 398 for (auto&& [manifestPath, frags] : extensions) { 399 HalManifest halManifest; 400 auto status = fetchOneHalManifest(manifestPath, &halManifest, error); 401 if (status != OK && status != NAME_NOT_FOUND) { 402 return status; 403 } 404 if (status == OK) { 405 if (!out->addAll(&halManifest, error)) { 406 if (error) { 407 error->insert(0, "Cannot add "s + manifestPath + ":"); 408 } 409 return UNKNOWN_ERROR; 410 } 411 } 412 413 auto fragmentStatus = addDirectoryManifests(frags, out, error); 414 if (fragmentStatus != OK) { 415 return fragmentStatus; 416 } 417 } 418 419 return OK; 420 } else { 421 LOG(WARNING) << "Cannot fetch " << kSystemManifest << ": " 422 << (error ? *error : strerror(-systemEtcStatus)); 423 } 424 425 return out->fetchAllInformation(getFileSystem().get(), kSystemLegacyManifest, error); 426 } 427 428 status_t VintfObject::fetchFrameworkHalManifest(HalManifest* out, std::string* error) { 429 status_t status = fetchUnfilteredFrameworkHalManifest(out, error); 430 if (status != OK) { 431 return status; 432 } 433 filterHalsByDeviceManifestLevel(out); 434 return OK; 435 } 436 437 void VintfObject::filterHalsByDeviceManifestLevel(HalManifest* out) { 438 auto deviceManifest = getDeviceHalManifest(); 439 if (deviceManifest == nullptr) { 440 LOG(WARNING) << "Cannot fetch device manifest to determine target FCM version to " 441 "filter framework manifest HALs."; 442 return; 443 } 444 Level deviceManifestLevel = deviceManifest->level(); 445 if (deviceManifestLevel == Level::UNSPECIFIED) { 446 LOG(WARNING) 447 << "Not filtering framework manifest HALs because target FCM version is unspecified."; 448 return; 449 } 450 out->removeHalsIf([deviceManifestLevel](const ManifestHal& hal) { 451 if (hal.getMaxLevel() == Level::UNSPECIFIED) { 452 return false; 453 } 454 return hal.getMaxLevel() < deviceManifestLevel; 455 }); 456 } 457 458 static void appendLine(std::string* error, const std::string& message) { 459 if (error != nullptr) { 460 if (!error->empty()) *error += "\n"; 461 *error += message; 462 } 463 } 464 465 status_t VintfObject::getOneMatrix(const std::string& path, CompatibilityMatrix* out, 466 std::string* error) { 467 std::string content; 468 status_t status = getFileSystem()->fetch(path, &content, error); 469 if (status != OK) { 470 return status; 471 } 472 if (!fromXml(out, content, error)) { 473 if (error) { 474 error->insert(0, "Cannot parse " + path + ": "); 475 } 476 return BAD_VALUE; 477 } 478 out->setFileName(path); 479 return OK; 480 } 481 482 status_t VintfObject::getAllFrameworkMatrixLevels(std::vector<CompatibilityMatrix>* results, 483 std::string* error) { 484 std::vector<std::string> dirs = { 485 kSystemVintfDir, 486 kSystemExtVintfDir, 487 kProductVintfDir, 488 }; 489 for (const auto& dir : dirs) { 490 std::vector<std::string> fileNames; 491 status_t listStatus = getFileSystem()->listFiles(dir, &fileNames, error); 492 if (listStatus == NAME_NOT_FOUND) { 493 continue; 494 } 495 if (listStatus != OK) { 496 return listStatus; 497 } 498 for (const std::string& fileName : fileNames) { 499 std::string path = dir + fileName; 500 CompatibilityMatrix namedMatrix; 501 std::string matrixError; 502 status_t matrixStatus = getOneMatrix(path, &namedMatrix, &matrixError); 503 if (matrixStatus != OK) { 504 // Manifests and matrices share the same dir. Client may not have enough 505 // permissions to read system manifests, or may not be able to parse it. 506 auto logLevel = matrixStatus == BAD_VALUE ? base::DEBUG : base::ERROR; 507 LOG(logLevel) << "Framework Matrix: Ignore file " << path << ": " << matrixError; 508 continue; 509 } 510 results->emplace_back(std::move(namedMatrix)); 511 } 512 513 if (dir == kSystemVintfDir && results->empty()) { 514 if (error) { 515 *error = "No framework matrices under " + dir + " can be fetched or parsed.\n"; 516 } 517 return NAME_NOT_FOUND; 518 } 519 } 520 521 if (results->empty()) { 522 if (error) { 523 *error = 524 "No framework matrices can be fetched or parsed. " 525 "The following directories are searched:\n " + 526 android::base::Join(dirs, "\n "); 527 } 528 return NAME_NOT_FOUND; 529 } 530 return OK; 531 } 532 533 std::shared_ptr<const RuntimeInfo> VintfObject::GetRuntimeInfo(RuntimeInfo::FetchFlags flags) { 534 return GetInstance()->getRuntimeInfo(flags); 535 } 536 std::shared_ptr<const RuntimeInfo> VintfObject::getRuntimeInfo(RuntimeInfo::FetchFlags flags) { 537 std::unique_lock<std::mutex> _lock(mDeviceRuntimeInfo.mutex); 538 539 // Skip fetching information that has already been fetched previously. 540 flags &= (~mDeviceRuntimeInfo.fetchedFlags); 541 542 if (mDeviceRuntimeInfo.object == nullptr) { 543 mDeviceRuntimeInfo.object = getRuntimeInfoFactory()->make_shared(); 544 } 545 546 status_t status = mDeviceRuntimeInfo.object->fetchAllInformation(flags); 547 if (status != OK) { 548 // If only kernel FCM is needed, ignore errors when fetching RuntimeInfo because RuntimeInfo 549 // is not available on host. On host, the kernel level can still be inferred from device 550 // manifest. 551 // If other information is needed, flag the error by returning nullptr. 552 auto allExceptKernelFcm = RuntimeInfo::FetchFlag::ALL & ~RuntimeInfo::FetchFlag::KERNEL_FCM; 553 bool needDeviceRuntimeInfo = flags & allExceptKernelFcm; 554 if (needDeviceRuntimeInfo) { 555 mDeviceRuntimeInfo.fetchedFlags &= (~flags); // mark the fields as "not fetched" 556 return nullptr; 557 } 558 } 559 560 // To support devices without GKI, RuntimeInfo::fetchAllInformation does not report errors 561 // if kernel level cannot be retrieved. If so, fetch kernel FCM version from device HAL 562 // manifest and store it in RuntimeInfo too. 563 if (flags & RuntimeInfo::FetchFlag::KERNEL_FCM) { 564 Level deviceManifestKernelLevel = Level::UNSPECIFIED; 565 auto manifest = getDeviceHalManifest(); 566 if (manifest) { 567 deviceManifestKernelLevel = manifest->inferredKernelLevel(); 568 } 569 if (deviceManifestKernelLevel != Level::UNSPECIFIED) { 570 Level kernelLevel = mDeviceRuntimeInfo.object->kernelLevel(); 571 if (kernelLevel == Level::UNSPECIFIED) { 572 mDeviceRuntimeInfo.object->setKernelLevel(deviceManifestKernelLevel); 573 } else if (kernelLevel != deviceManifestKernelLevel) { 574 LOG(WARNING) << "uname() reports kernel level " << kernelLevel 575 << " but device manifest sets kernel level " 576 << deviceManifestKernelLevel << ". Using kernel level " << kernelLevel; 577 } 578 } 579 } 580 581 mDeviceRuntimeInfo.fetchedFlags |= flags; 582 return mDeviceRuntimeInfo.object; 583 } 584 585 int32_t VintfObject::checkCompatibility(std::string* error, CheckFlags::Type flags) { 586 status_t status = OK; 587 // null checks for files and runtime info 588 if (getFrameworkHalManifest() == nullptr) { 589 appendLine(error, "No framework manifest file from device or from update package"); 590 status = NO_INIT; 591 } 592 if (getDeviceHalManifest() == nullptr) { 593 appendLine(error, "No device manifest file from device or from update package"); 594 status = NO_INIT; 595 } 596 if (getFrameworkCompatibilityMatrix() == nullptr) { 597 appendLine(error, "No framework matrix file from device or from update package"); 598 status = NO_INIT; 599 } 600 if (getDeviceCompatibilityMatrix() == nullptr) { 601 appendLine(error, "No device matrix file from device or from update package"); 602 status = NO_INIT; 603 } 604 605 if (flags.isRuntimeInfoEnabled()) { 606 if (getRuntimeInfo() == nullptr) { 607 appendLine(error, "No runtime info from device"); 608 status = NO_INIT; 609 } 610 } 611 if (status != OK) return status; 612 613 // compatiblity check. 614 if (!getDeviceHalManifest()->checkCompatibility(*getFrameworkCompatibilityMatrix(), error)) { 615 if (error) { 616 error->insert(0, 617 "Device manifest and framework compatibility matrix are incompatible: "); 618 } 619 return INCOMPATIBLE; 620 } 621 if (!getFrameworkHalManifest()->checkCompatibility(*getDeviceCompatibilityMatrix(), error)) { 622 if (error) { 623 error->insert(0, 624 "Framework manifest and device compatibility matrix are incompatible: "); 625 } 626 return INCOMPATIBLE; 627 } 628 629 if (flags.isRuntimeInfoEnabled()) { 630 if (!getRuntimeInfo()->checkCompatibility(*getFrameworkCompatibilityMatrix(), error, 631 flags)) { 632 if (error) { 633 error->insert(0, 634 "Runtime info and framework compatibility matrix are incompatible: "); 635 } 636 return INCOMPATIBLE; 637 } 638 } 639 640 return COMPATIBLE; 641 } 642 643 namespace details { 644 645 std::vector<std::string> dumpFileList() { 646 return { 647 // clang-format off 648 kSystemVintfDir, 649 kVendorVintfDir, 650 kOdmVintfDir, 651 kProductVintfDir, 652 kSystemExtVintfDir, 653 kOdmLegacyVintfDir, 654 kVendorLegacyManifest, 655 kVendorLegacyMatrix, 656 kSystemLegacyManifest, 657 kSystemLegacyMatrix, 658 // clang-format on 659 }; 660 } 661 662 } // namespace details 663 664 bool VintfObject::IsHalDeprecated(const MatrixHal& oldMatrixHal, 665 const CompatibilityMatrix& targetMatrix, 666 const ListInstances& listInstances, 667 const ChildrenMap& childrenMap, std::string* appendedError) { 668 bool isDeprecated = false; 669 oldMatrixHal.forEachInstance([&](const MatrixInstance& oldMatrixInstance) { 670 if (IsInstanceDeprecated(oldMatrixInstance, targetMatrix, listInstances, childrenMap, 671 appendedError)) { 672 isDeprecated = true; 673 } 674 return true; // continue to check next instance 675 }); 676 return isDeprecated; 677 } 678 679 // Let oldMatrixInstance = package@x.y-w::interface/instancePattern. 680 // If any "@servedVersion::interface/servedInstance" in listInstances(package@x.y::interface) 681 // matches instancePattern, return true iff for all child interfaces (from 682 // GetListedInstanceInheritance), IsFqInstanceDeprecated returns false. 683 bool VintfObject::IsInstanceDeprecated(const MatrixInstance& oldMatrixInstance, 684 const CompatibilityMatrix& targetMatrix, 685 const ListInstances& listInstances, 686 const ChildrenMap& childrenMap, std::string* appendedError) { 687 const std::string& package = oldMatrixInstance.package(); 688 const Version& version = oldMatrixInstance.versionRange().minVer(); 689 const std::string& interface = oldMatrixInstance.interface(); 690 691 std::vector<std::string> instanceHint; 692 if (!oldMatrixInstance.isRegex()) { 693 instanceHint.push_back(oldMatrixInstance.exactInstance()); 694 } 695 696 std::vector<std::string> accumulatedErrors; 697 auto list = listInstances(package, version, interface, instanceHint); 698 699 for (const auto& pair : list) { 700 const std::string& servedInstance = pair.first; 701 Version servedVersion = pair.second; 702 std::string servedFqInstanceString = 703 toFQNameString(package, servedVersion, interface, servedInstance); 704 if (!oldMatrixInstance.matchInstance(servedInstance)) { 705 // ignore unrelated instance 706 continue; 707 } 708 709 auto inheritance = GetListedInstanceInheritance(package, servedVersion, interface, 710 servedInstance, listInstances, childrenMap); 711 if (!inheritance.has_value()) { 712 accumulatedErrors.push_back(inheritance.error().message()); 713 continue; 714 } 715 716 std::vector<std::string> errors; 717 for (const auto& fqInstance : *inheritance) { 718 auto result = IsFqInstanceDeprecated(targetMatrix, oldMatrixInstance.format(), 719 fqInstance, listInstances); 720 if (result.ok()) { 721 errors.clear(); 722 break; 723 } 724 errors.push_back(result.error().message()); 725 } 726 727 if (errors.empty()) { 728 continue; 729 } 730 accumulatedErrors.insert(accumulatedErrors.end(), errors.begin(), errors.end()); 731 } 732 733 if (accumulatedErrors.empty()) { 734 return false; 735 } 736 appendLine(appendedError, android::base::Join(accumulatedErrors, "\n")); 737 return true; 738 } 739 740 // Check if fqInstance is listed in |listInstances|. 741 bool VintfObject::IsInstanceListed(const ListInstances& listInstances, 742 const FqInstance& fqInstance) { 743 auto list = 744 listInstances(fqInstance.getPackage(), fqInstance.getVersion(), fqInstance.getInterface(), 745 {fqInstance.getInstance()} /* instanceHint*/); 746 return std::any_of(list.begin(), list.end(), 747 [&](const auto& pair) { return pair.first == fqInstance.getInstance(); }); 748 } 749 750 // Return a list of FqInstance, where each element: 751 // - is listed in |listInstances|; AND 752 // - is, or inherits from, package@version::interface/instance (as specified by |childrenMap|) 753 android::base::Result<std::vector<FqInstance>> VintfObject::GetListedInstanceInheritance( 754 const std::string& package, const Version& version, const std::string& interface, 755 const std::string& instance, const ListInstances& listInstances, 756 const ChildrenMap& childrenMap) { 757 FqInstance fqInstance; 758 if (!fqInstance.setTo(package, version.majorVer, version.minorVer, interface, instance)) { 759 return android::base::Error() << toFQNameString(package, version, interface, instance) 760 << " is not a valid FqInstance"; 761 } 762 763 if (!IsInstanceListed(listInstances, fqInstance)) { 764 return {}; 765 } 766 767 const FQName& fqName = fqInstance.getFqName(); 768 769 std::vector<FqInstance> ret; 770 ret.push_back(fqInstance); 771 772 auto childRange = childrenMap.equal_range(fqName.string()); 773 for (auto it = childRange.first; it != childRange.second; ++it) { 774 const auto& childFqNameString = it->second; 775 FQName childFqName; 776 if (!childFqName.setTo(childFqNameString)) { 777 return android::base::Error() << "Cannot parse " << childFqNameString << " as FQName"; 778 } 779 FqInstance childFqInstance; 780 if (!childFqInstance.setTo(childFqName, fqInstance.getInstance())) { 781 return android::base::Error() << "Cannot merge " << childFqName.string() << "/" 782 << fqInstance.getInstance() << " as FqInstance"; 783 continue; 784 } 785 if (!IsInstanceListed(listInstances, childFqInstance)) { 786 continue; 787 } 788 ret.push_back(childFqInstance); 789 } 790 return ret; 791 } 792 793 // Check if |fqInstance| is in |targetMatrix|; essentially equal to 794 // targetMatrix.matchInstance(fqInstance), but provides richer error message. In details: 795 // 1. package@x.?::interface/servedInstance is not in targetMatrix; OR 796 // 2. package@x.z::interface/servedInstance is in targetMatrix but 797 // servedInstance is not in listInstances(package@x.z::interface) 798 android::base::Result<void> VintfObject::IsFqInstanceDeprecated( 799 const CompatibilityMatrix& targetMatrix, HalFormat format, const FqInstance& fqInstance, 800 const ListInstances& listInstances) { 801 // Find minimum package@x.? in target matrix, and check if instance is in target matrix. 802 bool foundInstance = false; 803 Version targetMatrixMinVer{SIZE_MAX, SIZE_MAX}; 804 targetMatrix.forEachInstanceOfPackage( 805 format, fqInstance.getPackage(), [&](const auto& targetMatrixInstance) { 806 if (targetMatrixInstance.versionRange().majorVer == fqInstance.getMajorVersion() && 807 targetMatrixInstance.interface() == fqInstance.getInterface() && 808 targetMatrixInstance.matchInstance(fqInstance.getInstance())) { 809 targetMatrixMinVer = 810 std::min(targetMatrixMinVer, targetMatrixInstance.versionRange().minVer()); 811 foundInstance = true; 812 } 813 return true; 814 }); 815 if (!foundInstance) { 816 return android::base::Error() 817 << fqInstance.string() << " is deprecated in compatibility matrix at FCM Version " 818 << targetMatrix.level() << "; it should not be served."; 819 } 820 821 // Assuming that targetMatrix requires @x.u-v, require that at least @x.u is served. 822 bool targetVersionServed = false; 823 for (const auto& newPair : 824 listInstances(fqInstance.getPackage(), targetMatrixMinVer, fqInstance.getInterface(), 825 {fqInstance.getInstance()} /* instanceHint */)) { 826 if (newPair.first == fqInstance.getInstance()) { 827 targetVersionServed = true; 828 break; 829 } 830 } 831 832 if (!targetVersionServed) { 833 return android::base::Error() 834 << fqInstance.string() << " is deprecated; requires at least " << targetMatrixMinVer; 835 } 836 return {}; 837 } 838 839 int32_t VintfObject::checkDeprecation(const ListInstances& listInstances, 840 const std::vector<HidlInterfaceMetadata>& hidlMetadata, 841 std::string* error) { 842 std::vector<CompatibilityMatrix> matrixFragments; 843 auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, error); 844 if (matrixFragmentsStatus != OK) { 845 return matrixFragmentsStatus; 846 } 847 if (matrixFragments.empty()) { 848 if (error && error->empty()) { 849 *error = "Cannot get framework matrix for each FCM version for unknown error."; 850 } 851 return NAME_NOT_FOUND; 852 } 853 auto deviceManifest = getDeviceHalManifest(); 854 if (deviceManifest == nullptr) { 855 if (error) *error = "No device manifest."; 856 return NAME_NOT_FOUND; 857 } 858 Level deviceLevel = deviceManifest->level(); 859 if (deviceLevel == Level::UNSPECIFIED) { 860 if (error) *error = "Device manifest does not specify Shipping FCM Version."; 861 return BAD_VALUE; 862 } 863 864 std::vector<CompatibilityMatrix> targetMatrices; 865 // Partition matrixFragments into two groups, where the second group 866 // contains all matrices whose level == deviceLevel. 867 auto targetMatricesPartition = std::partition( 868 matrixFragments.begin(), matrixFragments.end(), 869 [&](const CompatibilityMatrix& matrix) { return matrix.level() != deviceLevel; }); 870 // Move these matrices into the targetMatrices vector... 871 std::move(targetMatricesPartition, matrixFragments.end(), std::back_inserter(targetMatrices)); 872 if (targetMatrices.empty()) { 873 if (error) 874 *error = "Cannot find framework matrix at FCM version " + to_string(deviceLevel) + "."; 875 return NAME_NOT_FOUND; 876 } 877 // so that they can be combined into one matrix for deprecation checking. 878 auto targetMatrix = CompatibilityMatrix::combine(deviceLevel, &targetMatrices, error); 879 if (targetMatrix == nullptr) { 880 return BAD_VALUE; 881 } 882 883 std::multimap<std::string, std::string> childrenMap; 884 for (const auto& child : hidlMetadata) { 885 for (const auto& parent : child.inherited) { 886 childrenMap.emplace(parent, child.name); 887 } 888 } 889 890 // Find a list of possibly deprecated HALs by comparing |listInstances| with older matrices. 891 // Matrices with unspecified level are considered "current". 892 bool isDeprecated = false; 893 for (auto it = matrixFragments.begin(); it < targetMatricesPartition; ++it) { 894 const auto& namedMatrix = *it; 895 if (namedMatrix.level() == Level::UNSPECIFIED) continue; 896 if (namedMatrix.level() > deviceLevel) continue; 897 for (const MatrixHal& hal : namedMatrix.getHals()) { 898 if (IsHalDeprecated(hal, *targetMatrix, listInstances, childrenMap, error)) { 899 isDeprecated = true; 900 } 901 } 902 } 903 904 return isDeprecated ? DEPRECATED : NO_DEPRECATED_HALS; 905 } 906 907 int32_t VintfObject::checkDeprecation(const std::vector<HidlInterfaceMetadata>& hidlMetadata, 908 std::string* error) { 909 using namespace std::placeholders; 910 auto deviceManifest = getDeviceHalManifest(); 911 ListInstances inManifest = 912 [&deviceManifest](const std::string& package, Version version, const std::string& interface, 913 const std::vector<std::string>& /* hintInstances */) { 914 std::vector<std::pair<std::string, Version>> ret; 915 deviceManifest->forEachInstanceOfInterface( 916 HalFormat::HIDL, package, version, interface, 917 [&ret](const ManifestInstance& manifestInstance) { 918 ret.push_back( 919 std::make_pair(manifestInstance.instance(), manifestInstance.version())); 920 return true; 921 }); 922 return ret; 923 }; 924 return checkDeprecation(inManifest, hidlMetadata, error); 925 } 926 927 Level VintfObject::getKernelLevel(std::string* error) { 928 auto runtimeInfo = getRuntimeInfo(RuntimeInfo::FetchFlag::KERNEL_FCM); 929 if (!runtimeInfo) { 930 if (error) *error = "Cannot retrieve runtime info with kernel level."; 931 return Level::UNSPECIFIED; 932 } 933 if (runtimeInfo->kernelLevel() != Level::UNSPECIFIED) { 934 return runtimeInfo->kernelLevel(); 935 } 936 if (error) { 937 *error = "Both device manifest and kernel release do not specify kernel FCM version."; 938 } 939 return Level::UNSPECIFIED; 940 } 941 942 const std::unique_ptr<FileSystem>& VintfObject::getFileSystem() { 943 return mFileSystem; 944 } 945 946 const std::unique_ptr<PropertyFetcher>& VintfObject::getPropertyFetcher() { 947 return mPropertyFetcher; 948 } 949 950 const std::unique_ptr<ObjectFactory<RuntimeInfo>>& VintfObject::getRuntimeInfoFactory() { 951 return mRuntimeInfoFactory; 952 } 953 954 android::base::Result<bool> VintfObject::hasFrameworkCompatibilityMatrixExtensions() { 955 std::vector<CompatibilityMatrix> matrixFragments; 956 std::string error; 957 status_t status = getAllFrameworkMatrixLevels(&matrixFragments, &error); 958 if (status != OK) { 959 return android::base::Error(-status) 960 << "Cannot get all framework matrix fragments: " << error; 961 } 962 for (const auto& namedMatrix : matrixFragments) { 963 // Returns true if product matrix exists. 964 if (android::base::StartsWith(namedMatrix.fileName(), kProductVintfDir)) { 965 return true; 966 } 967 // Returns true if system_ext matrix exists. 968 if (android::base::StartsWith(namedMatrix.fileName(), kSystemExtVintfDir)) { 969 return true; 970 } 971 // Returns true if device system matrix exists. 972 if (android::base::StartsWith(namedMatrix.fileName(), kSystemVintfDir) && 973 namedMatrix.level() == Level::UNSPECIFIED && !namedMatrix.getHals().empty()) { 974 return true; 975 } 976 } 977 return false; 978 } 979 980 android::base::Result<void> VintfObject::checkUnusedHals( 981 const std::vector<HidlInterfaceMetadata>& hidlMetadata) { 982 auto matrix = getFrameworkCompatibilityMatrix(); 983 if (matrix == nullptr) { 984 return android::base::Error(-NAME_NOT_FOUND) << "Missing framework matrix."; 985 } 986 auto manifest = getDeviceHalManifest(); 987 if (manifest == nullptr) { 988 return android::base::Error(-NAME_NOT_FOUND) << "Missing device manifest."; 989 } 990 auto unused = manifest->checkUnusedHals(*matrix, hidlMetadata); 991 if (!unused.empty()) { 992 return android::base::Error() 993 << "The following instances are in the device manifest but " 994 << "not specified in framework compatibility matrix: \n" 995 << " " << android::base::Join(unused, "\n ") << "\n" 996 << "Suggested fix:\n" 997 << "1. Update deprecated HALs to the latest version.\n" 998 << "2. Check for any typos in device manifest or framework compatibility " 999 << "matrices with FCM version >= " << matrix->level() << ".\n" 1000 << "3. For new platform HALs, add them to any framework compatibility matrix " 1001 << "with FCM version >= " << matrix->level() << " where applicable.\n" 1002 << "4. For device-specific HALs, add to DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE " 1003 << "or DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE."; 1004 } 1005 return {}; 1006 } 1007 1008 namespace { 1009 1010 // Insert |name| into |ret| if shouldCheck(name). 1011 void InsertIf(const std::string& name, const std::function<bool(const std::string&)>& shouldCheck, 1012 std::set<std::string>* ret) { 1013 if (shouldCheck(name)) ret->insert(name); 1014 } 1015 1016 std::string StripHidlInterface(const std::string& fqNameString) { 1017 FQName fqName; 1018 if (!fqName.setTo(fqNameString)) { 1019 return ""; 1020 } 1021 return fqName.getPackageAndVersion().string(); 1022 } 1023 1024 std::string StripAidlType(const std::string& type) { 1025 auto items = android::base::Split(type, "."); 1026 if (items.empty()) { 1027 return ""; 1028 } 1029 items.erase(items.end() - 1); 1030 return android::base::Join(items, "."); 1031 } 1032 1033 // android.hardware.foo@1.0 1034 std::set<std::string> HidlMetadataToPackagesAndVersions( 1035 const std::vector<HidlInterfaceMetadata>& hidlMetadata, 1036 const std::function<bool(const std::string&)>& shouldCheck) { 1037 std::set<std::string> ret; 1038 for (const auto& item : hidlMetadata) { 1039 InsertIf(StripHidlInterface(item.name), shouldCheck, &ret); 1040 } 1041 return ret; 1042 } 1043 1044 // android.hardware.foo 1045 std::set<std::string> AidlMetadataToPackages( 1046 const std::vector<AidlInterfaceMetadata>& aidlMetadata, 1047 const std::function<bool(const std::string&)>& shouldCheck) { 1048 std::set<std::string> ret; 1049 for (const auto& item : aidlMetadata) { 1050 for (const auto& type : item.types) { 1051 InsertIf(StripAidlType(type), shouldCheck, &ret); 1052 } 1053 } 1054 return ret; 1055 } 1056 1057 // android.hardware.foo@1.0::IFoo. 1058 // Note that UDTs are not filtered out, so there might be non-interface types. 1059 std::set<std::string> HidlMetadataToNames(const std::vector<HidlInterfaceMetadata>& hidlMetadata) { 1060 std::set<std::string> ret; 1061 for (const auto& item : hidlMetadata) { 1062 ret.insert(item.name); 1063 } 1064 return ret; 1065 } 1066 1067 // android.hardware.foo.IFoo 1068 // Note that UDTs are not filtered out, so there might be non-interface types. 1069 std::set<std::string> AidlMetadataToNames(const std::vector<AidlInterfaceMetadata>& aidlMetadata) { 1070 std::set<std::string> ret; 1071 for (const auto& item : aidlMetadata) { 1072 for (const auto& type : item.types) { 1073 ret.insert(type); 1074 } 1075 } 1076 return ret; 1077 } 1078 1079 } // anonymous namespace 1080 1081 android::base::Result<std::vector<CompatibilityMatrix>> VintfObject::getAllFrameworkMatrixLevels() { 1082 // Get all framework matrix fragments instead of the combined framework compatibility matrix 1083 // because the latter may omit interfaces from the latest FCM if device target-level is not 1084 // the latest. 1085 std::vector<CompatibilityMatrix> matrixFragments; 1086 std::string error; 1087 auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, &error); 1088 if (matrixFragmentsStatus != OK) { 1089 return android::base::Error(-matrixFragmentsStatus) 1090 << "Unable to get all framework matrix fragments: " << error; 1091 } 1092 if (matrixFragments.empty()) { 1093 if (error.empty()) { 1094 error = "Cannot get framework matrix for each FCM version for unknown error."; 1095 } 1096 return android::base::Error(-NAME_NOT_FOUND) << error; 1097 } 1098 return matrixFragments; 1099 } 1100 1101 android::base::Result<void> VintfObject::checkMissingHalsInMatrices( 1102 const std::vector<HidlInterfaceMetadata>& hidlMetadata, 1103 const std::vector<AidlInterfaceMetadata>& aidlMetadata, 1104 std::function<bool(const std::string&)> shouldCheck) { 1105 if (!shouldCheck) { 1106 shouldCheck = [](const auto&) { return true; }; 1107 } 1108 1109 auto matrixFragments = getAllFrameworkMatrixLevels(); 1110 if (!matrixFragments.ok()) return matrixFragments.error(); 1111 1112 // Filter aidlMetadata and hidlMetadata with shouldCheck. 1113 auto allAidlPackages = AidlMetadataToPackages(aidlMetadata, shouldCheck); 1114 auto allHidlPackagesAndVersions = HidlMetadataToPackagesAndVersions(hidlMetadata, shouldCheck); 1115 1116 // Filter out instances in allAidlMetadata and allHidlMetadata that are in the matrices. 1117 std::vector<std::string> errors; 1118 for (const auto& matrix : matrixFragments.value()) { 1119 matrix.forEachInstance([&](const MatrixInstance& matrixInstance) { 1120 switch (matrixInstance.format()) { 1121 case HalFormat::AIDL: { 1122 allAidlPackages.erase(matrixInstance.package()); 1123 return true; // continue to next instance 1124 } 1125 case HalFormat::HIDL: { 1126 for (Version v = matrixInstance.versionRange().minVer(); 1127 v <= matrixInstance.versionRange().maxVer(); ++v.minorVer) { 1128 allHidlPackagesAndVersions.erase( 1129 toFQNameString(matrixInstance.package(), v)); 1130 } 1131 return true; // continue to next instance 1132 } 1133 default: { 1134 if (shouldCheck(matrixInstance.package())) { 1135 errors.push_back("HAL package " + matrixInstance.package() + 1136 " is not allowed to have format " + 1137 to_string(matrixInstance.format()) + "."); 1138 } 1139 return true; // continue to next instance 1140 } 1141 } 1142 }); 1143 } 1144 1145 if (!allHidlPackagesAndVersions.empty()) { 1146 errors.push_back( 1147 "The following HIDL packages are not found in any compatibility matrix fragments:\t\n" + 1148 android::base::Join(allHidlPackagesAndVersions, "\t\n")); 1149 } 1150 if (!allAidlPackages.empty()) { 1151 errors.push_back( 1152 "The following AIDL packages are not found in any compatibility matrix fragments:\t\n" + 1153 android::base::Join(allAidlPackages, "\t\n")); 1154 } 1155 1156 if (!errors.empty()) { 1157 return android::base::Error() << android::base::Join(errors, "\n"); 1158 } 1159 1160 return {}; 1161 } 1162 1163 android::base::Result<void> VintfObject::checkMatrixHalsHasDefinition( 1164 const std::vector<HidlInterfaceMetadata>& hidlMetadata, 1165 const std::vector<AidlInterfaceMetadata>& aidlMetadata) { 1166 auto matrixFragments = getAllFrameworkMatrixLevels(); 1167 if (!matrixFragments.ok()) return matrixFragments.error(); 1168 1169 auto allAidlNames = AidlMetadataToNames(aidlMetadata); 1170 auto allHidlNames = HidlMetadataToNames(hidlMetadata); 1171 std::set<std::string> badAidlInterfaces; 1172 std::set<std::string> badHidlInterfaces; 1173 1174 std::vector<std::string> errors; 1175 for (const auto& matrix : matrixFragments.value()) { 1176 if (matrix.level() == Level::UNSPECIFIED) { 1177 LOG(INFO) << "Skip checkMatrixHalsHasDefinition() on " << matrix.fileName() 1178 << " with no level."; 1179 continue; 1180 } 1181 1182 matrix.forEachInstance([&](const MatrixInstance& matrixInstance) { 1183 switch (matrixInstance.format()) { 1184 case HalFormat::AIDL: { 1185 auto matrixInterface = 1186 toAidlFqnameString(matrixInstance.package(), matrixInstance.interface()); 1187 if (allAidlNames.find(matrixInterface) == allAidlNames.end()) { 1188 errors.push_back( 1189 "AIDL interface " + matrixInterface + " is referenced in " + 1190 matrix.fileName() + 1191 ", but there is no corresponding .aidl definition associated with an " 1192 "aidl_interface module in this build. Typo?"); 1193 } 1194 return true; // continue to next instance 1195 } 1196 case HalFormat::HIDL: { 1197 for (Version v = matrixInstance.versionRange().minVer(); 1198 v <= matrixInstance.versionRange().maxVer(); ++v.minorVer) { 1199 auto matrixInterface = matrixInstance.interfaceDescription(v); 1200 if (allHidlNames.find(matrixInterface) == allHidlNames.end()) { 1201 errors.push_back( 1202 "HIDL interface " + matrixInterface + " is referenced in " + 1203 matrix.fileName() + 1204 ", but there is no corresponding .hal definition associated with " 1205 "a hidl_interface module in this build. Typo?"); 1206 } 1207 } 1208 return true; // continue to next instance 1209 } 1210 default: { 1211 // We do not have data for native HALs. 1212 return true; // continue to next instance 1213 } 1214 } 1215 }); 1216 } 1217 1218 if (!errors.empty()) { 1219 return android::base::Error() << android::base::Join(errors, "\n"); 1220 } 1221 1222 return {}; 1223 } 1224 1225 // make_unique does not work because VintfObject constructor is private. 1226 VintfObject::Builder::Builder() : mObject(std::unique_ptr<VintfObject>(new VintfObject())) {} 1227 1228 VintfObject::Builder& VintfObject::Builder::setFileSystem(std::unique_ptr<FileSystem>&& e) { 1229 mObject->mFileSystem = std::move(e); 1230 return *this; 1231 } 1232 1233 VintfObject::Builder& VintfObject::Builder::setRuntimeInfoFactory( 1234 std::unique_ptr<ObjectFactory<RuntimeInfo>>&& e) { 1235 mObject->mRuntimeInfoFactory = std::move(e); 1236 return *this; 1237 } 1238 1239 VintfObject::Builder& VintfObject::Builder::setPropertyFetcher( 1240 std::unique_ptr<PropertyFetcher>&& e) { 1241 mObject->mPropertyFetcher = std::move(e); 1242 return *this; 1243 } 1244 1245 std::unique_ptr<VintfObject> VintfObject::Builder::build() { 1246 if (!mObject->mFileSystem) mObject->mFileSystem = createDefaultFileSystem(); 1247 if (!mObject->mRuntimeInfoFactory) 1248 mObject->mRuntimeInfoFactory = std::make_unique<ObjectFactory<RuntimeInfo>>(); 1249 if (!mObject->mPropertyFetcher) mObject->mPropertyFetcher = createDefaultPropertyFetcher(); 1250 return std::move(mObject); 1251 } 1252 1253 } // namespace vintf 1254 } // namespace android 1255