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