From 7130e13262f788d35e85e0b38db58a1e2aa6266b Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Thu, 11 May 2017 02:15:24 +0900 Subject: [PATCH] add libvndksupport libvndksupport is a new LL-NDK library that provides vendor-visible APIs for platform-only functionalities of other LL-NDK libraries. Currently, it provides android_(load|unload)_sphal_library which abstracts the platform-only APIs of libdl (android_get_exported_namespace, etc.) Bug: 37323945 Test: sailfish builds and boots Test: libvndksupport-tests passes Change-Id: I6d2911b57e009d0c842554933aac87d6573ffcbf --- libvndksupport/Android.bp | 15 ++++++ libvndksupport/include/vndksupport/linker.h | 31 +++++++++++ libvndksupport/libvndksupport.map.txt | 7 +++ libvndksupport/linker.c | 52 ++++++++++++++++++ libvndksupport/tests/Android.bp | 26 +++++++++ libvndksupport/tests/linker_test.cpp | 60 +++++++++++++++++++++ 6 files changed, 191 insertions(+) create mode 100644 libvndksupport/Android.bp create mode 100644 libvndksupport/include/vndksupport/linker.h create mode 100644 libvndksupport/libvndksupport.map.txt create mode 100644 libvndksupport/linker.c create mode 100644 libvndksupport/tests/Android.bp create mode 100644 libvndksupport/tests/linker_test.cpp diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp new file mode 100644 index 000000000..ab9e26fe4 --- /dev/null +++ b/libvndksupport/Android.bp @@ -0,0 +1,15 @@ +subdirs = ["tests"] + +cc_library_shared { + name: "libvndksupport", + srcs: ["linker.c"], + local_include_dirs: ["include/vndksupport"], + export_include_dirs: ["include"], + shared_libs: ["liblog"], +} + +llndk_library { + name: "libvndksupport", + symbol_file: "libvndksupport.map.txt", + export_include_dirs: ["include"], +} diff --git a/libvndksupport/include/vndksupport/linker.h b/libvndksupport/include/vndksupport/linker.h new file mode 100644 index 000000000..f509564e1 --- /dev/null +++ b/libvndksupport/include/vndksupport/linker.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2017 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. + */ +#ifndef VNDKSUPPORT_LINKER_H_ +#define VNDKSUPPORT_LINKER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void* android_load_sphal_library(const char* name, int flag); + +int android_unload_sphal_library(void* handle); + +#ifdef __cplusplus +} +#endif + +#endif // VNDKSUPPORT_LINKER_H_ diff --git a/libvndksupport/libvndksupport.map.txt b/libvndksupport/libvndksupport.map.txt new file mode 100644 index 000000000..16e38da1a --- /dev/null +++ b/libvndksupport/libvndksupport.map.txt @@ -0,0 +1,7 @@ +LIBVNDKSUPPORT { + global: + android_load_sphal_library; # vndk + android_unload_sphal_library; # vndk + local: + *; +}; diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c new file mode 100644 index 000000000..d82307bb2 --- /dev/null +++ b/libvndksupport/linker.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 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 "linker.h" + +#include +#include + +#define LOG_TAG "vndksupport" +#include + +extern struct android_namespace_t* android_get_exported_namespace(const char*); + +void* android_load_sphal_library(const char* name, int flag) { + struct android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal"); + if (sphal_namespace != NULL) { + const android_dlextinfo dlextinfo = { + .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = sphal_namespace, + }; + void* handle = android_dlopen_ext(name, flag, &dlextinfo); + if (handle) { + return handle; + } else { + ALOGW( + "Could not load %s from sphal namespace: %s. " + "Falling back to loading it from the current namespace,", + name, dlerror()); + } + } else { + ALOGI( + "sphal namespace is not configured for this process. " + "Loading %s from the current namespace instead.", + name); + } + return dlopen(name, flag); +} + +int android_unload_sphal_library(void* handle) { + return dlclose(handle); +} diff --git a/libvndksupport/tests/Android.bp b/libvndksupport/tests/Android.bp new file mode 100644 index 000000000..3587cf88a --- /dev/null +++ b/libvndksupport/tests/Android.bp @@ -0,0 +1,26 @@ +// Copyright (C) 2017 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. + +cc_test { + name: "libvndksupport-tests", + srcs: [ + "linker_test.cpp", + ], + + host_supported: false, + shared_libs: [ + "libvndksupport", + "libbase", + ] +} diff --git a/libvndksupport/tests/linker_test.cpp b/libvndksupport/tests/linker_test.cpp new file mode 100644 index 000000000..7ce27d411 --- /dev/null +++ b/libvndksupport/tests/linker_test.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 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 + +#include +#include +#include +#include +#include + +// Since the test executable will be in /data and ld.config.txt does not +// configure sphal namespace for executables in /data, the call to +// android_load_sphal_library will always fallback to the plain dlopen from the +// default namespace. + +// Let's use libEGL_.so as a SP-HAL in test +static std::string find_sphal_lib() { + const char* path = +#if defined(__LP64__) + "/vendor/lib64/egl"; +#else + "/vendor/lib/egl"; +#endif + std::unique_ptr dir(opendir(path), closedir); + + dirent* dp; + while ((dp = readdir(dir.get())) != nullptr) { + std::string name = dp->d_name; + if (android::base::StartsWith(name, "libEGL_")) { + return std::string(path) + "/" + name; + } + } + return ""; +} + +TEST(linker, load_existing_lib) { + std::string name = find_sphal_lib(); + ASSERT_NE("", name); + void* handle = android_load_sphal_library(name.c_str(), RTLD_NOW | RTLD_LOCAL); + ASSERT_NE(nullptr, handle); + android_unload_sphal_library(handle); +} + +TEST(linker, load_nonexisting_lib) { + void* handle = android_load_sphal_library("libNeverUseThisName.so", RTLD_NOW | RTLD_LOCAL); + ASSERT_EQ(nullptr, handle); +}