Merge branch 'master' of github.com:FreeRDP/FreeRDP

This commit is contained in:
Marc-André Moreau
2013-11-12 12:59:41 -05:00
38 changed files with 1041 additions and 280 deletions

View File

@@ -273,7 +273,11 @@ endif(APPLE)
if(ANDROID)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
add_definitions(-DNDK_DEBUG=1)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG}")
# NOTE: Manually add -gdwarf-3, as newer toolchains default to -gdwarf-4,
# which is not supported by the gdbserver binary shipped with
# the android NDK (tested with r9b)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG} -gdwarf-3")
endif()
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -llog")
if (NOT FREERDP_ANDROID_EXTERNAL_SSL_PATH)
@@ -294,9 +298,12 @@ if(ANDROID)
endif()
endif()
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_ANDROID_EXTERNAL_SSL_PATH})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/client/Android/FreeRDPCore/libs/${ANDROID_ABI})
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/scripts/regenerate_jni_headers.sh.cmake
${CMAKE_CURRENT_SOURCE_DIR}/scripts/regenerate_jni_headers.sh @ONLY)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/client/Android/FreeRDPCore/jni/${ANDROID_ABI})
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/regenerate_jni_headers.sh.cmake
${CMAKE_BINARY_DIR}/scripts/regenerate_jni_headers.sh @ONLY)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/gprof_generate.sh.cmake
${CMAKE_BINARY_DIR}/scripts/gprof_generate.sh @ONLY)
endif()
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)

View File

@@ -335,6 +335,16 @@ int freerdp_channels_global_init(void)
int freerdp_channels_global_uninit(void)
{
EnterCriticalSection(&g_channels_lock);
DeleteCriticalSection(&g_channels_lock);
if (g_ChannelsList)
{
ArrayList_Lock(g_ChannelsList);
ArrayList_Free(g_ChannelsList);
g_ChannelsList = NULL;
}
return 0;
}
@@ -356,7 +366,9 @@ void freerdp_channels_free(rdpChannels* channels)
{
MessagePipe_Free(channels->MsgPipe);
/* TODO: remove from channels list */
ArrayList_Lock(g_ChannelsList);
ArrayList_Remove(g_ChannelsList, channels);
ArrayList_Unlock(g_ChannelsList);
free(channels);
}
@@ -496,8 +508,8 @@ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
{
int index;
char* name;
char* hostname;
int hostnameLength;
char* hostname;
int hostnameLength;
CHANNEL_CLIENT_DATA* pChannelClientData;
channels->is_connected = 1;

View File

@@ -661,7 +661,7 @@ void drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
drive->files = ListDictionary_New(TRUE);
ListDictionary_Object(drive->files)->fnObjectFree = (OBJECT_FREE_FN) drive_file_free;
drive->IrpQueue = MessageQueue_New();
drive->IrpQueue = MessageQueue_New(NULL);
drive->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_thread_func, drive, CREATE_SUSPENDED, NULL);
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) drive);
@@ -735,8 +735,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
if (*dev > 'B')
{
/* Suppress disk drives A and B to avoid pesty messages */
_snprintf(buf, sizeof(buf) - 4, "%s", drive->Name);
len = strlen(buf);
len = _snprintf(buf, sizeof(buf) - 4, "%s", drive->Name);
buf[len] = '_';
buf[len + 1] = dev[0];
buf[len + 2] = 0;

View File

@@ -327,7 +327,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
parallel->path = path;
parallel->queue = MessageQueue_New();
parallel->queue = MessageQueue_New(NULL);
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) parallel);

View File

@@ -930,8 +930,6 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
{
MessagePipe_PostQuit(rdpsnd->MsgPipe, 0);
WaitForSingleObject(rdpsnd->thread, INFINITE);
MessagePipe_Free(rdpsnd->MsgPipe);
CloseHandle(rdpsnd->thread);
rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle);

View File

@@ -15,8 +15,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
set(ANDROID_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/aFreeRDP")
if (NOT ANDROID_NDK)
message(FATAL_ERROR "ANDROID_NDK not set but required for building android native library.")
endif()
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH)
find_program(NDK_COMMAND ndk-build)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, ONLY)
if(NDK_COMMAND STREQUAL "ANT_COMMAND-NOTFOUND")
message(FATAL_ERROR "ndk-build not found but required to build native lib")
endif()
set(NDK_LIB_CFG "${CMAKE_CURRENT_BINARY_DIR}/FreeRDPCore/jni/Android.mk")
if(ANDROID_BUILD_JAVA)
if (NOT ANDROID_SDK)
message(FATAL_ERROR "ANDROID_SDK not set but required for building the java gui (ANDROID_BUILD_JAVA)")
@@ -30,18 +41,20 @@ if(ANDROID_BUILD_JAVA)
if(ANT_COMMAND STREQUAL "ANT_COMMAND-NOTFOUND")
message(FATAL_ERROR "ant not found but required to build android java")
endif()
if(ANDROID_BUILD_JAVA_DEBUG)
set(ANDROID_BUILD_TYPE "debug")
else()
set(ANDROID_BUILD_TYPE "release")
endif()
endif(ANDROID_BUILD_JAVA)
if(ANDROID_BUILD_JAVA_DEBUG)
set(ANDROID_BUILD_TYPE "debug")
else()
set(ANDROID_BUILD_TYPE "release")
endif()
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set(ANDROID_DEBUG_ENABLE "true")
set(NDK_DEBUG "1")
else()
set(ANDROID_DEBUG_ENABLE "false")
set(NDK_DEBUG "0")
endif()
add_subdirectory(FreeRDPCore)

