Add add all kernels from higher FCM version.

Before this change, when combining FCMs for target FCM version P, these
<kernel> tags are pulled in:
4.4-p, 4.9-p, 4.14-p, 4.19-q, 5.4-r

After this change, all these <kernel> tags are pulled in:
4.4-p, 4.9-p, 4.14-p, 4.9-q, 4.14-q, 4.19-q, 4.14-r, 5.4-r

KernelInfo.getMatchedKernelRequirements checks the appropriate kernel
requirements.

- For missing kernel FCM version (legacy behavior), check against
  4.4-p, 4.9-p, 4.14-p, 4.19-q
  (Note that 5.4-r and *-r+ is explicitly disallowed)
- For explicit kernel FCM version (new behavior), check against
  4.4-p, 4.9-p, 4.14-p, 4.9-q, 4.14-q, 4.14-r
  (all x.y-* where x.y-p exists)

KernelTest has explicit checks against the new behavior. Fix test by
allowing <kernel> from new matrices (e.g. 4.9-q) to be pulled in, then
add new tests for compatibility checks (i.e. 4.9-q cannot be used
without explicitly specifying kernel FCM version).

Bug: 139309488
Bug: 139308103

Test: libvintf_test
Test: vintf_object_test

Change-Id: Ia5d312e9b2ae0ad7a9d430801f41a0a78fb98f66
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index c6fa25e..a2ef873 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -45,13 +45,18 @@
 
     auto it = framework.mKernels.begin();
     for (; it != framework.mKernels.end(); ++it) {
+        if (it->getSourceMatrixLevel() != kernel.getSourceMatrixLevel()) {
+            continue;
+        }
         if (it->minLts() == kernel.minLts()) {
             break;
         }
         if (it->minLts().dropMinor() == kernel.minLts().dropMinor()) {
             if (error) {
-                *error = "Kernel version mismatch; cannot add " + to_string(kernel.minLts()) +
-                         " because " + to_string(it->minLts()) + " was added.";
+                *error = "Kernel version mismatch; for level " +
+                         to_string(kernel.getSourceMatrixLevel()) + ", cannot add " +
+                         to_string(kernel.minLts()) + " because " + to_string(it->minLts()) +
+                         " was added.";
             }
             return false;
         }
@@ -248,14 +253,7 @@
     return true;
 }
 
-// Merge Kernel.
-// Add <kernel> from exact "level", then optionally add <kernel> from high levels to low levels.
-// For example, (each letter is a kernel version x.y.z)
-// 1.xml: A1, B1
-// 2.xml: B2, C2, D2
-// 3.xml: D3, E3
-// Then the combined 1.xml should have
-// A1, B1 (from 1.xml, required), C2, D2, E3 (optional, use earliest possible).
+// Merge Kernel. See KernelInfo::getMatchedKernelRequirements for details on compatibility checks.
 bool CompatibilityMatrix::addAllKernels(CompatibilityMatrix* other, std::string* error) {
     for (MatrixKernel& kernel : other->framework.mKernels) {
         if (kernel.getSourceMatrixLevel() == Level::UNSPECIFIED) {
@@ -272,40 +270,6 @@
     return true;
 }
 
-bool CompatibilityMatrix::addAllKernelsAsOptional(CompatibilityMatrix* other, std::string* error) {
-    if (other == nullptr || other->level() <= level()) {
-        return true;
-    }
-
-    for (MatrixKernel& kernelToAdd : other->framework.mKernels) {
-        bool exists =
-            std::any_of(this->framework.mKernels.begin(), this->framework.mKernels.end(),
-                        [&kernelToAdd](const MatrixKernel& existing) {
-                            return kernelToAdd.minLts().version == existing.minLts().version &&
-                                   kernelToAdd.minLts().majorRev == existing.minLts().majorRev;
-                        });
-
-        if (exists) {
-            // Shouldn't retroactively add requirements to minLts(), so ignore this.
-            // This happens even when kernelToAdd.conditions() != existing.conditions().
-            continue;
-        }
-
-        if (kernelToAdd.getSourceMatrixLevel() == Level::UNSPECIFIED) {
-            kernelToAdd.setSourceMatrixLevel(other->level());
-        }
-
-        KernelVersion minLts = kernelToAdd.minLts();
-        if (!addKernel(std::move(kernelToAdd), error)) {
-            if (error) {
-                *error = "Cannot add " + to_string(minLts) + ": " + *error;
-            }
-            return false;
-        }
-    }
-    return true;
-}
-
 bool CompatibilityMatrix::addSepolicy(CompatibilityMatrix* other, std::string* error) {
     bool success = mergeField(&this->framework.mSepolicy, &other->framework.mSepolicy);
     if (!success && error) *error = "<sepolicy> is already defined";
@@ -445,7 +409,7 @@
                                            std::string* error) {
     if (!addAllHalsAsOptional(&inputMatrix->object, error) ||
         !addAllXmlFilesAsOptional(&inputMatrix->object, error) ||
-        !addAllKernelsAsOptional(&inputMatrix->object, error)) {
+        !addAllKernels(&inputMatrix->object, error)) {
         if (error) {
             *error = "File \"" + inputMatrix->name + "\" cannot be added: " + *error;
         }