1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "VintfObject.h"
18
19 #include <dirent.h>
20
21 #include <functional>
22 #include <memory>
23 #include <mutex>
24
25 #include <android-base/logging.h>
26
27 #include "CompatibilityMatrix.h"
28 #include "VintfObjectAfterUpdate.h"
29 #include "parse_string.h"
30 #include "parse_xml.h"
31 #include "utils.h"
32
33 using std::placeholders::_1;
34 using std::placeholders::_2;
35
36 namespace android {
37 namespace vintf {
38
39 using namespace details;
40
41 #ifdef LIBVINTF_TARGET
42 static constexpr bool kIsTarget = true;
43 #else
44 static constexpr bool kIsTarget = false;
45 #endif
46
47 template <typename T, typename F>
Get(LockedSharedPtr<T> * ptr,bool skipCache,const F & fetchAllInformation)48 static std::shared_ptr<const T> Get(
49 LockedSharedPtr<T> *ptr,
50 bool skipCache,
51 const F &fetchAllInformation) {
52 std::unique_lock<std::mutex> _lock(ptr->mutex);
53 if (skipCache || !ptr->fetchedOnce) {
54 ptr->object = std::make_unique<T>();
55 std::string error;
56 if (fetchAllInformation(ptr->object.get(), &error) != OK) {
57 LOG(WARNING) << error;
58 ptr->object = nullptr; // frees the old object
59 }
60 ptr->fetchedOnce = true;
61 }
62 return ptr->object;
63 }
64
createDefaultFileSystem()65 static std::unique_ptr<FileSystem> createDefaultFileSystem() {
66 std::unique_ptr<FileSystem> fileSystem;
67 if (kIsTarget) {
68 fileSystem = std::make_unique<details::FileSystemImpl>();
69 } else {
70 fileSystem = std::make_unique<details::FileSystemNoOp>();
71 }
72 return fileSystem;
73 }
74
createDefaultPropertyFetcher()75 static std::unique_ptr<PropertyFetcher> createDefaultPropertyFetcher() {
76 std::unique_ptr<PropertyFetcher> propertyFetcher;
77 if (kIsTarget) {
78 propertyFetcher = std::make_unique<details::PropertyFetcherImpl>();
79 } else {
80 propertyFetcher = std::make_unique<details::PropertyFetcherNoOp>();
81 }
82 return propertyFetcher;
83 }
84
85 details::LockedSharedPtr<VintfObject> VintfObject::sInstance{};
GetInstance()86 std::shared_ptr<VintfObject> VintfObject::GetInstance() {
87 std::unique_lock<std::mutex> lock(sInstance.mutex);
88 if (sInstance.object == nullptr) {
89 sInstance.object = std::shared_ptr<VintfObject>(VintfObject::Builder().build().release());
90 }
91 return sInstance.object;
92 }
93
GetDeviceHalManifest(bool skipCache)94 std::shared_ptr<const HalManifest> VintfObject::GetDeviceHalManifest(bool skipCache) {
95 return GetInstance()->getDeviceHalManifest(skipCache);
96 }
97
getDeviceHalManifest(bool skipCache)98 std::shared_ptr<const HalManifest> VintfObject::getDeviceHalManifest(bool skipCache) {
99 return Get(&mDeviceManifest, skipCache,
100 std::bind(&VintfObject::fetchDeviceHalManifest, this, _1, _2));
101 }
102
GetFrameworkHalManifest(bool skipCache)103 std::shared_ptr<const HalManifest> VintfObject::GetFrameworkHalManifest(bool skipCache) {
104 return GetInstance()->getFrameworkHalManifest(skipCache);
105 }
106
getFrameworkHalManifest(bool skipCache)107 std::shared_ptr<const HalManifest> VintfObject::getFrameworkHalManifest(bool skipCache) {
108 return Get(&mFrameworkManifest, skipCache,
109 std::bind(&VintfObject::fetchFrameworkHalManifest, this, _1, _2));
110 }
111
GetDeviceCompatibilityMatrix(bool skipCache)112 std::shared_ptr<const CompatibilityMatrix> VintfObject::GetDeviceCompatibilityMatrix(bool skipCache) {
113 return GetInstance()->getDeviceCompatibilityMatrix(skipCache);
114 }
115
getDeviceCompatibilityMatrix(bool skipCache)116 std::shared_ptr<const CompatibilityMatrix> VintfObject::getDeviceCompatibilityMatrix(
117 bool skipCache) {
118 return Get(&mDeviceMatrix, skipCache, std::bind(&VintfObject::fetchDeviceMatrix, this, _1, _2));
119 }
120
GetFrameworkCompatibilityMatrix(bool skipCache)121 std::shared_ptr<const CompatibilityMatrix> VintfObject::GetFrameworkCompatibilityMatrix(bool skipCache) {
122 return GetInstance()->getFrameworkCompatibilityMatrix(skipCache);
123 }
124
getFrameworkCompatibilityMatrix(bool skipCache)125 std::shared_ptr<const CompatibilityMatrix> VintfObject::getFrameworkCompatibilityMatrix(
126 bool skipCache) {
127 // To avoid deadlock, get device manifest before any locks.
128 auto deviceManifest = getDeviceHalManifest();
129
130 std::unique_lock<std::mutex> _lock(mFrameworkCompatibilityMatrixMutex);
131
132 auto combined =
133 Get(&mCombinedFrameworkMatrix, skipCache,
134 std::bind(&VintfObject::getCombinedFrameworkMatrix, this, deviceManifest, _1, _2));
135 if (combined != nullptr) {
136 return combined;
137 }
138
139 return Get(&mFrameworkMatrix, skipCache,
140 std::bind(&CompatibilityMatrix::fetchAllInformation, _1, getFileSystem().get(),
141 kSystemLegacyMatrix, _2));
142 }
143
getCombinedFrameworkMatrix(const std::shared_ptr<const HalManifest> & deviceManifest,CompatibilityMatrix * out,std::string * error)144 status_t VintfObject::getCombinedFrameworkMatrix(
145 const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out,
146 std::string* error) {
147 std::vector<Named<CompatibilityMatrix>> matrixFragments;
148 auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, error);
149 if (matrixFragmentsStatus != OK) {
150 return matrixFragmentsStatus;
151 }
152 if (matrixFragments.empty()) {
153 if (error && error->empty()) {
154 *error = "Cannot get framework matrix for each FCM version for unknown error.";
155 }
156 return NAME_NOT_FOUND;
157 }
158
159 Level deviceLevel = Level::UNSPECIFIED;
160
161 if (deviceManifest != nullptr) {
162 deviceLevel = deviceManifest->level();
163 }
164
165 // TODO(b/70628538): Do not infer from Shipping API level.
166 if (deviceLevel == Level::UNSPECIFIED) {
167 auto shippingApi = getPropertyFetcher()->getUintProperty("ro.product.first_api_level", 0u);
168 if (shippingApi != 0u) {
169 deviceLevel = details::convertFromApiLevel(shippingApi);
170 }
171 }
172
173 if (deviceLevel == Level::UNSPECIFIED) {
174 // Cannot infer FCM version. Combine all matrices by assuming
175 // Shipping FCM Version == min(all supported FCM Versions in the framework)
176 for (auto&& pair : matrixFragments) {
177 Level fragmentLevel = pair.object.level();
178 if (fragmentLevel != Level::UNSPECIFIED && deviceLevel > fragmentLevel) {
179 deviceLevel = fragmentLevel;
180 }
181 }
182 }
183
184 if (deviceLevel == Level::UNSPECIFIED) {
185 // None of the fragments specify any FCM version. Should never happen except
186 // for inconsistent builds.
187 if (error) {
188 *error = "No framework compatibility matrix files under " + kSystemVintfDir +
189 " declare FCM version.";
190 }
191 return NAME_NOT_FOUND;
192 }
193
194 auto combined = CompatibilityMatrix::combine(deviceLevel, &matrixFragments, error);
195 if (combined == nullptr) {
196 return BAD_VALUE;
197 }
198 *out = std::move(*combined);
199 return OK;
200 }
201
202 // Load and combine all of the manifests in a directory
addDirectoryManifests(const std::string & directory,HalManifest * manifest,std::string * error)203 status_t VintfObject::addDirectoryManifests(const std::string& directory, HalManifest* manifest,
204 std::string* error) {
205 std::vector<std::string> fileNames;
206 status_t err = getFileSystem()->listFiles(directory, &fileNames, error);
207 // if the directory isn't there, that's okay
208 if (err == NAME_NOT_FOUND) return OK;
209 if (err != OK) return err;
210
211 for (const std::string& file : fileNames) {
212 // Only adds HALs because all other things are added by libvintf
213 // itself for now.
214 HalManifest fragmentManifest;
215 err = fetchOneHalManifest(directory + file, &fragmentManifest, error);
216 if (err != OK) return err;
217
218 if (!manifest->addAll(&fragmentManifest, error)) {
219 if (error) {
220 error->insert(0, "Cannot add manifest fragment " + directory + file + ":");
221 }
222 return UNKNOWN_ERROR;
223 }
224 }
225
226 return OK;
227 }
228
229 // Priority for loading vendor manifest:
230 // 1. /vendor/etc/vintf/manifest.xml + device fragments + ODM manifest (optional) + odm fragments
231 // 2. /vendor/etc/vintf/manifest.xml + device fragments
232 // 3. ODM manifest (optional) + odm fragments
233 // 4. /vendor/manifest.xml (legacy, no fragments)
234 // where:
235 // A + B means unioning <hal> tags from A and B. If B declares an override, then this takes priority
236 // over A.
fetchDeviceHalManifest(HalManifest * out,std::string * error)237 status_t VintfObject::fetchDeviceHalManifest(HalManifest* out, std::string* error) {
238 status_t vendorStatus = fetchOneHalManifest(kVendorManifest, out, error);
239 if (vendorStatus != OK && vendorStatus != NAME_NOT_FOUND) {
240 return vendorStatus;
241 }
242
243 if (vendorStatus == OK) {
244 status_t fragmentStatus = addDirectoryManifests(kVendorManifestFragmentDir, out, error);
245 if (fragmentStatus != OK) {
246 return fragmentStatus;
247 }
248 }
249
250 HalManifest odmManifest;
251 status_t odmStatus = fetchOdmHalManifest(&odmManifest, error);
252 if (odmStatus != OK && odmStatus != NAME_NOT_FOUND) {
253 return odmStatus;
254 }
255
256 if (vendorStatus == OK) {
257 if (odmStatus == OK) {
258 if (!out->addAll(&odmManifest, error)) {
259 if (error) {
260 error->insert(0, "Cannot add ODM manifest :");
261 }
262 return UNKNOWN_ERROR;
263 }
264 }
265 return addDirectoryManifests(kOdmManifestFragmentDir, out, error);
266 }
267
268 // vendorStatus != OK, "out" is not changed.
269 if (odmStatus == OK) {
270 *out = std::move(odmManifest);
271 return addDirectoryManifests(kOdmManifestFragmentDir, out, error);
272 }
273
274 // Use legacy /vendor/manifest.xml
275 return out->fetchAllInformation(getFileSystem().get(), kVendorLegacyManifest, error);
276 }
277
278 // "out" is written to iff return status is OK.
279 // Priority:
280 // 1. if {sku} is defined, /odm/etc/vintf/manifest_{sku}.xml
281 // 2. /odm/etc/vintf/manifest.xml
282 // 3. if {sku} is defined, /odm/etc/manifest_{sku}.xml
283 // 4. /odm/etc/manifest.xml
284 // where:
285 // {sku} is the value of ro.boot.product.hardware.sku
fetchOdmHalManifest(HalManifest * out,std::string * error)286 status_t VintfObject::fetchOdmHalManifest(HalManifest* out, std::string* error) {
287 status_t status;
288
289 std::string productModel;
290 productModel = getPropertyFetcher()->getProperty("ro.boot.product.hardware.sku", "");
291
292 if (!productModel.empty()) {
293 status =
294 fetchOneHalManifest(kOdmVintfDir + "manifest_" + productModel + ".xml", out, error);
295 if (status == OK || status != NAME_NOT_FOUND) {
296 return status;
297 }
298 }
299
300 status = fetchOneHalManifest(kOdmManifest, out, error);
301 if (status == OK || status != NAME_NOT_FOUND) {
302 return status;
303 }
304
305 if (!productModel.empty()) {
306 status = fetchOneHalManifest(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml", out,
307 error);
308 if (status == OK || status != NAME_NOT_FOUND) {
309 return status;
310 }
311 }
312
313 status = fetchOneHalManifest(kOdmLegacyManifest, out, error);
314 if (status == OK || status != NAME_NOT_FOUND) {
315 return status;
316 }
317
318 return NAME_NOT_FOUND;
319 }
320
321 // Fetch one manifest.xml file. "out" is written to iff return status is OK.
322 // Returns NAME_NOT_FOUND if file is missing.
fetchOneHalManifest(const std::string & path,HalManifest * out,std::string * error)323 status_t VintfObject::fetchOneHalManifest(const std::string& path, HalManifest* out,
324 std::string* error) {
325 HalManifest ret;
326 status_t status = ret.fetchAllInformation(getFileSystem().get(), path, error);
327 if (status == OK) {
328 *out = std::move(ret);
329 }
330 return status;
331 }
332
fetchDeviceMatrix(CompatibilityMatrix * out,std::string * error)333 status_t VintfObject::fetchDeviceMatrix(CompatibilityMatrix* out, std::string* error) {
334 CompatibilityMatrix etcMatrix;
335 if (etcMatrix.fetchAllInformation(getFileSystem().get(), kVendorMatrix, error) == OK) {
336 *out = std::move(etcMatrix);
337 return OK;
338 }
339 return out->fetchAllInformation(getFileSystem().get(), kVendorLegacyMatrix, error);
340 }
341
342 // Priority:
343 // 1. /system/etc/vintf/manifest.xml
344 // + /system/etc/vintf/manifest/*.xml if they exist
345 // + /product/etc/vintf/manifest.xml if it exists
346 // + /product/etc/vintf/manifest/*.xml if they exist
347 // 2. (deprecated) /system/manifest.xml
fetchFrameworkHalManifest(HalManifest * out,std::string * error)348 status_t VintfObject::fetchFrameworkHalManifest(HalManifest* out, std::string* error) {
349 auto systemEtcStatus = fetchOneHalManifest(kSystemManifest, out, error);
350 if (systemEtcStatus == OK) {
351 auto dirStatus = addDirectoryManifests(kSystemManifestFragmentDir, out, error);
352 if (dirStatus != OK) {
353 return dirStatus;
354 }
355
356 HalManifest productManifest;
357 auto productStatus = fetchOneHalManifest(kProductManifest, &productManifest, error);
358 if (productStatus != OK && productStatus != NAME_NOT_FOUND) {
359 return productStatus;
360 }
361 if (productStatus == OK) {
362 if (!out->addAll(&productManifest, error)) {
363 if (error) {
364 error->insert(0, "Cannot add " + kProductManifest + ":");
365 }
366 return UNKNOWN_ERROR;
367 }
368 }
369
370 return addDirectoryManifests(kProductManifestFragmentDir, out, error);
371 } else {
372 LOG(WARNING) << "Cannot fetch " << kSystemManifest << ": "
373 << (error ? *error : strerror(-systemEtcStatus));
374 }
375
376 return out->fetchAllInformation(getFileSystem().get(), kSystemLegacyManifest, error);
377 }
378
appendLine(std::string * error,const std::string & message)379 static void appendLine(std::string* error, const std::string& message) {
380 if (error != nullptr) {
381 if (!error->empty()) *error += "\n";
382 *error += message;
383 }
384 }
385
getOneMatrix(const std::string & path,Named<CompatibilityMatrix> * out,std::string * error)386 status_t VintfObject::getOneMatrix(const std::string& path, Named<CompatibilityMatrix>* out,
387 std::string* error) {
388 std::string content;
389 status_t status = getFileSystem()->fetch(path, &content, error);
390 if (status != OK) {
391 return status;
392 }
393 if (!gCompatibilityMatrixConverter(&out->object, content, error)) {
394 if (error) {
395 error->insert(0, "Cannot parse " + path + ": ");
396 }
397 return BAD_VALUE;
398 }
399 out->name = path;
400 return OK;
401 }
402
getAllFrameworkMatrixLevels(std::vector<Named<CompatibilityMatrix>> * results,std::string * error)403 status_t VintfObject::getAllFrameworkMatrixLevels(std::vector<Named<CompatibilityMatrix>>* results,
404 std::string* error) {
405 std::vector<std::string> fileNames;
406
407 status_t listStatus = getFileSystem()->listFiles(kSystemVintfDir, &fileNames, error);
408 if (listStatus != OK) {
409 return listStatus;
410 }
411 for (const std::string& fileName : fileNames) {
412 std::string path = kSystemVintfDir + fileName;
413 Named<CompatibilityMatrix> namedMatrix;
414 std::string matrixError;
415 status_t matrixStatus = getOneMatrix(path, &namedMatrix, &matrixError);
416 if (matrixStatus != OK) {
417 // System manifests and matrices share the same dir. Client may not have enough
418 // permissions to read system manifests, or may not be able to parse it.
419 auto logLevel = matrixStatus == BAD_VALUE ? base::DEBUG : base::ERROR;
420 LOG(logLevel) << "Framework Matrix: Ignore file " << path << ": " << matrixError;
421 continue;
422 }
423 results->emplace_back(std::move(namedMatrix));
424 }
425
426 Named<CompatibilityMatrix> productMatrix;
427 std::string productError;
428 status_t productStatus = getOneMatrix(kProductMatrix, &productMatrix, &productError);
429 if (productStatus == OK) {
430 results->emplace_back(std::move(productMatrix));
431 } else if (productStatus == NAME_NOT_FOUND) {
432 LOG(DEBUG) << "Framework Matrix: missing " << kProductMatrix;
433 } else {
434 if (error) *error = std::move(productError);
435 return productStatus;
436 }
437
438 if (results->empty()) {
439 if (error) {
440 *error =
441 "No framework matrices under " + kSystemVintfDir + " can be fetched or parsed.\n";
442 }
443 return NAME_NOT_FOUND;
444 }
445 return OK;
446 }
447
GetRuntimeInfo(bool skipCache,RuntimeInfo::FetchFlags flags)448 std::shared_ptr<const RuntimeInfo> VintfObject::GetRuntimeInfo(bool skipCache,
449 RuntimeInfo::FetchFlags flags) {
450 return GetInstance()->getRuntimeInfo(skipCache, flags);
451 }
getRuntimeInfo(bool skipCache,RuntimeInfo::FetchFlags flags)452 std::shared_ptr<const RuntimeInfo> VintfObject::getRuntimeInfo(bool skipCache,
453 RuntimeInfo::FetchFlags flags) {
454 std::unique_lock<std::mutex> _lock(mDeviceRuntimeInfo.mutex);
455
456 if (!skipCache) {
457 flags &= (~mDeviceRuntimeInfo.fetchedFlags);
458 }
459
460 if (mDeviceRuntimeInfo.object == nullptr) {
461 mDeviceRuntimeInfo.object = getRuntimeInfoFactory()->make_shared();
462 }
463
464 status_t status = mDeviceRuntimeInfo.object->fetchAllInformation(flags);
465 if (status != OK) {
466 mDeviceRuntimeInfo.fetchedFlags &= (~flags); // mark the fields as "not fetched"
467 return nullptr;
468 }
469
470 mDeviceRuntimeInfo.fetchedFlags |= flags;
471 return mDeviceRuntimeInfo.object;
472 }
473
474 namespace details {
475
476 enum class ParseStatus {
477 OK,
478 PARSE_ERROR,
479 DUPLICATED_FWK_ENTRY,
480 DUPLICATED_DEV_ENTRY,
481 };
482
toString(ParseStatus status)483 static std::string toString(ParseStatus status) {
484 switch(status) {
485 case ParseStatus::OK: return "OK";
486 case ParseStatus::PARSE_ERROR: return "parse error";
487 case ParseStatus::DUPLICATED_FWK_ENTRY: return "duplicated framework";
488 case ParseStatus::DUPLICATED_DEV_ENTRY: return "duplicated device";
489 }
490 return "";
491 }
492
493 template <typename T>
tryParse(const std::string & xml,const XmlConverter<T> & parse,VintfObjectAfterUpdate * afterUpdate)494 static ParseStatus tryParse(const std::string& xml, const XmlConverter<T>& parse,
495 VintfObjectAfterUpdate* afterUpdate) {
496 std::shared_ptr<T> ret = std::make_shared<T>();
497 if (!parse(ret.get(), xml, nullptr /* error */)) {
498 return ParseStatus::PARSE_ERROR;
499 }
500 if (!afterUpdate->set(ret)) {
501 if (ret->type() == SchemaType::FRAMEWORK) {
502 return ParseStatus::DUPLICATED_FWK_ENTRY;
503 } else if (ret->type() == SchemaType::DEVICE) {
504 return ParseStatus::DUPLICATED_DEV_ENTRY;
505 }
506 LOG(FATAL) << "unknown SchemaType: "
507 << static_cast<std::underlying_type_t<SchemaType>>(ret->type());
508 }
509 return ParseStatus::OK;
510 }
511
512 } // namespace details
513
514 // Simulate applying xmls to VintfObject, then checkCompatibility as usual.
checkCompatibility(const std::vector<std::string> & xmls,std::string * error,CheckFlags::Type flags)515 int32_t VintfObject::checkCompatibility(const std::vector<std::string>& xmls, std::string* error,
516 CheckFlags::Type flags) {
517 VintfObjectAfterUpdate afterUpdate(this);
518 ParseStatus parseStatus = ParseStatus::OK;
519
520 // parse all information from package
521 for (const auto &xml : xmls) {
522 parseStatus = tryParse(xml, gHalManifestConverter, &afterUpdate);
523 if (parseStatus == ParseStatus::OK) {
524 continue; // work on next one
525 }
526 if (parseStatus != ParseStatus::PARSE_ERROR) {
527 appendLine(error, toString(parseStatus) + " manifest");
528 return ALREADY_EXISTS;
529 }
530 parseStatus = tryParse(xml, gCompatibilityMatrixConverter, &afterUpdate);
531 if (parseStatus == ParseStatus::OK) {
532 continue; // work on next one
533 }
534 if (parseStatus != ParseStatus::PARSE_ERROR) {
535 appendLine(error, toString(parseStatus) + " matrix");
536 return ALREADY_EXISTS;
537 }
538 appendLine(error, toString(parseStatus)); // parse error
539 return BAD_VALUE;
540 }
541
542 return afterUpdate.checkCompatibility(error, flags);
543 }
544
checkCompatibility(std::string * error,CheckFlags::Type flags)545 int32_t VintfObject::checkCompatibility(std::string* error, CheckFlags::Type flags) {
546 status_t status = OK;
547 // null checks for files and runtime info
548 if (getFrameworkHalManifest() == nullptr) {
549 appendLine(error, "No framework manifest file from device or from update package");
550 status = NO_INIT;
551 }
552 if (getDeviceHalManifest() == nullptr) {
553 appendLine(error, "No device manifest file from device or from update package");
554 status = NO_INIT;
555 }
556 if (getFrameworkCompatibilityMatrix() == nullptr) {
557 appendLine(error, "No framework matrix file from device or from update package");
558 status = NO_INIT;
559 }
560 if (getDeviceCompatibilityMatrix() == nullptr) {
561 appendLine(error, "No device matrix file from device or from update package");
562 status = NO_INIT;
563 }
564
565 if (flags.isRuntimeInfoEnabled()) {
566 if (getRuntimeInfo() == nullptr) {
567 appendLine(error, "No runtime info from device");
568 status = NO_INIT;
569 }
570 }
571 if (status != OK) return status;
572
573 // compatiblity check.
574 if (!getDeviceHalManifest()->checkCompatibility(*getFrameworkCompatibilityMatrix(), error)) {
575 if (error) {
576 error->insert(0,
577 "Device manifest and framework compatibility matrix are incompatible: ");
578 }
579 return INCOMPATIBLE;
580 }
581 if (!getFrameworkHalManifest()->checkCompatibility(*getDeviceCompatibilityMatrix(), error)) {
582 if (error) {
583 error->insert(0,
584 "Framework manifest and device compatibility matrix are incompatible: ");
585 }
586 return INCOMPATIBLE;
587 }
588
589 CheckFlags::Type runtimeInfoCheckFlags = flags;
590 if (!!getDeviceHalManifest()->kernel()) {
591 // Use kernel from incoming OTA package, but not on the device.
592 runtimeInfoCheckFlags = runtimeInfoCheckFlags.disableKernel();
593 }
594
595 if (flags.isRuntimeInfoEnabled()) {
596 if (!getRuntimeInfo()->checkCompatibility(*getFrameworkCompatibilityMatrix(), error,
597 runtimeInfoCheckFlags)) {
598 if (error) {
599 error->insert(0,
600 "Runtime info and framework compatibility matrix are incompatible: ");
601 }
602 return INCOMPATIBLE;
603 }
604 }
605
606 return COMPATIBLE;
607 }
608
609 namespace details {
610
611 const std::string kSystemVintfDir = "/system/etc/vintf/";
612 const std::string kVendorVintfDir = "/vendor/etc/vintf/";
613 const std::string kOdmVintfDir = "/odm/etc/vintf/";
614 const std::string kProductVintfDir = "/product/etc/vintf/";
615
616 const std::string kVendorManifest = kVendorVintfDir + "manifest.xml";
617 const std::string kSystemManifest = kSystemVintfDir + "manifest.xml";
618 const std::string kVendorMatrix = kVendorVintfDir + "compatibility_matrix.xml";
619 const std::string kOdmManifest = kOdmVintfDir + "manifest.xml";
620 const std::string kProductMatrix = kProductVintfDir + "compatibility_matrix.xml";
621 const std::string kProductManifest = kProductVintfDir + "manifest.xml";
622
623 const std::string kVendorManifestFragmentDir = kVendorVintfDir + "manifest/";
624 const std::string kSystemManifestFragmentDir = kSystemVintfDir + "manifest/";
625 const std::string kOdmManifestFragmentDir = kOdmVintfDir + "manifest/";
626 const std::string kProductManifestFragmentDir = kProductVintfDir + "manifest/";
627
628 const std::string kVendorLegacyManifest = "/vendor/manifest.xml";
629 const std::string kVendorLegacyMatrix = "/vendor/compatibility_matrix.xml";
630 const std::string kSystemLegacyManifest = "/system/manifest.xml";
631 const std::string kSystemLegacyMatrix = "/system/compatibility_matrix.xml";
632 const std::string kOdmLegacyVintfDir = "/odm/etc/";
633 const std::string kOdmLegacyManifest = kOdmLegacyVintfDir + "manifest.xml";
634
dumpFileList()635 std::vector<std::string> dumpFileList() {
636 return {
637 // clang-format off
638 kSystemVintfDir,
639 kVendorVintfDir,
640 kOdmVintfDir,
641 kProductVintfDir,
642 kOdmLegacyVintfDir,
643 kVendorLegacyManifest,
644 kVendorLegacyMatrix,
645 kSystemLegacyManifest,
646 kSystemLegacyMatrix,
647 // clang-format on
648 };
649 }
650
651 } // namespace details
652
CheckCompatibility(const std::vector<std::string> & xmls,std::string * error,CheckFlags::Type flags)653 int32_t VintfObject::CheckCompatibility(const std::vector<std::string>& xmls, std::string* error,
654 CheckFlags::Type flags) {
655 return GetInstance()->checkCompatibility(xmls, error, flags);
656 }
657
IsHalDeprecated(const MatrixHal & oldMatrixHal,const CompatibilityMatrix & targetMatrix,const ListInstances & listInstances,std::string * error)658 bool VintfObject::IsHalDeprecated(const MatrixHal& oldMatrixHal,
659 const CompatibilityMatrix& targetMatrix,
660 const ListInstances& listInstances, std::string* error) {
661 bool isDeprecated = false;
662 oldMatrixHal.forEachInstance([&](const MatrixInstance& oldMatrixInstance) {
663 if (IsInstanceDeprecated(oldMatrixInstance, targetMatrix, listInstances, error)) {
664 isDeprecated = true;
665 }
666 return !isDeprecated; // continue if no deprecated instance is found.
667 });
668 return isDeprecated;
669 }
670
671 // Let oldMatrixInstance = package@x.y-w::interface with instancePattern.
672 // If any "servedInstance" in listInstances(package@x.y::interface) matches instancePattern, return
673 // true iff:
674 // 1. package@x.?::interface/servedInstance is not in targetMatrix; OR
675 // 2. package@x.z::interface/servedInstance is in targetMatrix but
676 // servedInstance is not in listInstances(package@x.z::interface)
IsInstanceDeprecated(const MatrixInstance & oldMatrixInstance,const CompatibilityMatrix & targetMatrix,const ListInstances & listInstances,std::string * error)677 bool VintfObject::IsInstanceDeprecated(const MatrixInstance& oldMatrixInstance,
678 const CompatibilityMatrix& targetMatrix,
679 const ListInstances& listInstances, std::string* error) {
680 const std::string& package = oldMatrixInstance.package();
681 const Version& version = oldMatrixInstance.versionRange().minVer();
682 const std::string& interface = oldMatrixInstance.interface();
683
684 std::vector<std::string> instanceHint;
685 if (!oldMatrixInstance.isRegex()) {
686 instanceHint.push_back(oldMatrixInstance.exactInstance());
687 }
688
689 auto list = listInstances(package, version, interface, instanceHint);
690 for (const auto& pair : list) {
691 const std::string& servedInstance = pair.first;
692 Version servedVersion = pair.second;
693 if (!oldMatrixInstance.matchInstance(servedInstance)) {
694 continue;
695 }
696
697 // Find any package@x.? in target matrix, and check if instance is in target matrix.
698 bool foundInstance = false;
699 Version targetMatrixMinVer;
700 targetMatrix.forEachInstanceOfPackage(package, [&](const auto& targetMatrixInstance) {
701 if (targetMatrixInstance.versionRange().majorVer == version.majorVer &&
702 targetMatrixInstance.interface() == interface &&
703 targetMatrixInstance.matchInstance(servedInstance)) {
704 targetMatrixMinVer = targetMatrixInstance.versionRange().minVer();
705 foundInstance = true;
706 }
707 return !foundInstance; // continue if not found
708 });
709 if (!foundInstance) {
710 if (error) {
711 *error = toFQNameString(package, servedVersion, interface, servedInstance) +
712 " is deprecated in compatibility matrix at FCM Version " +
713 to_string(targetMatrix.level()) + "; it should not be served.";
714 }
715 return true;
716 }
717
718 // Assuming that targetMatrix requires @x.u-v, require that at least @x.u is served.
719 bool targetVersionServed = false;
720 for (const auto& newPair :
721 listInstances(package, targetMatrixMinVer, interface, instanceHint)) {
722 if (newPair.first == servedInstance) {
723 targetVersionServed = true;
724 break;
725 }
726 }
727
728 if (!targetVersionServed) {
729 appendLine(error, toFQNameString(package, servedVersion, interface, servedInstance) +
730 " is deprecated; requires at least " +
731 to_string(targetMatrixMinVer));
732 return true;
733 }
734 }
735
736 return false;
737 }
738
CheckDeprecation(const ListInstances & listInstances,std::string * error)739 int32_t VintfObject::CheckDeprecation(const ListInstances& listInstances, std::string* error) {
740 return GetInstance()->checkDeprecation(listInstances, error);
741 }
checkDeprecation(const ListInstances & listInstances,std::string * error)742 int32_t VintfObject::checkDeprecation(const ListInstances& listInstances, std::string* error) {
743 std::vector<Named<CompatibilityMatrix>> matrixFragments;
744 auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, error);
745 if (matrixFragmentsStatus != OK) {
746 return matrixFragmentsStatus;
747 }
748 if (matrixFragments.empty()) {
749 if (error && error->empty()) {
750 *error = "Cannot get framework matrix for each FCM version for unknown error.";
751 }
752 return NAME_NOT_FOUND;
753 }
754 auto deviceManifest = getDeviceHalManifest();
755 if (deviceManifest == nullptr) {
756 if (error) *error = "No device manifest.";
757 return NAME_NOT_FOUND;
758 }
759 Level deviceLevel = deviceManifest->level();
760 if (deviceLevel == Level::UNSPECIFIED) {
761 if (error) *error = "Device manifest does not specify Shipping FCM Version.";
762 return BAD_VALUE;
763 }
764
765 const CompatibilityMatrix* targetMatrix = nullptr;
766 for (const auto& namedMatrix : matrixFragments) {
767 if (namedMatrix.object.level() == deviceLevel) {
768 targetMatrix = &namedMatrix.object;
769 }
770 }
771 if (targetMatrix == nullptr) {
772 if (error)
773 *error = "Cannot find framework matrix at FCM version " + to_string(deviceLevel) + ".";
774 return NAME_NOT_FOUND;
775 }
776
777 bool hasDeprecatedHals = false;
778 for (const auto& namedMatrix : matrixFragments) {
779 if (namedMatrix.object.level() == Level::UNSPECIFIED) continue;
780 if (namedMatrix.object.level() >= deviceLevel) continue;
781
782 const auto& oldMatrix = namedMatrix.object;
783 for (const MatrixHal& hal : oldMatrix.getHals()) {
784 hasDeprecatedHals |= IsHalDeprecated(hal, *targetMatrix, listInstances, error);
785 }
786 }
787
788 return hasDeprecatedHals ? DEPRECATED : NO_DEPRECATED_HALS;
789 }
790
CheckDeprecation(std::string * error)791 int32_t VintfObject::CheckDeprecation(std::string* error) {
792 return GetInstance()->checkDeprecation(error);
793 }
checkDeprecation(std::string * error)794 int32_t VintfObject::checkDeprecation(std::string* error) {
795 using namespace std::placeholders;
796 auto deviceManifest = getDeviceHalManifest();
797 ListInstances inManifest =
798 [&deviceManifest](const std::string& package, Version version, const std::string& interface,
799 const std::vector<std::string>& /* hintInstances */) {
800 std::vector<std::pair<std::string, Version>> ret;
801 deviceManifest->forEachInstanceOfInterface(
802 package, version, interface, [&ret](const ManifestInstance& manifestInstance) {
803 ret.push_back(
804 std::make_pair(manifestInstance.instance(), manifestInstance.version()));
805 return true;
806 });
807 return ret;
808 };
809 return checkDeprecation(inManifest, error);
810 }
811
getFileSystem()812 const std::unique_ptr<FileSystem>& VintfObject::getFileSystem() {
813 return mFileSystem;
814 }
815
getPropertyFetcher()816 const std::unique_ptr<PropertyFetcher>& VintfObject::getPropertyFetcher() {
817 return mPropertyFetcher;
818 }
819
getRuntimeInfoFactory()820 const std::unique_ptr<ObjectFactory<RuntimeInfo>>& VintfObject::getRuntimeInfoFactory() {
821 return mRuntimeInfoFactory;
822 }
823
824 // make_unique does not work because VintfObject constructor is private.
Builder()825 VintfObject::Builder::Builder() : mObject(std::unique_ptr<VintfObject>(new VintfObject())) {}
826
setFileSystem(std::unique_ptr<FileSystem> && e)827 VintfObject::Builder& VintfObject::Builder::setFileSystem(std::unique_ptr<FileSystem>&& e) {
828 mObject->mFileSystem = std::move(e);
829 return *this;
830 }
831
setRuntimeInfoFactory(std::unique_ptr<ObjectFactory<RuntimeInfo>> && e)832 VintfObject::Builder& VintfObject::Builder::setRuntimeInfoFactory(
833 std::unique_ptr<ObjectFactory<RuntimeInfo>>&& e) {
834 mObject->mRuntimeInfoFactory = std::move(e);
835 return *this;
836 }
837
setPropertyFetcher(std::unique_ptr<PropertyFetcher> && e)838 VintfObject::Builder& VintfObject::Builder::setPropertyFetcher(
839 std::unique_ptr<PropertyFetcher>&& e) {
840 mObject->mPropertyFetcher = std::move(e);
841 return *this;
842 }
843
build()844 std::unique_ptr<VintfObject> VintfObject::Builder::build() {
845 if (!mObject->mFileSystem) mObject->mFileSystem = createDefaultFileSystem();
846 if (!mObject->mRuntimeInfoFactory)
847 mObject->mRuntimeInfoFactory = std::make_unique<ObjectFactory<RuntimeInfo>>();
848 if (!mObject->mPropertyFetcher) mObject->mPropertyFetcher = createDefaultPropertyFetcher();
849 return std::move(mObject);
850 }
851
852 } // namespace vintf
853 } // namespace android
854