Refactor the framebuffer service

Change-Id: I8ac4580af65b8d58976c97b77b309dd202e75003
diff --git a/Makefile.android b/Makefile.android
index b681764..e4ed4ca 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -1056,7 +1056,7 @@
               android/looper-qemu.c \
               android/looper-generic.c \
               android/display-core.c \
-              android/framebuffer-core.c \
+              android/protocol/fb-updates-proxy.c \
               android/protocol/user-events-impl.c \
               android/protocol/ui-commands-proxy.c \
               android/protocol/core-commands-impl.c \
@@ -1215,7 +1215,7 @@
               vl-android-ui.c \
               console-ui.c \
               iolooper-select.c \
-              android/framebuffer-ui.c \
+              android/protocol/fb-updates-impl.c \
               android/protocol/ui-commands-impl.c \
               android/protocol/core-commands-proxy.c \
               android/protocol/user-events-proxy.c \
diff --git a/android/console.c b/android/console.c
index 59610eb..e797d9e 100644
--- a/android/console.c
+++ b/android/console.c
@@ -51,7 +51,7 @@
 #include "android/keycode-array.h"
 #include "android/charmap.h"
 #include "android/display-core.h"
-#include "android/framebuffer-core.h"
+#include "android/protocol/fb-updates-proxy.h"
 #include "android/protocol/user-events-impl.h"
 #include "android/protocol/ui-commands-api.h"
 #include "android/protocol/core-commands-impl.h"
@@ -247,9 +247,9 @@
     }
 
     if (client == framebuffer_client) {
-        CoreFramebuffer* core_fb = coredisplay_detach_fb_service();
+        ProxyFramebuffer* core_fb = coredisplay_detach_fb_service();
         if (core_fb != NULL) {
-            corefb_destroy(core_fb);
+            proxyFb_destroy(core_fb);
             AFREE(core_fb);
         }
         framebuffer_client = NULL;
@@ -2523,7 +2523,7 @@
 static int
 do_create_framebuffer_service( ControlClient client, char* args )
 {
-    CoreFramebuffer* core_fb;
+    ProxyFramebuffer* core_fb;
     const char* protocol = "-raw";   // Default framebuffer exchange protocol.
 
     // Protocol type is defined by the arguments passed with the stream switch
@@ -2554,13 +2554,13 @@
         return -1;
     }
 
-    core_fb = corefb_create(client->sock, protocol, coredisplay_get_framebuffer());
+    core_fb = proxyFb_create(client->sock, protocol, coredisplay_get_framebuffer());
     if (!coredisplay_attach_fb_service(core_fb)) {
         char reply_buf[4096];
         framebuffer_client = client;
         // Reply "OK" with the framebuffer's bits per pixel
         snprintf(reply_buf, sizeof(reply_buf), "OK: -bitsperpixel=%d\r\n",
-                 corefb_get_bits_per_pixel(core_fb));
+                 proxyFb_get_bits_per_pixel(core_fb));
         control_write( client, reply_buf);
     } else {
         control_write( client, "KO\r\n" );
diff --git a/android/display-core.c b/android/display-core.c
index 27b0706..6834cd6 100644
--- a/android/display-core.c
+++ b/android/display-core.c
@@ -27,7 +27,7 @@
     QFrameBuffer*       fb;
 
     /* Framebuffer service associated with this core display. */
-    CoreFramebuffer*    core_fb;
+    ProxyFramebuffer*   core_fb;
 };
 
 /* One and only one core display instance. */
@@ -43,7 +43,7 @@
 {
     CoreDisplay* cd = (CoreDisplay*)opaque;
     if (cd->core_fb) {
-        corefb_update(cd->core_fb, cd->fb, x, y, w, h);
+        proxyFb_update(cd->core_fb, cd->fb, x, y, w, h);
     }
 }
 
@@ -109,7 +109,7 @@
 }
 
 int
-coredisplay_attach_fb_service(CoreFramebuffer* core_fb)
+coredisplay_attach_fb_service(ProxyFramebuffer* core_fb)
 {
     if (core_display.core_fb == NULL) {
         core_display.core_fb = core_fb;
@@ -119,10 +119,10 @@
     }
 }
 
-CoreFramebuffer*
+ProxyFramebuffer*
 coredisplay_detach_fb_service(void)
 {
-    CoreFramebuffer* ret = core_display.core_fb;
+    ProxyFramebuffer* ret = core_display.core_fb;
     core_display.core_fb = NULL;
     return ret;
 }
diff --git a/android/display-core.h b/android/display-core.h
index 4e1d07f..6204e56 100644
--- a/android/display-core.h
+++ b/android/display-core.h
@@ -20,7 +20,7 @@
 
 #include "framebuffer.h"
 #include "android/display.h"
-#include "android/framebuffer-core.h"
+#include "android/protocol/fb-updates-proxy.h"
 
 /* Descriptor for a core display instance */
 typedef struct CoreDisplay CoreDisplay;
@@ -39,7 +39,7 @@
  * Return:
  *  0 on success, or -1 on failure.
  */
-extern int coredisplay_attach_fb_service(CoreFramebuffer* core_fb);
+extern int coredisplay_attach_fb_service(ProxyFramebuffer* core_fb);
 
 /*
  * Detaches framebuffer service previously attached to the core display.
@@ -47,7 +47,7 @@
  *  Framebuffer service descriptor attached to the core display, or NULL if
  *  the core display didn't have framebuffer service attached to it.
  */
-extern CoreFramebuffer* coredisplay_detach_fb_service(void);
+extern ProxyFramebuffer* coredisplay_detach_fb_service(void);
 
 /*
  * Get framebuffer descriptor for core display.
diff --git a/android/framebuffer-ui.c b/android/framebuffer-ui.c
deleted file mode 100644
index 0ae109f..0000000
--- a/android/framebuffer-ui.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/* Copyright (C) 2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains UI-side framebuffer client that receives framebuffer updates
- * from the core.
- */
-
-#include "android/framebuffer-common.h"
-#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);                       \
-                    } while (0)
-
-/*
- * Enumerates states for the client framebuffer update reader.
- */
-typedef enum ClientFBState {
-    /* The reader is waiting on update header. */
-    WAIT_HEADER,
-
-    /* The reader is waiting on pixels. */
-    WAIT_PIXELS,
-} ClientFBState;
-
-/*
- * Descriptor for the framebuffer client.
- */
-struct ClientFramebuffer {
-    /* Framebuffer for this client. */
-    QFrameBuffer*   fb;
-
-    /* Core connection instance for the framebuffer client. */
-    CoreConnection* core_connection;
-
-    /* Current update header. */
-    FBUpdateMessage update_header;
-
-    /* Reader's buffer. */
-    uint8_t*        reader_buffer;
-
-    /* Offset in the reader's buffer where to read next chunk of data. */
-    size_t          reader_offset;
-
-    /* Total number of bytes the reader expects to read. */
-    size_t          reader_bytes;
-
-    /* Current state of the update reader. */
-    ClientFBState   fb_state;
-
-    /* Socket descriptor for the framebuffer client. */
-    int             sock;
-
-    /* Number of bits used to encode single pixel. */
-    int             bits_per_pixel;
-};
-
-/* The only instance of framebuffer client. */
-static ClientFramebuffer _client_fb;
-
-/*
- * Updates a display rectangle.
- * Param
- *  fb - Framebuffer where to update the rectangle.
- *  x, y, w, and h define rectangle to update.
- *  bits_per_pixel define number of bits used to encode a single pixel.
- *  pixels contains pixels for the rectangle. Buffer addressed by this parameter
- *      must be eventually freed with free()
- */
-static void
-update_rect(QFrameBuffer* fb, uint16_t x, uint16_t y, uint16_t w, uint16_t h,
-            uint8_t bits_per_pixel, uint8_t* pixels)
-{
-    if (fb != NULL) {
-        uint16_t n;
-        const uint8_t* src = pixels;
-        const uint16_t src_line_size = w * ((bits_per_pixel + 7) / 8);
-        uint8_t* dst  = (uint8_t*)fb->pixels + y * fb->pitch + x * fb->bytes_per_pixel;
-        for (n = 0; n < h; n++) {
-            memcpy(dst, src, src_line_size);
-            src += src_line_size;
-            dst += fb->pitch;
-        }
-        qframebuffer_update(fb, x, y, w, h);
-    }
-    free(pixels);
-}
-
-/*
- * Asynchronous I/O callback launched when framebuffer notifications are ready
- * to be read.
- * Param:
- *  opaque - ClientFramebuffer instance.
- */
-static void
-_clientfb_read_cb(void* opaque)
-{
-    ClientFramebuffer* fb_client = opaque;
-    int  ret;
-
-    // Read updates while they are immediately available.
-    for (;;) {
-        // Read next chunk of data.
-        ret = read(fb_client->sock, fb_client->reader_buffer + fb_client->reader_offset,
-                   fb_client->reader_bytes - fb_client->reader_offset);
-        if (ret == 0) {
-            /* disconnection ! */
-            clientfb_destroy(fb_client);
-            return;
-        }
-        if (ret < 0) {
-            if (errno == EINTR) {
-                /* loop on EINTR */
-                continue;
-            } else if (errno == EWOULDBLOCK || errno == EAGAIN) {
-                // Chunk is not avalable at this point. Come back later.
-                return;
-            }
-        }
-
-        fb_client->reader_offset += ret;
-        if (fb_client->reader_offset != fb_client->reader_bytes) {
-            // There are still some data left in the pipe.
-            continue;
-        }
-
-        // All expected data has been read. Time to change the state.
-        if (fb_client->fb_state == WAIT_HEADER) {
-            // Update header has been read. Prepare for the pixels.
-            fb_client->fb_state = WAIT_PIXELS;
-            fb_client->reader_offset = 0;
-            fb_client->reader_bytes = fb_client->update_header.w *
-                                      fb_client->update_header.h *
-                                      (fb_client->bits_per_pixel / 8);
-            fb_client->reader_buffer = malloc(fb_client->reader_bytes);
-            if (fb_client->reader_buffer == NULL) {
-                PANIC("Unable to allocate memory for framebuffer update\n");
-            }
-        } else {
-            // Pixels have been read. Prepare for the header.
-             uint8_t* pixels = fb_client->reader_buffer;
-
-            fb_client->fb_state = WAIT_HEADER;
-            fb_client->reader_offset = 0;
-            fb_client->reader_bytes = sizeof(FBUpdateMessage);
-            fb_client->reader_buffer = (uint8_t*)&fb_client->update_header;
-
-            // Perform the update. Note that pixels buffer must be freed there.
-            update_rect(fb_client->fb, fb_client->update_header.x,
-                        fb_client->update_header.y, fb_client->update_header.w,
-                        fb_client->update_header.h, fb_client->bits_per_pixel,
-                        pixels);
-        }
-    }
-}
-
-ClientFramebuffer*
-clientfb_create(SockAddress* console_socket,
-                const char* protocol,
-                QFrameBuffer* fb)
-{
-    char* connect_message = NULL;
-    char switch_cmd[256];
-
-    // Connect to the framebuffer service.
-    _client_fb.core_connection = core_connection_create(console_socket);
-    if (_client_fb.core_connection == NULL) {
-        derror("Framebuffer client is unable to connect to the console: %s\n",
-               errno_str);
-        return NULL;
-    }
-    if (core_connection_open(_client_fb.core_connection)) {
-        core_connection_free(_client_fb.core_connection);
-        _client_fb.core_connection = NULL;
-        derror("Framebuffer client is unable to open the console: %s\n",
-               errno_str);
-        return NULL;
-    }
-    snprintf(switch_cmd, sizeof(switch_cmd), "framebuffer %s", protocol);
-    if (core_connection_switch_stream(_client_fb.core_connection, switch_cmd,
-                                      &connect_message)) {
-        derror("Unable to attach to the framebuffer %s: %s\n",
-               switch_cmd, connect_message ? connect_message : "");
-        if (connect_message != NULL) {
-            free(connect_message);
-        }
-        core_connection_close(_client_fb.core_connection);
-        core_connection_free(_client_fb.core_connection);
-        _client_fb.core_connection = NULL;
-        return NULL;
-    }
-
-    // We expect core framebuffer to return us bits per pixel property in
-    // the handshake message.
-    _client_fb.bits_per_pixel = 0;
-    if (connect_message != NULL) {
-        char* bpp = strstr(connect_message, "bitsperpixel=");
-        if (bpp != NULL) {
-            char* end;
-            bpp += strlen("bitsperpixel=");
-            end = strchr(bpp, ' ');
-            if (end == NULL) {
-                end = bpp + strlen(bpp);
-            }
-            _client_fb.bits_per_pixel = strtol(bpp, &end, 0);
-        }
-    }
-
-    if (!_client_fb.bits_per_pixel) {
-        derror("Unexpected core framebuffer reply: %s\n"
-               "Bits per pixel property is not there, or is invalid\n", connect_message);
-        core_connection_close(_client_fb.core_connection);
-        core_connection_free(_client_fb.core_connection);
-        _client_fb.core_connection = NULL;
-        return NULL;
-    }
-
-    // Now that we're connected lets initialize the descriptor.
-    _client_fb.fb = fb;
-    _client_fb.sock = core_connection_get_socket(_client_fb.core_connection);
-    _client_fb.fb_state = WAIT_HEADER;
-    _client_fb.reader_buffer = (uint8_t*)&_client_fb.update_header;
-    _client_fb.reader_offset = 0;
-    _client_fb.reader_bytes = sizeof(FBUpdateMessage);
-
-    if (connect_message != NULL) {
-        free(connect_message);
-    }
-
-    // At last setup read callback, and start receiving the updates.
-    if (qemu_set_fd_handler(_client_fb.sock, _clientfb_read_cb, NULL, &_client_fb)) {
-        derror("Unable to set up framebuffer read callback\n");
-        core_connection_close(_client_fb.core_connection);
-        core_connection_free(_client_fb.core_connection);
-        _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));
-
-    return &_client_fb;
-}
-
-void
-clientfb_destroy(ClientFramebuffer* client_fb)
-{
-    if (client_fb != NULL && client_fb->core_connection != NULL) {
-        // Disable the reader callback.
-        qemu_set_fd_handler(client_fb->sock, NULL, NULL, NULL);
-
-        // Close framebuffer connection.
-        core_connection_close(client_fb->core_connection);
-        core_connection_free(client_fb->core_connection);
-        client_fb->core_connection = NULL;
-    }
-}
diff --git a/android/framebuffer-ui.h b/android/framebuffer-ui.h
deleted file mode 100644
index 158f137..0000000
--- a/android/framebuffer-ui.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (C) 2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains UI-side framebuffer client that receives framebuffer updates
- * from the core.
- */
-
-#ifndef _ANDROID_FRAMEBUFFER_UI_H
-#define _ANDROID_FRAMEBUFFER_UI_H
-
-#include "console.h"
-#include "framebuffer.h"
-#include "android/looper.h"
-#include "android/async-utils.h"
-#include "android/core-connection.h"
-
-/* Descriptor for the framebuffer client. */
-typedef struct ClientFramebuffer ClientFramebuffer;
-
-/*
- * Creates framebuffer client, and connects it with the core.
- * Param:
- *  console_socket Address of the core's console socket.
- *  protocol Protocol to use for the updates:
- *      -raw Stream pixels over socket
- *      -shared Use shared memory for pixels.
- * fb - Framebuffer associated with this FB client.
- * Return:
- *  Descriptor for the framebuffer client on success, or NULL on failure.
- */
-ClientFramebuffer* clientfb_create(SockAddress* console_socket,
-                                   const char* protocol,
-                                   QFrameBuffer* fb);
-
-/*
- * Disconnects and destroys framebuffer client.
- * Param:
- *  client_fb Framebuffer client descriptor created with clientfb_create.
- */
-void clientfb_destroy(ClientFramebuffer* client_fb);
-
-#endif /* _ANDROID_FRAMEBUFFER_UI_H */
diff --git a/android/main-ui.c b/android/main-ui.c
index 4b86ad1..968eeeb 100644
--- a/android/main-ui.c
+++ b/android/main-ui.c
@@ -60,7 +60,7 @@
 
 #include "android/snapshot.h"
 #include "android/core-connection.h"
