Merge "Use android::base::Result in libnativeloader"

This commit is contained in:
Treehugger Robot 2019-07-27 14:07:44 +00:00 committed by Gerrit Code Review
commit 244d9b8fb9
6 changed files with 213 additions and 159 deletions

View File

@ -33,6 +33,8 @@
#include "public_libraries.h"
#include "utils.h"
using android::base::Error;
namespace android::nativeloader {
namespace {
@ -128,11 +130,11 @@ void LibraryNamespaces::Initialize() {
}
}
NativeLoaderNamespace* LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version,
jobject class_loader, bool is_shared,
jstring dex_path, jstring java_library_path,
jstring java_permitted_path,
std::string* error_msg) {
Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version,
jobject class_loader, bool is_shared,
jstring dex_path,
jstring java_library_path,
jstring java_permitted_path) {
std::string library_path; // empty string by default.
if (java_library_path != nullptr) {
@ -158,14 +160,14 @@ NativeLoaderNamespace* LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sd
}
// Initialize the anonymous namespace with the first non-empty library path.
Result<void> ret;
if (!library_path.empty() && !initialized_ &&
!InitPublicNamespace(library_path.c_str(), error_msg)) {
return nullptr;
!(ret = InitPublicNamespace(library_path.c_str()))) {
return ret.error();
}
bool found = FindNamespaceByClassLoader(env, class_loader);
LOG_ALWAYS_FATAL_IF(found, "There is already a namespace associated with this classloader");
LOG_ALWAYS_FATAL_IF(FindNamespaceByClassLoader(env, class_loader) != nullptr,
"There is already a namespace associated with this classloader");
std::string system_exposed_libraries = default_public_libraries();
const char* namespace_name = kClassloaderNamespaceName;
@ -216,58 +218,66 @@ NativeLoaderNamespace* LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sd
auto app_ns =
NativeLoaderNamespace::Create(namespace_name, library_path, permitted_path, parent_ns,
is_shared, target_sdk_version < 24 /* is_greylist_enabled */);
if (app_ns.IsNil()) {
*error_msg = app_ns.GetError();
return nullptr;
if (!app_ns) {
return app_ns.error();
}
// ... and link to other namespaces to allow access to some public libraries
bool is_bridged = app_ns.IsBridged();
bool is_bridged = app_ns->IsBridged();
auto platform_ns = NativeLoaderNamespace::GetPlatformNamespace(is_bridged);
if (!app_ns.Link(platform_ns, system_exposed_libraries)) {
*error_msg = app_ns.GetError();
return nullptr;
if (!platform_ns) {
return platform_ns.error();
}
auto linked = app_ns->Link(*platform_ns, system_exposed_libraries);
if (!linked) {
return linked.error();
}
auto runtime_ns = NativeLoaderNamespace::GetExportedNamespace(kRuntimeNamespaceName, is_bridged);
// Runtime apex does not exist in host, and under certain build conditions.
if (!runtime_ns.IsNil()) {
if (!app_ns.Link(runtime_ns, runtime_public_libraries())) {
*error_msg = app_ns.GetError();
return nullptr;
if (runtime_ns) {
linked = app_ns->Link(*runtime_ns, runtime_public_libraries());
if (!linked) {
return linked.error();
}
}
// Give access to NNAPI libraries (apex-updated LLNDK library).
auto nnapi_ns =
NativeLoaderNamespace::GetExportedNamespace(kNeuralNetworksNamespaceName, is_bridged);
if (!app_ns.Link(nnapi_ns, neuralnetworks_public_libraries())) {
*error_msg = app_ns.GetError();
return nullptr;
if (nnapi_ns) {
linked = app_ns->Link(*nnapi_ns, neuralnetworks_public_libraries());
if (!linked) {
return linked.error();
}
}
// Give access to VNDK-SP libraries from the 'vndk' namespace.
if (unbundled_vendor_or_product_app && !vndksp_libraries().empty()) {
auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkNamespaceName, is_bridged);
if (!vndk_ns.IsNil() && !app_ns.Link(vndk_ns, vndksp_libraries())) {
*error_msg = app_ns.GetError();
return nullptr;
if (vndk_ns) {
linked = app_ns->Link(*vndk_ns, vndksp_libraries());
if (!linked) {
return linked.error();
}
}
}
// Note that when vendor_ns is not configured, vendor_ns.IsNil() will be true
// and it will result in linking to the default namespace which is expected
// behavior in this case.
if (!vendor_public_libraries().empty()) {
auto vendor_ns = NativeLoaderNamespace::GetExportedNamespace(kVendorNamespaceName, is_bridged);
if (!app_ns.Link(vendor_ns, vendor_public_libraries())) {
*error_msg = dlerror();
return nullptr;
// when vendor_ns is not configured, link to the platform namespace
auto target_ns = vendor_ns ? vendor_ns : platform_ns;
if (target_ns) {
linked = app_ns->Link(*target_ns, vendor_public_libraries());
if (!linked) {
return linked.error();
}
}
}
namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), app_ns));
namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns));
return &(namespaces_.back().second);
}
@ -285,7 +295,7 @@ NativeLoaderNamespace* LibraryNamespaces::FindNamespaceByClassLoader(JNIEnv* env
return nullptr;
}
bool LibraryNamespaces::InitPublicNamespace(const char* library_path, std::string* error_msg) {
Result<void> LibraryNamespaces::InitPublicNamespace(const char* library_path) {
// Ask native bride if this apps library path should be handled by it
bool is_native_bridge = NativeBridgeIsPathSupported(library_path);
@ -296,8 +306,7 @@ bool LibraryNamespaces::InitPublicNamespace(const char* library_path, std::strin
initialized_ = android_init_anonymous_namespace(default_public_libraries().c_str(),
is_native_bridge ? nullptr : library_path);
if (!initialized_) {
*error_msg = dlerror();
return false;
return Error() << dlerror();
}
// and now initialize native bridge namespaces if necessary.
@ -305,11 +314,11 @@ bool LibraryNamespaces::InitPublicNamespace(const char* library_path, std::strin
initialized_ = NativeBridgeInitAnonymousNamespace(default_public_libraries().c_str(),
is_native_bridge ? library_path : nullptr);
if (!initialized_) {
*error_msg = NativeBridgeGetError();
return Error() << NativeBridgeGetError();
}
}
return initialized_;
return {};
}
NativeLoaderNamespace* LibraryNamespaces::FindParentNamespaceByClassLoader(JNIEnv* env,

View File

@ -25,10 +25,13 @@
#include <list>
#include <string>
#include <android-base/result.h>
#include <jni.h>
namespace android::nativeloader {
using android::base::Result;
// LibraryNamespaces is a singleton object that manages NativeLoaderNamespace
// objects for an app process. Its main job is to create (and configure) a new
// NativeLoaderNamespace object for a Java ClassLoader, and to find an existing
@ -46,13 +49,13 @@ class LibraryNamespaces {
namespaces_.clear();
initialized_ = false;
}
NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader,
bool is_shared, jstring dex_path, jstring java_library_path,
jstring java_permitted_path, std::string* error_msg);
Result<NativeLoaderNamespace*> Create(JNIEnv* env, uint32_t target_sdk_version,
jobject class_loader, bool is_shared, jstring dex_path,
jstring java_library_path, jstring java_permitted_path);
NativeLoaderNamespace* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
private:
bool InitPublicNamespace(const char* library_path, std::string* error_msg);
Result<void> InitPublicNamespace(const char* library_path);
NativeLoaderNamespace* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
bool initialized_;

View File

@ -92,12 +92,10 @@ jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobj
jstring permitted_path) {
#if defined(__ANDROID__)
std::lock_guard<std::mutex> guard(g_namespaces_mutex);
std::string error_msg;
bool success = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
library_path, permitted_path, &error_msg) != nullptr;
if (!success) {
return env->NewStringUTF(error_msg.c_str());
auto ns = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
library_path, permitted_path);
if (!ns) {
return env->NewStringUTF(ns.error().message().c_str());
}
#else
UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path);
@ -139,11 +137,14 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat
if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
// This is the case where the classloader was not created by ApplicationLoaders
// In this case we create an isolated not-shared namespace for it.
std::string create_error_msg;
if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */,
nullptr, library_path, nullptr, &create_error_msg)) == nullptr) {
*error_msg = strdup(create_error_msg.c_str());
Result<NativeLoaderNamespace*> isolated_ns =
g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */, nullptr,
library_path, nullptr);
if (!isolated_ns) {
*error_msg = strdup(isolated_ns.error().message().c_str());
return nullptr;
} else {
ns = *isolated_ns;
}
}
@ -222,12 +223,14 @@ void NativeLoaderFreeErrorMessage(char* msg) {
#if defined(__ANDROID__)
void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
bool* needs_native_bridge, char** error_msg) {
void* handle = ns->Load(path);
if (handle == nullptr) {
*error_msg = ns->GetError();
auto handle = ns->Load(path);
if (!handle && error_msg != nullptr) {
*error_msg = strdup(handle.error().message().c_str());
}
*needs_native_bridge = ns->IsBridged();
return handle;
if (needs_native_bridge != nullptr) {
*needs_native_bridge = ns->IsBridged();
}
return handle ? *handle : nullptr;
}
// native_bridge_namespaces are not supported for callers of this function.

View File

@ -28,6 +28,9 @@
#include "nativeloader/dlext_namespaces.h"
using android::base::Error;
using android::base::Errorf;
namespace android {
namespace {
@ -35,41 +38,46 @@ namespace {
constexpr const char* kDefaultNamespaceName = "default";
constexpr const char* kPlatformNamespaceName = "platform";
} // namespace
NativeLoaderNamespace NativeLoaderNamespace::GetExportedNamespace(const std::string& name,
bool is_bridged) {
if (!is_bridged) {
return NativeLoaderNamespace(name, android_get_exported_namespace(name.c_str()));
} else {
return NativeLoaderNamespace(name, NativeBridgeGetExportedNamespace(name.c_str()));
std::string GetLinkerError(bool is_bridged) {
const char* msg = is_bridged ? NativeBridgeGetError() : dlerror();
if (msg == nullptr) {
return "no error";
}
return std::string(msg);
}
char* NativeLoaderNamespace::GetError() const {
if (!IsBridged()) {
return strdup(dlerror());
} // namespace
Result<NativeLoaderNamespace> NativeLoaderNamespace::GetExportedNamespace(const std::string& name,
bool is_bridged) {
if (!is_bridged) {
auto raw = android_get_exported_namespace(name.c_str());
if (raw != nullptr) {
return NativeLoaderNamespace(name, raw);
}
} else {
return strdup(NativeBridgeGetError());
auto raw = NativeBridgeGetExportedNamespace(name.c_str());
if (raw != nullptr) {
return NativeLoaderNamespace(name, raw);
}
}
return Errorf("namespace {} does not exist or exported", name);
}
// The platform namespace is called "default" for binaries in /system and
// "platform" for those in the Runtime APEX. Try "platform" first since
// "default" always exists.
NativeLoaderNamespace NativeLoaderNamespace::GetPlatformNamespace(bool is_bridged) {
NativeLoaderNamespace ns = GetExportedNamespace(kPlatformNamespaceName, is_bridged);
if (ns.IsNil()) {
Result<NativeLoaderNamespace> NativeLoaderNamespace::GetPlatformNamespace(bool is_bridged) {
auto ns = GetExportedNamespace(kPlatformNamespaceName, is_bridged);
if (!ns) {
ns = GetExportedNamespace(kDefaultNamespaceName, is_bridged);
}
return ns;
}
NativeLoaderNamespace NativeLoaderNamespace::Create(const std::string& name,
const std::string& search_paths,
const std::string& permitted_paths,
const NativeLoaderNamespace* parent,
bool is_shared, bool is_greylist_enabled) {
Result<NativeLoaderNamespace> NativeLoaderNamespace::Create(
const std::string& name, const std::string& search_paths, const std::string& permitted_paths,
const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled) {
bool is_bridged = false;
if (parent != nullptr) {
is_bridged = parent->IsBridged();
@ -78,8 +86,11 @@ NativeLoaderNamespace NativeLoaderNamespace::Create(const std::string& name,
}
// Fall back to the platform namespace if no parent is set.
const NativeLoaderNamespace& effective_parent =
parent != nullptr ? *parent : GetPlatformNamespace(is_bridged);
auto platform_ns = GetPlatformNamespace(is_bridged);
if (!platform_ns) {
return platform_ns.error();
}
const NativeLoaderNamespace& effective_parent = parent != nullptr ? *parent : *platform_ns;
uint64_t type = ANDROID_NAMESPACE_TYPE_ISOLATED;
if (is_shared) {
@ -93,37 +104,56 @@ NativeLoaderNamespace NativeLoaderNamespace::Create(const std::string& name,
android_namespace_t* raw =
android_create_namespace(name.c_str(), nullptr, search_paths.c_str(), type,
permitted_paths.c_str(), effective_parent.ToRawAndroidNamespace());
return NativeLoaderNamespace(name, raw);
if (raw != nullptr) {
return NativeLoaderNamespace(name, raw);
}
} else {
native_bridge_namespace_t* raw = NativeBridgeCreateNamespace(
name.c_str(), nullptr, search_paths.c_str(), type, permitted_paths.c_str(),
effective_parent.ToRawNativeBridgeNamespace());
return NativeLoaderNamespace(name, raw);
if (raw != nullptr) {
return NativeLoaderNamespace(name, raw);
}
}
return Errorf("failed to create {} namespace name:{}, search_paths:{}, permitted_paths:{}",
is_bridged ? "bridged" : "native", name, search_paths, permitted_paths);
}
bool NativeLoaderNamespace::Link(const NativeLoaderNamespace& target,
const std::string& shared_libs) const {
Result<void> NativeLoaderNamespace::Link(const NativeLoaderNamespace& target,
const std::string& shared_libs) const {
LOG_ALWAYS_FATAL_IF(shared_libs.empty(), "empty share lib when linking %s to %s",
this->name().c_str(), target.name().c_str());
if (!IsBridged()) {
return android_link_namespaces(this->ToRawAndroidNamespace(), target.ToRawAndroidNamespace(),
shared_libs.c_str());
if (android_link_namespaces(this->ToRawAndroidNamespace(), target.ToRawAndroidNamespace(),
shared_libs.c_str())) {
return {};
}
} else {
return NativeBridgeLinkNamespaces(this->ToRawNativeBridgeNamespace(),
target.ToRawNativeBridgeNamespace(), shared_libs.c_str());
if (NativeBridgeLinkNamespaces(this->ToRawNativeBridgeNamespace(),
target.ToRawNativeBridgeNamespace(), shared_libs.c_str())) {
return {};
}
}
return Error() << GetLinkerError(IsBridged());
}
void* NativeLoaderNamespace::Load(const char* lib_name) const {
Result<void*> NativeLoaderNamespace::Load(const char* lib_name) const {
if (!IsBridged()) {
android_dlextinfo extinfo;
extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
extinfo.library_namespace = this->ToRawAndroidNamespace();
return android_dlopen_ext(lib_name, RTLD_NOW, &extinfo);
void* handle = android_dlopen_ext(lib_name, RTLD_NOW, &extinfo);
if (handle != nullptr) {
return handle;
}
} else {
return NativeBridgeLoadLibraryExt(lib_name, RTLD_NOW, this->ToRawNativeBridgeNamespace());
void* handle =
NativeBridgeLoadLibraryExt(lib_name, RTLD_NOW, this->ToRawNativeBridgeNamespace());
if (handle != nullptr) {
return handle;
}
}
return Error() << GetLinkerError(IsBridged());
}
} // namespace android

View File

@ -21,22 +21,25 @@
#include <vector>
#include <android-base/logging.h>
#include <android-base/result.h>
#include <android/dlext.h>
#include <log/log.h>
#include <nativebridge/native_bridge.h>
namespace android {
using android::base::Result;
// NativeLoaderNamespace abstracts a linker namespace for the native
// architecture (ex: arm on arm) or the translated architecture (ex: arm on
// x86). Instances of this class are managed by LibraryNamespaces object.
struct NativeLoaderNamespace {
public:
// TODO(return with errors)
static NativeLoaderNamespace Create(const std::string& name, const std::string& search_paths,
const std::string& permitted_paths,
const NativeLoaderNamespace* parent, bool is_shared,
bool is_greylist_enabled);
static Result<NativeLoaderNamespace> Create(const std::string& name,
const std::string& search_paths,
const std::string& permitted_paths,
const NativeLoaderNamespace* parent, bool is_shared,
bool is_greylist_enabled);
NativeLoaderNamespace(NativeLoaderNamespace&&) = default;
NativeLoaderNamespace(const NativeLoaderNamespace&) = default;
@ -47,16 +50,13 @@ struct NativeLoaderNamespace {
std::string name() const { return name_; }
bool IsBridged() const { return raw_.index() == 1; }
bool IsNil() const {
return IsBridged() ? std::get<1>(raw_) == nullptr : std::get<0>(raw_) == nullptr;
}
bool Link(const NativeLoaderNamespace& target, const std::string& shared_libs) const;
void* Load(const char* lib_name) const;
char* GetError() const;
Result<void> Link(const NativeLoaderNamespace& target, const std::string& shared_libs) const;
Result<void*> Load(const char* lib_name) const;
static NativeLoaderNamespace GetExportedNamespace(const std::string& name, bool is_bridged);
static NativeLoaderNamespace GetPlatformNamespace(bool is_bridged);
static Result<NativeLoaderNamespace> GetExportedNamespace(const std::string& name,
bool is_bridged);
static Result<NativeLoaderNamespace> GetPlatformNamespace(bool is_bridged);
private:
explicit NativeLoaderNamespace(const std::string& name, android_namespace_t* ns)

View File

@ -26,6 +26,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/result.h>
#include <android-base/strings.h>
#include <log/log.h>
@ -34,6 +35,9 @@
namespace android::nativeloader {
using namespace std::string_literals;
using android::base::ErrnoError;
using android::base::Errorf;
using android::base::Result;
namespace {
@ -91,22 +95,21 @@ void InsertVndkVersionStr(std::string* file_name) {
file_name->insert(insert_pos, vndk_version_str());
}
const std::function<bool(const std::string&, std::string*)> always_true =
[](const std::string&, std::string*) { return true; };
const std::function<Result<void>(const std::string&)> always_true =
[](const std::string&) -> Result<void> { return {}; };
bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames,
const std::function<bool(const std::string& /* soname */,
std::string* /* error_msg */)>& check_soname,
std::string* error_msg = nullptr) {
Result<std::vector<std::string>> ReadConfig(
const std::string& configFile,
const std::function<Result<void>(const std::string& /* soname */)>& check_soname) {
// Read list of public native libraries from the config file.
std::string file_content;
if (!base::ReadFileToString(configFile, &file_content)) {
if (error_msg) *error_msg = strerror(errno);
return false;
return ErrnoError();
}
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()) {
@ -116,8 +119,7 @@ bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames
if (space_pos != std::string::npos) {
std::string type = trimmed_line.substr(space_pos + 1);
if (type != "32" && type != "64") {
if (error_msg) *error_msg = "Malformed line: " + line;
return false;
return Errorf("Malformed line: {}", line);
}
#if defined(__LP64__)
// Skip 32 bit public library.
@ -133,13 +135,13 @@ bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames
trimmed_line.resize(space_pos);
}
if (check_soname(trimmed_line, error_msg)) {
sonames->push_back(trimmed_line);
} else {
return false;
auto ret = check_soname(trimmed_line);
if (!ret) {
return ret.error();
}
sonames.push_back(trimmed_line);
}
return true;
return sonames;
}
void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) {
@ -162,24 +164,22 @@ void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonam
"Error extracting company name from public native library list file path \"%s\"",
config_file_path.c_str());
std::string error_msg;
LOG_ALWAYS_FATAL_IF(
!ReadConfig(config_file_path, sonames,
[&company_name](const std::string& soname, std::string* error_msg) {
if (android::base::StartsWith(soname, "lib") &&
android::base::EndsWith(soname, "." + company_name + ".so")) {
return true;
} else {
*error_msg = "Library name \"" + soname +
"\" does not end with the company name: " + company_name +
".";
return false;
}
},
&error_msg),
"Error reading public native library list from \"%s\": %s", config_file_path.c_str(),
error_msg.c_str());
auto ret = ReadConfig(
config_file_path, [&company_name](const std::string& soname) -> Result<void> {
if (android::base::StartsWith(soname, "lib") &&
android::base::EndsWith(soname, "." + company_name + ".so")) {
return {};
} else {
return Errorf("Library name \"{}\" does not end with the company name {}.", soname,
company_name);
}
});
if (ret) {
sonames->insert(sonames->end(), ret->begin(), ret->end());
} else {
LOG_ALWAYS_FATAL("Error reading public native library list from \"%s\": %s",
config_file_path.c_str(), ret.error().message().c_str());
}
}
}
}
@ -187,16 +187,17 @@ void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonam
static std::string InitDefaultPublicLibraries() {
std::string config_file = root_dir() + kDefaultPublicLibrariesFile;
std::vector<std::string> sonames;
std::string error_msg;
LOG_ALWAYS_FATAL_IF(!ReadConfig(config_file, &sonames, always_true, &error_msg),
"Error reading public native library list from \"%s\": %s",
config_file.c_str(), error_msg.c_str());
auto sonames = ReadConfig(config_file, always_true);
if (!sonames) {
LOG_ALWAYS_FATAL("Error reading public native library list from \"%s\": %s",
config_file.c_str(), sonames.error().message().c_str());
return "";
}
std::string additional_libs = additional_public_libraries();
if (!additional_libs.empty()) {
auto vec = base::Split(additional_libs, ":");
std::copy(vec.begin(), vec.end(), std::back_inserter(sonames));
std::copy(vec.begin(), vec.end(), std::back_inserter(*sonames));
}
// Remove the public libs in the runtime namespace.
@ -216,18 +217,18 @@ static std::string InitDefaultPublicLibraries() {
continue;
}
auto it = std::find(sonames.begin(), sonames.end(), lib_name);
if (it != sonames.end()) {
sonames.erase(it);
auto it = std::find(sonames->begin(), sonames->end(), lib_name);
if (it != sonames->end()) {
sonames->erase(it);
}
}
// Remove the public libs in the nnapi namespace.
auto it = std::find(sonames.begin(), sonames.end(), kNeuralNetworksApexPublicLibrary);
if (it != sonames.end()) {
sonames.erase(it);
auto it = std::find(sonames->begin(), sonames->end(), kNeuralNetworksApexPublicLibrary);
if (it != sonames->end()) {
sonames->erase(it);
}
return android::base::Join(sonames, ':');
return android::base::Join(*sonames, ':');
}
static std::string InitRuntimePublicLibraries() {
@ -243,9 +244,11 @@ static std::string InitRuntimePublicLibraries() {
static std::string InitVendorPublicLibraries() {
// This file is optional, quietly ignore if the file does not exist.
std::vector<std::string> sonames;
ReadConfig(kVendorPublicLibrariesFile, &sonames, always_true, nullptr);
return android::base::Join(sonames, ':');
auto sonames = ReadConfig(kVendorPublicLibrariesFile, always_true);
if (!sonames) {
return "";
}
return android::base::Join(*sonames, ':');
}
// read /system/etc/public.libraries-<companyname>.txt and
@ -262,17 +265,23 @@ static std::string InitExtendedPublicLibraries() {
static std::string InitLlndkLibraries() {
std::string config_file = kLlndkLibrariesFile;
InsertVndkVersionStr(&config_file);
std::vector<std::string> sonames;
ReadConfig(config_file, &sonames, always_true, nullptr);
return android::base::Join(sonames, ':');
auto sonames = ReadConfig(config_file, always_true);
if (!sonames) {
LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
return "";
}
return android::base::Join(*sonames, ':');
}
static std::string InitVndkspLibraries() {
std::string config_file = kVndkLibrariesFile;
InsertVndkVersionStr(&config_file);
std::vector<std::string> sonames;
ReadConfig(config_file, &sonames, always_true, nullptr);
return android::base::Join(sonames, ':');
auto sonames = ReadConfig(config_file, always_true);
if (!sonames) {
LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
return "";
}
return android::base::Join(*sonames, ':');
}
static std::string InitNeuralNetworksPublicLibraries() {