upload android base code part6

This commit is contained in:
August 2018-08-08 17:48:24 +08:00
parent 421e214c7d
commit 4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions

View file

@ -0,0 +1 @@
../.clang-format-2

View file

@ -0,0 +1,35 @@
cc_library_headers {
name: "libnativebridge-dummy-headers",
host_supported: true,
export_include_dirs=["include"],
}
cc_library {
name: "libnativebridge",
host_supported: true,
srcs: ["native_bridge.cc"],
shared_libs: ["liblog"],
clang: true,
export_include_dirs=["include"],
cflags: [
"-Werror",
"-Wall",
],
cppflags: [
"-fvisibility=protected",
],
host_ldlibs: ["-ldl"],
target: {
android: {
shared_libs: ["libdl"],
},
},
}
subdirs = ["tests"]

View file

@ -0,0 +1,3 @@
LOCAL_PATH:= $(call my-dir)
include $(LOCAL_PATH)/tests/Android.mk

View file

@ -0,0 +1,401 @@
/*
* Copyright (C) 2014 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_BRIDGE_H_
#define NATIVE_BRIDGE_H_
#include "jni.h"
#include <signal.h>
#include <stdint.h>
#include <sys/types.h>
namespace android {
struct NativeBridgeRuntimeCallbacks;
struct NativeBridgeRuntimeValues;
// Function pointer type for sigaction. This is mostly the signature of a signal handler, except
// for the return type. The runtime needs to know whether the signal was handled or should be given
// to the chain.
typedef bool (*NativeBridgeSignalHandlerFn)(int, siginfo_t*, void*);
// Open the native bridge, if any. Should be called by Runtime::Init(). A null library filename
// signals that we do not want to load a native bridge.
bool LoadNativeBridge(const char* native_bridge_library_filename,
const NativeBridgeRuntimeCallbacks* runtime_callbacks);
// Quick check whether a native bridge will be needed. This is based off of the instruction set
// of the process.
bool NeedsNativeBridge(const char* instruction_set);
// Do the early initialization part of the native bridge, if necessary. This should be done under
// high privileges.
bool PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set);
// Initialize the native bridge, if any. Should be called by Runtime::DidForkFromZygote. The JNIEnv*
// will be used to modify the app environment for the bridge.
bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set);
// Unload the native bridge, if any. Should be called by Runtime::DidForkFromZygote.
void UnloadNativeBridge();
// Check whether a native bridge is available (opened or initialized). Requires a prior call to
// LoadNativeBridge.
bool NativeBridgeAvailable();
// Check whether a native bridge is available (initialized). Requires a prior call to
// LoadNativeBridge & InitializeNativeBridge.
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 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
// successful LoadNativeBridge() and before closing it, that is, as long as NativeBridgeAvailable()
// returns true. Returns 0 otherwise.
uint32_t NativeBridgeGetVersion();
// Returns a signal handler that the bridge would like to be managed. Only valid for a native
// bridge supporting the version 2 interface. Will return null if the bridge does not support
// version 2, or if it doesn't have a signal handler it wants to be known.
NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal);
// Returns whether we have seen a native bridge error. This could happen because the library
// was not found, rejected, could not be initialized and so on.
//
// This functionality is mainly for testing.
bool NativeBridgeError();
// Returns whether a given string is acceptable as a native bridge library filename.
//
// 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.
const 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 anonymous namespace.
// NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
//
// The anonymous namespace is used in the case when a NativeBridge implementation
// cannot identify the caller of dlopen/dlsym which happens for the code not loaded
// by dynamic linker; for example calls from the mono-compiled code.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
const char* anon_ns_library_path);
// Create new namespace in which native libraries will be loaded.
// NativeBridge's peer of android_create_namespace() of dynamic linker.
//
// The libraries in the namespace are searched by folowing order:
// 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
// 2. In directories specified by DT_RUNPATH of the "needed by" binary.
// 3. deault_library_path (This of this as namespace-local default library path)
//
// 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);
// Creates a link which shares some libraries from one namespace to another.
// NativeBridge's peer of android_link_namespaces() of dynamic linker.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
const char* shared_libs_sonames);
// Load a shared library with namespace key that is supported by the native bridge.
// NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
// extension.
//
// 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);
// 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.
uint32_t version;
// Initialize native bridge. Native bridge's internal implementation must ensure MT safety and
// that the native bridge is initialized only once. Thus it is OK to call this interface for an
// already initialized native bridge.
//
// Parameters:
// runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
// Returns:
// true if initialization was successful.
bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,
const char* instruction_set);
// Load a shared library that is supported by the native bridge.
//
// Parameters:
// libpath [IN] path to the shared library
// 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
// sigature as the native method.
//
// Parameters:
// handle [IN] the handle returned from loadLibrary
// shorty [IN] short descriptor of native method
// len [IN] length of shorty
// Returns:
// address of trampoline if successful, otherwise NULL
void* (*getTrampoline)(void* handle, const char* name, const char* shorty, uint32_t len);
// Check whether native library is valid and is for an ABI that is supported by native bridge.
//
// Parameters:
// 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
// instruction set.
//
// Parameters:
// instruction_set [IN] the instruction set of the app
// Returns:
// NULL if not supported by native bridge.
// Otherwise, return all environment values to be set after fork.
const struct NativeBridgeRuntimeValues* (*getAppEnv)(const char* instruction_set);
// Added callbacks in version 2.
// Check whether the bridge is compatible with the given version. A bridge may decide not to be
// forwards- or backwards-compatible, and libnativebridge will then stop using it.
//
// Parameters:
// bridge_version [IN] the version of libnativebridge.
// Returns:
// true if the native bridge supports the given version of libnativebridge.
bool (*isCompatibleWith)(uint32_t bridge_version);
// A callback to retrieve a native bridge's signal handler for the specified signal. The runtime
// will ensure that the signal handler is being called after the runtime's own handler, but before
// all chained handlers. The native bridge should not try to install the handler by itself, as
// that will potentially lead to cycles.
//
// Parameters:
// signal [IN] the signal for which the handler is asked for. Currently, only SIGSEGV is
// supported by the runtime.
// Returns:
// NULL if the native bridge doesn't use a handler or doesn't want it to be managed by the
// 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.
const 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.
// NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
//
// The anonymous namespace is used in the case when a NativeBridge implementation
// cannot identify the caller of dlopen/dlsym which happens for the code not loaded
// by dynamic linker; for example calls from the mono-compiled code.
//
// 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 (*initAnonymousNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path);
// Create new namespace in which native libraries will be loaded.
// NativeBridge's peer of android_create_namespace() of dynamic linker.
//
// 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);
// Creates a link which shares some libraries from one namespace to another.
// NativeBridge's peer of android_link_namespaces() of dynamic linker.
//
// Parameters:
// from [IN] the namespace where libraries are accessed.
// to [IN] the namespace where libraries are loaded.
// shared_libs_sonames [IN] the libraries to be shared.
//
// Returns:
// Whether successed or not.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
bool (*linkNamespaces)(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
const char* shared_libs_sonames);
// Load a shared library within a namespace.
// NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
// extension.
//
// 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);
// 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.
struct NativeBridgeRuntimeCallbacks {
// Get shorty of a Java method. The shorty is supposed to be persistent in memory.
//
// Parameters:
// env [IN] pointer to JNIenv.
// mid [IN] Java methodID.
// Returns:
// short descriptor for method.
const char* (*getMethodShorty)(JNIEnv* env, jmethodID mid);
// Get number of native methods for specified class.
//
// Parameters:
// env [IN] pointer to JNIenv.
// clazz [IN] Java class object.
// Returns:
// number of native methods.
uint32_t (*getNativeMethodCount)(JNIEnv* env, jclass clazz);
// Get at most 'method_count' native methods for specified class 'clazz'. Results are outputed
// via 'methods' [OUT]. The signature pointer in JNINativeMethod is reused as the method shorty.
//
// Parameters:
// env [IN] pointer to JNIenv.
// clazz [IN] Java class object.
// methods [OUT] array of method with the name, shorty, and fnPtr.
// method_count [IN] max number of elements in methods.
// Returns:
// number of method it actually wrote to methods.
uint32_t (*getNativeMethods)(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
uint32_t method_count);
};
}; // namespace android
#endif // NATIVE_BRIDGE_H_

View file

@ -0,0 +1,645 @@
/*
* Copyright (C) 2014 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.
*/
#define LOG_TAG "nativebridge"
#include "nativebridge/native_bridge.h"
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstring>
#include <log/log.h>
namespace android {
// Environment values required by the apps running with native bridge.
struct NativeBridgeRuntimeValues {
const char* os_arch;
const char* cpu_abi;
const char* cpu_abi2;
const char* *supported_abis;
int32_t abi_count;
};
// The symbol name exposed by native-bridge with the type of NativeBridgeCallbacks.
static constexpr const char* kNativeBridgeInterfaceSymbol = "NativeBridgeItf";
enum class NativeBridgeState {
kNotSetup, // Initial state.
kOpened, // After successful dlopen.
kPreInitialized, // After successful pre-initialization.
kInitialized, // After successful initialization.
kClosed // Closed or errors.
};
static constexpr const char* kNotSetupString = "kNotSetup";
static constexpr const char* kOpenedString = "kOpened";
static constexpr const char* kPreInitializedString = "kPreInitialized";
static constexpr const char* kInitializedString = "kInitialized";
static constexpr const char* kClosedString = "kClosed";
static const char* GetNativeBridgeStateString(NativeBridgeState state) {
switch (state) {
case NativeBridgeState::kNotSetup:
return kNotSetupString;
case NativeBridgeState::kOpened:
return kOpenedString;
case NativeBridgeState::kPreInitialized:
return kPreInitializedString;
case NativeBridgeState::kInitialized:
return kInitializedString;
case NativeBridgeState::kClosed:
return kClosedString;
}
}
// 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,
// The version with vendor namespaces
VENDOR_NAMESPACE_VERSION = 4,
};
// Whether we had an error at some point.
static bool had_error = false;
// Handle of the loaded library.
static void* native_bridge_handle = nullptr;
// Pointer to the callbacks. Available as soon as LoadNativeBridge succeeds, but only initialized
// later.
static const NativeBridgeCallbacks* callbacks = nullptr;
// Callbacks provided by the environment to the bridge. Passed to LoadNativeBridge.
static const NativeBridgeRuntimeCallbacks* runtime_callbacks = nullptr;
// The app's code cache directory.
static char* app_code_cache_dir = nullptr;
// Code cache directory (relative to the application private directory)
// Ideally we'd like to call into framework to retrieve this name. However that's considered an
// implementation detail and will require either hacks or consistent refactorings. We compromise
// and hard code the directory name again here.
static constexpr const char* kCodeCacheDir = "code_cache";
// 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) {
if (first) {
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
} else {
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') ||
(c == '.') || (c == '_') || (c == '-');
}
}
static void ReleaseAppCodeCacheDir() {
if (app_code_cache_dir != nullptr) {
delete[] app_code_cache_dir;
app_code_cache_dir = nullptr;
}
}
// We only allow simple names for the library. It is supposed to be a file in
// /system/lib or /vendor/lib. Only allow a small range of characters, that is
// names consisting of [a-zA-Z0-9._-] and starting with [a-zA-Z].
bool NativeBridgeNameAcceptable(const char* nb_library_filename) {
const char* ptr = nb_library_filename;
if (*ptr == 0) {
// Emptry string. Allowed, means no native bridge.
return true;
} else {
// First character must be [a-zA-Z].
if (!CharacterAllowed(*ptr, true)) {
// Found an invalid fist character, don't accept.
ALOGE("Native bridge library %s has been rejected for first character %c",
nb_library_filename,
*ptr);
return false;
} else {
// For the rest, be more liberal.
ptr++;
while (*ptr != 0) {
if (!CharacterAllowed(*ptr, false)) {
// Found an invalid character, don't accept.
ALOGE("Native bridge library %s has been rejected for %c", nb_library_filename, *ptr);
return false;
}
ptr++;
}
}
return true;
}
}
// 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 (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 (callbacks->version >= SIGNAL_VERSION) {
return callbacks->isCompatibleWith(version);
}
return true;
}
static void CloseNativeBridge(bool with_error) {
state = NativeBridgeState::kClosed;
had_error |= with_error;
ReleaseAppCodeCacheDir();
}
bool LoadNativeBridge(const char* nb_library_filename,
const NativeBridgeRuntimeCallbacks* runtime_cbs) {
// We expect only one place that calls LoadNativeBridge: Runtime::Init. At that point we are not
// multi-threaded, so we do not need locking here.
if (state != NativeBridgeState::kNotSetup) {
// Setup has been called before. Ignore this call.
if (nb_library_filename != nullptr) { // Avoids some log-spam for dalvikvm.
ALOGW("Called LoadNativeBridge for an already set up native bridge. State is %s.",
GetNativeBridgeStateString(state));
}
// Note: counts as an error, even though the bridge may be functional.
had_error = true;
return false;
}
if (nb_library_filename == nullptr || *nb_library_filename == 0) {
CloseNativeBridge(false);
return false;
} else {
if (!NativeBridgeNameAcceptable(nb_library_filename)) {
CloseNativeBridge(true);
} else {
// Try to open the library.
void* handle = dlopen(nb_library_filename, RTLD_LAZY);
if (handle != nullptr) {
callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle,
kNativeBridgeInterfaceSymbol));
if (callbacks != nullptr) {
if (isCompatibleWith(NAMESPACE_VERSION)) {
// Store the handle for later.
native_bridge_handle = handle;
} else {
callbacks = nullptr;
dlclose(handle);
ALOGW("Unsupported native bridge interface.");
}
} else {
dlclose(handle);
}
}
// Two failure conditions: could not find library (dlopen failed), or could not find native
// bridge interface (dlsym failed). Both are an error and close the native bridge.
if (callbacks == nullptr) {
CloseNativeBridge(true);
} else {
runtime_callbacks = runtime_cbs;
state = NativeBridgeState::kOpened;
}
}
return state == NativeBridgeState::kOpened;
}
}
#if defined(__arm__)
static const char* kRuntimeISA = "arm";
#elif defined(__aarch64__)
static const char* kRuntimeISA = "arm64";
#elif defined(__mips__) && !defined(__LP64__)
static const char* kRuntimeISA = "mips";
#elif defined(__mips__) && defined(__LP64__)
static const char* kRuntimeISA = "mips64";
#elif defined(__i386__)
static const char* kRuntimeISA = "x86";
#elif defined(__x86_64__)
static const char* kRuntimeISA = "x86_64";
#else
static const char* kRuntimeISA = "unknown";
#endif
bool NeedsNativeBridge(const char* instruction_set) {
if (instruction_set == nullptr) {
ALOGE("Null instruction set in NeedsNativeBridge.");
return false;
}
return strncmp(instruction_set, kRuntimeISA, strlen(kRuntimeISA) + 1) != 0;
}
#ifdef __APPLE__
template<typename T> void UNUSED(const T&) {}
#endif
bool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) {
if (state != NativeBridgeState::kOpened) {
ALOGE("Invalid state: native bridge is expected to be opened.");
CloseNativeBridge(true);
return false;
}
if (app_data_dir_in == nullptr) {
ALOGE("Application private directory cannot be null.");
CloseNativeBridge(true);
return false;
}
// Create the path to the application code cache directory.
// The memory will be release after Initialization or when the native bridge is closed.
const size_t len = strlen(app_data_dir_in) + strlen(kCodeCacheDir) + 2; // '\0' + '/'
app_code_cache_dir = new char[len];
snprintf(app_code_cache_dir, len, "%s/%s", app_data_dir_in, kCodeCacheDir);
// Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo.
// Failure is not fatal and will keep the native bridge in kPreInitialized.
state = NativeBridgeState::kPreInitialized;
#ifndef __APPLE__
if (instruction_set == nullptr) {
return true;
}
size_t isa_len = strlen(instruction_set);
if (isa_len > 10) {
// 10 is a loose upper bound on the currently known instruction sets (a tight bound is 7 for
// x86_64 [including the trailing \0]). This is so we don't have to change here if there will
// be another instruction set in the future.
ALOGW("Instruction set %s is malformed, must be less than or equal to 10 characters.",
instruction_set);
return true;
}
// If the file does not exist, the mount command will fail,
// so we save the extra file existence check.
char cpuinfo_path[1024];
#if defined(__ANDROID__)
snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib"
#ifdef __LP64__
"64"
#endif // __LP64__
"/%s/cpuinfo", instruction_set);
#else // !__ANDROID__
// To be able to test on the host, we hardwire a relative path.
snprintf(cpuinfo_path, sizeof(cpuinfo_path), "./cpuinfo");
#endif
// Bind-mount.
if (TEMP_FAILURE_RETRY(mount(cpuinfo_path, // Source.
"/proc/cpuinfo", // Target.
nullptr, // FS type.
MS_BIND, // Mount flags: bind mount.
nullptr)) == -1) { // "Data."
ALOGW("Failed to bind-mount %s as /proc/cpuinfo: %s", cpuinfo_path, strerror(errno));
}
#else // __APPLE__
UNUSED(instruction_set);
ALOGW("Mac OS does not support bind-mounting. Host simulation of native bridge impossible.");
#endif
return true;
}
static void SetCpuAbi(JNIEnv* env, jclass build_class, const char* field, const char* value) {
if (value != nullptr) {
jfieldID field_id = env->GetStaticFieldID(build_class, field, "Ljava/lang/String;");
if (field_id == nullptr) {
env->ExceptionClear();
ALOGW("Could not find %s field.", field);
return;
}
jstring str = env->NewStringUTF(value);
if (str == nullptr) {
env->ExceptionClear();
ALOGW("Could not create string %s.", value);
return;
}
env->SetStaticObjectField(build_class, field_id, str);
}
}
// Set up the environment for the bridged app.
static void SetupEnvironment(const NativeBridgeCallbacks* callbacks, JNIEnv* env, const char* isa) {
// Need a JNIEnv* to do anything.
if (env == nullptr) {
ALOGW("No JNIEnv* to set up app environment.");
return;
}
// Query the bridge for environment values.
const struct NativeBridgeRuntimeValues* env_values = callbacks->getAppEnv(isa);
if (env_values == nullptr) {
return;
}
// Keep the JNIEnv clean.
jint success = env->PushLocalFrame(16); // That should be small and large enough.
if (success < 0) {
// Out of memory, really borked.
ALOGW("Out of memory while setting up app environment.");
env->ExceptionClear();
return;
}
// Reset CPU_ABI & CPU_ABI2 to values required by the apps running with native bridge.
if (env_values->cpu_abi != nullptr || env_values->cpu_abi2 != nullptr ||
env_values->abi_count >= 0) {
jclass bclass_id = env->FindClass("android/os/Build");
if (bclass_id != nullptr) {
SetCpuAbi(env, bclass_id, "CPU_ABI", env_values->cpu_abi);
SetCpuAbi(env, bclass_id, "CPU_ABI2", env_values->cpu_abi2);
} else {
// For example in a host test environment.
env->ExceptionClear();
ALOGW("Could not find Build class.");
}
}
if (env_values->os_arch != nullptr) {
jclass sclass_id = env->FindClass("java/lang/System");
if (sclass_id != nullptr) {
jmethodID set_prop_id = env->GetStaticMethodID(sclass_id, "setUnchangeableSystemProperty",
"(Ljava/lang/String;Ljava/lang/String;)V");
if (set_prop_id != nullptr) {
// Init os.arch to the value reqired by the apps running with native bridge.
env->CallStaticVoidMethod(sclass_id, set_prop_id, env->NewStringUTF("os.arch"),
env->NewStringUTF(env_values->os_arch));
} else {
env->ExceptionClear();
ALOGW("Could not find System#setUnchangeableSystemProperty.");
}
} else {
env->ExceptionClear();
ALOGW("Could not find System class.");
}
}
// Make it pristine again.
env->PopLocalFrame(nullptr);
}
bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
// We expect only one place that calls InitializeNativeBridge: Runtime::DidForkFromZygote. At that
// point we are not multi-threaded, so we do not need locking here.
if (state == NativeBridgeState::kPreInitialized) {
// Check for code cache: if it doesn't exist try to create it.
struct stat st;
if (stat(app_code_cache_dir, &st) == -1) {
if (errno == ENOENT) {
if (mkdir(app_code_cache_dir, S_IRWXU | S_IRWXG | S_IXOTH) == -1) {
ALOGW("Cannot create code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
ReleaseAppCodeCacheDir();
}
} else {
ALOGW("Cannot stat code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
ReleaseAppCodeCacheDir();
}
} else if (!S_ISDIR(st.st_mode)) {
ALOGW("Code cache is not a directory %s.", app_code_cache_dir);
ReleaseAppCodeCacheDir();
}
// If we're still PreInitialized (dind't fail the code cache checks) try to initialize.
if (state == NativeBridgeState::kPreInitialized) {
if (callbacks->initialize(runtime_callbacks, app_code_cache_dir, instruction_set)) {
SetupEnvironment(callbacks, env, instruction_set);
state = NativeBridgeState::kInitialized;
// We no longer need the code cache path, release the memory.
ReleaseAppCodeCacheDir();
} else {
// Unload the library.
dlclose(native_bridge_handle);
CloseNativeBridge(true);
}
}
} else {
CloseNativeBridge(true);
}
return state == NativeBridgeState::kInitialized;
}
void UnloadNativeBridge() {
// We expect only one place that calls UnloadNativeBridge: Runtime::DidForkFromZygote. At that
// point we are not multi-threaded, so we do not need locking here.
switch(state) {
case NativeBridgeState::kOpened:
case NativeBridgeState::kPreInitialized:
case NativeBridgeState::kInitialized:
// Unload.
dlclose(native_bridge_handle);
CloseNativeBridge(false);
break;
case NativeBridgeState::kNotSetup:
// Not even set up. Error.
CloseNativeBridge(true);
break;
case NativeBridgeState::kClosed:
// Ignore.
break;
}
}
bool NativeBridgeError() {
return had_error;
}
bool NativeBridgeAvailable() {
return state == NativeBridgeState::kOpened
|| state == NativeBridgeState::kPreInitialized
|| state == NativeBridgeState::kInitialized;
}
bool NativeBridgeInitialized() {
// Calls of this are supposed to happen in a state where the native bridge is stable, i.e., after
// Runtime::DidForkFromZygote. In that case we do not need a lock.
return state == NativeBridgeState::kInitialized;
}
void* NativeBridgeLoadLibrary(const char* libpath, int flag) {
if (NativeBridgeInitialized()) {
return callbacks->loadLibrary(libpath, flag);
}
return nullptr;
}
void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty,
uint32_t len) {
if (NativeBridgeInitialized()) {
return callbacks->getTrampoline(handle, name, shorty, len);
}
return nullptr;
}
bool NativeBridgeIsSupported(const char* libpath) {
if (NativeBridgeInitialized()) {
return callbacks->isSupported(libpath);
}
return false;
}
uint32_t NativeBridgeGetVersion() {
if (NativeBridgeAvailable()) {
return callbacks->version;
}
return 0;
}
NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
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;
}
const char* NativeBridgeGetError() {
if (NativeBridgeInitialized()) {
if (isCompatibleWith(NAMESPACE_VERSION)) {
return callbacks->getError();
} else {
return "native bridge implementation is not compatible with version 3, cannot get message";
}
}
return "native bridge is not initialized";
}
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 NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
const char* anon_ns_library_path) {
if (NativeBridgeInitialized()) {
if (isCompatibleWith(NAMESPACE_VERSION)) {
return callbacks->initAnonymousNamespace(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;
}
bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
const char* shared_libs_sonames) {
if (NativeBridgeInitialized()) {
if (isCompatibleWith(NAMESPACE_VERSION)) {
return callbacks->linkNamespaces(from, to, shared_libs_sonames);
} else {
ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
}
}
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)) {
return callbacks->loadLibraryExt(libpath, flag, ns);
} else {
ALOGE("not compatible with version %d, cannot load library in namespace", NAMESPACE_VERSION);
}
}
return nullptr;
}
}; // namespace android