-#include "android/framebuffer-ui.h"
+#include "android/protocol/fb-updates-impl.h"
 #include "android/protocol/user-events-proxy.h"
 #include "android/protocol/core-commands-proxy.h"
 #include "android/protocol/ui-commands-impl.h"
@@ -106,9 +106,6 @@
 /* Instance of the "attach-UI" Emulator's core console client. */
 CoreConnection*   attach_client = NULL;
 
-/* Instance of the "framebuffer" console client. */
-ClientFramebuffer* fb_client = NULL;
-
 /* -ui-settings parameters received from the core on UI attachment. */
 char* core_ui_settings = "";
 
@@ -960,9 +957,8 @@
     qemulator_set_title(emulator);
 
     // Connect to the core's framebuffer service
-    fb_client = clientfb_create(&console_socket, "-raw",
-                                qemulator_get_first_framebuffer(emulator));
-    if (fb_client == NULL) {
+    if (implFb_create(&console_socket, "-raw",
+                        qemulator_get_first_framebuffer(emulator))) {
         return -1;
     }
 
diff --git a/android/protocol/fb-updates-impl.c b/android/protocol/fb-updates-impl.c
new file mode 100644
index 0000000..ebe7309
--- /dev/null
+++ b/android/protocol/fb-updates-impl.c
@@ -0,0 +1,264 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+
+/*
+ * Contains UI-side framebuffer client that receives framebuffer updates
+ * from the core.
+ */
+
+#include "sysemu.h"
+#include "android/utils/system.h"
+#include "android/utils/debug.h"
+#include "android/utils/panic.h"
+#include "android/sync-utils.h"
+#include "android/protocol/fb-updates.h"
+#include "android/protocol/fb-updates-impl.h"
+
+/*Enumerates states for the client framebuffer update reader. */
+typedef enum ImplFBState {
+    /* The reader is waiting on update header. */
+    EXPECTS_HEADER,
+
+    /* The reader is waiting on pixels. */
+    EXPECTS_PIXELS,
+} ImplFBState;
+
+/* Descriptor for the UI-side implementation of the "framebufer" service.
+ */
+typedef struct ImplFramebuffer {
+    /* Framebuffer for this client. */
+    QFrameBuffer*   fb;
+
+    /* Core connection instance for the framebuffer client. */
+    CoreConnection* core_connection;
+
+    /* Current update header. */
+    FBUpdateMessage update_header;
+
+    /* Reader's buffer. */
+    uint8_t*        reader_buffer;
+
+    /* Offset in the reader's buffer where to read next chunk of data. */
+    size_t          reader_offset;
+
+    /* Total number of bytes the reader expects to read. */
+    size_t          reader_bytes;
+
+    /* Current state of the update reader. */
+    ImplFBState     fb_state;
+
+    /* Socket descriptor for the framebuffer client. */
+    int             sock;
+
+    /* Number of bits used to encode single pixel. */
+    int             bits_per_pixel;
+} ImplFramebuffer;
+
+/* One and the only ImplFramebuffer instance. */
+static ImplFramebuffer _implFb;
+
+/*
+ * Updates a display rectangle.
+ * Param
+ *  fb - Framebuffer where to update the rectangle.
+ *  x, y, w, and h define rectangle to update.
+ *  bits_per_pixel define number of bits used to encode a single pixel.
+ *  pixels contains pixels for the rectangle. Buffer addressed by this parameter
+ *      must be eventually freed with free()
+ */
+static void
+_update_rect(QFrameBuffer* fb, uint16_t x, uint16_t y, uint16_t w, uint16_t h,
+             uint8_t bits_per_pixel, uint8_t* pixels)
+{
+    if (fb != NULL) {
+        uint16_t n;
+        const uint8_t* src = pixels;
+        const uint16_t src_line_size = w * ((bits_per_pixel + 7) / 8);
+        uint8_t* dst  = (uint8_t*)fb->pixels + y * fb->pitch + x *
+                        fb->bytes_per_pixel;
+        for (n = 0; n < h; n++) {
+            memcpy(dst, src, src_line_size);
+            src += src_line_size;
+            dst += fb->pitch;
+        }
+        qframebuffer_update(fb, x, y, w, h);
+    }
+    free(pixels);
+}
+
+/*
+ * Asynchronous I/O callback launched when framebuffer notifications are ready
+ * to be read.
+ * Param:
+ *  opaque - ImplFramebuffer instance.
+ */
+static void
+_implFb_read_cb(void* opaque)
+{
+    ImplFramebuffer* fb_client = opaque;
+    int  ret;
+
+    // Read updates while they are immediately available.
+    for (;;) {
+        // Read next chunk of data.
+        ret = read(fb_client->sock, fb_client->reader_buffer + fb_client->reader_offset,
+                   fb_client->reader_bytes - fb_client->reader_offset);
+        if (ret == 0) {
+            /* disconnection ! */
+            implFb_destroy();
+            return;
+        }
+        if (ret < 0) {
+            if (errno == EINTR) {
+                /* loop on EINTR */
+                continue;
+            } else if (errno == EWOULDBLOCK || errno == EAGAIN) {
+                // Chunk is not avalable at this point. Come back later.
+                return;
+            }
+        }
+
+        fb_client->reader_offset += ret;
+        if (fb_client->reader_offset != fb_client->reader_bytes) {
+            // There are still some data left in the pipe.
+            continue;
+        }
+
+        // All expected data has been read. Time to change the state.
+        if (fb_client->fb_state == EXPECTS_HEADER) {
+            // Update header has been read. Prepare for the pixels.
+            fb_client->fb_state = EXPECTS_PIXELS;
+            fb_client->reader_offset = 0;
+            fb_client->reader_bytes = fb_client->update_header.w *
+                                      fb_client->update_header.h *
+                                      (fb_client->bits_per_pixel / 8);
+            fb_client->reader_buffer = malloc(fb_client->reader_bytes);
+            if (fb_client->reader_buffer == NULL) {
+                APANIC("Unable to allocate memory for framebuffer update\n");
+            }
+        } else {
+            // Pixels have been read. Prepare for the header.
+             uint8_t* pixels = fb_client->reader_buffer;
+
+            fb_client->fb_state = EXPECTS_HEADER;
+            fb_client->reader_offset = 0;
+            fb_client->reader_bytes = sizeof(FBUpdateMessage);
+            fb_client->reader_buffer = (uint8_t*)&fb_client->update_header;
+
+            // Perform the update. Note that pixels buffer must be freed there.
+            _update_rect(fb_client->fb, fb_client->update_header.x,
+                        fb_client->update_header.y, fb_client->update_header.w,
+                        fb_client->update_header.h, fb_client->bits_per_pixel,
+                        pixels);
+        }
+    }
+}
+
+int
+implFb_create(SockAddress* console_socket, const char* protocol, QFrameBuffer* fb)
+{
+    char* handshake = NULL;
+    char switch_cmd[256];
+
+    // Initialize descriptor.
+    _implFb.fb = fb;
+    _implFb.reader_buffer = (uint8_t*)&_implFb.update_header;
+    _implFb.reader_offset = 0;
+    _implFb.reader_bytes = sizeof(FBUpdateMessage);
+
+    // Connect to the framebuffer service.
+    snprintf(switch_cmd, sizeof(switch_cmd), "framebuffer %s", protocol);
+    _implFb.core_connection =
+        core_connection_create_and_switch(console_socket, switch_cmd, &handshake);
+    if (_implFb.core_connection == NULL) {
+        derror("Unable to connect to the framebuffer service: %s\n",
+               errno_str);
+        return -1;
+    }
+
+    // We expect core framebuffer to return us bits per pixel property in
+    // the handshake message.
+    _implFb.bits_per_pixel = 0;
+    if (handshake != NULL) {
+        char* bpp = strstr(handshake, "bitsperpixel=");
+        if (bpp != NULL) {
+            char* end;
+            bpp += strlen("bitsperpixel=");
+            end = strchr(bpp, ' ');
+            if (end == NULL) {
+                end = bpp + strlen(bpp);
+            }
+            _implFb.bits_per_pixel = strtol(bpp, &end, 0);
+        }
+    }
+    if (!_implFb.bits_per_pixel) {
+        derror("Unexpected core framebuffer reply: %s\n"
+               "Bits per pixel property is not there, or is invalid\n",
+               handshake);
+        implFb_destroy();
+        return -1;
+    }
+
+    _implFb.sock = core_connection_get_socket(_implFb.core_connection);
+
+    // At last setup read callback, and start receiving the updates.
+    if (qemu_set_fd_handler(_implFb.sock, _implFb_read_cb, NULL, &_implFb)) {
+        derror("Unable to set up framebuffer read callback.\n");
+        implFb_destroy();
+        return -1;
+    }
+    {
+        // Force the core to send us entire framebuffer now, when we're prepared
+        // to receive it.
+        FBRequestHeader hd;
+        SyncSocket* sk = syncsocket_init(_implFb.sock);
+
+        hd.request_type = AFB_REQUEST_REFRESH;
+        syncsocket_start_write(sk);
+        syncsocket_write(sk, &hd, sizeof(hd), 5000);
+        syncsocket_stop_write(sk);
+        syncsocket_free(sk);
+    }
+
+    fprintf(stdout, "framebuffer is now connected to the core at %s.",
+            sock_address_to_string(console_socket));
+    if (handshake != NULL) {
+        if (handshake[0] != '\0') {
+            fprintf(stdout, " Handshake: %s", handshake);
+        }
+        free(handshake);
+    }
+    fprintf(stdout, "\n");
+
+    return 0;
+}
+
+void
+implFb_destroy(void)
+{
+    if (_implFb.core_connection != NULL) {
+        // Disable the reader callback.
+        qemu_set_fd_handler(_implFb.sock, NULL, NULL, NULL);
+
+        // Close framebuffer connection.
+        core_connection_close(_implFb.core_connection);
+        core_connection_free(_implFb.core_connection);
+        _implFb.core_connection = NULL;
+    }
+
+    _implFb.fb = NULL;
+    if (_implFb.reader_buffer != NULL &&
+        _implFb.reader_buffer != (uint8_t*)&_implFb.update_header) {
+        free(_implFb.reader_buffer);
+        _implFb.reader_buffer = (uint8_t*)&_implFb.update_header;
+    }
+}
diff --git a/android/protocol/fb-updates-impl.h b/android/protocol/fb-updates-impl.h
new file mode 100644
index 0000000..0c351aa
--- /dev/null
+++ b/android/protocol/fb-updates-impl.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+
+/*
+ * Contains UI-side "framebuffer" client that receives framebuffer updates
+ * from the Core.
+ */
+
+#ifndef _ANDROID_FRAMEBUFFER_UI_H
+#define _ANDROID_FRAMEBUFFER_UI_H
+
+#include "console.h"
+#include "framebuffer.h"
+#include "android/looper.h"
+#include "android/async-utils.h"
+#include "android/core-connection.h"
+
+/* Creates framebuffer client, and connects it with the core.
+ * Param:
+ *  console_socket Address of the core's console socket.
+ *  protocol Protocol to use for the updates:
+ *      -raw Stream pixels over socket
+ *      -shared Use shared memory for pixels.
+ * fb - Framebuffer associated with this FB client.
+ * Return:
+ *  0 on success, or < 0 on failure.
+ */
+int implFb_create(SockAddress* console_socket,
+                  const char* protocol,
+                  QFrameBuffer* fb);
+
+/* Disconnects and destroys framebuffer client. */
+void implFb_destroy(void);
+
+#endif /* _ANDROID_FRAMEBUFFER_UI_H */
diff --git a/android/framebuffer-core.c b/android/protocol/fb-updates-proxy.c
similarity index 64%
rename from android/framebuffer-core.c
rename to android/protocol/fb-updates-proxy.c
index 89b7b46..fee1195 100644
--- a/android/framebuffer-core.c
+++ b/android/protocol/fb-updates-proxy.c
@@ -20,13 +20,14 @@
 #include "android/looper.h"
 #include "android/display-core.h"
 #include "android/async-utils.h"
-#include "android/framebuffer-common.h"
-#include "android/framebuffer-core.h"
+#include "android/protocol/fb-updates.h"
+#include "android/protocol/fb-updates-proxy.h"
 #include "android/utils/system.h"
 #include "android/utils/debug.h"
 
-/* Core framebuffer descriptor. */
-struct CoreFramebuffer {
+/* Descriptor for the Core-side implementation of the "framebufer" service.
+ */
+struct ProxyFramebuffer {
     /* Writer used to send FB update notification messages. */
     AsyncWriter             fb_update_writer;
 
@@ -55,13 +56,13 @@
     FBRequestHeader         fb_req_header;
 };
 
-/* Framebuffer update notification descriptor to the core. */
+/* Framebuffer update notification descriptor. */
 typedef struct FBUpdateNotify {
     /* Links all pending FB update notifications. */
     struct FBUpdateNotify*  next_fb_update;
 
     /* Core framebuffer instance that owns the message. */
-    CoreFramebuffer*        core_fb;
+    ProxyFramebuffer*       proxy_fb;
 
     /* Size of the message to transfer. */
     size_t                  message_size;
@@ -112,14 +113,14 @@
  *  Initialized framebuffer update notification descriptor.
  */
 static FBUpdateNotify*
-fbupdatenotify_create(CoreFramebuffer* core_fb, const QFrameBuffer* fb,
+fbupdatenotify_create(ProxyFramebuffer* proxy_fb, const QFrameBuffer* fb,
                       int x, int y, int w, int h)
 {
     const size_t rect_size = w * h * fb->bytes_per_pixel;
     FBUpdateNotify* ret = malloc(sizeof(FBUpdateNotify) + rect_size);
 
     ret->next_fb_update = NULL;
-    ret->core_fb = core_fb;
+    ret->proxy_fb = proxy_fb;
     ret->message_size = sizeof(FBUpdateMessage) + rect_size;
     ret->message.x = x;
     ret->message.y = y;
@@ -149,23 +150,23 @@
  * Asynchronous write I/O callback launched when writing framebuffer
  * notifications to the socket.
  * Param:
- *  core_fb - CoreFramebuffer instance.
+ *  proxy_fb - ProxyFramebuffer instance.
  */
 static void
-corefb_io_write(CoreFramebuffer* core_fb)
+_proxyFb_io_write(ProxyFramebuffer* proxy_fb)
 {
-    while (core_fb->fb_update_head != NULL) {
-        FBUpdateNotify* current_update = core_fb->fb_update_head;
+    while (proxy_fb->fb_update_head != NULL) {
+        FBUpdateNotify* current_update = proxy_fb->fb_update_head;
         // Lets continue writing of the current notification.
         const AsyncStatus status =
-            asyncWriter_write(&core_fb->fb_update_writer, &core_fb->io);
+            asyncWriter_write(&proxy_fb->fb_update_writer, &proxy_fb->io);
         switch (status) {
             case ASYNC_COMPLETE:
                 // Done with the current update. Move on to the next one.
                 break;
             case ASYNC_ERROR:
                 // Done with the current update. Move on to the next one.
-                loopIo_dontWantWrite(&core_fb->io);
+                loopIo_dontWantWrite(&proxy_fb->io);
                 break;
 
             case ASYNC_NEED_MORE:
@@ -174,18 +175,18 @@
         }
 
         // Advance the list of updates
-        core_fb->fb_update_head = current_update->next_fb_update;
-        if (core_fb->fb_update_head == NULL) {
-            core_fb->fb_update_tail = NULL;
+        proxy_fb->fb_update_head = current_update->next_fb_update;
+        if (proxy_fb->fb_update_head == NULL) {
+            proxy_fb->fb_update_tail = NULL;
         }
         fbupdatenotify_delete(current_update);
 
-        if (core_fb->fb_update_head != NULL) {
+        if (proxy_fb->fb_update_head != NULL) {
             // Schedule the next one.
-            asyncWriter_init(&core_fb->fb_update_writer,
-                             &core_fb->fb_update_head->message,
-                             core_fb->fb_update_head->message_size,
-                             &core_fb->io);
+            asyncWriter_init(&proxy_fb->fb_update_writer,
+                             &proxy_fb->fb_update_head->message,
+                             proxy_fb->fb_update_head->message_size,
+                             &proxy_fb->io);
         }
     }
 }
@@ -194,34 +195,35 @@
  * Asynchronous read I/O callback launched when reading framebuffer requests
  * from the socket.
  * Param:
- *  core_fb - CoreFramebuffer instance.
+ *  proxy_fb - ProxyFramebuffer instance.
  */
 static void
-corefb_io_read(CoreFramebuffer* core_fb)
+_proxyFb_io_read(ProxyFramebuffer* proxy_fb)
 {
     // Read the request header.
     const AsyncStatus status =
-        asyncReader_read(&core_fb->fb_req_reader, &core_fb->io);
+        asyncReader_read(&proxy_fb->fb_req_reader, &proxy_fb->io);
     switch (status) {
         case ASYNC_COMPLETE:
             // Request header is received
-            switch (core_fb->fb_req_header.request_type) {
+            switch (proxy_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);
+                    proxyFb_update(proxy_fb, proxy_fb->fb,
+                                  0, 0, proxy_fb->fb->width,
+                                  proxy_fb->fb->height);
                     break;
                 default:
                     derror("Unknown framebuffer request %d\n",
-                           core_fb->fb_req_header.request_type);
+                           proxy_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);
+            proxy_fb->fb_req_header.request_type = -1;
+            asyncReader_init(&proxy_fb->fb_req_reader, &proxy_fb->fb_req_header,
+                             sizeof(proxy_fb->fb_req_header), &proxy_fb->io);
             break;
         case ASYNC_ERROR:
-            loopIo_dontWantRead(&core_fb->io);
+            loopIo_dontWantRead(&proxy_fb->io);
             if (errno == ECONNRESET) {
                 // UI has exited. We need to destroy framebuffer service.
                 destroy_control_fb_client();
@@ -238,93 +240,93 @@
  * Asynchronous I/O callback launched when writing framebuffer notifications
  * to the socket.
  * Param:
- *  opaque - CoreFramebuffer instance.
+ *  opaque - ProxyFramebuffer instance.
  */
 static void
-corefb_io_func(void* opaque, int fd, unsigned events)
+_proxyFb_io_fun(void* opaque, int fd, unsigned events)
 {
     if (events & LOOP_IO_READ) {
-        corefb_io_read((CoreFramebuffer*)opaque);
+        _proxyFb_io_read((ProxyFramebuffer*)opaque);
     } else if (events & LOOP_IO_WRITE) {
-        corefb_io_write((CoreFramebuffer*)opaque);
+        _proxyFb_io_write((ProxyFramebuffer*)opaque);
     }
 }
 
-CoreFramebuffer*
-corefb_create(int sock, const char* protocol, QFrameBuffer* fb)
+ProxyFramebuffer*
+proxyFb_create(int sock, const char* protocol, QFrameBuffer* fb)
 {
     // At this point we're implementing the -raw protocol only.
-    CoreFramebuffer* ret;
+    ProxyFramebuffer* ret;
     ANEW0(ret);
     ret->sock = sock;
     ret->looper = looper_newCore();
     ret->fb = fb;
     ret->fb_update_head = NULL;
     ret->fb_update_tail = NULL;
-    loopIo_init(&ret->io, ret->looper, sock, corefb_io_func, ret);
+    loopIo_init(&ret->io, ret->looper, sock, _proxyFb_io_fun, ret);
     asyncReader_init(&ret->fb_req_reader, &ret->fb_req_header,
                      sizeof(ret->fb_req_header), &ret->io);
     return ret;
 }
 
 void
-corefb_destroy(CoreFramebuffer* core_fb)
+proxyFb_destroy(ProxyFramebuffer* proxy_fb)
 {
-    if (core_fb != NULL) {
-        if (core_fb->looper != NULL) {
+    if (proxy_fb != NULL) {
+        if (proxy_fb->looper != NULL) {
             // Stop all I/O that may still be going on.
-            loopIo_done(&core_fb->io);
+            loopIo_done(&proxy_fb->io);
             // Delete all pending frame updates.
-            while (core_fb->fb_update_head != NULL) {
-                FBUpdateNotify* pending_update = core_fb->fb_update_head;
-                core_fb->fb_update_head = pending_update->next_fb_update;
+            while (proxy_fb->fb_update_head != NULL) {
+                FBUpdateNotify* pending_update = proxy_fb->fb_update_head;
+                proxy_fb->fb_update_head = pending_update->next_fb_update;
                 fbupdatenotify_delete(pending_update);
             }
-            core_fb->fb_update_tail = NULL;
-            looper_free(core_fb->looper);
-            core_fb->looper = NULL;
+            proxy_fb->fb_update_tail = NULL;
+            looper_free(proxy_fb->looper);
+            proxy_fb->looper = NULL;
         }
     }
 }
 
 void
-corefb_update(CoreFramebuffer* core_fb,
+proxyFb_update(ProxyFramebuffer* proxy_fb,
               struct QFrameBuffer* fb, int x, int y, int w, int h)
 {
     AsyncStatus status;
-    FBUpdateNotify* descr = fbupdatenotify_create(core_fb, fb, x, y, w, h);
+    FBUpdateNotify* descr = fbupdatenotify_create(proxy_fb, fb, x, y, w, h);
 
     // Lets see if we should list it behind other pending updates.
-    if (core_fb->fb_update_tail != NULL) {
-        core_fb->fb_update_tail->next_fb_update = descr;
-        core_fb->fb_update_tail = descr;
+    if (proxy_fb->fb_update_tail != NULL) {
+        proxy_fb->fb_update_tail->next_fb_update = descr;
+        proxy_fb->fb_update_tail = descr;
         return;
     }
 
     // We're first in the list. Just send it now.
-    core_fb->fb_update_head = core_fb->fb_update_tail = descr;
-    asyncWriter_init(&core_fb->fb_update_writer,
-                     &core_fb->fb_update_head->message,
-                     core_fb->fb_update_head->message_size, &core_fb->io);
-    status = asyncWriter_write(&core_fb->fb_update_writer, &core_fb->io);
+    proxy_fb->fb_update_head = proxy_fb->fb_update_tail = descr;
+    asyncWriter_init(&proxy_fb->fb_update_writer,
+                     &proxy_fb->fb_update_head->message,
+                     proxy_fb->fb_update_head->message_size, &proxy_fb->io);
+    status = asyncWriter_write(&proxy_fb->fb_update_writer, &proxy_fb->io);
     switch (status) {
         case ASYNC_COMPLETE:
             fbupdatenotify_delete(descr);
-            core_fb->fb_update_head = core_fb->fb_update_tail = NULL;
+            proxy_fb->fb_update_head = proxy_fb->fb_update_tail = NULL;
             return;
         case ASYNC_ERROR:
             fbupdatenotify_delete(descr);
-            core_fb->fb_update_head = core_fb->fb_update_tail = NULL;
+            proxy_fb->fb_update_head = proxy_fb->fb_update_tail = NULL;
             return;
         case ASYNC_NEED_MORE:
-            // Update transfer will eventually complete in corefb_io_func
+            // Update transfer will eventually complete in _proxyFb_io_fun
             return;
     }
 }
 
 int
-corefb_get_bits_per_pixel(CoreFramebuffer* core_fb)
+proxyFb_get_bits_per_pixel(ProxyFramebuffer* proxy_fb)
 {
-    return (core_fb != NULL && core_fb->fb != NULL) ?
-                                                core_fb->fb->bits_per_pixel : -1;
+    return (proxy_fb != NULL && proxy_fb->fb != NULL) ?
+                                            proxy_fb->fb->bits_per_pixel : -1;
 }
diff --git a/android/framebuffer-core.h b/android/protocol/fb-updates-proxy.h
similarity index 66%
rename from android/framebuffer-core.h
rename to android/protocol/fb-updates-proxy.h
index 773c248..e750f1a 100644
--- a/android/framebuffer-core.h
+++ b/android/protocol/fb-updates-proxy.h
@@ -15,11 +15,11 @@
  * to the UI connected to the core.
  */
 
-#ifndef _ANDROID_FRAMEBUFFER_CORE_H
-#define _ANDROID_FRAMEBUFFER_CORE_H
+#ifndef _ANDROID_PROTOCOL_FB_UPDATES_PROXY_H
+#define _ANDROID_PROTOCOL_FB_UPDATES_PROXY_H
 
 /* Descriptor for a framebuffer core service instance */
-typedef struct CoreFramebuffer CoreFramebuffer;
+typedef struct ProxyFramebuffer ProxyFramebuffer;
 
 /*
  * Creates framebuffer service.
@@ -33,32 +33,32 @@
  * Return:
  *  Framebuffer service descriptor.
  */
-CoreFramebuffer* corefb_create(int sock, const char* protocol, struct QFrameBuffer* fb);
+ProxyFramebuffer* proxyFb_create(int sock, const char* protocol, struct QFrameBuffer* fb);
 
 /*
- * Destroys framebuffer service created with corefb_create.
+ * Destroys framebuffer service created with proxyFb_create.
  * Param:
- *  core_fb - Framebuffer service descriptor created with corefb_create
+ *  core_fb - Framebuffer service descriptor created with proxyFb_create
  */
-void corefb_destroy(CoreFramebuffer* core_fb);
+void proxyFb_destroy(ProxyFramebuffer* core_fb);
 
 /*
  * Notifies framebuffer client about changes in framebuffer.
  * Param:
- *  core_fb - Framebuffer service descriptor created with corefb_create
+ *  core_fb - Framebuffer service descriptor created with proxyFb_create
  *  fb Framebuffer containing pixels.
  *  x, y, w, and h identify the rectangle that has benn changed.
  */
-void corefb_update(CoreFramebuffer* core_fb, struct QFrameBuffer* fb,
+void proxyFb_update(ProxyFramebuffer* core_fb, struct QFrameBuffer* fb,
                    int x, int y, int w, int h);
 
 /*
  * Gets number of bits used to encode a single pixel.
  * Param:
- *  core_fb - Framebuffer service descriptor created with corefb_create
+ *  core_fb - Framebuffer service descriptor created with proxyFb_create
  * Return:
  *  Number of bits used to encode a single pixel.
  */
-int corefb_get_bits_per_pixel(CoreFramebuffer* core_fb);
+int proxyFb_get_bits_per_pixel(ProxyFramebuffer* core_fb);
 
-#endif /* _ANDROID_FRAMEBUFFER_CORE_H */
+#endif /* _ANDROID_PROTOCOL_FB_UPDATES_PROXY_H */
diff --git a/android/framebuffer-common.h b/android/protocol/fb-updates.h
similarity index 69%
rename from android/framebuffer-common.h
rename to android/protocol/fb-updates.h
index da773b7..c4f9779 100644
--- a/android/framebuffer-common.h
+++ b/android/protocol/fb-updates.h
@@ -11,14 +11,19 @@
 */
 
 /*
- * Contains framebuffer declarations that are shared by the core and the UI.
+ * Contains the API for calling into the UI with Core's framebuffer updates.
  */
 
-#ifndef _ANDROID_FRAMEBUFFER_COMMON_H
-#define _ANDROID_FRAMEBUFFER_COMMON_H
+#ifndef _ANDROID_PROTOCOL_FB_UPDATES_H
+#define _ANDROID_PROTOCOL_FB_UPDATES_H
 
 #include "sysemu.h"
 
+/* Requests the Core to refresh framebuffer.
+ * This message is sent by the UI to the Core right after the UI is initialized.
+ * This message forces the Core to send a full display update back to the UI. */
+#define AFB_REQUEST_REFRESH     1
+
 /* Header of framebuffer update message sent from the core to the UI. */
 typedef struct FBUpdateMessage {
     /* x, y, w, and h identify the rectangle that is being updated. */
@@ -31,15 +36,10 @@
     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).
- */
+/* Header for framebuffer requests sent from the UI to the Core. */
 typedef struct FBRequestHeader {
     /* Request type. See AFB_REQUEST_XXX for the values. */
     uint8_t request_type;
 } FBRequestHeader;
 
-#endif /* _ANDROID_FRAMEBUFFER_UI_H */
+#endif /* _ANDROID_PROTOCOL_FB_UPDATES_H */
diff --git a/vl-android-ui.c b/vl-android-ui.c
index 828590d..c1ef7ae 100644
--- a/vl-android-ui.c
+++ b/vl-android-ui.c
@@ -42,7 +42,7 @@
 #include "android/utils/bufprint.h"
 #include "android/utils/system.h"
 #include "android/core-connection.h"
-#include "android/framebuffer-ui.h"
+#include "android/protocol/fb-updates-impl.h"
 
 #ifdef CONFIG_MEMCHECK
 #include "memcheck/memcheck.h"
@@ -206,8 +206,6 @@
 
 /* Instance of the "attach UI" Emulator's core console client. */
 extern CoreConnection*   attach_client;
-/* Instance of the "framebuffer" console client. */
-extern ClientFramebuffer*  fb_client;
 
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
@@ -603,10 +601,7 @@
         core_connection_free(attach_client);
     }
 
-    if (fb_client != NULL) {
-        clientfb_destroy(fb_client);
-        fb_client = NULL;
-    }
+    implFb_destroy();
 
     quit_timers();
     return 0;