//
// Copyright 2005 The Android Open Source Project
//
// Management of the simulated device.
//

// 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 "DeviceManager.h"
#include "MyApp.h"
#include "DeviceWindow.h"
#include "LogWindow.h"
#include "UserEvent.h"
#include "UserEventMessage.h"

#include "SimRuntime.h"
#include "utils.h"

#include <unistd.h>
#include <signal.h>
#include <errno.h>

#if !defined(SIGKILL)      // doesn't exist in MinGW
# if defined(SIGBREAK)
#  define SIGKILL   SIGBREAK        // intended for Ctrl-Break
# else
#  define SIGKILL   SIGABRT
# endif
#endif


/*
 * Constructor.
 */
DeviceManager::DeviceManager(void)
    : mThread(NULL), mDisplay(NULL), mNumDisplays(0), mKeyMap(NULL),
      mpStatusWindow(NULL)
{
    //printf("--- DeviceManager constructor\n");
}

/*
 * Destructor.  Snuff the thread if it's still kicking.
 */
DeviceManager::~DeviceManager(void)
{
    //printf("--- DeviceManager destructor\n");

    if (mThread != NULL && mThread->IsRunning()) {
        mThread->KillChildProcesses();
    }
    if (mThread != NULL) {
        wxThread::ExitCode code;

        printf("Sim: Waiting for old runtime thread..."); fflush(stdout);
        code = mThread->Wait();        // join the old thread
        printf("done (code=%ld)\n", (long) code);
    }
    delete mThread;
    mThread = NULL;

    delete[] mDisplay;
    free((void*)mKeyMap);
}

/*
 * Initialize the device configuration.
 *
 * "statusWindow" is where message boxes with failure messages go, usually
 * the main frame.
 */
bool DeviceManager::Init(int numDisplays, wxWindow* statusWindow)
{
    //if (IsRunning()) {
    //    fprintf(stderr, "ERROR: tried to Configure device while running\n");
    //    return false;
    //}
    assert(mDisplay == NULL);
    assert(numDisplays > 0);

    //if (mDisplay != NULL)
    //     delete[] mDisplay;

    mDisplay = new Display[numDisplays];
    mNumDisplays = numDisplays;

    mpStatusWindow = statusWindow;

    return true;
}

/*
 * Have we been initialized already?
 */
bool DeviceManager::IsInitialized(void) const
{
    return (mDisplay != NULL);
}

#if 0
/*
 * Return the Nth display.
 */
int DeviceManager::GetShmemKey(int displayIndex)
{
    assert(displayIndex >= 0 && displayIndex < mNumDisplays);
    return mDisplay[displayIndex].GetShmemKey();
}
#endif

/*
 * Define mapping between the device's display and a wxWidgets window.
 */
bool DeviceManager::SetDisplayConfig(int displayIndex, wxWindow* window,
    int width, int height, android::PixelFormat format, int refresh)
{
    assert(displayIndex >= 0 && displayIndex < mNumDisplays);

    if (!mDisplay[displayIndex].Create(displayIndex, window, width, height,
        format, refresh))
    {
        fprintf(stderr, "Sim: ERROR: unable to configure display %d\n",
            displayIndex);
        return false;
    } else {
        printf("Sim: configured display %d (w=%d h=%d f=%d re=%d)\n",
            displayIndex, width, height, format, refresh);
        return true;
    }
}

/*
 * Define the keyboard
 */
bool DeviceManager::SetKeyboardConfig(const char *keymap) {
    free((void*)mKeyMap);
    mKeyMap = strdup(keymap);
    return true;
}

/*
 * Called before the phone window dialog destroys itself.  The goal here
 * is to prevent the runtime thread from trying to draw after the phone
 * window has closed for business but before the device manager destructor
 * gets called.
 */
void DeviceManager::WindowsClosing(void)
{
    int i;

    for (i = 0; i < mNumDisplays; i++)
        mDisplay[i].Uncreate();
}

/*
 * Launch a new runtime process.  If there is an existing device manager
 * thread, we assume that it is in the process of shutting down.
 */
bool DeviceManager::StartRuntime(void)
{
    return DeviceManager::DeviceThread::LaunchProcess(mpStatusWindow);
}

/*
 * Start the runtime management thread when a runtime connects to us.  If
 * there is an existing thread, we assume that it is in the process of
 * shutting down.
 */
