Combine version tag with fqname for AIDL HALs

For AIDL HALs (but not HIDL HALs), when
iterating over <fqname>, the <version> tag of a HAL mangles with the
HAL. For example:

  <hal format="aidl">
    <name>foo</name>
    <version>1</version>
    <fqname>IFoo/default</fqname>
  </hal>

... results in foo.IFoo/default (version 1). If <version> is not
specified, libvintf injects a <version>0</version> for AIDL HALs.

Test: libvintf_test
Test: vintf_object_test

Change-Id: Id86fdfd6e186e84d05bd4535eeabe0bfda3b6ee7
diff --git a/ManifestHal.cpp b/ManifestHal.cpp
index 3fdc6e2..cb60331 100644
--- a/ManifestHal.cpp
+++ b/ManifestHal.cpp
@@ -86,8 +86,19 @@
     }
 
     for (const auto& manifestInstance : mAdditionalInstances) {
-        if (!func(manifestInstance)) {
-            return false;
+        // For AIDL HALs, <version> tag is mangled with <fqname>. Note that if there's no
+        // <version> tag, libvintf will create one by default, so each <fqname> is executed
+        // at least once.
+        if (format == HalFormat::AIDL) {
+            for (const auto& v : versions) {
+                if (!func(manifestInstance.withVersion(v))) {
+                    return false;
+                }
+            }
+        } else {
+            if (!func(manifestInstance)) {
+                return false;
+            }
         }
     }
 
diff --git a/ManifestInstance.cpp b/ManifestInstance.cpp
index 0461808..9e0f919 100644
--- a/ManifestInstance.cpp
+++ b/ManifestInstance.cpp
@@ -23,6 +23,8 @@
 
 #include <utility>
 
+#include <android-base/logging.h>
+
 #include "parse_string.h"
 
 namespace android {
@@ -121,5 +123,12 @@
     }
 }
 
+ManifestInstance ManifestInstance::withVersion(const Version& v) const {
+    FqInstance fqInstance;
+    CHECK(fqInstance.setTo(getFqInstance().getPackage(), v.majorVer, v.minorVer,
+                           getFqInstance().getInterface(), getFqInstance().getInstance()));
+    return ManifestInstance(fqInstance, mTransportArch, format());
+}
+
 }  // namespace vintf
 }  // namespace android
diff --git a/include/vintf/ManifestInstance.h b/include/vintf/ManifestInstance.h
index 7fb6a2f..f8c44f1 100644
--- a/include/vintf/ManifestInstance.h
+++ b/include/vintf/ManifestInstance.h
@@ -60,6 +60,9 @@
     // For others, return package@version::interface/instance.
     std::string description() const;
 
+    // Return a new ManifestInstance that's the same as this, but with the given version.
+    ManifestInstance withVersion(const Version& v) const;
+
    private:
     FqInstance mFqInstance;
     TransportArch mTransportArch;
diff --git a/test/LibVintfTest.cpp b/test/LibVintfTest.cpp
index 12c9259..522575a 100644
--- a/test/LibVintfTest.cpp
+++ b/test/LibVintfTest.cpp
@@ -3921,6 +3921,34 @@
         EXPECT_EQ(manifest.getAidlInstances("android.system.does_not_exist", "IFoo"),
                   std::set<std::string>({}));
     }
+
+    {
+        HalManifest manifest;
+        std::string manifestXml =
+            "<manifest " + kMetaVersionStr + " type=\"framework\">\n"
+            "    <hal format=\"aidl\">\n"
+            "        <name>android.system.foo</name>\n"
+            "        <version>5</version>\n"
+            "        <fqname>IFoo/default</fqname>\n"
+            "        <fqname>IFoo/test0</fqname>\n"
+            "    </hal>\n"
+            "</manifest>\n";
+        EXPECT_TRUE(gHalManifestConverter(&manifest, manifestXml, &error)) << error;
+        EXPECT_EQ(manifestXml, gHalManifestConverter(manifest, SerializeFlags::HALS_ONLY));
+        EXPECT_TRUE(manifest.hasAidlInstance("android.system.foo", "IFoo", "default"));
+        EXPECT_TRUE(manifest.hasAidlInstance("android.system.foo", "IFoo", "test0"));
+        EXPECT_TRUE(manifest.hasAidlInstance("android.system.foo", 5, "IFoo", "default"));
+        EXPECT_TRUE(manifest.hasAidlInstance("android.system.foo", 5, "IFoo", "test0"));
+        EXPECT_FALSE(manifest.hasAidlInstance("android.system.foo", "IFoo", "does_not_exist"));
+        EXPECT_FALSE(manifest.hasAidlInstance("android.system.foo", "IDoesNotExist", "default"));
+        EXPECT_FALSE(manifest.hasAidlInstance("android.system.does_not_exist", "IFoo", "default"));
+        EXPECT_EQ(manifest.getAidlInstances("android.system.foo", "IFoo"),
+                  std::set<std::string>({"default", "test0"}));
+        EXPECT_EQ(manifest.getAidlInstances("android.system.foo", 5, "IFoo"),
+                  std::set<std::string>({"default", "test0"}));
+        EXPECT_EQ(manifest.getAidlInstances("android.system.does_not_exist", "IFoo"),
+                  std::set<std::string>({}));
+    }
 }
 
 TEST_F(LibVintfTest, GetTransportHidlHalWithFakeAidlVersion) {