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