Use ordered sequences for namespace links am: b461a7bffd
am: 92549cf436

Change-Id: I5fe10e5462627f02fa635efc28a77f6e05e6e727
diff --git a/contents/tests/configuration/sphal_test.cc b/contents/tests/configuration/sphal_test.cc
new file mode 100644
index 0000000..51ac2a6
--- /dev/null
+++ b/contents/tests/configuration/sphal_test.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <string>
+
+#include "linkerconfig/context.h"
+#include "linkerconfig/namespacebuilder.h"
+
+#include <gtest/gtest.h>
+
+using namespace android::linkerconfig::contents;
+using namespace android::linkerconfig::modules;
+
+TEST(sphal, rs_should_come_before_vndk) {
+  Context ctx;
+  auto sphal = BuildSphalNamespace(ctx);
+  const auto& links = sphal.Links();
+  auto rs = std::find_if(begin(links), end(links), [](const auto& link) {
+    return link.To() == "rs";
+  });
+  auto vndk = std::find_if(begin(links), end(links), [](const auto& link) {
+    return link.To() == "vndk";
+  });
+  EXPECT_LT(rs, vndk) << "rs should come before vndk";
+}
diff --git a/modules/include/linkerconfig/link.h b/modules/include/linkerconfig/link.h
index 13c4093..860e943 100644
--- a/modules/include/linkerconfig/link.h
+++ b/modules/include/linkerconfig/link.h
@@ -39,7 +39,11 @@
   void AddSharedLib(T&& lib_name, Args&&... lib_names);
   void AddSharedLib(const std::vector<std::string>& lib_names);
   void AllowAllSharedLibs();
-  void WriteConfig(ConfigWriter& writer);
+  void WriteConfig(ConfigWriter& writer) const;
+
+  std::string To() const {
+    return target_namespace_;
+  }
 
  private:
   const std::string origin_namespace_;
diff --git a/modules/include/linkerconfig/namespace.h b/modules/include/linkerconfig/namespace.h
index 6198cd1..835021a 100644
--- a/modules/include/linkerconfig/namespace.h
+++ b/modules/include/linkerconfig/namespace.h
@@ -15,7 +15,6 @@
  */
 #pragma once
 
-#include <map>
 #include <string>
 #include <vector>
 
@@ -91,7 +90,7 @@
                         AsanPath path_from_asan = AsanPath::SAME_PATH);
 
   // Returns a link from this namespace to the given one. If one already exists
-  // it is returned, otherwise one is created.
+  // it is returned, otherwise one is created and pushed back to tail.
   Link& GetLink(const std::string& target_namespace);
 
   void WriteConfig(ConfigWriter& writer);
@@ -100,6 +99,9 @@
   std::string GetName() const;
 
   // For test usage
+  const std::vector<Link>& Links() const {
+    return links_;
+  }
   std::vector<std::string> SearchPaths() const {
     return search_paths_;
   }
@@ -115,7 +117,7 @@
   std::vector<std::string> asan_search_paths_;
   std::vector<std::string> asan_permitted_paths_;
   std::vector<std::string> whitelisted_;
-  std::map<std::string, Link> links_;
+  std::vector<Link> links_;
   void WritePathString(ConfigWriter& writer, const std::string& path_type,
                        const std::vector<std::string>& path_list);
 };
diff --git a/modules/link.cc b/modules/link.cc
index 19569ae..4c0e2e9 100644
--- a/modules/link.cc
+++ b/modules/link.cc
@@ -33,7 +33,7 @@
   }
 }
 
-void Link::WriteConfig(ConfigWriter& writer) {
+void Link::WriteConfig(ConfigWriter& writer) const {
   writer.SetPrefix("namespace." + origin_namespace_ + ".link." +
                    target_namespace_);
   if (allow_all_shared_libs_) {
diff --git a/modules/namespace.cc b/modules/namespace.cc
index 7fcf94f..5d134d6 100644
--- a/modules/namespace.cc
+++ b/modules/namespace.cc
@@ -51,9 +51,12 @@
 }
 
 Link& Namespace::GetLink(const std::string& target_namespace) {
-  auto iter =
-      links_.try_emplace(target_namespace, name_, target_namespace).first;
-  return iter->second;
+  for (auto& link : links_) {
+    if (link.To() == target_namespace) {
+      return link;
+    }
+  }
+  return links_.emplace_back(name_, target_namespace);
 }
 
 void Namespace::WriteConfig(ConfigWriter& writer) {
@@ -78,21 +81,15 @@
   }
 
   if (!links_.empty()) {
-    std::string link_list = "";
-
-    is_first = true;
-    for (auto& link : links_) {
-      if (!is_first) {
-        link_list += ",";
-      }
-      link_list += link.first;
-      is_first = false;
+    std::vector<std::string> link_list;
+    link_list.reserve(links_.size());
+    for (const auto& link : links_) {
+      link_list.push_back(link.To());
     }
+    writer.WriteLine("links = " + android::base::Join(link_list, ","));
 
-    writer.WriteLine("links = " + link_list);
-
-    for (auto& link : links_) {
-      link.second.WriteConfig(writer);
+    for (const auto& link : links_) {
+      link.WriteConfig(writer);
     }
   }