Merge "Vapex vintf fragments are part of vendor manifest" into main
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 16f95d2..cb123b3 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -279,17 +279,6 @@
     return OK;
 }
 
-// Create device HalManifest
-// 1. Create manifest based on /vendor /odm data
-// 2. Add any APEX data
-status_t VintfObject::fetchDeviceHalManifest(HalManifest* out, std::string* error) {
-    auto status = fetchDeviceHalManifestMinusApex(out, error);
-    if (status != OK) {
-        return status;
-    }
-    return fetchDeviceHalManifestApex(out, error);
-}
-
 // Fetch fragments from apexes originated from /vendor.
 // For now, we don't have /odm apexes.
 status_t VintfObject::fetchDeviceHalManifestApex(HalManifest* out, std::string* error) {
@@ -303,14 +292,14 @@
 }
 
 // Priority for loading vendor manifest:
-// 1. Vendor manifest + device fragments + ODM manifest (optional) + odm fragments
-// 2. Vendor manifest + device fragments
+// 1. Vendor manifest + device fragments (including vapex) + ODM manifest (optional) + odm fragments
+// 2. Vendor manifest + device fragments (including vapex)
 // 3. ODM manifest (optional) + odm fragments
 // 4. /vendor/manifest.xml (legacy, no fragments)
 // where:
 // A + B means unioning <hal> tags from A and B. If B declares an override, then this takes priority
 // over A.