bool DeviceManager::StartRuntime(android::Pipe* reader, android::Pipe* writer)
{
    if (mThread != NULL) {
        wxThread::ExitCode code;

        if (mThread->IsRunning()) {
            fprintf(stderr,
                "Sim: ERROR: start requested, but thread running\n");
            return false;
        }

        // clean up old thread
        printf("Sim: Waiting for old runtime thread..."); fflush(stdout);
        code = mThread->Wait();        // join the old thread
        printf("done (code=%ld)\n", (long) code);

        delete mThread;
        mThread = NULL;
    }

    assert(mpStatusWindow != NULL);
    mThread = new DeviceThread(this, mpStatusWindow, reader, writer);
    if (mThread->Create() != wxTHREAD_NO_ERROR) {
        fprintf(stderr, "Sim: ERROR: can't create thread\n");
        return false;
    }
    mThread->Run();

    return true;
}

/*
 * Get the message stream.  Returns NULL if it doesn't exist.
 */
android::MessageStream* DeviceManager::GetStream(void)
{
    if (!IsRunning()) {
        fprintf(stderr, "Sim: ERROR: runtime thread not active\n");
        return NULL;
    }

    assert(mThread != NULL);
    android::MessageStream* pStream = mThread->GetStream();
    assert(pStream != NULL);

    if (!pStream->isReady()) {
        fprintf(stderr, "Sim: NOTE: connection to runtime not ready\n");
        return NULL;
    }

    return pStream;
}

/*
 * Stop the runtime, politely.
 *
 * We don't clean up the thread here, because it might not exit immediately.
 */
bool DeviceManager::StopRuntime(void)
{
    android::MessageStream* pStream = GetStream();
    if (pStream == NULL)
        return false;

    printf("Sim: Sending quit command\n");

    android::Message msg;
    msg.setCommand(android::Simulator::kCommandQuit, 0);
    pStream->send(&msg);
    return true;
}

/*
 * Kill the runtime as efficiently as possible.
 */
void DeviceManager::KillRuntime(void)
{
    if (mThread != NULL && mThread->IsRunning())
        mThread->KillChildProcesses();
}

#if 0
/*
 * Check if the modified time is newer than mLastModified
 */
bool DeviceManager::RefreshRuntime(void)
{
    return (IsRunning() && mThread->IsRuntimeNew());
}

/*
 * Tells the device manager that the user does not want to update
 * the runtime
 */
void DeviceManager::UserCancelledRefresh(void)
{
    mThread->UpdateLastModified();
}
#endif

/*
 * Send an event to the runtime.
 *
 * The events are defined in display_device.h.
 */
void DeviceManager::SendKeyEvent(int32_t keyCode, bool down)
{
    android::MessageStream* pStream = GetStream();
    if (pStream == NULL)
        return;

    int event = down ? android::Simulator::kCommandKeyDown :
                       android::Simulator::kCommandKeyUp;

    //printf("Sim: sending key-%s %d\n", down ? "down" : "up", keyCode);

    android::Message msg;
    msg.setCommand(event, keyCode);
    pStream->send(&msg);
}

/*
 * Send a "touch screen" event to the runtime.
 *
 * "mode" can be "down" (we're pressing), "up" (we're lifting our finger
 * off) or "drag".
 */
void DeviceManager::SendTouchEvent(android::Simulator::TouchMode mode,
    int x, int y)
{
    android::MessageStream* pStream = GetStream();
    if (pStream == NULL)
        return;

    //printf("Sim: sending touch-%d x=%d y=%d\n", (int) mode, x, y);

    android::Message msg;
    msg.setCommandExt(android::Simulator::kCommandTouch, mode, x, y);
    pStream->send(&msg);
}

/*
 * The runtime has sent us a new frame of stuff to display.
 *
 * NOTE: we're still in the runtime management thread.  We have to pass the
 * bitmap through AddPendingEvent to get it over to the main thread.
 *
 * We have to make a copy of the data from the runtime; the easiest
 * way to do that is to convert it to a bitmap here.  However, X11 gets
 * all worked up about calls being made from multiple threads, so we're
 * better off just copying it into a buffer.
 *
 * Because we're decoupled from the runtime, there is a chance that we
 * could drop frames.  Buffering them up is probably worse, since it
 * creates the possibility that we could stall and run out of memory.
 * We could save a copy by handing the runtime a pointer to our buffer,
 * but then we'd have to mutex the runtime against the simulator window
 * Paint function.
 */
void DeviceManager::ShowFrame(int displayIndex)
{
    assert(displayIndex >= 0 && displayIndex < mNumDisplays);

    // copy the data to local storage and convert
    mDisplay[displayIndex].CopyFromShared();

    // create a user event and send it to the window
    UserEvent uev(0, (void*) displayIndex);

    wxWindow* pEventWindow = mDisplay[displayIndex].GetWindow();
    if (pEventWindow != NULL) {
        //printf("runtime has image, passing up\n");
        pEventWindow->AddPendingEvent(uev);
    } else {
        fprintf(stderr, "NOTE: runtime has image, display not available\n");
    }
}

