Blame client/Android/android_jni_callback.c

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