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

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: Tidy up style. 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
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..ac5dba7d76928909f6d2bbc0a2a08d960ca75c69 100644
--- a/base/android/linker/linker_jni.cc
+++ b/base/android/linker/linker_jni.cc
@@ -140,6 +140,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.
@@ -282,6 +301,81 @@ jboolean LoadLibrary(JNIEnv* env,
return true;
}
+// Class to support simple callbacks from the Java side. Hold a pointer
+// to a function taking a single void* argument, and an argument value.
+struct callback_t {
+ public:
+ callback_t() : handler(NULL), opaque(NULL) { }
+
+ void (*handler)(void*);
+ void* opaque;
+};
+
+// 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 callback_t.
+void ReceiveCallbackFromMainThread(JNIEnv* env, jclass clazz, jlong arg) {
+ callback_t* callback = reinterpret_cast<callback_t*>(arg);
+
+ LOG_INFO("%s: Called back from java with handler %p, opaque %p",
+ __FUNCTION__, callback->handler, callback->opaque);
+
+ (*callback->handler)(callback->opaque);
+ delete callback;
+}
+
+// Class holding the Java class and method ID for the Java side Linker
+// PostCallbackOnMainThread method. Like crazy_context_t, there is
+// only one of these, requiring no locking.
+struct callback_refs_t {
+ public:
+ callback_refs_t() : clazz(NULL), method_id(NULL) { }
+
+ jclass clazz;
+ jmethodID method_id;
+};
+
+static callback_refs_t s_callback_refs;
+
+// Request a callback from Java. Constructs a new callback_t and calls
+// the Java side's PostCallbackOnMainThread, which will some time later
+// call back to our ReceiveCallbackFromMainThread.
+// |handler| is a handler function, taking a single void* argument.
+// |opaque| is the argument to supply to the handler when run in the callback.
+// Returns true if the callback request succeeded.
+static bool PostForLaterExecution(void (*handler)(void*), void *opaque) {
bulach 2014/04/15 13:58:14 nit: s/void *opaque/void* opaque/
simonb1 2014/04/17 14:45:43 Done.
+ 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;
+ }
+
+ callback_t* callback = new callback_t();
+ callback->handler = handler;
+ callback->opaque = opaque;
+
+ 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);
bulach 2014/04/15 13:58:14 need to clear any java exception (assuming it's sa
simonb1 2014/04/17 14:45:43 Done.
+ return true;
+}
+
jboolean CreateSharedRelro(JNIEnv* env,
jclass clazz,
jstring library_name,
@@ -391,6 +485,12 @@ const JNINativeMethod kNativeMethods[] = {
")"
"Z",
reinterpret_cast<void*>(&LoadLibrary)},
+ {"nativeReceiveCallbackFromMainThread",
+ "("
+ "J"
+ ")"
+ "V",
+ reinterpret_cast<void*>(&ReceiveCallbackFromMainThread)},
{"nativeCreateSharedRelro",
"("
"Ljava/lang/String;"
@@ -416,7 +516,6 @@ const JNINativeMethod kNativeMethods[] = {
")"
"J",
reinterpret_cast<void*>(&GetPageSize)}, };
-
} // namespace
// JNI_OnLoad() hook called when the linker library is loaded through
@@ -433,8 +532,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__);
@@ -452,6 +552,21 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
crazy_context_t* context = GetCrazyContext();
crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4);
+ // Resolve the Java side Linker callback method.
+ jmethodID method_id;
+ if (!InitStaticMethodId(env,
+ linker_class,
+ "PostCallbackOnMainThread",
+ "(J)V",
+ &method_id))
+ return -1;
+
+ // Save the callback class and method, and register the function that
+ // the crazy linker can call to post code for later execution.
+ s_callback_refs.clazz = linker_class;
+ s_callback_refs.method_id = method_id;
+ crazy_context_set_post_for_later_execution(context, &PostForLaterExecution);
+
LOG_INFO("%s: Done", __FUNCTION__);
return JNI_VERSION_1_4;
}

Powered by Google App Engine
This is Rietveld 408576698