View file

@ -0,0 +1,54 @@
//
// 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_defaults {
name: "libnativebridge-dummy-defaults",
host_supported: true,
cflags: [
"-Wall",
"-Wextra",
"-Werror",
],
header_libs: ["libnativebridge-dummy-headers"],
cppflags: ["-fvisibility=protected"],
target: {
android: {
shared_libs: ["libdl"],
},
host: {
host_ldlibs: ["-ldl"],
},
},
}
cc_library_shared {
name: "libnativebridge-dummy",
srcs: ["DummyNativeBridge.cpp"],
defaults: ["libnativebridge-dummy-defaults"],
}
cc_library_shared {
name: "libnativebridge2-dummy",
srcs: ["DummyNativeBridge2.cpp"],
defaults: ["libnativebridge-dummy-defaults"],
}
cc_library_shared {
name: "libnativebridge3-dummy",
srcs: ["DummyNativeBridge3.cpp"],
defaults: ["libnativebridge-dummy-defaults"],
}

View file

@ -0,0 +1,51 @@
# Build the unit tests.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build the unit tests.
test_src_files := \
CodeCacheCreate_test.cpp \
CodeCacheExists_test.cpp \
CodeCacheStatFail_test.cpp \
CompleteFlow_test.cpp \
InvalidCharsNativeBridge_test.cpp \
NativeBridge2Signal_test.cpp \
NativeBridgeVersion_test.cpp \
NeedsNativeBridge_test.cpp \
PreInitializeNativeBridge_test.cpp \
PreInitializeNativeBridgeFail1_test.cpp \
PreInitializeNativeBridgeFail2_test.cpp \
ReSetupNativeBridge_test.cpp \
UnavailableNativeBridge_test.cpp \
ValidNameNativeBridge_test.cpp \
NativeBridge3UnloadLibrary_test.cpp \
NativeBridge3GetError_test.cpp \
NativeBridge3IsPathSupported_test.cpp \
NativeBridge3InitAnonymousNamespace_test.cpp \
NativeBridge3CreateNamespace_test.cpp \
NativeBridge3LoadLibraryExt_test.cpp
shared_libraries := \
liblog \
libnativebridge \
libnativebridge-dummy
$(foreach file,$(test_src_files), \
$(eval include $(CLEAR_VARS)) \
$(eval LOCAL_CLANG := true) \
$(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
$(eval LOCAL_SRC_FILES := $(file)) \
$(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
$(eval include $(BUILD_NATIVE_TEST)) \
)
$(foreach file,$(test_src_files), \
$(eval include $(CLEAR_VARS)) \
$(eval LOCAL_CLANG := true) \
$(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
$(eval LOCAL_SRC_FILES := $(file)) \
$(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
$(eval include $(BUILD_HOST_NATIVE_TEST)) \
)

View file

@ -0,0 +1,51 @@
/*
* Copyright (C) 2014 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 "NativeBridgeTest.h"
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
namespace android {
// Tests that the bridge initialization creates the code_cache if it doesn't
// exists.
TEST_F(NativeBridgeTest, CodeCacheCreate) {
// Make sure that code_cache does not exists
struct stat st;
ASSERT_EQ(-1, stat(kCodeCache, &st));
ASSERT_EQ(ENOENT, errno);
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_FALSE(NativeBridgeError());
// Check that code_cache was created
ASSERT_EQ(0, stat(kCodeCache, &st));
ASSERT_TRUE(S_ISDIR(st.st_mode));
// Clean up
UnloadNativeBridge();
ASSERT_EQ(0, rmdir(kCodeCache));
ASSERT_FALSE(NativeBridgeError());
}
} // namespace android

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2014 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 "NativeBridgeTest.h"
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
namespace android {
// Tests that the bridge is initialized without errors if the code_cache already
// exists.
TEST_F(NativeBridgeTest, CodeCacheExists) {
// Make sure that code_cache does not exists
struct stat st;
ASSERT_EQ(-1, stat(kCodeCache, &st));
ASSERT_EQ(ENOENT, errno);
// Create the code_cache
ASSERT_EQ(0, mkdir(kCodeCache, S_IRWXU | S_IRWXG | S_IXOTH));
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_FALSE(NativeBridgeError());
// Check that the code cache is still there
ASSERT_EQ(0, stat(kCodeCache, &st));
ASSERT_TRUE(S_ISDIR(st.st_mode));
// Clean up
UnloadNativeBridge();
ASSERT_EQ(0, rmdir(kCodeCache));
ASSERT_FALSE(NativeBridgeError());
}
} // namespace android

View file

@ -0,0 +1,51 @@
/*
* Copyright (C) 2014 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 "NativeBridgeTest.h"
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
namespace android {
// Tests that the bridge is initialized without errors if the code_cache is
// existed as a file.
TEST_F(NativeBridgeTest, CodeCacheStatFail) {
int fd = creat(kCodeCache, O_RDWR);
ASSERT_NE(-1, fd);
close(fd);
struct stat st;
ASSERT_EQ(-1, stat(kCodeCacheStatFail, &st));
ASSERT_EQ(ENOTDIR, errno);
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
ASSERT_TRUE(PreInitializeNativeBridge(kCodeCacheStatFail, "isa"));
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_FALSE(NativeBridgeError());
// Clean up
UnloadNativeBridge();
ASSERT_FALSE(NativeBridgeError());
unlink(kCodeCache);
}
} // namespace android

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2014 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 "NativeBridgeTest.h"
#include <unistd.h>
namespace android {
TEST_F(NativeBridgeTest, CompleteFlow) {
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
// Basic calls to check that nothing crashes
ASSERT_FALSE(NativeBridgeIsSupported(nullptr));
ASSERT_EQ(nullptr, NativeBridgeLoadLibrary(nullptr, 0));
ASSERT_EQ(nullptr, NativeBridgeGetTrampoline(nullptr, nullptr, nullptr, 0));
// Unload
UnloadNativeBridge();
ASSERT_FALSE(NativeBridgeAvailable());
ASSERT_FALSE(NativeBridgeError());
// Clean-up code_cache
ASSERT_EQ(0, rmdir(kCodeCache));
}
} // namespace android

View file

@ -0,0 +1,53 @@
/*
* Copyright (C) 2014 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"
// NativeBridgeCallbacks implementations
extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
const char* /* app_code_cache_dir */,
const char* /* isa */) {
return true;
}
extern "C" void* native_bridge_loadLibrary(const char* /* libpath */, int /* flag */) {
return nullptr;
}
extern "C" void* native_bridge_getTrampoline(void* /* handle */, const char* /* name */,
const char* /* shorty */, uint32_t /* len */) {
return nullptr;
}
extern "C" bool native_bridge_isSupported(const char* /* libpath */) {
return false;
}
extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv(
const char* /* abi */) {
return nullptr;
}
android::NativeBridgeCallbacks NativeBridgeItf {
.version = 1,
.initialize = &native_bridge_initialize,
.loadLibrary = &native_bridge_loadLibrary,
.getTrampoline = &native_bridge_getTrampoline,
.isSupported = &native_bridge_isSupported,
.getAppEnv = &native_bridge_getAppEnv
};

View file

@ -0,0 +1,76 @@
/*
* Copyright (C) 2014 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_bridge2_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
const char* /* app_code_cache_dir */,
const char* /* isa */) {
return true;
}
extern "C" void* native_bridge2_loadLibrary(const char* /* libpath */, int /* flag */) {
return nullptr;
}
extern "C" void* native_bridge2_getTrampoline(void* /* handle */, const char* /* name */,
const char* /* shorty */, uint32_t /* len */) {
return nullptr;
}
extern "C" bool native_bridge2_isSupported(const char* /* libpath */) {
return false;
}
extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge2_getAppEnv(
const char* /* abi */) {
return nullptr;
}
extern "C" bool native_bridge2_is_compatible_compatible_with(uint32_t version) {
// For testing, allow 1 and 2, but disallow 3+.
return version <= 2;
}
static bool native_bridge2_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_bridge2_get_signal_handler(int signal) {
if (signal == SIGSEGV) {
return &native_bridge2_dummy_signal_handler;
}
return nullptr;
}
android::NativeBridgeCallbacks NativeBridgeItf {
.version = 2,
.initialize = &native_bridge2_initialize,
.loadLibrary = &native_bridge2_loadLibrary,
.getTrampoline = &native_bridge2_getTrampoline,
.isSupported = &native_bridge2_isSupported,
.getAppEnv = &native_bridge2_getAppEnv,
.isCompatibleWith = &native_bridge2_is_compatible_compatible_with,
.getSignalHandler = &native_bridge2_get_signal_handler
};

View file

@ -0,0 +1,124 @@
/*
* 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" const char* native_bridge3_getError() {
return nullptr;
}
extern "C" bool native_bridge3_isPathSupported(const char* /* path */) {
return true;
}
extern "C" bool native_bridge3_initAnonymousNamespace(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" bool native_bridge3_linkNamespaces(android::native_bridge_namespace_t* /* from */,
android::native_bridge_namespace_t* /* to */,
const char* /* shared_libs_soname */) {
return true;
}
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,
.initAnonymousNamespace = &native_bridge3_initAnonymousNamespace,
.createNamespace = &native_bridge3_createNamespace,
.linkNamespaces = &native_bridge3_linkNamespaces,
.loadLibraryExt = &native_bridge3_loadLibraryExt};

