Add system_ext manifest

Bug: 147915920
Test: vintf_object_tests
Change-Id: I0ffd05547aedbbb5e72198b67a5ab3344c7528c0
Merged-In: I0ffd05547aedbbb5e72198b67a5ab3344c7528c0
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 115081f..a19d3e1 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -385,21 +385,31 @@
             return dirStatus;
         }
 
-        HalManifest productManifest;
-        auto productStatus = fetchOneHalManifest(kProductManifest, &productManifest, error);
-        if (productStatus != OK && productStatus != NAME_NOT_FOUND) {
-            return productStatus;
-        }
-        if (productStatus == OK) {
-            if (!out->addAll(&productManifest, error)) {
-                if (error) {
-                    error->insert(0, "Cannot add " + kProductManifest + ":");
+        std::vector<std::pair<const std::string&, const std::string&>> extensions{
+            {kProductManifest, kProductManifestFragmentDir},
+            {kSystemExtManifest, kSystemExtManifestFragmentDir},
+        };
+        for (auto&& [manifestPath, frags] : extensions) {
+            HalManifest halManifest;
+            auto status = fetchOneHalManifest(manifestPath, &halManifest, error);
+            if (status != OK && status != NAME_NOT_FOUND) {
+                return status;
+            }
+            if (status == OK) {
+                if (!out->addAll(&halManifest, error)) {
+                    if (error) {
+                        error->insert(0, "Cannot add " + manifestPath + ":");
+                    }
+                    return UNKNOWN_ERROR;
                 }
-                return UNKNOWN_ERROR;
+            }
+
+            auto fragmentStatus = addDirectoryManifests(frags, out, error);
+            if (fragmentStatus != OK) {
+                return fragmentStatus;
             }
         }
-
-        return addDirectoryManifests(kProductManifestFragmentDir, out, error);
+        return OK;
     } else {
         LOG(WARNING) << "Cannot fetch " << kSystemManifest << ": "
                      << (error ? *error : strerror(-systemEtcStatus));
@@ -596,11 +606,13 @@
 const std::string kOdmManifest = kOdmVintfDir + "manifest.xml";
 const std::string kProductMatrix = kProductVintfDir + "compatibility_matrix.xml";
 const std::string kProductManifest = kProductVintfDir + "manifest.xml";
+const std::string kSystemExtManifest = kSystemExtVintfDir + "manifest.xml";
 
 const std::string kVendorManifestFragmentDir = kVendorVintfDir + "manifest/";
 const std::string kSystemManifestFragmentDir = kSystemVintfDir + "manifest/";
 const std::string kOdmManifestFragmentDir = kOdmVintfDir + "manifest/";
 const std::string kProductManifestFragmentDir = kProductVintfDir + "manifest/";
+const std::string kSystemExtManifestFragmentDir = kSystemExtVintfDir + "manifest/";
 
 const std::string kVendorLegacyManifest = "/vendor/manifest.xml";
 const std::string kVendorLegacyMatrix = "/vendor/compatibility_matrix.xml";
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index cfc26ee..fa25669 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -389,10 +389,12 @@
 extern const std::string kOdmManifest;
 extern const std::string kProductMatrix;
 extern const std::string kProductManifest;
+extern const std::string kSystemExtManifest;
 extern const std::string kVendorManifestFragmentDir;
 extern const std::string kSystemManifestFragmentDir;
 extern const std::string kOdmManifestFragmentDir;
 extern const std::string kProductManifestFragmentDir;
+extern const std::string kSystemExtManifestFragmentDir;
 extern const std::string kVendorLegacyManifest;
 extern const std::string kVendorLegacyMatrix;
 extern const std::string kSystemLegacyManifest;
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index 6b8f4c4..14d7025 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -1484,102 +1484,51 @@
     EXPECT_TRUE(vintfObject->checkCompatibility(&error)) << error;
 }
 
-const std::string systemEtcManifest =
-    "<manifest " + kMetaVersionStr + " type=\"framework\">\n"
-    "    <hal format=\"hidl\">\n"
-    "        <name>android.hardware.foo</name>\n"
-    "        <transport>hwbinder</transport>\n"
-    "        <fqname>@1.0::ISystemEtc/default</fqname>\n"
-    "    </hal>\n"
-    "</manifest>\n";
-
-const std::string systemEtcManifestFrag =
-    "<manifest " + kMetaVersionStr + " type=\"framework\">\n"
-    "    <hal format=\"hidl\">\n"
-    "        <name>android.hardware.foo</name>\n"
-    "        <transport>hwbinder</transport>\n"
-    "        <fqname>@1.0::ISystemEtcFragment/default</fqname>\n"
-    "    </hal>\n"
-    "</manifest>\n";
-
-const std::string productEtcManifest =
-    "<manifest " + kMetaVersionStr + " type=\"framework\">\n"
-    "    <hal format=\"hidl\">\n"
-    "        <name>android.hardware.foo</name>\n"
-    "        <transport>hwbinder</transport>\n"
-    "        <fqname>@1.0::IProductEtc/default</fqname>\n"
-    "    </hal>\n"
-    "</manifest>\n";
-
-const std::string productEtcManifestFrag =
-    "<manifest " + kMetaVersionStr + " type=\"framework\">\n"
-    "    <hal format=\"hidl\">\n"
-    "        <name>android.hardware.foo</name>\n"
-    "        <transport>hwbinder</transport>\n"
-    "        <fqname>@1.0::IProductEtcFragment/default</fqname>\n"
-    "    </hal>\n"
-    "</manifest>\n";
+std::string CreateFrameworkManifestFrag(const std::string& interface) {
+    return "<manifest " + kMetaVersionStr + " type=\"framework\">\n"
+           "    <hal format=\"hidl\">\n"
+           "        <name>android.hardware.foo</name>\n"
+           "        <transport>hwbinder</transport>\n"
+           "        <fqname>@1.0::" + interface + "/default</fqname>\n"
+           "    </hal>\n"
+           "</manifest>\n";
+}
 
 using FrameworkManifestTestParam =
     std::tuple<bool /* Existence of /system/etc/vintf/manifest.xml */,
                bool /* Existence of /system/etc/vintf/manifest/fragment.xml */,
                bool /* Existence of /product/etc/vintf/manifest.xml */,
-               bool /* Existence of /product/etc/vintf/manifest/fragment.xml */>;
+               bool /* Existence of /product/etc/vintf/manifest/fragment.xml */,
+               bool /* Existence of /system_ext/etc/vintf/manifest.xml */,
+               bool /* Existence of /system_ext/etc/vintf/manifest/fragment.xml */>;
 class FrameworkManifestTest : public VintfObjectTestBase,
                               public ::testing::WithParamInterface<FrameworkManifestTestParam> {
    protected:
+    // Set the existence of |path|.
+    void expectManifest(const std::string& path, const std::string& interface, bool exists) {
+        if (exists) {
+            expectFetchRepeatedly(path, CreateFrameworkManifestFrag(interface));
+        } else {
+            expectFileNotExist(StrEq(path));
+        }
+    }
 
-    // Set the existence of /system/etc/vintf/manifest.xml
-    void expectSystemManifest(bool exists) {
+    // Set the existence of |path| as a fragment dir
+    void expectFragment(const std::string& path, const std::string& interface, bool exists) {
         if (exists) {
-            expectFetchRepeatedly(kSystemManifest, systemEtcManifest);
-        } else {
-            expectFileNotExist(StrEq(kSystemManifest));
-        }
-        expectFileNotExist(StrEq(kSystemLegacyManifest));
-    }
-    // Set the existence of /system/etc/vintf/manifest/fragment.xml
-    void expectSystemManifestFragment(bool exists) {
-        if (exists) {
-            EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemManifestFragmentDir), _, _))
+            EXPECT_CALL(fetcher(), listFiles(StrEq(path), _, _))
                 .Times(AnyNumber())
                 .WillRepeatedly(Invoke([](const auto&, auto* out, auto*) {
                     *out = {"fragment.xml"};
                     return ::android::OK;
                 }));
-            expectFetchRepeatedly(kSystemManifestFragmentDir + "fragment.xml",
-                                  systemEtcManifestFrag);
+            expectFetchRepeatedly(path + "fragment.xml",
+                                  CreateFrameworkManifestFrag(interface));
         } else {
-            EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemManifestFragmentDir), _, _))
+            EXPECT_CALL(fetcher(), listFiles(StrEq(path), _, _))
                 .Times(AnyNumber())
                 .WillRepeatedly(Return(::android::OK));
