Manage dir list without priority
am: 96a4388208

Change-Id: I8fa86da3566b1def63426a884c271040b4599256
diff --git a/contents/namespace/conscrypt.cc b/contents/namespace/conscrypt.cc
index dbf7071..7015b37 100644
--- a/contents/namespace/conscrypt.cc
+++ b/contents/namespace/conscrypt.cc
@@ -21,14 +21,17 @@
 
 using android::linkerconfig::modules::Namespace;
 
+namespace {
 const std::vector<std::string> kLibsFromDefault = {"libc.so", "libm.so",
                                                    "libdl.so", "liblog.so"};
+}  // namespace
 
 namespace android {
 namespace linkerconfig {
 namespace contents {
 Namespace BuildConscryptNamespace([[maybe_unused]] const Context& ctx) {
-  Namespace ns("conscrypt", /*is_isolated=*/true, /*is_visible=*/true);
+  Namespace ns("conscrypt", /*is_isolated=*/true,
+               /*is_visible=*/true);
 
   ns.AddSearchPath("/apex/com.android.conscrypt/${LIB}", /*also_in_asan=*/true,
                    /*with_data_asan=*/false);
diff --git a/contents/namespace/media.cc b/contents/namespace/media.cc
index 8b594a6..f332a41 100644
--- a/contents/namespace/media.cc
+++ b/contents/namespace/media.cc
@@ -23,6 +23,7 @@
 
 using android::linkerconfig::modules::Namespace;
 
+namespace {
 const std::vector<std::string> kLibsFromDefaultLegacy = {
     "libandroid.so",
     "libbinder_ndk.so",
@@ -43,6 +44,7 @@
 const std::vector<std::string> kLibsFromDefault = {
     "@{LLNDK_LIBRARIES}", "libandroid.so", "libbinder_ndk.so",
     "libmediametrics.so", "@{SANITIZER_RUNTIME_LIBRARIES}"};
+}  // namespace
 
 namespace android {
 namespace linkerconfig {
diff --git a/contents/namespace/postinstall.cc b/contents/namespace/postinstall.cc
index f7ef8e6..e7a1e18 100644
--- a/contents/namespace/postinstall.cc
+++ b/contents/namespace/postinstall.cc
@@ -22,7 +22,8 @@
 namespace linkerconfig {
 namespace contents {
 Namespace BuildPostInstallNamespace([[maybe_unused]] const Context& ctx) {
-  Namespace ns("default", /*is_isolated=*/false, /*is_visible=*/false);
+  Namespace ns("default", /*is_isolated=*/false,
+               /*is_visible=*/false);
   ns.AddSearchPath("/system/${LIB}");
   ns.AddSearchPath("/@{PRODUCT:product}/${LIB}");
 
diff --git a/contents/namespace/resolv.cc b/contents/namespace/resolv.cc
index d68d060..57cae95 100644
--- a/contents/namespace/resolv.cc
+++ b/contents/namespace/resolv.cc
@@ -21,12 +21,14 @@
 
 using android::linkerconfig::modules::Namespace;
 
+namespace {
 const std::vector<std::string> kLibsFromDefault = {
     "libc.so",          "libcgrouprc.so", "libm.so",          "libdl.so",
     "libbinder_ndk.so", "liblog.so",      "libvndksupport.so"};
 
 const std::vector<std::string> kLibsFromUnrestrictedDefault = {
     "libc.so", "libm.so", "libdl.so", "libbinder_ndk.so", "liblog.so"};
+}  // namespace
 
 namespace android {
 namespace linkerconfig {
diff --git a/contents/namespace/systemdefault.cc b/contents/namespace/systemdefault.cc
index ada0343..b3e5f39 100644
--- a/contents/namespace/systemdefault.cc
+++ b/contents/namespace/systemdefault.cc
@@ -21,6 +21,7 @@
 
 using android::linkerconfig::modules::Namespace;
 
+namespace {
 const std::vector<std::string> kLibsFromRuntimeLegacy = {
     "libart.so:libartd.so", "libdexfile_external.so", "libnativebridge.so",
     "libnativehelper.so", "libnativeloader.so", "libandroidicu.so",
@@ -46,8 +47,6 @@
     "/@{PRODUCT_SERVICES:product_services}/priv-app", "/data", "/mnt/expand",
     "/apex/com.android.runtime/${LIB}/bionic", "/system/${LIB}/bootstrap"};
 
-namespace {
-using android::linkerconfig::modules::Namespace;
 void BuildPermittedPath(Namespace& ns) {
   for (const auto& path : kPermittedPaths) {
     ns.AddPermittedPath(path, true, false);
@@ -60,7 +59,8 @@
 namespace contents {
 Namespace BuildSystemDefaultNamespace([[maybe_unused]] const Context& ctx) {
   bool is_legacy = android::linkerconfig::modules::IsLegacyDevice();
-  Namespace ns("default", /*is_isolated=*/!is_legacy, /*is_visible=*/true);
+  Namespace ns("default", /*is_isolated=*/!is_legacy,
+               /*is_visible=*/true);
 
   ns.AddSearchPath("/system/${LIB}", /*also_in_asan=*/true,
                    /*with_data_asan=*/true);
diff --git a/contents/namespace/unrestricteddefault.cc b/contents/namespace/unrestricteddefault.cc
index 9c8bf56..a329f14 100644
--- a/contents/namespace/unrestricteddefault.cc
+++ b/contents/namespace/unrestricteddefault.cc
@@ -21,9 +21,11 @@
 
 using android::linkerconfig::modules::Namespace;
 
+namespace {
 const std::vector<std::string> kLibsFromRuntime = {
     "libdexfile_external.so", "libnativebridge.so", "libnativehelper.so",
     "libnativeloader.so",     "libandroidicu.so",   "libpac.so"};
+}  // namespace
 
 namespace android {
 namespace linkerconfig {
diff --git a/contents/namespace/vndkinsystem.cc b/contents/namespace/vndkinsystem.cc
index 0745fcd..05ab95b 100644
--- a/contents/namespace/vndkinsystem.cc
+++ b/contents/namespace/vndkinsystem.cc
@@ -22,7 +22,8 @@
 namespace linkerconfig {
 namespace contents {
 Namespace BuildVndkInSystemNamespace([[maybe_unused]] const Context& ctx) {
-  Namespace ns("vndk_in_system", /*is_isolated=*/true, /*is_visible=*/true);
+  Namespace ns("vndk_in_system", /*is_isolated=*/true,
+               /*is_visible=*/true);
 
   ns.AddSearchPath("/system/${LIB}", /*also_in_asan=*/true,
                    /*with_data_asan=*/true);
diff --git a/contents/section/legacy.cc b/contents/section/legacy.cc
index 89e7c04..20281f0 100644
--- a/contents/section/legacy.cc
+++ b/contents/section/legacy.cc
@@ -20,16 +20,14 @@
 #include "linkerconfig/section.h"
 
 using android::linkerconfig::contents::SectionType;
-using android::linkerconfig::modules::kDefaultPriority;
 using android::linkerconfig::modules::Namespace;
 using android::linkerconfig::modules::Section;
 
-const android::linkerconfig::modules::BinaryPathList kLegacyBinaryPath = {
-    {"/system", kDefaultPriority},
-    {"/product", kDefaultPriority},
-    {"/vendor", kDefaultPriority},
-    {"/odm", kDefaultPriority},
-    {"/sbin", kDefaultPriority}};
+namespace {
+const std::vector<std::string> kLegacyBinaryPath = {
+    "/system", "/product", "/vendor", "/odm", "/sbin",
+};
+}  // namespace
 
 namespace android {
 namespace linkerconfig {
diff --git a/contents/section/postinstall.cc b/contents/section/postinstall.cc
index 8aa8f16..8c51203 100644
--- a/contents/section/postinstall.cc
+++ b/contents/section/postinstall.cc
@@ -19,12 +19,12 @@
 #include "linkerconfig/namespacebuilder.h"
 
 using android::linkerconfig::contents::SectionType;
-using android::linkerconfig::modules::kDefaultPriority;
 using android::linkerconfig::modules::Namespace;
 using android::linkerconfig::modules::Section;
 
-const android::linkerconfig::modules::BinaryPathList kBinaryPath = {
-    {"/postinstall", kDefaultPriority}};
+namespace {
+const std::vector<std::string> kBinaryPath = {"/postinstall"};
+}  // namespace
 
 namespace android {
 namespace linkerconfig {
diff --git a/contents/section/system.cc b/contents/section/system.cc
index 9b2f9e2..e798e8f 100644
--- a/contents/section/system.cc
+++ b/contents/section/system.cc
@@ -21,16 +21,17 @@
 #include "linkerconfig/section.h"
 
 using android::linkerconfig::contents::SectionType;
-using android::linkerconfig::modules::kDefaultPriority;
-using android::linkerconfig::modules::kLowPriority;
 using android::linkerconfig::modules::Namespace;
 using android::linkerconfig::modules::Section;
 
-const android::linkerconfig::modules::BinaryPathList kBinaryPath = {
-    {"/system/bin/", kDefaultPriority},
-    {"/system/xbin/", kDefaultPriority},
-    {"/@{PRODUCT:product}/bin/", kDefaultPriority},
-    {"/data", kLowPriority}};
+namespace {
+const std::vector<std::string> kBinaryPath = {
+    "/system/bin/",
+    "/system/xbin/",
+    "/@{PRODUCT:product}/bin/",
+    "/data",
+};
+}  // namespace
 
 namespace android {
 namespace linkerconfig {
diff --git a/contents/section/unrestricted.cc b/contents/section/unrestricted.cc
index 8057f5a..2cc8b20 100644
--- a/contents/section/unrestricted.cc
+++ b/contents/section/unrestricted.cc
@@ -21,14 +21,16 @@
 #include "linkerconfig/section.h"
 
 using android::linkerconfig::contents::SectionType;
-using android::linkerconfig::modules::kDefaultPriority;
 using android::linkerconfig::modules::Namespace;
 using android::linkerconfig::modules::Section;
 
-const android::linkerconfig::modules::BinaryPathList kBinaryPath = {
-    {"/data/nativetest/unrestricted", kDefaultPriority},
-    {"/data/nativetest64/unrestricted", kDefaultPriority},
-    {"/data/local/tmp", kDefaultPriority}};
+namespace {
+const std::vector<std::string> kBinaryPath = {
+    "/data/nativetest/unrestricted",
+    "/data/nativetest64/unrestricted",
+    "/data/local/tmp",
+};
+}  // namespace
 
 namespace android {
 namespace linkerconfig {
diff --git a/contents/section/vendor.cc b/contents/section/vendor.cc
index 3079c6b..64f2ca2 100644
--- a/contents/section/vendor.cc
+++ b/contents/section/vendor.cc
@@ -21,21 +21,23 @@
 #include "linkerconfig/section.h"
 
 using android::linkerconfig::contents::SectionType;
-using android::linkerconfig::modules::kDefaultPriority;
 using android::linkerconfig::modules::Namespace;
 using android::linkerconfig::modules::Section;
 
-const android::linkerconfig::modules::BinaryPathList kBinaryPath = {
-    {"/odm/bin/", kDefaultPriority},
-    {"/vendor/bin/", kDefaultPriority},
-    {"/data/nativetest/odm", kDefaultPriority},
-    {"/data/nativetest64/odm", kDefaultPriority},
-    {"/data/benchmarktest/odm", kDefaultPriority},
-    {"/data/benchmarktest64/odm", kDefaultPriority},
-    {"/data/nativetest/vendor", kDefaultPriority},
-    {"/data/nativetest64/vendor", kDefaultPriority},
-    {"/data/benchmarktest/vendor", kDefaultPriority},
-    {"/data/benchmarktest64/vendor", kDefaultPriority}};
+namespace {
+const std::vector<std::string> kBinaryPath = {
+    "/odm/bin/",
+    "/vendor/bin/",
+    "/data/nativetest/odm",
+    "/data/nativetest64/odm",
+    "/data/benchmarktest/odm",
+    "/data/benchmarktest64/odm",
+    "/data/nativetest/vendor",
+    "/data/nativetest64/vendor",
+    "/data/benchmarktest/vendor",
+    "/data/benchmarktest64/vendor",
+};
+}  // namespace
 
 namespace android {
 namespace linkerconfig {
diff --git a/contents/tests/backward_compatibility/default_test.cc b/contents/tests/backward_compatibility/default_test.cc
index 668e9fa..1a8636a 100644
--- a/contents/tests/backward_compatibility/default_test.cc
+++ b/contents/tests/backward_compatibility/default_test.cc
@@ -18,7 +18,6 @@
 
 #include "linkerconfig/baseconfig.h"
 
-#include "linkerconfig/configwriter.h"
 #include "linkerconfig/variables.h"
 #include "testbase.h"
 
diff --git a/modules/configuration.cc b/modules/configuration.cc
index 5cf7cd2..544a8ce 100644
--- a/modules/configuration.cc
+++ b/modules/configuration.cc
@@ -20,14 +20,15 @@
 namespace linkerconfig {
 namespace modules {
 void Configuration::WriteConfig(ConfigWriter& writer) {
-  BinaryPathMap binary_paths_with_priority;
+  BinaryPathMap binary_paths;
 
   for (auto& section : sections_) {
-    section.CollectBinaryPaths(binary_paths_with_priority);
+    section.CollectBinaryPaths(binary_paths);
   }
 
-  for (auto& binary_path : binary_paths_with_priority) {
-    writer.WriteLine(binary_path.second);
+  // Navigate in reverse order to keep sub directories on top of parent directory
+  for (auto it = binary_paths.rbegin(); it != binary_paths.rend(); it++) {
+    writer.WriteLine("dir.%s = %s", it->second.c_str(), it->first.c_str());
   }
 
   for (auto& section : sections_) {
diff --git a/modules/include/linkerconfig/link.h b/modules/include/linkerconfig/link.h
index 53a7b66..25d9dd4 100644
--- a/modules/include/linkerconfig/link.h
+++ b/modules/include/linkerconfig/link.h
@@ -27,10 +27,10 @@
 namespace modules {
 class Link {
  public:
-  Link(const std::string& origin_namespace, const std::string& target_namespace,
+  Link(std::string origin_namespace, std::string target_namespace,
        bool allow_all_shared_libs = false)
-      : origin_namespace_(origin_namespace),
-        target_namespace_(target_namespace),
+      : origin_namespace_(std::move(origin_namespace)),
+        target_namespace_(std::move(target_namespace)),
         allow_all_shared_libs_(allow_all_shared_libs) {
   }
   Link(const Link&) = delete;
diff --git a/modules/include/linkerconfig/namespace.h b/modules/include/linkerconfig/namespace.h
index 3289454..c0176a4 100644
--- a/modules/include/linkerconfig/namespace.h
+++ b/modules/include/linkerconfig/namespace.h
@@ -29,9 +29,11 @@
 namespace modules {
 class Namespace {
  public:
-  Namespace(const std::string& name, bool is_isolated = false,
-            bool is_visible = false)
-      : is_isolated_(is_isolated), is_visible_(is_visible), name_(name) {
+  explicit Namespace(std::string name, bool is_isolated = false,
+                     bool is_visible = false)
+      : is_isolated_(is_isolated),
+        is_visible_(is_visible),
+        name_(std::move(name)) {
   }
 
   Namespace(const Namespace& ns) = delete;
diff --git a/modules/include/linkerconfig/section.h b/modules/include/linkerconfig/section.h
index 2a40564..7ee707d 100644
--- a/modules/include/linkerconfig/section.h
+++ b/modules/include/linkerconfig/section.h
@@ -27,20 +27,14 @@
 namespace linkerconfig {
 namespace modules {
 
-using BinaryPathPriority = unsigned int;
-using BinaryPathMap = std::multimap<BinaryPathPriority, std::string>;
-using BinaryPathList = std::vector<std::pair<std::string, BinaryPathPriority>>;
-
-constexpr const static BinaryPathPriority kHighPriority = 20;
-constexpr const static BinaryPathPriority kDefaultPriority = 50;
-constexpr const static BinaryPathPriority kLowPriority = 80;
+using BinaryPathMap = std::map<std::string, std::string>;
 
 class Section {
  public:
-  Section(const std::string& name, BinaryPathList binary_paths,
+  Section(std::string name, std::vector<std::string> binary_paths,
           std::vector<Namespace> namespaces)
-      : name_(name),
-        binary_paths_(binary_paths),
+      : name_(std::move(name)),
+        binary_paths_(std::move(binary_paths)),
         namespaces_(std::move(namespaces)) {
   }
 
@@ -56,7 +50,7 @@
 
  private:
   const std::string name_;
-  BinaryPathList binary_paths_;
+  std::vector<std::string> binary_paths_;
   std::vector<Namespace> namespaces_;
 };
 }  // namespace modules
diff --git a/modules/section.cc b/modules/section.cc
index 765c4fc..9fdf026 100644
--- a/modules/section.cc
+++ b/modules/section.cc
@@ -47,11 +47,16 @@
   }
 }
 
-void Section::CollectBinaryPaths(BinaryPathMap& binary_paths) {
-  std::string prefix = "dir." + name_ + " = ";
-  for (auto& item : binary_paths_) {
-    std::string path_config = prefix + item.first;
-    binary_paths.insert(std::make_pair(item.second, path_config));
+void Section::CollectBinaryPaths(BinaryPathMap& all_binary_paths) {
+  for (auto& path : binary_paths_) {
+    auto it = all_binary_paths.find(path);
+    if (it != all_binary_paths.end()) {
+      LOG(WARNING) << "Binary path " << path << " already found from "
+                   << it->second << ". Path from " << name_
+                   << " will be ignored.";
+    } else {
+      all_binary_paths.emplace(std::make_pair(path, name_));
+    }
   }
 }
 
diff --git a/modules/tests/configuration_test.cc b/modules/tests/configuration_test.cc
index 0ad2107..61abb21 100644
--- a/modules/tests/configuration_test.cc
+++ b/modules/tests/configuration_test.cc
@@ -22,12 +22,13 @@
 using namespace android::linkerconfig::modules;
 
 constexpr const char* kExpectedConfiguration =
-    R"(dir.system = /system/bin
+    R"(dir.vendor = /vendor/bin
 dir.system = /system/xbin
-dir.vendor = /odm/bin
-dir.vendor = /vendor/bin
-dir.vendor = /data/nativetest/odm
+dir.vendor = /system/bin/vendor
+dir.system = /system/bin
+dir.vendor = /product/bin/vendor
 dir.system = /product/bin
+dir.vendor = /odm/bin
 [system]
 additional.namespaces = namespace1,namespace2
 namespace.default.isolated = false
@@ -94,9 +95,11 @@
   std::vector<Section> sections;
 
   std::vector<Namespace> system_namespaces;
-  BinaryPathList system_binary_path = {{"/system/bin", kDefaultPriority},
-                                       {"/system/xbin", kDefaultPriority},
-                                       {"/product/bin", kLowPriority + 10}};
+  std::vector<std::string> system_binary_path = {
+      "/system/bin",
+      "/system/xbin",
+      "/product/bin",
+  };
 
   system_namespaces.emplace_back(CreateNamespaceWithLinks(
       "default", false, false, "namespace1", "namespace2"));
@@ -110,9 +113,8 @@
   sections.emplace_back(std::move(system_section));
 
   std::vector<Namespace> vendor_namespaces;
-  BinaryPathList vendor_binary_path = {{"/odm/bin", kLowPriority},
-                                       {"/vendor/bin", kLowPriority},
-                                       {"/data/nativetest/odm", kLowPriority}};
+  std::vector<std::string> vendor_binary_path = {
+      "/odm/bin", "/vendor/bin", "/system/bin/vendor", "/product/bin/vendor"};
 
   vendor_namespaces.emplace_back(
       CreateNamespaceWithPaths("default", false, false));
diff --git a/modules/tests/section_test.cc b/modules/tests/section_test.cc
index 6c3d181..970986b 100644
--- a/modules/tests/section_test.cc
+++ b/modules/tests/section_test.cc
@@ -95,9 +95,9 @@
 )";
 
 constexpr const char* kSectionBinaryPathExpectedResult =
-    R"(dir.test_section = binary_path1
-dir.test_section = binary_path2
-dir.test_section = binary_path3
+    R"(/root/a
+/root/a/b
+/root/b
 )";
 
 TEST(linkerconfig_section, section_with_namespaces) {
@@ -111,7 +111,7 @@
                                                    "default", "namespace2"));
   namespaces.emplace_back(CreateNamespaceWithPaths("namespace2", false, false));
 
-  BinaryPathList empty_list;
+  std::vector<std::string> empty_list;
 
   Section section("test_section", empty_list, std::move(namespaces));
 
@@ -126,7 +126,7 @@
   std::vector<Namespace> namespaces;
   namespaces.emplace_back(CreateNamespaceWithPaths("default", false, false));
 
-  BinaryPathList empty_list;
+  std::vector<std::string> empty_list;
 
   Section section("test_section", empty_list, std::move(namespaces));
   section.WriteConfig(writer);
@@ -135,19 +135,35 @@
 }
 
 TEST(linkerconfig_section, binary_paths) {
-  BinaryPathList binary_paths = {{"binary_path2", kLowPriority},
-                                 {"binary_path3", kLowPriority + 10},
-                                 {"binary_path1", kDefaultPriority}};
+  std::vector<std::string> binary_paths = {"/root/a", "/root/a/b", "/root/b"};
   std::vector<Namespace> empty_namespace;
   Section section("test_section", binary_paths, std::move(empty_namespace));
 
-  android::linkerconfig::modules::BinaryPathMap paths;
+  BinaryPathMap paths;
   section.CollectBinaryPaths(paths);
 
   std::string binary_path_output = "";
   for (auto& item : paths) {
-    binary_path_output += item.second + "\n";
+    binary_path_output += item.first + "\n";
   }
 
   ASSERT_EQ(binary_path_output, kSectionBinaryPathExpectedResult);
+}
+
+TEST(linkerconfig_section, same_binary_paths) {
+  std::vector<std::string> binary_paths_a = {"/root/a", "/root/b"};
+  std::vector<Namespace> empty_namespace_a;
+  Section section_a("test_section_a", binary_paths_a,
+                    std::move(empty_namespace_a));
+
+  std::vector<std::string> binary_paths_b = {"/root/b", "/root/c"};
+  std::vector<Namespace> empty_namespace_b;
+  Section section_b("test_section_b", binary_paths_b,
+                    std::move(empty_namespace_b));
+
+  BinaryPathMap paths;
+  section_a.CollectBinaryPaths(paths);
+  section_b.CollectBinaryPaths(paths);
+
+  ASSERT_EQ(paths["/root/b"], "test_section_a");
 }
\ No newline at end of file