Cherry-picked from d86c724b in master. Do not merge.

Implement ADB communication over QEMU pipe

Change-Id: I62ff5898c7a955aaaa8af8f7ee7ed018af860f80
diff --git a/Makefile.common b/Makefile.common
index 71100f3..a68e17e 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -425,7 +425,9 @@
     android/snapshot.c \
     android/utils/timezone.c \
     android/camera/camera-format-converters.c \
-    android/camera/camera-service.c
+    android/camera/camera-service.c \
+    android/adb-server.c \
+    android/adb-qemud.c
 
 $(call gen-hw-config-defs)
 
diff --git a/android/adb-qemud.c b/android/adb-qemud.c
new file mode 100644
index 0000000..bc51807
--- /dev/null
+++ b/android/adb-qemud.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "qemu-common.h"
+#include "android/globals.h"  /* for android_hw */
+#include "android/hw-qemud.h"
+#include "android/utils/misc.h"
+#include "android/utils/system.h"
+#include "android/utils/debug.h"
+#include "android/adb-server.h"
+#include "android/adb-qemud.h"
+
+#define  E(...)    derror(__VA_ARGS__)
+#define  W(...)    dwarning(__VA_ARGS__)
+#define  D(...)    VERBOSE_PRINT(adbclient,__VA_ARGS__)
+#define  D_ACTIVE  VERBOSE_CHECK(adbclient)
+#define  QB(b, s)  quote_bytes((const char*)b, (s < 32) ? s : 32)
+
+#define SERVICE_NAME    "adb"
+
+/* Enumerates ADB client state values. */
+typedef enum AdbClientState {
+    /* Waiting on a connection from ADB host. */
+    ADBC_STATE_WAIT_ON_HOST,
+    /* ADB host is connected. Waiting on the transport initialization completion
+     * in the guest. */
+    ADBC_STATE_HOST_CONNECTED,
+    /* Connection between ADB host and ADB guest is fully established. */
+    ADBC_STATE_CONNECTED,
+    /* ADB host has been disconnected. */
+    ADBC_STATE_HOST_DISCONNECTED,
+    /* ADB guest has been disconnected. */
+    ADBC_STATE_GUEST_DISCONNECTED,
+} AdbClientState;
+
+/* ADB client descriptor. */
+typedef struct AdbClient AdbClient;
+struct AdbClient {
+    /* Opaque pointer returned from adb_server_register_guest API. */
+    void*           opaque;
+    /* QEMUD client pipe for this client. */
+    QemudClient*    qemud_client;
+    /* Connection state. */
+    AdbClientState  state;
+};
+
+/********************************************************************************
+ *                      ADB host communication.
+ *******************************************************************************/
+
+/* A callback that is invoked when the host is connected.
+ * Param:
+ *  opaque - AdbClient instance.
+ *  connection - An opaque pointer that identifies connection with the ADB host.
+ */
+static void
+_adb_on_host_connected(void* opaque, void* connection)
+{
+    AdbClient* const adb_client = (AdbClient*)opaque;
+
+    if (adb_client->state == ADBC_STATE_WAIT_ON_HOST) {
+        D("ADB client %p(o=%p) is connected to the host %p",
+          adb_client, adb_client->opaque, connection);
+
+        /* Bump the state up. */
+         adb_client->state = ADBC_STATE_HOST_CONNECTED;
+
+        /* Notify the ADB guest that host has been  connected.This will unblock
+         * the guest from a 'read', then guest will register the transport, and
+         * will send 'setart' request, indicating that it is ready to receive
+         * data from the host. */
+        qemud_client_send(adb_client->qemud_client, (const uint8_t*)"ok", 2);
+    } else {
+        D("Unexpected ADB host connection while state is %d", adb_client->state);
+    }
+}
+
+/* A callback that is invoked when the host gets disconnected.
+ * Param:
+ *  opaque - AdbClient instance.
+ *  connection - An opaque pointer that identifies connection with the ADB host.
+ */
+static void
+_adb_on_host_disconnect(void* opaque, void* connection)
+{
+    AdbClient* const adb_client = (AdbClient*)opaque;
+
+    D("ADB client %p(o=%p) is disconnected from the host %p",
+      adb_client, adb_client->opaque, connection);
+    adb_client->state = ADBC_STATE_HOST_DISCONNECTED;
+}
+
+/* A callback that is invoked when the host sends data.
+ * Param:
+ *  opaque - AdbClient instance.
+ *  connection - An opaque pointer that identifies connection with the ADB host.
+ *  buff, size - Buffer containing the host data.
+ */
+static void
+_adb_on_host_data(void* opaque, void* connection, const void* buff, int size)
+{
+    AdbClient* const adb_client = (AdbClient*)opaque;
+    D("ADB client %p(o=%p) received from the host %p %d bytes in %s",
+      adb_client, adb_client->opaque, connection, size, QB(buff, size));
+
+    if (adb_client->state == ADBC_STATE_CONNECTED) {
+        /* Dispatch data down to the guest. */
+        qemud_client_send(adb_client->qemud_client, (const uint8_t*)buff, size);
+    } else {
+        D("Unexpected data from ADB host %p while client %p(o=%p) is in state %d",
+          connection, adb_client, adb_client->opaque, adb_client->state);
+    }
+}
+
+/* ADB guest API required for adb_server_register_guest */
+static AdbGuestRoutines _adb_client_routines = {
+    /* A callback that is invoked when the host is connected. */
+    _adb_on_host_connected,
+    /* A callback that is invoked when the host gets disconnected. */
+    _adb_on_host_disconnect,
+    /* A callback that is invoked when the host sends data. */
+    _adb_on_host_data,
+};
+
+/********************************************************************************
+ *                      ADB guest communication.
+ *******************************************************************************/
+
+/* Allocates AdbClient instance. */
+static AdbClient*
+_adb_client_new(void)
+{
+    AdbClient* adb_client;
+
+    ANEW0(adb_client);
+
+    return adb_client;
+}
+
+/* Frees AdbClient instance, allocated with _adb_client_new */
+static void
+_adb_client_free(AdbClient* adb_client)
+{
+    if (adb_client != NULL) {
+        free(adb_client);
+    }
+}
+
+/* A callback that is invoked when ADB guest sends data to the service.
+ * Param:
+ *  opaque - AdbClient instance.
+ *  msg, msglen - Message received from the ADB guest.
+ *  client - adb QEMUD client.
+ */
+static void
+_adb_client_recv(void* opaque, uint8_t* msg, int msglen, QemudClient* client)
+{
+    AdbClient* const adb_client = (AdbClient*)opaque;
+
+    D("ADB client %p(o=%p) received from guest %d bytes in %s",
+      adb_client, adb_client->opaque, msglen, QB(msg, msglen));
+
+    /* Properly dispatch the message, depending on the client state. */
+    switch (adb_client->state) {
+        case ADBC_STATE_CONNECTED:
+            /* Connection is fully established. Dispatch the message to the
+             * host. */
+            adb_server_on_guest_message(adb_client->opaque, msg, msglen);
+            break;
+
+        case ADBC_STATE_WAIT_ON_HOST:
+            /* At this state the only message that is allowed is 'accept' */
+            if (msglen == 6 && !memcmp(msg, "accept", 6)) {
+                /* Register ADB guest connection with the ADB server. */
+                adb_client->opaque =
+                    adb_server_register_guest(adb_client, &_adb_client_routines);
+                if (adb_client->opaque == NULL) {
+                    D("Unable to register ADB guest with the ADB server.");
+                    /* KO the guest. */
+                    qemud_client_send(adb_client->qemud_client,
+                                      (const uint8_t*)"ko", 2);
+                }
+            } else {
+                D("Unexpected guest request while waiting on ADB host to connect.");
+            }
+            break;
+
+        case ADBC_STATE_HOST_CONNECTED:
+            /* At this state the only message that is allowed is 'start' */
+            if (msglen == 5 && !memcmp(msg, "start", 5)) {
+                adb_client->state = ADBC_STATE_CONNECTED;
+                adb_server_complete_connection(adb_client->opaque);
+            } else {
+                D("Unexpected request while waiting on connection to start.");
+            }
+            break;
+
+        default:
+            D("Unexpected ADB guest request '%s' while client state is %d.",
+              QB(msg, msglen), adb_client->state);
+            break;
+    }
+}
+
+/* A callback that is invoked when ADB guest disconnects from the service. */
+static void
+_adb_client_close(void* opaque)
+{
+    AdbClient* const adb_client = (AdbClient*)opaque;
+
+    D("ADB client %p(o=%p) is disconnected from the guest.",
+      adb_client, adb_client->opaque);
+    adb_client->state = ADBC_STATE_GUEST_DISCONNECTED;
+    if (adb_client->opaque != NULL) {
+        /* Close connection with the host. */
+        adb_server_on_guest_closed(adb_client->opaque);
+    }
+    _adb_client_free(adb_client);
+}
+
+/* A callback that is invoked when ADB daemon running inside the guest connects
+ * to the service.
+ * Client parameters are ignored here. Typically they contain the ADB port number
+ * which is always 5555 for the device / emulated system.
+ */
+static QemudClient*
+_adb_service_connect(void*          opaque,
+                     QemudService*  serv,
+                     int            channel,
+                     const char*    client_param)
+{
+    /* Create new QEMUD client for the connection with ADB daemon. */
+    AdbClient* const adb_client = _adb_client_new();
+
+    D("Connecting ADB guest: '%s'", client_param ? client_param : "<null>");
+    adb_client->qemud_client =
+        qemud_client_new(serv, channel, client_param, adb_client,
+                         _adb_client_recv, _adb_client_close, NULL, NULL);
+    if (adb_client->qemud_client == NULL) {
+        D("Unable to create QEMUD client for ADB guest.");
+        _adb_client_free(adb_client);
+        return NULL;
+    }
+
+    return adb_client->qemud_client;
+}
+
+/********************************************************************************
+ *                      ADB service API.
+ *******************************************************************************/
+
+void
+android_adb_service_init(void)
+{
+static int _inited = 0;
+
+    if (!adb_server_is_initialized()) {
+        return;
+    }
+
+    if (!_inited) {
+        QemudService*  serv = qemud_service_register(SERVICE_NAME, 0, NULL,
+                                                     _adb_service_connect,
+                                                     NULL, NULL);
+        if (serv == NULL) {
+            derror("%s: Could not register '%s' service",
+                   __FUNCTION__, SERVICE_NAME);
+            return;
+        }
+        D("%s: Registered '%s' qemud service", __FUNCTION__, SERVICE_NAME);
+    }
+}
diff --git a/android/adb-qemud.h b/android/adb-qemud.h
new file mode 100644
index 0000000..a6fccbe
--- /dev/null
+++ b/android/adb-qemud.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ADB_PIPE_H_
+#define ANDROID_ADB_PIPE_H_
+
+/*
+ * Implements 'adb' QEMUD service that is responsible for the data exchange
+ * between the emulator and ADB daemon running on the guest.
+ */
+
+/* Initializes adb QEMUD service. */
+extern void android_adb_service_init(void);
+
+#endif  /* ANDROID_ADB_PIPE_H_ */
+
diff --git a/android/adb-server.c b/android/adb-server.c
new file mode 100644
index 0000000..41b2ffd
--- /dev/null
+++ b/android/adb-server.c
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "qemu-common.h"
+#include "sockets.h"
+#include "iolooper.h"
+#include "android/async-utils.h"
+#include "android/utils/debug.h"
+#include "android/utils/list.h"
+#include "android/utils/misc.h"
+#include "android/adb-server.h"
+
+#define  E(...)    derror(__VA_ARGS__)
+#define  W(...)    dwarning(__VA_ARGS__)
+#define  D(...)    VERBOSE_PRINT(adbserver,__VA_ARGS__)
+#define  D_ACTIVE  VERBOSE_CHECK(adbserver)
+#define  QB(b, s)  quote_bytes((const char*)b, (s < 32) ? s : 32)
+
+typedef struct AdbServer    AdbServer;
+typedef struct AdbHost      AdbHost;
+typedef struct AdbGuest     AdbGuest;
+
+/* ADB guest connection descriptor. */
+struct AdbGuest {
+    /* Entry in the list of pending or connected ADB guests.
+     * NOTE: This must be the first entry in the descriptor! */
+    ACList              list_entry;
+    /* Opaque pointer associated with the guest. */
+    void*               opaque;
+    /* ADB server for this guest. */
+    AdbServer*          adb_srv;
+    /* ADB host connected with this ADB guest. */
+    AdbHost*            adb_host;
+    /* Callback routines for the ADB guest. */
+    AdbGuestRoutines*   callbacks;
+    /* ADB guest connection status. If 0 indicates that ADB guest is not yet
+     * ready to receive data from the host. */
+    int                 is_connected;
+};
+
+/* ADB host connection descriptor. */
+struct AdbHost {
+    /* Entry in the list of pending or connected ADB hosts.
+     * NOTE: This must be the first entry in the descriptor! */
+    ACList      list_entry;
+    /* ADB server for this host. */
+    AdbServer*  adb_srv;
+    /* ADB socket connected with the host. */
+    int         host_so;
+    /* I/O port for asynchronous I/O on the host socket. */
+    LoopIo      io[1];
+    /* ADB guest connected with this ADB host. */
+    AdbGuest*   adb_guest;
+    /* Pending data to send to the guest when it is fully connected. */
+    uint8_t*    pending_data;
+    /* Size of the pending data buffer. */
+    int         pending_data_size;
+    /* Contains data that are pending to be sent to the host. */
+    uint8_t*    pending_send_buffer;
+    /* Number of bytes that are pending to be sent to the host. */
+    int         pending_send_data_size;
+    /* Size of the pending_send_buffer */
+    int         pending_send_buffer_size;
+};
+
+/* ADB server descriptor. */
+struct AdbServer {
+    /* ADB socket address. */
+    SockAddress socket_address;
+    /* Looper for async I/O on ADB server socket. */
+    Looper*     looper;
+    /* I/O port for asynchronous I/O on ADB server socket. */
+    LoopIo      io[1];
+    /* ADB port. */
+    int         port;
+    /* Server socket. */
+    int         so;
+    /* List of connected ADB hosts. */
+    ACList      adb_hosts;
+    /* List of connected ADB guests. */
+    ACList      adb_guests;
+    /* List of ADB hosts pending connection with ADB guest. */
+    ACList      pending_hosts;
+    /* List of ADB guests pending connection with ADB host. */
+    ACList      pending_guests;
+};
+
+/* One and only one ADB server instance. */
+static AdbServer    _adb_server;
+/* ADB server initialization flag. */
+static int          _adb_server_initialized = 0;
+
+/********************************************************************************
+ *                             ADB host API
+ *******************************************************************************/
+
+/* Creates and initializes a new AdbHost instance. */
+static AdbHost*
+_adb_host_new(AdbServer* adb_srv)
+{
+    AdbHost* adb_host;
+
+    ANEW0(adb_host);
+    alist_init(&adb_host->list_entry);
+    adb_host->adb_srv = adb_srv;
+    adb_host->host_so = -1;
+
+    return adb_host;
+}
+
+/* Frees AdbHost instance created with _adb_host_new routine. */
+static void
+_adb_host_free(AdbHost* adb_host)
+{
+    if (adb_host != NULL) {
+        /* At this point it must not be listed anywhere. */
+        assert(alist_is_empty(&adb_host->list_entry));
+
+        /* Close the host socket. */
+        if (adb_host->host_so >= 0) {
+            loopIo_done(adb_host->io);
+            socket_close(adb_host->host_so);
+        }
+
+        /* Free pending data buffers. */
+        if (adb_host->pending_data != NULL) {
+            free(adb_host->pending_data);
+        }
+        if (adb_host->pending_send_buffer != NULL) {
+            free(adb_host->pending_send_buffer);
+        }
+
+        AFREE(adb_host);
+    }
+}
+
+static void
+_adb_host_append_message(AdbHost* adb_host, const void* msg, int msglen)
+{
+    printf("Append %d bytes to ADB host buffer.\n", msglen);
+
+    /* Make sure that buffer can contain the appending data. */
+    if (adb_host->pending_send_buffer == NULL) {
+        adb_host->pending_send_buffer = (uint8_t*)malloc(msglen);
+        adb_host->pending_send_buffer_size = msglen;
+    } else if ((adb_host->pending_send_data_size + msglen) >
+               adb_host->pending_send_buffer_size) {
+        adb_host->pending_send_buffer =
+            (uint8_t*)realloc(adb_host->pending_send_buffer,
+                              adb_host->pending_send_data_size + msglen);
+        adb_host->pending_send_buffer_size =
+            adb_host->pending_send_data_size + msglen;
+    }
+
+    if (adb_host->pending_send_buffer == NULL) {
+        D("Unable to allocate %d bytes for pending ADB host data.",
+          adb_host->pending_send_data_size + msglen);
+        adb_host->pending_send_buffer_size = adb_host->pending_send_data_size = 0;
+        loopIo_dontWantWrite(adb_host->io);
+        return;
+    }
+
+    memcpy(adb_host->pending_send_buffer + adb_host->pending_send_data_size,
+           msg, msglen);
+    loopIo_wantWrite(adb_host->io);
+}
+
+/* Connects ADB host with ADB guest. */
+static void
+_adb_connect(AdbHost* adb_host, AdbGuest* adb_guest)
+{
+    D("Connecting ADB host %p(so=%d) with ADB guest %p(o=%p)",
+      adb_host, adb_host->host_so, adb_guest, adb_guest->opaque);
+
+    adb_guest->adb_host = adb_host;
+    adb_host->adb_guest = adb_guest;
+    adb_guest->callbacks->on_connected(adb_guest->opaque, adb_guest);
+}
+
+/* Callback invoked when ADB host socket gets disconnected. */
+static void
+_on_adb_host_disconnected(AdbHost* adb_host)
+{
+    AdbGuest* const adb_guest = adb_host->adb_guest;
+
+    /* Notify the ADB guest that the host got disconnected. */
+    if (adb_guest != NULL) {
+        D("Disconnecting ADB host %p(so=%d) from ADB guest %p(o=%p)",
+          adb_host, adb_host->host_so, adb_guest, adb_guest->opaque);
+        adb_host->adb_guest = NULL;
+        adb_guest->callbacks->on_disconnect(adb_guest->opaque, adb_guest);
+        adb_guest->adb_host = NULL;
+    } else {
+        D("Disconnecting ADB host %p(so=%d)", adb_host, adb_host->host_so);
+    }
+
+    /* Destroy the host. */
+    alist_remove(&adb_host->list_entry);
+    _adb_host_free(adb_host);
+
+    /* Remove the guest from the list. */
+    if (adb_guest != NULL) {
+        alist_remove(&adb_guest->list_entry);
+    }
+}
+
+/* Read I/O callback on ADB host socket. */
+static void
+_on_adb_host_read(AdbHost* adb_host)
+{
+    char buff[4096];
+
+    /* Read data from the socket. */
+    const int size = socket_recv(adb_host->host_so, buff, sizeof(buff));
+    if (size < 0) {
+        D("Error while reading from ADB host %p(so=%d). Error: %s",
+          adb_host, adb_host->host_so, strerror(errno));
+    } else if (size == 0) {
+        /* This is a "disconnect" condition. */
+        _on_adb_host_disconnected(adb_host);
+    } else {
+        D("%s %d bytes received from ADB host %p(so=%d): %s",
+           adb_host->adb_guest ? "Transfer" : "Pend", size, adb_host,
+           adb_host->host_so, QB(buff, size));
+
+        /* Lets see if there is an ADB guest associated with this host, and it
+         * is ready to receive host data. */
+        AdbGuest* const adb_guest = adb_host->adb_guest;
+        if (adb_guest != NULL && adb_guest->is_connected) {
+            /* Channel the data through... */
+            adb_guest->callbacks->on_read(adb_guest->opaque, adb_guest, buff, size);
+        } else {
+            /* Pend the data for the upcoming guest connection. */
+            if (adb_host->pending_data == NULL) {
+                adb_host->pending_data = malloc(size);
+            } else {
+                adb_host->pending_data = realloc(adb_host->pending_data,
+                                                 adb_host->pending_data_size + size);
+            }
+            if (adb_host->pending_data != NULL) {
+                memcpy(adb_host->pending_data + adb_host->pending_data_size,
+                       buff, size);
+                adb_host->pending_data_size += size;
+            } else {
+                D("Unable to (re)allocate %d bytes for pending ADB host data",
+                  adb_host->pending_data_size + size);
+            }
+        }
+    }
+}
+
+/* Write I/O callback on ADB host socket. */
+static void
+_on_adb_host_write(AdbHost* adb_host)
+{
+    while (adb_host->pending_send_data_size && adb_host->pending_send_buffer != NULL) {
+        const int sent = socket_send(adb_host->host_so,
+                                     adb_host->pending_send_buffer,
+                                     adb_host->pending_send_data_size);
+        if (sent < 0) {
+            if (errno == EWOULDBLOCK) {
+                /* Try again later. */
+                return;
+            } else {
+                D("Unable to send pending data to the ADB host: %s",
+                   strerror(errno));
+                free(adb_host->pending_send_buffer);
+                adb_host->pending_send_buffer = NULL;
+                adb_host->pending_send_buffer_size = 0;
+                adb_host->pending_send_data_size = 0;
+                break;
+            }
+        } else if (sent == 0) {
+            /* Disconnect condition. */
+            free(adb_host->pending_send_buffer);
+            adb_host->pending_send_buffer = NULL;
+            adb_host->pending_send_buffer_size = 0;
+            adb_host->pending_send_data_size = 0;
+            _on_adb_host_disconnected(adb_host);
+            break;
+        } else if (sent == adb_host->pending_send_data_size) {
+            free(adb_host->pending_send_buffer);
+            adb_host->pending_send_buffer = NULL;
+            adb_host->pending_send_buffer_size = 0;
+            adb_host->pending_send_data_size = 0;
+        } else {
+            adb_host->pending_send_data_size -= sent;
+            memmove(adb_host->pending_send_buffer,
+                    adb_host->pending_send_buffer + sent,
+                    adb_host->pending_send_data_size);
+            return;
+        }
+    }
+
+    loopIo_dontWantWrite(adb_host->io);
+}
+
+/* I/O callback on ADB host socket. */
+static void
+_on_adb_host_io(void* opaque, int fd, unsigned events)
+{
+    AdbHost* const adb_host = (AdbHost*)opaque;
+    assert(fd == adb_host->host_so);
+
+    /* Dispatch I/O to read / write handlers. */
+    if ((events & LOOP_IO_READ) != 0) {
+        _on_adb_host_read(adb_host);
+    }
+    if ((events & LOOP_IO_WRITE) != 0) {
+        _on_adb_host_write(adb_host);
+    }
+}
+
+/********************************************************************************
+ *                            ADB guest API
+ *******************************************************************************/
+
+/* Creates and initializes a new AdbGuest instance. */
+static AdbGuest*
+_adb_guest_new(AdbServer* adb_srv)
+{
+    AdbGuest* adb_guest;
+
+    ANEW0(adb_guest);
+    alist_init(&adb_guest->list_entry);
+    adb_guest->adb_srv = adb_srv;
+
+    return adb_guest;
+}
+
+/* Frees AdbGuest instance created with _adb_guest_new routine. */
+static void
+_adb_guest_free(AdbGuest* adb_guest)
+{
+    if (adb_guest != NULL) {
+        /* At this poin the guest must not be in any of the lists. */
+        assert(alist_is_empty(&adb_guest->list_entry));
+        AFREE(adb_guest);
+    }
+}
+
+/********************************************************************************
+ *                            ADB server internals
+ *******************************************************************************/
+
+/* I/O callback on ADB server socket. */
+static void
+_on_server_socket_io(void* opaque, int fd, unsigned events)
+{
+    AdbHost* adb_host;
+    AdbGuest* adb_guest;
+    AdbServer* adb_srv = (AdbServer*)opaque;
+    assert(adb_srv->so == fd);
+
+    /* Since this is a server socket, we only expect a connection I/O here. */
+    if ((events & LOOP_IO_READ) == 0) {
+        D("Unexpected write I/O on ADB server socket");
+        return;
+    }
+
+    /* Create AdbHost instance for the new host connection. */
+    adb_host = _adb_host_new(adb_srv);
+
+    /* Accept the connection. */
+    adb_host->host_so = socket_accept(fd, &adb_srv->socket_address);
+    if (adb_host->host_so < 0) {
+        D("Unable to accept ADB connection: %s", strerror(errno));
+        _adb_host_free(adb_host);
+        return;
+    }
+
+    /* Prepare for I/O on the host connection socket. */
+    loopIo_init(adb_host->io, adb_srv->looper, adb_host->host_so,
+                _on_adb_host_io, adb_host);
+
+    /* Lets see if there is an ADB guest waiting for a host connection. */
+    adb_guest = (AdbGuest*)alist_remove_head(&adb_srv->pending_guests);
+    if (adb_guest != NULL) {
+        /* Tie up ADB host with the ADB guest. */
+        alist_insert_tail(&adb_srv->adb_guests, &adb_guest->list_entry);
+        alist_insert_tail(&adb_srv->adb_hosts, &adb_host->list_entry);
+        _adb_connect(adb_host, adb_guest);
+    } else {
+        /* Pend this connection. */
+        D("Pend ADB host %p(so=%d)", adb_host, adb_host->host_so);
+        alist_insert_tail(&adb_srv->pending_hosts, &adb_host->list_entry);
+    }
+
+    /* Enable I/O on the host socket. */
+    loopIo_wantRead(adb_host->io);
+}
+
+/********************************************************************************
+ *                            ADB server API
+ *******************************************************************************/
+int
+adb_server_init(int port)
+{
+    if (!_adb_server_initialized) {
+        /* Initialize the descriptor. */
+        memset(&_adb_server, 0, sizeof(_adb_server));
+        alist_init(&_adb_server.adb_hosts);
+        alist_init(&_adb_server.adb_guests);
+        alist_init(&_adb_server.pending_hosts);
+        alist_init(&_adb_server.pending_guests);
+        _adb_server.port = port;
+
+        /* Create looper for an async I/O on the server. */
+        _adb_server.looper = looper_newCore();
+        if (_adb_server.looper == NULL) {
+            E("Unable to create I/O looper for ADB server");
+            return -1;
+        }
+
+        /* Create loopback server socket for the ADB port. */
+        sock_address_init_inet(&_adb_server.socket_address,
+                               SOCK_ADDRESS_INET_LOOPBACK, port);
+        _adb_server.so = socket_loopback_server(port, SOCKET_STREAM);
+        if (_adb_server.so < 0) {
+            E("Unable to create ADB server socket: %s", strerror(errno));
+            return -1;
+        }
+
+        /* Prepare server socket for I/O */
+        socket_set_nonblock(_adb_server.so);
+        loopIo_init(_adb_server.io, _adb_server.looper, _adb_server.so,
+                    _on_server_socket_io, &_adb_server);
+        loopIo_wantRead(_adb_server.io);
+
+        D("ADB server has been initialized for port %d. Socket: %d",
+          port, _adb_server.so);
+
+        _adb_server_initialized = 1;
+    }
+
+    return 0;
+}
+
+int
+adb_server_is_initialized(void)
+{
+    return _adb_server_initialized;
+}
+
+void*
+adb_server_register_guest(void* opaque, AdbGuestRoutines* callbacks)
+{
+    if (_adb_server_initialized) {
+        AdbHost* adb_host;
+
+        /* Create and initialize ADB guest descriptor. */
+        AdbGuest* const adb_guest = _adb_guest_new(&_adb_server);
+        adb_guest->opaque = opaque;
+        adb_guest->callbacks = callbacks;
+
+        /* Lets see if there is a pending ADB host for the new guest. */
+        adb_host = (AdbHost*)alist_remove_head(&_adb_server.pending_hosts);
+        if (adb_host != NULL) {
+            /* Tie up ADB host with the ADB guest. */
+            alist_insert_tail(&_adb_server.adb_guests, &adb_guest->list_entry);
+            alist_insert_tail(&_adb_server.adb_hosts, &adb_host->list_entry);
+            _adb_connect(adb_host, adb_guest);
+        } else {
+            /* Host is not available. Pend this guest. */
+            D("Pend ADB guest %p(o=%p)", adb_guest, adb_guest->opaque);
+            alist_insert_tail(&_adb_server.pending_guests, &adb_guest->list_entry);
+        }
+
+        return adb_guest;
+    } else {
+        D("%s is called on an uninitialized ADB server.", __FUNCTION__);
+        return NULL;
+    }
+}
+
+void
+adb_server_complete_connection(void* opaque)
+{
+    AdbGuest* const adb_guest = (AdbGuest*)opaque;
+    AdbHost* const adb_host = adb_guest->adb_host;
+
+    /* Mark the guest as fully connected and ready for the host data. */
+    adb_guest->is_connected = 1;
+
+    /* Lets see if there is a host data pending transmission to the guest. */
+    if (adb_host->pending_data != NULL && adb_host->pending_data_size != 0) {
+        /* Send the pending data to the guest. */
+        D("Pushing %d bytes of the pending ADB host data.",
+          adb_host->pending_data_size);
+        adb_guest->callbacks->on_read(adb_guest->opaque, adb_guest,
+                                      adb_host->pending_data,
+                                      adb_host->pending_data_size);
+        free(adb_host->pending_data);
+        adb_host->pending_data = NULL;
+        adb_host->pending_data_size = 0;
+    }
+}
+
+void
+adb_server_on_guest_message(void* opaque, const uint8_t* msg, int msglen)
+{
+    AdbGuest* const adb_guest = (AdbGuest*)opaque;
+    AdbHost* const adb_host = adb_guest->adb_host;
+
+    if (adb_host != NULL) {
+        D("Sending %d bytes to the ADB host: %s", msglen, QB(msg, msglen));
+
+        /* Lets see if we can send the data immediatelly... */
+        if (adb_host->pending_send_buffer == NULL) {
+            /* There are no data that are pending to be sent to the host. Do the
+             * direct send. */
+            const int sent = socket_send(adb_host->host_so, msg, msglen);
+            if (sent < 0) {
+                if (errno == EWOULDBLOCK) {
+                } else {
+                    D("Unable to send data to ADB host: %s", strerror(errno));
+                }
+            } else if (sent == 0) {
+                /* Disconnect condition. */
+                _on_adb_host_disconnected(adb_host);
+            } else if (sent < msglen) {
+                /* Couldn't send everything. Schedule write via I/O callback. */
+                _adb_host_append_message(adb_host, msg + sent, msglen - sent);
+            }
+        } else {
+            /* There are data that are pending to be sent to the host. We need
+             * to append new data to the end of the pending data buffer. */
+            _adb_host_append_message(adb_host, msg, msglen);
+        }
+    } else {
+        D("ADB host is disconneted and can't accept %d bytes in %s",
+          msglen, QB(msg, msglen));
+    }
+}
+
+void
+adb_server_on_guest_closed(void* opaque)
+{
+    AdbGuest* const adb_guest = (AdbGuest*)opaque;
+    AdbHost* const adb_host = adb_guest->adb_host;
+
+    /* Remove the guest from the list */
+    if (!alist_is_empty(&adb_guest->list_entry)) {
+        alist_remove(&adb_guest->list_entry);
+    }
+
+    /* Disassociate the host. */
+    if (adb_host != NULL) {
+        if (!alist_is_empty(&adb_host->list_entry)) {
+            alist_remove(&adb_host->list_entry);
+        }
+        _adb_host_free(adb_host);
+    }
+    _adb_guest_free(adb_guest);
+}
diff --git a/android/adb-server.h b/android/adb-server.h
new file mode 100644
index 0000000..33ede53
--- /dev/null
+++ b/android/adb-server.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ADB_SERVER_H_
+#define ANDROID_ADB_SERVER_H_
+
+/*
+ * Encapsulates a socket server that is bound to ADB port, and bridges ADB host
+ * connections and data to ADB daemon running inside the guest.
+ */
+
+/* Callback to be invoked wheh host ADB gets connected with the guest ADB.
+ * Param:
+ *  opaque - An opaque pointer associated with the guest. This pointer contains
+ *      the 'opaque' parameter that was passed to the adb_server_register_guest
+ *      routine.
+ *  connection - An opaque pointer defining the connection between the host and
+ *      the guest ADBs. This pointer must be used for further operations on the
+ *      host <-> guest connection.
+ */
+typedef void (*adbguest_connect)(void* opaque, void* connection);
+
+/* Callback to be invoked wheh the host ADB sends data to the guest ADB.
+ * Param:
+ *  opaque - An opaque pointer associated with the guest. This pointer contains
+ *      the 'opaque' parameter that was passed to the adb_server_register_guest
+ *      routine.
+ *  connection - An opaque pointer defining the connection between the host and
+ *      the guest ADB. This pointer must be used for further operations on the
+ *      host <-> guest connection.
+ *  buff, size - Buffer that has ben sent by the host.
+ */
+typedef void (*adbguest_read)(void* opaque,
+                              void* connection,
+                              const void* buff,
+                              int size);
+
+/* Callback to be invoked wheh the host ADB gets disconnected.
+ * Param:
+ *  opaque - An opaque pointer associated with the guest. This pointer contains
+ *      the 'opaque' parameter that was passed to the adb_server_register_guest
+ *      routine.
+ *  connection - An opaque pointer defining the connection between the host and
+ *      the guest ADB. This pointer must be used for further operations on the
+ *      host <-> guest connection.
+ */
+typedef void (*adbguest_disconnect)(void* opaque, void* connection);
+
+/* Defines a set of callbacks for a guest ADB. */
+typedef struct AdbGuestRoutines AdbGuestRoutines;
+struct AdbGuestRoutines {
+    /* Callback to invoke when ADB host is connected. */
+    adbguest_connect     on_connected;
+    /* Callback to invoke when ADB host is disconnected. */
+    adbguest_disconnect  on_disconnect;
+    /* Callback to invoke when ADB host sends data. */
+    adbguest_read        on_read;
+};
+
+/* Initializes ADB server.
+ * Param:
+ *  port - socket port that is assigned for communication with the ADB host. This
+ *      is 'base port' + 1.
+ * Return:
+ *  0 on success, or != 0 on failure.
+ */
+extern int adb_server_init(int port);
+
+/* Checks if ADB server has been initialized. */
+extern int adb_server_is_initialized(void);
+
+/* Registers ADB guest with the ADB server.
+ * There can be two cases here, as far as connection with the host is concerned:
+ *  - There is no host connection to immediately associate the guest with. In
+ *    this case the guest will be registered as "pending connection", and routine
+ *    will return.
+ *  - There is a pending host connection to associate with the new guest. In this
+ *    case the association will be made in this routine, and 'adbguest_connect'
+ *    callback will be called before this routine returns.
+ * Param:
+ *  opaque Opaque pointer associated with the guest. This pointer will be passed
+ *      back to thee guest API in callback routines.
+ *  callbacks Contains callback routines for the registering guest.
+ * Return:
+ *  An opaque pointer associated with the ADB guest on success, or NULL on
+ *  failure. The pointer returned from this routine must be passed into ADB
+ *  server API called from the guest.
+ */
+extern void* adb_server_register_guest(void* opaque, AdbGuestRoutines* callbacks);
+
+/* Completes connection with the guest.
+ * This routine is called by the guest when it receives a 'start' request from
+ * ADB guest. This request tells the system that ADB daemon running inside the
+ * guest is ready to receive data.
+ * Param:
+ *  opaque - An opaque pointer returned from adb_server_register_guest.
+ */
+extern void adb_server_complete_connection(void* opaque);
+
+/* Handles data received from the guest.
+ * Param:
+ *  opaque - An opaque pointer returned from adb_server_register_guest.
+ * data, size - Data buffer received from the guest.
+ */
+extern void adb_server_on_guest_message(void* opaque,
+                                        const uint8_t* data,
+                                        int size);
+
+/* Notifies the ADB server that the guest has closed its connection.
+ * Param:
+ *  opaque - An opaque pointer returned from adb_server_register_guest.
+ */
+extern void adb_server_on_guest_closed(void* opaque);
+
+#endif  /* ANDROID_ADB_SERVER_H_ */
diff --git a/android/avd/info.c b/android/avd/info.c
index 7e4f93e..815b0b4 100644
--- a/android/avd/info.c
+++ b/android/avd/info.c
@@ -1202,3 +1202,8 @@
 
     return _avdInfo_getContentOrSdkFilePath(i, fileName);
 }