-            expectFileNotExist(kSystemManifestFragmentDir + "fragment.xml");
-        }
-    }
-    // Set the existence of /product/etc/vintf/manifest.xml
-    void expectProductManifest(bool exists) {
-        if (exists) {
-            expectFetchRepeatedly(kProductManifest, productEtcManifest);
-        } else {
-            expectFileNotExist(kProductManifest);
-        }
-    }
-    // Set the existence of /product/etc/vintf/manifest/fragment.xml
-    void expectProductManifestFragment(bool exists) {
-        if (exists) {
-            EXPECT_CALL(fetcher(), listFiles(StrEq(kProductManifestFragmentDir), _, _))
-                .Times(AnyNumber())
-                .WillRepeatedly(Invoke([](const auto&, auto* out, auto*) {
-                    *out = {"fragment.xml"};
-                    return ::android::OK;
-                }));
-            expectFetchRepeatedly(kProductManifestFragmentDir + "fragment.xml",
-                                  productEtcManifestFrag);
-        } else {
-            EXPECT_CALL(fetcher(), listFiles(StrEq(kProductManifestFragmentDir), _, _))
-                .Times(AnyNumber())
-                .WillRepeatedly(Return(::android::OK));
-            expectFileNotExist(kProductManifestFragmentDir + "fragment.xml");
+            expectFileNotExist(path + "fragment.xml");
         }
     }
 
