Framework manifest: filter out HALs by level

Remove HALs with max-level > device target FCM version.

Test: vintf_object_test
Bug: 37226359

Change-Id: Ia9198269df786acea352a407bf4c1a1dc47ec0d0
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 5ec5505..559b8d8 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -382,7 +382,7 @@
 //    + /product/etc/vintf/manifest.xml if it exists
 //    + /product/etc/vintf/manifest/*.xml if they exist
 // 2. (deprecated) /system/manifest.xml
-status_t VintfObject::fetchFrameworkHalManifest(HalManifest* out, std::string* error) {
+status_t VintfObject::fetchUnfilteredFrameworkHalManifest(HalManifest* out, std::string* error) {
     auto systemEtcStatus = fetchOneHalManifest(kSystemManifest, out, error);
     if (systemEtcStatus == OK) {
         auto dirStatus = addDirectoryManifests(kSystemManifestFragmentDir, out, error);
@@ -414,6 +414,7 @@
                 return fragmentStatus;
             }
         }
+
         return OK;
     } else {
         LOG(WARNING) << "Cannot fetch " << kSystemManifest << ": "
@@ -423,6 +424,36 @@
     return out->fetchAllInformation(getFileSystem().get(), kSystemLegacyManifest, error);
 }
 
+status_t VintfObject::fetchFrameworkHalManifest(HalManifest* out, std::string* error) {
+    status_t status = fetchUnfilteredFrameworkHalManifest(out, error);
+    if (status != OK) {
+        return status;
+    }
+    filterHalsByDeviceManifestLevel(out);
+    return OK;
+}
+
+void VintfObject::filterHalsByDeviceManifestLevel(HalManifest* out) {
+    auto deviceManifest = getDeviceHalManifest();
+    if (deviceManifest == nullptr) {
+        LOG(WARNING) << "Cannot fetch device manifest to determine target FCM version to "
+                        "filter framework manifest HALs.";
+        return;
+    }
+    Level deviceManifestLevel = deviceManifest->level();
+    if (deviceManifestLevel == Level::UNSPECIFIED) {
+        LOG(WARNING)
+            << "Not filtering framework manifest HALs because target FCM version is unspecified.";
+        return;
+    }
+    out->removeHalsIf([deviceManifestLevel](const ManifestHal& hal) {
+        if (hal.getMaxLevel() == Level::UNSPECIFIED) {
+            return false;
+        }
+        return hal.getMaxLevel() < deviceManifestLevel;
+    });
+}
+
 static void appendLine(std::string* error, const std::string& message) {
     if (error != nullptr) {
         if (!error->empty()) *error += "\n";