+
+int avdInfo_getAdbdCommunicationMode( AvdInfo* i )
+{
+    return path_getAdbdCommunicationMode(i->androidOut);
+}
diff --git a/android/avd/info.h b/android/avd/info.h
index 34997b4..74a9b01 100644
--- a/android/avd/info.h
+++ b/android/avd/info.h
@@ -243,6 +243,15 @@
  */
 const char*  avdInfo_getCoreHwIniPath( AvdInfo* i );
 
+/* Returns mode in which ADB daemon running in the guest communicates with the
+ * emulator
+ * Return:
+ *  0 - ADBD communicates with the emulator via forwarded TCP port 5555 (a
+ *      "legacy" mode).
+ *  1 - ADBD communicates with the emulator via 'adb' QEMUD service.
+ */
+int          avdInfo_getAdbdCommunicationMode( AvdInfo* i );
+
 /* */
 
 #endif /* ANDROID_AVD_INFO_H */
diff --git a/android/avd/util.c b/android/avd/util.c
index 304b98f..82145b5 100644
--- a/android/avd/util.c
+++ b/android/avd/util.c
@@ -313,3 +313,24 @@
     return level;
 }
 
+int
+path_getAdbdCommunicationMode( const char* androidOut )
+{
+    char* prop = _getBuildProperty(androidOut, "ro.adb.qemud");
+    if (prop != NULL) {
+        long val = 0;
+        char* end;
+        val = strtol(prop, &end, 10);
+        if (end == NULL || *end != '\0' || val != (int)val) {
+            D("Invalid ro.adb.qemud build property: '%s'", prop);
+            val = 0;
+        } else {
+            D("Found ro.adb.qemud build property: %d", val);
+        }
+        AFREE(prop);
+        return (int)val;
+    } else {
+        /* Missing ro.adb.qemud means "legacy" ADBD. */
+        return 0;
+    }
+}
diff --git a/android/avd/util.h b/android/avd/util.h
index 877d5aa..edef6a0 100644
--- a/android/avd/util.h
+++ b/android/avd/util.h
@@ -64,4 +64,13 @@
  */
 int path_getBuildTargetApiLevel( const char* androidOut );
 