@@ -1593,10 +1542,14 @@
 };
 
 TEST_P(FrameworkManifestTest, Existence) {
-    expectSystemManifest(std::get<0>(GetParam()));
-    expectSystemManifestFragment(std::get<1>(GetParam()));
-    expectProductManifest(std::get<2>(GetParam()));
-    expectProductManifestFragment(std::get<3>(GetParam()));
+    expectFileNotExist(StrEq(kSystemLegacyManifest));
+
+    expectManifest(kSystemManifest, "ISystemEtc", std::get<0>(GetParam()));
+    expectFragment(kSystemManifestFragmentDir, "ISystemEtcFragment", std::get<1>(GetParam()));
+    expectManifest(kProductManifest, "IProductEtc", std::get<2>(GetParam()));
+    expectFragment(kProductManifestFragmentDir, "IProductEtcFragment", std::get<3>(GetParam()));
+    expectManifest(kSystemExtManifest, "ISystemExtEtc", std::get<4>(GetParam()));
+    expectFragment(kSystemExtManifestFragmentDir, "ISystemExtEtcFragment", std::get<5>(GetParam()));
 
     if (!std::get<0>(GetParam())) {
         EXPECT_EQ(nullptr, vintfObject->getFrameworkHalManifest())
@@ -1607,10 +1560,12 @@
         expectContainsInterface("ISystemEtcFragment", std::get<1>(GetParam()));
         expectContainsInterface("IProductEtc", std::get<2>(GetParam()));
         expectContainsInterface("IProductEtcFragment", std::get<3>(GetParam()));
+        expectContainsInterface("ISystemExtEtc", std::get<4>(GetParam()));
+        expectContainsInterface("ISystemExtEtcFragment", std::get<5>(GetParam()));
     }
 }
 INSTANTIATE_TEST_SUITE_P(Vintf, FrameworkManifestTest,
-                         ::testing::Combine(Bool(), Bool(), Bool(), Bool()));
+                         ::testing::Combine(Bool(), Bool(), Bool(), Bool(), Bool(), Bool()));
 
 
 //