View File

@@ -5,6 +5,16 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.cdt.managedbuilder.core.genmakebuilder.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
@@ -25,9 +35,19 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>

View File

@@ -3,19 +3,29 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
package="com.freerdp.freerdpcore"
android:versionCode="2"
android:versionCode="@ANDROID_APP_VERSION@"
android:versionName="@GIT_REVISION@" >
<uses-sdk android:targetSdkVersion="@ANDROID_APP_TARGET_SDK@" android:minSdkVersion="@ANDROID_APP_MIN_SDK@"/>
<uses-sdk
android:targetSdkVersion="@ANDROID_APP_TARGET_SDK@"
android:minSdkVersion="@ANDROID_APP_MIN_SDK@"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<supports-screens android:anyDensity="true" android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" />
<supports-screens
android:anyDensity="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true" />
<application>
<application
android:debuggable="@ANDROID_DEBUG_ENABLE@">
<!-- Activity to create shortcuts -->
<activity android:name=".presentation.ShortcutsActivity"

View File

@@ -17,7 +17,6 @@
# limitations under the License.
set(ANDROID_PACKAGE_NAME "aFreeRDPCore")
file(MAKE_DIRECTORY ${ANDROID_BINARY_DIR})
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake
${CMAKE_CURRENT_BINARY_DIR}/AndroidManifest.xml @ONLY)
@@ -45,20 +44,5 @@ endif()
add_subdirectory(jni)
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin;obj;libs")
if(ANDROID_BUILD_JAVA)
file(MAKE_DIRECTORY "${ANDROID_BINARY_DIR}/bin")
set(ANDROIDLIB "${ANDROID_BINARY_DIR}/bin/classes.jar")
# command to create the android package
add_custom_command(
OUTPUT "${ANDROIDLIB}"
COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE}
WORKING_DIRECTORY "${ANDROID_BINARY_DIR}"
MAIN_DEPENDENCY AndroidManifest.xml
DEPENDS freerdp-android
${CMAKE_CURRENT_BINARY_DIR}/local.properties
)
add_custom_target(android-lib ALL SOURCES "${ANDROIDLIB}")
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin")
endif()

View File

@@ -0,0 +1,8 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := freerdp-android
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfreerdp-android.so
LOCAL_EXPORT_C_INCLUDES := ../../../../include
include $(PREBUILT_SHARED_LIBRARY)

View File

@@ -0,0 +1 @@
APP_ABI := @ANDROID_ABI@

View File

@@ -19,10 +19,14 @@
set(MODULE_NAME "freerdp-android")
set(MODULE_PREFIX "FREERDP_CLIENT_ANDROID")
include_directories(.)
include_directories(generated)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Application.mk.cmake
${CMAKE_CURRENT_BINARY_DIR}/Application.mk @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Android.mk.cmake
${CMAKE_CURRENT_BINARY_DIR}/Android.mk @ONLY)
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-sign")
endif()
@@ -68,16 +72,11 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} jnigraphics)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_ABI}")
set_target_properties(${MODULE_NAME}
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${ANDROID_BINARY_DIR}/libs/${ANDROID_ABI}")
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_ABI}")
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Android")
get_property(LIB_ABSNAME TARGET ${MODULE_NAME} PROPERTY LOCATION)
file(MAKE_DIRECTORY ${ANDROID_BINARY_DIR}/obj/local/${ANDROID_NDK_ABI_NAME})
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${LIB_ABSNAME}
${ANDROID_BINARY_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/)

View File

@@ -16,19 +16,15 @@
#include "config.h"
#endif
#include <android/log.h>
#define TAG "LibFreeRDP"
#define DEBUG_ANDROID_NULL(fmt, ...) do { } while (0)
#define DEBUG_ANDROID_PRINT(_dbg_str, fmt, ...) __android_log_print(ANDROID_LOG_INFO, TAG, _dbg_str fmt "\n" , __FUNCTION__, __LINE__, ## __VA_ARGS__)
#define DEBUG_ANDROID_CLASS(_dbg_class, fmt, ...) DEBUG_ANDROID_PRINT("DBG_" #_dbg_class " %s (%d): ", fmt, ## __VA_ARGS__)
#include <freerdp/utils/debug.h>
#ifdef WITH_DEBUG_ANDROID_JNI
#define DEBUG_ANDROID(fmt, ...) DEBUG_ANDROID_PRINT("DBG %s (%d): ", fmt, ## __VA_ARGS__)
#define DEBUG_ANDROID(fmt, ...) DEBUG_CLASS(JNI, fmt, ## __VA_ARGS__)
#else
#define DEBUG_ANDROID(fmt, ...) DEBUG_ANDROID_NULL(fmt, ## __VA_ARGS__)
#define DEBUG_ANDROID(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
#endif /* FREERDP_ANDROID_DEBUG_H */

View File

