Add query methods for native instances

similar to those for HIDL/AIDL instances, but it doesn't need
interface/version.

Bug: 316051788
Test: libvintf_test
Change-Id: If9904520dadc5ea4acde9b1e92a38ce842b54333
diff --git a/HalManifest.cpp b/HalManifest.cpp
index 8caa182..0d4b829 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -293,6 +293,20 @@
     return true;
 }
 
+bool HalManifest::forEachNativeInstance(
+    const std::string& package, const std::function<bool(const ManifestInstance&)>& func) const {
+    for (const ManifestHal* hal : getHals(package)) {
+        bool cont = hal->forEachInstance([&](const ManifestInstance& manifestInstance) {
+            if (manifestInstance.format() == HalFormat::NATIVE) {
+                return func(manifestInstance);
+            }
+            return true;
+        });
+        if (!cont) return false;
+    }
+    return true;
+}
+
 // indent = 2, {"foo"} => "foo"
 // indent = 2, {"foo", "bar"} => "\n  foo\n  bar";
 template <typename Container>
@@ -653,6 +667,15 @@
                         interfaceName);
 }
 
+std::set<std::string> HalManifest::getNativeInstances(const std::string& package) const {
+    std::set<std::string> instances;
+    forEachNativeInstance(package, [&](const auto& inst) {
+        instances.insert(inst.instance());
+        return true;
+    });
+    return instances;
+}
+
 bool HalManifest::hasHidlInstance(const std::string& package, const Version& version,
                                   const std::string& interfaceName,
                                   const std::string& instance) const {
@@ -670,6 +693,15 @@
                        interface, instance);
 }
 
+bool HalManifest::hasNativeInstance(const std::string& package, const std::string& instance) const {
+    bool found = false;
+    forEachNativeInstance(package, [&](const auto& inst) {
+        found |= inst.instance() == instance;
+        return !found;  // continue if not found
+    });
+    return found;
+}
+
 bool HalManifest::insertInstance(const FqInstance& fqInstance, Transport transport, Arch arch,
                                  HalFormat format, std::string* error) {
     for (ManifestHal& hal : getHals()) {
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index dd4ab21..0230834 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -130,6 +130,7 @@
                                            const std::string& interfaceName) const;
     std::set<std::string> getAidlInstances(const std::string& package,
                                            const std::string& interfaceName) const;
+    std::set<std::string> getNativeInstances(const std::string& package) const;
 
     // Return whether instance is in getHidlInstances(...).
     bool hasHidlInstance(const std::string& package, const Version& version,
@@ -143,6 +144,9 @@
     bool hasAidlInstance(const std::string& package, const std::string& interfaceName,
                          const std::string& instance) const;
 
+    // Return whether a given native instance is in getNativeInstances(...).
+    bool hasNativeInstance(const std::string& package, const std::string& instance) const;
+
     // Insert the given instance. After inserting it, the instance will be available via
     // forEachInstance* functions. This modifies the manifest.
     // Return whether this operation is successful.
@@ -162,6 +166,9 @@
         HalFormat format, const std::string& package, const Version& expectVersion,
         const std::function<bool(const ManifestInstance&)>& func) const override;
 
+    bool forEachNativeInstance(const std::string& package,
+                               const std::function<bool(const ManifestInstance&)>& func) const;
+
    private:
     friend struct HalManifestConverter;
     friend class VintfObject;
diff --git a/test/LibVintfTest.cpp b/test/LibVintfTest.cpp
index 0e1ba9f..cea7bfb 100644
--- a/test/LibVintfTest.cpp
+++ b/test/LibVintfTest.cpp
@@ -548,6 +548,34 @@
     });
 }
 
+TEST_F(LibVintfTest, QueryNativeInstances) {
+    std::string error;
+    HalManifest manifest;
+    std::string xml = "<manifest " + kMetaVersionStr + R"( type="device">
+            <hal format="native">
+                <name>foo</name>
+                <version>1.0</version>
+                <interface>
+                    <instance>fooinst</instance>
+                </interface>
+           </hal>
+            <hal format="native">
+                <name>bar</name>
+                <fqname>@1.0::I/barinst</fqname>
+           </hal>
+        </manifest>
+    )";
+    ASSERT_TRUE(fromXml(&manifest, xml, &error)) << error;
+
+    EXPECT_EQ(manifest.getNativeInstances("foo"), std::set<std::string>{"fooinst"});
+    EXPECT_TRUE(manifest.hasNativeInstance("foo", "fooinst"));
+    EXPECT_EQ(manifest.getNativeInstances("bar"), std::set<std::string>{"barinst"});
+    EXPECT_TRUE(manifest.hasNativeInstance("bar", "barinst"));
+
+    EXPECT_EQ(manifest.getNativeInstances("baz"), std::set<std::string>{});
+    EXPECT_FALSE(manifest.hasNativeInstance("baz", "bazinst"));
+}
+
 // clang-format off
 
 TEST_F(LibVintfTest, HalManifestDuplicate) {