Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1761)

Unified Diff: base/android/linker/linker_jni.cc

Issue 228023005: Additions to support crazy linker callbacks from the UI thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/android/java/src/org/chromium/base/library_loader/Linker.java ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/android/linker/linker_jni.cc
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc
index 0222e49b344b695f4049aa375ebaffa0f225a416..b208a56255e0136611c84dd2304f55b96ddcf03a 100644
--- a/base/android/linker/linker_jni.cc
+++ b/base/android/linker/linker_jni.cc
@@ -71,31 +71,6 @@ String::String(JNIEnv* env, jstring str) {
env->ReleaseStringUTFChars(str, bytes);
}
-// A scoped crazy_library_t that automatically closes the handle
-// on scope exit, unless Release() has been called.
-class ScopedLibrary {
- public:
- ScopedLibrary() : lib_(NULL) {}
-
- ~ScopedLibrary() {
- if (lib_)
- crazy_library_close(lib_);
- }
-
- crazy_library_t* Get() { return lib_; }
-
- crazy_library_t** GetPtr() { return &lib_; }
-
- crazy_library_t* Release() {
- crazy_library_t* ret = lib_;
- lib_ = NULL;
- return ret;
- }
-
- private:
- crazy_library_t* lib_;
-};
-
// Return a pointer to the base name from an input |path| string.
const char* GetBaseNamePtr(const char* path) {
const char* p = strrchr(path, '/');
@@ -140,6 +115,25 @@ bool InitFieldId(JNIEnv* env,
return true;
}
+// Initialize a jmethodID corresponding to the static method of a given
+// |clazz|, with name |method_name| and signature |method_sig|.
+// |env| is the current JNI environment handle.
+// On success, return true and set |*method_id|.
+bool InitStaticMethodId(JNIEnv* env,
+ jclass clazz,
+ const char* method_name,
+ const char* method_sig,
+ jmethodID* method_id) {
+ *method_id = env->GetStaticMethodID(clazz, method_name, method_sig);
+ if (!*method_id) {
+ LOG_ERROR("Could not find ID for static method '%s'", method_name);
+ return false;
+ }
+ LOG_INFO("%s: Found ID %p for static method '%s'",
+ __FUNCTION__, *method_id, method_name);
+ return true;
+}
+
// A class used to model the field IDs of the org.chromium.base.Linker
// LibInfo inner class, used to communicate data with the Java side
// of the linker.
@@ -221,6 +215,31 @@ crazy_context_t* GetCrazyContext() {
return s_crazy_context;
}
+// A scoped crazy_library_t that automatically closes the handle
+// on scope exit, unless Release() has been called.
+class ScopedLibrary {
+ public:
+ ScopedLibrary() : lib_(NULL) {}
+
+ ~ScopedLibrary() {
+ if (lib_)
+ crazy_library_close_with_context(lib_, GetCrazyContext());
+ }
+
+ crazy_library_t* Get() { return lib_; }
+
+ crazy_library_t** GetPtr() { return &lib_; }
+
+ crazy_library_t* Release() {
+ crazy_library_t* ret = lib_;
+ lib_ = NULL;
+ return ret;
+ }
+
+ private:
+ crazy_library_t* lib_;
+};
+
// Load a library with the chromium linker. This will also call its
// JNI_OnLoad() method, which shall register its methods. Note that
// lazy native method resolution will _not_ work after this, because
@@ -282,6 +301,89 @@ jboolean LoadLibrary(JNIEnv* env,
return true;
}
+// Class holding the Java class and method ID for the Java side Linker
+// postCallbackOnMainThread method.
+struct CallbackRefs_class {
bulach 2014/05/07 16:10:53 nit: the name should be CallbackRefsClass. however
simonb1 2014/05/07 17:25:24 Done.
+ jclass clazz;
+ jmethodID method_id;
+
+ // Initialize an instance.
+ bool Init(JNIEnv* env, jclass linker_class) {
+ clazz = linker_class;
bulach 2014/05/07 16:10:53 nit: theoretically linker_class is a "localref" th
simonb1 2014/05/07 17:25:24 Done.
+ return InitStaticMethodId(env,
+ linker_class,
+ "postCallbackOnMainThread",
+ "(J)V",
+ &method_id);
+ }
+};
+
+static CallbackRefs_class s_callback_refs;
+
+// Designated receiver function for callbacks from Java. Its name is known
+// to the Java side.
+// |env| is the current JNI environment handle and is ignored here.
+// |clazz| is the static class handle for org.chromium.base.Linker,
+// and is ignored here.
+// |arg| is a pointer to an allocated crazy_callback_t, deleted after use.
+void RunCallbackOnUiThread(JNIEnv* env, jclass clazz, jlong arg) {
+ crazy_callback_t* callback = reinterpret_cast<crazy_callback_t*>(arg);
+
+ LOG_INFO("%s: Called back from java with handler %p, opaque %p",
+ __FUNCTION__, callback->handler, callback->opaque);
+
+ crazy_callback_run(callback);
+ delete callback;
+}
+
+// Request a callback from Java. The supplied crazy_callback_t is valid only
+// for the duration of this call, so we copy it to a newly allocated
+// crazy_callback_t and then call the Java side's postCallbackOnMainThread.
+// This will call back to to our RunCallbackOnUiThread some time
+// later on the UI thread.
+// |callback_request| is a crazy_callback_t.
+// |poster_opaque| is unused.
+// Returns true if the callback request succeeds.
+static bool PostForLaterExecution(crazy_callback_t* callback_request,
+ void* poster_opaque UNUSED) {
+ crazy_context_t* context = GetCrazyContext();
+
+ JavaVM* vm;
+ int minimum_jni_version;
+ crazy_context_get_java_vm(context,
+ reinterpret_cast<void**>(&vm),
+ &minimum_jni_version);
+
+ // Do not reuse JNIEnv from JNI_OnLoad, but retrieve our own.
+ JNIEnv* env;
+ if (JNI_OK != vm->GetEnv(
+ reinterpret_cast<void**>(&env), minimum_jni_version)) {
+ LOG_ERROR("Could not create JNIEnv");
+ return false;
+ }
+
+ // Copy the callback; the one passed as an argument may be temporary.
+ crazy_callback_t* callback = new crazy_callback_t();
+ *callback = *callback_request;
+
+ LOG_INFO("%s: Calling back to java with handler %p, opaque %p",
+ __FUNCTION__, callback->handler, callback->opaque);
+
+ jlong arg = static_cast<jlong>(reinterpret_cast<intptr_t>(callback));
+ env->CallStaticVoidMethod(
+ s_callback_refs.clazz, s_callback_refs.method_id, arg);
+
+ // Back out and return false if we encounter a JNI exception.
+ if (env->ExceptionCheck() == JNI_TRUE) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ delete callback;
+ return false;
+ }
+
+ return true;
+}
+
jboolean CreateSharedRelro(JNIEnv* env,
jclass clazz,
jstring library_name,
@@ -391,6 +493,12 @@ const JNINativeMethod kNativeMethods[] = {
")"
"Z",
reinterpret_cast<void*>(&LoadLibrary)},
+ {"nativeRunCallbackOnUiThread",
+ "("
+ "J"
+ ")"
+ "V",
+ reinterpret_cast<void*>(&RunCallbackOnUiThread)},
{"nativeCreateSharedRelro",
"("
"Ljava/lang/String;"
@@ -433,8 +541,9 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
// Register native methods.
jclass linker_class;
- if (!InitClassReference(
- env, "org/chromium/base/library_loader/Linker", &linker_class))
+ if (!InitClassReference(env,
+ "org/chromium/base/library_loader/Linker",
+ &linker_class))
return -1;
LOG_INFO("%s: Registering native methods", __FUNCTION__);
@@ -448,10 +557,20 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return -1;
}
+ // Resolve and save the Java side Linker callback class and method.
+ LOG_INFO("%s: Resolving callback references", __FUNCTION__);
+ if (!s_callback_refs.Init(env, linker_class)) {
+ return -1;
+ }
+
// Save JavaVM* handle into context.
crazy_context_t* context = GetCrazyContext();
crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4);
+ // Register the function that the crazy linker can call to post code
+ // for later execution.
+ crazy_context_set_callback_poster(context, &PostForLaterExecution, NULL);
+
LOG_INFO("%s: Done", __FUNCTION__);
return JNI_VERSION_1_4;
}
« no previous file with comments | « base/android/java/src/org/chromium/base/library_loader/Linker.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698