FreeRDP/client/Android/android_jni_callback.c

231 lines
5.3 KiB
C
Raw Normal View History

/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Android JNI Callback Helpers
*
2013-12-04 14:37:57 +04:00
* Copyright 2011-2013 Thincast Technologies GmbH, Author: Martin Fleisz
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include "android_jni_callback.h"
#include "android_freerdp_jni.h"
2014-09-12 19:13:01 +04:00
#include <freerdp/log.h>
#define TAG CLIENT_TAG("android.callback")
2014-09-12 19:13:01 +04:00
static JavaVM* jVM;
static jobject jLibFreeRDPObject;
2016-10-17 11:24:30 +03:00
static const char* jLibFreeRDPPath = JAVA_LIBFREERDP_CLASS;
2016-10-17 11:24:30 +03:00
static void jni_load_class(JNIEnv* env, const char* path, jobject* objptr)
{
jclass class;
jmethodID method;
jobject object;
WLog_DBG(TAG, "jni_load_class: %s", path);
class = (*env)->FindClass(env, path);
if (!class)
{
2014-09-12 19:13:01 +04:00
WLog_ERR(TAG, "jni_load_class: failed to find class %s", path);
goto finish;
}
method = (*env)->GetMethodID(env, class, "<init>", "()V");
if (!method)
{
2014-09-12 19:13:01 +04:00
WLog_ERR(TAG, "jni_load_class: failed to find class constructor of %s", path);
goto finish;
}
object = (*env)->NewObject(env, class, method);
if (!object)
{
2014-09-12 19:13:01 +04:00
WLog_ERR(TAG, "jni_load_class: failed create new object of %s", path);
goto finish;
}
(*objptr) = (*env)->NewGlobalRef(env, object);
finish:
2016-10-17 11:24:30 +03:00
while (0);
}
jint init_callback_environment(JavaVM* vm, JNIEnv* env)
{
jVM = vm;
jni_load_class(env, jLibFreeRDPPath, &jLibFreeRDPObject);
return JNI_VERSION_1_6;
}
/* attach current thread to jvm */
jboolean jni_attach_thread(JNIEnv** env)
{
if ((*jVM)->GetEnv(jVM, (void**) env, JNI_VERSION_1_4) != JNI_OK)
{
WLog_DBG(TAG, "android_java_callback: attaching current thread");
(*jVM)->AttachCurrentThread(jVM, env, NULL);
if ((*jVM)->GetEnv(jVM, (void**) env, JNI_VERSION_1_4) != JNI_OK)
{
2016-10-17 11:24:30 +03:00
WLog_ERR(TAG,
"android_java_callback: failed to obtain current JNI environment");
}
return JNI_TRUE;
}
return JNI_FALSE;
}
/* attach current thread to JVM */
void jni_detach_thread()
{
(*jVM)->DetachCurrentThread(jVM);
}
/* callback with void result */
2016-10-17 11:24:30 +03:00
static void java_callback_void(jobject obj, const char* callback,
const char* signature, va_list args)
{
jclass jObjClass;
jmethodID jCallback;
jboolean attached;
2016-10-17 11:24:30 +03:00
JNIEnv* env;
WLog_DBG(TAG, "java_callback: %s (%s)", callback, signature);
attached = jni_attach_thread(&env);
jObjClass = (*env)->GetObjectClass(env, obj);
2014-09-12 19:13:01 +04:00
if (!jObjClass)
{
WLog_ERR(TAG, "android_java_callback: failed to get class reference");
goto finish;
}
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
2014-09-12 19:13:01 +04:00
if (!jCallback)
{
WLog_ERR(TAG, "android_java_callback: failed to get method id");
goto finish;
}
(*env)->CallStaticVoidMethodV(env, jObjClass, jCallback, args);
finish:
2016-10-17 11:24:30 +03:00
if (attached == JNI_TRUE)
jni_detach_thread();
}
/* callback with bool result */
2016-10-17 11:24:30 +03:00
static jboolean java_callback_bool(jobject obj, const char* callback,
const char* signature, va_list args)
{
jclass jObjClass;
jmethodID jCallback;
jboolean attached;
jboolean res = JNI_FALSE;
2016-10-17 11:24:30 +03:00
JNIEnv* env;
WLog_DBG(TAG, "java_callback: %s (%s)", callback, signature);
attached = jni_attach_thread(&env);
jObjClass = (*env)->GetObjectClass(env, obj);
2014-09-12 19:13:01 +04:00
if (!jObjClass)
{
WLog_ERR(TAG, "android_java_callback: failed to get class reference");
goto finish;
}
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
2014-09-12 19:13:01 +04:00
if (!jCallback)
{
WLog_ERR(TAG, "android_java_callback: failed to get method id");
goto finish;
}
res = (*env)->CallStaticBooleanMethodV(env, jObjClass, jCallback, args);
finish:
2016-10-17 11:24:30 +03:00
if (attached == JNI_TRUE)
jni_detach_thread();
return res;
}
/* callback with int result */
2016-10-17 11:24:30 +03:00
static jint java_callback_int(jobject obj, const char* callback,
const char* signature, va_list args)
{
jclass jObjClass;
jmethodID jCallback;
jboolean attached;
jint res = -1;
2016-10-17 11:24:30 +03:00
JNIEnv* env;
2016-02-05 04:32:47 +03:00
WLog_DBG(TAG, "java_callback: %s (%s)", callback, signature);
attached = jni_attach_thread(&env);
jObjClass = (*env)->GetObjectClass(env, obj);
if (!jObjClass)
{
WLog_ERR(TAG, "android_java_callback: failed to get class reference");
goto finish;
}
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
if (!jCallback)
{
WLog_ERR(TAG, "android_java_callback: failed to get method id");
goto finish;
}
res = (*env)->CallStaticIntMethodV(env, jObjClass, jCallback, args);
finish:
2016-10-17 11:24:30 +03:00
if (attached == JNI_TRUE)
jni_detach_thread();
return res;
}
/* callback to freerdp class */
2016-10-17 11:24:30 +03:00
void freerdp_callback(const char* callback, const char* signature, ...)
{
va_list vl;
va_start(vl, signature);
java_callback_void(jLibFreeRDPObject, callback, signature, vl);
va_end(vl);
}
2016-10-17 11:24:30 +03:00
jboolean freerdp_callback_bool_result(const char* callback,
const char* signature, ...)
{
va_list vl;
va_start(vl, signature);
jboolean res = java_callback_bool(jLibFreeRDPObject, callback, signature, vl);
va_end(vl);
return res;
}
2016-10-17 11:24:30 +03:00
jint freerdp_callback_int_result(const char* callback, const char* signature,
...)
{
va_list vl;
2016-10-17 11:24:30 +03:00
va_start(vl, signature);
jint res = java_callback_int(jLibFreeRDPObject, callback, signature, vl);
va_end(vl);
return res;
}