ART: Native bridge command-line parameter
Add a command-line parameter for the native bridge library, slight
refactor/cleanup.
Add run-test 115 to test the native bridge interface. Currently the
tests are black-listed for the target, as the setup for the test
is too complicated in the current infrastructure.
Change-Id: I6ccf19485e8c30b96e9f2fd5425278cb1ebd403f
diff --git a/runtime/native_bridge.cc b/runtime/native_bridge.cc
index de04a99..ad26ee4 100644
--- a/runtime/native_bridge.cc
+++ b/runtime/native_bridge.cc
@@ -35,7 +35,7 @@
namespace art {
// Is native-bridge support enabled?
-static constexpr bool kNativeBridgeEnabled = false;
+static constexpr bool kNativeBridgeEnabled = true;
// Default library name for native-bridge.
static constexpr const char* kDefaultNativeBridge = "libnativebridge.so";
@@ -55,9 +55,6 @@
// ART interfaces to native-bridge.
struct NativeBridgeArtCallbacks {
- // Log utility, reserve unused.
- int (*logger)(int prio, const char* tag, const char* fmt, ...);
-
// Get shorty of a Java method. The shorty is supposed to be persistent in memory.
//
// Parameters:
@@ -190,71 +187,96 @@
}
NativeBridgeArtCallbacks NativeBridgeArtItf = {
- nullptr,
GetMethodShorty,
GetNativeMethodCount,
GetNativeMethods
};
-bool NativeBridge::Init() {
+void NativeBridge::SetNativeBridgeLibraryString(std::string& native_bridge_library_string) {
+ native_bridge_library_string_ = native_bridge_library_string;
+ // TODO: when given an empty string, set initialized_ to true and available_ to false. This
+ // change is dependent on the property removal in Initialize().
+}
+
+bool NativeBridge::Initialize() {
if (!kNativeBridgeEnabled) {
return false;
}
MutexLock mu(Thread::Current(), lock_);
- if (!initialized_) {
- const char* libnb_path = kDefaultNativeBridge;
+ if (initialized_) {
+ // Somebody did it before.
+ return available_;
+ }
+
+ available_ = false;
+
+ const char* libnb_path;
+
+ if (!native_bridge_library_string_.empty()) {
+ libnb_path = native_bridge_library_string_.c_str();
+ } else {
+ // TODO: Remove this once the frameworks side is completely implemented.
+
+ libnb_path = kDefaultNativeBridge;
#ifdef HAVE_ANDROID_OS
char prop_buf[PROP_VALUE_MAX];
property_get(kPropEnableNativeBridge, prop_buf, "false");
- if (strcmp(prop_buf, "true") != 0)
+ if (strcmp(prop_buf, "true") != 0) {
+ initialized_ = true;
return false;
+ }
// If prop persist.native.bridge set, overwrite the default name.
int name_len = property_get(kPropNativeBridge, prop_buf, kDefaultNativeBridge);
if (name_len > 0)
libnb_path = prop_buf;
#endif
- void* handle = dlopen(libnb_path, RTLD_LAZY);
- if (handle == nullptr)
- return false;
-
- callbacks_ = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle,
- kNativeBridgeInterfaceSymbol));
- if (callbacks_ == nullptr) {
- dlclose(handle);
- return false;
- }
-
- callbacks_->initialize(&NativeBridgeArtItf);
- initialized_ = true;
}
- return initialized_;
+ void* handle = dlopen(libnb_path, RTLD_LAZY);
+ if (handle != nullptr) {
+ callbacks_ = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle,
+ kNativeBridgeInterfaceSymbol));
+
+ if (callbacks_ != nullptr) {
+ available_ = callbacks_->initialize(&NativeBridgeArtItf);
+ }
+
+ if (!available_) {
+ dlclose(handle);
+ }
+ }
+
+ initialized_ = true;
+
+ return available_;
}
void* NativeBridge::LoadLibrary(const char* libpath, int flag) {
- if (Init())
+ if (Initialize())
return callbacks_->loadLibrary(libpath, flag);
return nullptr;
}
void* NativeBridge::GetTrampoline(void* handle, const char* name, const char* shorty,
uint32_t len) {
- if (Init())
+ if (Initialize())
return callbacks_->getTrampoline(handle, name, shorty, len);
return nullptr;
}
bool NativeBridge::IsSupported(const char* libpath) {
- if (Init())
+ if (Initialize())
return callbacks_->isSupported(libpath);
return false;
}
+bool NativeBridge::available_ = false;
bool NativeBridge::initialized_ = false;
Mutex NativeBridge::lock_("native bridge lock");
+std::string NativeBridge::native_bridge_library_string_ = "";
NativeBridgeCallbacks* NativeBridge::callbacks_ = nullptr;
}; // namespace art
diff --git a/runtime/native_bridge.h b/runtime/native_bridge.h
index dd895d2..3d20fe4 100644
--- a/runtime/native_bridge.h
+++ b/runtime/native_bridge.h
@@ -19,23 +19,38 @@
#include "base/mutex.h"
+#include <string>
+
namespace art {
struct NativeBridgeCallbacks;
class NativeBridge {
public:
+ // Initialize the native bridge, if any. Should be called by Runtime::Init(). An empty string
+ // signals that we do not want to load a native bridge.
+ static void SetNativeBridgeLibraryString(std::string& native_bridge_library_string);
+
// Load a shared library that is supported by the native-bridge.
static void* LoadLibrary(const char* libpath, int flag);
// Get a native-bridge trampoline for specified native method.
static void* GetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len);
// True if native library is valid and is for an ABI that is supported by native-bridge.
- static bool IsSupported(const char* libpath);
+ static bool IsSupported(const char* libpath);
private:
- static bool Init();
- static bool initialized_ GUARDED_BY(lock_);
+ static bool Initialize();
+
+ // The library name we are supposed to load.
+ static std::string native_bridge_library_string_;
+
+ // Whether we have already initialized (or tried to).
+ static bool initialized_ GUARDED_BY(lock_);
static Mutex lock_;
+
+ // Whether a native bridge is available (loaded and ready).
+ static bool available_;
+
static NativeBridgeCallbacks* callbacks_;
};
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 8d0aff8..49f6585 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -596,6 +596,10 @@
Usage("Unknown -Xverify option %s\n", verify_mode.c_str());
return false;
}
+ } else if (StartsWith(option, "-XX:NativeBridge=")) {
+ if (!ParseStringAfterChar(option, '=', &native_bridge_library_string_)) {
+ return false;
+ }
} else if (StartsWith(option, "-ea") ||
StartsWith(option, "-da") ||
StartsWith(option, "-enableassertions") ||
diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h
index 29d5494..668ed9e 100644
--- a/runtime/parsed_options.h
+++ b/runtime/parsed_options.h
@@ -45,6 +45,7 @@
std::string image_;
bool check_jni_;
std::string jni_trace_;
+ std::string native_bridge_library_string_;
CompilerCallbacks* compiler_callbacks_;
bool is_zygote_;
// TODO Change this to true when we want it on by default.
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index b7eae85..1cbf841 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -63,6 +63,7 @@
#include "mirror/stack_trace_element.h"
#include "mirror/throwable.h"
#include "monitor.h"
+#include "native_bridge.h"
#include "parsed_options.h"
#include "oat_file.h"
#include "quick/quick_method_frame_info.h"
@@ -718,6 +719,9 @@
pre_allocated_OutOfMemoryError_ = self->GetException(NULL);
self->ClearException();
+ // Look for a native bridge.
+ NativeBridge::SetNativeBridgeLibraryString(options->native_bridge_library_string_);
+
VLOG(startup) << "Runtime::Init exiting";
return true;
}