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