@@ -28,6 +28,8 @@
#include <freerdp/utils/event.h>
#include <freerdp/constants.h>
#include <freerdp/locale/keyboard.h>
#include <freerdp/primitives.h>
#include <freerdp/version.h>
#include <android/bitmap.h>
@@ -42,12 +44,6 @@
#include "jni/prof.h"
#endif
struct thread_data
{
freerdp* instance;
};
int android_context_new(freerdp* instance, rdpContext* context)
{
context->channels = freerdp_channels_new();
@@ -72,28 +68,33 @@ void android_begin_paint(rdpContext* context)
void android_end_paint(rdpContext* context)
{
androidContext *ctx = (androidContext*)context;
rdpSettings* settings = context->instance->settings;
DEBUG_ANDROID("ui_update");
rdpGdi *gdi = context->gdi;
if (gdi->primary->hdc->hwnd->invalid->null)
return;
assert(ctx);
assert(settings);
assert(context->instance);
int x = gdi->primary->hdc->hwnd->invalid->x;
int y = gdi->primary->hdc->hwnd->invalid->y;
int w = gdi->primary->hdc->hwnd->invalid->w;
int h = gdi->primary->hdc->hwnd->invalid->h;
DEBUG_ANDROID("ui_update: x:%d y:%d w:%d h:%d", x, y, w, h);
freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance, x, y, w, h);
DEBUG_ANDROID("width=%d, height=%d, bpp=%d", settings->DesktopWidth,
settings->DesktopHeight, settings->ColorDepth);
freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance,
0, 0, settings->DesktopWidth, settings->DesktopHeight);
}
void android_desktop_resize(rdpContext* context)
{
DEBUG_ANDROID("ui_desktop_resize");
rdpGdi *gdi = context->gdi;
freerdp_callback("OnGraphicsResize", "(IIII)V", context->instance, gdi->width, gdi->height, gdi->dstBpp);
assert(context);
assert(context->settings);
assert(context->instance);
freerdp_callback("OnGraphicsResize", "(IIII)V",
context->instance, context->settings->DesktopWidth,
context->settings->DesktopHeight, context->settings->ColorDepth);
}
@@ -138,17 +139,24 @@ BOOL android_pre_connect(freerdp* instance)
return TRUE;
}
BOOL android_post_connect(freerdp* instance)
static BOOL android_post_connect(freerdp* instance)
{
rdpSettings *settings = instance->settings;
DEBUG_ANDROID("android_post_connect");
assert(instance);
assert(settings);
freerdp_callback("OnSettingsChanged", "(IIII)V", instance,
instance->settings->DesktopWidth, instance->settings->DesktopHeight,
instance->settings->ColorDepth);
settings->DesktopWidth, settings->DesktopHeight,
settings->ColorDepth);
instance->context->cache = cache_new(instance->settings);
instance->context->cache = cache_new(settings);
gdi_init(instance, CLRCONV_ALPHA | ((instance->settings->ColorDepth > 16) ? CLRBUF_32BPP : CLRBUF_16BPP), NULL);
gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT |
((instance->settings->ColorDepth > 16) ? CLRBUF_32BPP : CLRBUF_16BPP),
NULL);
instance->update->BeginPaint = android_begin_paint;
instance->update->EndPaint = android_end_paint;
@@ -164,6 +172,13 @@ BOOL android_post_connect(freerdp* instance)
return TRUE;
}
static void android_post_disconnect(freerdp* instance)
{
gdi_free(instance);
cache_free(instance->context->cache);
android_cliprdr_uninit(instance);
}
BOOL android_authenticate(freerdp* instance, char** username, char** password, char** domain)
{
DEBUG_ANDROID("Authenticate user:");
@@ -314,6 +329,9 @@ static void* jni_input_thread(void* arg)
do
{
DWORD rc = WaitForMultipleObjects(3, event, FALSE, INFINITE);
if ((rc < WAIT_OBJECT_0) || (rc > WAIT_OBJECT_0 + 2))
continue;
if (rc == WAIT_OBJECT_0 + 2)
{
wMessage msg;
@@ -322,9 +340,6 @@ static void* jni_input_thread(void* arg)
if (msg.id == WMQ_QUIT)
break;
}
if ((rc < WAIT_OBJECT_0) && (rc > WAIT_OBJECT_0 + 1))
break;
if (android_check_fds(instance) != TRUE)
break;
}
@@ -374,7 +389,7 @@ static int android_freerdp_run(freerdp* instance)
int rcount;
int wcount;
int fd_input_event;
HANDLE input_event;
HANDLE input_event = NULL;
void* rfds[32];
void* wfds[32];
fd_set rfds_set;
@@ -413,7 +428,7 @@ static int android_freerdp_run(freerdp* instance)
(LPTHREAD_START_ROUTINE) jni_update_thread, instance, 0, NULL);
}
if (async_input)
if (async_input)
{
input_thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) jni_input_thread, instance, 0, NULL);
@@ -521,7 +536,7 @@ static int android_freerdp_run(freerdp* instance)
break;
}
}
else
else if (input_event)
{
if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0)
{
@@ -555,6 +570,13 @@ static int android_freerdp_run(freerdp* instance)
freerdp_channels_close(instance->context->channels, instance);
DEBUG_ANDROID("Cleanup threads...");
if (async_channels)
{
WaitForSingleObject(channels_thread, INFINITE);
CloseHandle(channels_thread);
}
if (async_update)
{
wMessageQueue* update_queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
@@ -570,19 +592,9 @@ static int android_freerdp_run(freerdp* instance)
WaitForSingleObject(input_thread, INFINITE);
CloseHandle(input_thread);
}
if (async_channels)
{
WaitForSingleObject(channels_thread, INFINITE);
CloseHandle(channels_thread);
}
DEBUG_ANDROID("Disconnecting...");
freerdp_channels_free(instance->context->channels);
freerdp_disconnect(instance);
gdi_free(instance);
cache_free(instance->context->cache);
android_cliprdr_uninit(instance);
freerdp_callback("OnDisconnected", "(I)V", instance);
DEBUG_ANDROID("Quit.");
@@ -590,19 +602,15 @@ static int android_freerdp_run(freerdp* instance)
return 0;
}
void* android_thread_func(void* param)
static void* android_thread_func(void* param)
{
struct thread_data* data;
data = (struct thread_data*) param;
assert(data);
assert(data->instance);
freerdp* instance = param;
DEBUG_ANDROID("Start.");
freerdp* instance = data->instance;
assert(instance);
android_freerdp_run(instance);
free(data);
DEBUG_ANDROID("Quit.");
@@ -615,6 +623,7 @@ JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls)
freerdp* instance;
#if defined(WITH_GPROF)
setenv("CPUPROFILE_FREQUENCY", "200", 1);
monstartup("libfreerdp-android.so");
#endif
@@ -622,6 +631,7 @@ JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls)
instance = freerdp_new();
instance->PreConnect = android_pre_connect;
instance->PostConnect = android_post_connect;
instance->PostDisconnect = android_post_disconnect;
instance->Authenticate = android_authenticate;
instance->VerifyCertificate = android_verify_certificate;
instance->VerifyChangedCertificate = android_verify_changed_certificate;
@@ -640,6 +650,8 @@ JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls)
JNIEXPORT void JNICALL jni_freerdp_free(JNIEnv *env, jclass cls, jint instance)
{
freerdp* inst = (freerdp*)instance;
freerdp_context_free(inst);
freerdp_free(inst);
#if defined(WITH_GPROF)
@@ -650,15 +662,13 @@ JNIEXPORT void JNICALL jni_freerdp_free(JNIEnv *env, jclass cls, jint instance)
JNIEXPORT jboolean JNICALL jni_freerdp_connect(JNIEnv *env, jclass cls, jint instance)
{
freerdp* inst = (freerdp*)instance;
struct thread_data* data = (struct thread_data*) malloc(sizeof(struct thread_data));
data->instance = inst;
androidContext* ctx = (androidContext*)inst->context;
assert(inst);
assert(data);
assert(inst->context);
assert(ctx);
androidContext* ctx = (androidContext*)inst->context;
pthread_create(&ctx->thread, 0, android_thread_func, data);
ctx->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)android_thread_func, inst, 0, NULL);
return JNI_TRUE;
}
@@ -666,19 +676,27 @@ JNIEXPORT jboolean JNICALL jni_freerdp_connect(JNIEnv *env, jclass cls, jint ins
JNIEXPORT jboolean JNICALL jni_freerdp_disconnect(JNIEnv *env, jclass cls, jint instance)
{
freerdp* inst = (freerdp*)instance;
androidContext* ctx = (androidContext*)inst->context;
ANDROID_EVENT* event = (ANDROID_EVENT*)android_event_disconnect_new();
assert(inst);
assert(ctx);
assert(event);
android_push_event(inst, event);
WaitForSingleObject(ctx->thread, INFINITE);
CloseHandle(ctx->thread);
ctx->thread = NULL;
freerdp_callback("OnDisconnecting", "(I)V", instance);
return (jboolean) JNI_TRUE;
}
JNIEXPORT void JNICALL jni_freerdp_cancel_connection(JNIEnv *env, jclass cls, jint instance)
{
DEBUG_ANDROID("Cancelling connection ...");
freerdp* inst = (freerdp*)instance;
ANDROID_EVENT* event = (ANDROID_EVENT*)android_event_disconnect_new();
android_push_event(inst, event);
freerdp_callback("OnDisconnecting", "(I)V", instance);
jni_freerdp_disconnect(env, cls, instance);
}
JNIEXPORT void JNICALL jni_freerdp_set_data_directory(JNIEnv *env, jclass cls, jint instance, jstring jdirectory)
@@ -1001,7 +1019,7 @@ JNIEXPORT void JNICALL jni_freerdp_set_gateway_info(JNIEnv *env, jclass cls, jin
(*env)->ReleaseStringUTFChars(env, jgatewaydomain, gatewaydomain);
}
void copy_pixel_buffer(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int wBuf, int hBuf, int bpp)
static void copy_pixel_buffer(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int wBuf, int hBuf, int bpp)
{
int i, j;
int length;

View File

@@ -11,7 +11,6 @@
#define __ANDROID_FREERDP_H
#include <jni.h>
#include <pthread.h>
#include <freerdp/freerdp.h>
#include "android_event.h"
@@ -21,18 +20,14 @@ struct android_context
rdpContext rdpCtx;
ANDROID_EVENT_QUEUE* event_queue;
pthread_t thread;
HANDLE thread;
BOOL is_connected;
void* clipboard_context;
};
typedef struct android_context androidContext;
void copy_remotefx_tile(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int bpp);
void copy_pixel_buffer(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int wBuf, int hBuf, int bpp);
JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls);
JNIEXPORT void JNICALL jni_freerdp_free(JNIEnv *env, jclass cls, jint instance);
JNIEXPORT jboolean JNICALL jni_freerdp_connect(JNIEnv *env, jclass cls, jint instance);