View file

@ -0,0 +1,40 @@
/*
* Copyright (C) 2014 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 "NativeBridgeTest.h"
namespace android {
static const char* kTestName = "../librandom$@-bridge_not.existing.so";
TEST_F(NativeBridgeTest, InvalidChars) {
// Do one test actually calling setup.
EXPECT_EQ(false, NativeBridgeError());
LoadNativeBridge(kTestName, nullptr);
// This should lead to an error for invalid characters.
EXPECT_EQ(true, NativeBridgeError());
// Further tests need to use NativeBridgeNameAcceptable, as the error
// state can't be changed back.
EXPECT_EQ(false, NativeBridgeNameAcceptable("."));
EXPECT_EQ(false, NativeBridgeNameAcceptable(".."));
EXPECT_EQ(false, NativeBridgeNameAcceptable("_"));
EXPECT_EQ(false, NativeBridgeNameAcceptable("-"));
EXPECT_EQ(false, NativeBridgeNameAcceptable("lib@.so"));
EXPECT_EQ(false, NativeBridgeNameAcceptable("lib$.so"));
}
} // namespace android

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) 2014 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 "NativeBridgeTest.h"
#include <signal.h>
#include <unistd.h>
namespace android {
constexpr const char* kNativeBridgeLibrary2 = "libnativebridge2-dummy.so";
TEST_F(NativeBridgeTest, V2_Signal) {
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary2, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_EQ(2U, NativeBridgeGetVersion());
ASSERT_NE(nullptr, NativeBridgeGetSignalHandler(SIGSEGV));
// Clean-up code_cache
ASSERT_EQ(0, rmdir(kCodeCache));
}
} // namespace android

View file

@ -0,0 +1,40 @@
/*
* 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.
*/
#include "NativeBridgeTest.h"
namespace android {
constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
TEST_F(NativeBridgeTest, V3_CreateNamespace) {
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_EQ(3U, NativeBridgeGetVersion());
ASSERT_EQ(nullptr, NativeBridgeCreateNamespace(nullptr, nullptr, nullptr,
0, nullptr, nullptr));
// Clean-up code_cache
ASSERT_EQ(0, rmdir(kCodeCache));
}
} // namespace android

