Add <hal format="aidl">.

Test: libvintf_test
Bug: 138244384

Change-Id: If4e9646ff1107f84ea0be68283488a37795133c3
diff --git a/parse_xml.cpp b/parse_xml.cpp
index b59bd6b..eedfa1a 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -26,6 +26,7 @@
 #include <tinyxml2.h>
 
 #include "Regex.h"
+#include "constants-private.h"
 #include "constants.h"
 #include "parse_string.h"
 
@@ -550,7 +551,10 @@
         appendAttr(root, "format", hal.format);
         appendAttr(root, "optional", hal.optional);
         appendTextElement(root, "name", hal.name, d);
-        appendChildren(root, versionRangeConverter, hal.versionRanges, d);
+        // Don't write <version> for format="aidl"
+        if (hal.format != HalFormat::AIDL) {
+            appendChildren(root, versionRangeConverter, hal.versionRanges, d);
+        }
         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
     }
     bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
@@ -563,6 +567,16 @@
             !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
             return false;
         }
+        if (object->format == HalFormat::AIDL) {
+            if (!object->versionRanges.empty()) {
+                LOG(WARNING) << "Ignoring <version> on matrix <hal format=\"aidl\"> "
+                             << object->name;
+                object->versionRanges.clear();
+            }
+            // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
+            // HAL formats can be unified.
+            object->versionRanges.push_back(details::kFakeAidlVersionRange);
+        }
         for (auto&& interface : interfaces) {
             std::string name{interface.name()};
             auto res = object->interfaces.emplace(std::move(name), std::move(interface));
@@ -673,20 +687,25 @@
                     SerializeFlags::Type flags) const override {
         appendAttr(root, "format", hal.format);
         appendTextElement(root, "name", hal.name, d);
-        appendChild(root, transportArchConverter(hal.transportArch, d));
-        appendChildren(root, versionConverter, hal.versions, d);
+        if (!hal.transportArch.empty()) {
+            appendChild(root, transportArchConverter(hal.transportArch, d));
+        }
+        // Don't output <version> for format="aidl"
+        if (hal.format != HalFormat::AIDL) {
+            appendChildren(root, versionConverter, hal.versions, d);
+        }
         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
         if (hal.isOverride()) {
             appendAttr(root, "override", hal.isOverride());
         }
 
         if (flags.isFqnameEnabled()) {
-            std::set<FqInstance> fqInstances;
-            hal.forEachInstance([&fqInstances](const auto& manifestInstance) {
-                fqInstances.emplace(manifestInstance.getFqInstanceNoPackage());
+            std::set<std::string> simpleFqInstances;
+            hal.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
+                simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
                 return true;
             });
-            appendChildren(root, fqInstanceConverter, fqInstances, d);
+            appendTextElements(root, fqInstanceConverter.elementName(), simpleFqInstances, d);
         }
     }
     bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
@@ -714,6 +733,20 @@
                     return false;
                 }
             } break;
+            case HalFormat::AIDL: {
+                if (!object->transportArch.empty()) {
+                    LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
+                                 << object->name;
+                    object->transportArch = {};
+                }
+                if (!object->versions.empty()) {
+                    LOG(WARNING) << "Ignoring <version> on manifest <hal format=\"aidl\"> "
+                                 << object->name;
+                    object->versions.clear();
+                }
+                // Insert fake version for AIDL HALs so that forEachInstance works.
+                object->versions.push_back(details::kFakeAidlVersion);
+            } break;
             default: {
                 LOG(FATAL) << "Unhandled HalFormat "
                            << static_cast<typename std::underlying_type<HalFormat>::type>(
@@ -747,13 +780,27 @@
         if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
             return false;
         }
-        for (const auto& e : fqInstances) {
+        std::set<FqInstance> fqInstancesToInsert;
+        for (auto& e : fqInstances) {
             if (e.hasPackage()) {
                 *error = "Should not specify package: \"" + e.string() + "\"";
                 return false;
             }
+            if (object->format == HalFormat::AIDL) {
+                // <fqname> in AIDL HALs should not contain version. Put in the fake
+                // kFakeAidlVersion so that compatibility check works.
+                FqInstance withFakeVersion;
+                if (!withFakeVersion.setTo(details::kFakeAidlVersion.majorVer,
+                                           details::kFakeAidlVersion.minorVer, e.getInterface(),
+                                           e.getInstance())) {
+                    return false;
+                }
+                fqInstancesToInsert.emplace(std::move(withFakeVersion));
+            } else {
+                fqInstancesToInsert.emplace(std::move(e));
+            }
         }
-        if (!object->insertInstances(fqInstances, error)) {
+        if (!object->insertInstances(fqInstancesToInsert, error)) {
             return false;
         }