void DeviceManager::Vibrate(int vibrateOn)
{
	((MyApp*)wxTheApp)->Vibrate(vibrateOn);
}

/*
 * Get the display data from the specified display.
 */
wxBitmap* DeviceManager::GetImageData(int displayIndex)
{
    assert(displayIndex >= 0 && displayIndex < mNumDisplays);
    return mDisplay[displayIndex].GetImageData();
}

/*
 * Send an event to all device windows
 */
void DeviceManager::BroadcastEvent(UserEvent& userEvent) {
    int numDisplays = GetNumDisplays();
    for (int i = 0; i < numDisplays; i++) {
        wxWindow* pEventWindow = mDisplay[i].GetWindow();
        if (pEventWindow != NULL) {
            pEventWindow->AddPendingEvent(userEvent);
        }
    }
}


/*
 * ===========================================================================
 *      DeviceManager::Display
 * ===========================================================================
 */

/*
 * Fill out the various interesting fields based on the parameters.
 */
bool DeviceManager::Display::Create(int displayNum, wxWindow* window,
    int width, int height, android::PixelFormat format, int refresh)
{
    //printf("DeviceManager::Display constructor\n");

    assert(window != NULL);
    if (mImageData != NULL) {
        assert(false);              // no re-init
        return false;
    }

    mDisplayNum = displayNum;
    mDisplayWindow = window;
    mWidth = width;
    mHeight = height;
    mFormat = format;
    mRefresh = refresh;

    // use a fixed key for now
    mShmemKey = GenerateKey(displayNum);
    // allocate 24bpp for now
    mpShmem = new android::Shmem;
    if (!mpShmem->create(mShmemKey, width * height * 3, true))
        return false;
    //printf("--- CREATED shmem, key=0x%08x addr=%p\n",
    //    mShmemKey, mpShmem->getAddr());

    mImageData = new unsigned char[width * height * 3];
    if (mImageData == NULL)
        return false;

    return true;
}

/*
 * The UI components are starting to shut down.  We need to do away with
 * our wxWindow pointer so that the runtime management thread doesn't try
 * to send it display update events.
 *
 * We also need to let go of our side of the shared memory, because a
 * new DeviceManager may get started up before our destructor gets called,
 * and we may be re-using the key.
 */
void DeviceManager::Display::Uncreate(void)
{
    wxMutexLocker locker(mImageDataLock);

    //printf("--- Uncreate\n");

    mDisplayWindow = NULL;

    // the "locker" mutex keeps this from hosing CopyFromShared()
    if (mpShmem != NULL) {
        //printf("--- DELETING shmem, addr=%p\n", mpShmem->getAddr());
        delete mpShmem;
        mpShmem = NULL;
    }
}

/*
 * Make a local copy of the image data.  The UI grabs this data from a
 * different thread, so we have to mutex it.
 */
void DeviceManager::Display::CopyFromShared(void)
{
    wxMutexLocker locker(mImageDataLock);

    if (mpShmem == NULL) {
        //printf("Sim: SKIP CopyFromShared\n");
        return;
    }

    //printf("Display %d: copying data from %p to %p\n",
    //    mDisplayNum, mpShmem->getAddr(), mImageData);

    /* data is always 24bpp RGB */
    mpShmem->lock();        // avoid tearing
    memcpy(mImageData, mpShmem->getAddr(), mWidth * mHeight * 3);
    mpShmem->unlock();
}

/*
 * Get the image data in the form of a newly-allocated bitmap.
 *
 * This MUST be called from the UI thread.  Creating wxBitmaps in the
 * runtime management thread will cause X11 failures (e.g.
 * "Xlib: unexpected async reply").
 */
wxBitmap* DeviceManager::Display::GetImageData(void)
{
    wxMutexLocker locker(mImageDataLock);

    assert(mImageData != NULL);

    //printf("HEY: creating tmpImage, w=%d h=%d data=%p\n",
    //    mWidth, mHeight, mImageData);

    /* create a temporary wxImage; it does not own the data */
    wxImage tmpImage(mWidth, mHeight, (unsigned char*) mImageData, true);

    /* return a new bitmap with the converted-for-display data */
    return new wxBitmap(tmpImage);
}


/*
 * ===========================================================================
 *      DeviceManager::DeviceThread
 * ===========================================================================
 */

