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

Merged-In: I6d2911b57e009d0c842554933aac87d6573ffcbf
Change-Id: I6d2911b57e009d0c842554933aac87d6573ffcbf
(cherry picked from commit 7130e13262)
This commit is contained in:
Jiyong Park 2017-05-11 02:15:24 +09:00
parent a7172f41b8
commit 8902f7571a
6 changed files with 189 additions and 0 deletions

15
libvndksupport/Android.bp Normal file
View file

@ -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"],
}

View file

@ -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_

View file

@ -0,0 +1,7 @@
LIBVNDKSUPPORT {
global:
android_load_sphal_library; # vndk
android_unload_sphal_library; # vndk
local:
*;
};

50
libvndksupport/linker.c Normal file
View file

@ -0,0 +1,50 @@
/*
* 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 <android/dlext.h>
#include <dlfcn.h>
#define LOG_TAG "vndksupport"
#include <log/log.h>
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); }

View file

@ -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",
]
}

View file

@ -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 <gtest/gtest.h>
#include <android-base/strings.h>
#include <dirent.h>
#include <dlfcn.h>
#include <vndksupport/linker.h>
#include <string>
// 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_<chipset>.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, decltype(&closedir)> 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);
}