+/* Returns mode in which ADB daemon running in the guest communicates with the
+ * emulator
+ * Return:
+ *  0 - ADBD communicates with the emulator via forwarded TCP port 5555 (a
+ *      "legacy" mode).
+ *  1 - ADBD communicates with the emulator via 'adb' QEMUD service.
+ */
+int path_getAdbdCommunicationMode( const char* androidOut );
+
 #endif /* _ANDROID_AVD_UTIL_H */
diff --git a/android/qemu-setup.c b/android/qemu-setup.c
index f1a12ee..181c95b 100644
--- a/android/qemu-setup.c
+++ b/android/qemu-setup.c
@@ -23,6 +23,8 @@
 #include "android/utils/path.h"
 #include "android/utils/system.h"
 #include "android/utils/bufprint.h"
+#include "android/adb-server.h"
+#include "android/adb-qemud.h"
 
 #define  D(...)  do {  if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
 
@@ -252,6 +254,8 @@
         exit(1);
     }
 
+    int legacy_adb = avdInfo_getAdbdCommunicationMode(android_avdInfo) ? 0 : 1;
+
     if (android_op_ports) {
         char* comma_location;
         char* end;
@@ -276,9 +280,16 @@
 
         // Set up redirect from host to guest system. adbd on the guest listens
         // on 5555.
-        slirp_redir( 0, adb_port, guest_ip, 5555 );
+        if (legacy_adb) {
+            slirp_redir( 0, adb_port, guest_ip, 5555 );
+        } else {
+            adb_server_init(adb_port);
+            android_adb_service_init();
+        }
         if ( control_console_start( console_port ) < 0 ) {
-            slirp_unredir( 0, adb_port );
+            if (legacy_adb) {
+                slirp_unredir( 0, adb_port );
+            }
         }
 
         base_port = console_port;
@@ -304,12 +315,20 @@
         for ( ; tries > 0; tries--, base_port += 2 ) {
 
             /* setup first redirection for ADB, the Android Debug Bridge */
-            if ( slirp_redir( 0, base_port+1, guest_ip, 5555 ) < 0 )
-                continue;
+            if (legacy_adb) {
+                if ( slirp_redir( 0, base_port+1, guest_ip, 5555 ) < 0 )
+                    continue;
+            } else {
+                if (adb_server_init(base_port+1))
+                    continue;
+                android_adb_service_init();
+            }
 
             /* setup second redirection for the emulator console */
             if ( control_console_start( base_port ) < 0 ) {
-                slirp_unredir( 0, base_port+1 );
+                if (legacy_adb) {
+                    slirp_unredir( 0, base_port+1 );
+                }
                 continue;
             }
 
diff --git a/android/utils/debug.h b/android/utils/debug.h
index 096b002..142e2a4 100644
--- a/android/utils/debug.h
+++ b/android/utils/debug.h
@@ -37,6 +37,8 @@
     _VERBOSE_TAG(memcheck,     "memory checker") \
     _VERBOSE_TAG(camera,       "camera") \
     _VERBOSE_TAG(gles,         "hardware OpenGLES emulation") \
+    _VERBOSE_TAG(adbserver,    "ADB server") \
+    _VERBOSE_TAG(adbclient,    "ADB QEMU client") \
 
 #define  _VERBOSE_TAG(x,y)  VERBOSE_##x,
 typedef enum {
diff --git a/docs/ANDROID-ADB-QEMU.TXT b/docs/ANDROID-ADB-QEMU.TXT
new file mode 100644
index 0000000..fba3c82
--- /dev/null
+++ b/docs/ANDROID-ADB-QEMU.TXT
@@ -0,0 +1,53 @@
+ADB COMMUNICATION OVER QEMUD SERVICE
+
+I. Overview:
+------------
+
+In certain cases ADB communication over TCP port forwarding might be unreliable.
+For instance, connection manager in the guest system may decide to reset all
+network connections, in which case connection between the ADB host, and ADB
+daemon running in the guest will be broken, and will not be reestablish until ADB
+host is killed, and then restarted. To address this issue ADB communication has
+been moved to use QEMUD pipe to transfer data between the emulator, and the
+ADB daemon running in the guest.
+
+
+II. Implementation:
+-------------------
+
+There are two major components implemented in the emulator to support ADB
+communication over QEMUD pipe:
+
+1. ADB server.
+2. ADB QEMUD service (or ADB client).
+
+ADB server is implemented as a socket server that is bound to the ADB port (which
+is the 'base port' + 1), and is responsible for accepting connections coming from
+the ADB host, and associatiating accepted connections with an ADB client.
+
+ADB client is implemented as QEMUD service (named 'adb'), and is responsible for
+accepting connections coming from the ADB daemon running in the guest, and
+associating accepted connections with ADB server.
+
+Essentially, ADB server, and ADB client serve as a bridge between ADB running on
+the host, and ADB running on the guest: ADB server receives data from ADB host,
+and channels them through ADB client to the ADB guest. Likewise, ADB client
+receives data from the ADB guest, and channels them through ADB server to the ADB
+host. The only tricky part here is establishing the connection. Once connection
+is established, everything is straight forward.
+
+II.III Establishing the connection:
+-----------------------------------
+
+The connection between ADB host and ADB guest is considered to be established,
+when there is an association between ADB socket connection in the ADB server, and
+QEMUD pipe connection in the ADB client, and ADB guest is ready to receive data
+from the ADB host.
+
+Since there is no particular order, in which ADB server, and ADB client
+connections are made, ADB server runs a list of pending host and guest
+connections. Every time either connection is made, that connection goes into a
+pending list on condition that there is no pending connection on the other side.
+If, however, there is already a pending connection from the other side, that
+pending connection is removed from the pending list, and gets associated with the
+new connection.
diff --git a/slirp-android/bootp.c b/slirp-android/bootp.c
index 814b030..1ff740e 100644
--- a/slirp-android/bootp.c
+++ b/slirp-android/bootp.c
@@ -65,7 +65,7 @@
  found:
     bc = &bootp_clients[i];
     bc->allocated = 1;
-    sock_address_init_inet( paddr, 
+    sock_address_init_inet( paddr,
                             special_addr_ip | (i+START_ADDR),
                             BOOTP_CLIENT );
     return bc;
@@ -170,7 +170,7 @@
     dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
     dprintf("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
     if (preq_addr) {
-        dprintf(" req_addr=%08x\n", ntohl(*preq_addr));
+        dprintf(" req_addr=%08x\n", ntohl(*(uint32_t*)preq_addr));
     } else {
         dprintf("\n");
     }