/*
 * Some notes on process management under Linux/Mac OS X:
 *
 * We want to put the runtime into its own process group.  That way we
 * can send SIGKILL to the entire group to guarantee that we kill it and
 * all of its children.  Simply killing the sim's direct descendant doesn't
 * do what we want.  If it's a debugger, we will just orphan the runtime
 * without killing it.  Even if the runtime is our child, the children of
 * the runtime might outlive it.
 *
 * We want to be able to run the child under GDB or Valgrind, both
 * of which take input from the tty.  They need to be in the "foreground"
 * process group.  We might be debugging or valgrinding the simulator,
 * or operating in a command-line-only "headless" mode, so in that case
 * the sim front-end should actually be in the foreground group.
 *
 * Putting the runtime in the background group means it can't read input
 * from the tty (not an issue) and will generate SIGTTOU signals when it
 * writes output to the tty (easy to ignore).  The trick, then, is to
 * have the simulator and gdb/valgrind in the foreground pgrp while the
 * runtime itself is in a different group.  This group needs to be known
 * to the simulator so that it can send signals to the appropriate place.
 *
 * The solution is to have the runtime process change its process group
 * after it starts but before it creates any new processes, and then send
 * the process group ID back to the simulator.  The sim can then send
 * signals to the pgrp to ensure that we don't end up with zombies.  Any
 * "pre-launch" processes, like GDB, stay in the sim's pgrp.  This also
 * allows a consistent API for platforms that don't have fork/exec
 * (e.g. MinGW).
 *
 * This doesn't help us with interactive valgrind (e.g. --db-attach=yes),
 * because valgrind is an LD_PRELOAD shared library rather than a
 * separate process.  For that, we actually need to use termios(3) to
 * change the terminal's pgrp, or the interactive stuff just doesn't work.
 * We don't want to do that every time or attempting to debug the simulator
 * front-end will have difficulties.
 *
 * Making this even more entertaining is the fact that the simulator
 * front-end could itself be launched in the background.  It's essential
 * that we be careful about assigning a process group to the foreground,
 * and that we don't restore ourselves unless we were in the foreground to
 * begin with.
 *
 *
 * Some notes on process management under Windows (Cygwin, MinGW):
 *
 * Signals cannot be caught or ignored under MinGW.  All signals are fatal.
 *
 * Signals can be ignored under Cygwin, but not caught.
 *
 * Windows has some process group stuff (e.g. CREATE_NEW_PROCESS_GROUP flag
 * and GenerateConsoleCtrlEvent()).  Need to explore.
 *
 *
 * UPDATE: we've abandoned Mac OS and MinGW, so we now launch the runtime in
 * a separate xterm.  This avoids all tty work on our side.  We still need
 * to learn the pgrp from the child during the initial communication
 * handshake so we can do necessary cleanup.
 */


/*
 * Convert a space-delimited string into an argument vector.
 *
 * "arg" is the current arg offset.
 */
static int stringToArgv(char* mangle, const char** argv, int arg, int maxArgs)
{
    bool first = true;

    while (*mangle != '\0') {
        assert(arg < maxArgs);
        if (first) {
            argv[arg++] = mangle;
            first = false;
        }
        if (*mangle == ' ') {
            *mangle = '\0';
            first = true;
        }
        mangle++;
    }

    return arg;
}

/*
 * Launch the runtime process in its own terminal window.  Start by setting
 * up the argument vector to the runtime process.
 *
 * The last entry in the vector will be a NULL pointer.
 *
 * This is awkward and annoying because the wxWidgets strings are current
 * configured for UNICODE.
 */
