Load vendor public libraries to sphal namespace
Load vendor public libraries to sphal namespace if it exists - preserve old behavior of loading these libraries to default namespace if sphal namespace is not present on the device. Bug: http://b/37410104 Test: cts-tradefed run singleCommand cts --skip-preconditions -m CtsJniTestCases on marlin (with enabled sphal configuration) and on angler where ld.config.txt is not present. Change-Id: Iaa3fa437ba2900acc2e5b9c78039fe1553e4c9dd
This commit is contained in:
parent
eb9694a2d1
commit
af0264bbe9
|
@ -161,6 +161,9 @@ bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_n
|
|||
// Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
|
||||
void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns);
|
||||
|
||||
// Returns vendor namespace if it is enabled for the device and null otherwise
|
||||
native_bridge_namespace_t* NativeBridgeGetVendorNamespace();
|
||||
|
||||
// Native bridge interfaces to runtime.
|
||||
struct NativeBridgeCallbacks {
|
||||
// Version number of the interface.
|
||||
|
@ -348,6 +351,15 @@ struct NativeBridgeCallbacks {
|
|||
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
|
||||
// Use loadLibrary instead in non-namespace scenario.
|
||||
void* (*loadLibraryExt)(const char* libpath, int flag, native_bridge_namespace_t* ns);
|
||||
|
||||
// Get native bridge version of vendor namespace.
|
||||
// The vendor namespace is the namespace used to load vendor public libraries.
|
||||
// With O release this namespace can be different from the default namespace.
|
||||
// For the devices without enable vendor namespaces this function should return null
|
||||
//
|
||||
// Returns:
|
||||
// vendor namespace or null if it was not set up for the device
|
||||
native_bridge_namespace_t* (*getVendorNamespace)();
|
||||
};
|
||||
|
||||
// Runtime interfaces to native bridge.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../.clang-format-2
|
|
@ -85,12 +85,14 @@ static NativeBridgeState state = NativeBridgeState::kNotSetup;
|
|||
// Nativebridge implementation.
|
||||
// Used by isCompatibleWith() which is introduced in v2.
|
||||
enum NativeBridgeImplementationVersion {
|
||||
// first version, not used.
|
||||
DEFAULT_VERSION = 1,
|
||||
// The version which signal semantic is introduced.
|
||||
SIGNAL_VERSION = 2,
|
||||
// The version which namespace semantic is introduced.
|
||||
NAMESPACE_VERSION = 3,
|
||||
// first version, not used.
|
||||
DEFAULT_VERSION = 1,
|
||||
// The version which signal semantic is introduced.
|
||||
SIGNAL_VERSION = 2,
|
||||
// The version which namespace semantic is introduced.
|
||||
NAMESPACE_VERSION = 3,
|
||||
// The version with vendor namespaces
|
||||
VENDOR_NAMESPACE_VERSION = 4,
|
||||
};
|
||||
|
||||
// Whether we had an error at some point.
|
||||
|
@ -621,6 +623,14 @@ bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_n
|
|||
return false;
|
||||
}
|
||||
|
||||
native_bridge_namespace_t* NativeBridgeGetVendorNamespace() {
|
||||
if (!NativeBridgeInitialized() || !isCompatibleWith(VENDOR_NAMESPACE_VERSION)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return callbacks->getVendorNamespace();
|
||||
}
|
||||
|
||||
void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
|
||||
if (NativeBridgeInitialized()) {
|
||||
if (isCompatibleWith(NAMESPACE_VERSION)) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../.clang-format-2
|
|
@ -124,6 +124,8 @@ extern bool android_link_namespaces(android_namespace_t* from,
|
|||
*/
|
||||
extern void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size);
|
||||
|
||||
extern android_namespace_t* android_get_exported_namespace(const char* name);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* __ANDROID_DLEXT_NAMESPACES_H__ */
|
||||
|
|
|
@ -83,6 +83,12 @@ static constexpr const char* kPublicNativeLibrariesSystemConfigPathFromRoot =
|
|||
static constexpr const char* kPublicNativeLibrariesVendorConfig =
|
||||
"/vendor/etc/public.libraries.txt";
|
||||
|
||||
// The device may be configured to have the vendor libraries loaded to a separate namespace.
|
||||
// For historical reasons this namespace was named sphal but effectively it is intended
|
||||
// to use to load vendor libraries to separate namespace with controlled interface between
|
||||
// vendor and system namespaces.
|
||||
static constexpr const char* kVendorNamespaceName = "sphal";
|
||||
|
||||
// (http://b/27588281) This is a workaround for apps using custom classloaders and calling
|
||||
// System.load() with an absolute path which is outside of the classloader library search path.
|
||||
// This list includes all directories app is allowed to access this way.
|
||||
|
@ -170,11 +176,23 @@ class LibraryNamespaces {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!android_link_namespaces(ns, nullptr, public_libraries_.c_str())) {
|
||||
// Note that when vendor_ns is not configured this function will return nullptr
|
||||
// and it will result in linking vendor_public_libraries_ to the default namespace
|
||||
// which is expected behavior in this case.
|
||||
android_namespace_t* vendor_ns = android_get_exported_namespace(kVendorNamespaceName);
|
||||
|
||||
if (!android_link_namespaces(ns, nullptr, system_public_libraries_.c_str())) {
|
||||
*error_msg = dlerror();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vendor_public_libraries_.empty()) {
|
||||
if (!android_link_namespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
|
||||
*error_msg = dlerror();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
native_loader_ns = NativeLoaderNamespace(ns);
|
||||
} else {
|
||||
native_bridge_namespace_t* ns = NativeBridgeCreateNamespace("classloader-namespace",
|
||||
|
@ -183,14 +201,24 @@ class LibraryNamespaces {
|
|||
namespace_type,
|
||||
permitted_path.c_str(),
|
||||
parent_ns.get_native_bridge_ns());
|
||||
|
||||
if (ns == nullptr) {
|
||||
*error_msg = NativeBridgeGetError();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NativeBridgeLinkNamespaces(ns, nullptr, public_libraries_.c_str())) {
|
||||
native_bridge_namespace_t* vendor_ns = NativeBridgeGetVendorNamespace();
|
||||
|
||||
if (!NativeBridgeLinkNamespaces(ns, nullptr, system_public_libraries_.c_str())) {
|
||||
*error_msg = NativeBridgeGetError();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vendor_public_libraries_.empty()) {
|
||||
if (!NativeBridgeLinkNamespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
|
||||
*error_msg = NativeBridgeGetError();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
native_loader_ns = NativeLoaderNamespace(ns);
|
||||
|
@ -249,9 +277,6 @@ class LibraryNamespaces {
|
|||
}
|
||||
}
|
||||
|
||||
// This file is optional, quietly ignore if the file does not exist.
|
||||
ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames);
|
||||
|
||||
// android_init_namespaces() expects all the public libraries
|
||||
// to be loaded so that they can be found by soname alone.
|
||||
//
|
||||
|
@ -266,7 +291,13 @@ class LibraryNamespaces {
|
|||
soname.c_str(), dlerror());
|
||||
}
|
||||
|
||||
public_libraries_ = base::Join(sonames, ':');
|
||||
system_public_libraries_ = base::Join(sonames, ':');
|
||||
|
||||
sonames.clear();
|
||||
// This file is optional, quietly ignore if the file does not exist.
|
||||
ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames);
|
||||
|
||||
vendor_public_libraries_ = base::Join(sonames, ':');
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
|
@ -325,7 +356,7 @@ class LibraryNamespaces {
|
|||
// code is one example) unknown to linker in which case linker uses anonymous
|
||||
// namespace. The second argument specifies the search path for the anonymous
|
||||
// namespace which is the library_path of the classloader.
|
||||
initialized_ = android_init_anonymous_namespace(public_libraries_.c_str(),
|
||||
initialized_ = android_init_anonymous_namespace(system_public_libraries_.c_str(),
|
||||
is_native_bridge ? nullptr : library_path);
|
||||
if (!initialized_) {
|
||||
*error_msg = dlerror();
|
||||
|
@ -334,10 +365,10 @@ class LibraryNamespaces {
|
|||
|
||||
// and now initialize native bridge namespaces if necessary.
|
||||
if (NativeBridgeInitialized()) {
|
||||
initialized_ = NativeBridgeInitAnonymousNamespace(
|
||||
public_libraries_.c_str(), is_native_bridge ? library_path : nullptr);
|
||||
if (!initialized_) {
|
||||
*error_msg = NativeBridgeGetError();
|
||||
initialized_ = NativeBridgeInitAnonymousNamespace(system_public_libraries_.c_str(),
|
||||
is_native_bridge ? library_path : nullptr);
|
||||
if (!initialized_) {
|
||||
*error_msg = NativeBridgeGetError();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,8 +402,8 @@ class LibraryNamespaces {
|
|||
|
||||
bool initialized_;
|
||||
std::vector<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
|
||||
std::string public_libraries_;
|
||||
|
||||
std::string system_public_libraries_;
|
||||
std::string vendor_public_libraries_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LibraryNamespaces);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue