auto import from //depot/cupcake/@135843
diff --git a/simulator/wrapsim/FakeDev.c b/simulator/wrapsim/FakeDev.c
new file mode 100644
index 0000000..3e223d3
--- /dev/null
+++ b/simulator/wrapsim/FakeDev.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ *
+ * Fake device support.
+ */
+/*
+Implementation notes:
+
+There are a couple of basic scenarios, exemplified by the "fb" and
+"events" devices.  The framebuffer driver is pretty simple, handling a
+few ioctl()s and managing a stretch of memory.  We can just intercept a
+few calls.  The input event driver can be used in a select() or poll()
+call with other file descriptors, which either requires us to do some
+fancy tricks with select() and poll(), or requires that we return a real
+file descriptor (perhaps based on a socketpair).
+
+We have three basic approaches to dealing with "fake" file descriptors:
+
+(1) Always use real fds.  We can dup() an open /dev/null to get a number
+    for the cases where we don't need a socketpair.
+(2) Always use fake fds with absurdly high numeric values.  Testing to see
+    if the fd is one we handle is trivial (range check).  This doesn't
+    work for select(), which uses fd bitmaps accessed through macros.
+(3) Use a mix of real and fake fds, in a high range (512-1023).  Because
+    it's in the "real" range, we can pass real fds around for things that
+    are handed to poll() and select(), but because of the high numeric
+    value we *should* be able to get away with a trivial range check.
+
+Approach (1) is the most portable and least likely to break, but the
+efficiencies gained in approach (2) make it more desirable.  There is
+a small risk of application fds wandering into our range, but we can
+minimize that by asserting on a "guard zone" and/or obstructing dup2().
+(We can also dup2(/dev/null) to "reserve" our fds, but that wastes
+resources.)
+*/
+
+#include "Common.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <assert.h>
+#include <fnmatch.h>
+
+/*
+ * Devices we intercept.
+ *
+ * Needed:
+ *  /dev/alarm
+ *  radio
+ */
+typedef FakeDev* (*wsFileHook)(const char *path, int flags);
+
+typedef struct FakedPath {
+    const char *pathexpr;
+    wsFileHook hook;
+} FakedPath;
+
+FakedPath fakedpaths[] =
+{
+    { "/dev/graphics/fb0",      wsOpenDevFb },
+    { "/dev/hw3d",              NULL },
+    { "/dev/eac",               wsOpenDevAudio },
+    { "/dev/tty0",              wsOpenDevConsoleTty },
+    { "/dev/input/event0",      wsOpenDevEvent },
+    { "/dev/input/*",           NULL },
+    { "/dev/log/*",             wsOpenDevLog },
+    { "/sys/class/power_supply/*", wsOpenDevPower },
+    { "/sys/devices/platform/android-vibrator/enable",  wsOpenDevVibrator },
+    { "/sys/qemu_trace/*",      NULL },
+    { NULL,                     NULL }
+};
+
+
+/*
+ * Generic drop-in for an unimplemented call.
+ *
+ * Returns -1, which conveniently is the same as MAP_FAILED for mmap.
+ */
+static int notImplemented(FakeDev* dev, const char* callName)
+{
+    wsLog("WARNING: unimplemented %s() on '%s' %p\n",
+        callName, dev->debugName, dev->state);
+    errno = kNoHandlerError;
+    return -1;
+}
+
+/*
+ * Default implementations.  We want to log as much information as we can
+ * so that we can fill in the missing implementation.
+ *
+ * TODO: for some or all of these we will want to display the full arg list.
+ */
+static int noClose(FakeDev* dev, ...)
+{
+    return 0;
+}
+static int noRead(FakeDev* dev, ...)
+{
+    return notImplemented(dev, "read");
+}
+static int noReadv(FakeDev* dev, ...)
+{
+    return notImplemented(dev, "readv");
+}
+static int noWrite(FakeDev* dev, ...)
+{
+    return notImplemented(dev, "write");
+}
+static int noWritev(FakeDev* dev, ...)
+{
+    return notImplemented(dev, "writev");
+}
+static int noMmap(FakeDev* dev, ...)
+{
+    return notImplemented(dev, "mmap");
+}
+static int noIoctl(FakeDev* dev, ...)
+{
+    return notImplemented(dev, "ioctl");
+}
+
+
+/*
+ * Create a new FakeDev entry.
+ *
+ * We mark the fd slot as "used" in the bitmap, but don't add it to the
+ * table yet since the entry is not fully prepared.
+ */
+FakeDev* wsCreateFakeDev(const char* debugName)
+{
+    FakeDev* newDev;
+    int cc;
+
+    assert(debugName != NULL);
+
+    newDev = (FakeDev*) calloc(1, sizeof(FakeDev));
+    if (newDev == NULL)
+        return NULL;
+
+    newDev->debugName = strdup(debugName);
+    newDev->state = NULL;
+
+    newDev->close = (Fake_close) noClose;
+    newDev->read = (Fake_read) noRead;
+    newDev->readv = (Fake_readv) noReadv;
+    newDev->write = (Fake_write) noWrite;
+    newDev->writev = (Fake_writev) noWritev;
+    newDev->mmap = (Fake_mmap) noMmap;
+    newDev->ioctl = (Fake_ioctl) noIoctl;
+
+    /*
+     * Allocate a new entry.  The bit vector map is really only used as a
+     * performance boost in the current implementation.
+     */
+    cc = pthread_mutex_lock(&gWrapSim.fakeFdLock); assert(cc == 0);
+    int newfd = wsAllocBit(gWrapSim.fakeFdMap);
+    cc = pthread_mutex_unlock(&gWrapSim.fakeFdLock); assert(cc == 0);
+
+    if (newfd < 0) {
+        wsLog("WARNING: ran out of 'fake' file descriptors\n");
+        free(newDev);
+        return NULL;
+    }
+    newDev->fd = newfd + kFakeFdBase;
+    newDev->otherFd = -1;
+    assert(gWrapSim.fakeFdList[newDev->fd - kFakeFdBase] == NULL);
+
+    return newDev;
+}
+
+/*
+ * Create a new FakeDev entry, and open a file descriptor that actually
+ * works.
+ */
+FakeDev* wsCreateRealFakeDev(const char* debugName)
+{
+    FakeDev* newDev = wsCreateFakeDev(debugName);
+    if (newDev == NULL)
+        return newDev;
+    
+    int fds[2];
+
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
+        wsLog("socketpair() failed: %s\n", strerror(errno));
+        wsFreeFakeDev(newDev);
+        return NULL;
+    }
+
+    if (dup2(fds[0], newDev->fd) < 0) {
+        wsLog("dup2(%d,%d) failed: %s\n",
+            fds[0], newDev->fd, strerror(errno));
+        wsFreeFakeDev(newDev);
+        return NULL;
+    }
+    close(fds[0]);
+
+    /* okay to leave this one in the "normal" range; not visible to app */
+    newDev->otherFd = fds[1];
+
+    return newDev;
+}
+
+/*
+ * Free fake device entry.
+ */
+void wsFreeFakeDev(FakeDev* dev)
+{
+    if (dev == NULL)
+        return;
+
+    wsLog("## closing/freeing '%s' (%d/%d)\n",
+        dev->debugName, dev->fd, dev->otherFd);
+
+    /*
+     * If we assigned a file descriptor slot, free it up.
+     */
+    if (dev->fd >= 0) {
+        int cc;
+
+        gWrapSim.fakeFdList[dev->fd - kFakeFdBase] = NULL;
+
+        cc = pthread_mutex_lock(&gWrapSim.fakeFdLock); assert(cc == 0);
+        wsFreeBit(gWrapSim.fakeFdMap, dev->fd - kFakeFdBase);
+        cc = pthread_mutex_unlock(&gWrapSim.fakeFdLock); assert(cc == 0);
+    }
+    if (dev->otherFd >= 0)
+        close(dev->otherFd);
+
+    if (dev->debugName) free(dev->debugName);
+    free(dev);
+}
+
+/*
+ * Map a file descriptor to a fake device.
+ *
+ * Returns NULL if there's no corresponding entry.
+ */
+FakeDev* wsFakeDevFromFd(int fd)
+{
+    /* quick range test */
+    if (fd < kFakeFdBase || fd >= kFakeFdBase + kMaxFakeFdCount)
+        return NULL;
+
+    return gWrapSim.fakeFdList[fd - kFakeFdBase];
+}
+
+
+/*
+ * Check to see if we're opening a device that we want to fake out.
+ *
+ * We return a file descriptor >= 0 on success, -1 if we're not interested,
+ * or -2 if we explicitly want to pretend that the device doesn't exist.
+ */
+int wsInterceptDeviceOpen(const char* pathName, int flags)
+{
+    FakedPath* p = fakedpaths;
+
+    while (p->pathexpr) {
+        if (fnmatch(p->pathexpr, pathName, 0) == 0) {
+            if (p->hook != NULL) {
+                FakeDev* dev = p->hook(pathName, flags);
+                if (dev != NULL) {
+                    /*
+                     * Now that the device entry is ready, add it to the list.
+                     */
+                    wsLog("## created fake dev %d: '%s' %p\n",
+                        dev->fd, dev->debugName, dev->state);
+                    gWrapSim.fakeFdList[dev->fd - kFakeFdBase] = dev;
+                    return dev->fd;
+                }
+            } else {
+                wsLog("## rejecting attempt to open %s\n", pathName);
+                errno = ENOENT;
+                return -2;
+            }
+            break;
+        }
+        p++;
+    }
+    return -1;
+}
+
+/*
+ * Check to see if we're accessing a device that we want to fake out.
+ * Returns 0 if the device can be (fake) opened with the given mode,
+ * -1 if it can't, -2 if it can't and we don't want to allow fallback
+ * to the host-device either.
+ * TODO: actually check the mode.
+ */
+int wsInterceptDeviceAccess(const char *pathName, int mode)
+{
+    FakedPath *p = fakedpaths;
+
+    while (p->pathexpr) {
+        if (fnmatch(p->pathexpr, pathName, 0) == 0) {
+            if (p->hook) {
+                return 0;
+            } else {
+                wsLog("## rejecting attempt to open %s\n", pathName);
+                errno = ENOENT;
+                return -2;
+            }
+            break;
+        }
+        p++;
+    }
+    errno = ENOENT;
+    return -1;
+}