/*static*/ bool DeviceManager::DeviceThread::LaunchProcess(wxWindow* statusWindow)
{
    static const char* kLaunchWrapper = "launch-wrapper";
    const int kMaxArgs = 64;
    Preferences* pPrefs;
    wxString errMsg;
    wxString runtimeExe;
    wxString debuggerExe;
	wxString debuggerScript;
    wxString valgrinderExe;
    wxString launchWrapperExe;
    wxString launchWrapperArgs;
    wxString javaAppName;
    wxString termCmd;
    wxString tmpStr;
    char gammaVal[8];
    //bool bval;
    double dval;
    bool result = false;
    bool doDebug, doValgrind, doCheckJni, doEnableSound, doEnableFakeCamera;
    const char** argv = NULL;
    int arg;
    wxCharBuffer runtimeExeTmp;
    wxCharBuffer debuggerExeTmp;
	wxCharBuffer debuggerScriptTmp;
    wxCharBuffer javaAppNameTmp;
    wxCharBuffer valgrinderExeTmp;
    wxCharBuffer termCmdTmp;
    wxCharBuffer launchWrapperExeTmp;
    wxCharBuffer launchWrapperArgsTmp;
    
    pPrefs = ((MyApp*)wxTheApp)->GetPrefs();
    if (pPrefs == NULL) {
        errMsg = wxT("Preferences were not loaded.");
        goto bail;
    }

    /*
     * Set environment variables.  This stuff should be passed through as
     * arguments, but the runtime binary currently has a disconnect
     * between main() and the VM initilization.
     *
     * TODO: remove this in favor of system properties
     */
#if 0
    // TODO: restore this
    doCheckJni = false;
    pPrefs->GetBool("check-jni", &doCheckJni);
#endif

    tmpStr.Empty();
    pPrefs->GetString("ld-assume-kernel", /*ref*/ tmpStr);
    if (tmpStr.IsEmpty()) {
        unsetenv("LD_ASSUME_KERNEL");
    } else {
        setenv("LD_ASSUME_KERNEL", tmpStr.ToAscii(), 1);
    }

    doEnableSound = false; 
    pPrefs->GetBool("enable-sound", &doEnableSound);
    if (doEnableSound)
        setenv("ANDROIDSOUND", "1", 1);

    doEnableFakeCamera = false; 
    pPrefs->GetBool("enable-fake-camera", &doEnableFakeCamera);
    if (doEnableFakeCamera)
        setenv("ANDROIDFAKECAMERA", "1", 1);

    /*
     * Set the Dalvik bootstrap class path.  Normally this is set by "init".
     */
    setenv("BOOTCLASSPATH",
        "/system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar",
        1);

    /*
     * Figure out where the "runtime" binary lives.
     */
    runtimeExe = ((MyApp*)wxTheApp)->GetRuntimeExe();
    assert(!runtimeExe.IsEmpty());

    //UpdateLastModified();

    /*
     * Initialize argv.
     */
    argv = new const char*[kMaxArgs];
    if (argv == NULL)
        goto bail;
    arg = 0;

    /*
     * We want to launch the runtime in its own terminal window so we don't
     * have to fight over who gets access to the controlling tty.  We allow
     * the user to specify the command they want to use to perform the
     * launch.  Here we cut it into pieces for argv.
     *
     * To make life easier here, we require that the launch command be
     * all one piece, i.e. it's not "xterm -e <stuff> -geom blah" with our
     * stuff in the middle.
     */
    termCmd.Empty();
    pPrefs->GetString("launch-command", /*ref*/ termCmd);
    if (termCmd.IsEmpty()) {
        fprintf(stderr, "Sim: WARNING: launch-command is empty\n");
    } else {
        termCmdTmp = termCmd.ToAscii();
        char* mangle = strdup(termCmdTmp);
        arg = stringToArgv(mangle, argv, arg, kMaxArgs);
    }

    /*
     * The "launch-wrapper" binary lives in the same place as the runtime.
     * This sets up LD_PRELOAD and some other environment variables.
     */
    int charIdx;

    charIdx = runtimeExe.Find('/', true);
    if (charIdx == -1) {
        launchWrapperExe = wxString::FromAscii(kLaunchWrapper);
    } else {
        launchWrapperExe = runtimeExe.Mid(0, charIdx+1);
        launchWrapperExe.Append(wxString::FromAscii(kLaunchWrapper));
    }
    printf("Sim launch wrapper: %s\n", (const char*)launchWrapperExe.ToAscii());

    argv[arg++] = launchWrapperExeTmp = launchWrapperExe.ToAscii();

    launchWrapperArgs.Empty();
    pPrefs->GetString("launch-wrapper-args", /*ref*/ launchWrapperArgs);
    if (!launchWrapperArgs.IsEmpty()) {
        launchWrapperArgsTmp = launchWrapperArgs.ToAscii();
        char* mangle = strdup(launchWrapperArgsTmp);
        arg = stringToArgv(mangle, argv, arg, kMaxArgs);
    }

    /*
     * If we're launching under GDB or valgrind, set that up.
     */
    doDebug = doValgrind = false;
    pPrefs->GetBool("debug", &doDebug);
    if (((MyApp*)wxTheApp)->GetDebuggerOption()) {
        doDebug = true;
    }
	debuggerScript = ((MyApp*)wxTheApp)->GetDebuggerScript();

    pPrefs->GetBool("valgrind", &doValgrind);
    if (doDebug || doValgrind) {

        pPrefs->GetString("debugger", /*ref*/ debuggerExe);
        pPrefs->GetString("valgrinder", /*ref*/ valgrinderExe);

        // check for empty or undefined preferences
        if (doDebug && debuggerExe.IsEmpty()) {
            errMsg = wxT("Debugger not defined.");
            goto bail;
        }
        if (doValgrind && valgrinderExe.IsEmpty()) {
            errMsg = wxT("Valgrinder not defined.");
            goto bail;
        }

        if (doValgrind) {
            argv[arg++] = valgrinderExeTmp = valgrinderExe.ToAscii();
            //argv[arg++] = "--tool=callgrind";
            argv[arg++] = "--tool=memcheck";
            argv[arg++] = "--leak-check=yes";       // check for leaks too
            argv[arg++] = "--leak-resolution=med";  // increase from 2 to 4
            argv[arg++] = "--num-callers=8";        // reduce from 12 to 8
            //argv[arg++] = "--show-reachable=yes";   // show still-reachable
            if (doDebug) {
                //mTerminalFollowsChild = true;   // interactive
                argv[arg++] = "--db-attach=yes";
            }
            //mSlowExit = true;
        } else /*doDebug*/ {
            argv[arg++] = debuggerExeTmp = debuggerExe.ToAscii();
			if (!debuggerScript.IsEmpty()) {
				argv[arg++] = "-x";
				argv[arg++] = debuggerScriptTmp = debuggerScript.ToAscii();
			}
            argv[arg++] = runtimeExeTmp = runtimeExe.ToAscii();
            argv[arg++] = "--args";
        }
    }

    /*
     * Get runtime args.
     */

    argv[arg++] = runtimeExeTmp = (const char*) runtimeExe.ToAscii();

    javaAppName = ((MyApp*)wxTheApp)->GetAutoRunApp();
    if (javaAppName.IsEmpty()) {
        if (!pPrefs->GetString("java-app-name", /*ref*/ javaAppName)) {
            javaAppName = wxT("");
        }
    }

    if (!javaAppName.IsEmpty())
    {
        argv[arg++] = "-j";
        argv[arg++] = javaAppNameTmp = (const char*) javaAppName.ToAscii();
    }

    if (pPrefs->GetDouble("gamma", &dval) && dval != 1.0) {
        snprintf(gammaVal, sizeof(gammaVal), "%.3f", dval);
        argv[arg++] = "-g";
        argv[arg++] = gammaVal;
    }

    /* finish arg set */
    argv[arg++] = NULL;

    assert(arg <= kMaxArgs);

#if 1
    printf("ARGS:\n");
    for (int i = 0; i < arg; i++)
        printf(" %d: '%s'\n", i, argv[i]);
#endif

    if (fork() == 0) {
        execvp(argv[0], (char* const*) argv);
        fprintf(stderr, "execvp '%s' failed: %s\n", argv[0], strerror(errno));
        exit(1);
    }

    /*
     * We assume success; if it didn't succeed we'll just sort of hang
     * out waiting for a connection.  There are ways to fix this (create
     * a non-close-on-exec pipe and watch to see if the other side closes),
     * but at this stage it's not worthwhile.
     */
    result = true;

    tmpStr = wxT("=== launched ");
    tmpStr += runtimeExe;
    LogWindow::PostLogMsg(tmpStr);

    assert(errMsg.IsEmpty());

bail:
    if (!errMsg.IsEmpty()) {
        assert(result == false);

        UserEventMessage* pUem = new UserEventMessage;
        pUem->CreateErrorMessage(errMsg);

        UserEvent uev(0, (void*) pUem);

        assert(statusWindow != NULL);
        statusWindow->AddPendingEvent(uev);
    }
    delete[] argv;
    return result;
}

