diff options
author | android-build-team Robot | 2018-01-25 03:06:49 -0600 |
---|---|---|
committer | android-build-team Robot | 2018-01-25 03:06:49 -0600 |
commit | 47eb53deac8f7bf49b917876fa1a217bc2e9b314 (patch) | |
tree | e0aa07d3c030ecea387110f1be5f6513da4614a1 | |
parent | 8495faa84e01d388bc778c2abfebaa0e1172380a (diff) | |
parent | 281358e7139a4978ca552a79a35d234944039d7c (diff) | |
download | platform-system-libvintf-47eb53deac8f7bf49b917876fa1a217bc2e9b314.tar.gz platform-system-libvintf-47eb53deac8f7bf49b917876fa1a217bc2e9b314.tar.xz platform-system-libvintf-47eb53deac8f7bf49b917876fa1a217bc2e9b314.zip |
Snap for 4565898 from 281358e7139a4978ca552a79a35d234944039d7c to pi-release
Change-Id: I761e3c7e1cbcbf64740707c7eb4989c86aff1625
-rw-r--r-- | AssembleVintf.cpp | 36 | ||||
-rw-r--r-- | CompatibilityMatrix.cpp | 20 | ||||
-rw-r--r-- | VintfObject.cpp | 139 | ||||
-rw-r--r-- | include-test/vintf/AssembleVintf.h | 4 | ||||
-rw-r--r-- | include/vintf/CompatibilityMatrix.h | 2 | ||||
-rw-r--r-- | include/vintf/Version.h | 8 | ||||
-rw-r--r-- | include/vintf/VintfObject.h | 39 | ||||
-rw-r--r-- | parse_xml.cpp | 8 | ||||
-rw-r--r-- | test/Android.bp | 1 | ||||
-rw-r--r-- | test/AssembleVintfTest.cpp | 9 | ||||
-rw-r--r-- | test/LibVintfTest.cpp | 8 | ||||
-rw-r--r-- | test/vintf_object_tests.cpp | 192 |
12 files changed, 435 insertions, 31 deletions
diff --git a/AssembleVintf.cpp b/AssembleVintf.cpp index d17f1c5..8951471 100644 --- a/AssembleVintf.cpp +++ b/AssembleVintf.cpp | |||
@@ -108,7 +108,7 @@ class AssembleVintfImpl : public AssembleVintf { | |||
108 | * Set *out to environment variable if *out is not a dummy value (i.e. default constructed). | 108 | * Set *out to environment variable if *out is not a dummy value (i.e. default constructed). |
109 | */ | 109 | */ |
110 | template <typename T> | 110 | template <typename T> |
111 | bool getFlagIfUnset(const std::string& envKey, T* out) const { | 111 | bool getFlagIfUnset(const std::string& envKey, T* out, bool log = true) const { |
112 | bool hasExistingValue = !(*out == T{}); | 112 | bool hasExistingValue = !(*out == T{}); |
113 | 113 | ||
114 | bool hasEnvValue = false; | 114 | bool hasEnvValue = false; |
@@ -116,22 +116,26 @@ class AssembleVintfImpl : public AssembleVintf { | |||
116 | std::string envStrValue = getEnv(envKey); | 116 | std::string envStrValue = getEnv(envKey); |
117 | if (!envStrValue.empty()) { | 117 | if (!envStrValue.empty()) { |
118 | if (!parse(envStrValue, &envValue)) { | 118 | if (!parse(envStrValue, &envValue)) { |
119 | std::cerr << "Cannot parse " << envValue << "." << std::endl; | 119 | if (log) { |
120 | std::cerr << "Cannot parse " << envValue << "." << std::endl; | ||
121 | } | ||
120 | return false; | 122 | return false; |
121 | } | 123 | } |
122 | hasEnvValue = true; | 124 | hasEnvValue = true; |
123 | } | 125 | } |
124 | 126 | ||
125 | if (hasExistingValue) { | 127 | if (hasExistingValue) { |
126 | if (hasEnvValue) { | 128 | if (hasEnvValue && log) { |
127 | std::cerr << "Warning: cannot override existing value " << *out << " with " | 129 | std::cerr << "Warning: cannot override existing value " << *out << " with " |
128 | << envKey << " (which is " << envValue << ")." << std::endl; | 130 | << envKey << " (which is " << envValue << ")." << std::endl; |
129 | } | 131 | } |
130 | return false; | 132 | return false; |
131 | } | 133 | } |
132 | if (!hasEnvValue) { | 134 | if (!hasEnvValue) { |
133 | std::cerr << "Warning: " << envKey << " is not specified. Default to " << T{} << "." | 135 | if (log) { |
134 | << std::endl; | 136 | std::cerr << "Warning: " << envKey << " is not specified. Default to " << T{} << "." |
137 | << std::endl; | ||
138 | } | ||
135 | return false; | 139 | return false; |
136 | } | 140 | } |
137 | *out = envValue; | 141 | *out = envValue; |
@@ -353,8 +357,7 @@ class AssembleVintfImpl : public AssembleVintf { | |||
353 | return false; | 357 | return false; |
354 | } | 358 | } |
355 | for (ConditionedConfig& conditionedConfig : conditionedConfigs) { | 359 | for (ConditionedConfig& conditionedConfig : conditionedConfigs) { |
356 | MatrixKernel kernel(KernelVersion{pair.first.majorVer, pair.first.minorVer, 0u}, | 360 | MatrixKernel kernel(KernelVersion{pair.first}, std::move(conditionedConfig.second)); |
357 | std::move(conditionedConfig.second)); | ||
358 | if (conditionedConfig.first != nullptr) | 361 | if (conditionedConfig.first != nullptr) |
359 | kernel.mConditions.push_back(std::move(*conditionedConfig.first)); | 362 | kernel.mConditions.push_back(std::move(*conditionedConfig.first)); |
360 | matrix->framework.mKernels.push_back(std::move(kernel)); | 363 | matrix->framework.mKernels.push_back(std::move(kernel)); |
@@ -473,12 +476,15 @@ class AssembleVintfImpl : public AssembleVintf { | |||
473 | &matrix->framework.mSepolicy.mSepolicyVersionRanges; | 476 | &matrix->framework.mSepolicy.mSepolicyVersionRanges; |
474 | VersionRange sepolicyVr; | 477 | VersionRange sepolicyVr; |
475 | if (!sepolicyVrs->empty()) sepolicyVr = sepolicyVrs->front(); | 478 | if (!sepolicyVrs->empty()) sepolicyVr = sepolicyVrs->front(); |
476 | if (getFlagIfUnset("BOARD_SEPOLICY_VERS", &sepolicyVr)) { | 479 | if (getFlagIfUnset("BOARD_SEPOLICY_VERS", &sepolicyVr, |
480 | deviceLevel == Level::UNSPECIFIED /* log */)) { | ||
477 | *sepolicyVrs = {{sepolicyVr}}; | 481 | *sepolicyVrs = {{sepolicyVr}}; |
478 | } | 482 | } |
479 | 483 | ||
480 | getFlagIfUnset("POLICYVERS", &matrix->framework.mSepolicy.mKernelSepolicyVersion); | 484 | getFlagIfUnset("POLICYVERS", &matrix->framework.mSepolicy.mKernelSepolicyVersion, |
481 | getFlagIfUnset("FRAMEWORK_VBMETA_VERSION", &matrix->framework.mAvbMetaVersion); | 485 | deviceLevel == Level::UNSPECIFIED /* log */); |
486 | getFlagIfUnset("FRAMEWORK_VBMETA_VERSION", &matrix->framework.mAvbMetaVersion, | ||
487 | deviceLevel == Level::UNSPECIFIED /* log */); | ||
482 | 488 | ||
483 | out() << "<!--" << std::endl; | 489 | out() << "<!--" << std::endl; |
484 | out() << " Input:" << std::endl; | 490 | out() << " Input:" << std::endl; |
@@ -576,12 +582,12 @@ class AssembleVintfImpl : public AssembleVintf { | |||
576 | return *mCheckFile; | 582 | return *mCheckFile; |
577 | } | 583 | } |
578 | 584 | ||
579 | bool hasKernelVersion(const Version& kernelVer) const override { | 585 | bool hasKernelVersion(const KernelVersion& kernelVer) const override { |
580 | return mKernels.find(kernelVer) != mKernels.end(); | 586 | return mKernels.find(kernelVer) != mKernels.end(); |
581 | } | 587 | } |
582 | 588 | ||
583 | std::istream& addKernelConfigInputStream(const Version& kernelVer, const std::string& name, | 589 | std::istream& addKernelConfigInputStream(const KernelVersion& kernelVer, |
584 | Istream&& in) override { | 590 | const std::string& name, Istream&& in) override { |
585 | auto&& kernel = mKernels[kernelVer]; | 591 | auto&& kernel = mKernels[kernelVer]; |
586 | auto it = kernel.emplace(kernel.end(), name, std::move(in)); | 592 | auto it = kernel.emplace(kernel.end(), name, std::move(in)); |
587 | return it->stream(); | 593 | return it->stream(); |
@@ -614,7 +620,7 @@ class AssembleVintfImpl : public AssembleVintf { | |||
614 | Istream mCheckFile; | 620 | Istream mCheckFile; |
615 | bool mOutputMatrix = false; | 621 | bool mOutputMatrix = false; |
616 | SerializeFlags mSerializeFlags = SerializeFlag::EVERYTHING; | 622 | SerializeFlags mSerializeFlags = SerializeFlag::EVERYTHING; |
617 | std::map<Version, std::vector<NamedIstream>> mKernels; | 623 | std::map<KernelVersion, std::vector<NamedIstream>> mKernels; |
618 | std::map<std::string, std::string> mFakeEnv; | 624 | std::map<std::string, std::string> mFakeEnv; |
619 | }; | 625 | }; |
620 | 626 | ||
@@ -639,7 +645,7 @@ bool AssembleVintf::addKernel(const std::string& kernelArg) { | |||
639 | std::cerr << "Unrecognized --kernel option '" << kernelArg << "'" << std::endl; | 645 | std::cerr << "Unrecognized --kernel option '" << kernelArg << "'" << std::endl; |
640 | return false; | 646 | return false; |
641 | } | 647 | } |
642 | Version kernelVer; | 648 | KernelVersion kernelVer; |
643 | if (!parse(tokens.front(), &kernelVer)) { | 649 | if (!parse(tokens.front(), &kernelVer)) { |
644 | std::cerr << "Unrecognized kernel version '" << tokens.front() << "'" << std::endl; | 650 | std::cerr << "Unrecognized kernel version '" << tokens.front() << "'" << std::endl; |
645 | return false; | 651 | return false; |
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp index d3c4ebf..00e4d14 100644 --- a/CompatibilityMatrix.cpp +++ b/CompatibilityMatrix.cpp | |||
@@ -96,6 +96,10 @@ std::pair<MatrixHal*, VersionRange*> CompatibilityMatrix::getHalWithMajorVersion | |||
96 | } | 96 | } |
97 | return {nullptr, nullptr}; | 97 | return {nullptr, nullptr}; |
98 | } | 98 | } |
99 | std::pair<const MatrixHal*, const VersionRange*> CompatibilityMatrix::getHalWithMajorVersion( | ||
100 | const std::string& name, size_t majorVer) const { | ||
101 | return const_cast<CompatibilityMatrix*>(this)->getHalWithMajorVersion(name, majorVer); | ||
102 | } | ||
99 | 103 | ||
100 | bool CompatibilityMatrix::addAllHalsAsOptional(CompatibilityMatrix* other, std::string* error) { | 104 | bool CompatibilityMatrix::addAllHalsAsOptional(CompatibilityMatrix* other, std::string* error) { |
101 | if (other == nullptr || other->level() <= level()) { | 105 | if (other == nullptr || other->level() <= level()) { |
@@ -290,6 +294,22 @@ CompatibilityMatrix* CompatibilityMatrix::combine(Level deviceLevel, | |||
290 | } | 294 | } |
291 | } | 295 | } |
292 | 296 | ||
297 | for (auto& e : *matrices) { | ||
298 | if (&e.object != matrix && e.object.level() == deviceLevel && | ||
299 | e.object.type() == SchemaType::FRAMEWORK) { | ||
300 | for (MatrixKernel& kernel : e.object.framework.mKernels) { | ||
301 | KernelVersion ver = kernel.minLts(); | ||
302 | if (!matrix->add(std::move(kernel))) { | ||
303 | if (error) { | ||
304 | *error = "Cannot add kernel version " + to_string(ver) + | ||
305 | " from FCM version " + to_string(deviceLevel); | ||
306 | } | ||
307 | return nullptr; | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | } | ||
312 | |||
293 | return matrix; | 313 | return matrix; |
294 | } | 314 | } |
295 | 315 | ||
diff --git a/VintfObject.cpp b/VintfObject.cpp index 90b446d..7c55181 100644 --- a/VintfObject.cpp +++ b/VintfObject.cpp | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "VintfObject.h" | 17 | #include "VintfObject.h" |
18 | 18 | ||
19 | #include "CompatibilityMatrix.h" | 19 | #include "CompatibilityMatrix.h" |
20 | #include "parse_string.h" | ||
20 | #include "parse_xml.h" | 21 | #include "parse_xml.h" |
21 | #include "utils.h" | 22 | #include "utils.h" |
22 | 23 | ||
@@ -567,6 +568,144 @@ int32_t VintfObject::CheckCompatibility(const std::vector<std::string>& xmls, st | |||
567 | disabledChecks); | 568 | disabledChecks); |
568 | } | 569 | } |
569 | 570 | ||
571 | bool VintfObject::isHalDeprecated(const MatrixHal& oldMatrixHal, | ||
572 | const CompatibilityMatrix& targetMatrix, | ||
573 | const IsInstanceInUse& isInstanceInUse, std::string* error) { | ||
574 | for (const VersionRange& range : oldMatrixHal.versionRanges) { | ||
575 | for (const HalInterface& interface : iterateValues(oldMatrixHal.interfaces)) { | ||
576 | for (const std::string& instance : interface.instances) { | ||
577 | if (isInstanceDeprecated(oldMatrixHal.name, range.minVer(), interface.name, | ||
578 | instance, targetMatrix, isInstanceInUse, error)) { | ||
579 | return true; | ||
580 | } | ||
581 | } | ||
582 | } | ||
583 | } | ||
584 | return false; | ||
585 | } | ||
586 | |||
587 | // If isInstanceInUse(package@x.y::interface/instance), return true iff: | ||
588 | // 1. package@x.?::interface/instance is not in targetMatrix; OR | ||
589 | // 2. package@x.z::interface/instance is in targetMatrix but | ||
590 | // !isInstanceInUse(package@x.z::interface/instance) | ||
591 | bool VintfObject::isInstanceDeprecated(const std::string& package, Version version, | ||
592 | const std::string& interface, const std::string& instance, | ||
593 | const CompatibilityMatrix& targetMatrix, | ||
594 | const IsInstanceInUse& isInstanceInUse, | ||
595 | std::string* error) { | ||
596 | bool oldVersionIsServed; | ||
597 | Version servedVersion; | ||
598 | std::tie(oldVersionIsServed, servedVersion) = | ||
599 | isInstanceInUse(package, version, interface, instance); | ||
600 | if (oldVersionIsServed) { | ||
601 | // Find any package@x.? in target matrix, and check if instance is in target matrix. | ||
602 | const MatrixHal* targetMatrixHal; | ||
603 | const VersionRange* targetMatrixRange; | ||
604 | std::tie(targetMatrixHal, targetMatrixRange) = | ||
605 | targetMatrix.getHalWithMajorVersion(package, version.majorVer); | ||
606 | if (targetMatrixHal == nullptr || targetMatrixRange == nullptr) { | ||
607 | if (error) { | ||
608 | *error = package + "@" + to_string(servedVersion) + | ||
609 | "is deprecated in compatibility matrix at FCM Version " + | ||
610 | to_string(targetMatrix.level()) + "; it should not be served."; | ||
611 | } | ||
612 | return true; | ||
613 | } | ||
614 | |||
615 | const auto& targetMatrixInstances = targetMatrixHal->getInstances(interface); | ||
616 | if (targetMatrixInstances.find(instance) == targetMatrixInstances.end()) { | ||
617 | if (error) { | ||
618 | *error += package + "@" + to_string(servedVersion) + "::" + interface + "/" + | ||
619 | instance + " is deprecated at FCM version " + | ||
620 | to_string(targetMatrix.level()) + "; it should be not be served.\n"; | ||
621 | } | ||
622 | return true; | ||
623 | } | ||
624 | |||
625 | // Assuming that targetMatrix requires @x.u-v, require that at least @x.u is served. | ||
626 | bool targetVersionServed; | ||
627 | std::tie(targetVersionServed, std::ignore) = | ||
628 | isInstanceInUse(package, targetMatrixRange->minVer(), interface, instance); | ||
629 | |||
630 | if (!targetVersionServed) { | ||
631 | if (error) { | ||
632 | *error += package + "@" + to_string(servedVersion) + " is deprecated; " + | ||
633 | "require at least " + to_string(targetMatrixRange->minVer()) + "\n"; | ||
634 | } | ||
635 | return true; | ||
636 | } | ||
637 | } | ||
638 | return false; | ||
639 | } | ||
640 | |||
641 | int32_t VintfObject::CheckDeprecation(const IsInstanceInUse& isInstanceInUse, | ||
642 | std::string* error) { | ||
643 | auto matrixFragments = GetAllFrameworkMatrixLevels(error); | ||
644 | if (matrixFragments.empty()) { | ||
645 | if (error && error->empty()) | ||
646 | *error = "Cannot get framework matrix for each FCM version for unknown error."; | ||
647 | return NAME_NOT_FOUND; | ||
648 | } | ||
649 | auto deviceManifest = GetDeviceHalManifest(); | ||
650 | if (deviceManifest == nullptr) { | ||
651 | if (error) *error = "No device manifest."; | ||
652 | return NAME_NOT_FOUND; | ||
653 | } | ||
654 | Level deviceLevel = deviceManifest->level(); | ||
655 | if (deviceLevel == Level::UNSPECIFIED) { | ||
656 | if (error) *error = "Device manifest does not specify Shipping FCM Version."; | ||
657 | return BAD_VALUE; | ||
658 | } | ||
659 | |||
660 | const CompatibilityMatrix* targetMatrix = nullptr; | ||
661 | for (const auto& namedMatrix : matrixFragments) { | ||
662 | if (namedMatrix.object.level() == deviceLevel) { | ||
663 | targetMatrix = &namedMatrix.object; | ||
664 | } | ||
665 | } | ||
666 | if (targetMatrix == nullptr) { | ||
667 | if (error) | ||
668 | *error = "Cannot find framework matrix at FCM version " + to_string(deviceLevel) + "."; | ||
669 | return NAME_NOT_FOUND; | ||
670 | } | ||
671 | |||
672 | bool hasDeprecatedHals = false; | ||
673 | for (const auto& namedMatrix : matrixFragments) { | ||
674 | if (namedMatrix.object.level() == Level::UNSPECIFIED) continue; | ||
675 | if (namedMatrix.object.level() >= deviceLevel) continue; | ||
676 | |||
677 | const auto& oldMatrix = namedMatrix.object; | ||
678 | for (const MatrixHal& hal : oldMatrix.getHals()) { | ||
679 | hasDeprecatedHals |= isHalDeprecated(hal, *targetMatrix, isInstanceInUse, error); | ||
680 | } | ||
681 | } | ||
682 | |||
683 | return hasDeprecatedHals ? DEPRECATED : NO_DEPRECATED_HALS; | ||
684 | } | ||
685 | |||
686 | int32_t VintfObject::CheckDeprecation(std::string* error) { | ||
687 | auto deviceManifest = GetDeviceHalManifest(); | ||
688 | IsInstanceInUse inManifest = [&deviceManifest](const std::string& package, Version version, | ||
689 | const std::string& interface, | ||
690 | const std::string& instance) { | ||
691 | const ManifestHal* hal = deviceManifest->getHal(package, version); | ||
692 | if (hal == nullptr) { | ||
693 | return std::make_pair(false, Version{}); | ||
694 | } | ||
695 | const auto& instances = hal->getInstances(interface); | ||
696 | if (instances.find(instance) == instances.end()) { | ||
697 | return std::make_pair(false, Version{}); | ||
698 | } | ||
699 | |||
700 | for (Version v : hal->versions) { | ||
701 | if (v.minorAtLeast(version)) { | ||
702 | return std::make_pair(true, v); | ||
703 | } | ||
704 | } | ||
705 | return std::make_pair(false, Version{}); | ||
706 | }; | ||
707 | return CheckDeprecation(inManifest, error); | ||
708 | } | ||
570 | 709 | ||
571 | } // namespace vintf | 710 | } // namespace vintf |
572 | } // namespace android | 711 | } // namespace android |
diff --git a/include-test/vintf/AssembleVintf.h b/include-test/vintf/AssembleVintf.h index 1b457eb..ac6d2af 100644 --- a/include-test/vintf/AssembleVintf.h +++ b/include-test/vintf/AssembleVintf.h | |||
@@ -49,12 +49,12 @@ class AssembleVintf { | |||
49 | virtual std::ostream& setOutputStream(Ostream&&) = 0; | 49 | virtual std::ostream& setOutputStream(Ostream&&) = 0; |
50 | virtual std::istream& addInputStream(const std::string& name, Istream&&) = 0; | 50 | virtual std::istream& addInputStream(const std::string& name, Istream&&) = 0; |
51 | virtual std::istream& setCheckInputStream(Istream&&) = 0; | 51 | virtual std::istream& setCheckInputStream(Istream&&) = 0; |
52 | virtual std::istream& addKernelConfigInputStream(const Version& kernelVer, | 52 | virtual std::istream& addKernelConfigInputStream(const KernelVersion& kernelVer, |
53 | const std::string& name, Istream&& in) = 0; | 53 | const std::string& name, Istream&& in) = 0; |
54 | virtual void setFakeEnv(const std::string& key, const std::string& value) = 0; | 54 | virtual void setFakeEnv(const std::string& key, const std::string& value) = 0; |
55 | 55 | ||
56 | protected: | 56 | protected: |
57 | virtual bool hasKernelVersion(const Version&) const = 0; | 57 | virtual bool hasKernelVersion(const KernelVersion&) const = 0; |
58 | virtual std::string getEnv(const std::string& key) const = 0; | 58 | virtual std::string getEnv(const std::string& key) const = 0; |
59 | }; | 59 | }; |
60 | 60 | ||
diff --git a/include/vintf/CompatibilityMatrix.h b/include/vintf/CompatibilityMatrix.h index 696a0bf..1b35d2d 100644 --- a/include/vintf/CompatibilityMatrix.h +++ b/include/vintf/CompatibilityMatrix.h | |||
@@ -71,6 +71,8 @@ struct CompatibilityMatrix : public HalGroup<MatrixHal>, public XmlFileGroup<Mat | |||
71 | // Return nullptr if none is found. | 71 | // Return nullptr if none is found. |
72 | std::pair<MatrixHal*, VersionRange*> getHalWithMajorVersion(const std::string& name, | 72 | std::pair<MatrixHal*, VersionRange*> getHalWithMajorVersion(const std::string& name, |
73 | size_t majorVer); | 73 | size_t majorVer); |
74 | std::pair<const MatrixHal*, const VersionRange*> getHalWithMajorVersion(const std::string& name, | ||
75 | size_t majorVer) const; | ||
74 | // Similar to addAllHalsAsOptional but on <xmlfile> entries. | 76 | // Similar to addAllHalsAsOptional but on <xmlfile> entries. |
75 | bool addAllXmlFilesAsOptional(CompatibilityMatrix* other, std::string* error); | 77 | bool addAllXmlFilesAsOptional(CompatibilityMatrix* other, std::string* error); |
76 | 78 | ||
diff --git a/include/vintf/Version.h b/include/vintf/Version.h index 0f38391..5fab0fa 100644 --- a/include/vintf/Version.h +++ b/include/vintf/Version.h | |||
@@ -82,6 +82,14 @@ struct KernelVersion { | |||
82 | inline bool operator!=(const KernelVersion &other) const { | 82 | inline bool operator!=(const KernelVersion &other) const { |
83 | return !((*this) == other); | 83 | return !((*this) == other); |
84 | } | 84 | } |
85 | |||
86 | inline bool operator<(const KernelVersion& other) const { | ||
87 | if (version < other.version) return true; | ||
88 | if (version > other.version) return false; | ||
89 | if (majorRev < other.majorRev) return true; | ||
90 | if (majorRev > other.majorRev) return false; | ||
91 | return minorRev < other.minorRev; | ||
92 | } | ||
85 | }; | 93 | }; |
86 | 94 | ||
87 | } // namespace vintf | 95 | } // namespace vintf |
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h index 06ccd00..656b2b8 100644 --- a/include/vintf/VintfObject.h +++ b/include/vintf/VintfObject.h | |||
@@ -112,6 +112,34 @@ public: | |||
112 | std::string* error = nullptr, | 112 | std::string* error = nullptr, |
113 | DisabledChecks disabledChecks = ENABLE_ALL_CHECKS); | 113 | DisabledChecks disabledChecks = ENABLE_ALL_CHECKS); |
114 | 114 | ||
115 | using IsInstanceInUse = std::function<std::pair<bool, Version>( | ||
116 | const std::string& package, Version version, const std::string& interface, | ||
117 | const std::string& instance)>; | ||
118 | /** | ||
119 | * Check deprecation on framework matrices with a provided predicate. | ||
120 | * | ||
121 | * @param isInstanceInUse predicate that takes parameter in this format: | ||
122 | * android.hardware.foo@1.0::IFoo/instance | ||
123 | * and returns {true, version} if HAL is in use, where version = | ||
124 | * first version in interfaceChain where package + major version matches. | ||
125 | * | ||
126 | * @return = 0 if success (no deprecated HALs) | ||
127 | * > 0 if there is at least one deprecated HAL | ||
128 | * < 0 if any error (mount partition fails, illformed XML, etc.) | ||
129 | */ | ||
130 | static int32_t CheckDeprecation(const IsInstanceInUse& isInstanceInUse, | ||
131 | std::string* error = nullptr); | ||
132 | |||
133 | /** | ||
134 | * Check deprecation on existing VINTF metadata. Use Device Manifest as the | ||
135 | * predicate to check if a HAL is in use. | ||
136 | * | ||
137 | * @return = 0 if success (no deprecated HALs) | ||
138 | * > 0 if there is at least one deprecated HAL | ||
139 | * < 0 if any error (mount partition fails, illformed XML, etc.) | ||
140 | */ | ||
141 | static int32_t CheckDeprecation(std::string* error = nullptr); | ||
142 | |||
115 | private: | 143 | private: |
116 | static status_t GetCombinedFrameworkMatrix( | 144 | static status_t GetCombinedFrameworkMatrix( |
117 | const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out, | 145 | const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out, |
@@ -123,11 +151,22 @@ public: | |||
123 | static status_t FetchOdmHalManifest(HalManifest* out, std::string* error = nullptr); | 151 | static status_t FetchOdmHalManifest(HalManifest* out, std::string* error = nullptr); |
124 | static status_t FetchOneHalManifest(const std::string& path, HalManifest* out, | 152 | static status_t FetchOneHalManifest(const std::string& path, HalManifest* out, |
125 | std::string* error = nullptr); | 153 | std::string* error = nullptr); |
154 | |||
155 | static bool isHalDeprecated(const MatrixHal& oldMatrixHal, | ||
156 | const CompatibilityMatrix& targetMatrix, | ||
157 | const IsInstanceInUse& isInstanceInUse, std::string* error); | ||
158 | static bool isInstanceDeprecated(const std::string& package, Version version, | ||
159 | const std::string& interface, const std::string& instance, | ||
160 | const CompatibilityMatrix& targetMatrix, | ||
161 | const IsInstanceInUse& isInstanceInUse, std::string* error); | ||
126 | }; | 162 | }; |
127 | 163 | ||
128 | enum : int32_t { | 164 | enum : int32_t { |
129 | COMPATIBLE = 0, | 165 | COMPATIBLE = 0, |
130 | INCOMPATIBLE = 1, | 166 | INCOMPATIBLE = 1, |
167 | |||
168 | NO_DEPRECATED_HALS = 0, | ||
169 | DEPRECATED = 1, | ||
131 | }; | 170 | }; |
132 | 171 | ||
133 | // exposed for testing and VintfObjectRecovery. | 172 | // exposed for testing and VintfObjectRecovery. |
diff --git a/parse_xml.cpp b/parse_xml.cpp index 74ba880..5900f27 100644 --- a/parse_xml.cpp +++ b/parse_xml.cpp | |||
@@ -954,10 +954,14 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri | |||
954 | appendChildren(root, matrixKernelConverter, m.framework.mKernels, d); | 954 | appendChildren(root, matrixKernelConverter, m.framework.mKernels, d); |
955 | } | 955 | } |
956 | if (!(flags & SerializeFlag::NO_SEPOLICY)) { | 956 | if (!(flags & SerializeFlag::NO_SEPOLICY)) { |
957 | appendChild(root, sepolicyConverter(m.framework.mSepolicy, d)); | 957 | if (!(m.framework.mSepolicy == Sepolicy{})) { |
958 | appendChild(root, sepolicyConverter(m.framework.mSepolicy, d)); | ||
959 | } | ||
958 | } | 960 | } |
959 | if (!(flags & SerializeFlag::NO_AVB)) { | 961 | if (!(flags & SerializeFlag::NO_AVB)) { |
960 | appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d)); | 962 | if (!(m.framework.mAvbMetaVersion == Version{})) { |
963 | appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d)); | ||
964 | } | ||
961 | } | 965 | } |
962 | } else if (m.mType == SchemaType::DEVICE) { | 966 | } else if (m.mType == SchemaType::DEVICE) { |
963 | if (!(flags & SerializeFlag::NO_VNDK)) { | 967 | if (!(flags & SerializeFlag::NO_VNDK)) { |
diff --git a/test/Android.bp b/test/Android.bp index 540298a..d2121c6 100644 --- a/test/Android.bp +++ b/test/Android.bp | |||
@@ -63,6 +63,7 @@ cc_test { | |||
63 | static_libs: [ | 63 | static_libs: [ |
64 | "libgtest", | 64 | "libgtest", |
65 | "libgmock", | 65 | "libgmock", |
66 | "libhidl-gen-utils", | ||
66 | "libvintftest", | 67 | "libvintftest", |
67 | ], | 68 | ], |
68 | cflags: [ | 69 | cflags: [ |
diff --git a/test/AssembleVintfTest.cpp b/test/AssembleVintfTest.cpp index 912a11d..64dfc3e 100644 --- a/test/AssembleVintfTest.cpp +++ b/test/AssembleVintfTest.cpp | |||
@@ -77,11 +77,12 @@ TEST_F(AssembleVintfTest, FrameworkMatrixEmpty) { | |||
77 | {"BOARD_SEPOLICY_VERS", "10000.0"}, | 77 | {"BOARD_SEPOLICY_VERS", "10000.0"}, |
78 | {"FRAMEWORK_VBMETA_VERSION", "1.0"}, | 78 | {"FRAMEWORK_VBMETA_VERSION", "1.0"}, |
79 | }); | 79 | }); |
80 | getInstance()->addKernelConfigInputStream({3, 18}, "android-base.cfg", makeStream(kernel318)); | 80 | getInstance()->addKernelConfigInputStream({3, 18, 0}, "android-base.cfg", |
81 | getInstance()->addKernelConfigInputStream({3, 18}, "android-base-arm64.cfg", | 81 | makeStream(kernel318)); |
82 | getInstance()->addKernelConfigInputStream({3, 18, 0}, "android-base-arm64.cfg", | ||
82 | makeStream(kernel318_64)); | 83 | makeStream(kernel318_64)); |
83 | getInstance()->addKernelConfigInputStream({4, 4}, "android-base.cfg", makeStream(kernel44)); | 84 | getInstance()->addKernelConfigInputStream({4, 4, 0}, "android-base.cfg", makeStream(kernel44)); |
84 | getInstance()->addKernelConfigInputStream({4, 4}, "android-base-arm64.cfg", | 85 | getInstance()->addKernelConfigInputStream({4, 4, 0}, "android-base-arm64.cfg", |
85 | makeStream(kernel44_64)); | 86 | makeStream(kernel44_64)); |
86 | 87 | ||
87 | EXPECT_TRUE(getInstance()->assemble()); | 88 | EXPECT_TRUE(getInstance()->assemble()); |
diff --git a/test/LibVintfTest.cpp b/test/LibVintfTest.cpp index d705243..e7a609a 100644 --- a/test/LibVintfTest.cpp +++ b/test/LibVintfTest.cpp | |||
@@ -1355,15 +1355,9 @@ TEST_F(LibVintfTest, HalManifestConverterXmlFile) { | |||
1355 | TEST_F(LibVintfTest, CompatibilityMatrixConverterXmlFile) { | 1355 | TEST_F(LibVintfTest, CompatibilityMatrixConverterXmlFile) { |
1356 | CompatibilityMatrix cm; | 1356 | CompatibilityMatrix cm; |
1357 | addXmlFile(cm, "media_profile", {1, 0}); | 1357 | addXmlFile(cm, "media_profile", {1, 0}); |
1358 | std::string xml = gCompatibilityMatrixConverter(cm); | 1358 | std::string xml = gCompatibilityMatrixConverter(cm, SerializeFlag::XMLFILES_ONLY); |
1359 | EXPECT_EQ(xml, | 1359 | EXPECT_EQ(xml, |
1360 | "<compatibility-matrix version=\"1.0\" type=\"framework\">\n" | 1360 | "<compatibility-matrix version=\"1.0\" type=\"framework\">\n" |
1361 | " <sepolicy>\n" | ||
1362 | " <kernel-sepolicy-version>0</kernel-sepolicy-version>\n" | ||
1363 | " </sepolicy>\n" | ||
1364 | " <avb>\n" | ||
1365 | " <vbmeta-version>0.0</vbmeta-version>\n" | ||
1366 | " </avb>\n" | ||
1367 | " <xmlfile format=\"dtd\" optional=\"true\">\n" | 1361 | " <xmlfile format=\"dtd\" optional=\"true\">\n" |
1368 | " <name>media_profile</name>\n" | 1362 | " <name>media_profile</name>\n" |
1369 | " <version>1.0</version>\n" | 1363 | " <version>1.0</version>\n" |
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp index f75baa3..659bd2b 100644 --- a/test/vintf_object_tests.cpp +++ b/test/vintf_object_tests.cpp | |||
@@ -25,13 +25,19 @@ | |||
25 | #include <android-base/properties.h> | 25 | #include <android-base/properties.h> |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | #include <android-base/strings.h> | ||
29 | #include <vintf/VintfObject.h> | ||
30 | #include <vintf/parse_string.h> | ||
28 | #include "utils-fake.h" | 31 | #include "utils-fake.h" |
29 | #include "vintf/VintfObject.h" | 32 | |
33 | #include <hidl-util/FQName.h> | ||
30 | 34 | ||
31 | using namespace ::testing; | 35 | using namespace ::testing; |
32 | using namespace ::android::vintf; | 36 | using namespace ::android::vintf; |
33 | using namespace ::android::vintf::details; | 37 | using namespace ::android::vintf::details; |
34 | 38 | ||
39 | using android::FQName; | ||
40 | |||
35 | // | 41 | // |
36 | // Set of Xml1 metadata compatible with each other. | 42 | // Set of Xml1 metadata compatible with each other. |
37 | // | 43 | // |
@@ -167,6 +173,59 @@ const std::string vendorManifestXml2 = | |||
167 | " </sepolicy>\n" | 173 | " </sepolicy>\n" |
168 | "</manifest>"; | 174 | "</manifest>"; |
169 | 175 | ||
176 | // | ||
177 | // Set of framework matrices of different FCM version. | ||
178 | // | ||
179 | |||
180 | const std::string systemMatrixLevel1 = | ||
181 | "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n" | ||
182 | " <hal format=\"hidl\" optional=\"true\">\n" | ||
183 | " <name>android.hardware.major</name>\n" | ||
184 | " <version>1.0</version>\n" | ||
185 | " <interface>\n" | ||
186 | " <name>IMajor</name>\n" | ||
187 | " <instance>default</instance>\n" | ||
188 | " </interface>\n" | ||
189 | " </hal>\n" | ||
190 | " <hal format=\"hidl\" optional=\"true\">\n" | ||
191 | " <name>android.hardware.removed</name>\n" | ||
192 | " <version>1.0</version>\n" | ||
193 | " <interface>\n" | ||
194 | " <name>IRemoved</name>\n" | ||
195 | " <instance>default</instance>\n" | ||
196 | " </interface>\n" | ||
197 | " </hal>\n" | ||
198 | " <hal format=\"hidl\" optional=\"true\">\n" | ||
199 | " <name>android.hardware.minor</name>\n" | ||
200 | " <version>1.0</version>\n" | ||
201 | " <interface>\n" | ||
202 | " <name>IMinor</name>\n" | ||
203 | " <instance>default</instance>\n" | ||
204 | " <instance>legacy</instance>\n" | ||
205 | " </interface>\n" | ||
206 | " </hal>\n" | ||
207 | "</compatibility-matrix>\n"; | ||
208 | |||
209 | const std::string systemMatrixLevel2 = | ||
210 | "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"2\">\n" | ||
211 | " <hal format=\"hidl\" optional=\"true\">\n" | ||
212 | " <name>android.hardware.major</name>\n" | ||
213 | " <version>2.0</version>\n" | ||
214 | " <interface>\n" | ||
215 | " <name>IMajor</name>\n" | ||
216 | " <instance>default</instance>\n" | ||
217 | " </interface>\n" | ||
218 | " </hal>\n" | ||
219 | " <hal format=\"hidl\" optional=\"true\">\n" | ||
220 | " <name>android.hardware.minor</name>\n" | ||
221 | " <version>1.1</version>\n" | ||
222 | " <interface>\n" | ||
223 | " <name>IMinor</name>\n" | ||
224 | " <instance>default</instance>\n" | ||
225 | " </interface>\n" | ||
226 | " </hal>\n" | ||
227 | "</compatibility-matrix>\n"; | ||
228 | |||
170 | // Setup the MockFileFetcher used by the fetchAllInformation template | 229 | // Setup the MockFileFetcher used by the fetchAllInformation template |
171 | // so it returns the given metadata info instead of fetching from device. | 230 | // so it returns the given metadata info instead of fetching from device. |
172 | void setupMockFetcher(const std::string& vendorManifestXml, const std::string& systemMatrixXml, | 231 | void setupMockFetcher(const std::string& vendorManifestXml, const std::string& systemMatrixXml, |
@@ -776,6 +835,137 @@ TEST_F(OdmManifestTest, OdmLegacyManifest) { | |||
776 | EXPECT_TRUE(containsOdmManifest(p)); | 835 | EXPECT_TRUE(containsOdmManifest(p)); |
777 | } | 836 | } |
778 | 837 | ||
838 | struct FQInstance { | ||
839 | FQName fqName; | ||
840 | std::string instance; | ||
841 | |||
842 | FQInstance(const char* s) : FQInstance(std::string(s)) {} | ||
843 | FQInstance(const std::string& s) { | ||
844 | auto tokens = android::base::Split(s, "/"); | ||
845 | CHECK(2u == tokens.size()); | ||
846 | fqName = FQName(tokens[0]); | ||
847 | CHECK(fqName.isValid()); | ||
848 | instance = tokens[1]; | ||
849 | } | ||
850 | |||
851 | Version getVersion() const { | ||
852 | return Version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()}; | ||
853 | } | ||
854 | }; | ||
855 | |||
856 | class DeprecateTest : public VintfObjectTestBase { | ||
857 | protected: | ||
858 | virtual void SetUp() override { | ||
859 | EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _)) | ||
860 | .WillRepeatedly(Invoke([](const auto&, auto* out, auto*) { | ||
861 | *out = { | ||
862 | "compatibility_matrix.1.xml", | ||
863 | "compatibility_matrix.2.xml", | ||
864 | }; | ||
865 | return ::android::OK; | ||
866 | })); | ||
867 | expectFetch(kSystemVintfDir + "compatibility_matrix.1.xml", systemMatrixLevel1); | ||
868 | expectFetch(kSystemVintfDir + "compatibility_matrix.2.xml", systemMatrixLevel2); | ||
869 | expectSystemMatrix(0); | ||
870 | |||
871 | expectFetch(kVendorManifest, | ||
872 | "<manifest version=\"1.0\" type=\"device\" target-level=\"2\"/>"); | ||
873 | expectFileNotExist(StartsWith("/odm/")); | ||
874 | |||
875 | // Update the device manifest cache because CheckDeprecate does not fetch | ||
876 | // device manifest again if cache exist. | ||
877 | VintfObject::GetDeviceHalManifest(true /* skipCache */); | ||
878 | } | ||
879 | |||
880 | VintfObject::IsInstanceInUse getPredicate(const std::vector<FQInstance>& instances) { | ||
881 | return [instances](const std::string& package, Version version, | ||
882 | const std::string& interface, const std::string& instance) { | ||
883 | for (auto&& existing : instances) { | ||
884 | if (existing.fqName.package() == package && | ||
885 | existing.getVersion().minorAtLeast(version) && | ||
886 | existing.fqName.name() == interface && existing.instance == instance) { | ||
887 | return std::make_pair(true, existing.getVersion()); | ||
888 | } | ||
889 | } | ||
890 | |||
891 | return std::make_pair(false, Version{}); | ||
892 | }; | ||
893 | } | ||
894 | }; | ||
895 | |||
896 | TEST_F(DeprecateTest, CheckNoDeprecate) { | ||
897 | auto pred = getPredicate({ | ||
898 | "android.hardware.minor@1.1::IMinor/default", | ||
899 | "android.hardware.major@2.0::IMajor/default", | ||
900 | }); | ||
901 | std::string error; | ||
902 | EXPECT_EQ(NO_DEPRECATED_HALS, VintfObject::CheckDeprecation(pred, &error)) << error; | ||
903 | } | ||
904 | |||
905 | TEST_F(DeprecateTest, CheckRemoved) { | ||
906 | auto pred = getPredicate({ | ||
907 | "android.hardware.removed@1.0::IRemoved/default", | ||
908 | "android.hardware.minor@1.1::IMinor/default", | ||
909 | "android.hardware.major@2.0::IMajor/default", | ||
910 | }); | ||
911 | std::string error; | ||
912 | EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error)) | ||
913 | << "removed@1.0 should be deprecated. " << error; | ||
914 | } | ||
915 | |||
916 | TEST_F(DeprecateTest, CheckMinor) { | ||
917 | auto pred = getPredicate({ | ||
918 | "android.hardware.minor@1.0::IMinor/default", | ||
919 | "android.hardware.major@2.0::IMajor/default", | ||
920 | }); | ||
921 | std::string error; | ||
922 | EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error)) | ||
923 | << "minor@1.0 should be deprecated. " << error; | ||
924 | } | ||
925 | |||
926 | TEST_F(DeprecateTest, CheckMinorDeprecatedInstance1) { | ||
927 | auto pred = getPredicate({ | ||
928 | "android.hardware.minor@1.0::IMinor/legacy", | ||
929 | "android.hardware.minor@1.1::IMinor/default", | ||
930 | "android.hardware.major@2.0::IMajor/default", | ||
931 | }); | ||
932 | std::string error; | ||
933 | EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error)) | ||
934 | << "minor@1.0::IMinor/legacy should be deprecated. " << error; | ||
935 | } | ||
936 | |||
937 | TEST_F(DeprecateTest, CheckMinorDeprecatedInstance2) { | ||
938 | auto pred = getPredicate({ | ||
939 | "android.hardware.minor@1.1::IMinor/default", | ||
940 | "android.hardware.minor@1.1::IMinor/legacy", | ||
941 | "android.hardware.major@2.0::IMajor/default", | ||
942 | }); | ||
943 | std::string error; | ||
944 | EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error)) | ||
945 | << "minor@1.1::IMinor/legacy should be deprecated. " << error; | ||
946 | } | ||
947 | |||
948 | TEST_F(DeprecateTest, CheckMajor1) { | ||
949 | auto pred = getPredicate({ | ||
950 | "android.hardware.minor@1.1::IMinor/default", | ||
951 | "android.hardware.major@1.0::IMajor/default", | ||
952 | "android.hardware.major@2.0::IMajor/default", | ||
953 | }); | ||
954 | std::string error; | ||
955 | EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error)) | ||
956 | << "major@1.0 should be deprecated. " << error; | ||
957 | } | ||
958 | |||
959 | TEST_F(DeprecateTest, CheckMajor2) { | ||
960 | auto pred = getPredicate({ | ||
961 | "android.hardware.minor@1.1::IMinor/default", | ||
962 | "android.hardware.major@1.0::IMajor/default", | ||
963 | }); | ||
964 | std::string error; | ||
965 | EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error)) | ||
966 | << "major@1.0 should be deprecated. " << error; | ||
967 | } | ||
968 | |||
779 | int main(int argc, char** argv) { | 969 | int main(int argc, char** argv) { |
780 | ::testing::InitGoogleMock(&argc, argv); | 970 | ::testing::InitGoogleMock(&argc, argv); |
781 | 971 | ||