View file

@ -0,0 +1,39 @@
/*
* 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.
*/
#include "NativeBridgeTest.h"
namespace android {
constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
TEST_F(NativeBridgeTest, V3_GetError) {
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_EQ(3U, NativeBridgeGetVersion());
ASSERT_EQ(nullptr, NativeBridgeGetError());
// Clean-up code_cache
ASSERT_EQ(0, rmdir(kCodeCache));
}
} // namespace android

View file

@ -0,0 +1,39 @@
/*
* 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.
*/
#include "NativeBridgeTest.h"
namespace android {
constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
TEST_F(NativeBridgeTest, V3_InitAnonymousNamespace) {
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_EQ(3U, NativeBridgeGetVersion());
ASSERT_EQ(true, NativeBridgeInitAnonymousNamespace(nullptr, nullptr));
// Clean-up code_cache
ASSERT_EQ(0, rmdir(kCodeCache));
}
} // namespace android

View file

@ -0,0 +1,39 @@
/*
* 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.
*/
#include "NativeBridgeTest.h"
namespace android {
constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
TEST_F(NativeBridgeTest, V3_IsPathSupported) {
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_EQ(3U, NativeBridgeGetVersion());
ASSERT_EQ(true, NativeBridgeIsPathSupported(nullptr));
// Clean-up code_cache
ASSERT_EQ(0, rmdir(kCodeCache));
}
} // namespace android