/*
 * This is the entry point for the device thread.  The thread launches the
 * runtime process and monitors it.  When the runtime exits, the thread
 * exits.
 *
 * Because this isn't running in the UI thread, any user interaction has
 * to be channeled through "user events" to the appropriate window.
 */
void* DeviceManager::DeviceThread::Entry(void)
{
    //android::MessageStream stream;
    android::Message msg;
    wxString errMsg;
    char statusBuf[64] = "(no status)";
    int result = 1;

    /* print this so we can make sense of log messages */
    LOG(LOG_DEBUG, "", "Sim: device management thread starting (pid=%d)\n",
        getpid());

    assert(mReader != NULL && mWriter != NULL);

    /*
     * Tell the main thread that we're running.  If something fails here,
     * we'll send them a "stopped running" immediately afterward.
     */
    {
        UserEventMessage* pUem = new UserEventMessage;
        pUem->CreateRuntimeStarted();

        UserEvent uev(0, (void*) pUem);

        assert(mpStatusWindow != NULL);
        mpStatusWindow->AddPendingEvent(uev);
    }
    LogWindow::PostLogMsg(
            "==============================================================");
    LogWindow::PostLogMsg("=== runtime starting");

    /*
     * Establish contact with runtime.
     */
    if (!mStream.init(mReader, mWriter, true)) {
        errMsg = wxT("ERROR: Unable to establish communication with runtime.\n");
        goto bail;
    }

    /*
     * Tell the runtime to put itself into a new process group and set
     * itself up as the foreground process.  The latter is only really
     * necessary to make valgrind+gdb work.
     */
    msg.setCommand(android::Simulator::kCommandNewPGroup, true);
    mStream.send(&msg);

    printf("Sim: Sending hardware configuration\n");

    /*
     * Send display config.
     *
     * Right now we're just shipping a big binary blob over.
     */
    assert(android::Simulator::kValuesPerDisplay >= 5);
    int buf[1 + 1 + mpDeviceManager->GetNumDisplays() *
                    android::Simulator::kValuesPerDisplay];
    buf[0] = android::Simulator::kDisplayConfigMagic;
    buf[1] = mpDeviceManager->GetNumDisplays();
    for (int i = 0; i < mpDeviceManager->GetNumDisplays(); i++) {
        DeviceManager::Display* pDisplay = mpDeviceManager->GetDisplay(i);
        int* pBuf = &buf[2 + android::Simulator::kValuesPerDisplay * i];

        pBuf[0] = pDisplay->GetWidth();
        pBuf[1] = pDisplay->GetHeight();
        pBuf[2] = pDisplay->GetFormat();
        pBuf[3] = pDisplay->GetRefresh();
        pBuf[4] = pDisplay->GetShmemKey();
    }
    msg.setRaw((const unsigned char*)buf, sizeof(buf),
        android::Message::kCleanupNoDelete);
    mStream.send(&msg);

    /*
     * Send other hardware config.
     *
     * Examples:
     * - Available input devices.
     * - Set of buttons on device.
     * - External devices (Bluetooth, etc).
     * - Initial mode (e.g. "flipped open" vs. "flipped closed").
     */

    msg.setConfig("keycharmap", mpDeviceManager->GetKeyMap());
    mStream.send(&msg);

    /*
     * Done with config.
     */
    msg.setCommand(android::Simulator::kCommandConfigDone, 0);
    mStream.send(&msg);

    /*
     * Sit forever, waiting for messages from the runtime process.
     */
    while (1) {
        if (!mStream.recv(&msg, true)) {
            /*
             * The read failed.  This usually means the child has died.
             */
            printf("Sim: runtime process has probably died\n");
            break;
        }

        if (msg.getType() == android::Message::kTypeCommand) {
            int cmd, arg;

            if (!msg.getCommand(&cmd, &arg)) {
                fprintf(stderr, "Sim: Warning: failed unpacking command\n");
                /* keep going? */
            } else {
                switch (cmd) {
                case android::Simulator::kCommandNewPGroupCreated:
                    // runtime has moved into a separate process group
                    // (not expected for external)
                    printf("Sim: child says it's now in pgrp %d\n", arg);
                    mRuntimeProcessGroup = arg;
                    break;
                case android::Simulator::kCommandRuntimeReady:
                    // sim is up and running, do late init
                    break;
                case android::Simulator::kCommandUpdateDisplay:
                    // new frame of graphics is ready
                    //printf("RCVD display update %d\n", arg);
                    mpDeviceManager->ShowFrame(arg);
                    break;
                case android::Simulator::kCommandVibrate:
                    // vibrator on or off
                    //printf("RCVD vibrator update %d\n", arg);
                    mpDeviceManager->Vibrate(arg);
                    break;
                default:
                    printf("Sim: got unknown command %d/%d\n", cmd, arg);
                    break;
                }
            }
        } else if (msg.getType() == android::Message::kTypeLogBundle) {
            android_LogBundle bundle;

            if (!msg.getLogBundle(&bundle)) {
                fprintf(stderr, "Sim: Warning: failed unpacking logBundle\n");
                /* keep going? */
            } else {
                LogWindow::PostLogMsg(&bundle);
            }
        } else {
            printf("Sim: got unknown message type=%d\n", msg.getType());
        }
    }

    result = 0;

bail:
    printf("Sim: DeviceManager thread preparing to exit\n");

    /* kill the comm channel; should encourage runtime to die */
    mStream.close();
    delete mReader;
    delete mWriter;
    mReader = mWriter = NULL;

    /*
     * We never really did get a "friendly death" working, so just slam
     * the thing if we have the process group.
     */
    if (mRuntimeProcessGroup != 0) {
        /* kill the group, not our immediate child */
        printf("Sim: killing pgrp %d\n", (int) mRuntimeProcessGroup);
        kill(-mRuntimeProcessGroup, 9);
    }

    if (!errMsg.IsEmpty()) {
        UserEventMessage* pUem = new UserEventMessage;
        pUem->CreateErrorMessage(errMsg);

        UserEvent uev(0, (void*) pUem);
        mpStatusWindow->AddPendingEvent(uev);
    }

    /* notify the main window that the runtime has stopped */
    {
        UserEventMessage* pUem = new UserEventMessage;
        pUem->CreateRuntimeStopped();

        UserEvent uev(0, (void*) pUem);
        mpStatusWindow->AddPendingEvent(uev);
    }

    /* show exit status in log file */
    wxString exitMsg;
    exitMsg.Printf(wxT("=== runtime exiting - %s"), statusBuf);
    LogWindow::PostLogMsg(exitMsg);
    LogWindow::PostLogMsg(
        "==============================================================\n");

    /*
     * Reset system properties for future runs.
     */
    ResetProperties();

    return (void*) result;
}


