diff options
-rw-r--r-- | runtime/native/dalvik_system_ZygoteHooks.cc | 6 | ||||
-rw-r--r-- | runtime/native_bridge_art_interface.cc | 39 | ||||
-rw-r--r-- | runtime/native_bridge_art_interface.h | 14 | ||||
-rw-r--r-- | runtime/runtime.cc | 25 | ||||
-rw-r--r-- | runtime/runtime.h | 14 | ||||
-rw-r--r-- | test/115-native-bridge/expected.txt | 1 | ||||
-rw-r--r-- | test/115-native-bridge/nativebridge.cc | 43 |
7 files changed, 109 insertions, 33 deletions
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index c3c8c2576e..e469126206 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -111,15 +111,17 @@ static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, ji thread->InitAfterFork(); EnableDebugFeatures(debug_flags); - Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload; if (instruction_set != nullptr) { ScopedUtfChars isa_string(env, instruction_set); InstructionSet isa = GetInstructionSetFromString(isa_string.c_str()); + Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload; if (isa != kNone && isa != kRuntimeISA) { action = Runtime::NativeBridgeAction::kInitialize; } + Runtime::Current()->DidForkFromZygote(env, action, isa_string.c_str()); + } else { + Runtime::Current()->DidForkFromZygote(env, Runtime::NativeBridgeAction::kUnload, nullptr); } - Runtime::Current()->DidForkFromZygote(action); } static JNINativeMethod gMethods[] = { diff --git a/runtime/native_bridge_art_interface.cc b/runtime/native_bridge_art_interface.cc index 453c92f495..fcd11ed442 100644 --- a/runtime/native_bridge_art_interface.cc +++ b/runtime/native_bridge_art_interface.cc @@ -16,6 +16,9 @@ #include "native_bridge_art_interface.h" +#include "nativebridge/native_bridge.h" + +#include "base/logging.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "scoped_thread_state_change.h" @@ -91,4 +94,40 @@ uint32_t GetNativeMethods(JNIEnv* env, jclass clazz, JNINativeMethod* methods, return count; } +// Native bridge library runtime callbacks. They represent the runtime interface to native bridge. +// +// The interface is expected to expose the following methods: +// getMethodShorty(): in the case of native method calling JNI native function CallXXXXMethodY(), +// native bridge calls back to VM for the shorty of the method so that it can prepare based on +// host calling convention. +// getNativeMethodCount() and getNativeMethods(): in case of JNI function UnregisterNatives(), +// native bridge can call back to get all native methods of specified class so that all +// corresponding trampolines can be destroyed. +static android::NativeBridgeRuntimeCallbacks native_bridge_art_callbacks_ { + GetMethodShorty, GetNativeMethodCount, GetNativeMethods +}; + +void LoadNativeBridge(std::string& native_bridge_library_filename) { + android::LoadNativeBridge(native_bridge_library_filename.c_str(), &native_bridge_art_callbacks_); + VLOG(startup) << "Runtime::Setup native bridge library: " + << (native_bridge_library_filename.empty() ? "(empty)" : native_bridge_library_filename); +} + +void PreInitializeNativeBridge(std::string dir) { + VLOG(startup) << "Runtime::Pre-initialize native bridge"; + if (unshare(CLONE_NEWNS) == -1) { + LOG(WARNING) << "Could not create mount namespace."; + return; + } + android::PreInitializeNativeBridge(dir.c_str(), GetInstructionSetString(kRuntimeISA)); +} + +void InitializeNativeBridge(JNIEnv* env, const char* instruction_set) { + android::InitializeNativeBridge(env, instruction_set); +} + +void UnloadNativeBridge() { + android::UnloadNativeBridge(); +} + }; // namespace art diff --git a/runtime/native_bridge_art_interface.h b/runtime/native_bridge_art_interface.h index 08735c8955..42f0ed25e6 100644 --- a/runtime/native_bridge_art_interface.h +++ b/runtime/native_bridge_art_interface.h @@ -19,15 +19,21 @@ #include <jni.h> #include <stdint.h> +#include <string> namespace art { -const char* GetMethodShorty(JNIEnv* env, jmethodID mid); +// Mirror libnativebridge interface. Done to have the ART callbacks out of line, and not require +// the system/core header file in other files. -uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz); +void LoadNativeBridge(std::string& native_bridge_library_filename); -uint32_t GetNativeMethods(JNIEnv* env, jclass clazz, JNINativeMethod* methods, - uint32_t method_count); +// This is mostly for testing purposes, as in a full system this is called by Zygote code. +void PreInitializeNativeBridge(std::string dir); + +void InitializeNativeBridge(JNIEnv* env, const char* instruction_set); + +void UnloadNativeBridge(); }; // namespace art diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 9b24bec574..0edf116c00 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -143,8 +143,7 @@ Runtime::Runtime() target_sdk_version_(0), implicit_null_checks_(false), implicit_so_checks_(false), - implicit_suspend_checks_(false), - native_bridge_art_callbacks_({GetMethodShorty, GetNativeMethodCount, GetNativeMethods}) { + implicit_suspend_checks_(false) { } Runtime::~Runtime() { @@ -418,18 +417,23 @@ bool Runtime::Start() { Thread::FinishStartup(); + system_class_loader_ = CreateSystemClassLoader(); + if (is_zygote_) { if (!InitZygote()) { return false; } } else { - DidForkFromZygote(NativeBridgeAction::kInitialize); + bool have_native_bridge = !native_bridge_library_filename_.empty(); + if (have_native_bridge) { + PreInitializeNativeBridge("."); + } + DidForkFromZygote(self->GetJniEnv(), have_native_bridge ? NativeBridgeAction::kInitialize : + NativeBridgeAction::kUnload, GetInstructionSetString(kRuntimeISA)); } StartDaemonThreads(); - system_class_loader_ = CreateSystemClassLoader(); - { ScopedObjectAccess soa(self); self->GetJniEnv()->locals.AssertEmpty(); @@ -501,16 +505,16 @@ bool Runtime::InitZygote() { #endif } -void Runtime::DidForkFromZygote(NativeBridgeAction action) { +void Runtime::DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const char* isa) { is_zygote_ = false; switch (action) { case NativeBridgeAction::kUnload: - android::UnloadNativeBridge(); + UnloadNativeBridge(); break; case NativeBridgeAction::kInitialize: - android::InitializeNativeBridge(); + InitializeNativeBridge(env, isa); break; } @@ -870,10 +874,7 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) // DidForkFromZygote(kInitialize) -> try to initialize any native bridge given. // No-op wrt native bridge. native_bridge_library_filename_ = options->native_bridge_library_filename_; - android::LoadNativeBridge(native_bridge_library_filename_.c_str(), &native_bridge_art_callbacks_); - VLOG(startup) << "Runtime::Setup native bridge library: " - << (native_bridge_library_filename_.empty() ? - "(empty)" : native_bridge_library_filename_); + LoadNativeBridge(native_bridge_library_filename_); VLOG(startup) << "Runtime::Init exiting"; return true; diff --git a/runtime/runtime.h b/runtime/runtime.h index cfb1abc477..9a8235dfc6 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -32,7 +32,6 @@ #include "instrumentation.h" #include "instruction_set.h" #include "jobject_comparator.h" -#include "nativebridge/native_bridge.h" #include "object_callbacks.h" #include "offsets.h" #include "profiler_options.h" @@ -398,7 +397,7 @@ class Runtime { }; void PreZygoteFork(); bool InitZygote(); - void DidForkFromZygote(NativeBridgeAction action); + void DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const char* isa); const instrumentation::Instrumentation* GetInstrumentation() const { return &instrumentation_; @@ -648,17 +647,6 @@ class Runtime { // the native bridge to load it and then gets the trampoline for the entry to native activity. std::string native_bridge_library_filename_; - // Native bridge library runtime callbacks. They represent the runtime interface to native bridge. - // - // The interface is expected to expose the following methods: - // getMethodShorty(): in the case of native method calling JNI native function CallXXXXMethodY(), - // native bridge calls back to VM for the shorty of the method so that it can prepare based on - // host calling convention. - // getNativeMethodCount() and getNativeMethods(): in case of JNI function UnregisterNatives(), - // native bridge can call back to get all native methods of specified class so that all - // corresponding trampolines can be destroyed. - android::NativeBridgeRuntimeCallbacks native_bridge_art_callbacks_; - DISALLOW_COPY_AND_ASSIGN(Runtime); }; diff --git a/test/115-native-bridge/expected.txt b/test/115-native-bridge/expected.txt index 808d968f67..a5eedc6a27 100644 --- a/test/115-native-bridge/expected.txt +++ b/test/115-native-bridge/expected.txt @@ -1,4 +1,5 @@ Native bridge initialized. +Checking for getEnvValues. Ready for native bridge tests. Checking for support. Getting trampoline for JNI_OnLoad with shorty (null). diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc index 3acc643d99..442f99c486 100644 --- a/test/115-native-bridge/nativebridge.cc +++ b/test/115-native-bridge/nativebridge.cc @@ -207,7 +207,8 @@ static NativeBridgeMethod* find_native_bridge_method(const char *name) { } // NativeBridgeCallbacks implementations -extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* art_cbs) { +extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* art_cbs, + const char* private_dir, const char* isa) { if (art_cbs != nullptr) { gNativeBridgeArtCallbacks = art_cbs; printf("Native bridge initialized.\n"); @@ -263,11 +264,49 @@ extern "C" bool native_bridge_isSupported(const char* libpath) { return strcmp(libpath, "libjavacore.so") != 0; } +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; +}; + +} // namespace android + +const char* supported_abis[] = { + "supported1", "supported2", "supported3" +}; + +const struct android::NativeBridgeRuntimeValues nb_env { + .os_arch = "os.arch", + .cpu_abi = "cpu_abi", + .cpu_abi2 = "cpu_abi2", + .supported_abis = supported_abis, + .abi_count = 3 +}; + +extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv( + const char* abi) { + printf("Checking for getEnvValues.\n"); + + if (abi == nullptr) { + return nullptr; + } + + return &nb_env; +} + // "NativeBridgeItf" is effectively an API (it is the name of the symbol that will be loaded // by the native bridge library). android::NativeBridgeCallbacks NativeBridgeItf { + .version = 1, .initialize = &native_bridge_initialize, .loadLibrary = &native_bridge_loadLibrary, .getTrampoline = &native_bridge_getTrampoline, - .isSupported = &native_bridge_isSupported + .isSupported = &native_bridge_isSupported, + .getAppEnv = &native_bridge_getAppEnv }; |