16 #include <freerdp/config.h>
25 #include <winpr/assert.h>
27 #include <freerdp/graphics.h>
28 #include <freerdp/codec/rfx.h>
29 #include <freerdp/gdi/gdi.h>
30 #include <freerdp/gdi/gfx.h>
31 #include <freerdp/client/rdpei.h>
32 #include <freerdp/client/rdpgfx.h>
33 #include <freerdp/client/cliprdr.h>
34 #include <freerdp/codec/h264.h>
35 #include <freerdp/channels/channels.h>
36 #include <freerdp/client/channels.h>
37 #include <freerdp/client/cmdline.h>
38 #include <freerdp/constants.h>
39 #include <freerdp/locale/keyboard.h>
40 #include <freerdp/primitives.h>
41 #include <freerdp/version.h>
42 #include <freerdp/settings.h>
43 #include <freerdp/utils/signal.h>
45 #include <android/bitmap.h>
47 #include "android_jni_callback.h"
48 #include "android_jni_utils.h"
49 #include "android_cliprdr.h"
50 #include "android_freerdp_jni.h"
52 #if defined(WITH_GPROF)
56 #define TAG CLIENT_TAG("android")
59 #define FREERDP_JNI_VERSION FREERDP_VERSION_FULL
60 static void android_OnChannelConnectedEventHandler(
void* context,
61 const ChannelConnectedEventArgs* e)
63 rdpSettings* settings;
68 WLog_FATAL(TAG,
"(context=%p, EventArgs=%p", context, (
void*)e);
73 settings = afc->common.context.settings;
75 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
77 android_cliprdr_init(afc, (CliprdrClientContext*)e->pInterface);
80 freerdp_client_OnChannelConnectedEventHandler(context, e);
83 static void android_OnChannelDisconnectedEventHandler(
void* context,
84 const ChannelDisconnectedEventArgs* e)
86 rdpSettings* settings;
91 WLog_FATAL(TAG,
"(context=%p, EventArgs=%p", context, (
void*)e);
96 settings = afc->common.context.settings;
98 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
100 android_cliprdr_uninit(afc, (CliprdrClientContext*)e->pInterface);
103 freerdp_client_OnChannelDisconnectedEventHandler(context, e);
106 static BOOL android_begin_paint(rdpContext* context)
111 static BOOL android_end_paint(rdpContext* context)
119 rdpSettings* settings;
121 if (!ctx || !context->instance)
124 settings = context->settings;
131 if (!gdi || !gdi->primary || !gdi->primary->hdc)
134 hwnd = ctx->common.context.gdi->primary->hdc->hwnd;
139 ninvalid = hwnd->ninvalid;
144 cinvalid = hwnd->cinvalid;
151 x2 = cinvalid[0].x + cinvalid[0].w;
152 y2 = cinvalid[0].y + cinvalid[0].h;
154 for (
int i = 0; i < ninvalid; i++)
156 x1 = MIN(x1, cinvalid[i].x);
157 y1 = MIN(y1, cinvalid[i].y);
158 x2 = MAX(x2, cinvalid[i].x + cinvalid[i].w);
159 y2 = MAX(y2, cinvalid[i].y + cinvalid[i].h);
162 freerdp_callback(
"OnGraphicsUpdate",
"(JIIII)V", (jlong)context->instance, x1, y1, x2 - x1,
165 hwnd->invalid->null = TRUE;
170 static BOOL android_desktop_resize(rdpContext* context)
172 WINPR_ASSERT(context);
173 WINPR_ASSERT(context->settings);
174 WINPR_ASSERT(context->instance);
176 freerdp_callback(
"OnGraphicsResize",
"(JIII)V", (jlong)context->instance,
183 static BOOL android_pre_connect(freerdp* instance)
186 rdpSettings* settings;
188 WINPR_ASSERT(instance);
189 WINPR_ASSERT(instance->context);
191 settings = instance->context->settings;
196 rc = PubSub_SubscribeChannelConnected(instance->context->pubSub,
197 android_OnChannelConnectedEventHandler);
199 if (rc != CHANNEL_RC_OK)
201 WLog_ERR(TAG,
"Could not subscribe to connect event handler [%l08X]", rc);
205 rc = PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
206 android_OnChannelDisconnectedEventHandler);
208 if (rc != CHANNEL_RC_OK)
210 WLog_ERR(TAG,
"Could not subscribe to disconnect event handler [%l08X]", rc);
214 freerdp_callback(
"OnPreConnect",
"(J)V", (jlong)instance);
218 static BOOL android_Pointer_New(rdpContext* context, rdpPointer* pointer)
220 WINPR_ASSERT(context);
221 WINPR_ASSERT(pointer);
222 WINPR_ASSERT(context->gdi);
227 static void android_Pointer_Free(rdpContext* context, rdpPointer* pointer)
229 WINPR_ASSERT(context);
232 static BOOL android_Pointer_Set(rdpContext* context, rdpPointer* pointer)
234 WINPR_ASSERT(context);
235 WINPR_ASSERT(pointer);
240 static BOOL android_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
242 WINPR_ASSERT(context);
247 static BOOL android_Pointer_SetNull(rdpContext* context)
249 WINPR_ASSERT(context);
254 static BOOL android_Pointer_SetDefault(rdpContext* context)
256 WINPR_ASSERT(context);
261 static BOOL android_register_pointer(rdpGraphics* graphics)
263 rdpPointer pointer = { 0 };
268 pointer.size =
sizeof(pointer);
269 pointer.New = android_Pointer_New;
270 pointer.Free = android_Pointer_Free;
271 pointer.Set = android_Pointer_Set;
272 pointer.SetNull = android_Pointer_SetNull;
273 pointer.SetDefault = android_Pointer_SetDefault;
274 pointer.SetPosition = android_Pointer_SetPosition;
275 graphics_register_pointer(graphics, &pointer);
279 static BOOL android_post_connect(freerdp* instance)
281 rdpSettings* settings;
284 WINPR_ASSERT(instance);
285 WINPR_ASSERT(instance->context);
287 update = instance->context->update;
288 WINPR_ASSERT(update);
290 settings = instance->context->settings;
291 WINPR_ASSERT(settings);
293 if (!gdi_init(instance, PIXEL_FORMAT_RGBX32))
296 if (!android_register_pointer(instance->context->graphics))
299 update->BeginPaint = android_begin_paint;
300 update->EndPaint = android_end_paint;
301 update->DesktopResize = android_desktop_resize;
302 freerdp_callback(
"OnSettingsChanged",
"(JIII)V", (jlong)instance,
306 freerdp_callback(
"OnConnectionSuccess",
"(J)V", (jlong)instance);
310 static void android_post_disconnect(freerdp* instance)
312 freerdp_callback(
"OnDisconnecting",
"(J)V", (jlong)instance);
316 static BOOL android_authenticate_int(freerdp* instance,
char** username,
char** password,
317 char** domain,
const char* cb_name)
320 jboolean attached = jni_attach_thread(&env);
321 jobject jstr1 = create_string_builder(env, *username);
322 jobject jstr2 = create_string_builder(env, *domain);
323 jobject jstr3 = create_string_builder(env, *password);
325 res = freerdp_callback_bool_result(cb_name,
326 "(JLjava/lang/StringBuilder;"
327 "Ljava/lang/StringBuilder;"
328 "Ljava/lang/StringBuilder;)Z",
329 (jlong)instance, jstr1, jstr2, jstr3);
335 *username = get_string_from_string_builder(env, jstr1);
337 *domain = get_string_from_string_builder(env, jstr2);
339 *password = get_string_from_string_builder(env, jstr3);
342 if (attached == JNI_TRUE)
345 return ((res == JNI_TRUE) ? TRUE : FALSE);
348 static BOOL android_authenticate(freerdp* instance,
char** username,
char** password,
char** domain)
350 return android_authenticate_int(instance, username, password, domain,
"OnAuthenticate");
353 static BOOL android_gw_authenticate(freerdp* instance,
char** username,
char** password,
356 return android_authenticate_int(instance, username, password, domain,
"OnGatewayAuthenticate");
359 static DWORD android_verify_certificate_ex(freerdp* instance,
const char* host, UINT16 port,
360 const char* common_name,
const char* subject,
361 const char* issuer,
const char* fingerprint, DWORD flags)
363 WLog_DBG(TAG,
"Certificate details [%s:%" PRIu16
":", host, port);
364 WLog_DBG(TAG,
"\tSubject: %s", subject);
365 WLog_DBG(TAG,
"\tIssuer: %s", issuer);
366 WLog_DBG(TAG,
"\tThumbprint: %s", fingerprint);
368 "The above X.509 certificate could not be verified, possibly because you do not have "
369 "the CA certificate in your certificate store, or the certificate has expired."
370 "Please look at the OpenSSL documentation on how to add a private CA to the store.\n");
372 jboolean attached = jni_attach_thread(&env);
373 jstring jstr0 = (*env)->NewStringUTF(env, host);
374 jstring jstr1 = (*env)->NewStringUTF(env, common_name);
375 jstring jstr2 = (*env)->NewStringUTF(env, subject);
376 jstring jstr3 = (*env)->NewStringUTF(env, issuer);
377 jstring jstr4 = (*env)->NewStringUTF(env, fingerprint);
378 jint res = freerdp_callback_int_result(
"OnVerifyCertificateEx",
379 "(JLjava/lang/String;JLjava/lang/String;Ljava/lang/"
380 "String;Ljava/lang/String;Ljava/lang/String;J)I",
381 (jlong)instance, jstr0, (jlong)port, jstr1, jstr2, jstr3,
382 jstr4, (jlong)flags);
384 if (attached == JNI_TRUE)
390 static DWORD android_verify_changed_certificate_ex(freerdp* instance,
const char* host, UINT16 port,
391 const char* common_name,
const char* subject,
392 const char* issuer,
const char* new_fingerprint,
393 const char* old_subject,
const char* old_issuer,
394 const char* old_fingerprint, DWORD flags)
397 jboolean attached = jni_attach_thread(&env);
398 jstring jhost = (*env)->NewStringUTF(env, host);
399 jstring jstr0 = (*env)->NewStringUTF(env, common_name);
400 jstring jstr1 = (*env)->NewStringUTF(env, subject);
401 jstring jstr2 = (*env)->NewStringUTF(env, issuer);
402 jstring jstr3 = (*env)->NewStringUTF(env, new_fingerprint);
403 jstring jstr4 = (*env)->NewStringUTF(env, old_subject);
404 jstring jstr5 = (*env)->NewStringUTF(env, old_issuer);
405 jstring jstr6 = (*env)->NewStringUTF(env, old_fingerprint);
407 freerdp_callback_int_result(
"OnVerifyChangedCertificateEx",
408 "(JLjava/lang/String;JLjava/lang/String;Ljava/lang/"
409 "String;Ljava/lang/String;Ljava/lang/String;"
410 "Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)I",
411 (jlong)instance, jhost, (jlong)port, jstr0, jstr1, jstr2, jstr3,
412 jstr4, jstr5, jstr6, (jlong)flags);
414 if (attached == JNI_TRUE)
420 static int android_freerdp_run(freerdp* instance)
423 DWORD status = WAIT_FAILED;
424 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
425 HANDLE inputEvent = NULL;
426 const rdpSettings* settings = instance->context->settings;
427 rdpContext* context = instance->context;
429 inputEvent = android_get_handle(instance);
431 while (!freerdp_shall_disconnect_context(instance->context))
436 handles[count++] = inputEvent;
438 tmp = freerdp_get_event_handles(context, &handles[count], 64 - count);
442 WLog_ERR(TAG,
"freerdp_get_event_handles failed");
447 status = WaitForMultipleObjects(count, handles, FALSE, INFINITE);
449 if (status == WAIT_FAILED)
451 WLog_ERR(TAG,
"WaitForMultipleObjects failed with %" PRIu32
" [%08lX]", status,
456 if (!freerdp_check_event_handles(context))
462 WLog_ERR(TAG,
"Failed to check FreeRDP file descriptor");
463 status = GetLastError();
467 if (freerdp_shall_disconnect_context(instance->context))
470 if (android_check_handle(instance) != TRUE)
472 WLog_ERR(TAG,
"Failed to check android file descriptor");
473 status = GetLastError();
479 WLog_INFO(TAG,
"Prepare shutdown...");
484 static DWORD WINAPI android_thread_func(LPVOID param)
486 DWORD status = ERROR_BAD_ARGUMENTS;
487 freerdp* instance = param;
488 WLog_DBG(TAG,
"Start...");
490 WINPR_ASSERT(instance);
491 WINPR_ASSERT(instance->context);
493 if (freerdp_client_start(instance->context) != CHANNEL_RC_OK)
496 WLog_DBG(TAG,
"Connect...");
498 if (!freerdp_connect(instance))
499 status = GetLastError();
502 status = android_freerdp_run(instance);
503 WLog_DBG(TAG,
"Disonnect...");
505 if (!freerdp_disconnect(instance))
506 status = GetLastError();
509 WLog_DBG(TAG,
"Stop...");
511 if (freerdp_client_stop(instance->context) != CHANNEL_RC_OK)
515 WLog_DBG(TAG,
"Session ended with %08" PRIX32
"", status);
517 if (status == CHANNEL_RC_OK)
518 freerdp_callback(
"OnDisconnected",
"(J)V", (jlong)instance);
520 freerdp_callback(
"OnConnectionFailure",
"(J)V", (jlong)instance);
522 WLog_DBG(TAG,
"Quit.");
527 static BOOL android_client_new(freerdp* instance, rdpContext* context)
529 WINPR_ASSERT(instance);
530 WINPR_ASSERT(context);
532 if (!android_event_queue_init(instance))
535 instance->PreConnect = android_pre_connect;
536 instance->PostConnect = android_post_connect;
537 instance->PostDisconnect = android_post_disconnect;
538 instance->Authenticate = android_authenticate;
539 instance->GatewayAuthenticate = android_gw_authenticate;
540 instance->VerifyCertificateEx = android_verify_certificate_ex;
541 instance->VerifyChangedCertificateEx = android_verify_changed_certificate_ex;
542 instance->LogonErrorInfo = NULL;
546 static void android_client_free(freerdp* instance, rdpContext* context)
551 android_event_queue_uninit(instance);
554 static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
556 WINPR_ASSERT(pEntryPoints);
558 ZeroMemory(pEntryPoints,
sizeof(RDP_CLIENT_ENTRY_POINTS));
560 pEntryPoints->Version = RDP_CLIENT_INTERFACE_VERSION;
561 pEntryPoints->Size =
sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
562 pEntryPoints->GlobalInit = NULL;
563 pEntryPoints->GlobalUninit = NULL;
565 pEntryPoints->ClientNew = android_client_new;
566 pEntryPoints->ClientFree = android_client_free;
567 pEntryPoints->ClientStart = NULL;
568 pEntryPoints->ClientStop = NULL;
572 JNIEXPORT jlong JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1new(
573 JNIEnv* env, jclass cls, jobject context)
578 jmethodID getFilesDirID;
579 jmethodID getAbsolutePathID;
583 RDP_CLIENT_ENTRY_POINTS clientEntryPoints;
585 #if defined(WITH_GPROF)
586 setenv(
"CPUPROFILE_FREQUENCY",
"200", 1);
587 monstartup(
"libfreerdp-android.so");
589 contextClass = (*env)->FindClass(env, JAVA_CONTEXT_CLASS);
590 fileClass = (*env)->FindClass(env, JAVA_FILE_CLASS);
592 if (!contextClass || !fileClass)
594 WLog_FATAL(TAG,
"Failed to load class references %s=%p, %s=%p", JAVA_CONTEXT_CLASS,
595 (
void*)contextClass, JAVA_FILE_CLASS, (
void*)fileClass);
600 (*env)->GetMethodID(env, contextClass,
"getFilesDir",
"()L" JAVA_FILE_CLASS
";");
604 WLog_FATAL(TAG,
"Failed to find method ID getFilesDir ()L" JAVA_FILE_CLASS
";");
609 (*env)->GetMethodID(env, fileClass,
"getAbsolutePath",
"()Ljava/lang/String;");
611 if (!getAbsolutePathID)
613 WLog_FATAL(TAG,
"Failed to find method ID getAbsolutePath ()Ljava/lang/String;");
617 filesDirObj = (*env)->CallObjectMethod(env, context, getFilesDirID);
621 WLog_FATAL(TAG,
"Failed to call getFilesDir");
625 path = (*env)->CallObjectMethod(env, filesDirObj, getAbsolutePathID);
629 WLog_FATAL(TAG,
"Failed to call getAbsolutePath");
633 raw = (*env)->GetStringUTFChars(env, path, 0);
637 WLog_FATAL(TAG,
"Failed to get C string from java string");
641 envStr = _strdup(raw);
642 (*env)->ReleaseStringUTFChars(env, path, raw);
646 WLog_FATAL(TAG,
"_strdup(%s) failed", raw);
650 if (setenv(
"HOME", _strdup(envStr), 1) != 0)
652 char ebuffer[256] = { 0 };
653 WLog_FATAL(TAG,
"Failed to set environemnt HOME=%s %s [%d]", env,
654 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
658 RdpClientEntry(&clientEntryPoints);
659 ctx = freerdp_client_context_new(&clientEntryPoints);
664 return (jlong)ctx->instance;
667 JNIEXPORT
void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1free(
668 JNIEnv* env, jclass cls, jlong instance)
670 freerdp* inst = (freerdp*)instance;
673 freerdp_client_context_free(inst->context);
675 #if defined(WITH_GPROF)
680 JNIEXPORT jstring JNICALL
681 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1last_1error_1string(JNIEnv* env,
685 freerdp* inst = (freerdp*)instance;
687 if (!inst || !inst->context)
688 return (*env)->NewStringUTF(env,
"");
690 return (*env)->NewStringUTF(
691 env, freerdp_get_last_error_string(freerdp_get_last_error(inst->context)));
694 JNIEXPORT jboolean JNICALL
695 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1parse_1arguments(JNIEnv* env, jclass cls,
697 jobjectArray arguments)
699 freerdp* inst = (freerdp*)instance;
704 if (!inst || !inst->context)
707 count = (*env)->GetArrayLength(env, arguments);
708 argv = calloc(count,
sizeof(
char*));
713 for (
int i = 0; i < count; i++)
715 jstring str = (jstring)(*env)->GetObjectArrayElement(env, arguments, i);
716 const char* raw = (*env)->GetStringUTFChars(env, str, 0);
717 argv[i] = _strdup(raw);
718 (*env)->ReleaseStringUTFChars(env, str, raw);
722 freerdp_client_settings_parse_command_line(inst->context->settings, count, argv, FALSE);
724 for (
int i = 0; i < count; i++)
728 return (status == 0) ? JNI_TRUE : JNI_FALSE;
731 JNIEXPORT jboolean JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1connect(
732 JNIEnv* env, jclass cls, jlong instance)
734 freerdp* inst = (freerdp*)instance;
737 if (!inst || !inst->context)
739 WLog_FATAL(TAG,
"(env=%p, cls=%p, instance=%d", (
void*)env, (
void*)cls, instance);
745 if (!(ctx->thread = CreateThread(NULL, 0, android_thread_func, inst, 0, NULL)))
753 JNIEXPORT jboolean JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1disconnect(
754 JNIEnv* env, jclass cls, jlong instance)
756 freerdp* inst = (freerdp*)instance;
760 if (!inst || !inst->context || !cls || !env)
762 WLog_FATAL(TAG,
"(env=%p, cls=%p, instance=%d", (
void*)env, (
void*)cls, instance);
772 if (!android_push_event(inst, event))
778 if (!freerdp_abort_connect_context(inst->context))
784 JNIEXPORT jboolean JNICALL
785 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1update_1graphics(JNIEnv* env, jclass cls,
787 jobject bitmap, jint x,
795 AndroidBitmapInfo info;
796 freerdp* inst = (freerdp*)instance;
799 if (!env || !cls || !inst)
801 WLog_FATAL(TAG,
"(env=%p, cls=%p, instance=%d", (
void*)env, (
void*)cls, instance);
805 gdi = inst->context->gdi;
807 if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0)
809 WLog_FATAL(TAG,
"AndroidBitmap_getInfo() failed ! error=%d", ret);
813 if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0)
815 WLog_FATAL(TAG,
"AndroidBitmap_lockPixels() failed ! error=%d", ret);
823 case ANDROID_BITMAP_FORMAT_RGBA_8888:
824 DstFormat = PIXEL_FORMAT_RGBX32;
827 case ANDROID_BITMAP_FORMAT_RGB_565:
828 DstFormat = PIXEL_FORMAT_RGB16;
831 case ANDROID_BITMAP_FORMAT_RGBA_4444:
832 case ANDROID_BITMAP_FORMAT_A_8:
833 case ANDROID_BITMAP_FORMAT_NONE:
841 rc = freerdp_image_copy(pixels, DstFormat, info.stride, x, y, width, height,
842 gdi->primary_buffer, gdi->dstFormat, gdi->stride, x, y,
843 &gdi->palette, FREERDP_FLIP_NONE);
846 if ((ret = AndroidBitmap_unlockPixels(env, bitmap)) < 0)
848 WLog_FATAL(TAG,
"AndroidBitmap_unlockPixels() failed ! error=%d", ret);
855 JNIEXPORT jboolean JNICALL
856 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1send_1key_1event(JNIEnv* env, jclass cls,
863 freerdp* inst = (freerdp*)instance;
864 scancode = GetVirtualScanCodeFromVirtualKeyCode(keycode, 4);
865 int flags = (down == JNI_TRUE) ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE;
866 flags |= (scancode & KBDEXT) ? KBD_FLAGS_EXTENDED : 0;
867 event = (
ANDROID_EVENT*)android_event_key_new(flags, scancode & 0xFF);
872 if (!android_push_event(inst, event))
874 android_event_free(event);
878 WLog_DBG(TAG,
"send_key_event: %" PRIu32
", %d", scancode, flags);
882 JNIEXPORT jboolean JNICALL
883 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1send_1unicodekey_1event(
884 JNIEnv* env, jclass cls, jlong instance, jint keycode, jboolean down)
887 freerdp* inst = (freerdp*)instance;
888 UINT16 flags = (down == JNI_TRUE) ? 0 : KBD_FLAGS_RELEASE;
889 event = (
ANDROID_EVENT*)android_event_unicodekey_new(flags, keycode);
894 if (!android_push_event(inst, event))
896 android_event_free(event);
900 WLog_DBG(TAG,
"send_unicodekey_event: %d", keycode);
904 JNIEXPORT jboolean JNICALL
905 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1send_1cursor_1event(
906 JNIEnv* env, jclass cls, jlong instance, jint x, jint y, jint flags)
909 freerdp* inst = (freerdp*)instance;
910 event = (
ANDROID_EVENT*)android_event_cursor_new(flags, x, y);
915 if (!android_push_event(inst, event))
917 android_event_free(event);
921 WLog_DBG(TAG,
"send_cursor_event: (%d, %d), %d", x, y, flags);
925 JNIEXPORT jboolean JNICALL
926 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1send_1clipboard_1data(JNIEnv* env,
932 freerdp* inst = (freerdp*)instance;
933 const char* data = jdata != NULL ? (*env)->GetStringUTFChars(env, jdata, NULL) : NULL;
934 const size_t data_length = data ? (*env)->GetStringUTFLength(env, jdata) : 0;
935 jboolean ret = JNI_FALSE;
936 event = (
ANDROID_EVENT*)android_event_clipboard_new((
void*)data, data_length);
941 if (!android_push_event(inst, event))
943 android_event_free(event);
947 WLog_DBG(TAG,
"send_clipboard_data: (%s)", data);
952 (*env)->ReleaseStringUTFChars(env, jdata, data);
957 JNIEXPORT jstring JNICALL
958 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1jni_1version(JNIEnv* env, jclass cls)
960 return (*env)->NewStringUTF(env, FREERDP_JNI_VERSION);
963 JNIEXPORT jboolean JNICALL
964 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1has_1h264(JNIEnv* env, jclass cls)
966 H264_CONTEXT* ctx = h264_context_new(FALSE);
969 h264_context_free(ctx);
973 JNIEXPORT jstring JNICALL
974 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1version(JNIEnv* env, jclass cls)
976 return (*env)->NewStringUTF(env, freerdp_get_version_string());
979 JNIEXPORT jstring JNICALL
980 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1build_1revision(JNIEnv* env,
983 return (*env)->NewStringUTF(env, freerdp_get_build_revision());
986 JNIEXPORT jstring JNICALL
987 Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1build_1config(JNIEnv* env,
990 return (*env)->NewStringUTF(env, freerdp_get_build_config());
993 static jclass gJavaActivityClass = NULL;
995 jint JNI_OnLoad(JavaVM* vm,
void* reserved)
998 setlocale(LC_ALL,
"");
999 WLog_DBG(TAG,
"Setting up JNI environement...");
1008 if ((*vm)->GetEnv(vm, (
void**)&env, JNI_VERSION_1_6) != JNI_OK)
1010 WLog_FATAL(TAG,
"Failed to get the environment");
1015 jclass activityClass = (*env)->FindClass(env, JAVA_LIBFREERDP_CLASS);
1019 WLog_FATAL(TAG,
"failed to get %s class reference", JAVA_LIBFREERDP_CLASS);
1024 gJavaActivityClass = (*env)->NewGlobalRef(env, activityClass);
1026 return init_callback_environment(vm, env);
1029 void JNICALL JNI_OnUnload(JavaVM* vm,
void* reserved)
1032 WLog_DBG(TAG,
"Tearing down JNI environement...");
1034 if ((*vm)->GetEnv(vm, (
void**)&env, JNI_VERSION_1_6) != JNI_OK)
1036 WLog_FATAL(TAG,
"Failed to get the environment");
1040 if (gJavaActivityClass)
1041 (*env)->DeleteGlobalRef(env, gJavaActivityClass);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.