Loading libnativeloader/library_namespaces.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -124,7 +124,7 @@ void LibraryNamespaces::Initialize() { // we might as well end up loading them from /system/lib or /product/lib // we might as well end up loading them from /system/lib or /product/lib // For now we rely on CTS test to catch things like this but // For now we rely on CTS test to catch things like this but // it should probably be addressed in the future. // it should probably be addressed in the future. for (const auto& soname : android::base::Split(default_public_libraries(), ":")) { for (const auto& soname : android::base::Split(preloadable_public_libraries(), ":")) { LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr, LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr, "Error preloading public library %s: %s", soname.c_str(), dlerror()); "Error preloading public library %s: %s", soname.c_str(), dlerror()); } } Loading libnativeloader/native_loader_test.cpp +84 −1 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include "public_libraries.h" #include "public_libraries.h" using namespace ::testing; using namespace ::testing; using namespace ::android::nativeloader::internal; namespace android { namespace android { namespace nativeloader { namespace nativeloader { Loading Loading @@ -289,7 +290,7 @@ class NativeLoaderTest : public ::testing::TestWithParam<bool> { void SetExpectations() { void SetExpectations() { std::vector<std::string> default_public_libs = std::vector<std::string> default_public_libs = android::base::Split(default_public_libraries(), ":"); android::base::Split(preloadable_public_libraries(), ":"); for (auto l : default_public_libs) { for (auto l : default_public_libs) { EXPECT_CALL(*mock, dlopen(StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE)) EXPECT_CALL(*mock, dlopen(StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE)) .WillOnce(Return(any_nonnull)); .WillOnce(Return(any_nonnull)); Loading Loading @@ -576,5 +577,87 @@ TEST_P(NativeLoaderTest_Create, TwoApks) { INSTANTIATE_TEST_SUITE_P(NativeLoaderTests_Create, NativeLoaderTest_Create, testing::Bool()); INSTANTIATE_TEST_SUITE_P(NativeLoaderTests_Create, NativeLoaderTest_Create, testing::Bool()); const std::function<Result<bool>(const struct ConfigEntry&)> always_true = [](const struct ConfigEntry&) -> Result<bool> { return true; }; TEST(NativeLoaderConfigParser, NamesAndComments) { const char file_content[] = R"( ###### libA.so #libB.so libC.so libD.so #### libE.so )"; const std::vector<std::string> expected_result = {"libA.so", "libC.so", "libD.so"}; Result<std::vector<std::string>> result = ParseConfig(file_content, always_true); ASSERT_TRUE(result) << result.error().message(); ASSERT_EQ(expected_result, *result); } TEST(NativeLoaderConfigParser, WithBitness) { const char file_content[] = R"( libA.so 32 libB.so 64 libC.so )"; #if defined(__LP64__) const std::vector<std::string> expected_result = {"libB.so", "libC.so"}; #else const std::vector<std::string> expected_result = {"libA.so", "libC.so"}; #endif Result<std::vector<std::string>> result = ParseConfig(file_content, always_true); ASSERT_TRUE(result) << result.error().message(); ASSERT_EQ(expected_result, *result); } TEST(NativeLoaderConfigParser, WithNoPreload) { const char file_content[] = R"( libA.so nopreload libB.so nopreload libC.so )"; const std::vector<std::string> expected_result = {"libC.so"}; Result<std::vector<std::string>> result = ParseConfig(file_content, [](const struct ConfigEntry& entry) -> Result<bool> { return !entry.nopreload; }); ASSERT_TRUE(result) << result.error().message(); ASSERT_EQ(expected_result, *result); } TEST(NativeLoaderConfigParser, WithNoPreloadAndBitness) { const char file_content[] = R"( libA.so nopreload 32 libB.so 64 nopreload libC.so 32 libD.so 64 libE.so nopreload )"; #if defined(__LP64__) const std::vector<std::string> expected_result = {"libD.so"}; #else const std::vector<std::string> expected_result = {"libC.so"}; #endif Result<std::vector<std::string>> result = ParseConfig(file_content, [](const struct ConfigEntry& entry) -> Result<bool> { return !entry.nopreload; }); ASSERT_TRUE(result) << result.error().message(); ASSERT_EQ(expected_result, *result); } TEST(NativeLoaderConfigParser, RejectMalformed) { ASSERT_FALSE(ParseConfig("libA.so 32 64", always_true)); ASSERT_FALSE(ParseConfig("libA.so 32 32", always_true)); ASSERT_FALSE(ParseConfig("libA.so 32 nopreload 64", always_true)); ASSERT_FALSE(ParseConfig("32 libA.so nopreload", always_true)); ASSERT_FALSE(ParseConfig("nopreload libA.so 32", always_true)); ASSERT_FALSE(ParseConfig("libA.so nopreload # comment", always_true)); } } // namespace nativeloader } // namespace nativeloader } // namespace android } // namespace android libnativeloader/public_libraries.cpp +87 −49 Original line number Original line Diff line number Diff line Loading @@ -34,7 +34,8 @@ namespace android::nativeloader { namespace android::nativeloader { using namespace std::string_literals; using namespace internal; using namespace ::std::string_literals; using android::base::ErrnoError; using android::base::ErrnoError; using android::base::Errorf; using android::base::Errorf; using android::base::Result; using android::base::Result; Loading Loading @@ -95,53 +96,21 @@ void InsertVndkVersionStr(std::string* file_name) { file_name->insert(insert_pos, vndk_version_str()); file_name->insert(insert_pos, vndk_version_str()); } } const std::function<Result<void>(const std::string&)> always_true = const std::function<Result<bool>(const struct ConfigEntry&)> always_true = [](const std::string&) -> Result<void> { return {}; }; [](const struct ConfigEntry&) -> Result<bool> { return true; }; Result<std::vector<std::string>> ReadConfig( Result<std::vector<std::string>> ReadConfig( const std::string& configFile, const std::string& configFile, const std::function<Result<void>(const std::string& /* soname */)>& check_soname) { const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn) { // Read list of public native libraries from the config file. std::string file_content; std::string file_content; if (!base::ReadFileToString(configFile, &file_content)) { if (!base::ReadFileToString(configFile, &file_content)) { return ErrnoError(); return ErrnoError(); } } Result<std::vector<std::string>> result = ParseConfig(file_content, filter_fn); std::vector<std::string> lines = base::Split(file_content, "\n"); if (!result) { return Errorf("Cannot parse {}: {}", configFile, result.error().message()); std::vector<std::string> sonames; for (auto& line : lines) { auto trimmed_line = base::Trim(line); if (trimmed_line[0] == '#' || trimmed_line.empty()) { continue; } size_t space_pos = trimmed_line.rfind(' '); if (space_pos != std::string::npos) { std::string type = trimmed_line.substr(space_pos + 1); if (type != "32" && type != "64") { return Errorf("Malformed line: {}", line); } #if defined(__LP64__) // Skip 32 bit public library. if (type == "32") { continue; } #else // Skip 64 bit public library. if (type == "64") { continue; } } #endif return result; trimmed_line.resize(space_pos); } auto ret = check_soname(trimmed_line); if (!ret) { return ret.error(); } sonames.push_back(trimmed_line); } return sonames; } } void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) { void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) { Loading @@ -165,13 +134,13 @@ void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonam config_file_path.c_str()); config_file_path.c_str()); auto ret = ReadConfig( auto ret = ReadConfig( config_file_path, [&company_name](const std::string& soname) -> Result<void> { config_file_path, [&company_name](const struct ConfigEntry& entry) -> Result<bool> { if (android::base::StartsWith(soname, "lib") && if (android::base::StartsWith(entry.soname, "lib") && android::base::EndsWith(soname, "." + company_name + ".so")) { android::base::EndsWith(entry.soname, "." + company_name + ".so")) { return {}; return true; } else { } else { return Errorf("Library name \"{}\" does not end with the company name {}.", soname, return Errorf("Library name \"{}\" does not end with the company name {}.", company_name); entry.soname, company_name); } } }); }); if (ret) { if (ret) { Loading @@ -185,9 +154,16 @@ void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonam } } } } static std::string InitDefaultPublicLibraries() { static std::string InitDefaultPublicLibraries(bool for_preload) { std::string config_file = root_dir() + kDefaultPublicLibrariesFile; std::string config_file = root_dir() + kDefaultPublicLibrariesFile; auto sonames = ReadConfig(config_file, always_true); auto sonames = ReadConfig(config_file, [&for_preload](const struct ConfigEntry& entry) -> Result<bool> { if (for_preload) { return !entry.nopreload; } else { return true; } }); if (!sonames) { if (!sonames) { LOG_ALWAYS_FATAL("Error reading public native library list from \"%s\": %s", LOG_ALWAYS_FATAL("Error reading public native library list from \"%s\": %s", config_file.c_str(), sonames.error().message().c_str()); config_file.c_str(), sonames.error().message().c_str()); Loading Loading @@ -290,8 +266,13 @@ static std::string InitNeuralNetworksPublicLibraries() { } // namespace } // namespace const std::string& preloadable_public_libraries() { static std::string list = InitDefaultPublicLibraries(/*for_preload*/ true); return list; } const std::string& default_public_libraries() { const std::string& default_public_libraries() { static std::string list = InitDefaultPublicLibraries(); static std::string list = InitDefaultPublicLibraries(/*for_preload*/ false); return list; return list; } } Loading Loading @@ -325,4 +306,61 @@ const std::string& vndksp_libraries() { return list; return list; } } namespace internal { // Exported for testing Result<std::vector<std::string>> ParseConfig( const std::string& file_content, const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn) { std::vector<std::string> lines = base::Split(file_content, "\n"); std::vector<std::string> sonames; for (auto& line : lines) { auto trimmed_line = base::Trim(line); if (trimmed_line[0] == '#' || trimmed_line.empty()) { continue; } std::vector<std::string> tokens = android::base::Split(trimmed_line, " "); if (tokens.size() < 1 || tokens.size() > 3) { return Errorf("Malformed line \"{}\"", line); } struct ConfigEntry entry = {.soname = "", .nopreload = false, .bitness = ALL}; size_t i = tokens.size(); while (i-- > 0) { if (tokens[i] == "nopreload") { entry.nopreload = true; } else if (tokens[i] == "32" || tokens[i] == "64") { if (entry.bitness != ALL) { return Errorf("Malformed line \"{}\": bitness can be specified only once", line); } entry.bitness = tokens[i] == "32" ? ONLY_32 : ONLY_64; } else { if (i != 0) { return Errorf("Malformed line \"{}\"", line); } entry.soname = tokens[i]; } } // skip 32-bit lib on 64-bit process and vice versa #if defined(__LP64__) if (entry.bitness == ONLY_32) continue; #else if (entry.bitness == ONLY_64) continue; #endif Result<bool> ret = filter_fn(entry); if (!ret) { return ret.error(); } if (*ret) { // filter_fn has returned true. sonames.push_back(entry.soname); } } return sonames; } } // namespace internal } // namespace android::nativeloader } // namespace android::nativeloader libnativeloader/public_libraries.h +24 −1 Original line number Original line Diff line number Diff line Loading @@ -15,13 +15,19 @@ */ */ #pragma once #pragma once #include <algorithm> #include <string> #include <string> #include <android-base/result.h> namespace android::nativeloader { namespace android::nativeloader { using android::base::Result; // These provide the list of libraries that are available to the namespace for apps. // These provide the list of libraries that are available to the namespace for apps. // Not all of the libraries are available to apps. Depending on the context, // Not all of the libraries are available to apps. Depending on the context, // e.g., if it is a vendor app or not, different set of libraries are made available. // e.g., if it is a vendor app or not, different set of libraries are made available. const std::string& preloadable_public_libraries(); const std::string& default_public_libraries(); const std::string& default_public_libraries(); const std::string& runtime_public_libraries(); const std::string& runtime_public_libraries(); const std::string& vendor_public_libraries(); const std::string& vendor_public_libraries(); Loading @@ -30,4 +36,21 @@ const std::string& neuralnetworks_public_libraries(); const std::string& llndk_libraries(); const std::string& llndk_libraries(); const std::string& vndksp_libraries(); const std::string& vndksp_libraries(); }; // namespace android::nativeloader // These are exported for testing namespace internal { enum Bitness { ALL = 0, ONLY_32, ONLY_64 }; struct ConfigEntry { std::string soname; bool nopreload; Bitness bitness; }; Result<std::vector<std::string>> ParseConfig( const std::string& file_content, const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn); } // namespace internal } // namespace android::nativeloader Loading
libnativeloader/library_namespaces.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -124,7 +124,7 @@ void LibraryNamespaces::Initialize() { // we might as well end up loading them from /system/lib or /product/lib // we might as well end up loading them from /system/lib or /product/lib // For now we rely on CTS test to catch things like this but // For now we rely on CTS test to catch things like this but // it should probably be addressed in the future. // it should probably be addressed in the future. for (const auto& soname : android::base::Split(default_public_libraries(), ":")) { for (const auto& soname : android::base::Split(preloadable_public_libraries(), ":")) { LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr, LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr, "Error preloading public library %s: %s", soname.c_str(), dlerror()); "Error preloading public library %s: %s", soname.c_str(), dlerror()); } } Loading
libnativeloader/native_loader_test.cpp +84 −1 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include "public_libraries.h" #include "public_libraries.h" using namespace ::testing; using namespace ::testing; using namespace ::android::nativeloader::internal; namespace android { namespace android { namespace nativeloader { namespace nativeloader { Loading Loading @@ -289,7 +290,7 @@ class NativeLoaderTest : public ::testing::TestWithParam<bool> { void SetExpectations() { void SetExpectations() { std::vector<std::string> default_public_libs = std::vector<std::string> default_public_libs = android::base::Split(default_public_libraries(), ":"); android::base::Split(preloadable_public_libraries(), ":"); for (auto l : default_public_libs) { for (auto l : default_public_libs) { EXPECT_CALL(*mock, dlopen(StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE)) EXPECT_CALL(*mock, dlopen(StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE)) .WillOnce(Return(any_nonnull)); .WillOnce(Return(any_nonnull)); Loading Loading @@ -576,5 +577,87 @@ TEST_P(NativeLoaderTest_Create, TwoApks) { INSTANTIATE_TEST_SUITE_P(NativeLoaderTests_Create, NativeLoaderTest_Create, testing::Bool()); INSTANTIATE_TEST_SUITE_P(NativeLoaderTests_Create, NativeLoaderTest_Create, testing::Bool()); const std::function<Result<bool>(const struct ConfigEntry&)> always_true = [](const struct ConfigEntry&) -> Result<bool> { return true; }; TEST(NativeLoaderConfigParser, NamesAndComments) { const char file_content[] = R"( ###### libA.so #libB.so libC.so libD.so #### libE.so )"; const std::vector<std::string> expected_result = {"libA.so", "libC.so", "libD.so"}; Result<std::vector<std::string>> result = ParseConfig(file_content, always_true); ASSERT_TRUE(result) << result.error().message(); ASSERT_EQ(expected_result, *result); } TEST(NativeLoaderConfigParser, WithBitness) { const char file_content[] = R"( libA.so 32 libB.so 64 libC.so )"; #if defined(__LP64__) const std::vector<std::string> expected_result = {"libB.so", "libC.so"}; #else const std::vector<std::string> expected_result = {"libA.so", "libC.so"}; #endif Result<std::vector<std::string>> result = ParseConfig(file_content, always_true); ASSERT_TRUE(result) << result.error().message(); ASSERT_EQ(expected_result, *result); } TEST(NativeLoaderConfigParser, WithNoPreload) { const char file_content[] = R"( libA.so nopreload libB.so nopreload libC.so )"; const std::vector<std::string> expected_result = {"libC.so"}; Result<std::vector<std::string>> result = ParseConfig(file_content, [](const struct ConfigEntry& entry) -> Result<bool> { return !entry.nopreload; }); ASSERT_TRUE(result) << result.error().message(); ASSERT_EQ(expected_result, *result); } TEST(NativeLoaderConfigParser, WithNoPreloadAndBitness) { const char file_content[] = R"( libA.so nopreload 32 libB.so 64 nopreload libC.so 32 libD.so 64 libE.so nopreload )"; #if defined(__LP64__) const std::vector<std::string> expected_result = {"libD.so"}; #else const std::vector<std::string> expected_result = {"libC.so"}; #endif Result<std::vector<std::string>> result = ParseConfig(file_content, [](const struct ConfigEntry& entry) -> Result<bool> { return !entry.nopreload; }); ASSERT_TRUE(result) << result.error().message(); ASSERT_EQ(expected_result, *result); } TEST(NativeLoaderConfigParser, RejectMalformed) { ASSERT_FALSE(ParseConfig("libA.so 32 64", always_true)); ASSERT_FALSE(ParseConfig("libA.so 32 32", always_true)); ASSERT_FALSE(ParseConfig("libA.so 32 nopreload 64", always_true)); ASSERT_FALSE(ParseConfig("32 libA.so nopreload", always_true)); ASSERT_FALSE(ParseConfig("nopreload libA.so 32", always_true)); ASSERT_FALSE(ParseConfig("libA.so nopreload # comment", always_true)); } } // namespace nativeloader } // namespace nativeloader } // namespace android } // namespace android
libnativeloader/public_libraries.cpp +87 −49 Original line number Original line Diff line number Diff line Loading @@ -34,7 +34,8 @@ namespace android::nativeloader { namespace android::nativeloader { using namespace std::string_literals; using namespace internal; using namespace ::std::string_literals; using android::base::ErrnoError; using android::base::ErrnoError; using android::base::Errorf; using android::base::Errorf; using android::base::Result; using android::base::Result; Loading Loading @@ -95,53 +96,21 @@ void InsertVndkVersionStr(std::string* file_name) { file_name->insert(insert_pos, vndk_version_str()); file_name->insert(insert_pos, vndk_version_str()); } } const std::function<Result<void>(const std::string&)> always_true = const std::function<Result<bool>(const struct ConfigEntry&)> always_true = [](const std::string&) -> Result<void> { return {}; }; [](const struct ConfigEntry&) -> Result<bool> { return true; }; Result<std::vector<std::string>> ReadConfig( Result<std::vector<std::string>> ReadConfig( const std::string& configFile, const std::string& configFile, const std::function<Result<void>(const std::string& /* soname */)>& check_soname) { const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn) { // Read list of public native libraries from the config file. std::string file_content; std::string file_content; if (!base::ReadFileToString(configFile, &file_content)) { if (!base::ReadFileToString(configFile, &file_content)) { return ErrnoError(); return ErrnoError(); } } Result<std::vector<std::string>> result = ParseConfig(file_content, filter_fn); std::vector<std::string> lines = base::Split(file_content, "\n"); if (!result) { return Errorf("Cannot parse {}: {}", configFile, result.error().message()); std::vector<std::string> sonames; for (auto& line : lines) { auto trimmed_line = base::Trim(line); if (trimmed_line[0] == '#' || trimmed_line.empty()) { continue; } size_t space_pos = trimmed_line.rfind(' '); if (space_pos != std::string::npos) { std::string type = trimmed_line.substr(space_pos + 1); if (type != "32" && type != "64") { return Errorf("Malformed line: {}", line); } #if defined(__LP64__) // Skip 32 bit public library. if (type == "32") { continue; } #else // Skip 64 bit public library. if (type == "64") { continue; } } #endif return result; trimmed_line.resize(space_pos); } auto ret = check_soname(trimmed_line); if (!ret) { return ret.error(); } sonames.push_back(trimmed_line); } return sonames; } } void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) { void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) { Loading @@ -165,13 +134,13 @@ void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonam config_file_path.c_str()); config_file_path.c_str()); auto ret = ReadConfig( auto ret = ReadConfig( config_file_path, [&company_name](const std::string& soname) -> Result<void> { config_file_path, [&company_name](const struct ConfigEntry& entry) -> Result<bool> { if (android::base::StartsWith(soname, "lib") && if (android::base::StartsWith(entry.soname, "lib") && android::base::EndsWith(soname, "." + company_name + ".so")) { android::base::EndsWith(entry.soname, "." + company_name + ".so")) { return {}; return true; } else { } else { return Errorf("Library name \"{}\" does not end with the company name {}.", soname, return Errorf("Library name \"{}\" does not end with the company name {}.", company_name); entry.soname, company_name); } } }); }); if (ret) { if (ret) { Loading @@ -185,9 +154,16 @@ void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonam } } } } static std::string InitDefaultPublicLibraries() { static std::string InitDefaultPublicLibraries(bool for_preload) { std::string config_file = root_dir() + kDefaultPublicLibrariesFile; std::string config_file = root_dir() + kDefaultPublicLibrariesFile; auto sonames = ReadConfig(config_file, always_true); auto sonames = ReadConfig(config_file, [&for_preload](const struct ConfigEntry& entry) -> Result<bool> { if (for_preload) { return !entry.nopreload; } else { return true; } }); if (!sonames) { if (!sonames) { LOG_ALWAYS_FATAL("Error reading public native library list from \"%s\": %s", LOG_ALWAYS_FATAL("Error reading public native library list from \"%s\": %s", config_file.c_str(), sonames.error().message().c_str()); config_file.c_str(), sonames.error().message().c_str()); Loading Loading @@ -290,8 +266,13 @@ static std::string InitNeuralNetworksPublicLibraries() { } // namespace } // namespace const std::string& preloadable_public_libraries() { static std::string list = InitDefaultPublicLibraries(/*for_preload*/ true); return list; } const std::string& default_public_libraries() { const std::string& default_public_libraries() { static std::string list = InitDefaultPublicLibraries(); static std::string list = InitDefaultPublicLibraries(/*for_preload*/ false); return list; return list; } } Loading Loading @@ -325,4 +306,61 @@ const std::string& vndksp_libraries() { return list; return list; } } namespace internal { // Exported for testing Result<std::vector<std::string>> ParseConfig( const std::string& file_content, const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn) { std::vector<std::string> lines = base::Split(file_content, "\n"); std::vector<std::string> sonames; for (auto& line : lines) { auto trimmed_line = base::Trim(line); if (trimmed_line[0] == '#' || trimmed_line.empty()) { continue; } std::vector<std::string> tokens = android::base::Split(trimmed_line, " "); if (tokens.size() < 1 || tokens.size() > 3) { return Errorf("Malformed line \"{}\"", line); } struct ConfigEntry entry = {.soname = "", .nopreload = false, .bitness = ALL}; size_t i = tokens.size(); while (i-- > 0) { if (tokens[i] == "nopreload") { entry.nopreload = true; } else if (tokens[i] == "32" || tokens[i] == "64") { if (entry.bitness != ALL) { return Errorf("Malformed line \"{}\": bitness can be specified only once", line); } entry.bitness = tokens[i] == "32" ? ONLY_32 : ONLY_64; } else { if (i != 0) { return Errorf("Malformed line \"{}\"", line); } entry.soname = tokens[i]; } } // skip 32-bit lib on 64-bit process and vice versa #if defined(__LP64__) if (entry.bitness == ONLY_32) continue; #else if (entry.bitness == ONLY_64) continue; #endif Result<bool> ret = filter_fn(entry); if (!ret) { return ret.error(); } if (*ret) { // filter_fn has returned true. sonames.push_back(entry.soname); } } return sonames; } } // namespace internal } // namespace android::nativeloader } // namespace android::nativeloader
libnativeloader/public_libraries.h +24 −1 Original line number Original line Diff line number Diff line Loading @@ -15,13 +15,19 @@ */ */ #pragma once #pragma once #include <algorithm> #include <string> #include <string> #include <android-base/result.h> namespace android::nativeloader { namespace android::nativeloader { using android::base::Result; // These provide the list of libraries that are available to the namespace for apps. // These provide the list of libraries that are available to the namespace for apps. // Not all of the libraries are available to apps. Depending on the context, // Not all of the libraries are available to apps. Depending on the context, // e.g., if it is a vendor app or not, different set of libraries are made available. // e.g., if it is a vendor app or not, different set of libraries are made available. const std::string& preloadable_public_libraries(); const std::string& default_public_libraries(); const std::string& default_public_libraries(); const std::string& runtime_public_libraries(); const std::string& runtime_public_libraries(); const std::string& vendor_public_libraries(); const std::string& vendor_public_libraries(); Loading @@ -30,4 +36,21 @@ const std::string& neuralnetworks_public_libraries(); const std::string& llndk_libraries(); const std::string& llndk_libraries(); const std::string& vndksp_libraries(); const std::string& vndksp_libraries(); }; // namespace android::nativeloader // These are exported for testing namespace internal { enum Bitness { ALL = 0, ONLY_32, ONLY_64 }; struct ConfigEntry { std::string soname; bool nopreload; Bitness bitness; }; Result<std::vector<std::string>> ParseConfig( const std::string& file_content, const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn); } // namespace internal } // namespace android::nativeloader