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