Loading include/nativebridge/native_bridge.h +138 −1 Original line number Diff line number Diff line Loading @@ -62,12 +62,19 @@ bool NativeBridgeAvailable(); bool NativeBridgeInitialized(); // Load a shared library that is supported by the native bridge. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use NativeBridgeLoadLibraryExt() instead in namespace scenario. void* NativeBridgeLoadLibrary(const char* libpath, int flag); // Get a native bridge trampoline for specified native method. void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len); // True if native library is valid and is for an ABI that is supported by native bridge. // True if native library paths are valid and is for an ABI that is supported by native bridge. // The *libpath* must point to a library. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use NativeBridgeIsPathSupported() instead in namespace scenario. bool NativeBridgeIsSupported(const char* libpath); // Returns the version number of the native bridge. This information is available after a Loading @@ -91,6 +98,48 @@ bool NativeBridgeError(); // This functionality is exposed mainly for testing. bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename); // Decrements the reference count on the dynamic library handler. If the reference count drops // to zero then the dynamic library is unloaded. int NativeBridgeUnloadLibrary(void* handle); // Get last error message of native bridge when fail to load library or search symbol. // This is reflection of dlerror() for native bridge. char* NativeBridgeGetError(); struct native_bridge_namespace_t; // True if native library paths are valid and is for an ABI that is supported by native bridge. // Different from NativeBridgeIsSupported(), the *path* here must be a directory containing // libraries of an ABI. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use NativeBridgeIsSupported() instead in non-namespace scenario. bool NativeBridgeIsPathSupported(const char* path); // Initializes public and anonymous namespace at native bridge side. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. bool NativeBridgeInitNamespace(const char* public_ns_sonames, const char* anon_ns_library_path); // Create a namespace and pass the key of related namespaces to native bridge. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, native_bridge_namespace_t* parent_ns); // Load a shared library with namespace key that is supported by the native bridge. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use NativeBridgeLoadLibrary() instead in non-namespace scenario. void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns); // Native bridge interfaces to runtime. struct NativeBridgeCallbacks { // Version number of the interface. Loading @@ -114,6 +163,9 @@ struct NativeBridgeCallbacks { // flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h // Returns: // The opaque handle of the shared library if sucessful, otherwise NULL // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use loadLibraryExt instead in namespace scenario. void* (*loadLibrary)(const char* libpath, int flag); // Get a native bridge trampoline for specified native method. The trampoline has same Loading @@ -133,6 +185,9 @@ struct NativeBridgeCallbacks { // libpath [IN] path to the shared library // Returns: // TRUE if library is supported by native bridge, FALSE otherwise // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use isPathSupported instead in namespace scenario. bool (*isSupported)(const char* libpath); // Provide environment values required by the app running with native bridge according to the Loading Loading @@ -169,6 +224,88 @@ struct NativeBridgeCallbacks { // runtime. // Otherwise, a pointer to the signal handler. NativeBridgeSignalHandlerFn (*getSignalHandler)(int signal); // Added callbacks in version 3. // Decrements the reference count on the dynamic library handler. If the reference count drops // to zero then the dynamic library is unloaded. // // Parameters: // handle [IN] the handler of a dynamic library. // // Returns: // 0 on success, and nonzero on error. int (*unloadLibrary)(void* handle); // Dump the last failure message of native bridge when fail to load library or search symbol. // // Parameters: // // Returns: // A string describing the most recent error that occurred when load library // or lookup symbol via native bridge. char* (*getError)(); // Check whether library paths are supported by native bridge. // // Parameters: // library_path [IN] search paths for native libraries (directories separated by ':') // Returns: // TRUE if libraries within search paths are supported by native bridge, FALSE otherwise // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use isSupported instead in non-namespace scenario. bool (*isPathSupported)(const char* library_path); // Initializes anonymous namespace at native bridge side and pass the key of // two namespaces(default and anonymous) owned by dynamic linker to native bridge. // // Parameters: // public_ns_sonames [IN] the name of "public" libraries. // anon_ns_library_path [IN] the library search path of (anonymous) namespace. // Returns: // true if the pass is ok. // Otherwise, false. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. bool (*initNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path); // Create a namespace and pass the key of releated namespaces to native bridge. // // Parameters: // name [IN] the name of the namespace. // ld_library_path [IN] the first set of library search paths of the namespace. // default_library_path [IN] the second set of library search path of the namespace. // type [IN] the attribute of the namespace. // permitted_when_isolated_path [IN] the permitted path for isolated namespace(if it is). // parent_ns [IN] the pointer of the parent namespace to be inherited from. // Returns: // native_bridge_namespace_t* for created namespace or nullptr in the case of error. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. native_bridge_namespace_t* (*createNamespace)(const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, native_bridge_namespace_t* parent_ns); // Load a shared library within a namespace. // // Parameters: // libpath [IN] path to the shared library // flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h // ns [IN] the pointer of the namespace in which the library should be loaded. // Returns: // The opaque handle of the shared library if sucessful, otherwise NULL // // 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); }; // Runtime interfaces to native bridge. Loading libnativebridge/native_bridge.cc +105 −12 Original line number Diff line number Diff line Loading @@ -80,6 +80,19 @@ static const char* GetNativeBridgeStateString(NativeBridgeState state) { // Current state of the native bridge. static NativeBridgeState state = NativeBridgeState::kNotSetup; // The version of NativeBridge implementation. // Different Nativebridge interface needs the service of different version of // 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, }; // Whether we had an error at some point. static bool had_error = false; Loading @@ -100,8 +113,6 @@ static char* app_code_cache_dir = nullptr; // and hard code the directory name again here. static constexpr const char* kCodeCacheDir = "code_cache"; static constexpr uint32_t kLibNativeBridgeVersion = 2; // Characters allowed in a native bridge filename. The first character must // be in [a-zA-Z] (expected 'l' for "libx"). The rest must be in [a-zA-Z0-9._-]. static bool CharacterAllowed(char c, bool first) { Loading Loading @@ -152,19 +163,18 @@ bool NativeBridgeNameAcceptable(const char* nb_library_filename) { } } static bool VersionCheck(const NativeBridgeCallbacks* cb) { // The policy of invoking Nativebridge changed in v3 with/without namespace. // Suggest Nativebridge implementation not maintain backward-compatible. static bool isCompatibleWith(const uint32_t version) { // Libnativebridge is now designed to be forward-compatible. So only "0" is an unsupported // version. if (cb == nullptr || cb->version == 0) { if (callbacks == nullptr || callbacks->version == 0 || version == 0) { return false; } // If this is a v2+ bridge, it may not be forwards- or backwards-compatible. Check. if (cb->version >= 2) { if (!callbacks->isCompatibleWith(kLibNativeBridgeVersion)) { // TODO: Scan which version is supported, and fall back to handle it. return false; } if (callbacks->version >= SIGNAL_VERSION) { return callbacks->isCompatibleWith(version); } return true; Loading Loading @@ -205,7 +215,7 @@ bool LoadNativeBridge(const char* nb_library_filename, callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle, kNativeBridgeInterfaceSymbol)); if (callbacks != nullptr) { if (VersionCheck(callbacks)) { if (isCompatibleWith(NAMESPACE_VERSION)) { // Store the handle for later. native_bridge_handle = handle; } else { Loading Loading @@ -520,8 +530,91 @@ uint32_t NativeBridgeGetVersion() { } NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) { if (NativeBridgeInitialized() && callbacks->version >= 2) { if (NativeBridgeInitialized()) { if (isCompatibleWith(SIGNAL_VERSION)) { return callbacks->getSignalHandler(signal); } else { ALOGE("not compatible with version %d, cannot get signal handler", SIGNAL_VERSION); } } return nullptr; } int NativeBridgeUnloadLibrary(void* handle) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->unloadLibrary(handle); } else { ALOGE("not compatible with version %d, cannot unload library", NAMESPACE_VERSION); } } return -1; } char* NativeBridgeGetError() { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->getError(); } else { ALOGE("not compatible with version %d, cannot get message", NAMESPACE_VERSION); } } return nullptr; } bool NativeBridgeIsPathSupported(const char* path) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->isPathSupported(path); } else { ALOGE("not compatible with version %d, cannot check via library path", NAMESPACE_VERSION); } } return false; } bool NativeBridgeInitNamespace(const char* public_ns_sonames, const char* anon_ns_library_path) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->initNamespace(public_ns_sonames, anon_ns_library_path); } else { ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION); } } return false; } native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, native_bridge_namespace_t* parent_ns) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->createNamespace(name, ld_library_path, default_library_path, type, permitted_when_isolated_path, parent_ns); } else { ALOGE("not compatible with version %d, cannot create namespace %s", NAMESPACE_VERSION, name); } } return nullptr; } void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->loadLibraryExt(libpath, flag, ns); } else { ALOGE("not compatible with version %d, cannot load library in namespace", NAMESPACE_VERSION); } } return nullptr; } Loading libnativebridge/tests/Android.mk +7 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,13 @@ test_src_files := \ PreInitializeNativeBridgeFail2_test.cpp \ ReSetupNativeBridge_test.cpp \ UnavailableNativeBridge_test.cpp \ ValidNameNativeBridge_test.cpp ValidNameNativeBridge_test.cpp \ NativeBridge3UnloadLibrary_test.cpp \ NativeBridge3GetError_test.cpp \ NativeBridge3IsPathSupported_test.cpp \ NativeBridge3InitNamespace_test.cpp \ NativeBridge3CreateNamespace_test.cpp \ NativeBridge3LoadLibraryExt_test.cpp shared_libraries := \ Loading libnativebridge/tests/Android.nativebridge-dummy.mk +38 −0 Original line number Diff line number Diff line Loading @@ -68,3 +68,41 @@ LOCAL_LDFLAGS := -ldl LOCAL_MULTILIB := both include $(BUILD_HOST_SHARED_LIBRARY) # v3. NATIVE_BRIDGE3_COMMON_SRC_FILES := \ DummyNativeBridge3.cpp # Shared library for target # ======================================================== include $(CLEAR_VARS) LOCAL_MODULE:= libnativebridge3-dummy LOCAL_SRC_FILES:= $(NATIVE_BRIDGE3_COMMON_SRC_FILES) LOCAL_CLANG := true LOCAL_CFLAGS += -Werror -Wall LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected LOCAL_LDFLAGS := -ldl LOCAL_MULTILIB := both include $(BUILD_SHARED_LIBRARY) # Shared library for host # ======================================================== include $(CLEAR_VARS) LOCAL_MODULE:= libnativebridge3-dummy LOCAL_SRC_FILES:= $(NATIVE_BRIDGE3_COMMON_SRC_FILES) LOCAL_CLANG := true LOCAL_CFLAGS += -Werror -Wall LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected LOCAL_LDFLAGS := -ldl LOCAL_MULTILIB := both include $(BUILD_HOST_SHARED_LIBRARY) libnativebridge/tests/DummyNativeBridge3.cpp 0 → 100644 +120 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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. */ // A dummy implementation of the native-bridge interface. #include "nativebridge/native_bridge.h" #include <signal.h> // NativeBridgeCallbacks implementations extern "C" bool native_bridge3_initialize( const android::NativeBridgeRuntimeCallbacks* /* art_cbs */, const char* /* app_code_cache_dir */, const char* /* isa */) { return true; } extern "C" void* native_bridge3_loadLibrary(const char* /* libpath */, int /* flag */) { return nullptr; } extern "C" void* native_bridge3_getTrampoline(void* /* handle */, const char* /* name */, const char* /* shorty */, uint32_t /* len */) { return nullptr; } extern "C" bool native_bridge3_isSupported(const char* /* libpath */) { return false; } extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge3_getAppEnv( const char* /* abi */) { return nullptr; } extern "C" bool native_bridge3_isCompatibleWith(uint32_t version) { // For testing, allow 1-3, but disallow 4+. return version <= 3; } static bool native_bridge3_dummy_signal_handler(int, siginfo_t*, void*) { // TODO: Implement something here. We'd either have to have a death test with a log here, or // we'd have to be able to resume after the faulting instruction... return true; } extern "C" android::NativeBridgeSignalHandlerFn native_bridge3_getSignalHandler(int signal) { if (signal == SIGSEGV) { return &native_bridge3_dummy_signal_handler; } return nullptr; } extern "C" int native_bridge3_unloadLibrary(void* /* handle */) { return 0; } extern "C" char* native_bridge3_getError() { return nullptr; } extern "C" bool native_bridge3_isPathSupported(const char* /* path */) { return true; } extern "C" bool native_bridge3_initNamespace(const char* /* public_ns_sonames */, const char* /* anon_ns_library_path */) { return true; } extern "C" android::native_bridge_namespace_t* native_bridge3_createNamespace(const char* /* name */, const char* /* ld_library_path */, const char* /* default_library_path */, uint64_t /* type */, const char* /* permitted_when_isolated_path */, android::native_bridge_namespace_t* /* parent_ns */) { return nullptr; } extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */, int /* flag */, android::native_bridge_namespace_t* /* ns */) { return nullptr; } android::NativeBridgeCallbacks NativeBridgeItf { // v1 .version = 3, .initialize = &native_bridge3_initialize, .loadLibrary = &native_bridge3_loadLibrary, .getTrampoline = &native_bridge3_getTrampoline, .isSupported = &native_bridge3_isSupported, .getAppEnv = &native_bridge3_getAppEnv, // v2 .isCompatibleWith = &native_bridge3_isCompatibleWith, .getSignalHandler = &native_bridge3_getSignalHandler, // v3 .unloadLibrary = &native_bridge3_unloadLibrary, .getError = &native_bridge3_getError, .isPathSupported = &native_bridge3_isPathSupported, .initNamespace = &native_bridge3_initNamespace, .createNamespace = &native_bridge3_createNamespace, .loadLibraryExt = &native_bridge3_loadLibraryExt }; Loading
include/nativebridge/native_bridge.h +138 −1 Original line number Diff line number Diff line Loading @@ -62,12 +62,19 @@ bool NativeBridgeAvailable(); bool NativeBridgeInitialized(); // Load a shared library that is supported by the native bridge. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use NativeBridgeLoadLibraryExt() instead in namespace scenario. void* NativeBridgeLoadLibrary(const char* libpath, int flag); // Get a native bridge trampoline for specified native method. void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len); // True if native library is valid and is for an ABI that is supported by native bridge. // True if native library paths are valid and is for an ABI that is supported by native bridge. // The *libpath* must point to a library. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use NativeBridgeIsPathSupported() instead in namespace scenario. bool NativeBridgeIsSupported(const char* libpath); // Returns the version number of the native bridge. This information is available after a Loading @@ -91,6 +98,48 @@ bool NativeBridgeError(); // This functionality is exposed mainly for testing. bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename); // Decrements the reference count on the dynamic library handler. If the reference count drops // to zero then the dynamic library is unloaded. int NativeBridgeUnloadLibrary(void* handle); // Get last error message of native bridge when fail to load library or search symbol. // This is reflection of dlerror() for native bridge. char* NativeBridgeGetError(); struct native_bridge_namespace_t; // True if native library paths are valid and is for an ABI that is supported by native bridge. // Different from NativeBridgeIsSupported(), the *path* here must be a directory containing // libraries of an ABI. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use NativeBridgeIsSupported() instead in non-namespace scenario. bool NativeBridgeIsPathSupported(const char* path); // Initializes public and anonymous namespace at native bridge side. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. bool NativeBridgeInitNamespace(const char* public_ns_sonames, const char* anon_ns_library_path); // Create a namespace and pass the key of related namespaces to native bridge. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, native_bridge_namespace_t* parent_ns); // Load a shared library with namespace key that is supported by the native bridge. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use NativeBridgeLoadLibrary() instead in non-namespace scenario. void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns); // Native bridge interfaces to runtime. struct NativeBridgeCallbacks { // Version number of the interface. Loading @@ -114,6 +163,9 @@ struct NativeBridgeCallbacks { // flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h // Returns: // The opaque handle of the shared library if sucessful, otherwise NULL // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use loadLibraryExt instead in namespace scenario. void* (*loadLibrary)(const char* libpath, int flag); // Get a native bridge trampoline for specified native method. The trampoline has same Loading @@ -133,6 +185,9 @@ struct NativeBridgeCallbacks { // libpath [IN] path to the shared library // Returns: // TRUE if library is supported by native bridge, FALSE otherwise // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use isPathSupported instead in namespace scenario. bool (*isSupported)(const char* libpath); // Provide environment values required by the app running with native bridge according to the Loading Loading @@ -169,6 +224,88 @@ struct NativeBridgeCallbacks { // runtime. // Otherwise, a pointer to the signal handler. NativeBridgeSignalHandlerFn (*getSignalHandler)(int signal); // Added callbacks in version 3. // Decrements the reference count on the dynamic library handler. If the reference count drops // to zero then the dynamic library is unloaded. // // Parameters: // handle [IN] the handler of a dynamic library. // // Returns: // 0 on success, and nonzero on error. int (*unloadLibrary)(void* handle); // Dump the last failure message of native bridge when fail to load library or search symbol. // // Parameters: // // Returns: // A string describing the most recent error that occurred when load library // or lookup symbol via native bridge. char* (*getError)(); // Check whether library paths are supported by native bridge. // // Parameters: // library_path [IN] search paths for native libraries (directories separated by ':') // Returns: // TRUE if libraries within search paths are supported by native bridge, FALSE otherwise // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use isSupported instead in non-namespace scenario. bool (*isPathSupported)(const char* library_path); // Initializes anonymous namespace at native bridge side and pass the key of // two namespaces(default and anonymous) owned by dynamic linker to native bridge. // // Parameters: // public_ns_sonames [IN] the name of "public" libraries. // anon_ns_library_path [IN] the library search path of (anonymous) namespace. // Returns: // true if the pass is ok. // Otherwise, false. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. bool (*initNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path); // Create a namespace and pass the key of releated namespaces to native bridge. // // Parameters: // name [IN] the name of the namespace. // ld_library_path [IN] the first set of library search paths of the namespace. // default_library_path [IN] the second set of library search path of the namespace. // type [IN] the attribute of the namespace. // permitted_when_isolated_path [IN] the permitted path for isolated namespace(if it is). // parent_ns [IN] the pointer of the parent namespace to be inherited from. // Returns: // native_bridge_namespace_t* for created namespace or nullptr in the case of error. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. native_bridge_namespace_t* (*createNamespace)(const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, native_bridge_namespace_t* parent_ns); // Load a shared library within a namespace. // // Parameters: // libpath [IN] path to the shared library // flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h // ns [IN] the pointer of the namespace in which the library should be loaded. // Returns: // The opaque handle of the shared library if sucessful, otherwise NULL // // 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); }; // Runtime interfaces to native bridge. Loading
libnativebridge/native_bridge.cc +105 −12 Original line number Diff line number Diff line Loading @@ -80,6 +80,19 @@ static const char* GetNativeBridgeStateString(NativeBridgeState state) { // Current state of the native bridge. static NativeBridgeState state = NativeBridgeState::kNotSetup; // The version of NativeBridge implementation. // Different Nativebridge interface needs the service of different version of // 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, }; // Whether we had an error at some point. static bool had_error = false; Loading @@ -100,8 +113,6 @@ static char* app_code_cache_dir = nullptr; // and hard code the directory name again here. static constexpr const char* kCodeCacheDir = "code_cache"; static constexpr uint32_t kLibNativeBridgeVersion = 2; // Characters allowed in a native bridge filename. The first character must // be in [a-zA-Z] (expected 'l' for "libx"). The rest must be in [a-zA-Z0-9._-]. static bool CharacterAllowed(char c, bool first) { Loading Loading @@ -152,19 +163,18 @@ bool NativeBridgeNameAcceptable(const char* nb_library_filename) { } } static bool VersionCheck(const NativeBridgeCallbacks* cb) { // The policy of invoking Nativebridge changed in v3 with/without namespace. // Suggest Nativebridge implementation not maintain backward-compatible. static bool isCompatibleWith(const uint32_t version) { // Libnativebridge is now designed to be forward-compatible. So only "0" is an unsupported // version. if (cb == nullptr || cb->version == 0) { if (callbacks == nullptr || callbacks->version == 0 || version == 0) { return false; } // If this is a v2+ bridge, it may not be forwards- or backwards-compatible. Check. if (cb->version >= 2) { if (!callbacks->isCompatibleWith(kLibNativeBridgeVersion)) { // TODO: Scan which version is supported, and fall back to handle it. return false; } if (callbacks->version >= SIGNAL_VERSION) { return callbacks->isCompatibleWith(version); } return true; Loading Loading @@ -205,7 +215,7 @@ bool LoadNativeBridge(const char* nb_library_filename, callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle, kNativeBridgeInterfaceSymbol)); if (callbacks != nullptr) { if (VersionCheck(callbacks)) { if (isCompatibleWith(NAMESPACE_VERSION)) { // Store the handle for later. native_bridge_handle = handle; } else { Loading Loading @@ -520,8 +530,91 @@ uint32_t NativeBridgeGetVersion() { } NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) { if (NativeBridgeInitialized() && callbacks->version >= 2) { if (NativeBridgeInitialized()) { if (isCompatibleWith(SIGNAL_VERSION)) { return callbacks->getSignalHandler(signal); } else { ALOGE("not compatible with version %d, cannot get signal handler", SIGNAL_VERSION); } } return nullptr; } int NativeBridgeUnloadLibrary(void* handle) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->unloadLibrary(handle); } else { ALOGE("not compatible with version %d, cannot unload library", NAMESPACE_VERSION); } } return -1; } char* NativeBridgeGetError() { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->getError(); } else { ALOGE("not compatible with version %d, cannot get message", NAMESPACE_VERSION); } } return nullptr; } bool NativeBridgeIsPathSupported(const char* path) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->isPathSupported(path); } else { ALOGE("not compatible with version %d, cannot check via library path", NAMESPACE_VERSION); } } return false; } bool NativeBridgeInitNamespace(const char* public_ns_sonames, const char* anon_ns_library_path) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->initNamespace(public_ns_sonames, anon_ns_library_path); } else { ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION); } } return false; } native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, native_bridge_namespace_t* parent_ns) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->createNamespace(name, ld_library_path, default_library_path, type, permitted_when_isolated_path, parent_ns); } else { ALOGE("not compatible with version %d, cannot create namespace %s", NAMESPACE_VERSION, name); } } return nullptr; } void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { return callbacks->loadLibraryExt(libpath, flag, ns); } else { ALOGE("not compatible with version %d, cannot load library in namespace", NAMESPACE_VERSION); } } return nullptr; } Loading
libnativebridge/tests/Android.mk +7 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,13 @@ test_src_files := \ PreInitializeNativeBridgeFail2_test.cpp \ ReSetupNativeBridge_test.cpp \ UnavailableNativeBridge_test.cpp \ ValidNameNativeBridge_test.cpp ValidNameNativeBridge_test.cpp \ NativeBridge3UnloadLibrary_test.cpp \ NativeBridge3GetError_test.cpp \ NativeBridge3IsPathSupported_test.cpp \ NativeBridge3InitNamespace_test.cpp \ NativeBridge3CreateNamespace_test.cpp \ NativeBridge3LoadLibraryExt_test.cpp shared_libraries := \ Loading
libnativebridge/tests/Android.nativebridge-dummy.mk +38 −0 Original line number Diff line number Diff line Loading @@ -68,3 +68,41 @@ LOCAL_LDFLAGS := -ldl LOCAL_MULTILIB := both include $(BUILD_HOST_SHARED_LIBRARY) # v3. NATIVE_BRIDGE3_COMMON_SRC_FILES := \ DummyNativeBridge3.cpp # Shared library for target # ======================================================== include $(CLEAR_VARS) LOCAL_MODULE:= libnativebridge3-dummy LOCAL_SRC_FILES:= $(NATIVE_BRIDGE3_COMMON_SRC_FILES) LOCAL_CLANG := true LOCAL_CFLAGS += -Werror -Wall LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected LOCAL_LDFLAGS := -ldl LOCAL_MULTILIB := both include $(BUILD_SHARED_LIBRARY) # Shared library for host # ======================================================== include $(CLEAR_VARS) LOCAL_MODULE:= libnativebridge3-dummy LOCAL_SRC_FILES:= $(NATIVE_BRIDGE3_COMMON_SRC_FILES) LOCAL_CLANG := true LOCAL_CFLAGS += -Werror -Wall LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected LOCAL_LDFLAGS := -ldl LOCAL_MULTILIB := both include $(BUILD_HOST_SHARED_LIBRARY)
libnativebridge/tests/DummyNativeBridge3.cpp 0 → 100644 +120 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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. */ // A dummy implementation of the native-bridge interface. #include "nativebridge/native_bridge.h" #include <signal.h> // NativeBridgeCallbacks implementations extern "C" bool native_bridge3_initialize( const android::NativeBridgeRuntimeCallbacks* /* art_cbs */, const char* /* app_code_cache_dir */, const char* /* isa */) { return true; } extern "C" void* native_bridge3_loadLibrary(const char* /* libpath */, int /* flag */) { return nullptr; } extern "C" void* native_bridge3_getTrampoline(void* /* handle */, const char* /* name */, const char* /* shorty */, uint32_t /* len */) { return nullptr; } extern "C" bool native_bridge3_isSupported(const char* /* libpath */) { return false; } extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge3_getAppEnv( const char* /* abi */) { return nullptr; } extern "C" bool native_bridge3_isCompatibleWith(uint32_t version) { // For testing, allow 1-3, but disallow 4+. return version <= 3; } static bool native_bridge3_dummy_signal_handler(int, siginfo_t*, void*) { // TODO: Implement something here. We'd either have to have a death test with a log here, or // we'd have to be able to resume after the faulting instruction... return true; } extern "C" android::NativeBridgeSignalHandlerFn native_bridge3_getSignalHandler(int signal) { if (signal == SIGSEGV) { return &native_bridge3_dummy_signal_handler; } return nullptr; } extern "C" int native_bridge3_unloadLibrary(void* /* handle */) { return 0; } extern "C" char* native_bridge3_getError() { return nullptr; } extern "C" bool native_bridge3_isPathSupported(const char* /* path */) { return true; } extern "C" bool native_bridge3_initNamespace(const char* /* public_ns_sonames */, const char* /* anon_ns_library_path */) { return true; } extern "C" android::native_bridge_namespace_t* native_bridge3_createNamespace(const char* /* name */, const char* /* ld_library_path */, const char* /* default_library_path */, uint64_t /* type */, const char* /* permitted_when_isolated_path */, android::native_bridge_namespace_t* /* parent_ns */) { return nullptr; } extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */, int /* flag */, android::native_bridge_namespace_t* /* ns */) { return nullptr; } android::NativeBridgeCallbacks NativeBridgeItf { // v1 .version = 3, .initialize = &native_bridge3_initialize, .loadLibrary = &native_bridge3_loadLibrary, .getTrampoline = &native_bridge3_getTrampoline, .isSupported = &native_bridge3_isSupported, .getAppEnv = &native_bridge3_getAppEnv, // v2 .isCompatibleWith = &native_bridge3_isCompatibleWith, .getSignalHandler = &native_bridge3_getSignalHandler, // v3 .unloadLibrary = &native_bridge3_unloadLibrary, .getError = &native_bridge3_getError, .isPathSupported = &native_bridge3_isPathSupported, .initNamespace = &native_bridge3_initNamespace, .createNamespace = &native_bridge3_createNamespace, .loadLibraryExt = &native_bridge3_loadLibraryExt };