View File

@@ -13,7 +13,6 @@
#endif
#include <stdio.h>
#include <android/log.h>
#include "android_jni_callback.h"
#include "android_debug.h"
@@ -36,24 +35,30 @@ void jni_load_class(JNIEnv *env, const char *path, jobject *objptr)
if (!class)
{
DEBUG_ANDROID("jni_load_class: failed to find class %s", path);
DEBUG_WARN("jni_load_class: failed to find class %s", path);
goto finish;
}
method = (*env)->GetMethodID(env, class, "<init>", "()V");
if (!method)
{
DEBUG_ANDROID("jni_load_class: failed to find class constructor of %s", path);
DEBUG_WARN("jni_load_class: failed to find class constructor of %s", path);
goto finish;
}
object = (*env)->NewObject(env, class, method);
if (!object)
{
DEBUG_ANDROID("jni_load_class: failed create new object of %s", path);
DEBUG_WARN("jni_load_class: failed create new object of %s", path);
goto finish;
}
(*objptr) = (*env)->NewGlobalRef(env, object);
finish:
while(0);
}
jint init_callback_environment(JavaVM* vm)
@@ -61,7 +66,7 @@ jint init_callback_environment(JavaVM* vm)
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
{
DEBUG_ANDROID("JNI_OnLoad: failed to obtain current JNI environment");
DEBUG_WARN("JNI_OnLoad: failed to obtain current JNI environment");
return -1;
}
@@ -83,7 +88,7 @@ jboolean jni_attach_thread(JNIEnv** env)
if ((*jVM)->GetEnv(jVM, (void**) env, JNI_VERSION_1_4) != JNI_OK)
{
DEBUG_ANDROID("android_java_callback: failed to obtain current JNI environment");
DEBUG_WARN("android_java_callback: failed to obtain current JNI environment");
}
return JNI_TRUE;
@@ -113,17 +118,20 @@ void java_callback_void(jobject obj, const char * callback, const char* signatur
jObjClass = (*env)->GetObjectClass(env, obj);
if (!jObjClass) {
DEBUG_ANDROID("android_java_callback: failed to get class reference");
DEBUG_WARN("android_java_callback: failed to get class reference");
goto finish;
}
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
if (!jCallback) {
DEBUG_ANDROID("android_java_callback: failed to get method id");
DEBUG_WARN("android_java_callback: failed to get method id");
goto finish;
}
(*env)->CallStaticVoidMethodV(env, jObjClass, jCallback, args);
finish:
if(attached == JNI_TRUE)
jni_detach_thread();
}
@@ -134,6 +142,7 @@ jboolean java_callback_bool(jobject obj, const char * callback, const char* sign
jclass jObjClass;
jmethodID jCallback;
jboolean attached;
jboolean res = JNI_FALSE;
JNIEnv *env;
DEBUG_ANDROID("java_callback: %s (%s)", callback, signature);
@@ -143,17 +152,20 @@ jboolean java_callback_bool(jobject obj, const char * callback, const char* sign
jObjClass = (*env)->GetObjectClass(env, obj);
if (!jObjClass) {
DEBUG_ANDROID("android_java_callback: failed to get class reference");
DEBUG_WARN("android_java_callback: failed to get class reference");
goto finish;
}
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
if (!jCallback) {
DEBUG_ANDROID("android_java_callback: failed to get method id");
DEBUG_WARN("android_java_callback: failed to get method id");
goto finish;
}
jboolean res = (*env)->CallStaticBooleanMethodV(env, jObjClass, jCallback, args);
res = (*env)->CallStaticBooleanMethodV(env, jObjClass, jCallback, args);
finish:
if(attached == JNI_TRUE)
jni_detach_thread();

View File

@@ -9,6 +9,7 @@
package com.freerdp.freerdpcore.presentation;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -530,7 +531,15 @@ public class SessionActivity extends Activity
protected void onDestroy() {
super.onDestroy();
Log.v(TAG, "Session.onDestroy");
// Cancel running disconnect timers.
GlobalApp.cancelDisconnectTimer();
// Disconnect all remaining sessions.
Collection<SessionState> sessions = GlobalApp.getSessions();
for (SessionState session : sessions)
LibFreeRDP.disconnect(session.getInstance());
// unregister freerdp events broadcast receiver
unregisterReceiver(libFreeRDPBroadcastReceiver);

View File

@@ -6,6 +6,60 @@
<project>FreeRDPCore</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?children?</key>
<value>?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|?name?=entry\\\\\\\|\\\|\||</value>
</dictionary>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>ndk-build</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>true</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
@@ -26,9 +80,19 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>

View File

@@ -3,14 +3,23 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
package="com.freerdp.afreerdp"
android:versionCode="3"
android:versionCode="@ANDROID_APP_VERSION@"
android:versionName="@GIT_REVISION@" >
<uses-sdk android:targetSdkVersion="@ANDROID_APP_TARGET_SDK@" android:minSdkVersion="@ANDROID_APP_MIN_SDK@"/>
<supports-screens android:anyDensity="true" android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" />
<uses-sdk
android:targetSdkVersion="@ANDROID_APP_TARGET_SDK@"
android:minSdkVersion="@ANDROID_APP_MIN_SDK@"/>
<supports-screens
android:anyDensity="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true" />
<application android:name="com.freerdp.afreerdp.application.GlobalApp"
android:label="aFreeRDP"
android:debuggable="@ANDROID_DEBUG_ENABLE@"
android:icon="@drawable/icon_launcher_freerdp" >
<!-- Main activity -->

View File

@@ -18,6 +18,8 @@
set(ANDROID_PACKAGE_NAME "aFreeRDP")
add_subdirectory(jni)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake
${CMAKE_CURRENT_BINARY_DIR}/AndroidManifest.xml @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build.xml.cmake
@@ -35,48 +37,30 @@ if (ANDROID_SDK)
${CMAKE_CURRENT_BINARY_DIR}/local.properties @ONLY)
endif()
if("${ANDROID_DEBUG_ENABLE}" STREQUAL "true")
# 1. generate Android.mk
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/jni/Android.mk
"APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
# 2. generate gdb.setup
get_directory_property(INCLUDE_DIRECTORIES DIRECTORY . INCLUDE_DIRECTORIES)
string(REGEX REPLACE ";" " " INCLUDE_DIRECTORIES "${INCLUDE_DIRECTORIES}")
set(LIB_DIRECTORIES "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}")
file(WRITE ${ANDROID_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/gdb.setup
"set solib-search-path ${CMAKE_CURRENT_BINARY_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}\n")
file(APPEND ${ANDROID_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/gdb.setup
"directory ${INCLUDE_DIRECTORIES} ${LIB_DIRECTORIES}\n")
# 3. copy gdbserver executable
file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver
DESTINATION ${ANDROID_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/)
# 4. Convenience target to launch debugger.
add_custom_target(debug-ndk
COMMAND adb install -r bin/aFreeRDP-debug.apk
COMMAND ndk-gdb --start --verbose --force
WORKING_DIRECTORY ${CURRENT_BINARY_DIR}
)
endif()
# command to create the android package
add_custom_target( ndk-build ALL
COMMAND ${NDK_COMMAND} NDK_DEBUG=${NDK_DEBUG}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPENDS freerdp-android
)
if(ANDROID_BUILD_JAVA)
if(NOT ANDROID_BUILD_JAVA_DEBUG)
set(APK "${ANDROID_BINARY_DIR}/bin/${ANDROID_PACKAGE_NAME}-release-unsigned.apk")
set(APK "${CMAKE_CURRENT_BINARY_DIR}/bin/${ANDROID_PACKAGE_NAME}-release-unsigned.apk")
else()
set(APK "${ANDROID_BINARY_DIR}/bin/${ANDROID_PACKAGE_NAME}-debug.apk")
set(APK "${CMAKE_CURRENT_BINARY_DIR}/bin/${ANDROID_PACKAGE_NAME}-debug.apk")
endif()
# command to create the android package
add_custom_command(
OUTPUT "${APK}"
COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE}
WORKING_DIRECTORY "${ANDROID_BINARY_DIR}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
MAIN_DEPENDENCY AndroidManifest.xml
DEPENDS freerdp-android
DEPENDS ndk-build
${CMAKE_CURRENT_BINARY_DIR}/local.properties
)
add_custom_target(android-package ALL SOURCES "${APK}")
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin")
endif()
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin;obj;libs")

View File

@@ -0,0 +1 @@
include @NDK_LIB_CFG@

View File

@@ -0,0 +1 @@
APP_ABI := @ANDROID_ABI@

View File

@@ -0,0 +1,22 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# Android Client
#
# Copyright 2013 Armin Novak <anovak@thinstuff.at>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Application.mk.cmake
${CMAKE_CURRENT_BINARY_DIR}/Application.mk @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Android.mk.cmake
${CMAKE_CURRENT_BINARY_DIR}/Android.mk @ONLY)

View File

@@ -25,7 +25,8 @@ option(WITH_ANDROID_DEBUG_MENU "Enable debug output for android jni bindings" ${
option(WITH_OPENSLES "Enable sound and microphone redirection using OpenSLES" ON)
option(ANDROID_BUILD_JAVA "Automatically android java code - build type depends on CMAKE_BUILD_TYPE" ON)
option(ANDROID_BUILD_JAVA_DEBUG "Create a android debug package" ${JAVA_DEBUG_DEFAULT})
set(ANDROID_APP_VERSION 3 CACHE STRING "Application version")
set(ANDROID_APP_TARGET_SDK 11 CACHE STRING "Application target android SDK")
set(ANDROID_APP_MIN_SDK 9 CACHE STRING "Application minimum android SDK requirement")
set(ANDROID_APP_GOOGLE_TARGET_SDK "16" CACHE STRING "Application target google SDK")

View File

@@ -52,7 +52,8 @@ to the absolut paths on your machine:
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/AndroidToolchain.cmake \
-DANDROID_NDK="_your_ndk_path_here_" \
-DFREERDP_ANDROID_EXTERNAL_SSL_PATH="_your_ssl_build_root_path_" \
-DANDROID_SDK="_your_sdk_path_here_"
-DANDROID_SDK="_your_sdk_path_here_" \
-DCMAKE_BUILD_TYPE=Debug
make
After that you should have a client/Android/bin/aFreeRDP-debug.apk.
@@ -66,12 +67,13 @@ to the absolut paths on your machine:
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/AndroidToolchain.cmake \
-DANDROID_NDK="_your_ndk_path_here_" \
-DFREERDP_ANDROID_EXTERNAL_SSL_PATH="_your_ssl_build_root_path_" \
-DANDROID_SDK="_your_sdk_path_here_" -DANDROID_BUILD_JAVA=OFF
-DANDROID_SDK="_your_sdk_path_here_" -DANDROID_BUILD_JAVA=OFF \
-DCMAKE_BUILD_TYPE=Debug
make
Now you can run your favourite ant command in client/Android like this:
cd client/Android
cd client/Android/aFreeRDP
ant debug install
Using an IDE
@@ -83,7 +85,7 @@ the eclipse marketplace).
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/AndroidToolchain.cmake \
-DANDROID_NDK="_your_ndk_path_here_" \
-DFREERDP_ANDROID_EXTERNAL_SSL_PATH="_your_ssl_build_root_path_" \
-DANDROID_BUILD_JAVA=OFF
-DCMAKE_BUILD_TYPE=Debug -DANDROID_BUILD_JAVA=OFF
make
Open Eclipse and choose:
@@ -97,6 +99,14 @@ Side note: If you add -G "Eclipse CDT4 - Unix Makefiles" when running cmake
you can also import FreeRDP into Eclipse too. Then you have one Java project and one c/c++
project you can work on. This requires CDT to be installed in Eclipse.
Debugging native code
---------------------
All CMake builds created with -DCMAKE_BUILD_TYPE=Debug will be ready to
debug with ndk-gdb.
Eclipse projects are already configured to allow debugging in either Java
or native code, no extra steps required.
cmake variables
===============
@@ -133,6 +143,35 @@ ANDROID_BUILD_JAVA (used by client/Android/CMakeLists.txt)
ANDROID_SDK (used by client/Android/CMakeLists.txt)
* absolute path to the Android SDK to use
ANDROID_NDK
* absolute path to the Android NDK to use.
WITH_DEBUG_ANDROID_JNI
* enable logcat debug messages for JNI calls.
WITH_ANDROID_DEBUG_MENU
* activate a debug menu in aFreeRDP to enable / disable runtime settings
* not available in release.
WITH_OPENSLES
* Enables / disables sound and microphone support for android using OpenSLES
ANDROID_BUILD_JAVA_DEBUG
* Enable / disable debugging code in the java parts of the application.
ANDROID_APP_VERSION
* The version the aFreeRDP-release.apk / aFreeRDP-debug.apk will have.
ANDROID_APP_TARGET_SDK
* The target SDK version of the project.
ANDROID_APP_MIN_SDK
* The lowest supported SDK version
ANDROID_NATIVE_API_LEVEL
* The native API level to compile the native code against.
* Should be equal to SDK level.
This is used to generate local.properties needed by ant. Needs to be set
if you build manually with ant or do integrated builds.

View File

@@ -20,17 +20,46 @@
#ifndef FREERDP_UTILS_DEBUG_H
#define FREERDP_UTILS_DEBUG_H
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define DEBUG_NULL(fmt, ...) do { } while (0)
/* When building for android redirect all debug messages
* to logcat. */
#if defined(ANDROID)
#include <android/log.h>
#define APP_NAME "freerdp-debug"
#define ANDROID_DEBUG_PRINT(_dbg_str, fmt, ...) do { \
__android_log_print(_dbg_str, fmt, ##__VA_ARGS__); \
} while( 0 )
#define DEBUG_CLASS(_dbg_class, fmt, ...) \
ANDROID_DEBUG_PRINT(ANDROID_LOG_DEBUG, APP_NAME, \
"DBG_" #_dbg_class " %s (%s:%d): " \
fmt, __FUNCTION__, __FILE__, __LINE__, ## __VA_ARGS__)
#define DEBUG_WARN(fmt, ...) \
ANDROID_DEBUG_PRINT(ANDROID_LOG_WARN, APP_NAME, "Warning %s (%s:%d): " \
fmt, __FUNCTION__, __FILE__, __LINE__, ## __VA_ARGS__)
#else
/* By default all log messages are written to stdout */
#include <stdio.h>
#define DEBUG_PRINT(_dbg_str, fmt, ...) do { \
fprintf(stderr, _dbg_str, __FUNCTION__, __FILE__, __LINE__); \
fprintf(stderr, fmt, ## __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while( 0 )
fprintf(stderr, _dbg_str, __FUNCTION__, __FILE__, __LINE__); \
fprintf(stderr, fmt, ## __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while( 0 )
#define DEBUG_CLASS(_dbg_class, fmt, ...) DEBUG_PRINT("DBG_" #_dbg_class " %s (%s:%d): ", fmt, ## __VA_ARGS__)
#define DEBUG_WARN(fmt, ...) DEBUG_PRINT("Warning %s (%s:%d): ", fmt, ## __VA_ARGS__)
#endif
#ifdef WITH_DEBUG
#define DEBUG_MSG(fmt, ...) DEBUG_PRINT("DBG %s (%s:%d): ", fmt, ## __VA_ARGS__)

View File

@@ -208,6 +208,10 @@ BOOL freerdp_check_fds(freerdp* instance)
int status;
rdpRdp* rdp;
assert(instance);
assert(instance->context);
assert(instance->context->rdp);
rdp = instance->context->rdp;
status = rdp_check_fds(rdp);

View File

@@ -486,8 +486,15 @@ int input_process_events(rdpInput* input)
return input_message_queue_process_pending_messages(input);
}
static void input_free_queued_message(void *obj)
{
wMessage *msg = (wMessage*)obj;
input_message_queue_free_message(msg);
}
rdpInput* input_new(rdpRdp* rdp)
{
const wObject cb = { .fnObjectFree = input_free_queued_message };
rdpInput* input;
input = (rdpInput*) malloc(sizeof(rdpInput));
@@ -496,7 +503,7 @@ rdpInput* input_new(rdpRdp* rdp)
{
ZeroMemory(input, sizeof(rdpInput));
input->queue = MessageQueue_New();
input->queue = MessageQueue_New(&cb);
}
return input;

File diff suppressed because it is too large Load Diff

View File

@@ -123,6 +123,8 @@ struct rdp_update_proxy
};
int update_message_queue_process_message(rdpUpdate* update, wMessage* message);
int update_message_queue_free_message(wMessage* message);
int update_message_queue_process_pending_messages(rdpUpdate* update);
rdpUpdateProxy* update_message_proxy_new(rdpUpdate* update);
@@ -148,6 +150,7 @@ struct rdp_input_proxy
};
int input_message_queue_process_message(rdpInput* input, wMessage* message);
int input_message_queue_free_message(wMessage* message);
int input_message_queue_process_pending_messages(rdpInput* input);
rdpInputProxy* input_message_proxy_new(rdpInput* input);

View File

@@ -1057,6 +1057,12 @@ void transport_free(rdpTransport* transport)
{
if (transport)
{
if (transport->async)
{
assert(!transport->thread);
assert(!transport->stopEvent);
}
if (transport->ReceiveBuffer)
Stream_Release(transport->ReceiveBuffer);

View File

@@ -1544,8 +1544,16 @@ int update_process_messages(rdpUpdate* update)
return update_message_queue_process_pending_messages(update);
}
static void update_free_queued_message(void *obj)
{
wMessage *msg = (wMessage*)obj;
update_message_queue_free_message(msg);
}
rdpUpdate* update_new(rdpRdp* rdp)
{
const wObject cb = { .fnObjectFree = update_free_queued_message };
rdpUpdate* update;
update = (rdpUpdate*) malloc(sizeof(rdpUpdate));
@@ -1587,7 +1595,7 @@ rdpUpdate* update_new(rdpRdp* rdp)
update->initialState = TRUE;
update->queue = MessageQueue_New();
update->queue = MessageQueue_New(&cb);
}
return update;

View File

@@ -1,6 +1,6 @@
#!/bin/bash
cd client/Android/FreeRDPCore/jni/generated/
cd @CMAKE_SOURCE_DIR@/client/Android/FreeRDPCore/jni/generated/
javah -classpath ../../bin/classes:@ANDROID_SDK@/platforms/android-8/android.jar -jni com.freerdp.freerdpcore.services.LibFreeRDP
rm com_freerdp_freerdpcore_services_LibFreeRDP_EventListener.h \
com_freerdp_freerdpcore_services_LibFreeRDP_UIEventListener.h

View File

@@ -402,6 +402,8 @@ struct _wMessageQueue
wMessage* array;
CRITICAL_SECTION lock;
HANDLE event;
wObject object;
};
typedef struct _wMessageQueue wMessageQueue;
@@ -418,7 +420,43 @@ WINPR_API void MessageQueue_PostQuit(wMessageQueue* queue, int nExitCode);
WINPR_API int MessageQueue_Get(wMessageQueue* queue, wMessage* message);
WINPR_API int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL remove);
WINPR_API wMessageQueue* MessageQueue_New(void);
/*! \brief Clears all elements in a message queue.
*
* \note If dynamically allocated data is part of the messages,
* a custom cleanup handler must be passed in the 'callback'
* argument for MessageQueue_New.
*
* \param queue The queue to clear.
*
* \return 0 in case of success or a error code otherwise.
*/
WINPR_API int MessageQueue_Clear(wMessageQueue *queue);
/*! \brief Creates a new message queue.
* If 'callback' is null, no custom cleanup will be done
* on message queue deallocation.
* If the 'callback' argument contains valid uninit or
* free functions those will be called by
* 'MessageQueue_Clear'.
*
* \param callback a pointer to custom initialization / cleanup functions.
* Can be NULL if not used.
*
* \return A pointer to a newly allocated MessageQueue or NULL.
*/
WINPR_API wMessageQueue* MessageQueue_New(const wObject *callback);
/*! \brief Frees resources allocated by a message queue.
* This function will only free resources allocated
* internally.
*
* \note Empty the queue before calling this function with
* 'MessageQueue_Clear', 'MessageQueue_Get' or
* 'MessageQueue_Peek' to free all resources allocated
* by the message contained.
*
* \param queue A pointer to the queue to be freed.
*/
WINPR_API void MessageQueue_Free(wMessageQueue* queue);
/* Message Pipe */

View File

@@ -66,7 +66,6 @@
#include <grp.h>
#include <errno.h>
#include <spawn.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>

View File

@@ -54,8 +54,8 @@ wMessagePipe* MessagePipe_New()
if (pipe)
{
pipe->In = MessageQueue_New();
pipe->Out = MessageQueue_New();
pipe->In = MessageQueue_New(NULL);
pipe->Out = MessageQueue_New(NULL);
}
return pipe;

View File

@@ -178,7 +178,7 @@ int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL remove)
* Construction, Destruction
*/
wMessageQueue* MessageQueue_New()
wMessageQueue* MessageQueue_New(const wObject *callback)
{
wMessageQueue* queue = NULL;
@@ -196,6 +196,11 @@ wMessageQueue* MessageQueue_New()
InitializeCriticalSectionAndSpinCount(&queue->lock, 4000);
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (callback)
queue->object = *callback;
else
ZeroMemory(&queue->object, sizeof(queue->object));
}
return queue;
@@ -209,3 +214,32 @@ void MessageQueue_Free(wMessageQueue* queue)
free(queue->array);
free(queue);
}
int MessageQueue_Clear(wMessageQueue *queue)
{
int status = 0;
EnterCriticalSection(&queue->lock);
while(queue->size > 0)
{
wMessage *msg = &(queue->array[queue->head]);
/* Free resources of message. */
if (queue->object.fnObjectUninit)
queue->object.fnObjectUninit(msg);
if (queue->object.fnObjectFree)
queue->object.fnObjectFree(msg);
ZeroMemory(msg, sizeof(wMessage));
queue->head = (queue->head + 1) % queue->capacity;
queue->size--;
}
ResetEvent(queue->event);
LeaveCriticalSection(&queue->lock);
return status;
}

View File

@@ -29,7 +29,7 @@ int TestMessageQueue(int argc, char* argv[])
HANDLE thread;
wMessageQueue* queue;
queue = MessageQueue_New();
queue = MessageQueue_New(NULL);
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) message_queue_consumer_thread, (void*) queue, 0, NULL);