Initial Contribution
diff --git a/simulator/app/LocalBiChannel.cpp b/simulator/app/LocalBiChannel.cpp
new file mode 100644
index 0000000..93a997d
--- /dev/null
+++ b/simulator/app/LocalBiChannel.cpp
@@ -0,0 +1,444 @@
+//
+// Copyright 2005 The Android Open Source Project
+//
+// Local named bi-directional communication channel.
+//
+#include "LocalBiChannel.h"
+#include "utils/Log.h"
+
+#if defined(HAVE_WIN32_IPC)
+# define _WIN32_WINNT 0x0500
+# include <windows.h>
+#else
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <sys/stat.h>
+# include <sys/un.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#ifndef SUN_LEN
+/*
+ * Our current set of ARM header files don't define this.
+ */
+# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path)        \
+                      + strlen ((ptr)->sun_path))
+#endif
+
+using namespace android;
+
+const unsigned long kInvalidHandle = (unsigned long) -1;
+
+/*
+ * Initialize data fields.
+ */
+LocalBiChannel::LocalBiChannel(void)
+    : mFileName(NULL), mIsListener(false), mHandle(kInvalidHandle)
+{
+}
+
+#if defined(HAVE_WIN32_IPC)
+/*
+ * Implementation for Win32, using named pipes.
+ *
+ * Cygwin actually supports UNIX-domain sockets, but we want to stuff
+ * the file handles into a Pipe, which uses HANDLE under Win32.
+ */
+
+const int kPipeSize = 4096;
+
+/*
+ * Destructor.  If we're the server side, we may need to clean up after
+ * ourselves.
+ */
+LocalBiChannel::~LocalBiChannel(void)
+{
+    if (mHandle != kInvalidHandle)
+        CloseHandle((HANDLE)mHandle);
+
+    delete[] mFileName;
+}
+
+/*
+ * Construct the full path.  The caller must delete[] the return value.
+ */
+static char* makeFilename(const char* name)
+{
+    static const char* kBasePath = "\\\\.\\pipe\\android-";
+    char* fileName;
+
+    assert(name != NULL && name[0] != '\0');
+
+    fileName = new char[strlen(kBasePath) + strlen(name) + 1];
+    strcpy(fileName, kBasePath);
+    strcat(fileName, name);
+
+    return fileName;
+}
+
+/*
+ * Create a named pipe, so the client has something to connect to.
+ */
+bool LocalBiChannel::create(const char* name)
+{
+    delete[] mFileName;
+    mFileName = makeFilename(name);
+
+#if 0
+    HANDLE hPipe;
+
+    hPipe = CreateNamedPipe(
+                    mFileName,              // unique pipe name
+                    PIPE_ACCESS_DUPLEX |    // open mode
+                        FILE_FLAG_FIRST_PIPE_INSTANCE,
+                    0,                      // pipe mode (byte, blocking)
+                    1,                      // max instances
+                    kPipeSize,              // output buffer
+                    kPipeSize,              // input buffer
+                    NMPWAIT_USE_DEFAULT_WAIT,   // client time-out
+                    NULL);                  // security
+
+    if (hPipe == 0) {
+        LOG(LOG_ERROR, "lbicomm",
+            "CreateNamedPipe failed (err=%ld)\n", GetLastError());
+        return false;
+    }
+
+    mHandle = (unsigned long) hPipe;
+#endif
+
+    return true;
+}
+
+/*
+ * Attach to an existing named pipe.
+ */
+bool LocalBiChannel::attach(const char* name, Pipe** ppReadPipe,
+    Pipe** ppWritePipe)
+{
+    HANDLE hPipe, dupHandle;
+
+    delete[] mFileName;
+    mFileName = makeFilename(name);
+
+    hPipe = CreateFile(
+                mFileName,                      // filename
+                GENERIC_READ | GENERIC_WRITE,   // access
+                0,                              // no sharing
+                NULL,                           // security
+                OPEN_EXISTING,                  // don't create
+                0,                              // attributes
+                NULL);                          // template
+    if (hPipe == INVALID_HANDLE_VALUE) {
+        LOG(LOG_ERROR, "lbicomm",
+            "CreateFile on pipe '%s' failed (err=%ld)\n", name, GetLastError());
+        return false;
+    }
+
+    assert(mHandle == kInvalidHandle);
+
+    /*
+     * Set up the pipes.  Use the new handle for one, and a duplicate
+     * of it for the other, in case we decide to only close one side.
+     */
+    *ppReadPipe = new Pipe();
+    (*ppReadPipe)->createReader((unsigned long) hPipe);
+
+    DuplicateHandle(
+            GetCurrentProcess(),
+            hPipe,
+            GetCurrentProcess(),
+            &dupHandle,
+            0,
+            FALSE,
+            DUPLICATE_SAME_ACCESS);
+    *ppWritePipe = new Pipe();
+    (*ppWritePipe)->createWriter((unsigned long) dupHandle);
+
+    return true;
+}
+
+/*
+ * Listen for a new connection, discarding any existing connection.
+ */
+bool LocalBiChannel::listen(Pipe** ppReadPipe, Pipe** ppWritePipe)
+{
+    BOOL connected;
+    HANDLE hPipe;
+
+    /*
+     * Create up to 3 instances of the named pipe:
+     * - currently active connection
+     * - connection currently being rejected because one is already active
+     * - a new listener to wait for the next round
+     */
+    hPipe = CreateNamedPipe(
+                    mFileName,              // unique pipe name
+                    PIPE_ACCESS_DUPLEX      // open mode
+                        /*| FILE_FLAG_FIRST_PIPE_INSTANCE*/,
+                    0,                      // pipe mode (byte, blocking)
+                    3,                      // max instances
+                    kPipeSize,              // output buffer
+                    kPipeSize,              // input buffer
+                    NMPWAIT_USE_DEFAULT_WAIT,   // client time-out
+                    NULL);                  // security
+
+    if (hPipe == 0) {
+        LOG(LOG_ERROR, "lbicomm",
+            "CreateNamedPipe failed (err=%ld)\n", GetLastError());
+        return false;
+    }
+
+    /*
+     * If a client is already connected to us, this fails with
+     * ERROR_PIPE_CONNECTED.  It returns success if we had to wait
+     * a little bit before the connection happens.
+     */
+    connected = ConnectNamedPipe(hPipe, NULL) ?
+        TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+
+    if (connected) {
+        /*
+         * Create the pipes.  Give one a duplicated handle so that,
+         * when one closes, we don't lose both.
+         */
+        HANDLE dupHandle;
+
+        *ppReadPipe = new Pipe();
+        (*ppReadPipe)->createReader((unsigned long) hPipe);
+
+        DuplicateHandle(
+                GetCurrentProcess(),
+                hPipe,
+                GetCurrentProcess(),
+                &dupHandle,
+                0,
+                FALSE,
+                DUPLICATE_SAME_ACCESS);
+        *ppWritePipe = new Pipe();
+        (*ppWritePipe)->createWriter((unsigned long) dupHandle);
+
+        return true;
+    } else {
+        LOG(LOG_WARN, "lbicomm",
+            "ConnectNamedPipe failed (err=%ld)\n", GetLastError());
+#ifdef HAVE_WIN32_THREADS
+        Sleep(500); /* 500 ms */
+#else            
+        usleep(500000);     // DEBUG DEBUG
+#endif        
+        return false;
+    }
+}
+
+#else
+
+/*
+ * Implementation for Linux and Darwin, using UNIX-domain sockets.
+ */
+
+/*
+ * Destructor.  If we're the server side, blow away the socket file.
+ */
+LocalBiChannel::~LocalBiChannel(void)
+{
+    if (mHandle != kInvalidHandle)
+        close((int) mHandle);
+
+    if (mIsListener && mFileName != NULL) {
+        LOG(LOG_DEBUG, "lbicomm", "Removing '%s'\n", mFileName);
+        (void) unlink(mFileName);
+    }
+    delete[] mFileName;
+}
+
+/*
+ * Construct the full path.  The caller must delete[] the return value.
+ */
+static char* makeFilename(const char* name)
+{
+    static const char* kBasePath = "/tmp/android-";
+    char* fileName;
+
+    assert(name != NULL && name[0] != '\0');
+
+    fileName = new char[strlen(kBasePath) + strlen(name) + 1];
+    strcpy(fileName, kBasePath);
+    strcat(fileName, name);
+
+    return fileName;
+}
+
+/*
+ * Create a UNIX domain socket, carefully removing it if it already
+ * exists.
+ */
+bool LocalBiChannel::create(const char* name)
+{
+    struct stat sb;
+    bool result = false;
+    int sock = -1;
+    int cc;
+
+    delete[] mFileName;
+    mFileName = makeFilename(name);
+
+    cc = stat(mFileName, &sb);
+    if (cc < 0) {
+        if (errno != ENOENT) {
+            LOG(LOG_ERROR, "lbicomm",
+                "Unable to stat '%s' (errno=%d)\n", mFileName, errno);
+            goto bail;
+        }
+    } else {
+        /* don't touch it if it's not a socket */
+        if (!(S_ISSOCK(sb.st_mode))) {
+            LOG(LOG_ERROR, "lbicomm",
+                "File '%s' exists and is not a socket\n", mFileName);
+            goto bail;
+        }
+
+        /* remove the cruft */
+        if (unlink(mFileName) < 0) {
+            LOG(LOG_ERROR, "lbicomm",
+                "Unable to remove '%s' (errno=%d)\n", mFileName, errno);
+            goto bail;
+        }
+    }
+
+    struct sockaddr_un addr;
+
+    sock = ::socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock < 0) {
+        LOG(LOG_ERROR, "lbicomm",
+            "UNIX domain socket create failed (errno=%d)\n", errno);
+        goto bail;
+    }
+
+    /* bind the socket; this creates the file on disk */
+    strcpy(addr.sun_path, mFileName);    // max 108 bytes
+    addr.sun_family = AF_UNIX;
+    cc = ::bind(sock, (struct sockaddr*) &addr, SUN_LEN(&addr));
+    if (cc < 0) {
+        LOG(LOG_ERROR, "lbicomm",
+            "AF_UNIX bind failed for '%s' (errno=%d)\n", mFileName, errno);
+        goto bail;
+    }
+
+    mHandle = (unsigned long) sock;
+    sock = -1;
+    mIsListener = true;
+    result = true;
+
+bail:
+    if (sock >= 0)
+        close(sock);
+    return result;
+}
+
+/*
+ * Attach to an existing UNIX domain socket.
+ */
+bool LocalBiChannel::attach(const char* name, Pipe** ppReadPipe,
+    Pipe** ppWritePipe)
+{
+    bool result = false;
+    int sock = -1;
+    int cc;
+
+    assert(ppReadPipe != NULL);
+    assert(ppWritePipe != NULL);
+
+    delete[] mFileName;
+    mFileName = makeFilename(name);
+
+    struct sockaddr_un addr;
+
+    sock = ::socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock < 0) {
+        LOG(LOG_ERROR, "lbicomm",
+            "UNIX domain socket create failed (errno=%d)\n", errno);
+        goto bail;
+    }
+
+    /* connect to socket; fails if file doesn't exist */
+    strcpy(addr.sun_path, mFileName);    // max 108 bytes
+    addr.sun_family = AF_UNIX;
+    cc = ::connect(sock, (struct sockaddr*) &addr, SUN_LEN(&addr));
+    if (cc < 0) {
+        // ENOENT means socket file doesn't exist
+        // ECONNREFUSED means socket exists but nobody is listening
+        LOG(LOG_ERROR, "lbicomm",
+            "AF_UNIX connect failed for '%s': %s\n", mFileName,strerror(errno));
+        goto bail;
+    }
+
+    /*
+     * Create the two halves.  We dup() the sock so that closing one side
+     * does not hose the other.
+     */
+    *ppReadPipe = new Pipe();
+    (*ppReadPipe)->createReader(sock);
+    *ppWritePipe = new Pipe();
+    (*ppWritePipe)->createWriter(dup(sock));
+
+    assert(mHandle == kInvalidHandle);
+    sock = -1;
+    mIsListener = false;
+
+    result = true;
+
+bail:
+    if (sock >= 0)
+        close(sock);
+    return result;
+}
+
+/*
+ * Listen for a new connection.
+ */
+bool LocalBiChannel::listen(Pipe** ppReadPipe, Pipe** ppWritePipe)
+{
+    bool result = false;
+    struct sockaddr_un from;
+    socklen_t fromlen;
+    int sock, lsock;
+    int cc;
+
+    assert(mHandle != kInvalidHandle);
+    lsock = (int) mHandle;
+
+    LOG(LOG_DEBUG, "lbicomm", "AF_UNIX listening\n");
+    cc = ::listen(lsock, 5);
+    if (cc < 0) {
+        LOG(LOG_ERROR, "lbicomm", "AF_UNIX listen failed (errno=%d)\n", errno);
+        goto bail;
+    }
+
+    fromlen = sizeof(from);     // not SUN_LEN()
+    sock = ::accept(lsock, (struct sockaddr*) &from, &fromlen);
+    if (sock < 0) {
+        LOG(LOG_WARN, "lbicomm", "AF_UNIX accept failed (errno=%d)\n", errno);
+        goto bail;
+    }
+
+    /*
+     * Create the two halves.  We dup() the sock so that closing one side
+     * does not hose the other.
+     */
+    *ppReadPipe = new Pipe();
+    (*ppReadPipe)->createReader(sock);
+    *ppWritePipe = new Pipe();
+    (*ppWritePipe)->createWriter(dup(sock));
+    result = true;
+
+bail:
+    return result;
+}
+
+#endif