Merge "Native loader as a separate library" am: beceb6ef53 am: 17f119eade

am: d6c9995d99

* commit 'd6c9995d992b4fdffe176acff207f1f066e2a920':
  Native loader as a separate library
This commit is contained in:
Dimitry Ivanov 2015-12-08 04:53:45 +00:00 committed by android-build-merger
commit d686fb3474
3 changed files with 229 additions and 0 deletions

View file

@ -0,0 +1,31 @@
/*
* Copyright (C) 2015 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 NATIVE_LOADER_H_
#define NATIVE_LOADER_H_
#include "jni.h"
#include <stdint.h>
namespace android {
__attribute__((visibility("default")))
void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
jobject class_loader, jstring library_path);
}; // namespace android
#endif // NATIVE_BRIDGE_H_

View file

@ -0,0 +1,54 @@
LOCAL_PATH:= $(call my-dir)
NATIVE_LOADER_COMMON_SRC_FILES := \
native_loader.cpp
# Shared library for target
# ========================================================
include $(CLEAR_VARS)
LOCAL_MODULE:= libnativeloader
LOCAL_SRC_FILES:= $(NATIVE_LOADER_COMMON_SRC_FILES)
LOCAL_SHARED_LIBRARIES := libnativehelper liblog libcutils
LOCAL_STATIC_LIBRARIES := libbase
LOCAL_CLANG := true
LOCAL_CFLAGS += -Werror -Wall
LOCAL_CPPFLAGS := -std=gnu++14 -fvisibility=hidden
LOCAL_LDFLAGS := -ldl
LOCAL_MULTILIB := both
include $(BUILD_SHARED_LIBRARY)
# Shared library for host
# ========================================================
include $(CLEAR_VARS)
LOCAL_MODULE:= libnativeloader
LOCAL_SRC_FILES:= $(NATIVE_LOADER_COMMON_SRC_FILES)
LOCAL_SHARED_LIBRARIES := libnativehelper liblog libcutils
LOCAL_STATIC_LIBRARIES := libbase
LOCAL_CLANG := true
LOCAL_CFLAGS += -Werror -Wall
LOCAL_CPPFLAGS := -std=gnu++14 -fvisibility=hidden
LOCAL_LDFLAGS := -ldl
LOCAL_MULTILIB := both
include $(BUILD_HOST_SHARED_LIBRARY)
# Static library for host
# ========================================================
include $(CLEAR_VARS)
LOCAL_MODULE:= libnativeloader
LOCAL_SRC_FILES:= $(NATIVE_LOADER_COMMON_SRC_FILES)
LOCAL_STATIC_LIBRARIES := libnativehelper libcutils liblog libbase
LOCAL_CLANG := true
LOCAL_CFLAGS += -Werror -Wall
LOCAL_CPPFLAGS := -std=gnu++14 -fvisibility=hidden
LOCAL_LDFLAGS := -ldl
LOCAL_MULTILIB := both
include $(BUILD_HOST_STATIC_LIBRARY)

View file

@ -0,0 +1,144 @@
/*
* Copyright (C) 2015 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 "nativeloader/native_loader.h"
#include "ScopedUtfChars.h"
#include <dlfcn.h>
#ifdef __ANDROID__
#include <android/dlext.h>
#include "cutils/properties.h"
#endif
#include <algorithm>
#include <vector>
#include <string>
#include <mutex>
#include "base/macros.h"
#include "base/strings.h"
namespace android {
#ifdef __ANDROID__
// TODO(dimitry): move this to system properties.
static const char* kPublicNativeLibraries = "libandroid.so:"
"libc.so:"
"libdl.so:"
"libEGL.so:"
"libGLESv1_CM.so:"
"libGLESv2.so:"
"libGLESv3.so:"
"libjnigraphics.so:"
"liblog.so:"
"libmediandk.so:"
"libm.so:"
"libOpenMAXAL.so:"
"libOpenSLES.so:"
"libstdc++.so:"
"libz.so";
class LibraryNamespaces {
public:
LibraryNamespaces() : initialized_(false) { }
android_namespace_t* GetOrCreate(JNIEnv* env, jobject class_loader, jstring library_path) {
ScopedUtfChars libraryPath(env, library_path);
if (!initialized_ && !InitPublicNamespace(libraryPath.c_str())) {
return nullptr;
}
std::lock_guard<std::mutex> guard(mutex_);
auto it = FindNamespaceByClassLoader(env, class_loader);
if (it != namespaces_.end()) {
return it->second;
}
android_namespace_t* ns =
android_create_namespace("classloader-namespace",
nullptr,
libraryPath.c_str(),
true);
namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), ns));
return ns;
}
private:
bool InitPublicNamespace(const char* library_path) {
// Make sure all the public libraries are loaded
std::vector<std::string> sonames = android::base::Split(kPublicNativeLibraries, ":");
for (const auto& soname : sonames) {
if (dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr) {
return false;
}
}
// Some apps call dlopen from generated code unknown to linker in which
// case linker uses anonymous namespace. See b/25844435 for details.
initialized_ = android_init_namespaces(kPublicNativeLibraries, library_path);
return initialized_;
}
std::vector<std::pair<jweak, android_namespace_t*>>::const_iterator
FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
return std::find_if(namespaces_.begin(), namespaces_.end(),
[&](const std::pair<jweak, android_namespace_t*>& value) {
return env->IsSameObject(value.first, class_loader);
});
}
bool initialized_;
std::mutex mutex_;
std::vector<std::pair<jweak, android_namespace_t*>> namespaces_;
DISALLOW_COPY_AND_ASSIGN(LibraryNamespaces);
};
static LibraryNamespaces* g_namespaces = new LibraryNamespaces;
#endif
void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
jobject class_loader, jstring library_path) {
#if defined(__ANDROID__)
if (target_sdk_version == 0 || class_loader == nullptr) {
return dlopen(path, RTLD_NOW);
}
android_namespace_t* ns = g_namespaces->GetOrCreate(env, class_loader, library_path);
if (ns == nullptr) {
return nullptr;
}
android_dlextinfo extinfo;
extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
extinfo.library_namespace = ns;
return android_dlopen_ext(path, RTLD_NOW, &extinfo);
#else
UNUSED(env, target_sdk_version, class_loader, library_path);
return dlopen(path, RTLD_NOW);
#endif
}
}; // android namespace