/*
 * Wait for a little bit to see if the thread will exit.
 *
 * "delay" is in 0.1s increments.
 */
void DeviceManager::DeviceThread::WaitForDeath(int delay)
{
    const int kDelayUnit = 100000;
    int i;

    for (i = 0; i < delay; i++) {
        if (!IsRunning())
            return;
        usleep(kDelayUnit);
    }
}


/*
 * Kill the runtime process.  The goal is to cause our local runtime
 * management thread to exit.  If it doesn't, this will kill the thread
 * before it returns.
 */
void DeviceManager::DeviceThread::KillChildProcesses(void)
{
    if (!this->IsRunning())
        return;

    /* clear "slow exit" flag -- we're forcefully killing this thing */
    //this->mSlowExit = false;

    /*
     * Use the ChildProcess object in the thread to send signals.  There's
     * a risk that the DeviceThread will exit and destroy the object while
     * we're using it.  Using a mutex here gets a little awkward because
     * we can't put it in DeviceThread.  It's easier to make a copy of
     * ChildProcess and operate on the copy, but we have to do that very
     * carefully to avoid interfering with the communcation pipes.
     *
     * For now, we just hope for the best.  FIX this someday.
     *
     * We broadcast to the process group, which will ordinarily kill
     * everything.  If we're running with valgrind+GDB everything is in our
     * pgrp and we can't do the broadcast; if GDB alone, then only GDB is
     * in our pgrp, so the broadcast will hit everything except it.  We
     * hit the group and then hit our child for good measure.
     */
    if (mRuntimeProcessGroup != 0) {
        /* kill the group, not our immediate child */
        printf("Sim: killing pgrp %d\n", (int) mRuntimeProcessGroup);
        kill(-mRuntimeProcessGroup, 9);
        WaitForDeath(15);
    }

    /*
     * Close the communication channel.  This should cause our thread
     * to snap out of its blocking read and the runtime thread to bail
     * out the next time it tries to interact with us.  We should only
     * get here if somebody other than our direct descendant has the
     * comm channel open and our broadcast didn't work, which should
     * no longer be possible.
     */
    if (this->IsRunning()) {
        printf("Sim: killing comm channel\n");
        mStream.close();
        delete mReader;
        delete mWriter;
        mReader = mWriter = NULL;
        WaitForDeath(15);
    }

    /*
     * At this point it's possible that our DeviceThread is just wedged.
     * Kill it.
     *
     * Using the thread Kill() function can orphan resources, including
     * locks and semaphores.  There is some risk that the simulator will
     * be hosed after this.
     */
    if (this->IsRunning()) {
        fprintf(stderr, "Sim: WARNING: killing runtime thread (%ld)\n",
            (long) GetId());
        this->Kill();
        WaitForDeath(15);
    }

    /*
     * Now I'm scared.
     */
    if (this->IsRunning()) {
        fprintf(stderr, "Sim: thread won't die!\n");
    }
}


