|
Packit |
1fb8d4 |
/*
|
|
Packit |
1fb8d4 |
Android JNI Client Layer
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
Packit |
1fb8d4 |
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
|
Packit |
1fb8d4 |
Copyright 2013 Thincast Technologies GmbH, Author: Armin Novak
|
|
Packit |
1fb8d4 |
Copyright 2015 Bernhard Miklautz <bernhard.miklautz@thincast.com>
|
|
Packit |
1fb8d4 |
Copyright 2016 Thincast Technologies GmbH
|
|
Packit |
1fb8d4 |
Copyright 2016 Armin Novak <armin.novak@thincast.com>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
Packit |
1fb8d4 |
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
1fb8d4 |
#include "config.h"
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <assert.h>
|
|
Packit |
1fb8d4 |
#include <locale.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <jni.h>
|
|
Packit |
1fb8d4 |
#include <stdio.h>
|
|
Packit |
1fb8d4 |
#include <stdlib.h>
|
|
Packit |
1fb8d4 |
#include <errno.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <freerdp/graphics.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/codec/rfx.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/gdi/gdi.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/gdi/gfx.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/client/rdpei.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/client/rdpgfx.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/client/cliprdr.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/channels/channels.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/client/channels.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/client/cmdline.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/constants.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/locale/keyboard.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/primitives.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/version.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/settings.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/utils/signal.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <android/bitmap.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include "android_jni_callback.h"
|
|
Packit |
1fb8d4 |
#include "android_jni_utils.h"
|
|
Packit |
1fb8d4 |
#include "android_cliprdr.h"
|
|
Packit |
1fb8d4 |
#include "android_freerdp_jni.h"
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#if defined(WITH_GPROF)
|
|
Packit |
1fb8d4 |
#include "jni/prof.h"
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#define TAG CLIENT_TAG("android")
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/* Defines the JNI version supported by this library. */
|
|
Packit |
1fb8d4 |
#define FREERDP_JNI_VERSION "2.0.0"
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static void android_OnChannelConnectedEventHandler(
|
|
Packit |
1fb8d4 |
void* context,
|
|
Packit |
1fb8d4 |
ChannelConnectedEventArgs* e)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
rdpSettings* settings;
|
|
Packit |
1fb8d4 |
androidContext* afc;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!context || !e)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p",
|
|
Packit |
1fb8d4 |
__FUNCTION__, context, (void*) e);
|
|
Packit |
1fb8d4 |
return;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
afc = (androidContext*) context;
|
|
Packit |
1fb8d4 |
settings = afc->rdpCtx.settings;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (settings->SoftwareGdi)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
gdi_graphics_pipeline_init(afc->rdpCtx.gdi,
|
|
Packit |
1fb8d4 |
(RdpgfxClientContext*) e->pInterface);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
else
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_WARN(TAG, "GFX without software GDI requested. "
|
|
Packit |
1fb8d4 |
" This is not supported, add /gdi:sw");
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
android_cliprdr_init(afc, (CliprdrClientContext*) e->pInterface);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static void android_OnChannelDisconnectedEventHandler(
|
|
Packit |
1fb8d4 |
void* context, ChannelDisconnectedEventArgs* e)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
rdpSettings* settings;
|
|
Packit |
1fb8d4 |
androidContext* afc;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!context || !e)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p",
|
|
Packit |
1fb8d4 |
__FUNCTION__, context, (void*) e);
|
|
Packit |
1fb8d4 |
return;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
afc = (androidContext*) context;
|
|
Packit |
1fb8d4 |
settings = afc->rdpCtx.settings;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (settings->SoftwareGdi)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
gdi_graphics_pipeline_uninit(afc->rdpCtx.gdi,
|
|
Packit |
1fb8d4 |
(RdpgfxClientContext*) e->pInterface);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
else
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_WARN(TAG, "GFX without software GDI requested. "
|
|
Packit |
1fb8d4 |
" This is not supported, add /gdi:sw");
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
android_cliprdr_uninit(afc, (CliprdrClientContext*) e->pInterface);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_begin_paint(rdpContext* context)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
rdpGdi* gdi;
|
|
Packit |
1fb8d4 |
HGDI_WND hwnd;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!context)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
gdi = context->gdi;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!gdi || !gdi->primary || !gdi->primary->hdc)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
hwnd = gdi->primary->hdc->hwnd;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!hwnd || !hwnd->invalid)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
hwnd->invalid->null = TRUE;
|
|
Packit |
1fb8d4 |
hwnd->ninvalid = 0;
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_end_paint(rdpContext* context)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
int i;
|
|
Packit |
1fb8d4 |
HGDI_WND hwnd;
|
|
Packit |
1fb8d4 |
int ninvalid;
|
|
Packit |
1fb8d4 |
rdpGdi* gdi;
|
|
Packit |
1fb8d4 |
HGDI_RGN cinvalid;
|
|
Packit |
1fb8d4 |
int x1, y1, x2, y2;
|
|
Packit |
1fb8d4 |
androidContext* ctx = (androidContext*)context;
|
|
Packit |
1fb8d4 |
rdpSettings* settings;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!ctx || !context->instance)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
settings = context->instance->settings;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!settings)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
gdi = context->gdi;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!gdi || !gdi->primary || !gdi->primary->hdc)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
hwnd = ctx->rdpCtx.gdi->primary->hdc->hwnd;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!hwnd)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
ninvalid = hwnd->ninvalid;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (ninvalid == 0)
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
cinvalid = hwnd->cinvalid;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!cinvalid)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
x1 = cinvalid[0].x;
|
|
Packit |
1fb8d4 |
y1 = cinvalid[0].y;
|
|
Packit |
1fb8d4 |
x2 = cinvalid[0].x + cinvalid[0].w;
|
|
Packit |
1fb8d4 |
y2 = cinvalid[0].y + cinvalid[0].h;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
for (i = 0; i < ninvalid; i++)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
x1 = MIN(x1, cinvalid[i].x);
|
|
Packit |
1fb8d4 |
y1 = MIN(y1, cinvalid[i].y);
|
|
Packit |
1fb8d4 |
x2 = MAX(x2, cinvalid[i].x + cinvalid[i].w);
|
|
Packit |
1fb8d4 |
y2 = MAX(y2, cinvalid[i].y + cinvalid[i].h);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
freerdp_callback("OnGraphicsUpdate", "(JIIII)V", (jlong)context->instance,
|
|
Packit |
1fb8d4 |
x1, y1, x2 - x1, y2 - y1);
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_desktop_resize(rdpContext* context)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!context || !context->instance || !context->settings)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
freerdp_callback("OnGraphicsResize", "(JIII)V",
|
|
Packit |
1fb8d4 |
(jlong)context->instance, context->settings->DesktopWidth,
|
|
Packit |
1fb8d4 |
context->settings->DesktopHeight, context->settings->ColorDepth);
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_pre_connect(freerdp* instance)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
int rc;
|
|
Packit |
1fb8d4 |
rdpSettings* settings;
|
|
Packit |
1fb8d4 |
BOOL bitmap_cache;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!instance)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
settings = instance->settings;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!settings || !settings->OrderSupport)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
bitmap_cache = settings->BitmapCacheEnabled;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_MEMBLT_INDEX] = bitmap_cache;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_MEM3BLT_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = bitmap_cache;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
|
|
Packit |
1fb8d4 |
rc = PubSub_SubscribeChannelConnected(
|
|
Packit |
1fb8d4 |
instance->context->pubSub,
|
|
Packit |
1fb8d4 |
android_OnChannelConnectedEventHandler);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (rc != CHANNEL_RC_OK)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "Could not subscribe to connect event handler [%l08X]", rc);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
rc = PubSub_SubscribeChannelDisconnected(
|
|
Packit |
1fb8d4 |
instance->context->pubSub,
|
|
Packit |
1fb8d4 |
android_OnChannelDisconnectedEventHandler);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (rc != CHANNEL_RC_OK)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "Could not subscribe to disconnect event handler [%l08X]", rc);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!freerdp_client_load_addins(instance->context->channels,
|
|
Packit |
1fb8d4 |
instance->settings))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "Failed to load addins [%l08X]", GetLastError());
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
freerdp_callback("OnPreConnect", "(J)V", (jlong)instance);
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_Pointer_New(rdpContext* context, rdpPointer* pointer)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!context || !pointer || !context->gdi)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static void android_Pointer_Free(rdpContext* context, rdpPointer* pointer)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!context || !pointer)
|
|
Packit |
1fb8d4 |
return;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_Pointer_Set(rdpContext* context,
|
|
Packit |
1fb8d4 |
const rdpPointer* pointer)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!context)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_Pointer_SetPosition(rdpContext* context,
|
|
Packit |
1fb8d4 |
UINT32 x, UINT32 y)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!context)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_Pointer_SetNull(rdpContext* context)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!context)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_Pointer_SetDefault(rdpContext* context)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!context)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_register_pointer(rdpGraphics* graphics)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
rdpPointer pointer;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!graphics)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
pointer.size = sizeof(pointer);
|
|
Packit |
1fb8d4 |
pointer.New = android_Pointer_New;
|
|
Packit |
1fb8d4 |
pointer.Free = android_Pointer_Free;
|
|
Packit |
1fb8d4 |
pointer.Set = android_Pointer_Set;
|
|
Packit |
1fb8d4 |
pointer.SetNull = android_Pointer_SetNull;
|
|
Packit |
1fb8d4 |
pointer.SetDefault = android_Pointer_SetDefault;
|
|
Packit |
1fb8d4 |
pointer.SetPosition = android_Pointer_SetPosition;
|
|
Packit |
1fb8d4 |
graphics_register_pointer(graphics, &pointer);
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_post_connect(freerdp* instance)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
rdpSettings* settings;
|
|
Packit |
1fb8d4 |
rdpUpdate* update;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!instance || !instance->settings || !instance->context || !instance->update)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
update = instance->update;
|
|
Packit |
1fb8d4 |
settings = instance->settings;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!gdi_init(instance, PIXEL_FORMAT_RGBA32))
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!android_register_pointer(instance->context->graphics))
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
instance->update->BeginPaint = android_begin_paint;
|
|
Packit |
1fb8d4 |
instance->update->EndPaint = android_end_paint;
|
|
Packit |
1fb8d4 |
instance->update->DesktopResize = android_desktop_resize;
|
|
Packit |
1fb8d4 |
freerdp_callback("OnSettingsChanged", "(JIII)V", (jlong)instance,
|
|
Packit |
1fb8d4 |
settings->DesktopWidth, settings->DesktopHeight,
|
|
Packit |
1fb8d4 |
settings->ColorDepth);
|
|
Packit |
1fb8d4 |
freerdp_callback("OnConnectionSuccess", "(J)V", (jlong)instance);
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static void android_post_disconnect(freerdp* instance)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
freerdp_callback("OnDisconnecting", "(J)V", (jlong)instance);
|
|
Packit |
1fb8d4 |
gdi_free(instance);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_authenticate_int(freerdp* instance, char** username,
|
|
Packit |
1fb8d4 |
char** password, char** domain, const char* cb_name)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
JNIEnv* env;
|
|
Packit |
1fb8d4 |
jboolean attached = jni_attach_thread(&env;;
|
|
Packit |
1fb8d4 |
jobject jstr1 = create_string_builder(env, *username);
|
|
Packit |
1fb8d4 |
jobject jstr2 = create_string_builder(env, *domain);
|
|
Packit |
1fb8d4 |
jobject jstr3 = create_string_builder(env, *password);
|
|
Packit |
1fb8d4 |
jboolean res;
|
|
Packit |
1fb8d4 |
res = freerdp_callback_bool_result(
|
|
Packit |
1fb8d4 |
cb_name,
|
|
Packit |
1fb8d4 |
"(JLjava/lang/StringBuilder;"
|
|
Packit |
1fb8d4 |
"Ljava/lang/StringBuilder;"
|
|
Packit |
1fb8d4 |
"Ljava/lang/StringBuilder;)Z",
|
|
Packit |
1fb8d4 |
(jlong)instance, jstr1, jstr2, jstr3);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (res == JNI_TRUE)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
// read back string values
|
|
Packit |
1fb8d4 |
free(*username);
|
|
Packit |
1fb8d4 |
*username = get_string_from_string_builder(env, jstr1);
|
|
Packit |
1fb8d4 |
free(*domain);
|
|
Packit |
1fb8d4 |
*domain = get_string_from_string_builder(env, jstr2);
|
|
Packit |
1fb8d4 |
free(*password);
|
|
Packit |
1fb8d4 |
*password = get_string_from_string_builder(env, jstr3);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (attached == JNI_TRUE)
|
|
Packit |
1fb8d4 |
jni_detach_thread();
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return ((res == JNI_TRUE) ? TRUE : FALSE);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_authenticate(freerdp* instance, char** username,
|
|
Packit |
1fb8d4 |
char** password, char** domain)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return android_authenticate_int(instance, username, password, domain,
|
|
Packit |
1fb8d4 |
"OnAuthenticate");
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_gw_authenticate(freerdp* instance, char** username,
|
|
Packit |
1fb8d4 |
char** password, char** domain)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return android_authenticate_int(instance, username, password, domain,
|
|
Packit |
1fb8d4 |
"OnGatewayAuthenticate");
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static DWORD android_verify_certificate(
|
|
Packit |
1fb8d4 |
freerdp* instance, const char* common_name,
|
|
Packit |
1fb8d4 |
const char* subject, const char* issuer,
|
|
Packit |
1fb8d4 |
const char* fingerprint, BOOL host_mismatch)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "Certificate details:");
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "\tSubject: %s", subject);
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "\tIssuer: %s", issuer);
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "\tThumbprint: %s", fingerprint);
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG,
|
|
Packit |
1fb8d4 |
"The above X.509 certificate could not be verified, possibly because you do not have "
|
|
Packit |
1fb8d4 |
"the CA certificate in your certificate store, or the certificate has expired."
|
|
Packit |
1fb8d4 |
"Please look at the OpenSSL documentation on how to add a private CA to the store.\n");
|
|
Packit |
1fb8d4 |
JNIEnv* env;
|
|
Packit |
1fb8d4 |
jboolean attached = jni_attach_thread(&env;;
|
|
Packit |
1fb8d4 |
jstring jstr0 = (*env)->NewStringUTF(env, common_name);
|
|
Packit |
1fb8d4 |
jstring jstr1 = (*env)->NewStringUTF(env, subject);
|
|
Packit |
1fb8d4 |
jstring jstr2 = (*env)->NewStringUTF(env, issuer);
|
|
Packit |
1fb8d4 |
jstring jstr3 = (*env)->NewStringUTF(env, fingerprint);
|
|
Packit |
1fb8d4 |
jint res = freerdp_callback_int_result("OnVerifyCertificate",
|
|
Packit |
1fb8d4 |
"(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)I",
|
|
Packit |
1fb8d4 |
(jlong)instance, jstr0, jstr1, jstr2, jstr3, host_mismatch);
|
|
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 |
static DWORD android_verify_changed_certificate(freerdp* instance,
|
|
Packit |
1fb8d4 |
const char* common_name,
|
|
Packit |
1fb8d4 |
const char* subject,
|
|
Packit |
1fb8d4 |
const char* issuer,
|
|
Packit |
1fb8d4 |
const char* new_fingerprint,
|
|
Packit |
1fb8d4 |
const char* old_subject,
|
|
Packit |
1fb8d4 |
const char* old_issuer,
|
|
Packit |
1fb8d4 |
const char* old_fingerprint)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
JNIEnv* env;
|
|
Packit |
1fb8d4 |
jboolean attached = jni_attach_thread(&env;;
|
|
Packit |
1fb8d4 |
jstring jstr0 = (*env)->NewStringUTF(env, common_name);
|
|
Packit |
1fb8d4 |
jstring jstr1 = (*env)->NewStringUTF(env, subject);
|
|
Packit |
1fb8d4 |
jstring jstr2 = (*env)->NewStringUTF(env, issuer);
|
|
Packit |
1fb8d4 |
jstring jstr3 = (*env)->NewStringUTF(env, new_fingerprint);
|
|
Packit |
1fb8d4 |
jstring jstr4 = (*env)->NewStringUTF(env, old_subject);
|
|
Packit |
1fb8d4 |
jstring jstr5 = (*env)->NewStringUTF(env, old_issuer);
|
|
Packit |
1fb8d4 |
jstring jstr6 = (*env)->NewStringUTF(env, old_fingerprint);
|
|
Packit |
1fb8d4 |
jint res = freerdp_callback_int_result("OnVerifyChangedCertificate",
|
|
Packit |
1fb8d4 |
"(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;"
|
|
Packit |
1fb8d4 |
"Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
|
|
Packit |
1fb8d4 |
(jlong)instance, jstr0, jstr1, jstr2, jstr3, jstr4, jstr5, jstr6);
|
|
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 |
static DWORD WINAPI jni_input_thread(LPVOID arg)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
HANDLE event[2];
|
|
Packit |
1fb8d4 |
wMessageQueue* queue;
|
|
Packit |
1fb8d4 |
freerdp* instance = (freerdp*) arg;
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "input_thread Start.");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!(queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE)))
|
|
Packit |
1fb8d4 |
goto disconnect;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!(event[0] = android_get_handle(instance)))
|
|
Packit |
1fb8d4 |
goto disconnect;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!(event[1] = freerdp_get_message_queue_event_handle(instance,
|
|
Packit |
1fb8d4 |
FREERDP_INPUT_MESSAGE_QUEUE)))
|
|
Packit |
1fb8d4 |
goto disconnect;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
do
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
DWORD rc = WaitForMultipleObjects(2, event, FALSE, INFINITE);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((rc < WAIT_OBJECT_0) || (rc > WAIT_OBJECT_0 + 1))
|
|
Packit |
1fb8d4 |
continue;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (rc == WAIT_OBJECT_0 + 1)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
wMessage msg;
|
|
Packit |
1fb8d4 |
MessageQueue_Peek(queue, &msg, FALSE);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (msg.id == WMQ_QUIT)
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (android_check_handle(instance) != TRUE)
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
while (1);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "input_thread Quit.");
|
|
Packit |
1fb8d4 |
disconnect:
|
|
Packit |
1fb8d4 |
MessageQueue_PostQuit(queue, 0);
|
|
Packit |
1fb8d4 |
ExitThread(0);
|
|
Packit |
1fb8d4 |
return 0;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static int android_freerdp_run(freerdp* instance)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
DWORD count;
|
|
Packit |
1fb8d4 |
DWORD status = WAIT_FAILED;
|
|
Packit |
1fb8d4 |
HANDLE handles[64];
|
|
Packit |
1fb8d4 |
HANDLE inputEvent = NULL;
|
|
Packit |
1fb8d4 |
HANDLE inputThread = NULL;
|
|
Packit |
1fb8d4 |
const rdpSettings* settings = instance->context->settings;
|
|
Packit |
1fb8d4 |
rdpContext* context = instance->context;
|
|
Packit |
1fb8d4 |
BOOL async_input = settings->AsyncInput;
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "AsyncInput=%"PRIu8"", settings->AsyncInput);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (async_input)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!(inputThread = CreateThread(NULL, 0, jni_input_thread, instance, 0, NULL)))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "async input: failed to create input thread");
|
|
Packit |
1fb8d4 |
goto disconnect;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
else
|
|
Packit |
1fb8d4 |
inputEvent = android_get_handle(instance);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
while (!freerdp_shall_disconnect(instance))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
DWORD tmp;
|
|
Packit |
1fb8d4 |
count = 0;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (inputThread)
|
|
Packit |
1fb8d4 |
handles[count++] = inputThread;
|
|
Packit |
1fb8d4 |
else
|
|
Packit |
1fb8d4 |
handles[count++] = inputEvent;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
tmp = freerdp_get_event_handles(context, &handles[count], 64 - count);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (tmp == 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "freerdp_get_event_handles failed");
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
count += tmp;
|
|
Packit |
1fb8d4 |
status = WaitForMultipleObjects(count, handles, FALSE, INFINITE);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((status == WAIT_FAILED))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "WaitForMultipleObjects failed with %"PRIu32" [%08lX]", status, GetLastError());
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!freerdp_check_event_handles(context))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
/* TODO: Auto reconnect
|
|
Packit |
1fb8d4 |
if (xf_auto_reconnect(instance))
|
|
Packit |
1fb8d4 |
continue;
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
|
|
Packit |
1fb8d4 |
status = GetLastError();
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (freerdp_shall_disconnect(instance))
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!async_input)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (android_check_handle(instance) != TRUE)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "Failed to check android file descriptor");
|
|
Packit |
1fb8d4 |
status = GetLastError();
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
disconnect:
|
|
Packit |
1fb8d4 |
WLog_INFO(TAG, "Prepare shutdown...");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (async_input && inputThread)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WaitForSingleObject(inputThread, INFINITE);
|
|
Packit |
1fb8d4 |
CloseHandle(inputThread);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return status;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static DWORD WINAPI android_thread_func(LPVOID param)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
DWORD status = ERROR_BAD_ARGUMENTS;
|
|
Packit |
1fb8d4 |
freerdp* instance = param;
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "Start...");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!instance || !instance->context)
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (freerdp_client_start(instance->context) != CHANNEL_RC_OK)
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "Connect...");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!freerdp_connect(instance))
|
|
Packit |
1fb8d4 |
status = GetLastError();
|
|
Packit |
1fb8d4 |
else
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
status = android_freerdp_run(instance);
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "Disonnect...");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!freerdp_disconnect(instance))
|
|
Packit |
1fb8d4 |
status = GetLastError();
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "Stop...");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (freerdp_client_stop(instance->context) != CHANNEL_RC_OK)
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
fail:
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "Session ended with %08"PRIX32"", status);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (status == CHANNEL_RC_OK)
|
|
Packit |
1fb8d4 |
freerdp_callback("OnDisconnected", "(J)V", (jlong)instance);
|
|
Packit |
1fb8d4 |
else
|
|
Packit |
1fb8d4 |
freerdp_callback("OnConnectionFailure", "(J)V", (jlong)instance);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "Quit.");
|
|
Packit |
1fb8d4 |
ExitThread(status);
|
|
Packit |
1fb8d4 |
return status;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL android_client_new(freerdp* instance, rdpContext* context)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!instance || !context)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!android_event_queue_init(instance))
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
instance->PreConnect = android_pre_connect;
|
|
Packit |
1fb8d4 |
instance->PostConnect = android_post_connect;
|
|
Packit |
1fb8d4 |
instance->PostDisconnect = android_post_disconnect;
|
|
Packit |
1fb8d4 |
instance->Authenticate = android_authenticate;
|
|
Packit |
1fb8d4 |
instance->GatewayAuthenticate = android_gw_authenticate;
|
|
Packit |
1fb8d4 |
instance->VerifyCertificate = android_verify_certificate;
|
|
Packit |
1fb8d4 |
instance->VerifyChangedCertificate = android_verify_changed_certificate;
|
|
Packit |
1fb8d4 |
instance->LogonErrorInfo = NULL;
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static void android_client_free(freerdp* instance, rdpContext* context)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!context)
|
|
Packit |
1fb8d4 |
return;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
android_event_queue_uninit(instance);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
ZeroMemory(pEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS));
|
|
Packit |
1fb8d4 |
pEntryPoints->Version = RDP_CLIENT_INTERFACE_VERSION;
|
|
Packit |
1fb8d4 |
pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
|
|
Packit |
1fb8d4 |
pEntryPoints->GlobalInit = NULL;
|
|
Packit |
1fb8d4 |
pEntryPoints->GlobalUninit = NULL;
|
|
Packit |
1fb8d4 |
pEntryPoints->ContextSize = sizeof(androidContext);
|
|
Packit |
1fb8d4 |
pEntryPoints->ClientNew = android_client_new;
|
|
Packit |
1fb8d4 |
pEntryPoints->ClientFree = android_client_free;
|
|
Packit |
1fb8d4 |
pEntryPoints->ClientStart = NULL;
|
|
Packit |
1fb8d4 |
pEntryPoints->ClientStop = NULL;
|
|
Packit |
1fb8d4 |
return 0;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jlong JNICALL jni_freerdp_new(JNIEnv* env, jclass cls, jobject context)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
jclass contextClass;
|
|
Packit |
1fb8d4 |
jclass fileClass;
|
|
Packit |
1fb8d4 |
jobject filesDirObj;
|
|
Packit |
1fb8d4 |
jmethodID getFilesDirID;
|
|
Packit |
1fb8d4 |
jmethodID getAbsolutePathID;
|
|
Packit |
1fb8d4 |
jstring path;
|
|
Packit |
1fb8d4 |
const char* raw;
|
|
Packit |
1fb8d4 |
char* envStr;
|
|
Packit |
1fb8d4 |
RDP_CLIENT_ENTRY_POINTS clientEntryPoints;
|
|
Packit |
1fb8d4 |
rdpContext* ctx;
|
|
Packit |
1fb8d4 |
#if defined(WITH_GPROF)
|
|
Packit |
1fb8d4 |
setenv("CPUPROFILE_FREQUENCY", "200", 1);
|
|
Packit |
1fb8d4 |
monstartup("libfreerdp-android.so");
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
contextClass = (*env)->FindClass(env, JAVA_CONTEXT_CLASS);
|
|
Packit |
1fb8d4 |
fileClass = (*env)->FindClass(env, JAVA_FILE_CLASS);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!contextClass || !fileClass)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "Failed to load class references %s=%p, %s=%p",
|
|
Packit |
1fb8d4 |
JAVA_CONTEXT_CLASS, (void*) contextClass, JAVA_FILE_CLASS, (void*) fileClass);
|
|
Packit |
1fb8d4 |
return (jlong)NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
getFilesDirID = (*env)->GetMethodID(env, contextClass, "getFilesDir",
|
|
Packit |
1fb8d4 |
"()L"JAVA_FILE_CLASS";");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!getFilesDirID)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "Failed to find method ID getFilesDir ()L"JAVA_FILE_CLASS";");
|
|
Packit |
1fb8d4 |
return (jlong)NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
getAbsolutePathID = (*env)->GetMethodID(env, fileClass, "getAbsolutePath",
|
|
Packit |
1fb8d4 |
"()Ljava/lang/String;");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!getAbsolutePathID)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG,
|
|
Packit |
1fb8d4 |
"Failed to find method ID getAbsolutePath ()Ljava/lang/String;");
|
|
Packit |
1fb8d4 |
return (jlong)NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
filesDirObj = (*env)->CallObjectMethod(env, context, getFilesDirID);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!filesDirObj)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "Failed to call getFilesDir");
|
|
Packit |
1fb8d4 |
return (jlong)NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
path = (*env)->CallObjectMethod(env, filesDirObj, getAbsolutePathID);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!path)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "Failed to call getAbsolutePath");
|
|
Packit |
1fb8d4 |
return (jlong)NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
raw = (*env)->GetStringUTFChars(env, path, 0);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!raw)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "Failed to get C string from java string");
|
|
Packit |
1fb8d4 |
return (jlong)NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
envStr = _strdup(raw);
|
|
Packit |
1fb8d4 |
(*env)->ReleaseStringUTFChars(env, path, raw);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!envStr)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "_strdup(%s) failed", raw);
|
|
Packit |
1fb8d4 |
return (jlong)NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (setenv("HOME", _strdup(envStr), 1) != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "Failed to set environemnt HOME=%s %s [%d]",
|
|
Packit |
1fb8d4 |
env, strerror(errno), errno);
|
|
Packit |
1fb8d4 |
return (jlong)NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
RdpClientEntry(&clientEntryPoints);
|
|
Packit |
1fb8d4 |
ctx = freerdp_client_context_new(&clientEntryPoints);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!ctx)
|
|
Packit |
1fb8d4 |
return (jlong)NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return (jlong) ctx->instance;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static void JNICALL jni_freerdp_free(JNIEnv* env, jclass cls, jlong instance)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
freerdp* inst = (freerdp*)instance;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (inst)
|
|
Packit |
1fb8d4 |
freerdp_client_context_free(inst->context);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#if defined(WITH_GPROF)
|
|
Packit |
1fb8d4 |
moncleanup();
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jboolean JNICALL jni_freerdp_parse_arguments(
|
|
Packit |
1fb8d4 |
JNIEnv* env, jclass cls, jlong instance, jobjectArray arguments)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
freerdp* inst = (freerdp*)instance;
|
|
Packit |
1fb8d4 |
int i, count;
|
|
Packit |
1fb8d4 |
char** argv;
|
|
Packit |
1fb8d4 |
DWORD status;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!inst || !inst->context)
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
count = (*env)->GetArrayLength(env, arguments);
|
|
Packit |
1fb8d4 |
argv = calloc(count, sizeof(char*));
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!argv)
|
|
Packit |
1fb8d4 |
return JNI_TRUE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
for (i = 0; i < count; i++)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
jstring str = (jstring)(*env)->GetObjectArrayElement(env, arguments, i);
|
|
Packit |
1fb8d4 |
const char* raw = (*env)->GetStringUTFChars(env, str, 0);
|
|
Packit |
1fb8d4 |
argv[i] = _strdup(raw);
|
|
Packit |
1fb8d4 |
(*env)->ReleaseStringUTFChars(env, str, raw);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
status = freerdp_client_settings_parse_command_line(inst->settings, count, argv,
|
|
Packit |
1fb8d4 |
FALSE);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
for (i = 0; i < count; i++)
|
|
Packit |
1fb8d4 |
free(argv[i]);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
free(argv);
|
|
Packit |
1fb8d4 |
return (status == 0) ? JNI_TRUE : JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jboolean JNICALL jni_freerdp_connect(JNIEnv* env, jclass cls,
|
|
Packit |
1fb8d4 |
jlong instance)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
freerdp* inst = (freerdp*)instance;
|
|
Packit |
1fb8d4 |
androidContext* ctx;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!inst || !inst->context)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "%s(env=%p, cls=%p, instance=%d", __FUNCTION__,
|
|
Packit |
1fb8d4 |
(void*) env, (void*) cls, instance);
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
ctx = (androidContext*)inst->context;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!(ctx->thread = CreateThread(NULL, 0, android_thread_func,
|
|
Packit |
1fb8d4 |
inst, 0, NULL)))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return JNI_TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jboolean JNICALL jni_freerdp_disconnect(JNIEnv* env, jclass cls,
|
|
Packit |
1fb8d4 |
jlong instance)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
freerdp* inst = (freerdp*)instance;
|
|
Packit |
1fb8d4 |
androidContext* ctx;
|
|
Packit |
1fb8d4 |
ANDROID_EVENT* event;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!inst || !inst->context || !cls || !env)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "%s(env=%p, cls=%p, instance=%d", __FUNCTION__,
|
|
Packit |
1fb8d4 |
(void*) env, (void*) cls, instance);
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
ctx = (androidContext*)inst->context;
|
|
Packit |
1fb8d4 |
event = (ANDROID_EVENT*)android_event_disconnect_new();
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!event)
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!android_push_event(inst, event))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
android_event_free((ANDROID_EVENT*)event);
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!freerdp_abort_connect(inst))
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return JNI_TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jboolean JNICALL jni_freerdp_update_graphics(
|
|
Packit |
1fb8d4 |
JNIEnv* env, jclass cls, jlong instance, jobject bitmap,
|
|
Packit |
1fb8d4 |
jint x, jint y, jint width, jint height)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
UINT32 DstFormat;
|
|
Packit |
1fb8d4 |
jboolean rc;
|
|
Packit |
1fb8d4 |
int ret;
|
|
Packit |
1fb8d4 |
void* pixels;
|
|
Packit |
1fb8d4 |
AndroidBitmapInfo info;
|
|
Packit |
1fb8d4 |
freerdp* inst = (freerdp*)instance;
|
|
Packit |
1fb8d4 |
rdpGdi* gdi;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!env || !cls || !inst)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "%s(env=%p, cls=%p, instance=%d", __FUNCTION__,
|
|
Packit |
1fb8d4 |
(void*) env, (void*) cls, instance);
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
gdi = inst->context->gdi;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "AndroidBitmap_getInfo() failed ! error=%d", ret);
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "AndroidBitmap_lockPixels() failed ! error=%d", ret);
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
rc = JNI_TRUE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
switch (info.format)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
case ANDROID_BITMAP_FORMAT_RGBA_8888:
|
|
Packit |
1fb8d4 |
DstFormat = PIXEL_FORMAT_RGBA32;
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
case ANDROID_BITMAP_FORMAT_RGB_565:
|
|
Packit |
1fb8d4 |
DstFormat = PIXEL_FORMAT_RGB16;
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
case ANDROID_BITMAP_FORMAT_RGBA_4444:
|
|
Packit |
1fb8d4 |
case ANDROID_BITMAP_FORMAT_A_8:
|
|
Packit |
1fb8d4 |
case ANDROID_BITMAP_FORMAT_NONE:
|
|
Packit |
1fb8d4 |
default:
|
|
Packit |
1fb8d4 |
rc = JNI_FALSE;
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (rc)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
rc = freerdp_image_copy(pixels, DstFormat, info.stride, x, y, width, height,
|
|
Packit |
1fb8d4 |
gdi->primary_buffer, gdi->dstFormat, gdi->stride, x, y,
|
|
Packit |
1fb8d4 |
&gdi->palette, FREERDP_FLIP_NONE);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((ret = AndroidBitmap_unlockPixels(env, bitmap)) < 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "AndroidBitmap_unlockPixels() failed ! error=%d", ret);
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return rc;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jboolean JNICALL jni_freerdp_send_key_event(
|
|
Packit |
1fb8d4 |
JNIEnv* env, jclass cls, jlong instance,
|
|
Packit |
1fb8d4 |
jint keycode, jboolean down)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
DWORD scancode;
|
|
Packit |
1fb8d4 |
ANDROID_EVENT* event;
|
|
Packit |
1fb8d4 |
freerdp* inst = (freerdp*)instance;
|
|
Packit |
1fb8d4 |
scancode = GetVirtualScanCodeFromVirtualKeyCode(keycode, 4);
|
|
Packit |
1fb8d4 |
int flags = (down == JNI_TRUE) ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE;
|
|
Packit |
1fb8d4 |
flags |= (scancode & KBDEXT) ? KBD_FLAGS_EXTENDED : 0;
|
|
Packit |
1fb8d4 |
event = (ANDROID_EVENT*) android_event_key_new(flags, scancode & 0xFF);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!event)
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!android_push_event(inst, event))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
android_event_free(event);
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "send_key_event: %"PRIu32", %d", scancode, flags);
|
|
Packit |
1fb8d4 |
return JNI_TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jboolean JNICALL jni_freerdp_send_unicodekey_event(
|
|
Packit |
1fb8d4 |
JNIEnv* env, jclass cls, jlong instance, jint keycode)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
ANDROID_EVENT* event;
|
|
Packit |
1fb8d4 |
freerdp* inst = (freerdp*)instance;
|
|
Packit |
1fb8d4 |
event = (ANDROID_EVENT*) android_event_unicodekey_new(keycode);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!event)
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!android_push_event(inst, event))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
android_event_free(event);
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "send_unicodekey_event: %d", keycode);
|
|
Packit |
1fb8d4 |
return JNI_TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jboolean JNICALL jni_freerdp_send_cursor_event(
|
|
Packit |
1fb8d4 |
JNIEnv* env, jclass cls, jlong instance, jint x, jint y, jint flags)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
ANDROID_EVENT* event;
|
|
Packit |
1fb8d4 |
freerdp* inst = (freerdp*)instance;
|
|
Packit |
1fb8d4 |
event = (ANDROID_EVENT*) android_event_cursor_new(flags, x, y);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!event)
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!android_push_event(inst, event))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
android_event_free(event);
|
|
Packit |
1fb8d4 |
return JNI_FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "send_cursor_event: (%d, %d), %d", x, y, flags);
|
|
Packit |
1fb8d4 |
return JNI_TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jboolean JNICALL jni_freerdp_send_clipboard_data(
|
|
Packit |
1fb8d4 |
JNIEnv* env, jclass cls,
|
|
Packit |
1fb8d4 |
jlong instance, jstring jdata)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
ANDROID_EVENT* event;
|
|
Packit |
1fb8d4 |
freerdp* inst = (freerdp*)instance;
|
|
Packit |
1fb8d4 |
const jbyte* data = jdata != NULL ? (*env)->GetStringUTFChars(env, jdata,
|
|
Packit |
1fb8d4 |
NULL) : NULL;
|
|
Packit |
1fb8d4 |
int data_length = data ? strlen(data) : 0;
|
|
Packit |
1fb8d4 |
jboolean ret = JNI_FALSE;;
|
|
Packit |
1fb8d4 |
event = (ANDROID_EVENT*) android_event_clipboard_new((void*)data, data_length);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!event)
|
|
Packit |
1fb8d4 |
goto out_fail;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!android_push_event(inst, event))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
android_event_free(event);
|
|
Packit |
1fb8d4 |
goto out_fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "send_clipboard_data: (%s)", data);
|
|
Packit |
1fb8d4 |
ret = JNI_TRUE;
|
|
Packit |
1fb8d4 |
out_fail:
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (data)
|
|
Packit |
1fb8d4 |
(*env)->ReleaseStringUTFChars(env, jdata, data);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return ret;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jstring JNICALL jni_freerdp_get_jni_version(JNIEnv* env, jclass cls)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return (*env)->NewStringUTF(env, FREERDP_JNI_VERSION);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jstring JNICALL jni_freerdp_get_version(JNIEnv* env, jclass cls)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return (*env)->NewStringUTF(env, freerdp_get_version_string());
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jstring JNICALL jni_freerdp_get_build_date(JNIEnv* env, jclass cls)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return (*env)->NewStringUTF(env, freerdp_get_build_date());
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jstring JNICALL jni_freerdp_get_build_revision(JNIEnv* env, jclass cls)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return (*env)->NewStringUTF(env, freerdp_get_build_revision());
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jstring JNICALL jni_freerdp_get_build_config(JNIEnv* env, jclass cls)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return (*env)->NewStringUTF(env, freerdp_get_build_config());
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static JNINativeMethod methods[] =
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_get_jni_version",
|
|
Packit |
1fb8d4 |
"()Ljava/lang/String;",
|
|
Packit |
1fb8d4 |
&jni_freerdp_get_jni_version
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_get_version",
|
|
Packit |
1fb8d4 |
"()Ljava/lang/String;",
|
|
Packit |
1fb8d4 |
&jni_freerdp_get_version
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_get_build_date",
|
|
Packit |
1fb8d4 |
"()Ljava/lang/String;",
|
|
Packit |
1fb8d4 |
&jni_freerdp_get_build_date
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_get_build_revision",
|
|
Packit |
1fb8d4 |
"()Ljava/lang/String;",
|
|
Packit |
1fb8d4 |
&jni_freerdp_get_build_revision
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_get_build_config",
|
|
Packit |
1fb8d4 |
"()Ljava/lang/String;",
|
|
Packit |
1fb8d4 |
&jni_freerdp_get_build_config
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_new",
|
|
Packit |
1fb8d4 |
"(Landroid/content/Context;)J",
|
|
Packit |
1fb8d4 |
&jni_freerdp_new
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_free",
|
|
Packit |
1fb8d4 |
"(J)V",
|
|
Packit |
1fb8d4 |
&jni_freerdp_free
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_parse_arguments",
|
|
Packit |
1fb8d4 |
"(J[Ljava/lang/String;)Z",
|
|
Packit |
1fb8d4 |
&jni_freerdp_parse_arguments
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_connect",
|
|
Packit |
1fb8d4 |
"(J)Z",
|
|
Packit |
1fb8d4 |
&jni_freerdp_connect
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_disconnect",
|
|
Packit |
1fb8d4 |
"(J)Z",
|
|
Packit |
1fb8d4 |
&jni_freerdp_disconnect
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_update_graphics",
|
|
Packit |
1fb8d4 |
"(JLandroid/graphics/Bitmap;IIII)Z",
|
|
Packit |
1fb8d4 |
&jni_freerdp_update_graphics
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_send_cursor_event",
|
|
Packit |
1fb8d4 |
"(JIII)Z",
|
|
Packit |
1fb8d4 |
&jni_freerdp_send_cursor_event
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_send_key_event",
|
|
Packit |
1fb8d4 |
"(JIZ)Z",
|
|
Packit |
1fb8d4 |
&jni_freerdp_send_key_event
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_send_unicodekey_event",
|
|
Packit |
1fb8d4 |
"(JI)Z",
|
|
Packit |
1fb8d4 |
&jni_freerdp_send_unicodekey_event
|
|
Packit |
1fb8d4 |
},
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
"freerdp_send_clipboard_data",
|
|
Packit |
1fb8d4 |
"(JLjava/lang/String;)Z",
|
|
Packit |
1fb8d4 |
&jni_freerdp_send_clipboard_data
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
};
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static jclass gJavaActivityClass = NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
JNIEnv* env;
|
|
Packit |
1fb8d4 |
setlocale(LC_ALL, "");
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "Setting up JNI environement...");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/*
|
|
Packit |
1fb8d4 |
if (freerdp_handle_signals() != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "Failed to register signal handler");
|
|
Packit |
1fb8d4 |
return -1;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "Failed to get the environment");
|
|
Packit |
1fb8d4 |
return -1;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
// Get SBCEngine activity class
|
|
Packit |
1fb8d4 |
jclass activityClass = (*env)->FindClass(env, JAVA_LIBFREERDP_CLASS);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!activityClass)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "failed to get %s class reference", JAVA_LIBFREERDP_CLASS);
|
|
Packit |
1fb8d4 |
return -1;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
// Register methods with env->RegisterNatives.
|
|
Packit |
1fb8d4 |
(*env)->RegisterNatives(env, activityClass, methods,
|
|
Packit |
1fb8d4 |
sizeof(methods) / sizeof(methods[0]));
|
|
Packit |
1fb8d4 |
/* create global reference for class */
|
|
Packit |
1fb8d4 |
gJavaActivityClass = (*env)->NewGlobalRef(env, activityClass);
|
|
Packit |
1fb8d4 |
g_JavaVm = vm;
|
|
Packit |
1fb8d4 |
return init_callback_environment(vm, env);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
JNIEnv* env;
|
|
Packit |
1fb8d4 |
WLog_DBG(TAG, "Tearing down JNI environement...");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "Failed to get the environment");
|
|
Packit |
1fb8d4 |
return;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
(*env)->UnregisterNatives(env, gJavaActivityClass);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (gJavaActivityClass)
|
|
Packit |
1fb8d4 |
(*env)->DeleteGlobalRef(env, gJavaActivityClass);
|
|
Packit |
1fb8d4 |
}
|