1 /* Copyright (C) 2006-2008 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 13 #include <signal.h> 14 #include <unistd.h> 15 #include <string.h> 16 #include <sys/time.h> 17 #ifdef _WIN32 18 #include <process.h> 19 #endif 20 #include "libslirp.h" 21 #include "sockets.h" 22 23 #include "android/android.h" 24 #include "qemu-common.h" 25 #include "sysemu.h" 26 #include "console.h" 27 28 #include <SDL.h> 29 #include <SDL_syswm.h> 30 31 #include "math.h" 32 33 #include "android/charmap.h" 34 #include "modem_driver.h" 35 #include "shaper.h" 36 #include "proxy_http.h" 37 38 #include "android/utils/debug.h" 39 #include "android/resource.h" 40 #include "android/config.h" 41 #include "android/config/config.h" 42 43 #include "android/skin/image.h" 44 #include "android/skin/trackball.h" 45 #include "android/skin/keyboard.h" 46 #include "android/skin/file.h" 47 #include "android/skin/window.h" 48 #include "android/skin/keyset.h" 49 50 #include "android/gps.h" 51 #include "android/hw-qemud.h" 52 #include "android/hw-kmsg.h" 53 #include "android/hw-lcd.h" 54 #include "android/hw-control.h" 55 #include "android/hw-sensors.h" 56 #include "android/boot-properties.h" 57 #include "android/user-config.h" 58 #include "android/utils/bufprint.h" 59 #include "android/utils/dirscanner.h" 60 #include "android/utils/path.h" 61 #include "android/utils/timezone.h" 62 63 #include "android/cmdline-option.h" 64 #include "android/help.h" 65 #include "hw/goldfish_nand.h" 66 #ifdef CONFIG_MEMCHECK 67 #include "memcheck/memcheck.h" 68 #endif // CONFIG_MEMCHECK 69 70 #include "android/globals.h" 71 #include "tcpdump.h" 72 73 /* in vl.c */ 74 extern void qemu_help(int code); 75 76 #include "framebuffer.h" 77 AndroidRotation android_framebuffer_rotation; 78 79 #define STRINGIFY(x) _STRINGIFY(x) 80 #define _STRINGIFY(x) #x 81 82 #ifdef ANDROID_SDK_TOOLS_REVISION 83 # define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0" 84 #else 85 # define VERSION_STRING "standalone" 86 #endif 87 88 #define KEYSET_FILE "default.keyset" 89 SkinKeyset* android_keyset; 90 91 #define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0) 92 93 extern int control_console_start( int port ); /* in control.c */ 94 95 extern int qemu_milli_needed; 96 97 /* the default device DPI if none is specified by the skin 98 */ 99 #define DEFAULT_DEVICE_DPI 165 100 101 int android_base_port; 102 103 #if 0 104 static int opts->flashkeys; /* forward */ 105 #endif 106 107 static void handle_key_command( void* opaque, SkinKeyCommand command, int param ); 108 109 #ifdef CONFIG_TRACE 110 extern void start_tracing(void); 111 extern void stop_tracing(void); 112 #endif 113 114 unsigned long android_verbose; 115 116 int qemu_cpu_delay = 0; 117 int qemu_cpu_delay_count; 118 119 /***********************************************************************/ 120 /***********************************************************************/ 121 /***** *****/ 122 /***** U T I L I T Y R O U T I N E S *****/ 123 /***** *****/ 124 /***********************************************************************/ 125 /***********************************************************************/ 126 127 /*** APPLICATION DIRECTORY 128 *** Where are we ? 129 ***/ 130 131 const char* get_app_dir(void) 132 { 133 char buffer[1024]; 134 char* p = buffer; 135 char* end = p + sizeof(buffer); 136 p = bufprint_app_dir(p, end); 137 if (p >= end) 138 return NULL; 139 140 return strdup(buffer); 141 } 142 143 /*** CONFIGURATION 144 ***/ 145 146 static AUserConfig* userConfig; 147 148 void 149 emulator_config_init( void ) 150 { 151 userConfig = auserConfig_new( android_avdInfo ); 152 } 153 154 /* only call this function on normal exits, so that ^C doesn't save the configuration */ 155 void 156 emulator_config_done( void ) 157 { 158 int win_x, win_y; 159 160 if (!userConfig) { 161 D("no user configuration?"); 162 return; 163 } 164 165 SDL_WM_GetPos( &win_x, &win_y ); 166 auserConfig_setWindowPos(userConfig, win_x, win_y); 167 auserConfig_save(userConfig); 168 } 169 170 void *loadpng(const char *fn, unsigned *_width, unsigned *_height); 171 void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height); 172 173 #ifdef CONFIG_DARWIN 174 # define ANDROID_ICON_PNG "android_icon_256.png" 175 #else 176 # define ANDROID_ICON_PNG "android_icon_16.png" 177 #endif 178 179 static void 180 sdl_set_window_icon( void ) 181 { 182 static int window_icon_set; 183 184 if (!window_icon_set) 185 { 186 #ifdef _WIN32 187 HANDLE handle = GetModuleHandle( NULL ); 188 HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) ); 189 SDL_SysWMinfo wminfo; 190 191 SDL_GetWMInfo(&wminfo); 192 193 SetClassLong( wminfo.window, GCL_HICON, (LONG)icon ); 194 #else /* !_WIN32 */ 195 unsigned icon_w, icon_h; 196 size_t icon_bytes; 197 const unsigned char* icon_data; 198 void* icon_pixels; 199 200 window_icon_set = 1; 201 202 icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes ); 203 if ( !icon_data ) 204 return; 205 206 icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h ); 207 if ( !icon_pixels ) 208 return; 209 210 /* the data is loaded into memory as RGBA bytes by libpng. we want to manage 211 * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending 212 * on our CPU endianess 213 */ 214 { 215 unsigned* d = icon_pixels; 216 unsigned* d_end = d + icon_w*icon_h; 217 218 for ( ; d < d_end; d++ ) { 219 unsigned pix = d[0]; 220 #if WORDS_BIGENDIAN 221 /* R,G,B,A read as RGBA => ARGB */ 222 pix = ((pix >> 8) & 0xffffff) | (pix << 24); 223 #else 224 /* R,G,B,A read as ABGR => ARGB */ 225 pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16); 226 #endif 227 d[0] = pix; 228 } 229 } 230 231 SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h ); 232 if (icon != NULL) { 233 SDL_WM_SetIcon(icon, NULL); 234 SDL_FreeSurface(icon); 235 free( icon_pixels ); 236 } 237 #endif /* !_WIN32 */ 238 } 239 } 240 241 /* see http://en.wikipedia.org/wiki/List_of_device_bandwidths or a complete list */ 242 const NetworkSpeed android_netspeeds[] = { 243 { "gsm", "GSM/CSD", 14400, 14400 }, 244 { "hscsd", "HSCSD", 14400, 43200 }, 245 { "gprs", "GPRS", 40000, 80000 }, 246 { "edge", "EDGE/EGPRS", 118400, 236800 }, 247 { "umts", "UMTS/3G", 128000, 1920000 }, 248 { "hsdpa", "HSDPA", 348000, 14400000 }, 249 { "full", "no limit", 0, 0 }, 250 { NULL, NULL, 0, 0 } 251 }; 252 253 const NetworkLatency android_netdelays[] = { 254 /* FIXME: these numbers are totally imaginary */ 255 { "gprs", "GPRS", 150, 550 }, 256 { "edge", "EDGE/EGPRS", 80, 400 }, 257 { "umts", "UMTS/3G", 35, 200 }, 258 { "none", "no latency", 0, 0 }, 259 { NULL, NULL, 0, 0 } 260 }; 261 262 263 264 265 #define ONE_MB (1024*1024) 266 267 unsigned convertBytesToMB( uint64_t size ) 268 { 269 if (size == 0) 270 return 0; 271 272 size = (size + ONE_MB-1) >> 20; 273 if (size > UINT_MAX) 274 size = UINT_MAX; 275 276 return (unsigned) size; 277 } 278 279 uint64_t convertMBToBytes( unsigned megaBytes ) 280 { 281 return ((uint64_t)megaBytes << 20); 282 } 283 284 /***********************************************************************/ 285 /***********************************************************************/ 286 /***** *****/ 287 /***** S K I N I M A G E S *****/ 288 /***** *****/ 289 /***********************************************************************/ 290 /***********************************************************************/ 291 292 void send_key_event(unsigned code, unsigned down) 293 { 294 if(code == 0) { 295 return; 296 } 297 if (VERBOSE_CHECK(keys)) 298 printf(">> KEY [0x%03x,%s]\n", (code & 0x1ff), down ? "down" : " up " ); 299 kbd_put_keycode((code & 0x1ff) | (down ? 0x200 : 0)); 300 } 301 302 303 304 typedef struct { 305 AConfig* aconfig; 306 SkinFile* layout_file; 307 SkinLayout* layout; 308 SkinKeyboard* keyboard; 309 SkinWindow* window; 310 int win_x; 311 int win_y; 312 int show_trackball; 313 SkinTrackBall* trackball; 314 int lcd_brightness; 315 SkinImage* onion; 316 SkinRotation onion_rotation; 317 int onion_alpha; 318 319 AndroidOptions opts[1]; /* copy of options */ 320 } QEmulator; 321 322 static QEmulator qemulator[1]; 323 324 static void 325 qemulator_done( QEmulator* emulator ) 326 { 327 if (emulator->window) { 328 skin_window_free(emulator->window); 329 emulator->window = NULL; 330 } 331 if (emulator->trackball) { 332 skin_trackball_destroy(emulator->trackball); 333 emulator->trackball = NULL; 334 } 335 if (emulator->keyboard) { 336 skin_keyboard_free(emulator->keyboard); 337 emulator->keyboard = NULL; 338 } 339 emulator->layout = NULL; 340 if (emulator->layout_file) { 341 skin_file_free(emulator->layout_file); 342 emulator->layout_file = NULL; 343 } 344 } 345 346 347 static void 348 qemulator_setup( QEmulator* emulator ); 349 350 static void 351 qemulator_fb_update( void* _emulator, int x, int y, int w, int h ) 352 { 353 QEmulator* emulator = _emulator; 354 355 if (emulator->window) 356 skin_window_update_display( emulator->window, x, y, w, h ); 357 } 358 359 static void 360 qemulator_fb_rotate( void* _emulator, int rotation ) 361 { 362 QEmulator* emulator = _emulator; 363 364 qemulator_setup( emulator ); 365 } 366 367 368 369 static int 370 qemulator_init( QEmulator* emulator, 371 AConfig* aconfig, 372 const char* basepath, 373 int x, 374 int y, 375 AndroidOptions* opts ) 376 { 377 emulator->aconfig = aconfig; 378 emulator->layout_file = skin_file_create_from_aconfig(aconfig, basepath); 379 emulator->layout = emulator->layout_file->layouts; 380 // If we have a custom charmap use it to initialize keyboard. 381 // Otherwise initialize keyboard from configuration settings. 382 // Another way to configure keyboard to use a custom charmap would 383 // be saving a custom charmap name into AConfig's keyboard->charmap 384 // property, and calling single skin_keyboard_create_from_aconfig 385 // routine to initialize keyboard. 386 if (NULL != opts->charmap) { 387 emulator->keyboard = skin_keyboard_create_from_kcm(opts->charmap, opts->raw_keys); 388 } else { 389 emulator->keyboard = skin_keyboard_create_from_aconfig(aconfig, opts->raw_keys); 390 } 391 emulator->window = NULL; 392 emulator->win_x = x; 393 emulator->win_y = y; 394 emulator->opts[0] = opts[0]; 395 396 /* register as a framebuffer clients for all displays defined in the skin file */ 397 SKIN_FILE_LOOP_PARTS( emulator->layout_file, part ) 398 SkinDisplay* disp = part->display; 399 if (disp->valid) { 400 qframebuffer_add_client( disp->qfbuff, 401 emulator, 402 qemulator_fb_update, 403 qemulator_fb_rotate, 404 NULL ); 405 } 406 SKIN_FILE_LOOP_END_PARTS 407 return 0; 408 } 409 410 411 static AndroidKeyCode 412 qemulator_rotate_keycode( QEmulator* emulator, 413 AndroidKeyCode sym ) 414 { 415 return android_keycode_rotate( sym, 416 skin_layout_get_dpad_rotation(emulator->layout) ); 417 } 418 419 static int 420 get_device_dpi( AndroidOptions* opts ) 421 { 422 int dpi_device = android_hw->hw_lcd_density; 423 424 if (opts->dpi_device != NULL) { 425 char* end; 426 dpi_device = strtol( opts->dpi_device, &end, 0 ); 427 if (end == NULL || *end != 0 || dpi_device <= 0) { 428 fprintf(stderr, "argument for -dpi-device must be a positive integer. Aborting\n" ); 429 exit(1); 430 } 431 } 432 return dpi_device; 433 } 434 435 static double 436 get_default_scale( AndroidOptions* opts ) 437 { 438 int dpi_device = get_device_dpi( opts ); 439 int dpi_monitor = -1; 440 double scale = 0.0; 441 442 /* possible values for the 'scale' option are 443 * 'auto' : try to determine the scale automatically 444 * '<number>dpi' : indicates the host monitor dpi, compute scale accordingly 445 * '<fraction>' : use direct scale coefficient 446 */ 447 448 if (opts->scale) { 449 if (!strcmp(opts->scale, "auto")) 450 { 451 /* we need to get the host dpi resolution ? */ 452 int xdpi, ydpi; 453 454 if ( SDL_WM_GetMonitorDPI( &xdpi, &ydpi ) < 0 ) { 455 fprintf(stderr, "could not get monitor DPI resolution from system. please use -dpi-monitor to specify one\n" ); 456 exit(1); 457 } 458 D( "system reported monitor resolutions: xdpi=%d ydpi=%d\n", xdpi, ydpi); 459 dpi_monitor = (xdpi + ydpi+1)/2; 460 } 461 else 462 { 463 char* end; 464 scale = strtod( opts->scale, &end ); 465 466 if (end && end[0] == 'd' && end[1] == 'p' && end[2] == 'i' && end[3] == 0) { 467 if ( scale < 20 || scale > 1000 ) { 468 fprintf(stderr, "emulator: ignoring bad -scale argument '%s': %s\n", opts->scale, 469 "host dpi number must be between 20 and 1000" ); 470 exit(1); 471 } 472 dpi_monitor = scale; 473 scale = 0.0; 474 } 475 else if (end == NULL || *end != 0) { 476 fprintf(stderr, "emulator: ignoring bad -scale argument '%s': %s\n", opts->scale, 477 "not a number or the 'auto' keyword" ); 478 exit(1); 479 } 480 else if ( scale < 0.1 || scale > 3. ) { 481 fprintf(stderr, "emulator: ignoring bad -window-scale argument '%s': %s\n", opts->scale, 482 "must be between 0.1 and 3.0" ); 483 exit(1); 484 } 485 } 486 } 487 488 if (scale == 0.0 && dpi_monitor > 0) 489 scale = dpi_monitor*1.0/dpi_device; 490 491 if (scale == 0.0) 492 scale = 1.0; 493 494 return scale; 495 } 496 497 void 498 android_emulator_set_window_scale( double scale, int is_dpi ) 499 { 500 QEmulator* emulator = qemulator; 501 502 if (is_dpi) 503 scale /= get_device_dpi( emulator->opts ); 504 505 if (emulator->window) 506 skin_window_set_scale( emulator->window, scale ); 507 } 508 509 510 static void 511 qemulator_set_title( QEmulator* emulator ) 512 { 513 char temp[128], *p=temp, *end=p+sizeof temp;; 514 515 if (emulator->window == NULL) 516 return; 517 518 if (emulator->show_trackball) { 519 SkinKeyBinding bindings[ SKIN_KEY_COMMAND_MAX_BINDINGS ]; 520 int count; 521 522 count = skin_keyset_get_bindings( android_keyset, 523 SKIN_KEY_COMMAND_TOGGLE_TRACKBALL, 524 bindings ); 525 526 if (count > 0) { 527 int nn; 528 p = bufprint( p, end, "Press " ); 529 for (nn = 0; nn < count; nn++) { 530 if (nn > 0) { 531 if (nn < count-1) 532 p = bufprint(p, end, ", "); 533 else 534 p = bufprint(p, end, " or "); 535 } 536 p = bufprint(p, end, "%s", 537 skin_key_symmod_to_str( bindings[nn].sym, 538 bindings[nn].mod ) ); 539 } 540 p = bufprint(p, end, " to leave trackball mode. "); 541 } 542 } 543 544 p = bufprint(p, end, "%d:%s", 545 android_base_port, 546 avdInfo_getName( android_avdInfo )); 547 548 skin_window_set_title( emulator->window, temp ); 549 } 550 551 /* called by the emulated framebuffer device each time the content of the 552 * framebuffer has changed. the rectangle is the bounding box of all changes 553 */ 554 static void 555 sdl_update(DisplayState *ds, int x, int y, int w, int h) 556 { 557 /* this function is being called from the console code that is currently inactive 558 ** simple totally ignore it... 559 */ 560 (void)ds; 561 (void)x; 562 (void)y; 563 (void)w; 564 (void)h; 565 } 566 567 568 569 static void 570 qemulator_light_brightness( void* opaque, const char* light, int value ) 571 { 572 QEmulator* emulator = opaque; 573 574 VERBOSE_PRINT(hw_control,"%s: light='%s' value=%d window=%p", __FUNCTION__, light, value, emulator->window); 575 if ( !strcmp(light, "lcd_backlight") ) { 576 emulator->lcd_brightness = value; 577 if (emulator->window) 578 skin_window_set_lcd_brightness( emulator->window, value ); 579 return; 580 } 581 } 582 583 584 static void 585 qemulator_setup( QEmulator* emulator ) 586 { 587 AndroidOptions* opts = emulator->opts; 588 589 if ( !emulator->window && !opts->no_window ) { 590 SkinLayout* layout = emulator->layout; 591 double scale = get_default_scale(emulator->opts); 592 593 emulator->window = skin_window_create( layout, emulator->win_x, emulator->win_y, scale, 0); 594 if (emulator->window == NULL) 595 return; 596 597 { 598 SkinTrackBall* ball; 599 SkinTrackBallParameters params; 600 601 params.diameter = 30; 602 params.ring = 2; 603 params.ball_color = 0xffe0e0e0; 604 params.dot_color = 0xff202020; 605 params.ring_color = 0xff000000; 606 607 ball = skin_trackball_create( ¶ms ); 608 emulator->trackball = ball; 609 skin_window_set_trackball( emulator->window, ball ); 610 611 emulator->lcd_brightness = 128; /* 50% */ 612 skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness ); 613 } 614 615 if ( emulator->onion != NULL ) 616 skin_window_set_onion( emulator->window, 617 emulator->onion, 618 emulator->onion_rotation, 619 emulator->onion_alpha ); 620 621 qemulator_set_title( emulator ); 622 623 skin_window_enable_touch ( emulator->window, android_hw->hw_touchScreen != 0 ); 624 skin_window_enable_dpad ( emulator->window, android_hw->hw_dPad != 0 ); 625 skin_window_enable_qwerty( emulator->window, android_hw->hw_keyboard != 0 ); 626 skin_window_enable_trackball( emulator->window, android_hw->hw_trackBall != 0 ); 627 } 628 629 /* initialize hardware control support */ 630 { 631 AndroidHwControlFuncs funcs; 632 633 funcs.light_brightness = qemulator_light_brightness; 634 android_hw_control_init( emulator, &funcs ); 635 } 636 } 637 638 639 /* called by the emulated framebuffer device each time the framebuffer 640 * is resized or rotated */ 641 static void 642 sdl_resize(DisplayState *ds) 643 { 644 //fprintf(stderr, "weird, sdl_resize being called with framebuffer interface\n"); 645 //exit(1); 646 } 647 648 649 /* called periodically to poll for user input events */ 650 static void sdl_refresh(DisplayState *ds) 651 { 652 QEmulator* emulator = ds->opaque; 653 SDL_Event ev; 654 SkinWindow* window = emulator->window; 655 SkinKeyboard* keyboard = emulator->keyboard; 656 657 /* this will eventually call sdl_update if the content of the VGA framebuffer 658 * has changed */ 659 qframebuffer_check_updates(); 660 661 if (window == NULL) 662 return; 663 664 while(SDL_PollEvent(&ev)){ 665 switch(ev.type){ 666 case SDL_VIDEOEXPOSE: 667 skin_window_redraw( window, NULL ); 668 break; 669 670 case SDL_KEYDOWN: 671 #ifdef _WIN32 672 /* special code to deal with Alt-F4 properly */ 673 if (ev.key.keysym.sym == SDLK_F4 && 674 ev.key.keysym.mod & KMOD_ALT) { 675 goto CleanExit; 676 } 677 #endif 678 #ifdef __APPLE__ 679 /* special code to deal with Command-Q properly */ 680 if (ev.key.keysym.sym == SDLK_q && 681 ev.key.keysym.mod & KMOD_META) { 682 goto CleanExit; 683 } 684 #endif 685 skin_keyboard_process_event( keyboard, &ev, 1 ); 686 break; 687 688 case SDL_KEYUP: 689 skin_keyboard_process_event( keyboard, &ev, 0 ); 690 break; 691 692 case SDL_MOUSEMOTION: 693 skin_window_process_event( window, &ev ); 694 break; 695 696 case SDL_MOUSEBUTTONDOWN: 697 case SDL_MOUSEBUTTONUP: 698 { 699 int down = (ev.type == SDL_MOUSEBUTTONDOWN); 700 if (ev.button.button == 4) 701 { 702 /* scroll-wheel simulates DPad up */ 703 AndroidKeyCode kcode; 704 705 kcode = qemulator_rotate_keycode(emulator, kKeyCodeDpadUp); 706 send_key_event( kcode, down ); 707 } 708 else if (ev.button.button == 5) 709 { 710 /* scroll-wheel simulates DPad down */ 711 AndroidKeyCode kcode; 712 713 kcode = qemulator_rotate_keycode(emulator, kKeyCodeDpadDown); 714 send_key_event( kcode, down ); 715 } 716 else if (ev.button.button == SDL_BUTTON_LEFT) { 717 skin_window_process_event( window, &ev ); 718 } 719 #if 0 720 else { 721 fprintf(stderr, "... mouse button %s: button=%d state=%04x x=%d y=%d\n", 722 down ? "down" : "up ", 723 ev.button.button, ev.button.state, ev.button.x, ev.button.y); 724 } 725 #endif 726 } 727 break; 728 729 case SDL_QUIT: 730 #if defined _WIN32 || defined __APPLE__ 731 CleanExit: 732 #endif 733 /* only save emulator config through clean exit */ 734 qemulator_done( emulator ); 735 qemu_system_shutdown_request(); 736 return; 737 } 738 } 739 740 skin_keyboard_flush( keyboard ); 741 } 742 743 744 /* used to respond to a given keyboard command shortcut 745 */ 746 static void 747 handle_key_command( void* opaque, SkinKeyCommand command, int down ) 748 { 749 static const struct { SkinKeyCommand cmd; AndroidKeyCode kcode; } keycodes[] = 750 { 751 { SKIN_KEY_COMMAND_BUTTON_CALL, kKeyCodeCall }, 752 { SKIN_KEY_COMMAND_BUTTON_HOME, kKeyCodeHome }, 753 { SKIN_KEY_COMMAND_BUTTON_BACK, kKeyCodeBack }, 754 { SKIN_KEY_COMMAND_BUTTON_HANGUP, kKeyCodeEndCall }, 755 { SKIN_KEY_COMMAND_BUTTON_POWER, kKeyCodePower }, 756 { SKIN_KEY_COMMAND_BUTTON_SEARCH, kKeyCodeSearch }, 757 { SKIN_KEY_COMMAND_BUTTON_MENU, kKeyCodeMenu }, 758 { SKIN_KEY_COMMAND_BUTTON_DPAD_UP, kKeyCodeDpadUp }, 759 { SKIN_KEY_COMMAND_BUTTON_DPAD_LEFT, kKeyCodeDpadLeft }, 760 { SKIN_KEY_COMMAND_BUTTON_DPAD_RIGHT, kKeyCodeDpadRight }, 761 { SKIN_KEY_COMMAND_BUTTON_DPAD_DOWN, kKeyCodeDpadDown }, 762 { SKIN_KEY_COMMAND_BUTTON_DPAD_CENTER, kKeyCodeDpadCenter }, 763 { SKIN_KEY_COMMAND_BUTTON_VOLUME_UP, kKeyCodeVolumeUp }, 764 { SKIN_KEY_COMMAND_BUTTON_VOLUME_DOWN, kKeyCodeVolumeDown }, 765 { SKIN_KEY_COMMAND_BUTTON_CAMERA, kKeyCodeCamera }, 766 { SKIN_KEY_COMMAND_NONE, 0 } 767 }; 768 int nn; 769 #ifdef CONFIG_TRACE 770 static int tracing = 0; 771 #endif 772 QEmulator* emulator = opaque; 773 774 775 for (nn = 0; keycodes[nn].kcode != 0; nn++) { 776 if (command == keycodes[nn].cmd) { 777 unsigned code = keycodes[nn].kcode; 778 if (down) 779 code |= 0x200; 780 kbd_put_keycode( code ); 781 return; 782 } 783 } 784 785 // for the show-trackball command, handle down events to enable, and 786 // up events to disable 787 if (command == SKIN_KEY_COMMAND_SHOW_TRACKBALL) { 788 emulator->show_trackball = (down != 0); 789 skin_window_show_trackball( emulator->window, emulator->show_trackball ); 790 //qemulator_set_title( emulator ); 791 return; 792 } 793 794 // only handle down events for the rest 795 if (down == 0) 796 return; 797 798 switch (command) 799 { 800 case SKIN_KEY_COMMAND_TOGGLE_NETWORK: 801 { 802 qemu_net_disable = !qemu_net_disable; 803 if (android_modem) { 804 amodem_set_data_registration( 805 android_modem, 806 qemu_net_disable ? A_REGISTRATION_UNREGISTERED 807 : A_REGISTRATION_HOME); 808 } 809 D( "network is now %s", qemu_net_disable ? "disconnected" : "connected" ); 810 } 811 break; 812 813 case SKIN_KEY_COMMAND_TOGGLE_FULLSCREEN: 814 if (emulator->window) { 815 skin_window_toggle_fullscreen(emulator->window); 816 } 817 break; 818 819 case SKIN_KEY_COMMAND_TOGGLE_TRACING: 820 { 821 #ifdef CONFIG_TRACE 822 tracing = !tracing; 823 if (tracing) 824 start_tracing(); 825 else 826 stop_tracing(); 827 #endif 828 } 829 break; 830 831 case SKIN_KEY_COMMAND_TOGGLE_TRACKBALL: 832 emulator->show_trackball = !emulator->show_trackball; 833 skin_window_show_trackball( emulator->window, emulator->show_trackball ); 834 qemulator_set_title( emulator ); 835 break; 836 837 case SKIN_KEY_COMMAND_ONION_ALPHA_UP: 838 case SKIN_KEY_COMMAND_ONION_ALPHA_DOWN: 839 if (emulator->onion) 840 { 841 int alpha = emulator->onion_alpha; 842 843 if (command == SKIN_KEY_COMMAND_ONION_ALPHA_UP) 844 alpha += 16; 845 else 846 alpha -= 16; 847 848 if (alpha > 256) 849 alpha = 256; 850 else if (alpha < 0) 851 alpha = 0; 852 853 emulator->onion_alpha = alpha; 854 skin_window_set_onion( emulator->window, emulator->onion, emulator->onion_rotation, alpha ); 855 skin_window_redraw( emulator->window, NULL ); 856 //dprint( "onion alpha set to %d (%.f %%)", alpha, alpha/2.56 ); 857 } 858 break; 859 860 case SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV: 861 case SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT: 862 { 863 SkinLayout* layout = NULL; 864 865 if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT) { 866 layout = emulator->layout->next; 867 if (layout == NULL) 868 layout = emulator->layout_file->layouts; 869 } 870 else if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV) { 871 layout = emulator->layout_file->layouts; 872 while (layout->next && layout->next != emulator->layout) 873 layout = layout->next; 874 } 875 if (layout != NULL) { 876 SkinRotation rotation; 877 878 emulator->layout = layout; 879 skin_window_reset( emulator->window, layout ); 880 881 rotation = skin_layout_get_dpad_rotation( layout ); 882 883 if (emulator->keyboard) 884 skin_keyboard_set_rotation( emulator->keyboard, rotation ); 885 886 if (emulator->trackball) { 887 skin_trackball_set_rotation( emulator->trackball, rotation ); 888 skin_window_set_trackball( emulator->window, emulator->trackball ); 889 skin_window_show_trackball( emulator->window, emulator->show_trackball ); 890 } 891 892 skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness ); 893 894 qframebuffer_invalidate_all(); 895 qframebuffer_check_updates(); 896 } 897 } 898 break; 899 900 default: 901 /* XXX: TODO ? */ 902 ; 903 } 904 } 905 906 907 static void sdl_at_exit(void) 908 { 909 emulator_config_done(); 910 qemulator_done( qemulator ); 911 SDL_Quit(); 912 } 913 914 915 void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) 916 { 917 QEmulator* emulator = qemulator; 918 SkinDisplay* disp = skin_layout_get_display(emulator->layout); 919 DisplayChangeListener* dcl; 920 int width, height; 921 922 if (disp->rotation & 1) { 923 width = disp->rect.size.h; 924 height = disp->rect.size.w; 925 } else { 926 width = disp->rect.size.w; 927 height = disp->rect.size.h; 928 } 929 930 /* Register a display state object for the emulated framebuffer */ 931 ds->allocator = &default_allocator; 932 ds->opaque = emulator; 933 ds->surface = qemu_create_displaysurface(ds, width, height); 934 register_displaystate(ds); 935 936 /* Register a change listener for it */ 937 dcl = (DisplayChangeListener *) qemu_mallocz(sizeof(DisplayChangeListener)); 938 dcl->dpy_update = sdl_update; 939 dcl->dpy_resize = sdl_resize; 940 dcl->dpy_refresh = sdl_refresh; 941 dcl->dpy_text_cursor = NULL; 942 register_displaychangelistener(ds, dcl); 943 944 skin_keyboard_enable( emulator->keyboard, 1 ); 945 skin_keyboard_on_command( emulator->keyboard, handle_key_command, emulator ); 946 } 947 948 949 extern SkinKeyboard* android_emulator_get_keyboard(void) 950 { 951 return qemulator->keyboard; 952 } 953 954 static const char* skin_network_speed = NULL; 955 static const char* skin_network_delay = NULL; 956 957 /* list of skin aliases */ 958 static const struct { 959 const char* name; 960 const char* alias; 961 } skin_aliases[] = { 962 { "QVGA-L", "320x240" }, 963 { "QVGA-P", "240x320" }, 964 { "HVGA-L", "480x320" }, 965 { "HVGA-P", "320x480" }, 966 { "QVGA", "320x240" }, 967 { "HVGA", "320x480" }, 968 { NULL, NULL } 969 }; 970 971 /* this is used by hw/events_device.c to send the charmap name to the system */ 972 const char* android_skin_keycharmap = NULL; 973 974 void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts) 975 { 976 char tmp[1024]; 977 AConfig* root; 978 AConfig* n; 979 int win_x, win_y, flags; 980 981 signal(SIGINT, SIG_DFL); 982 #ifndef _WIN32 983 signal(SIGQUIT, SIG_DFL); 984 #endif 985 986 /* we're not a game, so allow the screensaver to run */ 987 putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1"); 988 989 flags = SDL_INIT_NOPARACHUTE; 990 if (!opts->no_window) 991 flags |= SDL_INIT_VIDEO; 992 993 if(SDL_Init(flags)){ 994 fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() ); 995 exit(1); 996 } 997 998 if (!opts->no_window) { 999 SDL_EnableUNICODE(!opts->raw_keys); 1000 SDL_EnableKeyRepeat(0,0); 1001 1002 sdl_set_window_icon(); 1003 } 1004 else 1005 { 1006 #ifndef _WIN32 1007 /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be 1008 * able to run the emulator in the background (e.g. "emulator &"). 1009 * despite the fact that the emulator should not grab input or try to 1010 * write to the output in normal cases, we're stopped on some systems 1011 * (e.g. OS X) 1012 */ 1013 signal(SIGTTIN, SIG_IGN); 1014 signal(SIGTTOU, SIG_IGN); 1015 #endif 1016 } 1017 atexit(sdl_at_exit); 1018 1019 root = aconfig_node("", ""); 1020 1021 if(name) { 1022 /* Support skin aliases like QVGA-H QVGA-P, etc... 1023 But first we check if it's a directory that exist before applying 1024 the alias */ 1025 int checkAlias = 1; 1026 1027 if (path != NULL) { 1028 bufprint(tmp, tmp+sizeof(tmp), "%s/%s", path, name); 1029 if (path_exists(tmp)) { 1030 checkAlias = 0; 1031 } else { 1032 D("there is no '%s' skin in '%s'", name, path); 1033 } 1034 } 1035 1036 if (checkAlias) { 1037 int nn; 1038 1039 for (nn = 0; ; nn++ ) { 1040 const char* skin_name = skin_aliases[nn].name; 1041 const char* skin_alias = skin_aliases[nn].alias; 1042 1043 if ( !skin_name ) 1044 break; 1045 1046 if ( !strcasecmp( skin_name, name ) ) { 1047 D("skin name '%s' aliased to '%s'", name, skin_alias); 1048 name = skin_alias; 1049 break; 1050 } 1051 } 1052 } 1053 1054 /* Magically support skins like "320x240" */ 1055 if(isdigit(name[0])) { 1056 char *x = strchr(name, 'x'); 1057 if(x && isdigit(x[1])) { 1058 int width = atoi(name); 1059 int height = atoi(x + 1); 1060 sprintf(tmp,"display {\n width %d\n height %d\n}\n", 1061 width, height); 1062 aconfig_load(root, strdup(tmp)); 1063 path = ":"; 1064 goto found_a_skin; 1065 } 1066 } 1067 1068 if (path == NULL) { 1069 derror("unknown skin name '%s'", name); 1070 exit(1); 1071 } 1072 1073 sprintf(tmp, "%s/%s/layout", path, name); 1074 D("trying to load skin file '%s'", tmp); 1075 1076 if(aconfig_load_file(root, tmp) >= 0) { 1077 sprintf(tmp, "%s/%s/", path, name); 1078 path = tmp; 1079 goto found_a_skin; 1080 } else { 1081 dwarning("could not load skin file '%s', using built-in one\n", 1082 tmp); 1083 } 1084 } 1085 1086 { 1087 const unsigned char* layout_base; 1088 size_t layout_size; 1089 1090 name = "<builtin>"; 1091 1092 layout_base = android_resource_find( "layout", &layout_size ); 1093 if (layout_base != NULL) { 1094 char* base = malloc( layout_size+1 ); 1095 memcpy( base, layout_base, layout_size ); 1096 base[layout_size] = 0; 1097 1098 D("parsing built-in skin layout file (size=%d)", (int)layout_size); 1099 aconfig_load(root, base); 1100 path = ":"; 1101 } else { 1102 fprintf(stderr, "Couldn't load builtin skin\n"); 1103 exit(1); 1104 } 1105 } 1106 1107 found_a_skin: 1108 { 1109 win_x = 10; 1110 win_y = 10; 1111 1112 if (userConfig) 1113 auserConfig_getWindowPos(userConfig, &win_x, &win_y); 1114 } 1115 1116 if ( qemulator_init( qemulator, root, path, win_x, win_y, opts ) < 0 ) { 1117 fprintf(stderr, "### Error: could not load emulator skin '%s'\n", name); 1118 exit(1); 1119 } 1120 1121 android_skin_keycharmap = skin_keyboard_charmap_name(qemulator->keyboard); 1122 1123 /* the default network speed and latency can now be specified by the device skin */ 1124 n = aconfig_find(root, "network"); 1125 if (n != NULL) { 1126 skin_network_speed = aconfig_str(n, "speed", 0); 1127 skin_network_delay = aconfig_str(n, "delay", 0); 1128 } 1129 1130 #if 0 1131 /* create a trackball if needed */ 1132 n = aconfig_find(root, "trackball"); 1133 if (n != NULL) { 1134 SkinTrackBallParameters params; 1135 1136 params.x = aconfig_unsigned(n, "x", 0); 1137 params.y = aconfig_unsigned(n, "y", 0); 1138 params.diameter = aconfig_unsigned(n, "diameter", 20); 1139 params.ring = aconfig_unsigned(n, "ring", 1); 1140 1141 params.ball_color = aconfig_unsigned(n, "ball-color", 0xffe0e0e0); 1142 params.dot_color = aconfig_unsigned(n, "dot-color", 0xff202020 ); 1143 params.ring_color = aconfig_unsigned(n, "ring-color", 0xff000000 ); 1144 1145 qemu_disp->trackball = skin_trackball_create( ¶ms ); 1146 skin_trackball_refresh( qemu_disp->trackball ); 1147 } 1148 #endif 1149 1150 /* add an onion overlay image if needed */ 1151 if (opts->onion) { 1152 SkinImage* onion = skin_image_find_simple( opts->onion ); 1153 int alpha, rotate; 1154 1155 if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) { 1156 alpha = (256*alpha)/100; 1157 } else 1158 alpha = 128; 1159 1160 if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) { 1161 rotate &= 3; 1162 } else 1163 rotate = SKIN_ROTATION_0; 1164 1165 qemulator->onion = onion; 1166 qemulator->onion_alpha = alpha; 1167 qemulator->onion_rotation = rotate; 1168 } 1169 } 1170 1171 int qemu_main(int argc, char **argv); 1172 1173 /* this function dumps the QEMU help */ 1174 extern void help( void ); 1175 extern void emulator_help( void ); 1176 1177 #define VERBOSE_OPT(str,var) { str, &var } 1178 1179 #define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y }, 1180 static const struct { const char* name; int flag; const char* text; } 1181 verbose_options[] = { 1182 VERBOSE_TAG_LIST 1183 { 0, 0, 0 } 1184 }; 1185 1186 int 1187 android_parse_network_speed(const char* speed) 1188 { 1189 int n; 1190 char* end; 1191 double sp; 1192 1193 if (speed == NULL || speed[0] == 0) { 1194 speed = DEFAULT_NETSPEED; 1195 } 1196 1197 for (n = 0; android_netspeeds[n].name != NULL; n++) { 1198 if (!strcmp(android_netspeeds[n].name, speed)) { 1199 qemu_net_download_speed = android_netspeeds[n].download; 1200 qemu_net_upload_speed = android_netspeeds[n].upload; 1201 return 0; 1202 } 1203 } 1204 1205 /* is this a number ? */ 1206 sp = strtod(speed, &end); 1207 if (end == speed) { 1208 return -1; 1209 } 1210 1211 qemu_net_download_speed = qemu_net_upload_speed = sp*1000.; 1212 if (*end == ':') { 1213 speed = end+1; 1214 sp = strtod(speed, &end); 1215 if (end > speed) { 1216 qemu_net_download_speed = sp*1000.; 1217 } 1218 } 1219 1220 if (android_modem) 1221 amodem_set_data_network_type( android_modem, 1222 android_parse_network_type(speed) ); 1223 return 0; 1224 } 1225 1226 1227 int 1228 android_parse_network_latency(const char* delay) 1229 { 1230 int n; 1231 char* end; 1232 double sp; 1233 1234 if (delay == NULL || delay[0] == 0) 1235 delay = DEFAULT_NETDELAY; 1236 1237 for (n = 0; android_netdelays[n].name != NULL; n++) { 1238 if ( !strcmp( android_netdelays[n].name, delay ) ) { 1239 qemu_net_min_latency = android_netdelays[n].min_ms; 1240 qemu_net_max_latency = android_netdelays[n].max_ms; 1241 return 0; 1242 } 1243 } 1244 1245 /* is this a number ? */ 1246 sp = strtod(delay, &end); 1247 if (end == delay) { 1248 return -1; 1249 } 1250 1251 qemu_net_min_latency = qemu_net_max_latency = (int)sp; 1252 if (*end == ':') { 1253 delay = (const char*)end+1; 1254 sp = strtod(delay, &end); 1255 if (end > delay) { 1256 qemu_net_max_latency = (int)sp; 1257 } 1258 } 1259 return 0; 1260 } 1261 1262 1263 static int 1264 load_keyset(const char* path) 1265 { 1266 if (path_can_read(path)) { 1267 AConfig* root = aconfig_node("",""); 1268 if (!aconfig_load_file(root, path)) { 1269 android_keyset = skin_keyset_new(root); 1270 if (android_keyset != NULL) { 1271 D( "keyset loaded from: %s", path); 1272 return 0; 1273 } 1274 } 1275 } 1276 return -1; 1277 } 1278 1279 static void 1280 parse_keyset(const char* keyset, AndroidOptions* opts) 1281 { 1282 char kname[MAX_PATH]; 1283 char temp[MAX_PATH]; 1284 char* p; 1285 char* end; 1286 1287 /* append .keyset suffix if needed */ 1288 if (strchr(keyset, '.') == NULL) { 1289 p = kname; 1290 end = p + sizeof(kname); 1291 p = bufprint(p, end, "%s.keyset", keyset); 1292 if (p >= end) { 1293 derror( "keyset name too long: '%s'\n", keyset); 1294 exit(1); 1295 } 1296 keyset = kname; 1297 } 1298 1299 /* look for a the keyset file */ 1300 p = temp; 1301 end = p + sizeof(temp); 1302 p = bufprint_config_file(p, end, keyset); 1303 if (p < end && load_keyset(temp) == 0) 1304 return; 1305 1306 p = temp; 1307 p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset); 1308 if (p < end && load_keyset(temp) == 0) 1309 return; 1310 1311 p = temp; 1312 p = bufprint_app_dir(p, end); 1313 p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset); 1314 if (p < end && load_keyset(temp) == 0) 1315 return; 1316 1317 return; 1318 } 1319 1320 static void 1321 write_default_keyset( void ) 1322 { 1323 char path[MAX_PATH]; 1324 1325 bufprint_config_file( path, path+sizeof(path), KEYSET_FILE ); 1326 1327 /* only write if there is no file here */ 1328 if ( !path_exists(path) ) { 1329 int fd = open( path, O_WRONLY | O_CREAT, 0666 ); 1330 int ret; 1331 const char* ks = skin_keyset_get_default(); 1332 1333 1334 D( "writing default keyset file to %s", path ); 1335 1336 if (fd < 0) { 1337 D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) ); 1338 return; 1339 } 1340 CHECKED(ret, write(fd, ks, strlen(ks))); 1341 close(fd); 1342 } 1343 } 1344 1345 #ifdef CONFIG_NAND_LIMITS 1346 1347 static uint64_t 1348 parse_nand_rw_limit( const char* value ) 1349 { 1350 char* end; 1351 uint64_t val = strtoul( value, &end, 0 ); 1352 1353 if (end == value) { 1354 derror( "bad parameter value '%s': expecting unsigned integer", value ); 1355 exit(1); 1356 } 1357 1358 switch (end[0]) { 1359 case 'K': val <<= 10; break; 1360 case 'M': val <<= 20; break; 1361 case 'G': val <<= 30; break; 1362 case 0: break; 1363 default: 1364 derror( "bad read/write limit suffix: use K, M or G" ); 1365 exit(1); 1366 } 1367 return val; 1368 } 1369 1370 static void 1371 parse_nand_limits(char* limits) 1372 { 1373 int pid = -1, signal = -1; 1374 int64_t reads = 0, writes = 0; 1375 char* item = limits; 1376 1377 /* parse over comma-separated items */ 1378 while (item && *item) { 1379 char* next = strchr(item, ','); 1380 char* end; 1381 1382 if (next == NULL) { 1383 next = item + strlen(item); 1384 } else { 1385 *next++ = 0; 1386 } 1387 1388 if ( !memcmp(item, "pid=", 4) ) { 1389 pid = strtol(item+4, &end, 10); 1390 if (end == NULL || *end) { 1391 derror( "bad parameter, expecting pid=<number>, got '%s'", 1392 item ); 1393 exit(1); 1394 } 1395 if (pid <= 0) { 1396 derror( "bad parameter: process identifier must be > 0" ); 1397 exit(1); 1398 } 1399 } 1400 else if ( !memcmp(item, "signal=", 7) ) { 1401 signal = strtol(item+7,&end, 10); 1402 if (end == NULL || *end) { 1403 derror( "bad parameter: expecting signal=<number>, got '%s'", 1404 item ); 1405 exit(1); 1406 } 1407 if (signal <= 0) { 1408 derror( "bad parameter: signal number must be > 0" ); 1409 exit(1); 1410 } 1411 } 1412 else if ( !memcmp(item, "reads=", 6) ) { 1413 reads = parse_nand_rw_limit(item+6); 1414 } 1415 else if ( !memcmp(item, "writes=", 7) ) { 1416 writes = parse_nand_rw_limit(item+7); 1417 } 1418 else { 1419 derror( "bad parameter '%s' (see -help-nand-limits)", item ); 1420 exit(1); 1421 } 1422 item = next; 1423 } 1424 if (pid < 0) { 1425 derror( "bad paramater: missing pid=<number>" ); 1426 exit(1); 1427 } 1428 else if (signal < 0) { 1429 derror( "bad parameter: missing signal=<number>" ); 1430 exit(1); 1431 } 1432 else if (reads == 0 && writes == 0) { 1433 dwarning( "no read or write limit specified. ignoring -nand-limits" ); 1434 } else { 1435 nand_threshold* t; 1436 1437 t = &android_nand_read_threshold; 1438 t->pid = pid; 1439 t->signal = signal; 1440 t->counter = 0; 1441 t->limit = reads; 1442 1443 t = &android_nand_write_threshold; 1444 t->pid = pid; 1445 t->signal = signal; 1446 t->counter = 0; 1447 t->limit = writes; 1448 } 1449 } 1450 #endif /* CONFIG_NAND_LIMITS */ 1451 1452 void emulator_help( void ) 1453 { 1454 STRALLOC_DEFINE(out); 1455 android_help_main(out); 1456 printf( "%.*s", out->n, out->s ); 1457 stralloc_reset(out); 1458 exit(1); 1459 } 1460 1461 static int 1462 add_dns_server( const char* server_name ) 1463 { 1464 SockAddress addr; 1465 1466 if (sock_address_init_resolve( &addr, server_name, 55, 0 ) < 0) { 1467 fprintf(stderr, 1468 "### WARNING: can't resolve DNS server name '%s'\n", 1469 server_name ); 1470 return -1; 1471 } 1472 1473 D( "DNS server name '%s' resolved to %s", server_name, sock_address_to_string(&addr) ); 1474 1475 if ( slirp_add_dns_server( &addr ) < 0 ) { 1476 fprintf(stderr, 1477 "### WARNING: could not add DNS server '%s' to the network stack\n", server_name); 1478 return -1; 1479 } 1480 return 0; 1481 } 1482 1483 1484 enum { 1485 REPORT_CONSOLE_SERVER = (1 << 0), 1486 REPORT_CONSOLE_MAX = (1 << 1) 1487 }; 1488 1489 static int 1490 get_report_console_options( char* end, int *maxtries ) 1491 { 1492 int flags = 0; 1493 1494 if (end == NULL || *end == 0) 1495 return 0; 1496 1497 if (end[0] != ',') { 1498 derror( "socket port/path can be followed by [,<option>]+ only\n"); 1499 exit(3); 1500 } 1501 end += 1; 1502 while (*end) { 1503 char* p = strchr(end, ','); 1504 if (p == NULL) 1505 p = end + strlen(end); 1506 1507 if (memcmp( end, "server", p-end ) == 0) 1508 flags |= REPORT_CONSOLE_SERVER; 1509 else if (memcmp( end, "max=", 4) == 0) { 1510 end += 4; 1511 *maxtries = strtol( end, NULL, 10 ); 1512 flags |= REPORT_CONSOLE_MAX; 1513 } else { 1514 derror( "socket port/path can be followed by [,server][,max=<count>] only\n"); 1515 exit(3); 1516 } 1517 1518 end = p; 1519 if (*end) 1520 end += 1; 1521 } 1522 return flags; 1523 } 1524 1525 static void 1526 report_console( const char* proto_port, int console_port ) 1527 { 1528 int s = -1, s2; 1529 int maxtries = 10; 1530 int flags = 0; 1531 signal_state_t sigstate; 1532 1533 disable_sigalrm( &sigstate ); 1534 1535 if ( !strncmp( proto_port, "tcp:", 4) ) { 1536 char* end; 1537 long port = strtol(proto_port + 4, &end, 10); 1538 1539 flags = get_report_console_options( end, &maxtries ); 1540 1541 if (flags & REPORT_CONSOLE_SERVER) { 1542 s = socket_loopback_server( port, SOCKET_STREAM ); 1543 if (s < 0) { 1544 fprintf(stderr, "could not create server socket on TCP:%ld: %s\n", 1545 port, errno_str); 1546 exit(3); 1547 } 1548 } else { 1549 for ( ; maxtries > 0; maxtries-- ) { 1550 D("trying to find console-report client on tcp:%d", port); 1551 s = socket_loopback_client( port, SOCKET_STREAM ); 1552 if (s >= 0) 1553 break; 1554 1555 sleep_ms(1000); 1556 } 1557 if (s < 0) { 1558 fprintf(stderr, "could not connect to server on TCP:%ld: %s\n", 1559 port, errno_str); 1560 exit(3); 1561 } 1562 } 1563 } else if ( !strncmp( proto_port, "unix:", 5) ) { 1564 #ifdef _WIN32 1565 fprintf(stderr, "sorry, the unix: protocol is not supported on Win32\n"); 1566 exit(3); 1567 #else 1568 char* path = strdup(proto_port+5); 1569 char* end = strchr(path, ','); 1570 if (end != NULL) { 1571 flags = get_report_console_options( end, &maxtries ); 1572 *end = 0; 1573 } 1574 if (flags & REPORT_CONSOLE_SERVER) { 1575 s = socket_unix_server( path, SOCKET_STREAM ); 1576 if (s < 0) { 1577 fprintf(stderr, "could not bind unix socket on '%s': %s\n", 1578 proto_port+5, errno_str); 1579 exit(3); 1580 } 1581 } else { 1582 for ( ; maxtries > 0; maxtries-- ) { 1583 s = socket_unix_client( path, SOCKET_STREAM ); 1584 if (s >= 0) 1585 break; 1586 1587 sleep_ms(1000); 1588 } 1589 if (s < 0) { 1590 fprintf(stderr, "could not connect to unix socket on '%s': %s\n", 1591 path, errno_str); 1592 exit(3); 1593 } 1594 } 1595 free(path); 1596 #endif 1597 } else { 1598 fprintf(stderr, "-report-console must be followed by a 'tcp:<port>' or 'unix:<path>'\n"); 1599 exit(3); 1600 } 1601 1602 if (flags & REPORT_CONSOLE_SERVER) { 1603 int tries = 3; 1604 D( "waiting for console-reporting client" ); 1605 do { 1606 s2 = socket_accept(s, NULL); 1607 } while (s2 < 0 && --tries > 0); 1608 1609 if (s2 < 0) { 1610 fprintf(stderr, "could not accept console-reporting client connection: %s\n", 1611 errno_str); 1612 exit(3); 1613 } 1614 1615 socket_close(s); 1616 s = s2; 1617 } 1618 1619 /* simply send the console port in text */ 1620 { 1621 char temp[12]; 1622 snprintf( temp, sizeof(temp), "%d", console_port ); 1623 1624 if (socket_send(s, temp, strlen(temp)) < 0) { 1625 fprintf(stderr, "could not send console number report: %d: %s\n", 1626 errno, errno_str ); 1627 exit(3); 1628 } 1629 socket_close(s); 1630 } 1631 D( "console port number sent to remote. resuming boot" ); 1632 1633 restore_sigalrm (&sigstate); 1634 } 1635 1636 /* this function is used to perform auto-detection of the 1637 * system directory in the case of a SDK installation. 1638 * 1639 * we want to deal with several historical usages, hence 1640 * the slightly complicated logic. 1641 * 1642 * NOTE: the function returns the path to the directory 1643 * containing 'fileName'. this is *not* the full 1644 * path to 'fileName'. 1645 */ 1646 static char* 1647 _getSdkImagePath( const char* fileName ) 1648 { 1649 char temp[MAX_PATH]; 1650 char* p = temp; 1651 char* end = p + sizeof(temp); 1652 char* q; 1653 char* app; 1654 1655 static const char* const searchPaths[] = { 1656 "", /* program's directory */ 1657 "/lib/images", /* this is for SDK 1.0 */ 1658 "/../platforms/android-1.1/images", /* this is for SDK 1.1 */ 1659 NULL 1660 }; 1661 1662 app = bufprint_app_dir(temp, end); 1663 if (app >= end) 1664 return NULL; 1665 1666 do { 1667 int nn; 1668 1669 /* first search a few well-known paths */ 1670 for (nn = 0; searchPaths[nn] != NULL; nn++) { 1671 p = bufprint(app, end, "%s", searchPaths[nn]); 1672 q = bufprint(p, end, "/%s", fileName); 1673 if (q < end && path_exists(temp)) { 1674 *p = 0; 1675 goto FOUND_IT; 1676 } 1677 } 1678 1679 /* hmmm. let's assume that we are in a post-1.1 SDK 1680 * scan ../platforms if it exists 1681 */ 1682 p = bufprint(app, end, "/../platforms"); 1683 if (p < end) { 1684 DirScanner* scanner = dirScanner_new(temp); 1685 if (scanner != NULL) { 1686 int found = 0; 1687 const char* subdir; 1688 1689 for (;;) { 1690 subdir = dirScanner_next(scanner); 1691 if (!subdir) break; 1692 1693 q = bufprint(p, end, "/%s/images/%s", subdir, fileName); 1694 if (q >= end || !path_exists(temp)) 1695 continue; 1696 1697 found = 1; 1698 p = bufprint(p, end, "/%s/images", subdir); 1699 break; 1700 } 1701 dirScanner_free(scanner); 1702 if (found) 1703 break; 1704 } 1705 } 1706 1707 /* I'm out of ideas */ 1708 return NULL; 1709 1710 } while (0); 1711 1712 FOUND_IT: 1713 //D("image auto-detection: %s/%s", temp, fileName); 1714 return qemu_strdup(temp); 1715 } 1716 1717 static char* 1718 _getSdkImage( const char* path, const char* file ) 1719 { 1720 char temp[MAX_PATH]; 1721 char *p = temp, *end = p + sizeof(temp); 1722 1723 p = bufprint(temp, end, "%s/%s", path, file); 1724 if (p >= end || !path_exists(temp)) 1725 return NULL; 1726 1727 return qemu_strdup(temp); 1728 } 1729 1730 static char* 1731 _getSdkSystemImage( const char* path, const char* optionName, const char* file ) 1732 { 1733 char* image = _getSdkImage(path, file); 1734 1735 if (image == NULL) { 1736 derror("Your system directory is missing the '%s' image file.\n" 1737 "Please specify one with the '%s <filepath>' option", 1738 file, optionName); 1739 exit(2); 1740 } 1741 return image; 1742 } 1743 1744 static void 1745 _forceAvdImagePath( AvdImageType imageType, 1746 const char* path, 1747 const char* description, 1748 int required ) 1749 { 1750 if (path == NULL) 1751 return; 1752 1753 if (required && !path_exists(path)) { 1754 derror("Cannot find %s image file: %s", description, path); 1755 exit(1); 1756 } 1757 android_avdParams->forcePaths[imageType] = path; 1758 } 1759 1760 static uint64_t 1761 _adjustPartitionSize( const char* description, 1762 uint64_t imageBytes, 1763 uint64_t defaultBytes, 1764 int inAndroidBuild ) 1765 { 1766 char temp[64]; 1767 unsigned imageMB; 1768 unsigned defaultMB; 1769 1770 if (imageBytes <= defaultBytes) 1771 return defaultBytes; 1772 1773 imageMB = convertBytesToMB(imageBytes); 1774 defaultMB = convertBytesToMB(defaultBytes); 1775 1776 if (imageMB > defaultMB) { 1777 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB); 1778 } else { 1779 snprintf(temp, sizeof temp, "(%lld bytes > %lld bytes)", imageBytes, defaultBytes); 1780 } 1781 1782 if (inAndroidBuild) { 1783 dwarning("%s partition size adjusted to match image file %s\n", description, temp); 1784 } 1785 1786 return convertMBToBytes(imageMB); 1787 } 1788 1789 #ifdef _WIN32 1790 #undef main /* we don't want SDL to define main */ 1791 #endif 1792 1793 int main(int argc, char **argv) 1794 { 1795 char tmp[MAX_PATH]; 1796 char* tmpend = tmp + sizeof(tmp); 1797 char* args[128]; 1798 int n; 1799 char* opt; 1800 int use_sdcard_img = 0; 1801 int serial = 0; 1802 int gps_serial = 0; 1803 int radio_serial = 0; 1804 int qemud_serial = 0; 1805 int shell_serial = 0; 1806 int dns_count = 0; 1807 unsigned cachePartitionSize = 0; 1808 unsigned systemPartitionSize = 0; 1809 unsigned dataPartitionSize = 0; 1810 unsigned defaultPartitionSize = convertMBToBytes(66); 1811 1812 AndroidHwConfig* hw; 1813 AvdInfo* avd; 1814 1815 //const char *appdir = get_app_dir(); 1816 char* android_build_root = NULL; 1817 char* android_build_out = NULL; 1818 1819 AndroidOptions opts[1]; 1820 1821 args[0] = argv[0]; 1822 1823 if ( android_parse_options( &argc, &argv, opts ) < 0 ) { 1824 exit(1); 1825 } 1826 1827 while (argc-- > 1) { 1828 opt = (++argv)[0]; 1829 1830 if(!strcmp(opt, "-qemu")) { 1831 argc--; 1832 argv++; 1833 break; 1834 } 1835 1836 if (!strcmp(opt, "-help")) { 1837 emulator_help(); 1838 } 1839 1840 if (!strncmp(opt, "-help-",6)) { 1841 STRALLOC_DEFINE(out); 1842 opt += 6; 1843 1844 if (!strcmp(opt, "all")) { 1845 android_help_all(out); 1846 } 1847 else if (android_help_for_option(opt, out) == 0) { 1848 /* ok */ 1849 } 1850 else if (android_help_for_topic(opt, out) == 0) { 1851 /* ok */ 1852 } 1853 if (out->n > 0) { 1854 printf("\n%.*s", out->n, out->s); 1855 exit(0); 1856 } 1857 1858 fprintf(stderr, "unknown option: -help-%s\n", opt); 1859 fprintf(stderr, "please use -help for a list of valid topics\n"); 1860 exit(1); 1861 } 1862 1863 if (opt[0] == '-') { 1864 fprintf(stderr, "unknown option: %s\n", opt); 1865 fprintf(stderr, "please use -help for a list of valid options\n"); 1866 exit(1); 1867 } 1868 1869 fprintf(stderr, "invalid command-line parameter: %s.\n", opt); 1870 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n"); 1871 fprintf(stderr, "please use -help for more information\n"); 1872 exit(1); 1873 } 1874 1875 /* special case, if -qemu -h is used, directly invoke the QEMU-specific help */ 1876 if (argc > 0) { 1877 int nn; 1878 for (nn = 0; nn < argc; nn++) 1879 if (!strcmp(argv[nn], "-h")) { 1880 qemu_help(0); 1881 break; 1882 } 1883 } 1884 1885 if (android_charmap_setup(opts->charmap)) { 1886 exit(1); 1887 } 1888 1889 if (opts->version) { 1890 printf("Android emulator version %s\n" 1891 "Copyright (C) 2006-2008 The Android Open Source Project and many others.\n" 1892 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n", 1893 #if defined ANDROID_BUILD_ID 1894 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" ); 1895 #else 1896 VERSION_STRING); 1897 #endif 1898 printf(" This software is licensed under the terms of the GNU General Public\n" 1899 " License version 2, as published by the Free Software Foundation, and\n" 1900 " may be copied, distributed, and modified under those terms.\n\n" 1901 " This program is distributed in the hope that it will be useful,\n" 1902 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 1903 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 1904 " GNU General Public License for more details.\n\n"); 1905 1906 exit(0); 1907 } 1908 1909 if (opts->timezone) { 1910 if ( timezone_set(opts->timezone) < 0 ) { 1911 fprintf(stderr, "emulator: it seems the timezone '%s' is not in zoneinfo format\n", opts->timezone); 1912 } 1913 } 1914 1915 /* legacy support: we used to use -system <dir> and -image <file> 1916 * instead of -sysdir <dir> and -system <file>, so handle this by checking 1917 * whether the options point to directories or files. 1918 */ 1919 if (opts->image != NULL) { 1920 if (opts->system != NULL) { 1921 if (opts->sysdir != NULL) { 1922 derror( "You can't use -sysdir, -system and -image at the same time.\n" 1923 "You should probably use '-sysdir <path> -system <file>'.\n" ); 1924 exit(2); 1925 } 1926 } 1927 dwarning( "Please note that -image is obsolete and that -system is now used to point\n" 1928 "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" ); 1929 opts->sysdir = opts->system; 1930 opts->system = opts->image; 1931 opts->image = NULL; 1932 } 1933 else if (opts->system != NULL && path_is_dir(opts->system)) { 1934 if (opts->sysdir != NULL) { 1935 derror( "Option -system should now be followed by a file path, not a directory one.\n" 1936 "Please use '-sysdir <path>' to point to the system directory.\n" ); 1937 exit(1); 1938 } 1939 dwarning( "Please note that the -system option should now be used to point to the initial\n" 1940 "system image (like the obsolete -image option). To point to the system directory\n" 1941 "please now use '-sysdir <path>' instead.\n" ); 1942 1943 opts->sysdir = opts->system; 1944 opts->system = NULL; 1945 } 1946 1947 if (opts->nojni) 1948 opts->no_jni = opts->nojni; 1949 1950 if (opts->nocache) 1951 opts->no_cache = opts->nocache; 1952 1953 if (opts->noaudio) 1954 opts->no_audio = opts->noaudio; 1955 1956 if (opts->noskin) 1957 opts->no_skin = opts->noskin; 1958 1959 if (opts->initdata) { 1960 opts->init_data = opts->initdata; 1961 opts->initdata = NULL; 1962 } 1963 1964 /* If no AVD name was given, try to find the top of the 1965 * Android build tree 1966 */ 1967 if (opts->avd == NULL) { 1968 do { 1969 char* out = getenv("ANDROID_PRODUCT_OUT"); 1970 1971 if (out == NULL || out[0] == 0) 1972 break; 1973 1974 if (!path_exists(out)) { 1975 derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n" 1976 "You need to build the Android system before launching the emulator", 1977 out); 1978 exit(2); 1979 } 1980 1981 android_build_root = path_parent( out, 4 ); 1982 if (android_build_root == NULL || !path_exists(android_build_root)) { 1983 derror("Can't find the Android build root from '%s'\n" 1984 "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n" 1985 "It should point to your product-specific build output directory.\n", 1986 out ); 1987 exit(2); 1988 } 1989 android_build_out = out; 1990 D( "found Android build root: %s", android_build_root ); 1991 D( "found Android build out: %s", android_build_out ); 1992 } while (0); 1993 } 1994 /* if no virtual device name is given, and we're not in the 1995 * Android build system, we'll need to perform some auto-detection 1996 * magic :-) 1997 */ 1998 if (opts->avd == NULL && !android_build_out) 1999 { 2000 char dataDirIsSystem = 0; 2001 2002 if (!opts->sysdir) { 2003 opts->sysdir = _getSdkImagePath("system.img"); 2004 if (!opts->sysdir) { 2005 derror( 2006 "You did not specify a virtual device name, and the system\n" 2007 "directory could not be found.\n\n" 2008 "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n" 2009 "to start a given virtual device (see -help-avd for details).\n\n" 2010 2011 "Otherwise, follow the instructions in -help-disk-images to start the emulator\n" 2012 ); 2013 exit(2); 2014 } 2015 D("autoconfig: -sysdir %s", opts->sysdir); 2016 } 2017 2018 if (!opts->system) { 2019 opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img"); 2020 D("autoconfig: -image %s", opts->image); 2021 } 2022 2023 if (!opts->kernel) { 2024 opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu"); 2025 D("autoconfig: -kernel %s", opts->kernel); 2026 } 2027 2028 if (!opts->ramdisk) { 2029 opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img"); 2030 D("autoconfig: -ramdisk %s", opts->ramdisk); 2031 } 2032 2033 /* if no data directory is specified, use the system directory */ 2034 if (!opts->datadir) { 2035 opts->datadir = qemu_strdup(opts->sysdir); 2036 dataDirIsSystem = 1; 2037 D("autoconfig: -datadir %s", opts->sysdir); 2038 } 2039 2040 if (!opts->data) { 2041 /* check for userdata-qemu.img in the data directory */ 2042 bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir); 2043 if (!path_exists(tmp)) { 2044 derror( 2045 "You did not provide the name of an Android Virtual Device\n" 2046 "with the '-avd <name>' option. Read -help-avd for more information.\n\n" 2047 2048 "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n" 2049 "to specify a data partition image file (I hope you know what you're doing).\n" 2050 ); 2051 exit(2); 2052 } 2053 2054 opts->data = qemu_strdup(tmp); 2055 D("autoconfig: -data %s", opts->data); 2056 } 2057 2058 if (!opts->sdcard && opts->datadir) { 2059 bufprint(tmp, tmpend, "%s/sdcard.img", opts->datadir); 2060 if (path_exists(tmp)) { 2061 opts->sdcard = qemu_strdup(tmp); 2062 D("autoconfig: -sdcard %s", opts->sdcard); 2063 } 2064 } 2065 } 2066 2067 /* setup the virtual device parameters from our options 2068 */ 2069 if (opts->no_cache) { 2070 android_avdParams->flags |= AVDINFO_NO_CACHE; 2071 } 2072 if (opts->wipe_data) { 2073 android_avdParams->flags |= AVDINFO_WIPE_DATA | AVDINFO_WIPE_CACHE; 2074 } 2075 2076 /* if certain options are set, we can force the path of 2077 * certain kernel/disk image files 2078 */ 2079 _forceAvdImagePath(AVD_IMAGE_KERNEL, opts->kernel, "kernel", 1); 2080 _forceAvdImagePath(AVD_IMAGE_INITSYSTEM, opts->system, "system", 1); 2081 _forceAvdImagePath(AVD_IMAGE_RAMDISK, opts->ramdisk,"ramdisk", 1); 2082 _forceAvdImagePath(AVD_IMAGE_USERDATA, opts->data, "user data", 0); 2083 _forceAvdImagePath(AVD_IMAGE_CACHE, opts->cache, "cache", 0); 2084 _forceAvdImagePath(AVD_IMAGE_SDCARD, opts->sdcard, "SD Card", 0); 2085 2086 /* we don't accept -skindir without -skin now 2087 * to simplify the autoconfig stuff with virtual devices 2088 */ 2089 if (opts->no_skin) { 2090 opts->skin = "320x480"; 2091 opts->skindir = NULL; 2092 } 2093 2094 if (opts->skindir) { 2095 if (!opts->skin) { 2096 derror( "the -skindir <path> option requires a -skin <name> option"); 2097 exit(1); 2098 } 2099 } 2100 android_avdParams->skinName = opts->skin; 2101 android_avdParams->skinRootPath = opts->skindir; 2102 2103 /* setup the virtual device differently depending on whether 2104 * we are in the Android build system or not 2105 */ 2106 if (opts->avd != NULL) 2107 { 2108 android_avdInfo = avdInfo_new( opts->avd, android_avdParams ); 2109 if (android_avdInfo == NULL) { 2110 /* an error message has already been printed */ 2111 dprint("could not find virtual device named '%s'", opts->avd); 2112 exit(1); 2113 } 2114 } 2115 else 2116 { 2117 if (!android_build_out) { 2118 android_build_out = android_build_root = opts->sysdir; 2119 } 2120 android_avdInfo = avdInfo_newForAndroidBuild( 2121 android_build_root, 2122 android_build_out, 2123 android_avdParams ); 2124 2125 if(android_avdInfo == NULL) { 2126 D("could not start virtual device\n"); 2127 exit(1); 2128 } 2129 } 2130 2131 avd = android_avdInfo; 2132 2133 /* get the skin from the virtual device configuration */ 2134 opts->skin = (char*) avdInfo_getSkinName( avd ); 2135 opts->skindir = (char*) avdInfo_getSkinDir( avd ); 2136 2137 if (opts->skin) { 2138 D("autoconfig: -skin %s", opts->skin); 2139 } 2140 if (opts->skindir) { 2141 D("autoconfig: -skindir %s", opts->skindir); 2142 } 2143 2144 /* Read hardware configuration */ 2145 hw = android_hw; 2146 if (avdInfo_getHwConfig(avd, hw) < 0) { 2147 derror("could not read hardware configuration ?"); 2148 exit(1); 2149 } 2150 2151 #ifdef CONFIG_NAND_LIMITS 2152 if (opts->nand_limits) 2153 parse_nand_limits(opts->nand_limits); 2154 #endif 2155 2156 if (opts->keyset) { 2157 parse_keyset(opts->keyset, opts); 2158 if (!android_keyset) { 2159 fprintf(stderr, 2160 "emulator: WARNING: could not find keyset file named '%s'," 2161 " using defaults instead\n", 2162 opts->keyset); 2163 } 2164 } 2165 if (!android_keyset) { 2166 parse_keyset("default", opts); 2167 if (!android_keyset) { 2168 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() ); 2169 if (!android_keyset) { 2170 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" ); 2171 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" ); 2172 exit(1); 2173 } 2174 if (!opts->keyset) 2175 write_default_keyset(); 2176 } 2177 } 2178 2179 /* the purpose of -no-audio is to disable sound output from the emulator, 2180 * not to disable Audio emulation. So simply force the 'none' backends */ 2181 if (opts->no_audio) 2182 opts->audio = "none"; 2183 2184 if (opts->audio) { 2185 if (opts->audio_in || opts->audio_out) { 2186 derror( "you can't use -audio with -audio-in or -audio-out\n" ); 2187 exit(1); 2188 } 2189 if ( !audio_check_backend_name( 0, opts->audio ) ) { 2190 derror( "'%s' is not a valid audio output backend. see -help-audio-out\n", 2191 opts->audio); 2192 exit(1); 2193 } 2194 opts->audio_out = opts->audio; 2195 opts->audio_in = opts->audio; 2196 2197 if ( !audio_check_backend_name( 1, opts->audio ) ) { 2198 fprintf(stderr, 2199 "emulator: warning: '%s' is not a valid audio input backend. audio record disabled\n", 2200 opts->audio); 2201 opts->audio_in = "none"; 2202 } 2203 } 2204 2205 if (opts->audio_in) { 2206 static char env[64]; /* note: putenv needs a static unique string buffer */ 2207 if ( !audio_check_backend_name( 1, opts->audio_in ) ) { 2208 derror( "'%s' is not a valid audio input backend. see -help-audio-in\n", 2209 opts->audio_in); 2210 exit(1); 2211 } 2212 bufprint( env, env+sizeof(env), "QEMU_AUDIO_IN_DRV=%s", opts->audio_in ); 2213 putenv( env ); 2214 2215 if (!hw->hw_audioInput) { 2216 dwarning( "Emulated hardware doesn't have audio input."); 2217 } 2218 } 2219 if (opts->audio_out) { 2220 static char env[64]; /* note: putenv needs a static unique string buffer */ 2221 if ( !audio_check_backend_name( 0, opts->audio_out ) ) { 2222 derror( "'%s' is not a valid audio output backend. see -help-audio-out\n", 2223 opts->audio_out); 2224 exit(1); 2225 } 2226 bufprint( env, env+sizeof(env), "QEMU_AUDIO_OUT_DRV=%s", opts->audio_out ); 2227 putenv( env ); 2228 if (!hw->hw_audioOutput) { 2229 dwarning( "Emulated hardware doesn't have audio output"); 2230 } 2231 } 2232 2233 if (opts->cpu_delay) { 2234 char* end; 2235 long delay = strtol(opts->cpu_delay, &end, 0); 2236 if (end == NULL || *end || delay < 0 || delay > 1000 ) { 2237 fprintf(stderr, "option -cpu-delay must be an integer between 0 and 1000\n" ); 2238 exit(1); 2239 } 2240 if (delay > 0) 2241 delay = (1000-delay); 2242 2243 qemu_cpu_delay = (int) delay; 2244 } 2245 2246 emulator_config_init(); 2247 init_skinned_ui(opts->skindir, opts->skin, opts); 2248 2249 if (!opts->netspeed) { 2250 if (skin_network_speed) 2251 D("skin network speed: '%s'", skin_network_speed); 2252 opts->netspeed = (char*)skin_network_speed; 2253 } 2254 if (!opts->netdelay) { 2255 if (skin_network_delay) 2256 D("skin network delay: '%s'", skin_network_delay); 2257 opts->netdelay = (char*)skin_network_delay; 2258 } 2259 2260 if ( android_parse_network_speed(opts->netspeed) < 0 ) { 2261 fprintf(stderr, "invalid -netspeed parameter '%s', see emulator -usage\n", opts->netspeed); 2262 emulator_help(); 2263 } 2264 2265 if ( android_parse_network_latency(opts->netdelay) < 0 ) { 2266 fprintf(stderr, "invalid -netdelay parameter '%s', see emulator -usage\n", opts->netdelay); 2267 emulator_help(); 2268 } 2269 2270 if (opts->netfast) { 2271 qemu_net_download_speed = 0; 2272 qemu_net_upload_speed = 0; 2273 qemu_net_min_latency = 0; 2274 qemu_net_max_latency = 0; 2275 } 2276 2277 if (opts->trace) { 2278 char* tracePath = avdInfo_getTracePath(avd, opts->trace); 2279 int ret; 2280 2281 if (tracePath == NULL) { 2282 derror( "bad -trace parameter" ); 2283 exit(1); 2284 } 2285 ret = path_mkdir_if_needed( tracePath, 0755 ); 2286 if (ret < 0) { 2287 fprintf(stderr, "could not create directory '%s'\n", tmp); 2288 exit(2); 2289 } 2290 opts->trace = tracePath; 2291 } 2292 2293 #ifdef CONFIG_MEMCHECK 2294 if (opts->memcheck) { 2295 memcheck_init(opts->memcheck); 2296 } 2297 #endif // CONFIG_MEMCHECK 2298 2299 if (opts->tcpdump) { 2300 if (qemu_tcpdump_start(opts->tcpdump) < 0) { 2301 dwarning( "could not start packet capture: %s", strerror(errno)); 2302 } 2303 } 2304 2305 if (opts->no_cache) 2306 opts->cache = 0; 2307 2308 if (opts->dns_server) { 2309 char* x = strchr(opts->dns_server, ','); 2310 dns_count = 0; 2311 if (x == NULL) 2312 { 2313 if ( add_dns_server( opts->dns_server ) == 0 ) 2314 dns_count = 1; 2315 } 2316 else 2317 { 2318 x = strdup(opts->dns_server); 2319 while (*x) { 2320 char* y = strchr(x, ','); 2321 2322 if (y != NULL) 2323 *y = 0; 2324 2325 if (y == NULL || y > x) { 2326 if ( add_dns_server( x ) == 0 ) 2327 dns_count += 1; 2328 } 2329 2330 if (y == NULL) 2331 break; 2332 2333 x = y+1; 2334 } 2335 } 2336 if (dns_count == 0) 2337 fprintf( stderr, "### WARNING: will use system default DNS server\n" ); 2338 } 2339 2340 if (dns_count == 0) 2341 dns_count = slirp_get_system_dns_servers(); 2342 2343 n = 1; 2344 /* generate arguments for the underlying qemu main() */ 2345 { 2346 const char* kernelFile = avdInfo_getImageFile(avd, AVD_IMAGE_KERNEL); 2347 int kernelFileLen = strlen(kernelFile); 2348 2349 args[n++] = "-kernel"; 2350 args[n++] = (char*)kernelFile; 2351 2352 /* If the kernel image name ends in "-armv7", then change the cpu 2353 * type automatically. This is a poor man's approach to configuration 2354 * management, but should allow us to get past building ARMv7 2355 * system images with dex preopt pass without introducing too many 2356 * changes to the emulator sources. 2357 * 2358 * XXX: 2359 * A 'proper' change would require adding some sort of hardware-property 2360 * to each AVD config file, then automatically determine its value for 2361 * full Android builds (depending on some environment variable), plus 2362 * some build system changes. I prefer not to do that for now for reasons 2363 * of simplicity. 2364 */ 2365 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) { 2366 args[n++] = "-cpu"; 2367 args[n++] = "cortex-a8"; 2368 } 2369 } 2370 2371 args[n++] = "-initrd"; 2372 args[n++] = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_RAMDISK); 2373 2374 if (opts->partition_size) { 2375 char* end; 2376 long sizeMB = strtol(opts->partition_size, &end, 0); 2377 long minSizeMB = 10; 2378 long maxSizeMB = LONG_MAX / ONE_MB; 2379 2380 if (sizeMB < 0 || *end != 0) { 2381 derror( "-partition-size must be followed by a positive integer" ); 2382 exit(1); 2383 } 2384 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) { 2385 derror( "partition-size (%d) must be between %dMB and %dMB", 2386 sizeMB, minSizeMB, maxSizeMB ); 2387 exit(1); 2388 } 2389 defaultPartitionSize = sizeMB * ONE_MB; 2390 } 2391 2392 /* Check the size of the system partition image. 2393 * If we have an AVD, it must be smaller than 2394 * the disk.systemPartition.size hardware property. 2395 * 2396 * Otherwise, we need to adjust the systemPartitionSize 2397 * automatically, and print a warning. 2398 * 2399 */ 2400 { 2401 uint64_t systemBytes = avdInfo_getImageFileSize(avd, AVD_IMAGE_INITSYSTEM); 2402 uint64_t defaultBytes = defaultPartitionSize; 2403 2404 if (defaultBytes == 0 || opts->partition_size) 2405 defaultBytes = defaultPartitionSize; 2406 2407 systemPartitionSize = _adjustPartitionSize("system", systemBytes, defaultBytes, 2408 android_build_out != NULL); 2409 } 2410 2411 /* Check the size of the /data partition. The only interesting cases here are: 2412 * - when the USERDATA image already exists and is larger than the default 2413 * - when we're wiping data and the INITDATA is larger than the default. 2414 */ 2415 2416 { 2417 const char* dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA); 2418 uint64_t defaultBytes = defaultPartitionSize; 2419 2420 if (defaultBytes == 0 || opts->partition_size) 2421 defaultBytes = defaultPartitionSize; 2422 2423 if (dataPath == NULL || !path_exists(dataPath) || opts->wipe_data) { 2424 dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_INITDATA); 2425 } 2426 if (dataPath == NULL || !path_exists(dataPath)) { 2427 dataPartitionSize = defaultBytes; 2428 } 2429 else { 2430 uint64_t dataBytes; 2431 path_get_size(dataPath, &dataBytes); 2432 2433 dataPartitionSize = _adjustPartitionSize("data", dataBytes, defaultBytes, 2434 android_build_out != NULL); 2435 } 2436 } 2437 2438 { 2439 const char* filetype = "file"; 2440 2441 if (avdInfo_isImageReadOnly(avd, AVD_IMAGE_INITSYSTEM)) 2442 filetype = "initfile"; 2443 2444 bufprint(tmp, tmpend, 2445 "system,size=0x%x,%s=%s", systemPartitionSize, filetype, 2446 avdInfo_getImageFile(avd, AVD_IMAGE_INITSYSTEM)); 2447 2448 args[n++] = "-nand"; 2449 args[n++] = strdup(tmp); 2450 } 2451 2452 bufprint(tmp, tmpend, 2453 "userdata,size=0x%x,file=%s", 2454 dataPartitionSize, 2455 avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA)); 2456 2457 args[n++] = "-nand"; 2458 args[n++] = strdup(tmp); 2459 2460 if (hw->disk_cachePartition) { 2461 opts->cache = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_CACHE); 2462 cachePartitionSize = hw->disk_cachePartition_size; 2463 } 2464 else if (opts->cache) { 2465 dwarning( "Emulated hardware doesn't support a cache partition" ); 2466 opts->cache = NULL; 2467 opts->no_cache = 1; 2468 } 2469 2470 if (opts->cache) { 2471 /* use a specific cache file */ 2472 sprintf(tmp, "cache,size=0x%0x,file=%s", cachePartitionSize, opts->cache); 2473 args[n++] = "-nand"; 2474 args[n++] = strdup(tmp); 2475 } 2476 else if (!opts->no_cache) { 2477 /* create a temporary cache partition file */ 2478 sprintf(tmp, "cache,size=0x%0x", cachePartitionSize); 2479 args[n++] = "-nand"; 2480 args[n++] = strdup(tmp); 2481 } 2482 2483 if (hw->hw_sdCard != 0) 2484 opts->sdcard = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SDCARD); 2485 else if (opts->sdcard) { 2486 dwarning( "Emulated hardware doesn't support SD Cards" ); 2487 opts->sdcard = NULL; 2488 } 2489 2490 if(opts->sdcard) { 2491 uint64_t size; 2492 if (path_get_size(opts->sdcard, &size) == 0) { 2493 /* see if we have an sdcard image. get its size if it exists */ 2494 /* due to what looks like limitations of the MMC protocol, one has 2495 * to use an SD Card image that is equal or larger than 9 MB 2496 */ 2497 if (size < 9*1024*1024ULL) { 2498 fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard); 2499 } else { 2500 args[n++] = "-hda"; 2501 args[n++] = opts->sdcard; 2502 use_sdcard_img = 1; 2503 } 2504 } else { 2505 D("no SD Card image at '%s'", opts->sdcard); 2506 } 2507 } 2508 2509 if (!opts->logcat || opts->logcat[0] == 0) { 2510 opts->logcat = getenv("ANDROID_LOG_TAGS"); 2511 if (opts->logcat && opts->logcat[0] == 0) 2512 opts->logcat = NULL; 2513 } 2514 2515 #if 0 2516 if (opts->console) { 2517 derror( "option -console is obsolete. please use -shell instead" ); 2518 exit(1); 2519 } 2520 #endif 2521 2522 /* we always send the kernel messages from ttyS0 to android_kmsg */ 2523 { 2524 AndroidKmsgFlags flags = 0; 2525 2526 if (opts->show_kernel) 2527 flags |= ANDROID_KMSG_PRINT_MESSAGES; 2528 2529 android_kmsg_init( flags ); 2530 args[n++] = "-serial"; 2531 args[n++] = "android-kmsg"; 2532 serial++; 2533 } 2534 2535 /* XXXX: TODO: implement -shell and -logcat through qemud instead */ 2536 if (!opts->shell_serial) { 2537 #ifdef _WIN32 2538 opts->shell_serial = "con:"; 2539 #else 2540 opts->shell_serial = "stdio"; 2541 #endif 2542 } 2543 else 2544 opts->shell = 1; 2545 2546 if (opts->shell || opts->logcat) { 2547 args[n++] = "-serial"; 2548 args[n++] = opts->shell_serial; 2549 shell_serial = serial++; 2550 } 2551 2552 if (opts->old_system) 2553 { 2554 if (opts->radio) { 2555 args[n++] = "-serial"; 2556 args[n++] = opts->radio; 2557 radio_serial = serial++; 2558 } 2559 else { 2560 args[n++] = "-serial"; 2561 args[n++] = "android-modem"; 2562 radio_serial = serial++; 2563 } 2564 if (opts->gps) { 2565 args[n++] = "-serial"; 2566 args[n++] = opts->gps; 2567 gps_serial = serial++; 2568 } 2569 } 2570 else /* !opts->old_system */ 2571 { 2572 args[n++] = "-serial"; 2573 args[n++] = "android-qemud"; 2574 qemud_serial = serial++; 2575 2576 if (opts->radio) { 2577 CharDriverState* cs = qemu_chr_open("radio",opts->radio,NULL); 2578 if (cs == NULL) { 2579 derror( "unsupported character device specification: %s\n" 2580 "used -help-char-devices for list of available formats\n", opts->radio ); 2581 exit(1); 2582 } 2583 android_qemud_set_channel( ANDROID_QEMUD_GSM, cs); 2584 } 2585 else if ( hw->hw_gsmModem != 0 ) { 2586 if ( android_qemud_get_channel( ANDROID_QEMUD_GSM, &android_modem_cs ) < 0 ) { 2587 derror( "could not initialize qemud 'gsm' channel" ); 2588 exit(1); 2589 } 2590 } 2591 2592 if (opts->gps) { 2593 CharDriverState* cs = qemu_chr_open("gps",opts->gps,NULL); 2594 if (cs == NULL) { 2595 derror( "unsupported character device specification: %s\n" 2596 "used -help-char-devices for list of available formats\n", opts->gps ); 2597 exit(1); 2598 } 2599 android_qemud_set_channel( ANDROID_QEMUD_GPS, cs); 2600 } 2601 else if ( hw->hw_gps != 0 ) { 2602 if ( android_qemud_get_channel( "gps", &android_gps_cs ) < 0 ) { 2603 derror( "could not initialize qemud 'gps' channel" ); 2604 exit(1); 2605 } 2606 } 2607 } 2608 2609 if (opts->memory) { 2610 char* end; 2611 long ramSize = strtol(opts->memory, &end, 0); 2612 if (ramSize < 0 || *end != 0) { 2613 derror( "-memory must be followed by a positive integer" ); 2614 exit(1); 2615 } 2616 if (ramSize < 32 || ramSize > 4096) { 2617 derror( "physical memory size must be between 32 and 4096 MB" ); 2618 exit(1); 2619 } 2620 } 2621 if (!opts->memory) { 2622 bufprint(tmp, tmpend, "%d", hw->hw_ramSize); 2623 opts->memory = qemu_strdup(tmp); 2624 } 2625 2626 if (opts->trace) { 2627 args[n++] = "-trace"; 2628 args[n++] = opts->trace; 2629 args[n++] = "-tracing"; 2630 args[n++] = "off"; 2631 } 2632 2633 args[n++] = "-append"; 2634 2635 if (opts->bootchart) { 2636 char* end; 2637 int timeout = strtol(opts->bootchart, &end, 10); 2638 if (timeout == 0) 2639 opts->bootchart = NULL; 2640 else if (timeout < 0 || timeout > 15*60) { 2641 derror( "timeout specified for -bootchart option is invalid.\n" 2642 "please use integers between 1 and 900\n"); 2643 exit(1); 2644 } 2645 } 2646 2647 /* start the 'boot-properties service, and parse the -prop 2648 * options, if any. 2649 */ 2650 boot_property_init_service(); 2651 2652 hwLcd_setBootProperty(get_device_dpi(opts)); 2653 2654 /* Set the VM's max heap size, passed as a boot property */ 2655 if (hw->vm_heapSize > 0) { 2656 char tmp[32], *p=tmp, *end=p + sizeof(tmp); 2657 p = bufprint(p, end, "%dm", hw->vm_heapSize); 2658 2659 boot_property_add("dalvik.vm.heapsize",tmp); 2660 } 2661 2662 if (opts->prop != NULL) { 2663 ParamList* pl = opts->prop; 2664 for ( ; pl != NULL; pl = pl->next ) { 2665 boot_property_parse_option(pl->param); 2666 } 2667 } 2668 2669 /* Setup the kernel init options 2670 */ 2671 { 2672 static char params[1024]; 2673 char *p = params, *end = p + sizeof(params); 2674 2675 p = bufprint(p, end, "qemu=1 console=ttyS0" ); 2676 2677 if (opts->shell || opts->logcat) { 2678 p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial ); 2679 } 2680 2681 if (opts->trace) { 2682 p = bufprint(p, end, " android.tracing=1"); 2683 } 2684 2685 #ifdef CONFIG_MEMCHECK 2686 if (opts->memcheck) { 2687 /* This will set ro.kernel.memcheck system property 2688 * to memcheck's tracing flags. */ 2689 p = bufprint(p, end, " memcheck=%s", opts->memcheck); 2690 } 2691 #endif // CONFIG_MEMCHECK 2692 2693 if (!opts->no_jni) { 2694 p = bufprint(p, end, " android.checkjni=1"); 2695 } 2696 2697 if (opts->no_boot_anim) { 2698 p = bufprint( p, end, " android.bootanim=0" ); 2699 } 2700 2701 if (opts->logcat) { 2702 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat); 2703 2704 if (q < end) { 2705 /* replace any space by a comma ! */ 2706 { 2707 int nn; 2708 for (nn = 1; p[nn] != 0; nn++) 2709 if (p[nn] == ' ' || p[nn] == '\t') 2710 p[nn] = ','; 2711 p += nn; 2712 } 2713 } 2714 p = q; 2715 } 2716 2717 if (opts->old_system) 2718 { 2719 p = bufprint(p, end, " android.ril=ttyS%d", radio_serial); 2720 2721 if (opts->gps) { 2722 p = bufprint(p, end, " android.gps=ttyS%d", gps_serial); 2723 } 2724 } 2725 else 2726 { 2727 p = bufprint(p, end, " android.qemud=ttyS%d", qemud_serial); 2728 } 2729 2730 if (dns_count > 0) { 2731 p = bufprint(p, end, " android.ndns=%d", dns_count); 2732 } 2733 2734 if (opts->bootchart) { 2735 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart); 2736 } 2737 2738 if (p >= end) { 2739 fprintf(stderr, "### ERROR: kernel parameters too long\n"); 2740 exit(1); 2741 } 2742 2743 args[n++] = strdup(params); 2744 } 2745 2746 /* physical memory */ 2747 args[n++] = "-m"; 2748 args[n++] = opts->memory; 2749 2750 /* on Linux, the 'dynticks' clock sometimes doesn't work 2751 * properly. this results in the UI freezing while emulation 2752 * continues, for several seconds... 2753 */ 2754 #ifdef __linux__ 2755 args[n++] = "-clock"; 2756 args[n++] = "unix"; 2757 #endif 2758 2759 while(argc-- > 0) { 2760 args[n++] = *argv++; 2761 } 2762 args[n] = 0; 2763 2764 if(VERBOSE_CHECK(init)) { 2765 int i; 2766 for(i = 0; i < n; i++) { 2767 fprintf(stdout, "emulator: argv[%02d] = \"%s\"\n", i, args[i]); 2768 } 2769 } 2770 return qemu_main(n, args); 2771 } 2772 2773 /* this function is called from qemu_main() once all arguments have been parsed 2774 * it should be used to setup any Android-specific items in the emulation before the 2775 * main loop runs 2776 */ 2777 void android_emulation_setup( void ) 2778 { 2779 int tries = 16; 2780 int base_port = 5554; 2781 int success = 0; 2782 int s; 2783 uint32_t guest_ip; 2784 2785 AndroidOptions* opts = qemulator->opts; 2786 2787 inet_strtoip("10.0.2.15", &guest_ip); 2788 2789 #if 0 2790 if (opts->adb_port) { 2791 fprintf( stderr, "option -adb-port is obsolete, use -port instead\n" ); 2792 exit(1); 2793 } 2794 #endif 2795 2796 if (opts->port && opts->ports) { 2797 fprintf( stderr, "options -port and -ports cannot be used together.\n"); 2798 exit(1); 2799 } 2800 2801 if (opts->ports) { 2802 char* comma_location; 2803 char* end; 2804 int console_port = strtol( opts->ports, &comma_location, 0 ); 2805 2806 if ( comma_location == NULL || *comma_location != ',' ) { 2807 derror( "option -ports must be followed by two comma separated positive integer numbers" ); 2808 exit(1); 2809 } 2810 2811 int adb_port = strtol( comma_location+1, &end, 0 ); 2812 2813 if ( end == NULL || *end ) { 2814 derror( "option -ports must be followed by two comma separated positive integer numbers" ); 2815 exit(1); 2816 } 2817 2818 if ( console_port == adb_port ) { 2819 derror( "option -ports must be followed by two different integer numbers" ); 2820 exit(1); 2821 } 2822 2823 slirp_redir( 0, adb_port, guest_ip, 5555 ); 2824 if ( control_console_start( console_port ) < 0 ) { 2825 slirp_unredir( 0, adb_port ); 2826 } 2827 2828 base_port = console_port; 2829 } else { 2830 if (opts->port) { 2831 char* end; 2832 int port = strtol( opts->port, &end, 0 ); 2833 if ( end == NULL || *end || 2834 (unsigned)((port - base_port) >> 1) >= (unsigned)tries ) { 2835 derror( "option -port must be followed by an even integer number between %d and %d\n", 2836 base_port, base_port + (tries-1)*2 ); 2837 exit(1); 2838 } 2839 if ( (port & 1) != 0 ) { 2840 port &= ~1; 2841 dwarning( "option -port must be followed by an even integer, using port number %d\n", 2842 port ); 2843 } 2844 base_port = port; 2845 tries = 1; 2846 } 2847 2848 for ( ; tries > 0; tries--, base_port += 2 ) { 2849 2850 /* setup first redirection for ADB, the Android Debug Bridge */ 2851 if ( slirp_redir( 0, base_port+1, guest_ip, 5555 ) < 0 ) 2852 continue; 2853 2854 /* setup second redirection for the emulator console */ 2855 if ( control_console_start( base_port ) < 0 ) { 2856 slirp_unredir( 0, base_port+1 ); 2857 continue; 2858 } 2859 2860 D( "control console listening on port %d, ADB on port %d", base_port, base_port+1 ); 2861 success = 1; 2862 break; 2863 } 2864 2865 if (!success) { 2866 fprintf(stderr, "it seems too many emulator instances are running on this machine. Aborting\n" ); 2867 exit(1); 2868 } 2869 } 2870 2871 if (opts->report_console) { 2872 report_console(opts->report_console, base_port); 2873 } 2874 2875 android_modem_init( base_port ); 2876 2877 android_base_port = base_port; 2878 /* send a simple message to the ADB host server to tell it we just started. 2879 * it should be listening on port 5037. if we can't reach it, don't bother 2880 */ 2881 do 2882 { 2883 SockAddress addr; 2884 char tmp[32]; 2885 2886 s = socket_create_inet( SOCKET_STREAM ); 2887 if (s < 0) { 2888 D("can't create socket to talk to the ADB server"); 2889 break; 2890 } 2891 2892 sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, 5037 ); 2893 if (socket_connect( s, &addr ) < 0) { 2894 D("can't connect to ADB server: %s", errno_str ); 2895 break; 2896 } 2897 2898 sprintf(tmp,"0012host:emulator:%d",base_port+1); 2899 socket_send(s, tmp, 18+4); 2900 D("sent '%s' to ADB server", tmp); 2901 } 2902 while (0); 2903 2904 if (s >= 0) 2905 socket_close(s); 2906 2907 /* setup the http proxy, if any */ 2908 if (VERBOSE_CHECK(proxy)) 2909 proxy_set_verbose(1); 2910 2911 if (!opts->http_proxy) { 2912 opts->http_proxy = getenv("http_proxy"); 2913 } 2914 2915 do 2916 { 2917 const char* env = opts->http_proxy; 2918 int envlen; 2919 ProxyOption option_tab[4]; 2920 ProxyOption* option = option_tab; 2921 char* p; 2922 char* q; 2923 const char* proxy_name; 2924 int proxy_name_len; 2925 int proxy_port; 2926 2927 if (!env) 2928 break; 2929 2930 envlen = strlen(env); 2931 2932 /* skip the 'http://' header, if present */ 2933 if (envlen >= 7 && !memcmp(env, "http://", 7)) { 2934 env += 7; 2935 envlen -= 7; 2936 } 2937 2938 /* do we have a username:password pair ? */ 2939 p = strchr(env, '@'); 2940 if (p != 0) { 2941 q = strchr(env, ':'); 2942 if (q == NULL) { 2943 BadHttpProxyFormat: 2944 dprint("http_proxy format unsupported, try 'proxy:port' or 'username:password@proxy:port'"); 2945 break; 2946 } 2947 2948 option->type = PROXY_OPTION_AUTH_USERNAME; 2949 option->string = env; 2950 option->string_len = q - env; 2951 option++; 2952 2953 option->type = PROXY_OPTION_AUTH_PASSWORD; 2954 option->string = q+1; 2955 option->string_len = p - (q+1); 2956 option++; 2957 2958 env = p+1; 2959 } 2960 2961 p = strchr(env,':'); 2962 if (p == NULL) 2963 goto BadHttpProxyFormat; 2964 2965 proxy_name = env; 2966 proxy_name_len = p - env; 2967 proxy_port = atoi(p+1); 2968 2969 D( "setting up http proxy: server=%.*s port=%d", 2970 proxy_name_len, proxy_name, proxy_port ); 2971 2972 if ( proxy_http_setup( proxy_name, proxy_name_len, proxy_port, 2973 option - option_tab, option_tab ) < 0 ) 2974 { 2975 dprint( "http proxy setup failed, check your $http_proxy variable"); 2976 } 2977 } 2978 while (0); 2979 2980 /* initialize sensors, this must be done here due to timer issues */ 2981 android_hw_sensors_init(); 2982 2983 /* cool, now try to run the "ddms ping" command, which will take care of pinging usage 2984 * if the user agreed for it. the emulator itself never sends anything to any outside 2985 * machine 2986 */ 2987 { 2988 #ifdef _WIN32 2989 # define _ANDROID_PING_PROGRAM "ddms.bat" 2990 #else 2991 # define _ANDROID_PING_PROGRAM "ddms" 2992 #endif 2993 2994 char tmp[PATH_MAX]; 2995 const char* appdir = get_app_dir(); 2996 2997 if (snprintf( tmp, PATH_MAX, "%s%s%s", appdir, PATH_SEP, 2998 _ANDROID_PING_PROGRAM ) >= PATH_MAX) { 2999 dprint( "Application directory too long: %s", appdir); 3000 return; 3001 } 3002 3003 /* if the program isn't there, don't bother */ 3004 D( "ping program: %s", tmp); 3005 if (path_exists(tmp)) { 3006 #ifdef _WIN32 3007 STARTUPINFO startup; 3008 PROCESS_INFORMATION pinfo; 3009 3010 ZeroMemory( &startup, sizeof(startup) ); 3011 startup.cb = sizeof(startup); 3012 startup.dwFlags = STARTF_USESHOWWINDOW; 3013 startup.wShowWindow = SW_SHOWMINIMIZED; 3014 3015 ZeroMemory( &pinfo, sizeof(pinfo) ); 3016 3017 char* comspec = getenv("COMSPEC"); 3018 if (!comspec) comspec = "cmd.exe"; 3019 3020 // Run 3021 char args[PATH_MAX + 30]; 3022 if (snprintf( args, PATH_MAX, "/C \"%s\" ping emulator " VERSION_STRING, 3023 tmp) >= PATH_MAX ) { 3024 D( "DDMS path too long: %s", tmp); 3025 return; 3026 } 3027 3028 CreateProcess( 3029 comspec, /* program path */ 3030 args, /* command line args */ 3031 NULL, /* process handle is not inheritable */ 3032 NULL, /* thread handle is not inheritable */ 3033 FALSE, /* no, don't inherit any handles */ 3034 DETACHED_PROCESS, /* the new process doesn't have a console */ 3035 NULL, /* use parent's environment block */ 3036 NULL, /* use parent's starting directory */ 3037 &startup, /* startup info, i.e. std handles */ 3038 &pinfo ); 3039 3040 D( "ping command: %s %s", comspec, args ); 3041 #else 3042 int pid; 3043 3044 /* disable SIGALRM for the fork(), the periodic signal seems to 3045 * interefere badly with the fork() implementation on Linux running 3046 * under VMWare. 3047 */ 3048 BEGIN_NOSIGALRM 3049 pid = fork(); 3050 if (pid == 0) { 3051 int fd = open("/dev/null", O_WRONLY); 3052 dup2(fd, 1); 3053 dup2(fd, 2); 3054 execl( tmp, _ANDROID_PING_PROGRAM, "ping", "emulator", VERSION_STRING, NULL ); 3055 } 3056 END_NOSIGALRM 3057 3058 /* don't do anything in the parent or in case of error */ 3059 strncat( tmp, " ping emulator " VERSION_STRING, PATH_MAX - strlen(tmp) ); 3060 D( "ping command: %s", tmp ); 3061 #endif 3062 } 3063 } 3064 } 3065 3066 3067 void android_emulation_teardown( void ) 3068 { 3069 android_charmap_done(); 3070 } 3071