Merge "Read apex_manifest and generate Namespace"
am: 5fa6e715d4
Change-Id: I9da8e4ab2f96e0487ca1c28857a7d13d19a87ee1
diff --git a/Android.bp b/Android.bp
index bf980cd..c93ea50 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,6 +24,8 @@
static_libs: [
"libbase",
"liblog",
+ "libprotobuf-cpp-lite",
+ "lib_apex_manifest_proto_lite",
],
host_supported: true,
recovery_available: true,
@@ -100,6 +102,7 @@
"modules/tests/*_test.cc",
],
static_libs: [
+ "libgmock",
"linkerconfig_modules",
],
}
diff --git a/contents/tests/configuration/vndk_test.cc b/contents/tests/configuration/vndk_test.cc
index 495c42d..81d4b98 100644
--- a/contents/tests/configuration/vndk_test.cc
+++ b/contents/tests/configuration/vndk_test.cc
@@ -20,13 +20,13 @@
#include <unordered_map>
#include <vector>
+#include <gtest/gtest.h>
+
#include "linkerconfig/context.h"
#include "linkerconfig/namespace.h"
#include "linkerconfig/namespacebuilder.h"
#include "linkerconfig/sectionbuilder.h"
-#include "gtest/gtest.h"
-
using namespace android::linkerconfig::contents;
using namespace android::linkerconfig::modules;
diff --git a/modules/include/linkerconfig/link.h b/modules/include/linkerconfig/link.h
index 860e943..3208494 100644
--- a/modules/include/linkerconfig/link.h
+++ b/modules/include/linkerconfig/link.h
@@ -41,6 +41,10 @@
void AllowAllSharedLibs();
void WriteConfig(ConfigWriter& writer) const;
+ // accessors
+ std::vector<std::string> GetSharedLibs() const {
+ return shared_libs_;
+ }
std::string To() const {
return target_namespace_;
}
diff --git a/modules/include/linkerconfig/namespace.h b/modules/include/linkerconfig/namespace.h
index 64c69c8..1cc6a6b 100644
--- a/modules/include/linkerconfig/namespace.h
+++ b/modules/include/linkerconfig/namespace.h
@@ -19,6 +19,8 @@
#include <string>
#include <vector>
+#include <android-base/result.h>
+
#include "linkerconfig/configwriter.h"
#include "linkerconfig/link.h"
#include "linkerconfig/log.h"
@@ -109,10 +111,20 @@
bool ContainsSearchPath(const std::string& path, AsanPath path_from_asan);
bool ContainsPermittedPath(const std::string& path, AsanPath path_from_asan);
- void AddProvides(std::vector<std::string> list);
- void AddRequires(std::vector<std::string> list);
- const std::set<std::string>& GetProvides() const;
- const std::set<std::string>& GetRequires() const;
+ template <typename Vec>
+ void AddProvides(const Vec& list) {
+ provides_.insert(list.begin(), list.end());
+ }
+ template <typename Vec>
+ void AddRequires(const Vec& list) {
+ requires_.insert(list.begin(), list.end());
+ }
+ const std::set<std::string>& GetProvides() const {
+ return provides_;
+ }
+ const std::set<std::string>& GetRequires() const {
+ return requires_;
+ }
private:
const bool is_isolated_;
@@ -130,6 +142,10 @@
void WritePathString(ConfigWriter& writer, const std::string& path_type,
const std::vector<std::string>& path_list);
};
+
+::android::base::Result<void> InitializeWithApex(Namespace& ns,
+ const std::string& apex_path);
+
} // namespace modules
} // namespace linkerconfig
} // namespace android
diff --git a/modules/include/linkerconfig/section.h b/modules/include/linkerconfig/section.h
index c945fa2..7f2c4a1 100644
--- a/modules/include/linkerconfig/section.h
+++ b/modules/include/linkerconfig/section.h
@@ -20,7 +20,8 @@
#include <utility>
#include <vector>
-#include "android-base/result.h"
+#include <android-base/result.h>
+
#include "linkerconfig/configwriter.h"
#include "linkerconfig/namespace.h"
diff --git a/modules/namespace.cc b/modules/namespace.cc
index 3a36ee1..bdc45d5 100644
--- a/modules/namespace.cc
+++ b/modules/namespace.cc
@@ -16,11 +16,22 @@
#include "linkerconfig/namespace.h"
+#include <android-base/file.h>
#include <android-base/strings.h>
+#include <apex_manifest.pb.h>
#include "linkerconfig/log.h"
+using ::android::base::Error;
+using ::android::base::ReadFileToString;
+using ::android::base::Result;
+using ::android::base::WriteStringToFile;
+using ::apex::proto::ApexManifest;
+
namespace {
+
+constexpr const char* kDataAsanPath = "/data/asan";
+
bool FindFromPathList(const std::vector<std::string>& list,
const std::string& path) {
for (auto& path_member : list) {
@@ -31,13 +42,37 @@
return false;
}
+
+Result<ApexManifest> ParseApexManifest(const std::string& manifest_path) {
+ std::string content;
+ if (!ReadFileToString(manifest_path, &content)) {
+ return Error() << "Failed to read manifest file: " << manifest_path;
+ }
+
+ ApexManifest manifest;
+ if (!manifest.ParseFromString(content)) {
+ return Error() << "Can't parse APEX manifest.";
+ }
+ return manifest;
+}
+
} // namespace
namespace android {
namespace linkerconfig {
namespace modules {
-constexpr const char* kDataAsanPath = "/data/asan";
+Result<void> InitializeWithApex(Namespace& ns, const std::string& apex_path) {
+ auto apex_manifest = ParseApexManifest(apex_path + "/apex_manifest.pb");
+ if (!apex_manifest) {
+ return apex_manifest.error();
+ }
+ ns.AddSearchPath(apex_path + "/${LIB}");
+ ns.AddPermittedPath("/system/${LIB}");
+ ns.AddProvides(apex_manifest->providenativelibs());
+ ns.AddRequires(apex_manifest->requirenativelibs());
+ return {};
+}
void Namespace::WritePathString(ConfigWriter& writer,
const std::string& path_type,
@@ -155,21 +190,6 @@
FindFromPathList(asan_permitted_paths_, kDataAsanPath + path));
}
-void Namespace::AddProvides(std::vector<std::string> list) {
- provides_.insert(list.begin(), list.end());
-}
-
-void Namespace::AddRequires(std::vector<std::string> list) {
- requires_.insert(list.begin(), list.end());
-}
-
-const std::set<std::string>& Namespace::GetProvides() const {
- return provides_;
-}
-
-const std::set<std::string>& Namespace::GetRequires() const {
- return requires_;
-}
} // namespace modules
} // namespace linkerconfig
} // namespace android
diff --git a/modules/section.cc b/modules/section.cc
index 16ad7fb..b4e66f1 100644
--- a/modules/section.cc
+++ b/modules/section.cc
@@ -18,7 +18,7 @@
#include <unordered_map>
-#include "android-base/result.h"
+#include <android-base/result.h>
using android::base::Errorf;
using android::base::Result;
diff --git a/modules/tests/apex_test.cc b/modules/tests/apex_test.cc
new file mode 100644
index 0000000..72923a5
--- /dev/null
+++ b/modules/tests/apex_test.cc
@@ -0,0 +1,105 @@
+/*
+ * 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 <string>
+#include <utility>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/result.h>
+#include <android-base/stringprintf.h>
+#include <apex_manifest.pb.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "linkerconfig/configwriter.h"
+#include "linkerconfig/namespace.h"
+#include "linkerconfig/section.h"
+
+using ::android::base::Result;
+using ::android::base::StringPrintf;
+using ::android::base::WriteStringToFile;
+using ::android::linkerconfig::modules::ConfigWriter;
+using ::android::linkerconfig::modules::InitializeWithApex;
+using ::android::linkerconfig::modules::Namespace;
+using ::android::linkerconfig::modules::Section;
+using ::apex::proto::ApexManifest;
+using ::testing::Contains;
+
+namespace {
+
+void PrepareTestApexDir(const std::string& path, const std::string& name,
+ std::vector<std::string> provided_libs,
+ std::vector<std::string> required_libs) {
+ ApexManifest manifest;
+ manifest.set_name(name);
+ for (auto lib : provided_libs) {
+ manifest.add_providenativelibs(lib);
+ }
+ for (auto lib : required_libs) {
+ manifest.add_requirenativelibs(lib);
+ }
+ std::string content = manifest.SerializeAsString();
+ std::string manifest_path = path + "/apex_manifest.pb";
+ if (!WriteStringToFile(content, manifest_path)) {
+ LOG(ERROR) << "Failed to write a file: " << manifest_path;
+ }
+}
+
+} // namespace
+
+TEST(apex_namespace, build_namespace) {
+ TemporaryDir foo_dir;
+ PrepareTestApexDir(foo_dir.path, "foo", {}, {});
+
+ Namespace ns("foo");
+ auto result = InitializeWithApex(ns, foo_dir.path);
+ ASSERT_TRUE(result);
+
+ ConfigWriter writer;
+ ns.WriteConfig(writer);
+ ASSERT_EQ(
+ StringPrintf("namespace.foo.isolated = false\n"
+ "namespace.foo.search.paths = %s/${LIB}\n"
+ "namespace.foo.permitted.paths = /system/${LIB}\n"
+ "namespace.foo.asan.search.paths = %s/${LIB}\n"
+ "namespace.foo.asan.permitted.paths = /system/${LIB}\n",
+ foo_dir.path,
+ foo_dir.path),
+ writer.ToString());
+}
+
+TEST(apex_namespace, resolve_between_apex_namespaces) {
+ TemporaryDir foo_dir, bar_dir;
+ PrepareTestApexDir(foo_dir.path, "foo", {"foo.so"}, {"bar.so"});
+ PrepareTestApexDir(bar_dir.path, "bar", {"bar.so"}, {});
+
+ Namespace foo("foo"), bar("bar");
+ InitializeWithApex(foo, foo_dir.path);
+ InitializeWithApex(bar, bar_dir.path);
+
+ std::vector<Namespace> namespaces;
+ namespaces.push_back(std::move(foo));
+ namespaces.push_back(std::move(bar));
+ Section section("section", std::move(namespaces));
+
+ auto result = section.Resolve();
+ ASSERT_TRUE(result) << result.error();
+
+ // See if two namespaces are linked correctly
+ ASSERT_THAT(section.GetNamespace("foo")->GetLink("bar").GetSharedLibs(),
+ Contains("bar.so"));
+}
\ No newline at end of file
diff --git a/modules/tests/section_test.cc b/modules/tests/section_test.cc
index ef6cdba..8a5253e 100644
--- a/modules/tests/section_test.cc
+++ b/modules/tests/section_test.cc
@@ -14,11 +14,12 @@
* limitations under the License.
*/
+#include "linkerconfig/section.h"
+
+#include <android-base/result.h>
#include <gtest/gtest.h>
-#include "android-base/result.h"
#include "linkerconfig/configwriter.h"
-#include "linkerconfig/section.h"
#include "modules_testbase.h"
using android::base::Errorf;
@@ -129,12 +130,12 @@
TEST(linkerconfig_section, resolve_contraints) {
std::vector<Namespace> namespaces;
Namespace& foo = namespaces.emplace_back("foo");
- foo.AddProvides({"libfoo.so"});
- foo.AddRequires({"libbar.so"});
+ foo.AddProvides(std::vector{"libfoo.so"});
+ foo.AddRequires(std::vector{"libbar.so"});
Namespace& bar = namespaces.emplace_back("bar");
- bar.AddProvides({"libbar.so"});
+ bar.AddProvides(std::vector{"libbar.so"});
Namespace& baz = namespaces.emplace_back("baz");
- baz.AddRequires({"libfoo.so"});
+ baz.AddRequires(std::vector{"libfoo.so"});
Section section("section", std::move(namespaces));
section.Resolve();
@@ -158,11 +159,11 @@
TEST(linkerconfig_section, error_if_duplicate_providing) {
std::vector<Namespace> namespaces;
Namespace& foo1 = namespaces.emplace_back("foo1");
- foo1.AddProvides({"libfoo.so"});
+ foo1.AddProvides(std::vector{"libfoo.so"});
Namespace& foo2 = namespaces.emplace_back("foo2");
- foo2.AddProvides({"libfoo.so"});
+ foo2.AddProvides(std::vector{"libfoo.so"});
Namespace& bar = namespaces.emplace_back("bar");
- bar.AddRequires({"libfoo.so"});
+ bar.AddRequires(std::vector{"libfoo.so"});
Section section("section", std::move(namespaces));
auto result = section.Resolve();
@@ -173,7 +174,7 @@
TEST(linkerconfig_section, error_if_no_providers) {
std::vector<Namespace> namespaces;
Namespace& foo = namespaces.emplace_back("foo");
- foo.AddRequires({"libfoo.so"});
+ foo.AddRequires(std::vector{"libfoo.so"});
Section section("section", std::move(namespaces));
auto result = section.Resolve();