예제 #1
0
static BOOL android_post_connect(freerdp* instance)
{
	rdpSettings* settings;
	rdpUpdate* update;

	if (!instance || !instance->settings || !instance->context || !instance->update)
		return FALSE;

	update = instance->update;
	settings = instance->settings;

	if (!gdi_init(instance, PIXEL_FORMAT_RGBA32))
		return FALSE;

	if (!android_register_pointer(instance->context->graphics))
		return FALSE;

	instance->update->BeginPaint = android_begin_paint;
	instance->update->EndPaint = android_end_paint;
	instance->update->DesktopResize = android_desktop_resize;
	pointer_cache_register_callbacks(update);
	freerdp_callback("OnSettingsChanged", "(IIII)V", instance,
	                 settings->DesktopWidth, settings->DesktopHeight,
	                 settings->ColorDepth);
	freerdp_callback("OnConnectionSuccess", "(I)V", instance);
	return TRUE;
}
예제 #2
0
static BOOL android_post_connect(freerdp* instance)
{
	UINT32 gdi_flags;
	rdpSettings *settings = instance->settings;

	DEBUG_ANDROID("android_post_connect");

	assert(instance);
	assert(settings);

	freerdp_callback("OnSettingsChanged", "(IIII)V", instance,
			settings->DesktopWidth, settings->DesktopHeight,
			settings->ColorDepth);

	instance->context->cache = cache_new(settings);

	if (instance->settings->ColorDepth > 16)
		gdi_flags = CLRBUF_32BPP | CLRCONV_ALPHA | CLRCONV_INVERT;
	else
		gdi_flags = CLRBUF_16BPP;

	gdi_init(instance, gdi_flags, NULL);

	instance->update->BeginPaint = android_begin_paint;
	instance->update->EndPaint = android_end_paint;
	instance->update->DesktopResize = android_desktop_resize;

	freerdp_channels_post_connect(instance->context->channels, instance);

	freerdp_callback("OnConnectionSuccess", "(I)V", instance);

	return TRUE;
}
예제 #3
0
BOOL android_post_connect(freerdp* instance)
{
	DEBUG_ANDROID("android_post_connect");

	freerdp_callback("OnSettingsChanged", "(IIII)V", instance,
			instance->settings->DesktopWidth, instance->settings->DesktopHeight,
			instance->settings->ColorDepth);

	instance->context->cache = cache_new(instance->settings);

	gdi_init(instance, CLRCONV_ALPHA | ((instance->settings->ColorDepth > 16) ? CLRBUF_32BPP : CLRBUF_16BPP), NULL);

	instance->update->BeginPaint = android_begin_paint;
	instance->update->EndPaint = android_end_paint;
	instance->update->DesktopResize = android_desktop_resize;

	android_cliprdr_init(instance);

	freerdp_channels_post_connect(instance->context->channels, instance);

	// send notifications 
	freerdp_callback("OnConnectionSuccess", "(I)V", instance);

	return TRUE;
}
예제 #4
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
UINT android_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
	BYTE* data;
	UINT32 size;
	UINT32 index;
	UINT32 formatId;
	CLIPRDR_FORMAT* format = NULL;
	androidContext* afc = (androidContext*) cliprdr->custom;
	freerdp* instance = ((rdpContext*) afc)->instance;

	for (index = 0; index < afc->numServerFormats; index++)
	{
		if (afc->requestedFormatId == afc->serverFormats[index].formatId)
			format = &(afc->serverFormats[index]);
	}

	if (!format)
	{
		SetEvent(afc->clipboardRequestEvent);
		return ERROR_INTERNAL_ERROR;
	}

	if (format->formatName)
		formatId = ClipboardRegisterFormat(afc->clipboard, format->formatName);
	else
		formatId = format->formatId;

	size = formatDataResponse->dataLen;
	data = (BYTE*) malloc(size);
	CopyMemory(data, formatDataResponse->requestedFormatData, size);

	ClipboardSetData(afc->clipboard, formatId, data, size);

	SetEvent(afc->clipboardRequestEvent);

	if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT))
	{
		JNIEnv* env;
		jstring jdata;
		jboolean attached;

		formatId = ClipboardRegisterFormat(afc->clipboard, "UTF8_STRING");

		data = (void*) ClipboardGetData(afc->clipboard, formatId, &size);

		attached = jni_attach_thread(&env);
		jdata = jniNewStringUTF(env, data, size);

		freerdp_callback("OnRemoteClipboardChanged", "(ILjava/lang/String;)V", instance, jdata);

		(*env)->DeleteLocalRef(env, jdata);

		if (attached == JNI_TRUE)
		{
			jni_detach_thread();
		}
	}

	return CHANNEL_RC_OK;
}
예제 #5
0
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);
}
예제 #6
0
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();
	if (!event)
		return JNI_FALSE;

	DEBUG_ANDROID("DISCONNECT!");

	assert(inst);
	assert(ctx);
	assert(event);

	if (!android_push_event(inst, event))
	{
		android_event_disconnect_free(event);
		return JNI_FALSE;
	}

	WaitForSingleObject(ctx->thread, INFINITE);
	CloseHandle(ctx->thread);
	ctx->thread = NULL;

	freerdp_callback("OnDisconnecting", "(I)V", instance);

	return (jboolean) JNI_TRUE;
}
예제 #7
0
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);
}
예제 #8
0
JNIEXPORT jboolean JNICALL jni_freerdp_disconnect(JNIEnv *env, jclass cls, jint instance)
{
	freerdp* inst = (freerdp*)instance;
	ANDROID_EVENT* event = (ANDROID_EVENT*)android_event_disconnect_new();
	android_push_event(inst, event);
	freerdp_callback("OnDisconnecting", "(I)V", instance);
	return (jboolean) JNI_TRUE;
}
예제 #9
0
static BOOL android_end_paint(rdpContext* context)
{
	int i;
	HGDI_WND hwnd;
	int ninvalid;
	rdpGdi* gdi;
	HGDI_RGN cinvalid;
	int x1, y1, x2, y2;
	androidContext* ctx = (androidContext*)context;
	rdpSettings* settings;

	if (!ctx || !context->instance)
		return FALSE;

	settings = context->instance->settings;

	if (!settings)
		return FALSE;

	gdi = context->gdi;

	if (!gdi || !gdi->primary || !gdi->primary->hdc)
		return FALSE;

	hwnd = ctx->rdpCtx.gdi->primary->hdc->hwnd;

	if (!hwnd)
		return FALSE;

	ninvalid = hwnd->ninvalid;

	if (ninvalid == 0)
		return TRUE;

	cinvalid = hwnd->cinvalid;

	if (!cinvalid)
		return FALSE;

	x1 = cinvalid[0].x;
	y1 = cinvalid[0].y;
	x2 = cinvalid[0].x + cinvalid[0].w;
	y2 = cinvalid[0].y + cinvalid[0].h;

	for (i = 0; i < ninvalid; i++)
	{
		x1 = MIN(x1, cinvalid[i].x);
		y1 = MIN(y1, cinvalid[i].y);
		x2 = MAX(x2, cinvalid[i].x + cinvalid[i].w);
		y2 = MAX(y2, cinvalid[i].y + cinvalid[i].h);
	}

	freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance,
	                 x1, y1, x2 - x1, y2 - y1);
	return TRUE;
}
예제 #10
0
static BOOL android_desktop_resize(rdpContext* context)
{
	if (!context || !context->instance || !context->settings)
		return FALSE;

	freerdp_callback("OnGraphicsResize", "(IIII)V",
	                 context->instance, context->settings->DesktopWidth,
	                 context->settings->DesktopHeight, context->settings->ColorDepth);
	return TRUE;
}
예제 #11
0
static void* android_thread_func(void* param)
{
	DWORD status = ERROR_BAD_ARGUMENTS;
	freerdp* instance = param;
	WLog_DBG(TAG, "Start...");

	if (!instance || !instance->context)
		goto fail;

	if (freerdp_client_start(instance->context) != CHANNEL_RC_OK)
		goto fail;

	WLog_DBG(TAG, "Connect...");

	if (!freerdp_connect(instance))
		status = GetLastError();
	else
	{
		status = android_freerdp_run(instance);
		WLog_DBG(TAG, "Disonnect...");

		if (!freerdp_disconnect(instance))
			status = GetLastError();
	}

	WLog_DBG(TAG, "Stop...");

	if (freerdp_client_stop(instance->context) != CHANNEL_RC_OK)
		goto fail;

fail:
	WLog_DBG(TAG, "Session ended with %08lX", status);

	if (status == CHANNEL_RC_OK)
		freerdp_callback("OnDisconnected", "(I)V", instance);
	else
		freerdp_callback("OnConnectionFailure", "(I)V", instance);

	WLog_DBG(TAG, "Quit.");
	ExitThread(status);
	return NULL;
}
예제 #12
0
void android_desktop_resize(rdpContext* context)
{
	DEBUG_ANDROID("ui_desktop_resize");

	assert(context);
	assert(context->settings);
	assert(context->instance);

	freerdp_callback("OnGraphicsResize", "(IIII)V",
			context->instance, context->settings->DesktopWidth,
			context->settings->DesktopHeight, context->settings->ColorDepth);
}
예제 #13
0
static void android_cliprdr_process_cb_data_response_event(clipboardContext* cb, RDP_CB_DATA_RESPONSE_EVENT* event)
{
	DEBUG_ANDROID("size=%d", event->size);	

	if (event->size > 0)
	{
		if (cb->data)
		{
			free(cb->data);
			cb->data = NULL;
			cb->data_length = 0;
		}
		switch (cb->data_format)
		{
			case CB_FORMAT_RAW:
			case CB_FORMAT_PNG:
			case CB_FORMAT_JPEG:
			case CB_FORMAT_GIF:
			case CB_FORMAT_DIB:
			default:
				DEBUG_ANDROID("unsupported format\n");
				break;

			case CB_FORMAT_TEXT:
				android_cliprdr_process_text(cb, event->data, event->size - 1);
				break;

			case CB_FORMAT_UNICODETEXT:
				android_cliprdr_process_unicodetext(cb, event->data, event->size - 2);
				break;

			case CB_FORMAT_HTML:
				android_cliprdr_process_html(cb, event->data, event->size);
				break;
		}
		DEBUG_ANDROID("computer_clipboard_data %s ", (char*)cb->data);		
		if (cb->data)
		{   //CALLBACK
			JNIEnv* env;
			jboolean attached = jni_attach_thread(&env);
			jstring jdata = jniNewStringUTF(env, cb->data, cb->data_length);

			freerdp_callback("OnRemoteClipboardChanged", "(ILjava/lang/String;)V", cb->instance, jdata);

			(*env)->DeleteLocalRef(env, jdata);
			if(attached == JNI_TRUE)
			{
				jni_detach_thread();
			}
		}
	}
}
예제 #14
0
void android_end_paint(rdpContext* context)
{
	DEBUG_ANDROID("ui_update");

	rdpGdi *gdi = context->gdi;
	if (gdi->primary->hdc->hwnd->invalid->null)
		return;

	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);
}
예제 #15
0
void android_end_paint(rdpContext* context)
{
	androidContext *ctx = (androidContext*)context;
	rdpSettings* settings = context->instance->settings;
	
	DEBUG_ANDROID("ui_update");

	assert(ctx);
	assert(settings);
	assert(context->instance);

	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);
}
예제 #16
0
static BOOL android_end_paint(rdpContext* context)
{
	int i;
	int ninvalid;
	HGDI_RGN cinvalid;
	int x1, y1, x2, y2;
	androidContext *ctx = (androidContext*)context;
	rdpSettings* settings = context->instance->settings;
	
	assert(ctx);
	assert(settings);
	assert(context->instance);

	ninvalid = ctx->rdpCtx.gdi->primary->hdc->hwnd->ninvalid;
	if (ninvalid == 0)
	{
		DEBUG_ANDROID("ui_update: ninvalid=%d", ninvalid);
		return TRUE;
	}

	cinvalid = ctx->rdpCtx.gdi->primary->hdc->hwnd->cinvalid;

	x1 = cinvalid[0].x;
	y1 = cinvalid[0].y;
	x2 = cinvalid[0].x + cinvalid[0].w;
	y2 = cinvalid[0].y + cinvalid[0].h;

	for (i = 0; i < ninvalid; i++)
	{
		x1 = MIN(x1, cinvalid[i].x);
		y1 = MIN(y1, cinvalid[i].y);
		x2 = MAX(x2, cinvalid[i].x + cinvalid[i].w);
		y2 = MAX(y2, cinvalid[i].y + cinvalid[i].h);
	}

	DEBUG_ANDROID("ui_update: ninvalid=%d x=%d, y=%d, width=%d, height=%d, bpp=%d",
			ninvalid, x1, y1, x2 - x1, y2 - y1, settings->ColorDepth);
	
	freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance,
		x1, y1, x2 - x1, y2 - y1);
	return TRUE;
}
예제 #17
0
static int android_freerdp_run(freerdp* instance)
{
	int i;
	int fds;
	int max_fds;
	int rcount;
	int wcount;
	int fd_input_event;
	HANDLE input_event = NULL;
	void* rfds[32];
	void* wfds[32];
	fd_set rfds_set;
	fd_set wfds_set;
	int select_status;
	struct timeval timeout;

	const rdpSettings* settings = instance->context->settings;

	HANDLE input_thread = NULL;
	HANDLE channels_thread = NULL;
	
	BOOL async_input = settings->AsyncInput;
	BOOL async_channels = settings->AsyncChannels;
	BOOL async_transport = settings->AsyncTransport;

	DEBUG_ANDROID("AsyncUpdate=%d", settings->AsyncUpdate);
	DEBUG_ANDROID("AsyncInput=%d", settings->AsyncInput);
	DEBUG_ANDROID("AsyncChannels=%d", settings->AsyncChannels);
	DEBUG_ANDROID("AsyncTransport=%d", settings->AsyncTransport);

	memset(rfds, 0, sizeof(rfds));
	memset(wfds, 0, sizeof(wfds));

	if (!freerdp_connect(instance))
	{
		freerdp_callback("OnConnectionFailure", "(I)V", instance);
		return 0;
	}

	if (async_input)
	{
		if (!(input_thread = CreateThread(NULL, 0,
				(LPTHREAD_START_ROUTINE) jni_input_thread, instance, 0, NULL)))
		{
			DEBUG_ANDROID("Failed to create async input thread\n");
			goto disconnect;
		}
	}
	      
	if (async_channels)
	{
		if (!(channels_thread = CreateThread(NULL, 0,
				(LPTHREAD_START_ROUTINE) jni_channels_thread, instance, 0, NULL)))
		{
			DEBUG_ANDROID("Failed to create async channels thread\n");
			goto disconnect;
		}
	}

	((androidContext*)instance->context)->is_connected = TRUE;
	while (!freerdp_shall_disconnect(instance))
	{
		rcount = 0;
		wcount = 0;

		if (!async_transport)
		{
			if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
			{
				DEBUG_ANDROID("Failed to get FreeRDP file descriptor\n");
				break;
			}
		}

		if (!async_channels)
		{
			if (freerdp_channels_get_fds(instance->context->channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
			{
				DEBUG_ANDROID("Failed to get channel manager file descriptor\n");
				break;
			}
		}

		if (!async_input)
		{
			if (android_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
			{
				DEBUG_ANDROID("Failed to get android file descriptor\n");
				break;
			}
		}
		else
		{
			input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
			fd_input_event = GetEventFileDescriptor(input_event);
			rfds[rcount++] = (void*) (long) fd_input_event;
		}

		max_fds = 0;
		FD_ZERO(&rfds_set);
		FD_ZERO(&wfds_set);

		for (i = 0; i < rcount; i++)
		{
			fds = (int)(long)(rfds[i]);

			if (fds > max_fds)
				max_fds = fds;

			FD_SET(fds, &rfds_set);
		}

		if (max_fds == 0)
			break;

		timeout.tv_sec = 1;
		timeout.tv_usec = 0;

		select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout);

		if (select_status == 0)
			continue;
		else if (select_status == -1)
		{
			/* these are not really errors */
			if (!((errno == EAGAIN) ||
				(errno == EWOULDBLOCK) ||
				(errno == EINPROGRESS) ||
				(errno == EINTR))) /* signal occurred */
			{
				DEBUG_ANDROID("android_run: select failed\n");
				break;
			}
		}
		
		if (freerdp_shall_disconnect(instance))
			break;

		if (!async_transport)
		{
			if (freerdp_check_fds(instance) != TRUE)
			{
				DEBUG_ANDROID("Failed to check FreeRDP file descriptor\n");
				break;
			}
		}

		if (!async_input)
		{
			if (android_check_fds(instance) != TRUE)
			{
				DEBUG_ANDROID("Failed to check android file descriptor\n");
				break;
			}
		}
		else if (input_event)
		{
			if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0)
			{
				if (!freerdp_message_queue_process_pending_messages(instance,
							FREERDP_INPUT_MESSAGE_QUEUE))
				{
					DEBUG_ANDROID("User Disconnect");
					break;
				}
			}
		}

		if (!async_channels)
		{
			if (freerdp_channels_check_fds(instance->context->channels, instance) != TRUE)
			{
				DEBUG_ANDROID("Failed to check channel manager file descriptor\n");
				break;
			}
		}
	}

disconnect:
	DEBUG_ANDROID("Prepare shutdown...");

	// issue another OnDisconnecting here in case the disconnect was initiated by the server and not our client
	freerdp_callback("OnDisconnecting", "(I)V", instance);
	
	DEBUG_ANDROID("Close channels...");
	freerdp_channels_disconnect(instance->context->channels, instance);

	DEBUG_ANDROID("Cleanup threads...");

	if (async_channels && channels_thread)
	{
		WaitForSingleObject(channels_thread, INFINITE);
		CloseHandle(channels_thread);
	}
 
	if (async_input && input_thread)
	{
		wMessageQueue* input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
		if (input_queue)
		{
			if (MessageQueue_PostQuit(input_queue, 0))
				WaitForSingleObject(input_thread, INFINITE);
		}
		CloseHandle(input_thread);
	}

	DEBUG_ANDROID("run Disconnecting...");
	freerdp_disconnect(instance);
	freerdp_callback("OnDisconnected", "(I)V", instance);

	DEBUG_ANDROID("run Quit.");

	return 0;
}
예제 #18
0
int android_freerdp_run(freerdp* instance)
{
	int i;
	int fds;
	int max_fds;
	int rcount;
	int wcount;
	void* rfds[32];
	void* wfds[32];
	fd_set rfds_set;
	fd_set wfds_set;
	int select_status;
	struct timeval timeout;

	assert(instance);

	memset(rfds, 0, sizeof(rfds));
	memset(wfds, 0, sizeof(wfds));

	if (!freerdp_connect(instance))
	{
		freerdp_callback("OnConnectionFailure", "(I)V", instance);
		return 0;
	}
	
	((androidContext*)instance->context)->is_connected = TRUE;
	while (!freerdp_shall_disconnect(instance))
	{
		rcount = 0;
		wcount = 0;

		if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
		{
			DEBUG_ANDROID("Failed to get FreeRDP file descriptor\n");
			break;
		}
		if (freerdp_channels_get_fds(instance->context->channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
		{
			DEBUG_ANDROID("Failed to get channel manager file descriptor\n");
			break;
		}
		if (android_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
		{
			DEBUG_ANDROID("Failed to get android file descriptor\n");
			break;
		}

		max_fds = 0;
		FD_ZERO(&rfds_set);
		FD_ZERO(&wfds_set);

		for (i = 0; i < rcount; i++)
		{
			fds = (int)(long)(rfds[i]);

			if (fds > max_fds)
				max_fds = fds;

			FD_SET(fds, &rfds_set);
		}

		if (max_fds == 0)
			break;

		timeout.tv_sec = 1;
		timeout.tv_usec = 0;

		select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout);

		if (select_status == 0)
			continue;
		else if (select_status == -1)
		{
			/* these are not really errors */
			if (!((errno == EAGAIN) ||
				(errno == EWOULDBLOCK) ||
				(errno == EINPROGRESS) ||
				(errno == EINTR))) /* signal occurred */
			{
				DEBUG_ANDROID("android_run: select failed\n");
				break;
			}
		}
		
		if (freerdp_shall_disconnect(instance))
			break;

		if (freerdp_check_fds(instance) != TRUE)
		{
			DEBUG_ANDROID("Failed to check FreeRDP file descriptor\n");
			break;
		}
		if (android_check_fds(instance) != TRUE)
		{
			DEBUG_ANDROID("Failed to check android file descriptor\n");
			break;
		}
		if (freerdp_channels_check_fds(instance->context->channels, instance) != TRUE)
		{
			DEBUG_ANDROID("Failed to check channel manager file descriptor\n");
			break;
		}
		android_process_channel_event(instance->context->channels, instance);
	}

	// issue another OnDisconnecting here in case the disconnect was initiated by the sever and not our client
	freerdp_callback("OnDisconnecting", "(I)V", instance);
	freerdp_channels_close(instance->context->channels, instance);
	freerdp_disconnect(instance);
	gdi_free(instance);
	cache_free(instance->context->cache);
	android_cliprdr_uninit(instance);
	freerdp_callback("OnDisconnected", "(I)V", instance);

	return 0;
}
예제 #19
0
static void android_post_disconnect(freerdp* instance)
{
	freerdp_callback("OnDisconnecting", "(I)V", instance);
	gdi_free(instance);
}
예제 #20
0
static BOOL android_pre_connect(freerdp* instance)
{
	int rc;
	rdpSettings* settings;
	BOOL bitmap_cache;

	if (!instance)
		return FALSE;

	settings = instance->settings;

	if (!settings || !settings->OrderSupport)
		return FALSE;

	bitmap_cache = settings->BitmapCacheEnabled;
	settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
	settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
	settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
	settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
	settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
	settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
	settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
	settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
	settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
	settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
	settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
	settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
	settings->OrderSupport[NEG_MEMBLT_INDEX] = bitmap_cache;
	settings->OrderSupport[NEG_MEM3BLT_INDEX] = TRUE;
	settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = bitmap_cache;
	settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
	settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
	settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
	settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
	settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
	settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
	settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
	settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
	settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
	rc = PubSub_SubscribeChannelConnected(
	         instance->context->pubSub,
	         (pChannelConnectedEventHandler)
	         android_OnChannelConnectedEventHandler);

	if (rc != CHANNEL_RC_OK)
	{
		WLog_ERR(TAG, "Could not subscribe to connect event handler [%l08X]", rc);
		return FALSE;
	}

	rc = PubSub_SubscribeChannelDisconnected(
	         instance->context->pubSub,
	         (pChannelDisconnectedEventHandler)
	         android_OnChannelDisconnectedEventHandler);

	if (rc != CHANNEL_RC_OK)
	{
		WLog_ERR(TAG, "Could not subscribe to disconnect event handler [%l08X]", rc);
		return FALSE;
	}

	if (!freerdp_client_load_addins(instance->context->channels,
	                                instance->settings))
	{
		WLog_ERR(TAG, "Failed to load addins [%l08X]", GetLastError());
		return FALSE;
	}

	freerdp_callback("OnPreConnect", "(I)V", instance);
	return TRUE;
}