Refactor the framebuffer service

Change-Id: I8ac4580af65b8d58976c97b77b309dd202e75003
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/protocol/fb-updates-proxy.c b/android/protocol/fb-updates-proxy.c
new file mode 100644
index 0000000..fee1195
--- /dev/null
+++ b/android/protocol/fb-updates-proxy.c
@@ -0,0 +1,332 @@
+/* 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 core-side framebuffer service that sends framebuffer updates
+ * to the UI connected to the core.
+ */
+
+#include "console.h"
+#include "framebuffer.h"
+#include "android/looper.h"
+#include "android/display-core.h"
+#include "android/async-utils.h"
+#include "android/protocol/fb-updates.h"
+#include "android/protocol/fb-updates-proxy.h"
+#include "android/utils/system.h"
+#include "android/utils/debug.h"
+
+/* Descriptor for the Core-side implementation of the "framebufer" service.
+ */
+struct ProxyFramebuffer {
+    /* 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;
+
+    /* Framebuffer used for this service. */
+    QFrameBuffer*           fb;
+
+    /* Looper used to communicate framebuffer updates. */
+    Looper* looper;
+
+    /* Head of the list of pending FB update notifications. */
+    struct FBUpdateNotify*  fb_update_head;
+
+    /* Tail of the list of pending FB update notifications. */
+    struct FBUpdateNotify*  fb_update_tail;
+
+    /* Socket used to communicate framebuffer updates. */
+    int     sock;
+
+    /* Framebuffer request header. */
+    FBRequestHeader         fb_req_header;
+};
+
+/* 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. */
+    ProxyFramebuffer*       proxy_fb;
+
+    /* Size of the message to transfer. */
+    size_t                  message_size;
+
+    /* Update message. */
+    FBUpdateMessage         message;
+} FBUpdateNotify;
+
+/*
+ * Gets pointer in framebuffer's pixels for the given pixel.
+ * Param:
+ *  fb Framebuffer containing pixels.
+ *  x, and y identify the pixel to get pointer for.
+ * Return:
+ *  Pointer in framebuffer's pixels for the given pixel.
+ */
+static const uint8_t*
+_pixel_offset(const QFrameBuffer* fb, int x, int y)
+{
+    return (const uint8_t*)fb->pixels + y * fb->pitch + x * fb->bytes_per_pixel;
+}
+
+/*
+ * Copies pixels from a framebuffer rectangle.
+ * Param:
+ *  rect - Buffer where to copy pixel.
+ *  fb - Framebuffer containing the rectangle to copy.
+ *  x, y, w, and h - dimensions of the rectangle to copy.
+ */
+static void
+_copy_fb_rect(uint8_t* rect, const QFrameBuffer* fb, int x, int y, int w, int h)
+{
+    const uint8_t* start = _pixel_offset(fb, x, y);
+    for (; h > 0; h--) {
+        memcpy(rect, start, w * fb->bytes_per_pixel);
+        start += fb->pitch;
+        rect += w * fb->bytes_per_pixel;
+    }
+}
+
+/*
+ * Allocates and initializes framebuffer update notification descriptor.
+ * Param:
+ *  ds - Display state for the framebuffer.
+ *  fb Framebuffer containing pixels.
+ *  x, y, w, and h identify the rectangle that is being updated.
+ * Return:
+ *  Initialized framebuffer update notification descriptor.
+ */
+static FBUpdateNotify*
+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->proxy_fb = proxy_fb;
+    ret->message_size = sizeof(FBUpdateMessage) + rect_size;
+    ret->message.x = x;
+    ret->message.y = y;
+    ret->message.w = w;
+    ret->message.h = h;
+    _copy_fb_rect(ret->message.rect, fb, x, y, w, h);
+    return ret;
+}
+
+/*
+ * Deletes FBUpdateNotify descriptor, created with fbupdatenotify_create.
+ * Param:
+ *  desc - Descreptor to delete.
+ */
+static void
+fbupdatenotify_delete(FBUpdateNotify* desc)
+{
+    if (desc != NULL) {
+        free(desc);
+    }
+}
+
+/* Implemented in android/console.c */
+extern void destroy_control_fb_client(void);
+
+/*
+ * Asynchronous write I/O callback launched when writing framebuffer
+ * notifications to the socket.
+ * Param:
+ *  proxy_fb - ProxyFramebuffer instance.
+ */
+static void
+_proxyFb_io_write(ProxyFramebuffer* proxy_fb)
+{
+    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(&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(&proxy_fb->io);
+                break;
+
+            case ASYNC_NEED_MORE:
+                // Transfer will eventually come back into this routine.
+                return;
+        }
+
+        // Advance the list of updates
+        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 (proxy_fb->fb_update_head != NULL) {
+            // Schedule the next one.
+            asyncWriter_init(&proxy_fb->fb_update_writer,
+                             &proxy_fb->fb_update_head->message,
+                             proxy_fb->fb_update_head->message_size,
+                             &proxy_fb->io);
+        }
+    }
+}
+
+/*
+ * Asynchronous read I/O callback launched when reading framebuffer requests
+ * from the socket.
+ * Param:
+ *  proxy_fb - ProxyFramebuffer instance.
+ */
+static void
+_proxyFb_io_read(ProxyFramebuffer* proxy_fb)
+{
+    // Read the request header.
+    const AsyncStatus status =
+        asyncReader_read(&proxy_fb->fb_req_reader, &proxy_fb->io);
+    switch (status) {
+        case ASYNC_COMPLETE:
+            // Request header is received
+            switch (proxy_fb->fb_req_header.request_type) {
+                case AFB_REQUEST_REFRESH:
+                    // Force full screen update to be sent
+                    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",
+                           proxy_fb->fb_req_header.request_type);
+                    break;
+            }
+            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(&proxy_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 - ProxyFramebuffer instance.
+ */
+static void
+_proxyFb_io_fun(void* opaque, int fd, unsigned events)
+{
+    if (events & LOOP_IO_READ) {
+        _proxyFb_io_read((ProxyFramebuffer*)opaque);
+    } else if (events & LOOP_IO_WRITE) {
+        _proxyFb_io_write((ProxyFramebuffer*)opaque);
+    }
+}
+
+ProxyFramebuffer*
+proxyFb_create(int sock, const char* protocol, QFrameBuffer* fb)
+{
+    // At this point we're implementing the -raw protocol only.
+    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, _proxyFb_io_fun, ret);
+    asyncReader_init(&ret->fb_req_reader, &ret->fb_req_header,
+                     sizeof(ret->fb_req_header), &ret->io);
+    return ret;
+}
+
+void
+proxyFb_destroy(ProxyFramebuffer* proxy_fb)
+{
+    if (proxy_fb != NULL) {
+        if (proxy_fb->looper != NULL) {
+            // Stop all I/O that may still be going on.
+            loopIo_done(&proxy_fb->io);
+            // Delete all pending frame updates.
+            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);
+            }
+            proxy_fb->fb_update_tail = NULL;
+            looper_free(proxy_fb->looper);
+            proxy_fb->looper = NULL;
+        }
+    }
+}
+
+void
+proxyFb_update(ProxyFramebuffer* proxy_fb,
+              struct QFrameBuffer* fb, int x, int y, int w, int h)
+{
+    AsyncStatus status;
+    FBUpdateNotify* descr = fbupdatenotify_create(proxy_fb, fb, x, y, w, h);
+
+    // Lets see if we should list it behind other pending updates.
+    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.
+    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);
+            proxy_fb->fb_update_head = proxy_fb->fb_update_tail = NULL;
+            return;
+        case ASYNC_ERROR:
+            fbupdatenotify_delete(descr);
+            proxy_fb->fb_update_head = proxy_fb->fb_update_tail = NULL;
+            return;
+        case ASYNC_NEED_MORE:
+            // Update transfer will eventually complete in _proxyFb_io_fun
+            return;
+    }
+}
+
+int
+proxyFb_get_bits_per_pixel(ProxyFramebuffer* proxy_fb)
+{
+    return (proxy_fb != NULL && proxy_fb->fb != NULL) ?
+                                            proxy_fb->fb->bits_per_pixel : -1;
+}
diff --git a/android/protocol/fb-updates-proxy.h b/android/protocol/fb-updates-proxy.h
new file mode 100644
index 0000000..e750f1a
--- /dev/null
+++ b/android/protocol/fb-updates-proxy.h
@@ -0,0 +1,64 @@
+/* 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 core-side framebuffer service that sends framebuffer updates
+ * to the UI connected to the core.
+ */
+
+#ifndef _ANDROID_PROTOCOL_FB_UPDATES_PROXY_H
+#define _ANDROID_PROTOCOL_FB_UPDATES_PROXY_H
+
+/* Descriptor for a framebuffer core service instance */
+typedef struct ProxyFramebuffer ProxyFramebuffer;
+
+/*
+ * Creates framebuffer service.
+ * Param:
+ *  sock - Socket descriptor for the service
+ *  protocol - Defines protocol to use when sending FB updates to the UI. The
+ *      supported values ar:
+ *      -raw Transfers the updating rectangle buffer over the socket.
+ *      -shared Used a shared memory to transfer the updating rectangle buffer.
+ *  fb - Framebuffer descriptor for this service.
+ * Return:
+ *  Framebuffer service descriptor.
+ */
+ProxyFramebuffer* proxyFb_create(int sock, const char* protocol, struct QFrameBuffer* fb);
+
+/*
+ * Destroys framebuffer service created with proxyFb_create.
+ * Param:
+ *  core_fb - Framebuffer service descriptor created with proxyFb_create
+ */
+void proxyFb_destroy(ProxyFramebuffer* core_fb);
+
+/*
+ * Notifies framebuffer client about changes in framebuffer.
+ * Param:
+ *  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 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 proxyFb_create
+ * Return:
+ *  Number of bits used to encode a single pixel.
+ */
+int proxyFb_get_bits_per_pixel(ProxyFramebuffer* core_fb);
+
+#endif /* _ANDROID_PROTOCOL_FB_UPDATES_PROXY_H */
diff --git a/android/protocol/fb-updates.h b/android/protocol/fb-updates.h
new file mode 100644
index 0000000..c4f9779
--- /dev/null
+++ b/android/protocol/fb-updates.h
@@ -0,0 +1,45 @@
+/* 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 the API for calling into the UI with Core's framebuffer updates.
+ */
+
+#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. */
+    uint16_t    x;
+    uint16_t    y;
+    uint16_t    w;
+    uint16_t    h;
+
+    /* Contains updating rectangle copied over from the framebuffer's pixels. */
+    uint8_t rect[0];
+} FBUpdateMessage;
+
+/* 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_PROTOCOL_FB_UPDATES_H */