-status_t VintfObject::fetchDeviceHalManifestMinusApex(HalManifest* out, std::string* error) {
+status_t VintfObject::fetchDeviceHalManifest(HalManifest* out, std::string* error) {
     HalManifest vendorManifest;
     status_t vendorStatus = fetchVendorHalManifest(&vendorManifest, error);
     if (vendorStatus != OK && vendorStatus != NAME_NOT_FOUND) {
@@ -324,6 +313,11 @@
         if (fragmentStatus != OK) {
             return fragmentStatus;
         }
+
+        status_t apexStatus = fetchDeviceHalManifestApex(out, error);
+        if (apexStatus != OK) {
+            return apexStatus;
+        }
     }
 
     HalManifest odmManifest;
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index 8f29ec0..67cfdcb 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -309,7 +309,6 @@
                                      HalManifest* manifests, bool ignoreSchemaType,
                                      std::string* error);
     status_t fetchDeviceHalManifest(HalManifest* out, std::string* error = nullptr);
-    status_t fetchDeviceHalManifestMinusApex(HalManifest* out, std::string* error = nullptr);
     status_t fetchDeviceHalManifestApex(HalManifest* out, std::string* error = nullptr);
     status_t fetchDeviceMatrix(CompatibilityMatrix* out, std::string* error = nullptr);
     status_t fetchOdmHalManifest(HalManifest* out, std::string* error = nullptr);
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index a13007c..52376c1 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -1170,6 +1170,125 @@
 
 INSTANTIATE_TEST_SUITE_P(OdmManifest, OdmManifestTest, ::testing::Values("", "fake_sku"));
 
+struct ManifestOverrideTest : public VintfObjectTestBase {
+  protected:
+    void SetUp() override {
+        VintfObjectTestBase::SetUp();
+        ON_CALL(fetcher(), fetch(_, _))
+            .WillByDefault(Invoke([&](auto path, std::string& out) {
+                auto dirIt = dirs_.find(base::Dirname(path) + "/");
+                if (dirIt != dirs_.end()) {
+                    auto fileIt = dirIt->second.find(base::Basename(path));
+                    if (fileIt != dirIt->second.end()) {
+                        out = fileIt->second;
+                        return OK;
+                    }
+                }
+                return NAME_NOT_FOUND;
+            }));
+        ON_CALL(fetcher(), listFiles(_, _, _))
+            .WillByDefault(Invoke([&](auto path, std::vector<std::string>* out, auto) {
+                auto dirIt = dirs_.find(path);
+                if (dirIt != dirs_.end()) {
+                    for (const auto& [f, _]: dirIt->second) {
+                        out->push_back(f);
+                    }
+                    return OK;
+                }
+                return NAME_NOT_FOUND;
+            }));
+    }
+    void expect(std::string path, std::string content) {
+        dirs_[base::Dirname(path) + "/"][base::Basename(path)] = content;
+    }
+  private:
+    std::map<std::string, std::map<std::string, std::string>> dirs_;
+};
+
+TEST_F(ManifestOverrideTest, NoOverrideForVendor) {
+    expect(kVendorManifest,
+        "<manifest " + kMetaVersionStr + " type=\"device\">"
+        "  <hal format=\"aidl\">"
+        "    <name>android.hardware.foo</name>"
+        "    <fqname>IFoo/default</fqname>"
+        "  </hal>"
+        "</manifest>");
+    auto p = vintfObject->getDeviceHalManifest();
+    ASSERT_NE(nullptr, p);
+    ASSERT_EQ(p->getAidlInstances("android.hardware.foo", "IFoo"),
+        std::set<std::string>({"default"}));
+}
+
+TEST_F(ManifestOverrideTest, OdmOverridesVendor) {
+    expect(kVendorManifest, "<manifest " + kMetaVersionStr + " type=\"device\">"
+        "  <hal format=\"aidl\">"
+        "    <name>android.hardware.foo</name>"
+        "    <fqname>IFoo/default</fqname>"
+        "  </hal>"
+        "</manifest>");
+    // ODM overrides(disables) HAL in Vendor
+    expect(kOdmManifest, "<manifest " + kMetaVersionStr + " type=\"device\">"
+        "  <hal override=\"true\" format=\"aidl\">"
+        "    <name>android.hardware.foo</name>"
+        "  </hal>"
+        "</manifest>");
+    auto p = vintfObject->getDeviceHalManifest();
+    ASSERT_NE(nullptr, p);
+    ASSERT_EQ(p->getAidlInstances("android.hardware.foo", "IFoo"), std::set<std::string>({}));
+}
+
+TEST_F(ManifestOverrideTest, NoOverrideForVendorApex) {
+    expect(kVendorManifest,
+        "<manifest " + kMetaVersionStr + " type=\"device\" />");
+    expect(kApexInfoFile,
+        R"(<apex-info-list>
+          <apex-info
+            moduleName="com.android.foo"
+            preinstalledModulePath="/vendor/apex/com.android.foo.apex"
+            isActive="true"/>
+        </apex-info-list>)");
+    expect("/apex/com.android.foo/etc/vintf/foo.xml",
+        "<manifest " + kMetaVersionStr + "type=\"device\">"
+        "  <hal format=\"aidl\">"
+        "    <name>android.hardware.foo</name>"
+        "    <fqname>IFoo/default</fqname>"
+        "  </hal>"
+        "</manifest>");
+    auto p = vintfObject->getDeviceHalManifest();
+    ASSERT_NE(nullptr, p);
+    ASSERT_EQ(p->getAidlInstances("android.hardware.foo", "IFoo"),
+        std::set<std::string>({"default"}));
+}
+
+TEST_F(ManifestOverrideTest, OdmOverridesVendorApex) {
+    expect(kVendorManifest,
+        "<manifest " + kMetaVersionStr + " type=\"device\" />");
+    expect(kApexInfoFile,
+        R"(<apex-info-list>
+            <apex-info
+                moduleName="com.android.foo"
+                preinstalledModulePath="/vendor/apex/com.android.foo.apex"
+                isActive="true"/>
+            </apex-info-list>)");
+    expect("/apex/com.android.foo/etc/vintf/foo.xml",
+        "<manifest " + kMetaVersionStr + "type=\"device\">"
+        "  <hal format=\"aidl\">"
+        "    <name>android.hardware.foo</name>"
+        "    <fqname>IFoo/default</fqname>"
+        "  </hal>"
+        "</manifest>");
+    // ODM overrides(disables) HAL in Vendor APEX
+    expect(kOdmManifest, "<manifest " + kMetaVersionStr + " type=\"device\">"
+        "  <hal override=\"true\" format=\"aidl\">"
+        "    <name>android.hardware.foo</name>"
+        "  </hal>"
+        "</manifest>");
+    auto p = vintfObject->getDeviceHalManifest();
+    ASSERT_NE(nullptr, p);
+    ASSERT_EQ(p->getAidlInstances("android.hardware.foo", "IFoo"),
+        std::set<std::string>({}));
+}
+
 struct CheckedFqInstance : FqInstance {
     CheckedFqInstance(const char* s) : CheckedFqInstance(std::string(s)) {}
     CheckedFqInstance(const std::string& s) { CHECK(setTo(s)) << s; }