View file

@ -0,0 +1,39 @@
/*
* 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.
*/
#include "NativeBridgeTest.h"
namespace android {
constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
TEST_F(NativeBridgeTest, V3_LoadLibraryExt) {
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_EQ(3U, NativeBridgeGetVersion());
ASSERT_EQ(nullptr, NativeBridgeLoadLibraryExt(nullptr, 0, nullptr));
// Clean-up code_cache
ASSERT_EQ(0, rmdir(kCodeCache));
}
} // namespace android

View file

@ -0,0 +1,39 @@
/*
* 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.
*/
#include "NativeBridgeTest.h"
namespace android {
constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
TEST_F(NativeBridgeTest, V3_UnloadLibrary) {
// Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_EQ(3U, NativeBridgeGetVersion());
ASSERT_EQ(0, NativeBridgeUnloadLibrary(nullptr));
// Clean-up code_cache
ASSERT_EQ(0, rmdir(kCodeCache));
}
} // namespace android

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2014 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_BRIDGE_TEST_H_
#define NATIVE_BRIDGE_TEST_H_
#define LOG_TAG "NativeBridge_test"
#include <nativebridge/native_bridge.h>
#include <gtest/gtest.h>
constexpr const char* kNativeBridgeLibrary = "libnativebridge-dummy.so";
constexpr const char* kCodeCache = "./code_cache";
constexpr const char* kCodeCacheStatFail = "./code_cache/temp";
constexpr const char* kNativeBridgeLibrary2 = "libnativebridge2-dummy.so";
constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
namespace android {
class NativeBridgeTest : public testing::Test {
};
}; // namespace android
#endif // NATIVE_BRIDGE_H_