/*
 * Configure system properties for the simulated device.
 *
 * Property requests can arrive *before* the full connection to the
 * simulator is established, so we want to reset these during cleanup.
 */
void DeviceManager::DeviceThread::ResetProperties(void)
{
	wxWindow* mainFrame = ((MyApp*)wxTheApp)->GetMainFrame();
    PropertyServer* props = ((MainFrame*)mainFrame)->GetPropertyServer();

    props->ClearProperties();
    props->SetDefaultProperties();
}


#if 0
/*
 * Return true if the executable found is newer than
 * what is currently running
 */
bool DeviceManager::DeviceThread::IsRuntimeNew(void)
{
    if (mLastModified == 0) {
        /*
         * Haven't called UpdateLastModified yet, or called it but
         * couldn't stat() the executable.
         */
        return false;
    }

    struct stat status;
    if (stat(mRuntimeExe.ToAscii(), &status) == 0) {
        return (status.st_mtime > mLastModified);
    } else {
        // doesn't exist, so it can't be newer
        fprintf(stderr, "Sim: unable to stat '%s': %s\n",
            (const char*) mRuntimeExe.ToAscii(), strerror(errno));
        return false;
    }
}

/*
 * Updates mLastModified to reflect the current executables mtime
 */
void DeviceManager::DeviceThread::UpdateLastModified(void)
{
    struct stat status;
    if (stat(mRuntimeExe.ToAscii(), &status) == 0) {
        mLastModified = status.st_mtime;
    } else {
        fprintf(stderr, "Sim: unable to stat '%s': %s\n",
            (const char*) mRuntimeExe.ToAscii(), strerror(errno));
        mLastModified = 0;
    }
}
#endif

