auto import from //depot/cupcake/@135843
diff --git a/simulator/app/PropertyServer.cpp b/simulator/app/PropertyServer.cpp
new file mode 100644
index 0000000..0d6054f
--- /dev/null
+++ b/simulator/app/PropertyServer.cpp
@@ -0,0 +1,467 @@
+//
+// Copyright 2007 The Android Open Source Project
+//
+// Property sever.  Mimics behavior provided on the device by init(8) and
+// some code built into libc.
+//
+    
+// For compilers that support precompilation, include "wx/wx.h".
+#include "wx/wxprec.h"
+    
+// Otherwise, include all standard headers
+#ifndef WX_PRECOMP
+# include "wx/wx.h"
+#endif
+#include "wx/image.h"
+    
+#include "PropertyServer.h"
+#include "MyApp.h"
+#include "Preferences.h"
+#include "MainFrame.h"
+#include "utils.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+
+using namespace android;
+
+const char* PropertyServer::kPropCheckJni = "ro.kernel.android.checkjni";
+
+/*
+ * Destructor.
+ */
+PropertyServer::~PropertyServer(void)
+{
+    if (IsRunning()) {
+        // TODO: cause thread to stop, then Wait for it
+    }
+    printf("Sim: in ~PropertyServer()\n");
+}
+
+/*
+ * Create and run the thread.
+ */
+bool PropertyServer::StartThread(void)
+{
+    if (Create() != wxTHREAD_NO_ERROR) {
+        fprintf(stderr, "Sim: ERROR: can't create PropertyServer thread\n");
+        return false;
+    }
+
+    Run();
+    return true;
+}
+
+
+/*
+ * Clear out the list.
+ */
+void PropertyServer::ClearProperties(void)
+{
+    typedef List<Property>::iterator PropIter;
+
+    for (PropIter pi = mPropList.begin(); pi != mPropList.end(); ++pi) {
+        pi = mPropList.erase(pi);
+    }
+}
+
+/*
+ * Set default values for several properties.
+ */
+void PropertyServer::SetDefaultProperties(void)
+{
+    static const struct {
+        const char* key;
+        const char* value;
+    } propList[] = {
+        { "net.bt.name", "Android" },
+        { "ro.kernel.mem", "60M" },
+        { "ro.kernel.board_sardine.version", "4" },
+        { "ro.kernel.console", "null" },
+        { "ro.build.id", "engineering" },
+        { "ro.build.date", "Wed Nov 28 07:44:14 PST 2007" },
+        { "ro.build.date.utc", "1196264654" },
+        { "ro.build.type", "eng" },
+        { "ro.product.device", "simulator" /*"sooner"*/ },
+        { "ro.product.brand", "generic" },
+        { "ro.build.user", "fadden" },
+        { "ro.build.host", "marathon" },
+        { "ro.config.nocheckin", "yes" },
+        { "ro.product.manufacturer", "" },
+        { "ro.radio.use-ppp", "no" },
+        { "ro.FOREGROUND_APP_ADJ", "0" },
+        { "ro.VISIBLE_APP_ADJ", "1" },
+        { "ro.SECONDARY_SERVER_ADJ", "2" },
+        { "ro.HIDDEN_APP_MIN_ADJ", "7" },
+        { "ro.CONTENT_PROVIDER_ADJ", "14" },
+        { "ro.EMPTY_APP_ADJ", "15" },
+        { "ro.FOREGROUND_APP_MEM", "1536" },
+        { "ro.VISIBLE_APP_MEM", "2048" },
+        { "ro.SECONDARY_SERVER_MEM", "4096" },
+        { "ro.HIDDEN_APP_MEM", "8192" },
+        { "ro.EMPTY_APP_MEM", "16384" },
+        //{ "init.svc.adbd", "running" },       // causes ADB-JDWP
+        { "init.svc.usbd", "running" },
+        { "init.svc.debuggerd", "running" },
+        { "init.svc.ril-daemon", "running" },
+        { "init.svc.zygote", "running" },
+        { "init.svc.runtime", "running" },
+        { "init.svc.dbus", "running" },
+        { "init.svc.pppd_gprs", "running" },
+        { "adb.connected", "0" },
+        //{ "use-adb-networking", "1" },
+        /*
+        { "status.battery.state", "Slow" },
+        { "status.battery.level", "5" },
+        { "status.battery.level_raw", "50" },
+        { "status.battery.level_scale", "9" },
+        */
+
+        /* disable the annoying setup wizard */
+        { "app.setupwizard.disable", "1" },
+
+        /* Dalvik options, set by AndroidRuntime */
+        { "dalvik.vm.stack-trace-file", "/data/anr/traces.txt" },
+        //{ "dalvik.vm.execution-mode", "int:portable" },
+        { "dalvik.vm.enableassertions", "all" },    // -ea
+        { "dalvik.vm.dexopt-flags", "" },           // e.g. "v=a,o=v,m=n"
+        { "dalvik.vm.deadlock-predict", "off" },    // -Xdeadlockpredict
+        //{ "dalvik.vm.jniopts", "forcecopy" },       // -Xjniopts
+        { "log.redirect-stdio", "false" },          // -Xlog-stdio
+
+        /* SurfaceFlinger options */
+        { "debug.sf.nobootanimation", "1" },
+        { "debug.sf.showupdates", "0" },
+        { "debug.sf.showcpu", "0" },
+        { "debug.sf.showbackground", "0" },
+        { "debug.sf.showfps", "0" },
+    };
+
+    for (int i = 0; i < NELEM(propList); i++)
+        SetProperty(propList[i].key, propList[i].value);
+
+    Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();
+    bool doCheckJni = false;
+
+    pPrefs->GetBool("check-jni", &doCheckJni);
+    if (doCheckJni)
+        SetProperty(kPropCheckJni, "1");
+    else
+        SetProperty(kPropCheckJni, "0");
+}
+
+/*
+ * Get the value of a property.
+ *
+ * "valueBuf" must hold at least PROPERTY_VALUE_MAX bytes.
+ *
+ * Returns "true" if the property was found.
+ */
+bool PropertyServer::GetProperty(const char* key, char* valueBuf)
+{
+    typedef List<Property>::iterator PropIter;
+
+    assert(key != NULL);
+    assert(valueBuf != NULL);
+
+    for (PropIter pi = mPropList.begin(); pi != mPropList.end(); ++pi) {
+        Property& prop = *pi;
+        if (strcmp(prop.key, key) == 0) {
+            if (strlen(prop.value) >= PROPERTY_VALUE_MAX) {
+                fprintf(stderr,
+                    "GLITCH: properties table holds '%s' '%s' (len=%d)\n",
+                    prop.key, prop.value, strlen(prop.value));
+                abort();
+            }
+            assert(strlen(prop.value) < PROPERTY_VALUE_MAX);
+            strcpy(valueBuf, prop.value);
+            return true;
+        }
+    }
+
+    //printf("Prop: get [%s] not found\n", key);
+    return false;
+}
+
+/*
+ * Set the value of a property, replacing it if it already exists.
+ *
+ * If "value" is NULL, the property is removed.
+ *
+ * If the property is immutable, this returns "false" without doing
+ * anything.  (Not implemented.)
+ */
+bool PropertyServer::SetProperty(const char* key, const char* value)
+{
+    typedef List<Property>::iterator PropIter;
+
+    assert(key != NULL);
+    assert(value != NULL);
+
+    for (PropIter pi = mPropList.begin(); pi != mPropList.end(); ++pi) {
+        Property& prop = *pi;
+        if (strcmp(prop.key, key) == 0) {
+            if (value != NULL) {
+                //printf("Prop: replacing [%s]: [%s] with [%s]\n",
+                //    prop.key, prop.value, value);
+                strcpy(prop.value, value);
+            } else {
+                //printf("Prop: removing [%s]\n", prop.key);
+                mPropList.erase(pi);
+            }
+            return true;
+        }
+    }
+
+    //printf("Prop: adding [%s]: [%s]\n", key, value);
+    Property tmp;
+    strcpy(tmp.key, key);
+    strcpy(tmp.value, value);
+    mPropList.push_back(tmp);
+    return true;
+}
+
+/*
+ * Create a UNIX domain socket, carefully removing it if it already
+ * exists.
+ */
+bool PropertyServer::CreateSocket(const char* fileName)
+{
+    struct stat sb;
+    bool result = false;
+    int sock = -1;
+    int cc;
+
+    cc = stat(fileName, &sb);
+    if (cc < 0) {
+        if (errno != ENOENT) {
+            LOG(LOG_ERROR, "sim-prop",
+                "Unable to stat '%s' (errno=%d)\n", fileName, errno);
+            goto bail;
+        }
+    } else {
+        /* don't touch it if it's not a socket */
+        if (!(S_ISSOCK(sb.st_mode))) {
+            LOG(LOG_ERROR, "sim-prop",
+                "File '%s' exists and is not a socket\n", fileName);
+            goto bail;
+        }
+
+        /* remove the cruft */
+        if (unlink(fileName) < 0) {
+            LOG(LOG_ERROR, "sim-prop",
+                "Unable to remove '%s' (errno=%d)\n", fileName, errno);
+            goto bail;
+        }
+    }
+
+    struct sockaddr_un addr;
+
+    sock = ::socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock < 0) {
+        LOG(LOG_ERROR, "sim-prop",
+            "UNIX domain socket create failed (errno=%d)\n", errno);
+        goto bail;
+    }
+
+    /* bind the socket; this creates the file on disk */
+    strcpy(addr.sun_path, fileName);    // max 108 bytes
+    addr.sun_family = AF_UNIX;
+    cc = ::bind(sock, (struct sockaddr*) &addr, SUN_LEN(&addr));
+    if (cc < 0) {
+        LOG(LOG_ERROR, "sim",
+            "AF_UNIX bind failed for '%s' (errno=%d)\n", fileName, errno);
+        goto bail;
+    }
+
+    cc = ::listen(sock, 5);
+    if (cc < 0) {
+        LOG(LOG_ERROR, "sim", "AF_UNIX listen failed (errno=%d)\n", errno);
+        goto bail;
+    }
+
+    mListenSock = sock;
+    sock = -1;
+    result = true;
+
+bail:
+    if (sock >= 0)
+        close(sock);
+    return result;
+}
+
+/*
+ * Handle a client request.
+ *
+ * Returns true on success, false if the fd should be closed.
+ */
+bool PropertyServer::HandleRequest(int fd)
+{
+    char reqBuf[PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX];
+    char valueBuf[1 + PROPERTY_VALUE_MAX];
+    ssize_t actual;
+
+    memset(valueBuf, 'x', sizeof(valueBuf));        // placate valgrind
+
+    /* read the command byte; this determines the message length */
+    actual = read(fd, reqBuf, 1);
+    if (actual <= 0)
+        return false;
+
+    if (reqBuf[0] == kSystemPropertyGet) {
+        actual = read(fd, reqBuf, PROPERTY_KEY_MAX);
+
+        if (actual != PROPERTY_KEY_MAX) {
+            fprintf(stderr, "Bad read on get: %d of %d\n",
+                actual, PROPERTY_KEY_MAX);
+            return false;
+        }
+        if (GetProperty(reqBuf, valueBuf+1))
+            valueBuf[0] = 1;
+        else
+            valueBuf[0] = 0;
+        //printf("GET property [%s]: (found=%d) [%s]\n",
+        //    reqBuf, valueBuf[0], valueBuf+1);
+        if (write(fd, valueBuf, sizeof(valueBuf)) != sizeof(valueBuf)) {
+            fprintf(stderr, "Bad write on get\n");
+            return false;
+        }
+    } else if (reqBuf[0] == kSystemPropertySet) {
+        actual = read(fd, reqBuf, PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX);
+        if (actual != PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX) {
+            fprintf(stderr, "Bad read on set: %d of %d\n",
+                actual, PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX);
+            return false;
+        }
+        //printf("SET property '%s'\n", reqBuf);
+        if (SetProperty(reqBuf, reqBuf + PROPERTY_KEY_MAX))
+            valueBuf[0] = 1;
+        else
+            valueBuf[0] = 0;
+        if (write(fd, valueBuf, 1) != 1) {
+            fprintf(stderr, "Bad write on set\n");
+            return false;
+        }
+    } else if (reqBuf[0] == kSystemPropertyList) {
+        /* TODO */
+        assert(false);
+    } else {
+        fprintf(stderr, "Unexpected request %d from prop client\n", reqBuf[0]);
+        return false;
+    }
+
+    return true;
+}
+
+/*
+ * Serve up properties.
+ */
+void PropertyServer::ServeProperties(void)
+{
+    typedef List<int>::iterator IntIter;
+    fd_set readfds;
+    int maxfd;
+
+    while (true) {
+        int cc;
+
+        FD_ZERO(&readfds);
+        FD_SET(mListenSock, &readfds);
+        maxfd = mListenSock;
+
+        for (IntIter ii = mClientList.begin(); ii != mClientList.end(); ++ii) {
+            int fd = (*ii);
+
+            FD_SET(fd, &readfds);
+            if (maxfd < fd)
+                maxfd = fd;
+        }
+
+        cc = select(maxfd+1, &readfds, NULL, NULL, NULL);
+        if (cc < 0) {
+            if (errno == EINTR) {
+                printf("hiccup!\n");
+                continue;
+            }
+            return;
+        }
+        if (FD_ISSET(mListenSock, &readfds)) {
+            struct sockaddr_un from;
+            socklen_t fromlen;
+            int newSock;
+
+            fromlen = sizeof(from);
+            newSock = ::accept(mListenSock, (struct sockaddr*) &from, &fromlen);
+            if (newSock < 0) {
+                LOG(LOG_WARN, "sim",
+                    "AF_UNIX accept failed (errno=%d)\n", errno);
+            } else {
+                //printf("new props connection on %d --> %d\n",
+                //    mListenSock, newSock);
+
+                mClientList.push_back(newSock);
+            }
+        }
+
+        for (IntIter ii = mClientList.begin(); ii != mClientList.end(); ) {
+            int fd = (*ii);
+            bool ok = true;
+
+            if (FD_ISSET(fd, &readfds)) {
+                //printf("--- activity on %d\n", fd);
+
+                ok = HandleRequest(fd);
+            }
+
+            if (ok) {
+                ++ii;
+            } else {
+                //printf("--- closing %d\n", fd);
+                close(fd);
+                ii = mClientList.erase(ii);
+            }
+        }
+    }
+}
+
+/*
+ * Thread entry point.
+ *
+ * This just sits and waits for a new connection.  It hands it off to the
+ * main thread and then goes back to waiting.
+ *
+ * There is currently no "polite" way to shut this down.
+ */
+void* PropertyServer::Entry(void)
+{
+    if (CreateSocket(SYSTEM_PROPERTY_PIPE_NAME)) {
+        assert(mListenSock >= 0);
+        SetDefaultProperties();
+
+        /* loop until it's time to exit or we fail */
+        ServeProperties();
+
+        ClearProperties();
+
+        /*
+         * Close listen socket and all clients.
+         */
+        LOG(LOG_INFO, "sim", "Cleaning up socket list\n");
+        typedef List<int>::iterator IntIter;
+        for (IntIter ii = mClientList.begin(); ii != mClientList.end(); ++ii)
+            close((*ii));
+        close(mListenSock);
+    }
+
+    LOG(LOG_INFO, "sim", "PropertyServer thread exiting\n");
+    return NULL;
+}
+