OSDN Git Service

Merge "Update samples to use new getMotionRanges() API." into honeycomb-mr1
[android-x86/development.git] / simulator / app / DeviceManager.cpp
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