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