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