Blame client/Android/android_jni_callback.c

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 fa4841
	while (0)
Packit Service fa4841
		;
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 fa4841
	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 fa4841
		if ((*jVM)->GetEnv(jVM, (void**)env, JNI_VERSION_1_4) != JNI_OK)
Packit Service fa4841
		{
Packit Service fa4841
			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 fa4841
static void java_callback_void(jobject obj, const char* callback, const char* signature,
Packit Service fa4841
                               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 fa4841
static jboolean java_callback_bool(jobject obj, const char* callback, const char* signature,
Packit Service fa4841
                                   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 fa4841
static jint java_callback_int(jobject obj, const char* callback, const char* signature,
Packit Service fa4841
                              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 fa4841
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 fa4841
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
}