Combines FCMs with the same device level before checking deprecation.

This allows product / system_ext FCMs to specify level, which are
combined with the framework FCM when checking deprecation.

Bug: 183507590
Test: atest vintf_object_test
Test: Create a product FCM with level="5". Place this FCM and a current
      product FCM on a system-half build. Merge this build with a
      vendor-half build from R. Observe checkvintf success.
Change-Id: Ic6dc1a8eea988ddaddccf0fb5cf35a649bfe0f11
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 2627c80..2ef4e79 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -861,17 +861,24 @@
         return BAD_VALUE;
     }
 
-    const CompatibilityMatrix* targetMatrix = nullptr;
-    for (const auto& namedMatrix : matrixFragments) {
-        if (namedMatrix.level() == deviceLevel) {
-            targetMatrix = &namedMatrix;
-        }
-    }
-    if (targetMatrix == nullptr) {
+    std::vector<CompatibilityMatrix> targetMatrices;
+    // Partition matrixFragments into two groups, where the second group
+    // contains all matrices whose level == deviceLevel.
+    auto targetMatricesPartition = std::partition(
+        matrixFragments.begin(), matrixFragments.end(),
+        [&](const CompatibilityMatrix& matrix) { return matrix.level() != deviceLevel; });
+    // Move these matrices into the targetMatrices vector...
+    std::move(targetMatricesPartition, matrixFragments.end(), std::back_inserter(targetMatrices));
+    if (targetMatrices.empty()) {
         if (error)
             *error = "Cannot find framework matrix at FCM version " + to_string(deviceLevel) + ".";
         return NAME_NOT_FOUND;
     }
+    // so that they can be combined into one matrix for deprecation checking.
+    auto targetMatrix = CompatibilityMatrix::combine(deviceLevel, &targetMatrices, error);
+    if (targetMatrix == nullptr) {
+        return BAD_VALUE;
+    }
 
     std::multimap<std::string, std::string> childrenMap;
     for (const auto& child : hidlMetadata) {
@@ -883,10 +890,10 @@
     // Find a list of possibly deprecated HALs by comparing |listInstances| with older matrices.
     // Matrices with unspecified level are considered "current".
     bool isDeprecated = false;
-    for (const auto& namedMatrix : matrixFragments) {
+    for (auto it = matrixFragments.begin(); it < targetMatricesPartition; ++it) {
+        const auto& namedMatrix = *it;
         if (namedMatrix.level() == Level::UNSPECIFIED) continue;
-        if (namedMatrix.level() >= deviceLevel) continue;
-
+        if (namedMatrix.level() > deviceLevel) continue;
         for (const MatrixHal& hal : namedMatrix.getHals()) {
             if (IsHalDeprecated(hal, *targetMatrix, listInstances, childrenMap, error)) {
                 isDeprecated = true;