From ac389ae4513263597dc02e4099867d5123faaa04 Mon Sep 17 00:00:00 2001 From: Vladimir Chtchetkine Date: Thu, 20 Jan 2011 14:35:55 -0800 Subject: Force core to send entire framebuffer on UI attachment Change-Id: I2feb813314163b94781ffe765eb23527b6c4a0f1 --- android/display-core.c | 2 +- android/framebuffer-common.h | 11 ++++++ android/framebuffer-core.c | 94 ++++++++++++++++++++++++++++++++++---------- android/framebuffer-core.h | 5 +-- android/framebuffer-ui.c | 14 ++++++- android/sync-utils.c | 1 - android/sync-utils.h | 2 +- 7 files changed, 102 insertions(+), 27 deletions(-) (limited to 'android') diff --git a/android/display-core.c b/android/display-core.c index 0b2a869..27b0706 100644 --- a/android/display-core.c +++ b/android/display-core.c @@ -43,7 +43,7 @@ coredisplay_fb_update(void* opaque, int x, int y, int w, int h) { CoreDisplay* cd = (CoreDisplay*)opaque; if (cd->core_fb) { - corefb_update(cd->core_fb, cd->ds, cd->fb, x, y, w, h); + corefb_update(cd->core_fb, cd->fb, x, y, w, h); } } diff --git a/android/framebuffer-common.h b/android/framebuffer-common.h index 95f65b6..da773b7 100644 --- a/android/framebuffer-common.h +++ b/android/framebuffer-common.h @@ -31,4 +31,15 @@ typedef struct FBUpdateMessage { uint8_t rect[0]; } FBUpdateMessage; +/* Requests the service to refresh framebuffer. */ +#define AFB_REQUEST_REFRESH 1 + +/* Header for framebuffer requests sent from the client (UI) + * to the service (core). + */ +typedef struct FBRequestHeader { + /* Request type. See AFB_REQUEST_XXX for the values. */ + uint8_t request_type; +} FBRequestHeader; + #endif /* _ANDROID_FRAMEBUFFER_UI_H */ diff --git a/android/framebuffer-core.c b/android/framebuffer-core.c index 3eb7665..89b7b46 100644 --- a/android/framebuffer-core.c +++ b/android/framebuffer-core.c @@ -30,6 +30,9 @@ struct CoreFramebuffer { /* Writer used to send FB update notification messages. */ AsyncWriter fb_update_writer; + /* Reader used to read FB requests from the client. */ + AsyncReader fb_req_reader; + /* I/O associated with this descriptor. */ LoopIo io; @@ -47,6 +50,9 @@ struct CoreFramebuffer { /* Socket used to communicate framebuffer updates. */ int sock; + + /* Framebuffer request header. */ + FBRequestHeader fb_req_header; }; /* Framebuffer update notification descriptor to the core. */ @@ -140,25 +146,14 @@ fbupdatenotify_delete(FBUpdateNotify* desc) extern void destroy_control_fb_client(void); /* - * Asynchronous I/O callback launched when writing framebuffer notifications - * to the socket. + * Asynchronous write I/O callback launched when writing framebuffer + * notifications to the socket. * Param: - * opaque - CoreFramebuffer instance. + * core_fb - CoreFramebuffer instance. */ static void -corefb_io_func(void* opaque, int fd, unsigned events) +corefb_io_write(CoreFramebuffer* core_fb) { - CoreFramebuffer* core_fb = opaque; - - if (events & LOOP_IO_READ) { - // We don't expect the UI client to write anything here, except when - // the client gets disconnected. - loopIo_dontWantWrite(&core_fb->io); - loopIo_dontWantRead(&core_fb->io); - destroy_control_fb_client(); - return; - } - while (core_fb->fb_update_head != NULL) { FBUpdateNotify* current_update = core_fb->fb_update_head; // Lets continue writing of the current notification. @@ -195,6 +190,66 @@ corefb_io_func(void* opaque, int fd, unsigned events) } } +/* + * Asynchronous read I/O callback launched when reading framebuffer requests + * from the socket. + * Param: + * core_fb - CoreFramebuffer instance. + */ +static void +corefb_io_read(CoreFramebuffer* core_fb) +{ + // Read the request header. + const AsyncStatus status = + asyncReader_read(&core_fb->fb_req_reader, &core_fb->io); + switch (status) { + case ASYNC_COMPLETE: + // Request header is received + switch (core_fb->fb_req_header.request_type) { + case AFB_REQUEST_REFRESH: + // Force full screen update to be sent + corefb_update(core_fb, core_fb->fb, + 0, 0, core_fb->fb->width, core_fb->fb->height); + break; + default: + derror("Unknown framebuffer request %d\n", + core_fb->fb_req_header.request_type); + break; + } + core_fb->fb_req_header.request_type = -1; + asyncReader_init(&core_fb->fb_req_reader, &core_fb->fb_req_header, + sizeof(core_fb->fb_req_header), &core_fb->io); + break; + case ASYNC_ERROR: + loopIo_dontWantRead(&core_fb->io); + if (errno == ECONNRESET) { + // UI has exited. We need to destroy framebuffer service. + destroy_control_fb_client(); + } + break; + + case ASYNC_NEED_MORE: + // Transfer will eventually come back into this routine. + return; + } +} + +/* + * Asynchronous I/O callback launched when writing framebuffer notifications + * to the socket. + * Param: + * opaque - CoreFramebuffer instance. + */ +static void +corefb_io_func(void* opaque, int fd, unsigned events) +{ + if (events & LOOP_IO_READ) { + corefb_io_read((CoreFramebuffer*)opaque); + } else if (events & LOOP_IO_WRITE) { + corefb_io_write((CoreFramebuffer*)opaque); + } +} + CoreFramebuffer* corefb_create(int sock, const char* protocol, QFrameBuffer* fb) { @@ -203,13 +258,12 @@ corefb_create(int sock, const char* protocol, QFrameBuffer* fb) ANEW0(ret); ret->sock = sock; ret->looper = looper_newCore(); - loopIo_init(&ret->io, ret->looper, sock, corefb_io_func, ret); - // Since we're overriding the read callback with our looper's I/O routine, - // we need to have set our read callback here to monitor disconnections. - loopIo_wantRead(&ret->io); ret->fb = fb; ret->fb_update_head = NULL; ret->fb_update_tail = NULL; + loopIo_init(&ret->io, ret->looper, sock, corefb_io_func, ret); + asyncReader_init(&ret->fb_req_reader, &ret->fb_req_header, + sizeof(ret->fb_req_header), &ret->io); return ret; } @@ -234,7 +288,7 @@ corefb_destroy(CoreFramebuffer* core_fb) } void -corefb_update(CoreFramebuffer* core_fb, struct DisplayState* ds, +corefb_update(CoreFramebuffer* core_fb, struct QFrameBuffer* fb, int x, int y, int w, int h) { AsyncStatus status; diff --git a/android/framebuffer-core.h b/android/framebuffer-core.h index fd4af52..773c248 100644 --- a/android/framebuffer-core.h +++ b/android/framebuffer-core.h @@ -46,12 +46,11 @@ void corefb_destroy(CoreFramebuffer* core_fb); * Notifies framebuffer client about changes in framebuffer. * Param: * core_fb - Framebuffer service descriptor created with corefb_create - * ds - Display state for the framebuffer. * fb Framebuffer containing pixels. * x, y, w, and h identify the rectangle that has benn changed. */ -void corefb_update(CoreFramebuffer* core_fb, struct DisplayState* ds, - struct QFrameBuffer* fb, int x, int y, int w, int h); +void corefb_update(CoreFramebuffer* core_fb, struct QFrameBuffer* fb, + int x, int y, int w, int h); /* * Gets number of bits used to encode a single pixel. diff --git a/android/framebuffer-ui.c b/android/framebuffer-ui.c index 5202381..0ae109f 100644 --- a/android/framebuffer-ui.c +++ b/android/framebuffer-ui.c @@ -19,6 +19,7 @@ #include "android/framebuffer-ui.h" #include "android/utils/system.h" #include "android/utils/debug.h" +#include "android/sync-utils.h" #define PANIC(...) do { fprintf(stderr, __VA_ARGS__); \ exit(1); \ @@ -247,7 +248,18 @@ clientfb_create(SockAddress* console_socket, _client_fb.core_connection = NULL; return NULL; } - + { + // Force the core to send us entire framebuffer now, when we're prepared + // to receive it. + FBRequestHeader hd; + SyncSocket* sk = syncsocket_init(_client_fb.sock); + + hd.request_type = AFB_REQUEST_REFRESH; + syncsocket_start_write(sk); + syncsocket_write(sk, &hd, sizeof(hd), 500); + syncsocket_stop_write(sk); + syncsocket_free(sk); + } fprintf(stdout, "Framebuffer %s is now attached to the core %s\n", protocol, sock_address_to_string(console_socket)); diff --git a/android/sync-utils.c b/android/sync-utils.c index 32c803c..6d3cea6 100644 --- a/android/sync-utils.c +++ b/android/sync-utils.c @@ -113,7 +113,6 @@ void syncsocket_free(SyncSocket* ssocket) { if (ssocket != NULL) { - syncsocket_close(ssocket); if (ssocket->iolooper != NULL) { iolooper_free(ssocket->iolooper); } diff --git a/android/sync-utils.h b/android/sync-utils.h index 110a143..1dcf649 100644 --- a/android/sync-utils.h +++ b/android/sync-utils.h @@ -43,7 +43,7 @@ SyncSocket* syncsocket_connect(int fd, SockAddress* sockaddr, int timeout); * Note: this routine will explicitly call socket_set_nonblock on the fd passed * to this routine. * Param: - * fd - File descriptor for the already connected. + * fd - File descriptor for the already connected socket. * Return: * Initialized SyncSocket descriptor on success, or NULL on failure. */ -- cgit v1.1