main.c revision 34f2974ce7ec7c71beb47b5daf9089d5c8c40c79
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#include "user-events.h" 28 29#include <SDL.h> 30#include <SDL_syswm.h> 31 32#include "math.h" 33 34#include "android/charmap.h" 35#include "modem_driver.h" 36#include "shaper.h" 37#include "proxy_http.h" 38 39#include "android/utils/debug.h" 40#include "android/resource.h" 41#include "android/config.h" 42#include "android/config/config.h" 43 44#include "android/skin/image.h" 45#include "android/skin/trackball.h" 46#include "android/skin/keyboard.h" 47#include "android/skin/file.h" 48#include "android/skin/window.h" 49#include "android/skin/keyset.h" 50 51#include "android/gps.h" 52#include "android/hw-qemud.h" 53#include "android/hw-kmsg.h" 54#include "android/hw-lcd.h" 55#include "android/hw-control.h" 56#include "android/hw-sensors.h" 57#include "android/boot-properties.h" 58#include "android/user-config.h" 59#include "android/utils/bufprint.h" 60#include "android/utils/dirscanner.h" 61#include "android/utils/path.h" 62#include "android/utils/timezone.h" 63 64#include "android/cmdline-option.h" 65#include "android/help.h" 66#include "hw/goldfish_nand.h" 67#ifdef CONFIG_MEMCHECK 68#include "memcheck/memcheck.h" 69#endif // CONFIG_MEMCHECK 70 71#include "android/globals.h" 72#include "tcpdump.h" 73 74#include "android/qemulator.h" 75 76/* in vl.c */ 77extern void qemu_help(int code); 78 79#include "framebuffer.h" 80AndroidRotation android_framebuffer_rotation; 81 82#define STRINGIFY(x) _STRINGIFY(x) 83#define _STRINGIFY(x) #x 84 85#ifdef ANDROID_SDK_TOOLS_REVISION 86# define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0" 87#else 88# define VERSION_STRING "standalone" 89#endif 90 91#define KEYSET_FILE "default.keyset" 92SkinKeyset* android_keyset; 93 94#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0) 95 96extern int control_console_start( int port ); /* in control.c */ 97 98extern int qemu_milli_needed; 99 100/* the default device DPI if none is specified by the skin 101 */ 102#define DEFAULT_DEVICE_DPI 165 103 104int android_base_port; 105 106#if 0 107static int opts->flashkeys; /* forward */ 108#endif 109 110static void handle_key_command( void* opaque, SkinKeyCommand command, int param ); 111 112#ifdef CONFIG_TRACE 113extern void start_tracing(void); 114extern void stop_tracing(void); 115#endif 116 117unsigned long android_verbose; 118 119int qemu_cpu_delay = 0; 120int qemu_cpu_delay_count; 121 122/***********************************************************************/ 123/***********************************************************************/ 124/***** *****/ 125/***** U T I L I T Y R O U T I N E S *****/ 126/***** *****/ 127/***********************************************************************/ 128/***********************************************************************/ 129 130/*** CONFIGURATION 131 ***/ 132 133static AUserConfig* userConfig; 134 135void 136emulator_config_init( void ) 137{ 138 userConfig = auserConfig_new( android_avdInfo ); 139} 140 141/* only call this function on normal exits, so that ^C doesn't save the configuration */ 142void 143emulator_config_done( void ) 144{ 145 int win_x, win_y; 146 147 if (!userConfig) { 148 D("no user configuration?"); 149 return; 150 } 151 152 SDL_WM_GetPos( &win_x, &win_y ); 153 auserConfig_setWindowPos(userConfig, win_x, win_y); 154 auserConfig_save(userConfig); 155} 156 157void *loadpng(const char *fn, unsigned *_width, unsigned *_height); 158void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height); 159 160#ifdef CONFIG_DARWIN 161# define ANDROID_ICON_PNG "android_icon_256.png" 162#else 163# define ANDROID_ICON_PNG "android_icon_16.png" 164#endif 165 166static void 167sdl_set_window_icon( void ) 168{ 169 static int window_icon_set; 170 171 if (!window_icon_set) 172 { 173#ifdef _WIN32 174 HANDLE handle = GetModuleHandle( NULL ); 175 HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) ); 176 SDL_SysWMinfo wminfo; 177 178 SDL_GetWMInfo(&wminfo); 179 180 SetClassLong( wminfo.window, GCL_HICON, (LONG)icon ); 181#else /* !_WIN32 */ 182 unsigned icon_w, icon_h; 183 size_t icon_bytes; 184 const unsigned char* icon_data; 185 void* icon_pixels; 186 187 window_icon_set = 1; 188 189 icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes ); 190 if ( !icon_data ) 191 return; 192 193 icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h ); 194 if ( !icon_pixels ) 195 return; 196 197 /* the data is loaded into memory as RGBA bytes by libpng. we want to manage 198 * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending 199 * on our CPU endianess 200 */ 201 { 202 unsigned* d = icon_pixels; 203 unsigned* d_end = d + icon_w*icon_h; 204 205 for ( ; d < d_end; d++ ) { 206 unsigned pix = d[0]; 207#if HOST_WORDS_BIGENDIAN 208 /* R,G,B,A read as RGBA => ARGB */ 209 pix = ((pix >> 8) & 0xffffff) | (pix << 24); 210#else 211 /* R,G,B,A read as ABGR => ARGB */ 212 pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16); 213#endif 214 d[0] = pix; 215 } 216 } 217 218 SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h ); 219 if (icon != NULL) { 220 SDL_WM_SetIcon(icon, NULL); 221 SDL_FreeSurface(icon); 222 free( icon_pixels ); 223 } 224#endif /* !_WIN32 */ 225 } 226} 227 228/* see http://en.wikipedia.org/wiki/List_of_device_bandwidths or a complete list */ 229const NetworkSpeed android_netspeeds[] = { 230 { "gsm", "GSM/CSD", 14400, 14400 }, 231 { "hscsd", "HSCSD", 14400, 43200 }, 232 { "gprs", "GPRS", 40000, 80000 }, 233 { "edge", "EDGE/EGPRS", 118400, 236800 }, 234 { "umts", "UMTS/3G", 128000, 1920000 }, 235 { "hsdpa", "HSDPA", 348000, 14400000 }, 236 { "full", "no limit", 0, 0 }, 237 { NULL, NULL, 0, 0 } 238}; 239 240const NetworkLatency android_netdelays[] = { 241 /* FIXME: these numbers are totally imaginary */ 242 { "gprs", "GPRS", 150, 550 }, 243 { "edge", "EDGE/EGPRS", 80, 400 }, 244 { "umts", "UMTS/3G", 35, 200 }, 245 { "none", "no latency", 0, 0 }, 246 { NULL, NULL, 0, 0 } 247}; 248 249 250 251 252#define ONE_MB (1024*1024) 253 254unsigned convertBytesToMB( uint64_t size ) 255{ 256 if (size == 0) 257 return 0; 258 259 size = (size + ONE_MB-1) >> 20; 260 if (size > UINT_MAX) 261 size = UINT_MAX; 262 263 return (unsigned) size; 264} 265 266uint64_t convertMBToBytes( unsigned megaBytes ) 267{ 268 return ((uint64_t)megaBytes << 20); 269} 270 271/***********************************************************************/ 272/***********************************************************************/ 273/***** *****/ 274/***** S K I N I M A G E S *****/ 275/***** *****/ 276/***********************************************************************/ 277/***********************************************************************/ 278 279/* called by the emulated framebuffer device each time the content of the 280 * framebuffer has changed. the rectangle is the bounding box of all changes 281 */ 282static void 283sdl_update(DisplayState *ds, int x, int y, int w, int h) 284{ 285 /* this function is being called from the console code that is currently inactive 286 ** simple totally ignore it... 287 */ 288 (void)ds; 289 (void)x; 290 (void)y; 291 (void)w; 292 (void)h; 293} 294 295 296 297 298/* called by the emulated framebuffer device each time the framebuffer 299 * is resized or rotated */ 300static void 301sdl_resize(DisplayState *ds) 302{ 303 //fprintf(stderr, "weird, sdl_resize being called with framebuffer interface\n"); 304 //exit(1); 305} 306 307 308/* called periodically to poll for user input events */ 309static void sdl_refresh(DisplayState *ds) 310{ 311 QEmulator* emulator = ds->opaque; 312 SDL_Event ev; 313 SkinWindow* window = emulator->window; 314 SkinKeyboard* keyboard = emulator->keyboard; 315 316 /* this will eventually call sdl_update if the content of the VGA framebuffer 317 * has changed */ 318 qframebuffer_check_updates(); 319 320 if (window == NULL) 321 return; 322 323 while(SDL_PollEvent(&ev)){ 324 switch(ev.type){ 325 case SDL_VIDEOEXPOSE: 326 skin_window_redraw( window, NULL ); 327 break; 328 329 case SDL_KEYDOWN: 330#ifdef _WIN32 331 /* special code to deal with Alt-F4 properly */ 332 if (ev.key.keysym.sym == SDLK_F4 && 333 ev.key.keysym.mod & KMOD_ALT) { 334 goto CleanExit; 335 } 336#endif 337#ifdef __APPLE__ 338 /* special code to deal with Command-Q properly */ 339 if (ev.key.keysym.sym == SDLK_q && 340 ev.key.keysym.mod & KMOD_META) { 341 goto CleanExit; 342 } 343#endif 344 skin_keyboard_process_event( keyboard, &ev, 1 ); 345 break; 346 347 case SDL_KEYUP: 348 skin_keyboard_process_event( keyboard, &ev, 0 ); 349 break; 350 351 case SDL_MOUSEMOTION: 352 skin_window_process_event( window, &ev ); 353 break; 354 355 case SDL_MOUSEBUTTONDOWN: 356 case SDL_MOUSEBUTTONUP: 357 { 358 int down = (ev.type == SDL_MOUSEBUTTONDOWN); 359 if (ev.button.button == 4) 360 { 361 /* scroll-wheel simulates DPad up */ 362 AndroidKeyCode kcode; 363 364 kcode = // qemulator_rotate_keycode(kKeyCodeDpadUp); 365 android_keycode_rotate(kKeyCodeDpadUp, 366 skin_layout_get_dpad_rotation(qemulator_get_layout(qemulator_get()))); 367 user_event_key( kcode, down ); 368 } 369 else if (ev.button.button == 5) 370 { 371 /* scroll-wheel simulates DPad down */ 372 AndroidKeyCode kcode; 373 374 kcode = // qemulator_rotate_keycode(kKeyCodeDpadDown); 375 android_keycode_rotate(kKeyCodeDpadDown, 376 skin_layout_get_dpad_rotation(qemulator_get_layout(qemulator_get()))); 377 user_event_key( kcode, down ); 378 } 379 else if (ev.button.button == SDL_BUTTON_LEFT) { 380 skin_window_process_event( window, &ev ); 381 } 382#if 0 383 else { 384 fprintf(stderr, "... mouse button %s: button=%d state=%04x x=%d y=%d\n", 385 down ? "down" : "up ", 386 ev.button.button, ev.button.state, ev.button.x, ev.button.y); 387 } 388#endif 389 } 390 break; 391 392 case SDL_QUIT: 393#if defined _WIN32 || defined __APPLE__ 394 CleanExit: 395#endif 396 /* only save emulator config through clean exit */ 397 qemulator_done(qemulator_get()); 398 qemu_system_shutdown_request(); 399 return; 400 } 401 } 402 403 skin_keyboard_flush( keyboard ); 404} 405 406 407/* used to respond to a given keyboard command shortcut 408 */ 409static void 410handle_key_command( void* opaque, SkinKeyCommand command, int down ) 411{ 412 static const struct { SkinKeyCommand cmd; AndroidKeyCode kcode; } keycodes[] = 413 { 414 { SKIN_KEY_COMMAND_BUTTON_CALL, kKeyCodeCall }, 415 { SKIN_KEY_COMMAND_BUTTON_HOME, kKeyCodeHome }, 416 { SKIN_KEY_COMMAND_BUTTON_BACK, kKeyCodeBack }, 417 { SKIN_KEY_COMMAND_BUTTON_HANGUP, kKeyCodeEndCall }, 418 { SKIN_KEY_COMMAND_BUTTON_POWER, kKeyCodePower }, 419 { SKIN_KEY_COMMAND_BUTTON_SEARCH, kKeyCodeSearch }, 420 { SKIN_KEY_COMMAND_BUTTON_MENU, kKeyCodeMenu }, 421 { SKIN_KEY_COMMAND_BUTTON_DPAD_UP, kKeyCodeDpadUp }, 422 { SKIN_KEY_COMMAND_BUTTON_DPAD_LEFT, kKeyCodeDpadLeft }, 423 { SKIN_KEY_COMMAND_BUTTON_DPAD_RIGHT, kKeyCodeDpadRight }, 424 { SKIN_KEY_COMMAND_BUTTON_DPAD_DOWN, kKeyCodeDpadDown }, 425 { SKIN_KEY_COMMAND_BUTTON_DPAD_CENTER, kKeyCodeDpadCenter }, 426 { SKIN_KEY_COMMAND_BUTTON_VOLUME_UP, kKeyCodeVolumeUp }, 427 { SKIN_KEY_COMMAND_BUTTON_VOLUME_DOWN, kKeyCodeVolumeDown }, 428 { SKIN_KEY_COMMAND_BUTTON_CAMERA, kKeyCodeCamera }, 429 { SKIN_KEY_COMMAND_NONE, 0 } 430 }; 431 int nn; 432#ifdef CONFIG_TRACE 433 static int tracing = 0; 434#endif 435 QEmulator* emulator = opaque; 436 437 438 for (nn = 0; keycodes[nn].kcode != 0; nn++) { 439 if (command == keycodes[nn].cmd) { 440 unsigned code = keycodes[nn].kcode; 441 if (down) 442 code |= 0x200; 443 kbd_put_keycode( code ); 444 return; 445 } 446 } 447 448 // for the show-trackball command, handle down events to enable, and 449 // up events to disable 450 if (command == SKIN_KEY_COMMAND_SHOW_TRACKBALL) { 451 emulator->show_trackball = (down != 0); 452 skin_window_show_trackball( emulator->window, emulator->show_trackball ); 453 //qemulator_set_title( emulator ); 454 return; 455 } 456 457 // only handle down events for the rest 458 if (down == 0) 459 return; 460 461 switch (command) 462 { 463 case SKIN_KEY_COMMAND_TOGGLE_NETWORK: 464 { 465 qemu_net_disable = !qemu_net_disable; 466 if (android_modem) { 467 amodem_set_data_registration( 468 android_modem, 469 qemu_net_disable ? A_REGISTRATION_UNREGISTERED 470 : A_REGISTRATION_HOME); 471 } 472 D( "network is now %s", qemu_net_disable ? "disconnected" : "connected" ); 473 } 474 break; 475 476 case SKIN_KEY_COMMAND_TOGGLE_FULLSCREEN: 477 if (emulator->window) { 478 skin_window_toggle_fullscreen(emulator->window); 479 } 480 break; 481 482 case SKIN_KEY_COMMAND_TOGGLE_TRACING: 483 { 484#ifdef CONFIG_TRACE 485 tracing = !tracing; 486 if (tracing) 487 start_tracing(); 488 else 489 stop_tracing(); 490#endif 491 } 492 break; 493 494 case SKIN_KEY_COMMAND_TOGGLE_TRACKBALL: 495 emulator->show_trackball = !emulator->show_trackball; 496 skin_window_show_trackball( emulator->window, emulator->show_trackball ); 497 qemulator_set_title(emulator); 498 break; 499 500 case SKIN_KEY_COMMAND_ONION_ALPHA_UP: 501 case SKIN_KEY_COMMAND_ONION_ALPHA_DOWN: 502 if (emulator->onion) 503 { 504 int alpha = emulator->onion_alpha; 505 506 if (command == SKIN_KEY_COMMAND_ONION_ALPHA_UP) 507 alpha += 16; 508 else 509 alpha -= 16; 510 511 if (alpha > 256) 512 alpha = 256; 513 else if (alpha < 0) 514 alpha = 0; 515 516 emulator->onion_alpha = alpha; 517 skin_window_set_onion( emulator->window, emulator->onion, emulator->onion_rotation, alpha ); 518 skin_window_redraw( emulator->window, NULL ); 519 //dprint( "onion alpha set to %d (%.f %%)", alpha, alpha/2.56 ); 520 } 521 break; 522 523 case SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV: 524 case SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT: 525 { 526 SkinLayout* layout = NULL; 527 528 if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT) { 529 layout = emulator->layout->next; 530 if (layout == NULL) 531 layout = emulator->layout_file->layouts; 532 } 533 else if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV) { 534 layout = emulator->layout_file->layouts; 535 while (layout->next && layout->next != emulator->layout) 536 layout = layout->next; 537 } 538 if (layout != NULL) { 539 SkinRotation rotation; 540 541 emulator->layout = layout; 542 skin_window_reset( emulator->window, layout ); 543 544 rotation = skin_layout_get_dpad_rotation( layout ); 545 546 if (emulator->keyboard) 547 skin_keyboard_set_rotation( emulator->keyboard, rotation ); 548 549 if (emulator->trackball) { 550 skin_trackball_set_rotation( emulator->trackball, rotation ); 551 skin_window_set_trackball( emulator->window, emulator->trackball ); 552 skin_window_show_trackball( emulator->window, emulator->show_trackball ); 553 } 554 555 skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness ); 556 557 qframebuffer_invalidate_all(); 558 qframebuffer_check_updates(); 559 } 560 } 561 break; 562 563 default: 564 /* XXX: TODO ? */ 565 ; 566 } 567} 568 569 570static void sdl_at_exit(void) 571{ 572 emulator_config_done(); 573 qemulator_done(qemulator_get()); 574 SDL_Quit(); 575} 576 577 578void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) 579{ 580 QEmulator* emulator = qemulator_get(); 581 SkinDisplay* disp = skin_layout_get_display(emulator->layout); 582 DisplayChangeListener* dcl; 583 int width, height; 584 585 if (disp->rotation & 1) { 586 width = disp->rect.size.h; 587 height = disp->rect.size.w; 588 } else { 589 width = disp->rect.size.w; 590 height = disp->rect.size.h; 591 } 592 593 /* Register a display state object for the emulated framebuffer */ 594 ds->allocator = &default_allocator; 595 ds->opaque = emulator; 596 ds->surface = qemu_create_displaysurface(ds, width, height); 597 register_displaystate(ds); 598 599 /* Register a change listener for it */ 600 dcl = (DisplayChangeListener *) qemu_mallocz(sizeof(DisplayChangeListener)); 601 dcl->dpy_update = sdl_update; 602 dcl->dpy_resize = sdl_resize; 603 dcl->dpy_refresh = sdl_refresh; 604 dcl->dpy_text_cursor = NULL; 605 register_displaychangelistener(ds, dcl); 606 607 skin_keyboard_enable( emulator->keyboard, 1 ); 608 skin_keyboard_on_command( emulator->keyboard, handle_key_command, emulator ); 609} 610 611 612static const char* skin_network_speed = NULL; 613static const char* skin_network_delay = NULL; 614 615/* list of skin aliases */ 616static const struct { 617 const char* name; 618 const char* alias; 619} skin_aliases[] = { 620 { "QVGA-L", "320x240" }, 621 { "QVGA-P", "240x320" }, 622 { "HVGA-L", "480x320" }, 623 { "HVGA-P", "320x480" }, 624 { "QVGA", "320x240" }, 625 { "HVGA", "320x480" }, 626 { NULL, NULL } 627}; 628 629/* this is used by hw/events_device.c to send the charmap name to the system */ 630const char* android_skin_keycharmap = NULL; 631 632void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts) 633{ 634 char tmp[1024]; 635 AConfig* root; 636 AConfig* n; 637 int win_x, win_y, flags; 638 639 signal(SIGINT, SIG_DFL); 640#ifndef _WIN32 641 signal(SIGQUIT, SIG_DFL); 642#endif 643 644 /* we're not a game, so allow the screensaver to run */ 645 putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1"); 646 647 flags = SDL_INIT_NOPARACHUTE; 648 if (!opts->no_window) 649 flags |= SDL_INIT_VIDEO; 650 651 if(SDL_Init(flags)){ 652 fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() ); 653 exit(1); 654 } 655 656 if (!opts->no_window) { 657 SDL_EnableUNICODE(!opts->raw_keys); 658 SDL_EnableKeyRepeat(0,0); 659 660 sdl_set_window_icon(); 661 } 662 else 663 { 664#ifndef _WIN32 665 /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be 666 * able to run the emulator in the background (e.g. "emulator &"). 667 * despite the fact that the emulator should not grab input or try to 668 * write to the output in normal cases, we're stopped on some systems 669 * (e.g. OS X) 670 */ 671 signal(SIGTTIN, SIG_IGN); 672 signal(SIGTTOU, SIG_IGN); 673#endif 674 } 675 atexit(sdl_at_exit); 676 677 root = aconfig_node("", ""); 678 679 if(name) { 680 /* Support skin aliases like QVGA-H QVGA-P, etc... 681 But first we check if it's a directory that exist before applying 682 the alias */ 683 int checkAlias = 1; 684 685 if (path != NULL) { 686 bufprint(tmp, tmp+sizeof(tmp), "%s/%s", path, name); 687 if (path_exists(tmp)) { 688 checkAlias = 0; 689 } else { 690 D("there is no '%s' skin in '%s'", name, path); 691 } 692 } 693 694 if (checkAlias) { 695 int nn; 696 697 for (nn = 0; ; nn++ ) { 698 const char* skin_name = skin_aliases[nn].name; 699 const char* skin_alias = skin_aliases[nn].alias; 700 701 if ( !skin_name ) 702 break; 703 704 if ( !strcasecmp( skin_name, name ) ) { 705 D("skin name '%s' aliased to '%s'", name, skin_alias); 706 name = skin_alias; 707 break; 708 } 709 } 710 } 711 712 /* Magically support skins like "320x240" */ 713 if(isdigit(name[0])) { 714 char *x = strchr(name, 'x'); 715 if(x && isdigit(x[1])) { 716 int width = atoi(name); 717 int height = atoi(x + 1); 718 sprintf(tmp,"display {\n width %d\n height %d\n}\n", 719 width, height); 720 aconfig_load(root, strdup(tmp)); 721 path = ":"; 722 goto found_a_skin; 723 } 724 } 725 726 if (path == NULL) { 727 derror("unknown skin name '%s'", name); 728 exit(1); 729 } 730 731 sprintf(tmp, "%s/%s/layout", path, name); 732 D("trying to load skin file '%s'", tmp); 733 734 if(aconfig_load_file(root, tmp) >= 0) { 735 sprintf(tmp, "%s/%s/", path, name); 736 path = tmp; 737 goto found_a_skin; 738 } else { 739 dwarning("could not load skin file '%s', using built-in one\n", 740 tmp); 741 } 742 } 743 744 { 745 const unsigned char* layout_base; 746 size_t layout_size; 747 748 name = "<builtin>"; 749 750 layout_base = android_resource_find( "layout", &layout_size ); 751 if (layout_base != NULL) { 752 char* base = malloc( layout_size+1 ); 753 memcpy( base, layout_base, layout_size ); 754 base[layout_size] = 0; 755 756 D("parsing built-in skin layout file (size=%d)", (int)layout_size); 757 aconfig_load(root, base); 758 path = ":"; 759 } else { 760 fprintf(stderr, "Couldn't load builtin skin\n"); 761 exit(1); 762 } 763 } 764 765found_a_skin: 766 { 767 win_x = 10; 768 win_y = 10; 769 770 if (userConfig) 771 auserConfig_getWindowPos(userConfig, &win_x, &win_y); 772 } 773 774 if ( qemulator_init(qemulator_get(), root, path, win_x, win_y, opts ) < 0 ) { 775 fprintf(stderr, "### Error: could not load emulator skin '%s'\n", name); 776 exit(1); 777 } 778 779 android_skin_keycharmap = skin_keyboard_charmap_name(qemulator_get()->keyboard); 780 781 /* the default network speed and latency can now be specified by the device skin */ 782 n = aconfig_find(root, "network"); 783 if (n != NULL) { 784 skin_network_speed = aconfig_str(n, "speed", 0); 785 skin_network_delay = aconfig_str(n, "delay", 0); 786 } 787 788#if 0 789 /* create a trackball if needed */ 790 n = aconfig_find(root, "trackball"); 791 if (n != NULL) { 792 SkinTrackBallParameters params; 793 794 params.x = aconfig_unsigned(n, "x", 0); 795 params.y = aconfig_unsigned(n, "y", 0); 796 params.diameter = aconfig_unsigned(n, "diameter", 20); 797 params.ring = aconfig_unsigned(n, "ring", 1); 798 799 params.ball_color = aconfig_unsigned(n, "ball-color", 0xffe0e0e0); 800 params.dot_color = aconfig_unsigned(n, "dot-color", 0xff202020 ); 801 params.ring_color = aconfig_unsigned(n, "ring-color", 0xff000000 ); 802 803 qemu_disp->trackball = skin_trackball_create( ¶ms ); 804 skin_trackball_refresh( qemu_disp->trackball ); 805 } 806#endif 807 808 /* add an onion overlay image if needed */ 809 if (opts->onion) { 810 SkinImage* onion = skin_image_find_simple( opts->onion ); 811 int alpha, rotate; 812 813 if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) { 814 alpha = (256*alpha)/100; 815 } else 816 alpha = 128; 817 818 if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) { 819 rotate &= 3; 820 } else 821 rotate = SKIN_ROTATION_0; 822 823 qemulator_get()->onion = onion; 824 qemulator_get()->onion_alpha = alpha; 825 qemulator_get()->onion_rotation = rotate; 826 } 827} 828 829int qemu_main(int argc, char **argv); 830 831/* this function dumps the QEMU help */ 832extern void help( void ); 833extern void emulator_help( void ); 834 835#define VERBOSE_OPT(str,var) { str, &var } 836 837#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y }, 838static const struct { const char* name; int flag; const char* text; } 839verbose_options[] = { 840 VERBOSE_TAG_LIST 841 { 0, 0, 0 } 842}; 843 844int 845android_parse_network_speed(const char* speed) 846{ 847 int n; 848 char* end; 849 double sp; 850 851 if (speed == NULL || speed[0] == 0) { 852 speed = DEFAULT_NETSPEED; 853 } 854 855 for (n = 0; android_netspeeds[n].name != NULL; n++) { 856 if (!strcmp(android_netspeeds[n].name, speed)) { 857 qemu_net_download_speed = android_netspeeds[n].download; 858 qemu_net_upload_speed = android_netspeeds[n].upload; 859 return 0; 860 } 861 } 862 863 /* is this a number ? */ 864 sp = strtod(speed, &end); 865 if (end == speed) { 866 return -1; 867 } 868 869 qemu_net_download_speed = qemu_net_upload_speed = sp*1000.; 870 if (*end == ':') { 871 speed = end+1; 872 sp = strtod(speed, &end); 873 if (end > speed) { 874 qemu_net_download_speed = sp*1000.; 875 } 876 } 877 878 if (android_modem) 879 amodem_set_data_network_type( android_modem, 880 android_parse_network_type(speed) ); 881 return 0; 882} 883 884 885int 886android_parse_network_latency(const char* delay) 887{ 888 int n; 889 char* end; 890 double sp; 891 892 if (delay == NULL || delay[0] == 0) 893 delay = DEFAULT_NETDELAY; 894 895 for (n = 0; android_netdelays[n].name != NULL; n++) { 896 if ( !strcmp( android_netdelays[n].name, delay ) ) { 897 qemu_net_min_latency = android_netdelays[n].min_ms; 898 qemu_net_max_latency = android_netdelays[n].max_ms; 899 return 0; 900 } 901 } 902 903 /* is this a number ? */ 904 sp = strtod(delay, &end); 905 if (end == delay) { 906 return -1; 907 } 908 909 qemu_net_min_latency = qemu_net_max_latency = (int)sp; 910 if (*end == ':') { 911 delay = (const char*)end+1; 912 sp = strtod(delay, &end); 913 if (end > delay) { 914 qemu_net_max_latency = (int)sp; 915 } 916 } 917 return 0; 918} 919 920 921static int 922load_keyset(const char* path) 923{ 924 if (path_can_read(path)) { 925 AConfig* root = aconfig_node("",""); 926 if (!aconfig_load_file(root, path)) { 927 android_keyset = skin_keyset_new(root); 928 if (android_keyset != NULL) { 929 D( "keyset loaded from: %s", path); 930 return 0; 931 } 932 } 933 } 934 return -1; 935} 936 937static void 938parse_keyset(const char* keyset, AndroidOptions* opts) 939{ 940 char kname[MAX_PATH]; 941 char temp[MAX_PATH]; 942 char* p; 943 char* end; 944 945 /* append .keyset suffix if needed */ 946 if (strchr(keyset, '.') == NULL) { 947 p = kname; 948 end = p + sizeof(kname); 949 p = bufprint(p, end, "%s.keyset", keyset); 950 if (p >= end) { 951 derror( "keyset name too long: '%s'\n", keyset); 952 exit(1); 953 } 954 keyset = kname; 955 } 956 957 /* look for a the keyset file */ 958 p = temp; 959 end = p + sizeof(temp); 960 p = bufprint_config_file(p, end, keyset); 961 if (p < end && load_keyset(temp) == 0) 962 return; 963 964 p = temp; 965 p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset); 966 if (p < end && load_keyset(temp) == 0) 967 return; 968 969 p = temp; 970 p = bufprint_app_dir(p, end); 971 p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset); 972 if (p < end && load_keyset(temp) == 0) 973 return; 974 975 return; 976} 977 978static void 979write_default_keyset( void ) 980{ 981 char path[MAX_PATH]; 982 983 bufprint_config_file( path, path+sizeof(path), KEYSET_FILE ); 984 985 /* only write if there is no file here */ 986 if ( !path_exists(path) ) { 987 int fd = open( path, O_WRONLY | O_CREAT, 0666 ); 988 int ret; 989 const char* ks = skin_keyset_get_default(); 990 991 992 D( "writing default keyset file to %s", path ); 993 994 if (fd < 0) { 995 D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) ); 996 return; 997 } 998 CHECKED(ret, write(fd, ks, strlen(ks))); 999 close(fd); 1000 } 1001} 1002 1003#ifdef CONFIG_NAND_LIMITS 1004 1005static uint64_t 1006parse_nand_rw_limit( const char* value ) 1007{ 1008 char* end; 1009 uint64_t val = strtoul( value, &end, 0 ); 1010 1011 if (end == value) { 1012 derror( "bad parameter value '%s': expecting unsigned integer", value ); 1013 exit(1); 1014 } 1015 1016 switch (end[0]) { 1017 case 'K': val <<= 10; break; 1018 case 'M': val <<= 20; break; 1019 case 'G': val <<= 30; break; 1020 case 0: break; 1021 default: 1022 derror( "bad read/write limit suffix: use K, M or G" ); 1023 exit(1); 1024 } 1025 return val; 1026} 1027 1028static void 1029parse_nand_limits(char* limits) 1030{ 1031 int pid = -1, signal = -1; 1032 int64_t reads = 0, writes = 0; 1033 char* item = limits; 1034 1035 /* parse over comma-separated items */ 1036 while (item && *item) { 1037 char* next = strchr(item, ','); 1038 char* end; 1039 1040 if (next == NULL) { 1041 next = item + strlen(item); 1042 } else { 1043 *next++ = 0; 1044 } 1045 1046 if ( !memcmp(item, "pid=", 4) ) { 1047 pid = strtol(item+4, &end, 10); 1048 if (end == NULL || *end) { 1049 derror( "bad parameter, expecting pid=<number>, got '%s'", 1050 item ); 1051 exit(1); 1052 } 1053 if (pid <= 0) { 1054 derror( "bad parameter: process identifier must be > 0" ); 1055 exit(1); 1056 } 1057 } 1058 else if ( !memcmp(item, "signal=", 7) ) { 1059 signal = strtol(item+7,&end, 10); 1060 if (end == NULL || *end) { 1061 derror( "bad parameter: expecting signal=<number>, got '%s'", 1062 item ); 1063 exit(1); 1064 } 1065 if (signal <= 0) { 1066 derror( "bad parameter: signal number must be > 0" ); 1067 exit(1); 1068 } 1069 } 1070 else if ( !memcmp(item, "reads=", 6) ) { 1071 reads = parse_nand_rw_limit(item+6); 1072 } 1073 else if ( !memcmp(item, "writes=", 7) ) { 1074 writes = parse_nand_rw_limit(item+7); 1075 } 1076 else { 1077 derror( "bad parameter '%s' (see -help-nand-limits)", item ); 1078 exit(1); 1079 } 1080 item = next; 1081 } 1082 if (pid < 0) { 1083 derror( "bad paramater: missing pid=<number>" ); 1084 exit(1); 1085 } 1086 else if (signal < 0) { 1087 derror( "bad parameter: missing signal=<number>" ); 1088 exit(1); 1089 } 1090 else if (reads == 0 && writes == 0) { 1091 dwarning( "no read or write limit specified. ignoring -nand-limits" ); 1092 } else { 1093 nand_threshold* t; 1094 1095 t = &android_nand_read_threshold; 1096 t->pid = pid; 1097 t->signal = signal; 1098 t->counter = 0; 1099 t->limit = reads; 1100 1101 t = &android_nand_write_threshold; 1102 t->pid = pid; 1103 t->signal = signal; 1104 t->counter = 0; 1105 t->limit = writes; 1106 } 1107} 1108#endif /* CONFIG_NAND_LIMITS */ 1109 1110void emulator_help( void ) 1111{ 1112 STRALLOC_DEFINE(out); 1113 android_help_main(out); 1114 printf( "%.*s", out->n, out->s ); 1115 stralloc_reset(out); 1116 exit(1); 1117} 1118 1119static int 1120add_dns_server( const char* server_name ) 1121{ 1122 SockAddress addr; 1123 1124 if (sock_address_init_resolve( &addr, server_name, 55, 0 ) < 0) { 1125 fprintf(stderr, 1126 "### WARNING: can't resolve DNS server name '%s'\n", 1127 server_name ); 1128 return -1; 1129 } 1130 1131 D( "DNS server name '%s' resolved to %s", server_name, sock_address_to_string(&addr) ); 1132 1133 if ( slirp_add_dns_server( &addr ) < 0 ) { 1134 fprintf(stderr, 1135 "### WARNING: could not add DNS server '%s' to the network stack\n", server_name); 1136 return -1; 1137 } 1138 return 0; 1139} 1140 1141 1142/* this function is used to perform auto-detection of the 1143 * system directory in the case of a SDK installation. 1144 * 1145 * we want to deal with several historical usages, hence 1146 * the slightly complicated logic. 1147 * 1148 * NOTE: the function returns the path to the directory 1149 * containing 'fileName'. this is *not* the full 1150 * path to 'fileName'. 1151 */ 1152static char* 1153_getSdkImagePath( const char* fileName ) 1154{ 1155 char temp[MAX_PATH]; 1156 char* p = temp; 1157 char* end = p + sizeof(temp); 1158 char* q; 1159 char* app; 1160 1161 static const char* const searchPaths[] = { 1162 "", /* program's directory */ 1163 "/lib/images", /* this is for SDK 1.0 */ 1164 "/../platforms/android-1.1/images", /* this is for SDK 1.1 */ 1165 NULL 1166 }; 1167 1168 app = bufprint_app_dir(temp, end); 1169 if (app >= end) 1170 return NULL; 1171 1172 do { 1173 int nn; 1174 1175 /* first search a few well-known paths */ 1176 for (nn = 0; searchPaths[nn] != NULL; nn++) { 1177 p = bufprint(app, end, "%s", searchPaths[nn]); 1178 q = bufprint(p, end, "/%s", fileName); 1179 if (q < end && path_exists(temp)) { 1180 *p = 0; 1181 goto FOUND_IT; 1182 } 1183 } 1184 1185 /* hmmm. let's assume that we are in a post-1.1 SDK 1186 * scan ../platforms if it exists 1187 */ 1188 p = bufprint(app, end, "/../platforms"); 1189 if (p < end) { 1190 DirScanner* scanner = dirScanner_new(temp); 1191 if (scanner != NULL) { 1192 int found = 0; 1193 const char* subdir; 1194 1195 for (;;) { 1196 subdir = dirScanner_next(scanner); 1197 if (!subdir) break; 1198 1199 q = bufprint(p, end, "/%s/images/%s", subdir, fileName); 1200 if (q >= end || !path_exists(temp)) 1201 continue; 1202 1203 found = 1; 1204 p = bufprint(p, end, "/%s/images", subdir); 1205 break; 1206 } 1207 dirScanner_free(scanner); 1208 if (found) 1209 break; 1210 } 1211 } 1212 1213 /* I'm out of ideas */ 1214 return NULL; 1215 1216 } while (0); 1217 1218FOUND_IT: 1219 //D("image auto-detection: %s/%s", temp, fileName); 1220 return qemu_strdup(temp); 1221} 1222 1223static char* 1224_getSdkImage( const char* path, const char* file ) 1225{ 1226 char temp[MAX_PATH]; 1227 char *p = temp, *end = p + sizeof(temp); 1228 1229 p = bufprint(temp, end, "%s/%s", path, file); 1230 if (p >= end || !path_exists(temp)) 1231 return NULL; 1232 1233 return qemu_strdup(temp); 1234} 1235 1236static char* 1237_getSdkSystemImage( const char* path, const char* optionName, const char* file ) 1238{ 1239 char* image = _getSdkImage(path, file); 1240 1241 if (image == NULL) { 1242 derror("Your system directory is missing the '%s' image file.\n" 1243 "Please specify one with the '%s <filepath>' option", 1244 file, optionName); 1245 exit(2); 1246 } 1247 return image; 1248} 1249 1250static void 1251_forceAvdImagePath( AvdImageType imageType, 1252 const char* path, 1253 const char* description, 1254 int required ) 1255{ 1256 if (path == NULL) 1257 return; 1258 1259 if (required && !path_exists(path)) { 1260 derror("Cannot find %s image file: %s", description, path); 1261 exit(1); 1262 } 1263 android_avdParams->forcePaths[imageType] = path; 1264} 1265 1266static uint64_t 1267_adjustPartitionSize( const char* description, 1268 uint64_t imageBytes, 1269 uint64_t defaultBytes, 1270 int inAndroidBuild ) 1271{ 1272 char temp[64]; 1273 unsigned imageMB; 1274 unsigned defaultMB; 1275 1276 if (imageBytes <= defaultBytes) 1277 return defaultBytes; 1278 1279 imageMB = convertBytesToMB(imageBytes); 1280 defaultMB = convertBytesToMB(defaultBytes); 1281 1282 if (imageMB > defaultMB) { 1283 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB); 1284 } else { 1285 snprintf(temp, sizeof temp, "(%lld bytes > %lld bytes)", imageBytes, defaultBytes); 1286 } 1287 1288 if (inAndroidBuild) { 1289 dwarning("%s partition size adjusted to match image file %s\n", description, temp); 1290 } 1291 1292 return convertMBToBytes(imageMB); 1293} 1294 1295 1296int main(int argc, char **argv) 1297{ 1298 char tmp[MAX_PATH]; 1299 char* tmpend = tmp + sizeof(tmp); 1300 char* args[128]; 1301 int n; 1302 char* opt; 1303 int use_sdcard_img = 0; 1304 int serial = 0; 1305 int gps_serial = 0; 1306 int radio_serial = 0; 1307 int qemud_serial = 0; 1308 int shell_serial = 0; 1309 int dns_count = 0; 1310 unsigned cachePartitionSize = 0; 1311 unsigned systemPartitionSize = 0; 1312 unsigned dataPartitionSize = 0; 1313 unsigned defaultPartitionSize = convertMBToBytes(66); 1314 1315 AndroidHwConfig* hw; 1316 AvdInfo* avd; 1317 1318 //const char *appdir = get_app_dir(); 1319 char* android_build_root = NULL; 1320 char* android_build_out = NULL; 1321 1322 AndroidOptions opts[1]; 1323 1324 args[0] = argv[0]; 1325 1326 if ( android_parse_options( &argc, &argv, opts ) < 0 ) { 1327 exit(1); 1328 } 1329 1330 while (argc-- > 1) { 1331 opt = (++argv)[0]; 1332 1333 if(!strcmp(opt, "-qemu")) { 1334 argc--; 1335 argv++; 1336 break; 1337 } 1338 1339 if (!strcmp(opt, "-help")) { 1340 emulator_help(); 1341 } 1342 1343 if (!strncmp(opt, "-help-",6)) { 1344 STRALLOC_DEFINE(out); 1345 opt += 6; 1346 1347 if (!strcmp(opt, "all")) { 1348 android_help_all(out); 1349 } 1350 else if (android_help_for_option(opt, out) == 0) { 1351 /* ok */ 1352 } 1353 else if (android_help_for_topic(opt, out) == 0) { 1354 /* ok */ 1355 } 1356 if (out->n > 0) { 1357 printf("\n%.*s", out->n, out->s); 1358 exit(0); 1359 } 1360 1361 fprintf(stderr, "unknown option: -help-%s\n", opt); 1362 fprintf(stderr, "please use -help for a list of valid topics\n"); 1363 exit(1); 1364 } 1365 1366 if (opt[0] == '-') { 1367 fprintf(stderr, "unknown option: %s\n", opt); 1368 fprintf(stderr, "please use -help for a list of valid options\n"); 1369 exit(1); 1370 } 1371 1372 fprintf(stderr, "invalid command-line parameter: %s.\n", opt); 1373 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n"); 1374 fprintf(stderr, "please use -help for more information\n"); 1375 exit(1); 1376 } 1377 1378 /* special case, if -qemu -h is used, directly invoke the QEMU-specific help */ 1379 if (argc > 0) { 1380 int nn; 1381 for (nn = 0; nn < argc; nn++) 1382 if (!strcmp(argv[nn], "-h")) { 1383 qemu_help(0); 1384 break; 1385 } 1386 } 1387 1388 if (android_charmap_setup(opts->charmap)) { 1389 exit(1); 1390 } 1391 1392 if (opts->version) { 1393 printf("Android emulator version %s\n" 1394 "Copyright (C) 2006-2008 The Android Open Source Project and many others.\n" 1395 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n", 1396#if defined ANDROID_BUILD_ID 1397 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" ); 1398#else 1399 VERSION_STRING); 1400#endif 1401 printf(" This software is licensed under the terms of the GNU General Public\n" 1402 " License version 2, as published by the Free Software Foundation, and\n" 1403 " may be copied, distributed, and modified under those terms.\n\n" 1404 " This program is distributed in the hope that it will be useful,\n" 1405 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 1406 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 1407 " GNU General Public License for more details.\n\n"); 1408 1409 exit(0); 1410 } 1411 1412 if (opts->timezone) { 1413 if ( timezone_set(opts->timezone) < 0 ) { 1414 fprintf(stderr, "emulator: it seems the timezone '%s' is not in zoneinfo format\n", opts->timezone); 1415 } 1416 } 1417 1418 /* legacy support: we used to use -system <dir> and -image <file> 1419 * instead of -sysdir <dir> and -system <file>, so handle this by checking 1420 * whether the options point to directories or files. 1421 */ 1422 if (opts->image != NULL) { 1423 if (opts->system != NULL) { 1424 if (opts->sysdir != NULL) { 1425 derror( "You can't use -sysdir, -system and -image at the same time.\n" 1426 "You should probably use '-sysdir <path> -system <file>'.\n" ); 1427 exit(2); 1428 } 1429 } 1430 dwarning( "Please note that -image is obsolete and that -system is now used to point\n" 1431 "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" ); 1432 opts->sysdir = opts->system; 1433 opts->system = opts->image; 1434 opts->image = NULL; 1435 } 1436 else if (opts->system != NULL && path_is_dir(opts->system)) { 1437 if (opts->sysdir != NULL) { 1438 derror( "Option -system should now be followed by a file path, not a directory one.\n" 1439 "Please use '-sysdir <path>' to point to the system directory.\n" ); 1440 exit(1); 1441 } 1442 dwarning( "Please note that the -system option should now be used to point to the initial\n" 1443 "system image (like the obsolete -image option). To point to the system directory\n" 1444 "please now use '-sysdir <path>' instead.\n" ); 1445 1446 opts->sysdir = opts->system; 1447 opts->system = NULL; 1448 } 1449 1450 if (opts->nojni) 1451 opts->no_jni = opts->nojni; 1452 1453 if (opts->nocache) 1454 opts->no_cache = opts->nocache; 1455 1456 if (opts->noaudio) 1457 opts->no_audio = opts->noaudio; 1458 1459 if (opts->noskin) 1460 opts->no_skin = opts->noskin; 1461 1462 if (opts->initdata) { 1463 opts->init_data = opts->initdata; 1464 opts->initdata = NULL; 1465 } 1466 1467 /* If no AVD name was given, try to find the top of the 1468 * Android build tree 1469 */ 1470 if (opts->avd == NULL) { 1471 do { 1472 char* out = getenv("ANDROID_PRODUCT_OUT"); 1473 1474 if (out == NULL || out[0] == 0) 1475 break; 1476 1477 if (!path_exists(out)) { 1478 derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n" 1479 "You need to build the Android system before launching the emulator", 1480 out); 1481 exit(2); 1482 } 1483 1484 android_build_root = path_parent( out, 4 ); 1485 if (android_build_root == NULL || !path_exists(android_build_root)) { 1486 derror("Can't find the Android build root from '%s'\n" 1487 "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n" 1488 "It should point to your product-specific build output directory.\n", 1489 out ); 1490 exit(2); 1491 } 1492 android_build_out = out; 1493 D( "found Android build root: %s", android_build_root ); 1494 D( "found Android build out: %s", android_build_out ); 1495 } while (0); 1496 } 1497 /* if no virtual device name is given, and we're not in the 1498 * Android build system, we'll need to perform some auto-detection 1499 * magic :-) 1500 */ 1501 if (opts->avd == NULL && !android_build_out) 1502 { 1503 char dataDirIsSystem = 0; 1504 1505 if (!opts->sysdir) { 1506 opts->sysdir = _getSdkImagePath("system.img"); 1507 if (!opts->sysdir) { 1508 derror( 1509 "You did not specify a virtual device name, and the system\n" 1510 "directory could not be found.\n\n" 1511 "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n" 1512 "to start a given virtual device (see -help-avd for details).\n\n" 1513 1514 "Otherwise, follow the instructions in -help-disk-images to start the emulator\n" 1515 ); 1516 exit(2); 1517 } 1518 D("autoconfig: -sysdir %s", opts->sysdir); 1519 } 1520 1521 if (!opts->system) { 1522 opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img"); 1523 D("autoconfig: -image %s", opts->image); 1524 } 1525 1526 if (!opts->kernel) { 1527 opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu"); 1528 D("autoconfig: -kernel %s", opts->kernel); 1529 } 1530 1531 if (!opts->ramdisk) { 1532 opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img"); 1533 D("autoconfig: -ramdisk %s", opts->ramdisk); 1534 } 1535 1536 /* if no data directory is specified, use the system directory */ 1537 if (!opts->datadir) { 1538 opts->datadir = qemu_strdup(opts->sysdir); 1539 dataDirIsSystem = 1; 1540 D("autoconfig: -datadir %s", opts->sysdir); 1541 } 1542 1543 if (!opts->data) { 1544 /* check for userdata-qemu.img in the data directory */ 1545 bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir); 1546 if (!path_exists(tmp)) { 1547 derror( 1548 "You did not provide the name of an Android Virtual Device\n" 1549 "with the '-avd <name>' option. Read -help-avd for more information.\n\n" 1550 1551 "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n" 1552 "to specify a data partition image file (I hope you know what you're doing).\n" 1553 ); 1554 exit(2); 1555 } 1556 1557 opts->data = qemu_strdup(tmp); 1558 D("autoconfig: -data %s", opts->data); 1559 } 1560 1561 if (!opts->sdcard && opts->datadir) { 1562 bufprint(tmp, tmpend, "%s/sdcard.img", opts->datadir); 1563 if (path_exists(tmp)) { 1564 opts->sdcard = qemu_strdup(tmp); 1565 D("autoconfig: -sdcard %s", opts->sdcard); 1566 } 1567 } 1568 } 1569 1570 /* setup the virtual device parameters from our options 1571 */ 1572 if (opts->no_cache) { 1573 android_avdParams->flags |= AVDINFO_NO_CACHE; 1574 } 1575 if (opts->wipe_data) { 1576 android_avdParams->flags |= AVDINFO_WIPE_DATA | AVDINFO_WIPE_CACHE; 1577 } 1578 1579 /* if certain options are set, we can force the path of 1580 * certain kernel/disk image files 1581 */ 1582 _forceAvdImagePath(AVD_IMAGE_KERNEL, opts->kernel, "kernel", 1); 1583 _forceAvdImagePath(AVD_IMAGE_INITSYSTEM, opts->system, "system", 1); 1584 _forceAvdImagePath(AVD_IMAGE_RAMDISK, opts->ramdisk,"ramdisk", 1); 1585 _forceAvdImagePath(AVD_IMAGE_USERDATA, opts->data, "user data", 0); 1586 _forceAvdImagePath(AVD_IMAGE_CACHE, opts->cache, "cache", 0); 1587 _forceAvdImagePath(AVD_IMAGE_SDCARD, opts->sdcard, "SD Card", 0); 1588 1589 /* we don't accept -skindir without -skin now 1590 * to simplify the autoconfig stuff with virtual devices 1591 */ 1592 if (opts->no_skin) { 1593 opts->skin = "320x480"; 1594 opts->skindir = NULL; 1595 } 1596 1597 if (opts->skindir) { 1598 if (!opts->skin) { 1599 derror( "the -skindir <path> option requires a -skin <name> option"); 1600 exit(1); 1601 } 1602 } 1603 android_avdParams->skinName = opts->skin; 1604 android_avdParams->skinRootPath = opts->skindir; 1605 1606 /* setup the virtual device differently depending on whether 1607 * we are in the Android build system or not 1608 */ 1609 if (opts->avd != NULL) 1610 { 1611 android_avdInfo = avdInfo_new( opts->avd, android_avdParams ); 1612 if (android_avdInfo == NULL) { 1613 /* an error message has already been printed */ 1614 dprint("could not find virtual device named '%s'", opts->avd); 1615 exit(1); 1616 } 1617 } 1618 else 1619 { 1620 if (!android_build_out) { 1621 android_build_out = android_build_root = opts->sysdir; 1622 } 1623 android_avdInfo = avdInfo_newForAndroidBuild( 1624 android_build_root, 1625 android_build_out, 1626 android_avdParams ); 1627 1628 if(android_avdInfo == NULL) { 1629 D("could not start virtual device\n"); 1630 exit(1); 1631 } 1632 } 1633 1634 avd = android_avdInfo; 1635 1636 /* get the skin from the virtual device configuration */ 1637 opts->skin = (char*) avdInfo_getSkinName( avd ); 1638 opts->skindir = (char*) avdInfo_getSkinDir( avd ); 1639 1640 if (opts->skin) { 1641 D("autoconfig: -skin %s", opts->skin); 1642 } 1643 if (opts->skindir) { 1644 D("autoconfig: -skindir %s", opts->skindir); 1645 } 1646 1647 /* Read hardware configuration */ 1648 hw = android_hw; 1649 if (avdInfo_getHwConfig(avd, hw) < 0) { 1650 derror("could not read hardware configuration ?"); 1651 exit(1); 1652 } 1653 1654#ifdef CONFIG_NAND_LIMITS 1655 if (opts->nand_limits) 1656 parse_nand_limits(opts->nand_limits); 1657#endif 1658 1659 if (opts->keyset) { 1660 parse_keyset(opts->keyset, opts); 1661 if (!android_keyset) { 1662 fprintf(stderr, 1663 "emulator: WARNING: could not find keyset file named '%s'," 1664 " using defaults instead\n", 1665 opts->keyset); 1666 } 1667 } 1668 if (!android_keyset) { 1669 parse_keyset("default", opts); 1670 if (!android_keyset) { 1671 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() ); 1672 if (!android_keyset) { 1673 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" ); 1674 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" ); 1675 exit(1); 1676 } 1677 if (!opts->keyset) 1678 write_default_keyset(); 1679 } 1680 } 1681 1682 /* the purpose of -no-audio is to disable sound output from the emulator, 1683 * not to disable Audio emulation. So simply force the 'none' backends */ 1684 if (opts->no_audio) 1685 opts->audio = "none"; 1686 1687 if (opts->audio) { 1688 if (opts->audio_in || opts->audio_out) { 1689 derror( "you can't use -audio with -audio-in or -audio-out\n" ); 1690 exit(1); 1691 } 1692 if ( !audio_check_backend_name( 0, opts->audio ) ) { 1693 derror( "'%s' is not a valid audio output backend. see -help-audio-out\n", 1694 opts->audio); 1695 exit(1); 1696 } 1697 opts->audio_out = opts->audio; 1698 opts->audio_in = opts->audio; 1699 1700 if ( !audio_check_backend_name( 1, opts->audio ) ) { 1701 fprintf(stderr, 1702 "emulator: warning: '%s' is not a valid audio input backend. audio record disabled\n", 1703 opts->audio); 1704 opts->audio_in = "none"; 1705 } 1706 } 1707 1708 if (opts->audio_in) { 1709 static char env[64]; /* note: putenv needs a static unique string buffer */ 1710 if ( !audio_check_backend_name( 1, opts->audio_in ) ) { 1711 derror( "'%s' is not a valid audio input backend. see -help-audio-in\n", 1712 opts->audio_in); 1713 exit(1); 1714 } 1715 bufprint( env, env+sizeof(env), "QEMU_AUDIO_IN_DRV=%s", opts->audio_in ); 1716 putenv( env ); 1717 1718 if (!hw->hw_audioInput) { 1719 dwarning( "Emulated hardware doesn't have audio input."); 1720 } 1721 } 1722 if (opts->audio_out) { 1723 static char env[64]; /* note: putenv needs a static unique string buffer */ 1724 if ( !audio_check_backend_name( 0, opts->audio_out ) ) { 1725 derror( "'%s' is not a valid audio output backend. see -help-audio-out\n", 1726 opts->audio_out); 1727 exit(1); 1728 } 1729 bufprint( env, env+sizeof(env), "QEMU_AUDIO_OUT_DRV=%s", opts->audio_out ); 1730 putenv( env ); 1731 if (!hw->hw_audioOutput) { 1732 dwarning( "Emulated hardware doesn't have audio output"); 1733 } 1734 } 1735 1736 if (opts->cpu_delay) { 1737 char* end; 1738 long delay = strtol(opts->cpu_delay, &end, 0); 1739 if (end == NULL || *end || delay < 0 || delay > 1000 ) { 1740 fprintf(stderr, "option -cpu-delay must be an integer between 0 and 1000\n" ); 1741 exit(1); 1742 } 1743 if (delay > 0) 1744 delay = (1000-delay); 1745 1746 qemu_cpu_delay = (int) delay; 1747 } 1748 1749 if (opts->shared_net_id) { 1750 char* end; 1751 long shared_net_id = strtol(opts->shared_net_id, &end, 0); 1752 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) { 1753 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n"); 1754 exit(1); 1755 } 1756 char ip[11]; 1757 snprintf(ip, 11, "10.1.2.%ld", shared_net_id); 1758 boot_property_add("net.shared_net_ip",ip); 1759 } 1760 1761 1762 emulator_config_init(); 1763 init_skinned_ui(opts->skindir, opts->skin, opts); 1764 1765 if (!opts->netspeed) { 1766 if (skin_network_speed) 1767 D("skin network speed: '%s'", skin_network_speed); 1768 opts->netspeed = (char*)skin_network_speed; 1769 } 1770 if (!opts->netdelay) { 1771 if (skin_network_delay) 1772 D("skin network delay: '%s'", skin_network_delay); 1773 opts->netdelay = (char*)skin_network_delay; 1774 } 1775 1776 if ( android_parse_network_speed(opts->netspeed) < 0 ) { 1777 fprintf(stderr, "invalid -netspeed parameter '%s', see emulator -usage\n", opts->netspeed); 1778 emulator_help(); 1779 } 1780 1781 if ( android_parse_network_latency(opts->netdelay) < 0 ) { 1782 fprintf(stderr, "invalid -netdelay parameter '%s', see emulator -usage\n", opts->netdelay); 1783 emulator_help(); 1784 } 1785 1786 if (opts->netfast) { 1787 qemu_net_download_speed = 0; 1788 qemu_net_upload_speed = 0; 1789 qemu_net_min_latency = 0; 1790 qemu_net_max_latency = 0; 1791 } 1792 1793 if (opts->trace) { 1794 char* tracePath = avdInfo_getTracePath(avd, opts->trace); 1795 int ret; 1796 1797 if (tracePath == NULL) { 1798 derror( "bad -trace parameter" ); 1799 exit(1); 1800 } 1801 ret = path_mkdir_if_needed( tracePath, 0755 ); 1802 if (ret < 0) { 1803 fprintf(stderr, "could not create directory '%s'\n", tmp); 1804 exit(2); 1805 } 1806 opts->trace = tracePath; 1807 } 1808 1809#ifdef CONFIG_MEMCHECK 1810 if (opts->memcheck) { 1811 memcheck_init(opts->memcheck); 1812 } 1813#endif // CONFIG_MEMCHECK 1814 1815 if (opts->tcpdump) { 1816 if (qemu_tcpdump_start(opts->tcpdump) < 0) { 1817 dwarning( "could not start packet capture: %s", strerror(errno)); 1818 } 1819 } 1820 1821 if (opts->no_cache) 1822 opts->cache = 0; 1823 1824 if (opts->dns_server) { 1825 char* x = strchr(opts->dns_server, ','); 1826 dns_count = 0; 1827 if (x == NULL) 1828 { 1829 if ( add_dns_server( opts->dns_server ) == 0 ) 1830 dns_count = 1; 1831 } 1832 else 1833 { 1834 x = strdup(opts->dns_server); 1835 while (*x) { 1836 char* y = strchr(x, ','); 1837 1838 if (y != NULL) 1839 *y = 0; 1840 1841 if (y == NULL || y > x) { 1842 if ( add_dns_server( x ) == 0 ) 1843 dns_count += 1; 1844 } 1845 1846 if (y == NULL) 1847 break; 1848 1849 x = y+1; 1850 } 1851 } 1852 if (dns_count == 0) 1853 fprintf( stderr, "### WARNING: will use system default DNS server\n" ); 1854 } 1855 1856 if (dns_count == 0) 1857 dns_count = slirp_get_system_dns_servers(); 1858 1859 n = 1; 1860 /* generate arguments for the underlying qemu main() */ 1861 { 1862 const char* kernelFile = avdInfo_getImageFile(avd, AVD_IMAGE_KERNEL); 1863 int kernelFileLen = strlen(kernelFile); 1864 1865 args[n++] = "-kernel"; 1866 args[n++] = (char*)kernelFile; 1867 1868 /* If the kernel image name ends in "-armv7", then change the cpu 1869 * type automatically. This is a poor man's approach to configuration 1870 * management, but should allow us to get past building ARMv7 1871 * system images with dex preopt pass without introducing too many 1872 * changes to the emulator sources. 1873 * 1874 * XXX: 1875 * A 'proper' change would require adding some sort of hardware-property 1876 * to each AVD config file, then automatically determine its value for 1877 * full Android builds (depending on some environment variable), plus 1878 * some build system changes. I prefer not to do that for now for reasons 1879 * of simplicity. 1880 */ 1881 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) { 1882 args[n++] = "-cpu"; 1883 args[n++] = "cortex-a8"; 1884 } 1885 } 1886 1887 args[n++] = "-initrd"; 1888 args[n++] = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_RAMDISK); 1889 1890 if (opts->partition_size) { 1891 char* end; 1892 long sizeMB = strtol(opts->partition_size, &end, 0); 1893 long minSizeMB = 10; 1894 long maxSizeMB = LONG_MAX / ONE_MB; 1895 1896 if (sizeMB < 0 || *end != 0) { 1897 derror( "-partition-size must be followed by a positive integer" ); 1898 exit(1); 1899 } 1900 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) { 1901 derror( "partition-size (%d) must be between %dMB and %dMB", 1902 sizeMB, minSizeMB, maxSizeMB ); 1903 exit(1); 1904 } 1905 defaultPartitionSize = sizeMB * ONE_MB; 1906 } 1907 1908 /* Check the size of the system partition image. 1909 * If we have an AVD, it must be smaller than 1910 * the disk.systemPartition.size hardware property. 1911 * 1912 * Otherwise, we need to adjust the systemPartitionSize 1913 * automatically, and print a warning. 1914 * 1915 */ 1916 { 1917 uint64_t systemBytes = avdInfo_getImageFileSize(avd, AVD_IMAGE_INITSYSTEM); 1918 uint64_t defaultBytes = defaultPartitionSize; 1919 1920 if (defaultBytes == 0 || opts->partition_size) 1921 defaultBytes = defaultPartitionSize; 1922 1923 systemPartitionSize = _adjustPartitionSize("system", systemBytes, defaultBytes, 1924 android_build_out != NULL); 1925 } 1926 1927 /* Check the size of the /data partition. The only interesting cases here are: 1928 * - when the USERDATA image already exists and is larger than the default 1929 * - when we're wiping data and the INITDATA is larger than the default. 1930 */ 1931 1932 { 1933 const char* dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA); 1934 uint64_t defaultBytes = defaultPartitionSize; 1935 1936 if (defaultBytes == 0 || opts->partition_size) 1937 defaultBytes = defaultPartitionSize; 1938 1939 if (dataPath == NULL || !path_exists(dataPath) || opts->wipe_data) { 1940 dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_INITDATA); 1941 } 1942 if (dataPath == NULL || !path_exists(dataPath)) { 1943 dataPartitionSize = defaultBytes; 1944 } 1945 else { 1946 uint64_t dataBytes; 1947 path_get_size(dataPath, &dataBytes); 1948 1949 dataPartitionSize = _adjustPartitionSize("data", dataBytes, defaultBytes, 1950 android_build_out != NULL); 1951 } 1952 } 1953 1954 { 1955 const char* filetype = "file"; 1956 1957 if (avdInfo_isImageReadOnly(avd, AVD_IMAGE_INITSYSTEM)) 1958 filetype = "initfile"; 1959 1960 bufprint(tmp, tmpend, 1961 "system,size=0x%x,%s=%s", systemPartitionSize, filetype, 1962 avdInfo_getImageFile(avd, AVD_IMAGE_INITSYSTEM)); 1963 1964 args[n++] = "-nand"; 1965 args[n++] = strdup(tmp); 1966 } 1967 1968 bufprint(tmp, tmpend, 1969 "userdata,size=0x%x,file=%s", 1970 dataPartitionSize, 1971 avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA)); 1972 1973 args[n++] = "-nand"; 1974 args[n++] = strdup(tmp); 1975 1976 if (hw->disk_cachePartition) { 1977 opts->cache = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_CACHE); 1978 cachePartitionSize = hw->disk_cachePartition_size; 1979 } 1980 else if (opts->cache) { 1981 dwarning( "Emulated hardware doesn't support a cache partition" ); 1982 opts->cache = NULL; 1983 opts->no_cache = 1; 1984 } 1985 1986 if (opts->cache) { 1987 /* use a specific cache file */ 1988 sprintf(tmp, "cache,size=0x%0x,file=%s", cachePartitionSize, opts->cache); 1989 args[n++] = "-nand"; 1990 args[n++] = strdup(tmp); 1991 } 1992 else if (!opts->no_cache) { 1993 /* create a temporary cache partition file */ 1994 sprintf(tmp, "cache,size=0x%0x", cachePartitionSize); 1995 args[n++] = "-nand"; 1996 args[n++] = strdup(tmp); 1997 } 1998 1999 if (hw->hw_sdCard != 0) 2000 opts->sdcard = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SDCARD); 2001 else if (opts->sdcard) { 2002 dwarning( "Emulated hardware doesn't support SD Cards" ); 2003 opts->sdcard = NULL; 2004 } 2005 2006 if(opts->sdcard) { 2007 uint64_t size; 2008 if (path_get_size(opts->sdcard, &size) == 0) { 2009 /* see if we have an sdcard image. get its size if it exists */ 2010 /* due to what looks like limitations of the MMC protocol, one has 2011 * to use an SD Card image that is equal or larger than 9 MB 2012 */ 2013 if (size < 9*1024*1024ULL) { 2014 fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard); 2015 } else { 2016 args[n++] = "-hda"; 2017 args[n++] = opts->sdcard; 2018 use_sdcard_img = 1; 2019 } 2020 } else { 2021 D("no SD Card image at '%s'", opts->sdcard); 2022 } 2023 } 2024 2025 if (!opts->logcat || opts->logcat[0] == 0) { 2026 opts->logcat = getenv("ANDROID_LOG_TAGS"); 2027 if (opts->logcat && opts->logcat[0] == 0) 2028 opts->logcat = NULL; 2029 } 2030 2031#if 0 2032 if (opts->console) { 2033 derror( "option -console is obsolete. please use -shell instead" ); 2034 exit(1); 2035 } 2036#endif 2037 2038 /* we always send the kernel messages from ttyS0 to android_kmsg */ 2039 { 2040 AndroidKmsgFlags flags = 0; 2041 2042 if (opts->show_kernel) 2043 flags |= ANDROID_KMSG_PRINT_MESSAGES; 2044 2045 android_kmsg_init( flags ); 2046 args[n++] = "-serial"; 2047 args[n++] = "android-kmsg"; 2048 serial++; 2049 } 2050 2051 /* XXXX: TODO: implement -shell and -logcat through qemud instead */ 2052 if (!opts->shell_serial) { 2053#ifdef _WIN32 2054 opts->shell_serial = "con:"; 2055#else 2056 opts->shell_serial = "stdio"; 2057#endif 2058 } 2059 else 2060 opts->shell = 1; 2061 2062 if (opts->shell || opts->logcat) { 2063 args[n++] = "-serial"; 2064 args[n++] = opts->shell_serial; 2065 shell_serial = serial++; 2066 } 2067 2068 if (opts->old_system) 2069 { 2070 if (opts->radio) { 2071 args[n++] = "-serial"; 2072 args[n++] = opts->radio; 2073 radio_serial = serial++; 2074 } 2075 else { 2076 args[n++] = "-serial"; 2077 args[n++] = "android-modem"; 2078 radio_serial = serial++; 2079 } 2080 if (opts->gps) { 2081 args[n++] = "-serial"; 2082 args[n++] = opts->gps; 2083 gps_serial = serial++; 2084 } 2085 } 2086 else /* !opts->old_system */ 2087 { 2088 args[n++] = "-serial"; 2089 args[n++] = "android-qemud"; 2090 qemud_serial = serial++; 2091 2092 if (opts->radio) { 2093 CharDriverState* cs = qemu_chr_open("radio",opts->radio,NULL); 2094 if (cs == NULL) { 2095 derror( "unsupported character device specification: %s\n" 2096 "used -help-char-devices for list of available formats\n", opts->radio ); 2097 exit(1); 2098 } 2099 android_qemud_set_channel( ANDROID_QEMUD_GSM, cs); 2100 } 2101 else if ( hw->hw_gsmModem != 0 ) { 2102 if ( android_qemud_get_channel( ANDROID_QEMUD_GSM, &android_modem_cs ) < 0 ) { 2103 derror( "could not initialize qemud 'gsm' channel" ); 2104 exit(1); 2105 } 2106 } 2107 2108 if (opts->gps) { 2109 CharDriverState* cs = qemu_chr_open("gps",opts->gps,NULL); 2110 if (cs == NULL) { 2111 derror( "unsupported character device specification: %s\n" 2112 "used -help-char-devices for list of available formats\n", opts->gps ); 2113 exit(1); 2114 } 2115 android_qemud_set_channel( ANDROID_QEMUD_GPS, cs); 2116 } 2117 else if ( hw->hw_gps != 0 ) { 2118 if ( android_qemud_get_channel( "gps", &android_gps_cs ) < 0 ) { 2119 derror( "could not initialize qemud 'gps' channel" ); 2120 exit(1); 2121 } 2122 } 2123 } 2124 2125 if (opts->memory) { 2126 char* end; 2127 long ramSize = strtol(opts->memory, &end, 0); 2128 if (ramSize < 0 || *end != 0) { 2129 derror( "-memory must be followed by a positive integer" ); 2130 exit(1); 2131 } 2132 if (ramSize < 32 || ramSize > 4096) { 2133 derror( "physical memory size must be between 32 and 4096 MB" ); 2134 exit(1); 2135 } 2136 } 2137 if (!opts->memory) { 2138 bufprint(tmp, tmpend, "%d", hw->hw_ramSize); 2139 opts->memory = qemu_strdup(tmp); 2140 } 2141 2142 if (opts->trace) { 2143 args[n++] = "-trace"; 2144 args[n++] = opts->trace; 2145 args[n++] = "-tracing"; 2146 args[n++] = "off"; 2147 } 2148 2149 args[n++] = "-append"; 2150 2151 if (opts->bootchart) { 2152 char* end; 2153 int timeout = strtol(opts->bootchart, &end, 10); 2154 if (timeout == 0) 2155 opts->bootchart = NULL; 2156 else if (timeout < 0 || timeout > 15*60) { 2157 derror( "timeout specified for -bootchart option is invalid.\n" 2158 "please use integers between 1 and 900\n"); 2159 exit(1); 2160 } 2161 } 2162 2163 /* start the 'boot-properties service, and parse the -prop 2164 * options, if any. 2165 */ 2166 boot_property_init_service(); 2167 2168 hwLcd_setBootProperty(get_device_dpi(opts)); 2169 2170 /* Set the VM's max heap size, passed as a boot property */ 2171 if (hw->vm_heapSize > 0) { 2172 char tmp[32], *p=tmp, *end=p + sizeof(tmp); 2173 p = bufprint(p, end, "%dm", hw->vm_heapSize); 2174 2175 boot_property_add("dalvik.vm.heapsize",tmp); 2176 } 2177 2178 if (opts->prop != NULL) { 2179 ParamList* pl = opts->prop; 2180 for ( ; pl != NULL; pl = pl->next ) { 2181 boot_property_parse_option(pl->param); 2182 } 2183 } 2184 2185 /* Setup the kernel init options 2186 */ 2187 { 2188 static char params[1024]; 2189 char *p = params, *end = p + sizeof(params); 2190 2191 p = bufprint(p, end, "qemu=1 console=ttyS0" ); 2192 2193 if (opts->shell || opts->logcat) { 2194 p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial ); 2195 } 2196 2197 if (opts->trace) { 2198 p = bufprint(p, end, " android.tracing=1"); 2199 } 2200 2201#ifdef CONFIG_MEMCHECK 2202 if (opts->memcheck) { 2203 /* This will set ro.kernel.memcheck system property 2204 * to memcheck's tracing flags. */ 2205 p = bufprint(p, end, " memcheck=%s", opts->memcheck); 2206 } 2207#endif // CONFIG_MEMCHECK 2208 2209 if (!opts->no_jni) { 2210 p = bufprint(p, end, " android.checkjni=1"); 2211 } 2212 2213 if (opts->no_boot_anim) { 2214 p = bufprint( p, end, " android.bootanim=0" ); 2215 } 2216 2217 if (opts->logcat) { 2218 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat); 2219 2220 if (q < end) { 2221 /* replace any space by a comma ! */ 2222 { 2223 int nn; 2224 for (nn = 1; p[nn] != 0; nn++) 2225 if (p[nn] == ' ' || p[nn] == '\t') 2226 p[nn] = ','; 2227 p += nn; 2228 } 2229 } 2230 p = q; 2231 } 2232 2233 if (opts->old_system) 2234 { 2235 p = bufprint(p, end, " android.ril=ttyS%d", radio_serial); 2236 2237 if (opts->gps) { 2238 p = bufprint(p, end, " android.gps=ttyS%d", gps_serial); 2239 } 2240 } 2241 else 2242 { 2243 p = bufprint(p, end, " android.qemud=ttyS%d", qemud_serial); 2244 } 2245 2246 if (dns_count > 0) { 2247 p = bufprint(p, end, " android.ndns=%d", dns_count); 2248 } 2249 2250 if (opts->bootchart) { 2251 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart); 2252 } 2253 2254 if (p >= end) { 2255 fprintf(stderr, "### ERROR: kernel parameters too long\n"); 2256 exit(1); 2257 } 2258 2259 args[n++] = strdup(params); 2260 } 2261 2262 /* physical memory */ 2263 args[n++] = "-m"; 2264 args[n++] = opts->memory; 2265 2266 /* on Linux, the 'dynticks' clock sometimes doesn't work 2267 * properly. this results in the UI freezing while emulation 2268 * continues, for several seconds... 2269 */ 2270#ifdef __linux__ 2271 args[n++] = "-clock"; 2272 args[n++] = "unix"; 2273#endif 2274 2275 /* Set up the interfaces for inter-emulator networking */ 2276 if (opts->shared_net_id) { 2277 unsigned int shared_net_id = atoi(opts->shared_net_id); 2278 char nic[37]; 2279 args[n++] = "-net"; 2280 snprintf(nic, 37, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id); 2281 args[n++] = strdup(nic); 2282 args[n++] = "-net"; 2283 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234"; 2284 2285 args[n++] = "-net"; 2286 args[n++] = "nic,vlan=0"; 2287 args[n++] = "-net"; 2288 args[n++] = "user,vlan=0"; 2289 } 2290 2291 while(argc-- > 0) { 2292 args[n++] = *argv++; 2293 } 2294 args[n] = 0; 2295 2296 if(VERBOSE_CHECK(init)) { 2297 int i; 2298 for(i = 0; i < n; i++) { 2299 fprintf(stdout, "emulator: argv[%02d] = \"%s\"\n", i, args[i]); 2300 } 2301 } 2302 return qemu_main(n, args); 2303} 2304 2305void android_emulation_teardown( void ) 2306{ 2307 android_charmap_done(); 2308} 2309