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