summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/native/dalvik_system_ZygoteHooks.cc6
-rw-r--r--runtime/native_bridge_art_interface.cc39
-rw-r--r--runtime/native_bridge_art_interface.h14
-rw-r--r--runtime/runtime.cc25
-rw-r--r--runtime/runtime.h14
-rw-r--r--test/115-native-bridge/expected.txt1
-rw-r--r--test/115-native-bridge/nativebridge.cc43
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
};