View file

@ -0,0 +1,38 @@
/*
* 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 "NativeBridgeTest.h"
#include <unistd.h>
namespace android {
TEST_F(NativeBridgeTest, Version) {
// When a bridge isn't loaded, we expect 0.
EXPECT_EQ(NativeBridgeGetVersion(), 0U);
// After our dummy bridge has been loaded, we expect 1.
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
EXPECT_EQ(NativeBridgeGetVersion(), 1U);
// Unload
UnloadNativeBridge();
// Version information is gone.
EXPECT_EQ(NativeBridgeGetVersion(), 0U);
}
} // namespace android

View file

@ -0,0 +1,50 @@
/*
* Copyright (C) 2014 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 "NativeBridgeTest.h"
namespace android {
static const char* kISAs[] = { "arm", "arm64", "mips", "mips64", "x86", "x86_64", "random", "64arm",
"64_x86", "64_x86_64", "", "reallylongstringabcd", nullptr };
#if defined(__arm__)
static const char* kRuntimeISA = "arm";
#elif defined(__aarch64__)
static const char* kRuntimeISA = "arm64";
#elif defined(__mips__) && !defined(__LP64__)
static const char* kRuntimeISA = "mips";
#elif defined(__mips__) && defined(__LP64__)
static const char* kRuntimeISA = "mips64";
#elif defined(__i386__)
static const char* kRuntimeISA = "x86";
#elif defined(__x86_64__)
static const char* kRuntimeISA = "x86_64";
#else
static const char* kRuntimeISA = "unknown";
#endif
TEST_F(NativeBridgeTest, NeedsNativeBridge) {
EXPECT_EQ(false, NeedsNativeBridge(kRuntimeISA));
const size_t kISACount = sizeof(kISAs)/sizeof(kISAs[0]);
for (size_t i = 0; i < kISACount; i++) {
EXPECT_EQ(kISAs[i] == nullptr ? false : strcmp(kISAs[i], kRuntimeISA) != 0,
NeedsNativeBridge(kISAs[i]));
}
}
} // namespace android

View file

@ -0,0 +1,40 @@
/*
* Copyright (C) 2014 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 "NativeBridgeTest.h"
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <cstdio>
#include <cstring>
#include <android/log.h>
namespace android {
TEST_F(NativeBridgeTest, PreInitializeNativeBridgeFail1) {
// Needs a valid application directory.
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
ASSERT_FALSE(PreInitializeNativeBridge(nullptr, "isa"));
ASSERT_TRUE(NativeBridgeError());
}
} // namespace android

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2014 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 <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <cstdio>
#include <cstring>
#include <android/log.h>
#include "NativeBridgeTest.h"
namespace android {
TEST_F(NativeBridgeTest, PreInitializeNativeBridgeFail2) {
// Needs LoadNativeBridge() first
ASSERT_FALSE(PreInitializeNativeBridge(nullptr, "isa"));
ASSERT_TRUE(NativeBridgeError());
}
} // namespace android

View file

@ -0,0 +1,68 @@
/*
* Copyright (C) 2014 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 <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <cstdio>
#include <cstring>
#include <android/log.h>
#include "NativeBridgeTest.h"
namespace android {
static constexpr const char* kTestData = "PreInitializeNativeBridge test.";
TEST_F(NativeBridgeTest, PreInitializeNativeBridge) {
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
#if !defined(__APPLE__) // Mac OS does not support bind-mount.
#if !defined(__ANDROID__) // Cannot write into the hard-wired location.
// Try to create our mount namespace.
if (unshare(CLONE_NEWNS) != -1) {
// Create a dummy file.
FILE* cpuinfo = fopen("./cpuinfo", "w");
ASSERT_NE(nullptr, cpuinfo) << strerror(errno);
fprintf(cpuinfo, kTestData);
fclose(cpuinfo);
ASSERT_TRUE(PreInitializeNativeBridge("does not matter 1", "short 2"));
// Read /proc/cpuinfo
FILE* proc_cpuinfo = fopen("/proc/cpuinfo", "r");
ASSERT_NE(nullptr, proc_cpuinfo) << strerror(errno);
char buf[1024];
EXPECT_NE(nullptr, fgets(buf, sizeof(buf), proc_cpuinfo)) << "Error reading.";
fclose(proc_cpuinfo);
EXPECT_EQ(0, strcmp(buf, kTestData));
// Delete the file.
ASSERT_EQ(0, unlink("./cpuinfo")) << "Error unlinking temporary file.";
// Ending the test will tear down the mount namespace.
} else {
GTEST_LOG_(WARNING) << "Could not create mount namespace. Are you running this as root?";
}
#endif
#endif
}
} // namespace android

View file

@ -0,0 +1,30 @@
/*
* Copyright (C) 2014 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 "NativeBridgeTest.h"
namespace android {
TEST_F(NativeBridgeTest, ReSetup) {
EXPECT_EQ(false, NativeBridgeError());
LoadNativeBridge("", nullptr);
EXPECT_EQ(false, NativeBridgeError());
LoadNativeBridge("", nullptr);
// This should lead to an error for trying to re-setup a native bridge.
EXPECT_EQ(true, NativeBridgeError());
}
} // namespace android

View file

@ -0,0 +1,29 @@
/*
* Copyright (C) 2011 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 "NativeBridgeTest.h"
namespace android {
TEST_F(NativeBridgeTest, NoNativeBridge) {
EXPECT_EQ(false, NativeBridgeAvailable());
// Try to initialize. This should fail as we are not set up.
EXPECT_EQ(false, InitializeNativeBridge(nullptr, nullptr));
EXPECT_EQ(true, NativeBridgeError());
EXPECT_EQ(false, NativeBridgeAvailable());
}
} // namespace android

View file

@ -0,0 +1,35 @@
/*
* Copyright (C) 2011 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 <NativeBridgeTest.h>
namespace android {
static const char* kTestName = "librandom-bridge_not.existing.so";
TEST_F(NativeBridgeTest, ValidName) {
// Check that the name is acceptable.
EXPECT_EQ(true, NativeBridgeNameAcceptable(kTestName));
// Now check what happens on LoadNativeBridge.
EXPECT_EQ(false, NativeBridgeError());
LoadNativeBridge(kTestName, nullptr);
// This will lead to an error as the library doesn't exist.
EXPECT_EQ(true, NativeBridgeError());
EXPECT_EQ(false, NativeBridgeAvailable());
}
} // namespace android