Home | History | Annotate | Download | only in app
      1 //
      2 // Copyright 2005 The Android Open Source Project
      3 //
      4 // Management of the simulated device.
      5 //
      6 
      7 // For compilers that support precompilation, include "wx/wx.h".
      8 #include "wx/wxprec.h"
      9 
     10 // Otherwise, include all standard headers
     11 #ifndef WX_PRECOMP
     12 # include "wx/wx.h"
     13 #endif
     14 #include "wx/image.h"
     15 
     16 #include "DeviceManager.h"
     17 #include "MyApp.h"
     18 #include "DeviceWindow.h"
     19 #include "LogWindow.h"
     20 #include "UserEvent.h"
     21 #include "UserEventMessage.h"
     22 
     23 #include "SimRuntime.h"
     24 #include "utils.h"
     25 
     26 #include <unistd.h>
     27 #include <signal.h>
     28 #include <errno.h>
     29 
     30 #if !defined(SIGKILL)      // doesn't exist in MinGW
     31 # if defined(SIGBREAK)
     32 #  define SIGKILL   SIGBREAK        // intended for Ctrl-Break
     33 # else
     34 #  define SIGKILL   SIGABRT
     35 # endif
     36 #endif
     37 
     38 
     39 /*
     40  * Constructor.
     41  */
     42 DeviceManager::DeviceManager(void)
     43     : mThread(NULL), mDisplay(NULL), mNumDisplays(0), mKeyMap(NULL),
     44       mpStatusWindow(NULL)
     45 {
     46     //printf("--- DeviceManager constructor\n");
     47 }
     48 
     49 /*
     50  * Destructor.  Snuff the thread if it's still kicking.
     51  */
     52 DeviceManager::~DeviceManager(void)
     53 {
     54     //printf("--- DeviceManager destructor\n");
     55 
     56     if (mThread != NULL && mThread->IsRunning()) {
     57         mThread->KillChildProcesses();
     58     }
     59     if (mThread != NULL) {
     60         wxThread::ExitCode code;
     61 
     62         printf("Sim: Waiting for old runtime thread..."); fflush(stdout);
     63         code = mThread->Wait();        // join the old thread
     64         printf("done (code=%ld)\n", (long) code);
     65     }
     66     delete mThread;
     67     mThread = NULL;
     68 
     69     delete[] mDisplay;
     70     free((void*)mKeyMap);
     71 }
     72 
     73 /*
     74  * Initialize the device configuration.
     75  *
     76  * "statusWindow" is where message boxes with failure messages go, usually
     77  * the main frame.
     78  */
     79 bool DeviceManager::Init(int numDisplays, wxWindow* statusWindow)
     80 {
     81     //if (IsRunning()) {
     82     //    fprintf(stderr, "ERROR: tried to Configure device while running\n");
     83     //    return false;
     84     //}
     85     assert(mDisplay == NULL);
     86     assert(numDisplays > 0);
     87 
     88     //if (mDisplay != NULL)
     89     //     delete[] mDisplay;
     90 
     91     mDisplay = new Display[numDisplays];
     92     mNumDisplays = numDisplays;
     93 
     94     mpStatusWindow = statusWindow;
     95 
     96     return true;
     97 }
     98 
     99 /*
    100  * Have we been initialized already?
    101  */
    102 bool DeviceManager::IsInitialized(void) const
    103 {
    104     return (mDisplay != NULL);
    105 }
    106 
    107 #if 0
    108 /*
    109  * Return the Nth display.
    110  */
    111 int DeviceManager::GetShmemKey(int displayIndex)
    112 {
    113     assert(displayIndex >= 0 && displayIndex < mNumDisplays);
    114     return mDisplay[displayIndex].GetShmemKey();
    115 }
    116 #endif
    117 
    118 /*
    119  * Define mapping between the device's display and a wxWidgets window.
    120  */
    121 bool DeviceManager::SetDisplayConfig(int displayIndex, wxWindow* window,
    122     int width, int height, android::PixelFormat format, int refresh)
    123 {
    124     assert(displayIndex >= 0 && displayIndex < mNumDisplays);
    125 
    126     if (!mDisplay[displayIndex].Create(displayIndex, window, width, height,
    127         format, refresh))
    128     {
    129         fprintf(stderr, "Sim: ERROR: unable to configure display %d\n",
    130             displayIndex);
    131         return false;
    132     } else {
    133         printf("Sim: configured display %d (w=%d h=%d f=%d re=%d)\n",
    134             displayIndex, width, height, format, refresh);
    135         return true;
    136     }
    137 }
    138 
    139 /*
    140  * Define the keyboard
    141  */
    142 bool DeviceManager::SetKeyboardConfig(const char *keymap) {
    143     free((void*)mKeyMap);
    144     mKeyMap = strdup(keymap);
    145     return true;
    146 }
    147 
    148 /*
    149  * Called before the phone window dialog destroys itself.  The goal here
    150  * is to prevent the runtime thread from trying to draw after the phone
    151  * window has closed for business but before the device manager destructor
    152  * gets called.
    153  */
    154 void DeviceManager::WindowsClosing(void)
    155 {
    156     int i;
    157 
    158     for (i = 0; i < mNumDisplays; i++)
    159         mDisplay[i].Uncreate();
    160 }
    161 
    162 /*
    163  * Launch a new runtime process.  If there is an existing device manager
    164  * thread, we assume that it is in the process of shutting down.
    165  */
    166 bool DeviceManager::StartRuntime(void)
    167 {
    168     return DeviceManager::DeviceThread::LaunchProcess(mpStatusWindow);
    169 }
    170 
    171 /*
    172  * Start the runtime management thread when a runtime connects to us.  If
    173  * there is an existing thread, we assume that it is in the process of
    174  * shutting down.
    175  */
    176 bool DeviceManager::StartRuntime(android::Pipe* reader, android::Pipe* writer)
    177 {
    178     if (mThread != NULL) {
    179         wxThread::ExitCode code;
    180 
    181         if (mThread->IsRunning()) {
    182             fprintf(stderr,
    183                 "Sim: ERROR: start requested, but thread running\n");
    184             return false;
    185         }
    186 
    187         // clean up old thread
    188         printf("Sim: Waiting for old runtime thread..."); fflush(stdout);
    189         code = mThread->Wait();        // join the old thread
    190         printf("done (code=%ld)\n", (long) code);
    191 
    192         delete mThread;
    193         mThread = NULL;
    194     }
    195 
    196     assert(mpStatusWindow != NULL);
    197     mThread = new DeviceThread(this, mpStatusWindow, reader, writer);
    198     if (mThread->Create() != wxTHREAD_NO_ERROR) {
    199         fprintf(stderr, "Sim: ERROR: can't create thread\n");
    200         return false;
    201     }
    202     mThread->Run();
    203 
    204     return true;
    205 }
    206 
    207 /*
    208  * Get the message stream.  Returns NULL if it doesn't exist.
    209  */
    210 android::MessageStream* DeviceManager::GetStream(void)
    211 {
    212     if (!IsRunning()) {
    213         fprintf(stderr, "Sim: ERROR: runtime thread not active\n");
    214         return NULL;
    215     }
    216 
    217     assert(mThread != NULL);
    218     android::MessageStream* pStream = mThread->GetStream();
    219     assert(pStream != NULL);
    220 
    221     if (!pStream->isReady()) {
    222         fprintf(stderr, "Sim: NOTE: connection to runtime not ready\n");
    223         return NULL;
    224     }
    225 
    226     return pStream;
    227 }
    228 
    229 /*
    230  * Stop the runtime, politely.
    231  *
    232  * We don't clean up the thread here, because it might not exit immediately.
    233  */
    234 bool DeviceManager::StopRuntime(void)
    235 {
    236     android::MessageStream* pStream = GetStream();
    237     if (pStream == NULL)
    238         return false;
    239 
    240     printf("Sim: Sending quit command\n");
    241 
    242     android::Message msg;
    243     msg.setCommand(android::Simulator::kCommandQuit, 0);
    244     pStream->send(&msg);
    245     return true;
    246 }
    247 
    248 /*
    249  * Kill the runtime as efficiently as possible.
    250  */
    251 void DeviceManager::KillRuntime(void)
    252 {
    253     if (mThread != NULL && mThread->IsRunning())
    254         mThread->KillChildProcesses();
    255 }
    256 
    257 #if 0
    258 /*
    259  * Check if the modified time is newer than mLastModified
    260  */
    261 bool DeviceManager::RefreshRuntime(void)
    262 {
    263     return (IsRunning() && mThread->IsRuntimeNew());
    264 }
    265 
    266 /*
    267  * Tells the device manager that the user does not want to update
    268  * the runtime
    269  */
    270 void DeviceManager::UserCancelledRefresh(void)
    271 {
    272     mThread->UpdateLastModified();
    273 }
    274 #endif
    275 
    276 /*
    277  * Send an event to the runtime.
    278  *
    279  * The events are defined in display_device.h.
    280  */
    281 void DeviceManager::SendKeyEvent(int32_t keyCode, bool down)
    282 {
    283     android::MessageStream* pStream = GetStream();
    284     if (pStream == NULL)
    285         return;
    286 
    287     int event = down ? android::Simulator::kCommandKeyDown :
    288                        android::Simulator::kCommandKeyUp;
    289 
    290     //printf("Sim: sending key-%s %d\n", down ? "down" : "up", keyCode);
    291 
    292     android::Message msg;
    293     msg.setCommand(event, keyCode);
    294     pStream->send(&msg);
    295 }
    296 
    297 /*
    298  * Send a "touch screen" event to the runtime.
    299  *
    300  * "mode" can be "down" (we're pressing), "up" (we're lifting our finger
    301  * off) or "drag".
    302  */
    303 void DeviceManager::SendTouchEvent(android::Simulator::TouchMode mode,
    304     int x, int y)
    305 {
    306     android::MessageStream* pStream = GetStream();
    307     if (pStream == NULL)
    308         return;
    309 
    310     //printf("Sim: sending touch-%d x=%d y=%d\n", (int) mode, x, y);
    311 
    312     android::Message msg;
    313     msg.setCommandExt(android::Simulator::kCommandTouch, mode, x, y);
    314     pStream->send(&msg);
    315 }
    316 
    317 /*
    318  * The runtime has sent us a new frame of stuff to display.
    319  *
    320  * NOTE: we're still in the runtime management thread.  We have to pass the
    321  * bitmap through AddPendingEvent to get it over to the main thread.
    322  *
    323  * We have to make a copy of the data from the runtime; the easiest
    324  * way to do that is to convert it to a bitmap here.  However, X11 gets
    325  * all worked up about calls being made from multiple threads, so we're
    326  * better off just copying it into a buffer.
    327  *
    328  * Because we're decoupled from the runtime, there is a chance that we
    329  * could drop frames.  Buffering them up is probably worse, since it
    330  * creates the possibility that we could stall and run out of memory.
    331  * We could save a copy by handing the runtime a pointer to our buffer,
    332  * but then we'd have to mutex the runtime against the simulator window
    333  * Paint function.
    334  */
    335 void DeviceManager::ShowFrame(int displayIndex)
    336 {
    337     assert(displayIndex >= 0 && displayIndex < mNumDisplays);
    338 
    339     // copy the data to local storage and convert
    340     mDisplay[displayIndex].CopyFromShared();
    341 
    342     // create a user event and send it to the window
    343     UserEvent uev(0, (void*) displayIndex);
    344 
    345     wxWindow* pEventWindow = mDisplay[displayIndex].GetWindow();
    346     if (pEventWindow != NULL) {
    347         //printf("runtime has image, passing up\n");
    348         pEventWindow->AddPendingEvent(uev);
    349     } else {
    350         fprintf(stderr, "NOTE: runtime has image, display not available\n");
    351     }
    352 }
    353 
    354 void DeviceManager::Vibrate(int vibrateOn)
    355 {
    356 	((MyApp*)wxTheApp)->Vibrate(vibrateOn);
    357 }
    358 
    359 /*
    360  * Get the display data from the specified display.
    361  */
    362 wxBitmap* DeviceManager::GetImageData(int displayIndex)
    363 {
    364     assert(displayIndex >= 0 && displayIndex < mNumDisplays);
    365     return mDisplay[displayIndex].GetImageData();
    366 }
    367 
    368 /*
    369  * Send an event to all device windows
    370  */
    371 void DeviceManager::BroadcastEvent(UserEvent& userEvent) {
    372     int numDisplays = GetNumDisplays();
    373     for (int i = 0; i < numDisplays; i++) {
    374         wxWindow* pEventWindow = mDisplay[i].GetWindow();
    375         if (pEventWindow != NULL) {
    376             pEventWindow->AddPendingEvent(userEvent);
    377         }
    378     }
    379 }
    380 
    381 
    382 /*
    383  * ===========================================================================
    384  *      DeviceManager::Display
    385  * ===========================================================================
    386  */
    387 
    388 /*
    389  * Fill out the various interesting fields based on the parameters.
    390  */
    391 bool DeviceManager::Display::Create(int displayNum, wxWindow* window,
    392     int width, int height, android::PixelFormat format, int refresh)
    393 {
    394     //printf("DeviceManager::Display constructor\n");
    395 
    396     assert(window != NULL);
    397     if (mImageData != NULL) {
    398         assert(false);              // no re-init
    399         return false;
    400     }
    401 
    402     mDisplayNum = displayNum;
    403     mDisplayWindow = window;
    404     mWidth = width;
    405     mHeight = height;
    406     mFormat = format;
    407     mRefresh = refresh;
    408 
    409     // use a fixed key for now
    410     mShmemKey = GenerateKey(displayNum);
    411     // allocate 24bpp for now
    412     mpShmem = new android::Shmem;
    413     if (!mpShmem->create(mShmemKey, width * height * 3, true))
    414         return false;
    415     //printf("--- CREATED shmem, key=0x%08x addr=%p\n",
    416     //    mShmemKey, mpShmem->getAddr());
    417 
    418     mImageData = new unsigned char[width * height * 3];
    419     if (mImageData == NULL)
    420         return false;
    421 
    422     return true;
    423 }
    424 
    425 /*
    426  * The UI components are starting to shut down.  We need to do away with
    427  * our wxWindow pointer so that the runtime management thread doesn't try
    428  * to send it display update events.
    429  *
    430  * We also need to let go of our side of the shared memory, because a
    431  * new DeviceManager may get started up before our destructor gets called,
    432  * and we may be re-using the key.
    433  */
    434 void DeviceManager::Display::Uncreate(void)
    435 {
    436     wxMutexLocker locker(mImageDataLock);
    437 
    438     //printf("--- Uncreate\n");
    439 
    440     mDisplayWindow = NULL;
    441 
    442     // the "locker" mutex keeps this from hosing CopyFromShared()
    443     if (mpShmem != NULL) {
    444         //printf("--- DELETING shmem, addr=%p\n", mpShmem->getAddr());
    445         delete mpShmem;
    446         mpShmem = NULL;
    447     }
    448 }
    449 
    450 /*
    451  * Make a local copy of the image data.  The UI grabs this data from a
    452  * different thread, so we have to mutex it.
    453  */
    454 void DeviceManager::Display::CopyFromShared(void)
    455 {
    456     wxMutexLocker locker(mImageDataLock);
    457 
    458     if (mpShmem == NULL) {
    459         //printf("Sim: SKIP CopyFromShared\n");
    460         return;
    461     }
    462 
    463     //printf("Display %d: copying data from %p to %p\n",
    464     //    mDisplayNum, mpShmem->getAddr(), mImageData);
    465 
    466     /* data is always 24bpp RGB */
    467     mpShmem->lock();        // avoid tearing
    468     memcpy(mImageData, mpShmem->getAddr(), mWidth * mHeight * 3);
    469     mpShmem->unlock();
    470 }
    471 
    472 /*
    473  * Get the image data in the form of a newly-allocated bitmap.
    474  *
    475  * This MUST be called from the UI thread.  Creating wxBitmaps in the
    476  * runtime management thread will cause X11 failures (e.g.
    477  * "Xlib: unexpected async reply").
    478  */
    479 wxBitmap* DeviceManager::Display::GetImageData(void)
    480 {
    481     wxMutexLocker locker(mImageDataLock);
    482 
    483     assert(mImageData != NULL);
    484 
    485     //printf("HEY: creating tmpImage, w=%d h=%d data=%p\n",
    486     //    mWidth, mHeight, mImageData);
    487 
    488     /* create a temporary wxImage; it does not own the data */
    489     wxImage tmpImage(mWidth, mHeight, (unsigned char*) mImageData, true);
    490 
    491     /* return a new bitmap with the converted-for-display data */
    492     return new wxBitmap(tmpImage);
    493 }
    494 
    495 
    496 /*
    497  * ===========================================================================
    498  *      DeviceManager::DeviceThread
    499  * ===========================================================================
    500  */
    501 
    502 /*
    503  * Some notes on process management under Linux/Mac OS X:
    504  *
    505  * We want to put the runtime into its own process group.  That way we
    506  * can send SIGKILL to the entire group to guarantee that we kill it and
    507  * all of its children.  Simply killing the sim's direct descendant doesn't
    508  * do what we want.  If it's a debugger, we will just orphan the runtime
    509  * without killing it.  Even if the runtime is our child, the children of
    510  * the runtime might outlive it.
    511  *
    512  * We want to be able to run the child under GDB or Valgrind, both
    513  * of which take input from the tty.  They need to be in the "foreground"
    514  * process group.  We might be debugging or valgrinding the simulator,
    515  * or operating in a command-line-only "headless" mode, so in that case
    516  * the sim front-end should actually be in the foreground group.
    517  *
    518  * Putting the runtime in the background group means it can't read input
    519  * from the tty (not an issue) and will generate SIGTTOU signals when it
    520  * writes output to the tty (easy to ignore).  The trick, then, is to
    521  * have the simulator and gdb/valgrind in the foreground pgrp while the
    522  * runtime itself is in a different group.  This group needs to be known
    523  * to the simulator so that it can send signals to the appropriate place.
    524  *
    525  * The solution is to have the runtime process change its process group
    526  * after it starts but before it creates any new processes, and then send
    527  * the process group ID back to the simulator.  The sim can then send
    528  * signals to the pgrp to ensure that we don't end up with zombies.  Any
    529  * "pre-launch" processes, like GDB, stay in the sim's pgrp.  This also
    530  * allows a consistent API for platforms that don't have fork/exec
    531  * (e.g. MinGW).
    532  *
    533  * This doesn't help us with interactive valgrind (e.g. --db-attach=yes),
    534  * because valgrind is an LD_PRELOAD shared library rather than a
    535  * separate process.  For that, we actually need to use termios(3) to
    536  * change the terminal's pgrp, or the interactive stuff just doesn't work.
    537  * We don't want to do that every time or attempting to debug the simulator
    538  * front-end will have difficulties.
    539  *
    540  * Making this even more entertaining is the fact that the simulator
    541  * front-end could itself be launched in the background.  It's essential
    542  * that we be careful about assigning a process group to the foreground,
    543  * and that we don't restore ourselves unless we were in the foreground to
    544  * begin with.
    545  *
    546  *
    547  * Some notes on process management under Windows (Cygwin, MinGW):
    548  *
    549  * Signals cannot be caught or ignored under MinGW.  All signals are fatal.
    550  *
    551  * Signals can be ignored under Cygwin, but not caught.
    552  *
    553  * Windows has some process group stuff (e.g. CREATE_NEW_PROCESS_GROUP flag
    554  * and GenerateConsoleCtrlEvent()).  Need to explore.
    555  *
    556  *
    557  * UPDATE: we've abandoned Mac OS and MinGW, so we now launch the runtime in
    558  * a separate xterm.  This avoids all tty work on our side.  We still need
    559  * to learn the pgrp from the child during the initial communication
    560  * handshake so we can do necessary cleanup.
    561  */
    562 
    563 
    564 /*
    565  * Convert a space-delimited string into an argument vector.
    566  *
    567  * "arg" is the current arg offset.
    568  */
    569 static int stringToArgv(char* mangle, const char** argv, int arg, int maxArgs)
    570 {
    571     bool first = true;
    572 
    573     while (*mangle != '\0') {
    574         assert(arg < maxArgs);
    575         if (first) {
    576             argv[arg++] = mangle;
    577             first = false;
    578         }
    579         if (*mangle == ' ') {
    580             *mangle = '\0';
    581             first = true;
    582         }
    583         mangle++;
    584     }
    585 
    586     return arg;
    587 }
    588 
    589 /*
    590  * Launch the runtime process in its own terminal window.  Start by setting
    591  * up the argument vector to the runtime process.
    592  *
    593  * The last entry in the vector will be a NULL pointer.
    594  *
    595  * This is awkward and annoying because the wxWidgets strings are current
    596  * configured for UNICODE.
    597  */
    598 /*static*/ bool DeviceManager::DeviceThread::LaunchProcess(wxWindow* statusWindow)
    599 {
    600     static const char* kLaunchWrapper = "launch-wrapper";
    601     const int kMaxArgs = 64;
    602     Preferences* pPrefs;
    603     wxString errMsg;
    604     wxString runtimeExe;
    605     wxString debuggerExe;
    606 	wxString debuggerScript;
    607     wxString valgrinderExe;
    608     wxString launchWrapperExe;
    609     wxString launchWrapperArgs;
    610     wxString javaAppName;
    611     wxString termCmd;
    612     wxString tmpStr;
    613     char gammaVal[8];
    614     //bool bval;
    615     double dval;
    616     bool result = false;
    617     bool doDebug, doValgrind, doCheckJni, doEnableSound, doEnableFakeCamera;
    618     const char** argv = NULL;
    619     int arg;
    620     wxCharBuffer runtimeExeTmp;
    621     wxCharBuffer debuggerExeTmp;
    622 	wxCharBuffer debuggerScriptTmp;
    623     wxCharBuffer javaAppNameTmp;
    624     wxCharBuffer valgrinderExeTmp;
    625     wxCharBuffer termCmdTmp;
    626     wxCharBuffer launchWrapperExeTmp;
    627     wxCharBuffer launchWrapperArgsTmp;
    628 
    629     pPrefs = ((MyApp*)wxTheApp)->GetPrefs();
    630     if (pPrefs == NULL) {
    631         errMsg = wxT("Preferences were not loaded.");
    632         goto bail;
    633     }
    634 
    635     /*
    636      * Set environment variables.  This stuff should be passed through as
    637      * arguments, but the runtime binary currently has a disconnect
    638      * between main() and the VM initilization.
    639      *
    640      * TODO: remove this in favor of system properties
    641      */
    642 #if 0
    643     // TODO: restore this
    644     doCheckJni = false;
    645     pPrefs->GetBool("check-jni", &doCheckJni);
    646 #endif
    647 
    648     tmpStr.Empty();
    649     pPrefs->GetString("ld-assume-kernel", /*ref*/ tmpStr);
    650     if (tmpStr.IsEmpty()) {
    651         unsetenv("LD_ASSUME_KERNEL");
    652     } else {
    653         setenv("LD_ASSUME_KERNEL", tmpStr.ToAscii(), 1);
    654     }
    655 
    656     doEnableSound = false;
    657     pPrefs->GetBool("enable-sound", &doEnableSound);
    658     if (doEnableSound)
    659         setenv("ANDROIDSOUND", "1", 1);
    660 
    661     doEnableFakeCamera = false;
    662     pPrefs->GetBool("enable-fake-camera", &doEnableFakeCamera);
    663     if (doEnableFakeCamera)
    664         setenv("ANDROIDFAKECAMERA", "1", 1);
    665 
    666     /*
    667      * Set the Dalvik bootstrap class path.  Normally this is set by "init".
    668      */
    669     setenv("BOOTCLASSPATH",
    670         "/system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar",
    671         1);
    672 
    673     /*
    674      * Figure out where the "runtime" binary lives.
    675      */
    676     runtimeExe = ((MyApp*)wxTheApp)->GetRuntimeExe();
    677     assert(!runtimeExe.IsEmpty());
    678 
    679     //UpdateLastModified();
    680 
    681     /*
    682      * Initialize argv.
    683      */
    684     argv = new const char*[kMaxArgs];
    685     if (argv == NULL)
    686         goto bail;
    687     arg = 0;
    688 
    689     /*
    690      * We want to launch the runtime in its own terminal window so we don't
    691      * have to fight over who gets access to the controlling tty.  We allow
    692      * the user to specify the command they want to use to perform the
    693      * launch.  Here we cut it into pieces for argv.
    694      *
    695      * To make life easier here, we require that the launch command be
    696      * all one piece, i.e. it's not "xterm -e <stuff> -geom blah" with our
    697      * stuff in the middle.
    698      */
    699     termCmd.Empty();
    700     pPrefs->GetString("launch-command", /*ref*/ termCmd);
    701     if (termCmd.IsEmpty()) {
    702         fprintf(stderr, "Sim: WARNING: launch-command is empty\n");
    703     } else {
    704         termCmdTmp = termCmd.ToAscii();
    705         char* mangle = strdup(termCmdTmp);
    706         arg = stringToArgv(mangle, argv, arg, kMaxArgs);
    707     }
    708 
    709     /*
    710      * The "launch-wrapper" binary lives in the same place as the runtime.
    711      * This sets up LD_PRELOAD and some other environment variables.
    712      */
    713     int charIdx;
    714 
    715     charIdx = runtimeExe.Find('/', true);
    716     if (charIdx == -1) {
    717         launchWrapperExe = wxString::FromAscii(kLaunchWrapper);
    718     } else {
    719         launchWrapperExe = runtimeExe.Mid(0, charIdx+1);
    720         launchWrapperExe.Append(wxString::FromAscii(kLaunchWrapper));
    721     }
    722     printf("Sim launch wrapper: %s\n", (const char*)launchWrapperExe.ToAscii());
    723 
    724     argv[arg++] = launchWrapperExeTmp = launchWrapperExe.ToAscii();
    725 
    726     launchWrapperArgs.Empty();
    727     pPrefs->GetString("launch-wrapper-args", /*ref*/ launchWrapperArgs);
    728     if (!launchWrapperArgs.IsEmpty()) {
    729         launchWrapperArgsTmp = launchWrapperArgs.ToAscii();
    730         char* mangle = strdup(launchWrapperArgsTmp);
    731         arg = stringToArgv(mangle, argv, arg, kMaxArgs);
    732     }
    733 
    734     /*
    735      * If we're launching under GDB or valgrind, set that up.
    736      */
    737     doDebug = doValgrind = false;
    738     pPrefs->GetBool("debug", &doDebug);
    739     if (((MyApp*)wxTheApp)->GetDebuggerOption()) {
    740         doDebug = true;
    741     }
    742 	debuggerScript = ((MyApp*)wxTheApp)->GetDebuggerScript();
    743 
    744     pPrefs->GetBool("valgrind", &doValgrind);
    745     if (doDebug || doValgrind) {
    746 
    747         pPrefs->GetString("debugger", /*ref*/ debuggerExe);
    748         pPrefs->GetString("valgrinder", /*ref*/ valgrinderExe);
    749 
    750         // check for empty or undefined preferences
    751         if (doDebug && debuggerExe.IsEmpty()) {
    752             errMsg = wxT("Debugger not defined.");
    753             goto bail;
    754         }
    755         if (doValgrind && valgrinderExe.IsEmpty()) {
    756             errMsg = wxT("Valgrinder not defined.");
    757             goto bail;
    758         }
    759 
    760         if (doValgrind) {
    761             argv[arg++] = valgrinderExeTmp = valgrinderExe.ToAscii();
    762             //argv[arg++] = "--tool=callgrind";
    763             argv[arg++] = "--tool=memcheck";
    764             argv[arg++] = "--leak-check=yes";       // check for leaks too
    765             argv[arg++] = "--leak-resolution=med";  // increase from 2 to 4
    766             argv[arg++] = "--num-callers=8";        // reduce from 12 to 8
    767             //argv[arg++] = "--show-reachable=yes";   // show still-reachable
    768             if (doDebug) {
    769                 //mTerminalFollowsChild = true;   // interactive
    770                 argv[arg++] = "--db-attach=yes";
    771             }
    772             //mSlowExit = true;
    773         } else /*doDebug*/ {
    774             argv[arg++] = debuggerExeTmp = debuggerExe.ToAscii();
    775 			if (!debuggerScript.IsEmpty()) {
    776 				argv[arg++] = "-x";
    777 				argv[arg++] = debuggerScriptTmp = debuggerScript.ToAscii();
    778 			}
    779             argv[arg++] = runtimeExeTmp = runtimeExe.ToAscii();
    780             argv[arg++] = "--args";
    781         }
    782     }
    783 
    784     /*
    785      * Get runtime args.
    786      */
    787 
    788     argv[arg++] = runtimeExeTmp = (const char*) runtimeExe.ToAscii();
    789 
    790     javaAppName = ((MyApp*)wxTheApp)->GetAutoRunApp();
    791     if (javaAppName.IsEmpty()) {
    792         if (!pPrefs->GetString("java-app-name", /*ref*/ javaAppName)) {
    793             javaAppName = wxT("");
    794         }
    795     }
    796 
    797     if (!javaAppName.IsEmpty())
    798     {
    799         argv[arg++] = "-j";
    800         argv[arg++] = javaAppNameTmp = (const char*) javaAppName.ToAscii();
    801     }
    802 
    803     if (pPrefs->GetDouble("gamma", &dval) && dval != 1.0) {
    804         snprintf(gammaVal, sizeof(gammaVal), "%.3f", dval);
    805         argv[arg++] = "-g";
    806         argv[arg++] = gammaVal;
    807     }
    808 
    809     /* finish arg set */
    810     argv[arg++] = NULL;
    811 
    812     assert(arg <= kMaxArgs);
    813 
    814 #if 1
    815     printf("ARGS:\n");
    816     for (int i = 0; i < arg; i++)
    817         printf(" %d: '%s'\n", i, argv[i]);
    818 #endif
    819 
    820     if (fork() == 0) {
    821         execvp(argv[0], (char* const*) argv);
    822         fprintf(stderr, "execvp '%s' failed: %s\n", argv[0], strerror(errno));
    823         exit(1);
    824     }
    825 
    826     /*
    827      * We assume success; if it didn't succeed we'll just sort of hang
    828      * out waiting for a connection.  There are ways to fix this (create
    829      * a non-close-on-exec pipe and watch to see if the other side closes),
    830      * but at this stage it's not worthwhile.
    831      */
    832     result = true;
    833 
    834     tmpStr = wxT("=== launched ");
    835     tmpStr += runtimeExe;
    836     LogWindow::PostLogMsg(tmpStr);
    837 
    838     assert(errMsg.IsEmpty());
    839 
    840 bail:
    841     if (!errMsg.IsEmpty()) {
    842         assert(result == false);
    843 
    844         UserEventMessage* pUem = new UserEventMessage;
    845         pUem->CreateErrorMessage(errMsg);
    846 
    847         UserEvent uev(0, (void*) pUem);
    848 
    849         assert(statusWindow != NULL);
    850         statusWindow->AddPendingEvent(uev);
    851     }
    852     delete[] argv;
    853     return result;
    854 }
    855 
    856 /*
    857  * This is the entry point for the device thread.  The thread launches the
    858  * runtime process and monitors it.  When the runtime exits, the thread
    859  * exits.
    860  *
    861  * Because this isn't running in the UI thread, any user interaction has
    862  * to be channeled through "user events" to the appropriate window.
    863  */
    864 void* DeviceManager::DeviceThread::Entry(void)
    865 {
    866     //android::MessageStream stream;
    867     android::Message msg;
    868     wxString errMsg;
    869     char statusBuf[64] = "(no status)";
    870     int result = 1;
    871 
    872     /* print this so we can make sense of log messages */
    873     LOG(LOG_DEBUG, "", "Sim: device management thread starting (pid=%d)\n",
    874         getpid());
    875 
    876     assert(mReader != NULL && mWriter != NULL);
    877 
    878     /*
    879      * Tell the main thread that we're running.  If something fails here,
    880      * we'll send them a "stopped running" immediately afterward.
    881      */
    882     {
    883         UserEventMessage* pUem = new UserEventMessage;
    884         pUem->CreateRuntimeStarted();
    885 
    886         UserEvent uev(0, (void*) pUem);
    887 
    888         assert(mpStatusWindow != NULL);
    889         mpStatusWindow->AddPendingEvent(uev);
    890     }
    891     LogWindow::PostLogMsg(
    892             "==============================================================");
    893     LogWindow::PostLogMsg("=== runtime starting");
    894 
    895     /*
    896      * Establish contact with runtime.
    897      */
    898     if (!mStream.init(mReader, mWriter, true)) {
    899         errMsg = wxT("ERROR: Unable to establish communication with runtime.\n");
    900         goto bail;
    901     }
    902 
    903     /*
    904      * Tell the runtime to put itself into a new process group and set
    905      * itself up as the foreground process.  The latter is only really
    906      * necessary to make valgrind+gdb work.
    907      */
    908     msg.setCommand(android::Simulator::kCommandNewPGroup, true);
    909     mStream.send(&msg);
    910 
    911     printf("Sim: Sending hardware configuration\n");
    912 
    913     /*
    914      * Send display config.
    915      *
    916      * Right now we're just shipping a big binary blob over.
    917      */
    918     assert(android::Simulator::kValuesPerDisplay >= 5);
    919     int buf[1 + 1 + mpDeviceManager->GetNumDisplays() *
    920                     android::Simulator::kValuesPerDisplay];
    921     buf[0] = android::Simulator::kDisplayConfigMagic;
    922     buf[1] = mpDeviceManager->GetNumDisplays();
    923     for (int i = 0; i < mpDeviceManager->GetNumDisplays(); i++) {
    924         DeviceManager::Display* pDisplay = mpDeviceManager->GetDisplay(i);
    925         int* pBuf = &buf[2 + android::Simulator::kValuesPerDisplay * i];
    926 
    927         pBuf[0] = pDisplay->GetWidth();
    928         pBuf[1] = pDisplay->GetHeight();
    929         pBuf[2] = pDisplay->GetFormat();
    930         pBuf[3] = pDisplay->GetRefresh();
    931         pBuf[4] = pDisplay->GetShmemKey();
    932     }
    933     msg.setRaw((const unsigned char*)buf, sizeof(buf),
    934         android::Message::kCleanupNoDelete);
    935     mStream.send(&msg);
    936 
    937     /*
    938      * Send other hardware config.
    939      *
    940      * Examples:
    941      * - Available input devices.
    942      * - Set of buttons on device.
    943      * - External devices (Bluetooth, etc).
    944      * - Initial mode (e.g. "flipped open" vs. "flipped closed").
    945      */
    946 
    947     msg.setConfig("keycharmap", mpDeviceManager->GetKeyMap());
    948     mStream.send(&msg);
    949 
    950     /*
    951      * Done with config.
    952      */
    953     msg.setCommand(android::Simulator::kCommandConfigDone, 0);
    954     mStream.send(&msg);
    955 
    956     /*
    957      * Sit forever, waiting for messages from the runtime process.
    958      */
    959     while (1) {
    960         if (!mStream.recv(&msg, true)) {
    961             /*
    962              * The read failed.  This usually means the child has died.
    963              */
    964             printf("Sim: runtime process has probably died\n");
    965             break;
    966         }
    967 
    968         if (msg.getType() == android::Message::kTypeCommand) {
    969             int cmd, arg;
    970 
    971             if (!msg.getCommand(&cmd, &arg)) {
    972                 fprintf(stderr, "Sim: Warning: failed unpacking command\n");
    973                 /* keep going? */
    974             } else {
    975                 switch (cmd) {
    976                 case android::Simulator::kCommandNewPGroupCreated:
    977                     // runtime has moved into a separate process group
    978                     // (not expected for external)
    979                     printf("Sim: child says it's now in pgrp %d\n", arg);
    980                     mRuntimeProcessGroup = arg;
    981                     break;
    982                 case android::Simulator::kCommandRuntimeReady:
    983                     // sim is up and running, do late init
    984                     break;
    985                 case android::Simulator::kCommandUpdateDisplay:
    986                     // new frame of graphics is ready
    987                     //printf("RCVD display update %d\n", arg);
    988                     mpDeviceManager->ShowFrame(arg);
    989                     break;
    990                 case android::Simulator::kCommandVibrate:
    991                     // vibrator on or off
    992                     //printf("RCVD vibrator update %d\n", arg);
    993                     mpDeviceManager->Vibrate(arg);
    994                     break;
    995                 default:
    996                     printf("Sim: got unknown command %d/%d\n", cmd, arg);
    997                     break;
    998                 }
    999             }
   1000         } else if (msg.getType() == android::Message::kTypeLogBundle) {
   1001             android_LogBundle bundle;
   1002 
   1003             if (!msg.getLogBundle(&bundle)) {
   1004                 fprintf(stderr, "Sim: Warning: failed unpacking logBundle\n");
   1005                 /* keep going? */
   1006             } else {
   1007                 LogWindow::PostLogMsg(&bundle);
   1008             }
   1009         } else {
   1010             printf("Sim: got unknown message type=%d\n", msg.getType());
   1011         }
   1012     }
   1013 
   1014     result = 0;
   1015 
   1016 bail:
   1017     printf("Sim: DeviceManager thread preparing to exit\n");
   1018 
   1019     /* kill the comm channel; should encourage runtime to die */
   1020     mStream.close();
   1021     delete mReader;
   1022     delete mWriter;
   1023     mReader = mWriter = NULL;
   1024 
   1025     /*
   1026      * We never really did get a "friendly death" working, so just slam
   1027      * the thing if we have the process group.
   1028      */
   1029     if (mRuntimeProcessGroup != 0) {
   1030         /* kill the group, not our immediate child */
   1031         printf("Sim: killing pgrp %d\n", (int) mRuntimeProcessGroup);
   1032         kill(-mRuntimeProcessGroup, 9);
   1033     }
   1034 
   1035     if (!errMsg.IsEmpty()) {
   1036         UserEventMessage* pUem = new UserEventMessage;
   1037         pUem->CreateErrorMessage(errMsg);
   1038 
   1039         UserEvent uev(0, (void*) pUem);
   1040         mpStatusWindow->AddPendingEvent(uev);
   1041     }
   1042 
   1043     /* notify the main window that the runtime has stopped */
   1044     {
   1045         UserEventMessage* pUem = new UserEventMessage;
   1046         pUem->CreateRuntimeStopped();
   1047 
   1048         UserEvent uev(0, (void*) pUem);
   1049         mpStatusWindow->AddPendingEvent(uev);
   1050     }
   1051 
   1052     /* show exit status in log file */
   1053     wxString exitMsg;
   1054     exitMsg.Printf(wxT("=== runtime exiting - %s"), statusBuf);
   1055     LogWindow::PostLogMsg(exitMsg);
   1056     LogWindow::PostLogMsg(
   1057         "==============================================================\n");
   1058 
   1059     /*
   1060      * Reset system properties for future runs.
   1061      */
   1062     ResetProperties();
   1063 
   1064     return (void*) result;
   1065 }
   1066 
   1067 
   1068 /*
   1069  * Wait for a little bit to see if the thread will exit.
   1070  *
   1071  * "delay" is in 0.1s increments.
   1072  */
   1073 void DeviceManager::DeviceThread::WaitForDeath(int delay)
   1074 {
   1075     const int kDelayUnit = 100000;
   1076     int i;
   1077 
   1078     for (i = 0; i < delay; i++) {
   1079         if (!IsRunning())
   1080             return;
   1081         usleep(kDelayUnit);
   1082     }
   1083 }
   1084 
   1085 
   1086 /*
   1087  * Kill the runtime process.  The goal is to cause our local runtime
   1088  * management thread to exit.  If it doesn't, this will kill the thread
   1089  * before it returns.
   1090  */
   1091 void DeviceManager::DeviceThread::KillChildProcesses(void)
   1092 {
   1093     if (!this->IsRunning())
   1094         return;
   1095 
   1096     /* clear "slow exit" flag -- we're forcefully killing this thing */
   1097     //this->mSlowExit = false;
   1098 
   1099     /*
   1100      * Use the ChildProcess object in the thread to send signals.  There's
   1101      * a risk that the DeviceThread will exit and destroy the object while
   1102      * we're using it.  Using a mutex here gets a little awkward because
   1103      * we can't put it in DeviceThread.  It's easier to make a copy of
   1104      * ChildProcess and operate on the copy, but we have to do that very
   1105      * carefully to avoid interfering with the communcation pipes.
   1106      *
   1107      * For now, we just hope for the best.  FIX this someday.
   1108      *
   1109      * We broadcast to the process group, which will ordinarily kill
   1110      * everything.  If we're running with valgrind+GDB everything is in our
   1111      * pgrp and we can't do the broadcast; if GDB alone, then only GDB is
   1112      * in our pgrp, so the broadcast will hit everything except it.  We
   1113      * hit the group and then hit our child for good measure.
   1114      */
   1115     if (mRuntimeProcessGroup != 0) {
   1116         /* kill the group, not our immediate child */
   1117         printf("Sim: killing pgrp %d\n", (int) mRuntimeProcessGroup);
   1118         kill(-mRuntimeProcessGroup, 9);
   1119         WaitForDeath(15);
   1120     }
   1121 
   1122     /*
   1123      * Close the communication channel.  This should cause our thread
   1124      * to snap out of its blocking read and the runtime thread to bail
   1125      * out the next time it tries to interact with us.  We should only
   1126      * get here if somebody other than our direct descendant has the
   1127      * comm channel open and our broadcast didn't work, which should
   1128      * no longer be possible.
   1129      */
   1130     if (this->IsRunning()) {
   1131         printf("Sim: killing comm channel\n");
   1132         mStream.close();
   1133         delete mReader;
   1134         delete mWriter;
   1135         mReader = mWriter = NULL;
   1136         WaitForDeath(15);
   1137     }
   1138 
   1139     /*
   1140      * At this point it's possible that our DeviceThread is just wedged.
   1141      * Kill it.
   1142      *
   1143      * Using the thread Kill() function can orphan resources, including
   1144      * locks and semaphores.  There is some risk that the simulator will
   1145      * be hosed after this.
   1146      */
   1147     if (this->IsRunning()) {
   1148         fprintf(stderr, "Sim: WARNING: killing runtime thread (%ld)\n",
   1149             (long) GetId());
   1150         this->Kill();
   1151         WaitForDeath(15);
   1152     }
   1153 
   1154     /*
   1155      * Now I'm scared.
   1156      */
   1157     if (this->IsRunning()) {
   1158         fprintf(stderr, "Sim: thread won't die!\n");
   1159     }
   1160 }
   1161 
   1162 
   1163 /*
   1164  * Configure system properties for the simulated device.
   1165  *
   1166  * Property requests can arrive *before* the full connection to the
   1167  * simulator is established, so we want to reset these during cleanup.
   1168  */
   1169 void DeviceManager::DeviceThread::ResetProperties(void)
   1170 {
   1171 	wxWindow* mainFrame = ((MyApp*)wxTheApp)->GetMainFrame();
   1172     PropertyServer* props = ((MainFrame*)mainFrame)->GetPropertyServer();
   1173 
   1174     props->ClearProperties();
   1175     props->SetDefaultProperties();
   1176 }
   1177 
   1178 
   1179 #if 0
   1180 /*
   1181  * Return true if the executable found is newer than
   1182  * what is currently running
   1183  */
   1184 bool DeviceManager::DeviceThread::IsRuntimeNew(void)
   1185 {
   1186     if (mLastModified == 0) {
   1187         /*
   1188          * Haven't called UpdateLastModified yet, or called it but
   1189          * couldn't stat() the executable.
   1190          */
   1191         return false;
   1192     }
   1193 
   1194     struct stat status;
   1195     if (stat(mRuntimeExe.ToAscii(), &status) == 0) {
   1196         return (status.st_mtime > mLastModified);
   1197     } else {
   1198         // doesn't exist, so it can't be newer
   1199         fprintf(stderr, "Sim: unable to stat '%s': %s\n",
   1200             (const char*) mRuntimeExe.ToAscii(), strerror(errno));
   1201         return false;
   1202     }
   1203 }
   1204 
   1205 /*
   1206  * Updates mLastModified to reflect the current executables mtime
   1207  */
   1208 void DeviceManager::DeviceThread::UpdateLastModified(void)
   1209 {
   1210     struct stat status;
   1211     if (stat(mRuntimeExe.ToAscii(), &status) == 0) {
   1212         mLastModified = status.st_mtime;
   1213     } else {
   1214         fprintf(stderr, "Sim: unable to stat '%s': %s\n",
   1215             (const char*) mRuntimeExe.ToAscii(), strerror(errno));
   1216         mLastModified = 0;
   1217     }
   1218 }
   1219 #endif
   1220 
   1221