Fail on duplicate when activating flattened apexes

Bug: 254172648
Test: ApexTestCases:ApexdMountTest
Change-Id: Ic76d06f8c984fd620a95bddf0cfd14a3d292caa0
diff --git a/apexd/apexd.cpp b/apexd/apexd.cpp
index cd9557e..60fdf83 100644
--- a/apexd/apexd.cpp
+++ b/apexd/apexd.cpp
@@ -3726,6 +3726,7 @@
   LOG(INFO) << "ActivateFlattenedApex";
 
   std::vector<com::android::apex::ApexInfo> apex_infos;
+  std::unordered_map<std::string, std::string> apex_names;
 
   for (const std::string& dir : gConfig->apex_built_in_dirs) {
     LOG(INFO) << "Scanning " << dir;
@@ -3758,6 +3759,13 @@
         continue;
       }
 
+      if (auto it = apex_names.find(manifest->name()); it != apex_names.end()) {
+        LOG(ERROR) << "Failed to activate apex from " << apex_dir
+                   << " : duplicate of " << manifest->name() << " found in "
+                   << it->second;
+        return 1;
+      }
+
       std::string mount_point = std::string(kApexRoot) + "/" + manifest->name();
       if (mkdir(mount_point.c_str(), 0755) != 0) {
         PLOG(ERROR) << "Failed to mkdir " << mount_point;
@@ -3779,6 +3787,7 @@
                               /* isFactory= */ true, /* isActive= */ true,
                               /* lastUpdateMillis= */ 0,
                               /* provideSharedApexLibs= */ false);
+      apex_names.emplace(manifest->name(), apex_dir);
     }
   }
 
diff --git a/apexd/apexd_test.cpp b/apexd/apexd_test.cpp
index 606d1c1..766130d 100644
--- a/apexd/apexd_test.cpp
+++ b/apexd/apexd_test.cpp
@@ -83,6 +83,8 @@
 using ::testing::StartsWith;
 using ::testing::UnorderedElementsAre;
 using ::testing::UnorderedElementsAreArray;
+using ::testing::internal::CaptureStderr;
+using ::testing::internal::GetCapturedStderr;
 
 static std::string GetTestDataDir() { return GetExecutableDirectory(); }
 static std::string GetTestFile(const std::string& name) {
@@ -3048,29 +3050,25 @@
                                    ApexInfoXmlEq(apex_info_xml_2)));
 }
 
+void PrepareFlattenedApex(const std::string& apex_dir,
+                          const std::string& apex_name, int version) {
+  ASSERT_EQ(mkdir(apex_dir.c_str(), 0755), 0);
+
+  ::apex::proto::ApexManifest manifest;
+  manifest.set_name(apex_name);
+  manifest.set_version(version);
+  manifest.set_versionname(std::to_string(version));
+
+  std::string out;
+  manifest.SerializeToString(&out);
+  ASSERT_TRUE(WriteStringToFile(out, apex_dir + "/apex_manifest.pb"));
+}
+
 TEST_F(ApexdMountTest, ActivateFlattenedApex) {
   std::string apex_dir_1 = GetBuiltInDir() + "/com.android.apex.test_package";
   std::string apex_dir_2 = GetBuiltInDir() + "/com.android.apex.test_package_2";
-
-  ASSERT_EQ(mkdir(apex_dir_1.c_str(), 0755), 0);
-  ASSERT_EQ(mkdir(apex_dir_2.c_str(), 0755), 0);
-
-  auto write_manifest_fn = [&](const std::string& apex_dir,
-                               const std::string& module_name, int version) {
-    using ::apex::proto::ApexManifest;
-
-    ApexManifest manifest;
-    manifest.set_name(module_name);
-    manifest.set_version(version);
-    manifest.set_versionname(std::to_string(version));
-
-    std::string out;
-    manifest.SerializeToString(&out);
-    ASSERT_TRUE(WriteStringToFile(out, apex_dir + "/apex_manifest.pb"));
-  };
-
-  write_manifest_fn(apex_dir_1, "com.android.apex.test_package", 2);
-  write_manifest_fn(apex_dir_2, "com.android.apex.test_package_2", 1);
+  PrepareFlattenedApex(apex_dir_1, "com.android.apex.test_package", 2);
+  PrepareFlattenedApex(apex_dir_2, "com.android.apex.test_package_2", 1);
 
   ASSERT_EQ(ActivateFlattenedApex(), 0);
 
@@ -3108,6 +3106,20 @@
                                    ApexInfoXmlEq(apex_info_xml_2)));
 }
 
+TEST_F(ApexdMountTest, ActivateFlattenedApexShouldFailWithDuplicate) {
+  // Two flattened APEXes with the same name
+  PrepareFlattenedApex(GetBuiltInDir() + "/com.android.apex.test_package",
+                       "com.android.apex.test_package", 1);
+  PrepareFlattenedApex(GetBuiltInDir() + "/com.android.apex.test_package_2",
+                       "com.android.apex.test_package", 1);
+
+  CaptureStderr();
+  ASSERT_EQ(ActivateFlattenedApex(), 1);
+  std::string error = GetCapturedStderr();
+  ASSERT_THAT(error,
+              HasSubstr("duplicate of com.android.apex.test_package found"));
+}
+
 TEST_F(ApexdMountTest, OnStartOnlyPreInstalledApexes) {
   MockCheckpointInterface checkpoint_interface;
   // Need to call InitializeVold before calling OnStart