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 
   60static 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);
 
   83static 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);
 
  106static BOOL android_begin_paint(rdpContext* context)
 
  111static 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;
 
  170static 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,
 
  183static 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);
 
  218static BOOL android_Pointer_New(rdpContext* context, rdpPointer* pointer)
 
  220  WINPR_ASSERT(context);
 
  221  WINPR_ASSERT(pointer);
 
  222  WINPR_ASSERT(context->gdi);
 
  227static void android_Pointer_Free(rdpContext* context, rdpPointer* pointer)
 
  229  WINPR_ASSERT(context);
 
  232static BOOL android_Pointer_Set(rdpContext* context, rdpPointer* pointer)
 
  234  WINPR_ASSERT(context);
 
  235  WINPR_ASSERT(pointer);
 
  240static BOOL android_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
 
  242  WINPR_ASSERT(context);
 
  247static BOOL android_Pointer_SetNull(rdpContext* context)
 
  249  WINPR_ASSERT(context);
 
  254static BOOL android_Pointer_SetDefault(rdpContext* context)
 
  256  WINPR_ASSERT(context);
 
  261static 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);
 
  279static 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);
 
  310static void android_post_disconnect(freerdp* instance)
 
  312  freerdp_callback(
"OnDisconnecting", 
"(J)V", (jlong)instance);
 
  316static 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);
 
  348static BOOL android_authenticate(freerdp* instance, 
char** username, 
char** password, 
char** domain)
 
  350  return android_authenticate_int(instance, username, password, domain, 
"OnAuthenticate");
 
  353static BOOL android_gw_authenticate(freerdp* instance, 
char** username, 
char** password,
 
  356  return android_authenticate_int(instance, username, password, domain, 
"OnGatewayAuthenticate");
 
  359static 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)
 
  390static 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)
 
  420static 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...");
 
  484static 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, 
"Disconnect...");
 
  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.");
 
  527static 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;
 
  546static void android_client_free(freerdp* instance, rdpContext* context)
 
  551  android_event_queue_uninit(instance);
 
  554static 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;
 
  572JNIEXPORT 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 environment 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;
 
  667JNIEXPORT 
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) 
  680JNIEXPORT jstring JNICALL
 
  681Java_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)));
 
  694JNIEXPORT jboolean JNICALL
 
  695Java_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;
 
  731JNIEXPORT 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)))
 
  753JNIEXPORT 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))
 
  784JNIEXPORT jboolean JNICALL
 
  785Java_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);
 
  855JNIEXPORT jboolean JNICALL
 
  856Java_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);
 
  882JNIEXPORT jboolean JNICALL
 
  883Java_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);
 
  904JNIEXPORT jboolean JNICALL
 
  905Java_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);
 
  925JNIEXPORT jboolean JNICALL
 
  926Java_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);
 
  957JNIEXPORT jstring JNICALL
 
  958Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1jni_1version(JNIEnv* env, jclass cls)
 
  960  return (*env)->NewStringUTF(env, FREERDP_JNI_VERSION);
 
  963JNIEXPORT jboolean JNICALL
 
  964Java_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);
 
  973JNIEXPORT jstring JNICALL
 
  974Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1version(JNIEnv* env, jclass cls)
 
  976  return (*env)->NewStringUTF(env, freerdp_get_version_string());
 
  979JNIEXPORT jstring JNICALL
 
  980Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1build_1revision(JNIEnv* env,
 
  983  return (*env)->NewStringUTF(env, freerdp_get_build_revision());
 
  986JNIEXPORT jstring JNICALL
 
  987Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1build_1config(JNIEnv* env,
 
  990  return (*env)->NewStringUTF(env, freerdp_get_build_config());
 
  993static jclass gJavaActivityClass = NULL;
 
  995jint JNI_OnLoad(JavaVM* vm, 
void* reserved)
 
  998  setlocale(LC_ALL, 
"");
 
  999  WLog_DBG(TAG, 
"Setting up JNI environment...");
 
 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);
 
 1029void JNICALL JNI_OnUnload(JavaVM* vm, 
void* reserved)
 
 1032  WLog_DBG(TAG, 
"Tearing down JNI environment...");
 
 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.