main-common.c revision 40841b2d221273a08abfe20824e7631211ade31d
1/* Copyright (C) 2011 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#include <signal.h> 13#include <unistd.h> 14#include <string.h> 15#include <sys/time.h> 16#include <errno.h> 17#include <fcntl.h> 18#ifdef _WIN32 19#include <process.h> 20#endif 21 22#include <SDL.h> 23#include <SDL_syswm.h> 24 25#include "console.h" 26 27#include "android/utils/debug.h" 28#include "android/utils/path.h" 29#include "android/utils/bufprint.h" 30#include "android/utils/dirscanner.h" 31#include "android/main-common.h" 32#include "android/globals.h" 33#include "android/resource.h" 34#include "android/user-config.h" 35#include "android/qemulator.h" 36#include "android/display.h" 37#include "android/skin/image.h" 38#include "android/skin/trackball.h" 39#include "android/skin/keyboard.h" 40#include "android/skin/file.h" 41#include "android/skin/window.h" 42 43 44 45/***********************************************************************/ 46/***********************************************************************/ 47/***** *****/ 48/***** U T I L I T Y R O U T I N E S *****/ 49/***** *****/ 50/***********************************************************************/ 51/***********************************************************************/ 52 53#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0) 54 55/*** CONFIGURATION 56 ***/ 57 58static AUserConfig* userConfig; 59 60void 61user_config_init( void ) 62{ 63 userConfig = auserConfig_new( android_avdInfo ); 64} 65 66/* only call this function on normal exits, so that ^C doesn't save the configuration */ 67void 68user_config_done( void ) 69{ 70 int win_x, win_y; 71 72 if (!userConfig) { 73 D("no user configuration?"); 74 return; 75 } 76 77 SDL_WM_GetPos( &win_x, &win_y ); 78 auserConfig_setWindowPos(userConfig, win_x, win_y); 79 auserConfig_save(userConfig); 80} 81 82void 83user_config_get_window_pos( int *window_x, int *window_y ) 84{ 85 *window_x = *window_y = 10; 86 87 if (userConfig) 88 auserConfig_getWindowPos(userConfig, window_x, window_y); 89} 90 91unsigned convertBytesToMB( uint64_t size ) 92{ 93 if (size == 0) 94 return 0; 95 96 size = (size + ONE_MB-1) >> 20; 97 if (size > UINT_MAX) 98 size = UINT_MAX; 99 100 return (unsigned) size; 101} 102 103uint64_t convertMBToBytes( unsigned megaBytes ) 104{ 105 return ((uint64_t)megaBytes << 20); 106} 107 108 109/***********************************************************************/ 110/***********************************************************************/ 111/***** *****/ 112/***** K E Y S E T R O U T I N E S *****/ 113/***** *****/ 114/***********************************************************************/ 115/***********************************************************************/ 116 117#define KEYSET_FILE "default.keyset" 118 119SkinKeyset* android_keyset = NULL; 120 121static int 122load_keyset(const char* path) 123{ 124 if (path_can_read(path)) { 125 AConfig* root = aconfig_node("",""); 126 if (!aconfig_load_file(root, path)) { 127 android_keyset = skin_keyset_new(root); 128 if (android_keyset != NULL) { 129 D( "keyset loaded from: %s", path); 130 return 0; 131 } 132 } 133 } 134 return -1; 135} 136 137void 138parse_keyset(const char* keyset, AndroidOptions* opts) 139{ 140 char kname[MAX_PATH]; 141 char temp[MAX_PATH]; 142 char* p; 143 char* end; 144 145 /* append .keyset suffix if needed */ 146 if (strchr(keyset, '.') == NULL) { 147 p = kname; 148 end = p + sizeof(kname); 149 p = bufprint(p, end, "%s.keyset", keyset); 150 if (p >= end) { 151 derror( "keyset name too long: '%s'\n", keyset); 152 exit(1); 153 } 154 keyset = kname; 155 } 156 157 /* look for a the keyset file */ 158 p = temp; 159 end = p + sizeof(temp); 160 p = bufprint_config_file(p, end, keyset); 161 if (p < end && load_keyset(temp) == 0) 162 return; 163 164 p = temp; 165 p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset); 166 if (p < end && load_keyset(temp) == 0) 167 return; 168 169 p = temp; 170 p = bufprint_app_dir(p, end); 171 p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset); 172 if (p < end && load_keyset(temp) == 0) 173 return; 174 175 return; 176} 177 178void 179write_default_keyset( void ) 180{ 181 char path[MAX_PATH]; 182 183 bufprint_config_file( path, path+sizeof(path), KEYSET_FILE ); 184 185 /* only write if there is no file here */ 186 if ( !path_exists(path) ) { 187 int fd = open( path, O_WRONLY | O_CREAT, 0666 ); 188 int ret; 189 const char* ks = skin_keyset_get_default(); 190 191 192 D( "writing default keyset file to %s", path ); 193 194 if (fd < 0) { 195 D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) ); 196 return; 197 } 198 CHECKED(ret, write(fd, ks, strlen(ks))); 199 close(fd); 200 } 201} 202 203 204 205/***********************************************************************/ 206/***********************************************************************/ 207/***** *****/ 208/***** S D L S U P P O R T *****/ 209/***** *****/ 210/***********************************************************************/ 211/***********************************************************************/ 212 213void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height); 214 215#ifdef CONFIG_DARWIN 216# define ANDROID_ICON_PNG "android_icon_256.png" 217#else 218# define ANDROID_ICON_PNG "android_icon_16.png" 219#endif 220 221static void 222sdl_set_window_icon( void ) 223{ 224 static int window_icon_set; 225 226 if (!window_icon_set) 227 { 228#ifdef _WIN32 229 HANDLE handle = GetModuleHandle( NULL ); 230 HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) ); 231 SDL_SysWMinfo wminfo; 232 233 SDL_GetWMInfo(&wminfo); 234 235 SetClassLong( wminfo.window, GCL_HICON, (LONG)icon ); 236#else /* !_WIN32 */ 237 unsigned icon_w, icon_h; 238 size_t icon_bytes; 239 const unsigned char* icon_data; 240 void* icon_pixels; 241 242 window_icon_set = 1; 243 244 icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes ); 245 if ( !icon_data ) 246 return; 247 248 icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h ); 249 if ( !icon_pixels ) 250 return; 251 252 /* the data is loaded into memory as RGBA bytes by libpng. we want to manage 253 * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending 254 * on our CPU endianess 255 */ 256 { 257 unsigned* d = icon_pixels; 258 unsigned* d_end = d + icon_w*icon_h; 259 260 for ( ; d < d_end; d++ ) { 261 unsigned pix = d[0]; 262#if HOST_WORDS_BIGENDIAN 263 /* R,G,B,A read as RGBA => ARGB */ 264 pix = ((pix >> 8) & 0xffffff) | (pix << 24); 265#else 266 /* R,G,B,A read as ABGR => ARGB */ 267 pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16); 268#endif 269 d[0] = pix; 270 } 271 } 272 273 SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h ); 274 if (icon != NULL) { 275 SDL_WM_SetIcon(icon, NULL); 276 SDL_FreeSurface(icon); 277 free( icon_pixels ); 278 } 279#endif /* !_WIN32 */ 280 } 281} 282 283/***********************************************************************/ 284/***********************************************************************/ 285/***** *****/ 286/***** S K I N S U P P O R T *****/ 287/***** *****/ 288/***********************************************************************/ 289/***********************************************************************/ 290 291const char* skin_network_speed = NULL; 292const char* skin_network_delay = NULL; 293 294 295static void sdl_at_exit(void) 296{ 297 user_config_done(); 298 qemulator_done(qemulator_get()); 299 SDL_Quit(); 300} 301 302 303void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) 304{ 305 QEmulator* emulator = qemulator_get(); 306 SkinDisplay* disp = skin_layout_get_display(emulator->layout); 307 int width, height; 308 char buf[128]; 309 310 if (disp->rotation & 1) { 311 width = disp->rect.size.h; 312 height = disp->rect.size.w; 313 } else { 314 width = disp->rect.size.w; 315 height = disp->rect.size.h; 316 } 317 318 snprintf(buf, sizeof buf, "width=%d,height=%d", width, height); 319#if !defined(CONFIG_STANDALONE_UI) && !defined(CONFIG_STANDALONE_CORE) 320 android_display_init(ds, qframebuffer_fifo_get()); 321#endif 322} 323 324/* list of skin aliases */ 325static const struct { 326 const char* name; 327 const char* alias; 328} skin_aliases[] = { 329 { "QVGA-L", "320x240" }, 330 { "QVGA-P", "240x320" }, 331 { "HVGA-L", "480x320" }, 332 { "HVGA-P", "320x480" }, 333 { "QVGA", "320x240" }, 334 { "HVGA", "320x480" }, 335 { NULL, NULL } 336}; 337 338/* this is used by hw/events_device.c to send the charmap name to the system */ 339const char* android_skin_keycharmap = NULL; 340 341void 342parse_skin_files(const char* skinDirPath, 343 const char* skinName, 344 AndroidOptions* opts, 345 AndroidHwConfig* hwConfig, 346 AConfig* *skinConfig, 347 char* *skinPath) 348{ 349 char tmp[1024]; 350 AConfig* root; 351 const char* path = NULL; 352 AConfig* n; 353 354 root = aconfig_node("", ""); 355 356 if (skinName == NULL) 357 goto DEFAULT_SKIN; 358 359 /* Support skin aliases like QVGA-H QVGA-P, etc... 360 But first we check if it's a directory that exist before applying 361 the alias */ 362 int checkAlias = 1; 363 364 if (skinDirPath != NULL) { 365 bufprint(tmp, tmp+sizeof(tmp), "%s/%s", skinDirPath, skinName); 366 if (path_exists(tmp)) { 367 checkAlias = 0; 368 } else { 369 D("there is no '%s' skin in '%s'", skinName, skinDirPath); 370 } 371 } 372 373 if (checkAlias) { 374 int nn; 375 376 for (nn = 0; ; nn++ ) { 377 const char* skin_name = skin_aliases[nn].name; 378 const char* skin_alias = skin_aliases[nn].alias; 379 380 if (!skin_name) 381 break; 382 383 if (!strcasecmp( skin_name, skinName )) { 384 D("skin name '%s' aliased to '%s'", skinName, skin_alias); 385 skinName = skin_alias; 386 break; 387 } 388 } 389 } 390 391 /* Magically support skins like "320x240" or "320x240x16" */ 392 if(isdigit(skinName[0])) { 393 char *x = strchr(skinName, 'x'); 394 if(x && isdigit(x[1])) { 395 int width = atoi(skinName); 396 int height = atoi(x+1); 397 int bpp = 16; 398 char* y = strchr(x+1, 'x'); 399 if (y && isdigit(y[1])) { 400 bpp = atoi(y+1); 401 } 402 snprintf(tmp, sizeof tmp, 403 "display {\n width %d\n height %d\n bpp %d}\n", 404 width, height,bpp); 405 aconfig_load(root, strdup(tmp)); 406 path = ":"; 407 D("found magic skin width=%d height=%d bpp=%d\n", width, height, bpp); 408 goto FOUND_SKIN; 409 } 410 } 411 412 if (skinDirPath == NULL) { 413 derror("unknown skin name '%s'", skinName); 414 exit(1); 415 } 416 417 snprintf(tmp, sizeof tmp, "%s/%s/layout", skinDirPath, skinName); 418 D("trying to load skin file '%s'", tmp); 419 420 if(aconfig_load_file(root, tmp) < 0) { 421 dwarning("could not load skin file '%s', using built-in one\n", 422 tmp); 423 goto DEFAULT_SKIN; 424 } 425 426 snprintf(tmp, sizeof tmp, "%s/%s/", skinDirPath, skinName); 427 path = tmp; 428 goto FOUND_SKIN; 429 430FOUND_SKIN: 431 /* the default network speed and latency can now be specified by the device skin */ 432 n = aconfig_find(root, "network"); 433 if (n != NULL) { 434 skin_network_speed = aconfig_str(n, "speed", 0); 435 skin_network_delay = aconfig_str(n, "delay", 0); 436 } 437 438 /* extract framebuffer information from the skin. 439 * 440 * for version 1 of the skin format, they are in the top-level 441 * 'display' element. 442 * 443 * for version 2 of the skin format, they are under parts.device.display 444 */ 445 n = aconfig_find(root, "display"); 446 if (n == NULL) { 447 n = aconfig_find(root, "parts"); 448 if (n != NULL) { 449 n = aconfig_find(root, "device"); 450 if (n != NULL) { 451 n = aconfig_find(root, "display"); 452 } 453 } 454 } 455 456 if (n != NULL) { 457 int width = aconfig_int(n, "width", hwConfig->hw_lcd_width); 458 int height = aconfig_int(n, "height", hwConfig->hw_lcd_height); 459 int depth = aconfig_int(n, "bpp", hwConfig->hw_lcd_depth); 460 461 if (width > 0 && height > 0) { 462 /* The emulated framebuffer wants sizes that are multiples of 4 */ 463 if (((width|height) & 3) != 0) { 464 width = (width+3) & ~3; 465 height = (height+3) & ~3; 466 D("adjusting LCD dimensions to (%dx%dx)", width, height); 467 } 468 469 /* only depth values of 16 and 32 are correct. 16 is the default. */ 470 if (depth != 32 && depth != 16) { 471 depth = 16; 472 D("adjusting LCD bit depth to %d", depth); 473 } 474 475 hwConfig->hw_lcd_width = width; 476 hwConfig->hw_lcd_height = height; 477 hwConfig->hw_lcd_depth = depth; 478 } 479 else { 480 D("ignoring invalid skin LCD dimensions (%dx%dx%d)", 481 width, height, depth); 482 } 483 } 484 485 *skinConfig = root; 486 *skinPath = strdup(path); 487 return; 488 489DEFAULT_SKIN: 490 { 491 const unsigned char* layout_base; 492 size_t layout_size; 493 char* base; 494 495 skinName = "<builtin>"; 496 497 layout_base = android_resource_find( "layout", &layout_size ); 498 if (layout_base == NULL) { 499 fprintf(stderr, "Couldn't load builtin skin\n"); 500 exit(1); 501 } 502 base = malloc( layout_size+1 ); 503 memcpy( base, layout_base, layout_size ); 504 base[layout_size] = 0; 505 506 D("parsing built-in skin layout file (%d bytes)", (int)layout_size); 507 aconfig_load(root, base); 508 path = ":"; 509 } 510 goto FOUND_SKIN; 511} 512 513 514void 515init_sdl_ui(AConfig* skinConfig, 516 const char* skinPath, 517 AndroidOptions* opts) 518{ 519 int win_x, win_y, flags; 520 521 signal(SIGINT, SIG_DFL); 522#ifndef _WIN32 523 signal(SIGQUIT, SIG_DFL); 524#endif 525 526 /* we're not a game, so allow the screensaver to run */ 527 putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1"); 528 529 flags = SDL_INIT_NOPARACHUTE; 530 if (!opts->no_window) 531 flags |= SDL_INIT_VIDEO; 532 533 if(SDL_Init(flags)){ 534 fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() ); 535 exit(1); 536 } 537 538 if (!opts->no_window) { 539 SDL_EnableUNICODE(!opts->raw_keys); 540 SDL_EnableKeyRepeat(0,0); 541 542 sdl_set_window_icon(); 543 } 544 else 545 { 546#ifndef _WIN32 547 /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be 548 * able to run the emulator in the background (e.g. "emulator &"). 549 * despite the fact that the emulator should not grab input or try to 550 * write to the output in normal cases, we're stopped on some systems 551 * (e.g. OS X) 552 */ 553 signal(SIGTTIN, SIG_IGN); 554 signal(SIGTTOU, SIG_IGN); 555#endif 556 } 557 atexit(sdl_at_exit); 558 559 user_config_get_window_pos(&win_x, &win_y); 560 561 if ( qemulator_init(qemulator_get(), skinConfig, skinPath, win_x, win_y, opts) < 0 ) { 562 fprintf(stderr, "### Error: could not load emulator skin from '%s'\n", skinPath); 563 exit(1); 564 } 565 566 android_skin_keycharmap = skin_keyboard_charmap_name(qemulator_get()->keyboard); 567 568 /* add an onion overlay image if needed */ 569 if (opts->onion) { 570 SkinImage* onion = skin_image_find_simple( opts->onion ); 571 int alpha, rotate; 572 573 if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) { 574 alpha = (256*alpha)/100; 575 } else 576 alpha = 128; 577 578 if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) { 579 rotate &= 3; 580 } else 581 rotate = SKIN_ROTATION_0; 582 583 qemulator_get()->onion = onion; 584 qemulator_get()->onion_alpha = alpha; 585 qemulator_get()->onion_rotation = rotate; 586 } 587} 588 589/* this function is used to perform auto-detection of the 590 * system directory in the case of a SDK installation. 591 * 592 * we want to deal with several historical usages, hence 593 * the slightly complicated logic. 594 * 595 * NOTE: the function returns the path to the directory 596 * containing 'fileName'. this is *not* the full 597 * path to 'fileName'. 598 */ 599static char* 600_getSdkImagePath( const char* fileName ) 601{ 602 char temp[MAX_PATH]; 603 char* p = temp; 604 char* end = p + sizeof(temp); 605 char* q; 606 char* app; 607 608 static const char* const searchPaths[] = { 609 "", /* program's directory */ 610 "/lib/images", /* this is for SDK 1.0 */ 611 "/../platforms/android-1.1/images", /* this is for SDK 1.1 */ 612 NULL 613 }; 614 615 app = bufprint_app_dir(temp, end); 616 if (app >= end) 617 return NULL; 618 619 do { 620 int nn; 621 622 /* first search a few well-known paths */ 623 for (nn = 0; searchPaths[nn] != NULL; nn++) { 624 p = bufprint(app, end, "%s", searchPaths[nn]); 625 q = bufprint(p, end, "/%s", fileName); 626 if (q < end && path_exists(temp)) { 627 *p = 0; 628 goto FOUND_IT; 629 } 630 } 631 632 /* hmmm. let's assume that we are in a post-1.1 SDK 633 * scan ../platforms if it exists 634 */ 635 p = bufprint(app, end, "/../platforms"); 636 if (p < end) { 637 DirScanner* scanner = dirScanner_new(temp); 638 if (scanner != NULL) { 639 int found = 0; 640 const char* subdir; 641 642 for (;;) { 643 subdir = dirScanner_next(scanner); 644 if (!subdir) break; 645 646 q = bufprint(p, end, "/%s/images/%s", subdir, fileName); 647 if (q >= end || !path_exists(temp)) 648 continue; 649 650 found = 1; 651 p = bufprint(p, end, "/%s/images", subdir); 652 break; 653 } 654 dirScanner_free(scanner); 655 if (found) 656 break; 657 } 658 } 659 660 /* I'm out of ideas */ 661 return NULL; 662 663 } while (0); 664 665FOUND_IT: 666 //D("image auto-detection: %s/%s", temp, fileName); 667 return android_strdup(temp); 668} 669 670static char* 671_getSdkImage( const char* path, const char* file ) 672{ 673 char temp[MAX_PATH]; 674 char *p = temp, *end = p + sizeof(temp); 675 676 p = bufprint(temp, end, "%s/%s", path, file); 677 if (p >= end || !path_exists(temp)) 678 return NULL; 679 680 return android_strdup(temp); 681} 682 683static char* 684_getSdkSystemImage( const char* path, const char* optionName, const char* file ) 685{ 686 char* image = _getSdkImage(path, file); 687 688 if (image == NULL) { 689 derror("Your system directory is missing the '%s' image file.\n" 690 "Please specify one with the '%s <filepath>' option", 691 file, optionName); 692 exit(2); 693 } 694 return image; 695} 696 697static void 698_forceAvdImagePath( AvdImageType imageType, 699 const char* path, 700 const char* description, 701 int required ) 702{ 703 if (path == NULL) 704 return; 705 706 if (required && !path_exists(path)) { 707 derror("Cannot find %s image file: %s", description, path); 708 exit(1); 709 } 710 android_avdParams->forcePaths[imageType] = path; 711} 712 713 714void sanitizeOptions( AndroidOptions* opts ) 715{ 716 /* legacy support: we used to use -system <dir> and -image <file> 717 * instead of -sysdir <dir> and -system <file>, so handle this by checking 718 * whether the options point to directories or files. 719 */ 720 if (opts->image != NULL) { 721 if (opts->system != NULL) { 722 if (opts->sysdir != NULL) { 723 derror( "You can't use -sysdir, -system and -image at the same time.\n" 724 "You should probably use '-sysdir <path> -system <file>'.\n" ); 725 exit(2); 726 } 727 } 728 dwarning( "Please note that -image is obsolete and that -system is now used to point\n" 729 "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" ); 730 opts->sysdir = opts->system; 731 opts->system = opts->image; 732 opts->image = NULL; 733 } 734 else if (opts->system != NULL && path_is_dir(opts->system)) { 735 if (opts->sysdir != NULL) { 736 derror( "Option -system should now be followed by a file path, not a directory one.\n" 737 "Please use '-sysdir <path>' to point to the system directory.\n" ); 738 exit(1); 739 } 740 dwarning( "Please note that the -system option should now be used to point to the initial\n" 741 "system image (like the obsolete -image option). To point to the system directory\n" 742 "please now use '-sysdir <path>' instead.\n" ); 743 744 opts->sysdir = opts->system; 745 opts->system = NULL; 746 } 747 748 if (opts->nojni) { 749 opts->no_jni = opts->nojni; 750 opts->nojni = 0; 751 } 752 753 if (opts->nocache) { 754 opts->no_cache = opts->nocache; 755 opts->nocache = 0; 756 } 757 758 if (opts->noaudio) { 759 opts->no_audio = opts->noaudio; 760 opts->noaudio = 0; 761 } 762 763 if (opts->noskin) { 764 opts->no_skin = opts->noskin; 765 opts->noskin = 0; 766 } 767 768 /* If -no-cache is used, ignore any -cache argument */ 769 if (opts->no_cache) { 770 opts->cache = 0; 771 } 772 773 /* the purpose of -no-audio is to disable sound output from the emulator, 774 * not to disable Audio emulation. So simply force the 'none' backends */ 775 if (opts->no_audio) 776 opts->audio = "none"; 777 778 /* we don't accept -skindir without -skin now 779 * to simplify the autoconfig stuff with virtual devices 780 */ 781 if (opts->no_skin) { 782 opts->skin = "320x480"; 783 opts->skindir = NULL; 784 } 785 786 if (opts->skindir) { 787 if (!opts->skin) { 788 derror( "the -skindir <path> option requires a -skin <name> option"); 789 exit(1); 790 } 791 } 792 793 if (opts->bootchart) { 794 char* end; 795 int timeout = strtol(opts->bootchart, &end, 10); 796 if (timeout == 0) 797 opts->bootchart = NULL; 798 else if (timeout < 0 || timeout > 15*60) { 799 derror( "timeout specified for -bootchart option is invalid.\n" 800 "please use integers between 1 and 900\n"); 801 exit(1); 802 } 803 } 804} 805 806AvdInfo* createAVD(AndroidOptions* opts, int* inAndroidBuild) 807{ 808 AvdInfo* ret = NULL; 809 char tmp[MAX_PATH]; 810 char* tmpend = tmp + sizeof(tmp); 811 char* android_build_root = NULL; 812 char* android_build_out = NULL; 813 814 /* setup the virtual device parameters from our options 815 */ 816 if (opts->no_cache) { 817 android_avdParams->flags |= AVDINFO_NO_CACHE; 818 } 819 if (opts->wipe_data) { 820 android_avdParams->flags |= AVDINFO_WIPE_DATA | AVDINFO_WIPE_CACHE; 821 } 822 if (opts->no_snapstorage) { 823 android_avdParams->flags |= AVDINFO_NO_SNAPSHOTS; 824 } 825 826 /* If no AVD name was given, try to find the top of the 827 * Android build tree 828 */ 829 if (opts->avd == NULL) { 830 do { 831 char* out = getenv("ANDROID_PRODUCT_OUT"); 832 833 if (out == NULL || out[0] == 0) 834 break; 835 836 if (!path_exists(out)) { 837 derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n" 838 "You need to build the Android system before launching the emulator", 839 out); 840 exit(2); 841 } 842 843 android_build_root = path_parent( out, 4 ); 844 if (android_build_root == NULL || !path_exists(android_build_root)) { 845 derror("Can't find the Android build root from '%s'\n" 846 "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n" 847 "It should point to your product-specific build output directory.\n", 848 out ); 849 exit(2); 850 } 851 android_build_out = out; 852 D( "found Android build root: %s", android_build_root ); 853 D( "found Android build out: %s", android_build_out ); 854 } while (0); 855 } 856 /* if no virtual device name is given, and we're not in the 857 * Android build system, we'll need to perform some auto-detection 858 * magic :-) 859 */ 860 if (opts->avd == NULL && !android_build_out) 861 { 862 char dataDirIsSystem = 0; 863 864 if (!opts->sysdir) { 865 opts->sysdir = _getSdkImagePath("system.img"); 866 if (!opts->sysdir) { 867 derror( 868 "You did not specify a virtual device name, and the system\n" 869 "directory could not be found.\n\n" 870 "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n" 871 "to start a given virtual device (see -help-avd for details).\n\n" 872 873 "Otherwise, follow the instructions in -help-disk-images to start the emulator\n" 874 ); 875 exit(2); 876 } 877 D("autoconfig: -sysdir %s", opts->sysdir); 878 } 879 880 if (!opts->system) { 881 opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img"); 882 D("autoconfig: -image %s", opts->image); 883 } 884 885 if (!opts->kernel) { 886 opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu"); 887 D("autoconfig: -kernel %s", opts->kernel); 888 } 889 890 if (!opts->ramdisk) { 891 opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img"); 892 D("autoconfig: -ramdisk %s", opts->ramdisk); 893 } 894 895 /* if no data directory is specified, use the system directory */ 896 if (!opts->datadir) { 897 opts->datadir = android_strdup(opts->sysdir); 898 dataDirIsSystem = 1; 899 D("autoconfig: -datadir %s", opts->sysdir); 900 } 901 902 if (!opts->data) { 903 /* check for userdata-qemu.img in the data directory */ 904 bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir); 905 if (!path_exists(tmp)) { 906 derror( 907 "You did not provide the name of an Android Virtual Device\n" 908 "with the '-avd <name>' option. Read -help-avd for more information.\n\n" 909 910 "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n" 911 "to specify a data partition image file (I hope you know what you're doing).\n" 912 ); 913 exit(2); 914 } 915 916 opts->data = android_strdup(tmp); 917 D("autoconfig: -data %s", opts->data); 918 } 919 920 if (!opts->snapstorage && opts->datadir) { 921 bufprint(tmp, tmpend, "%s/snapshots.img", opts->datadir); 922 if (path_exists(tmp)) { 923 opts->snapstorage = android_strdup(tmp); 924 D("autoconfig: -snapstorage %s", opts->snapstorage); 925 } 926 } 927 } 928 929 /* if certain options are set, we can force the path of 930 * certain kernel/disk image files 931 */ 932 _forceAvdImagePath(AVD_IMAGE_INITSYSTEM, opts->system, "system", 1); 933 _forceAvdImagePath(AVD_IMAGE_USERDATA, opts->data, "user data", 0); 934 _forceAvdImagePath(AVD_IMAGE_SNAPSHOTS, opts->snapstorage, "snapshots", 0); 935 936 android_avdParams->skinName = opts->skin; 937 android_avdParams->skinRootPath = opts->skindir; 938 939 /* setup the virtual device differently depending on whether 940 * we are in the Android build system or not 941 */ 942 if (opts->avd != NULL) 943 { 944 ret = avdInfo_new( opts->avd, android_avdParams ); 945 if (ret == NULL) { 946 /* an error message has already been printed */ 947 dprint("could not find virtual device named '%s'", opts->avd); 948 exit(1); 949 } 950 } 951 else 952 { 953 if (!android_build_out) { 954 android_build_out = android_build_root = opts->sysdir; 955 } 956 ret = avdInfo_newForAndroidBuild( 957 android_build_root, 958 android_build_out, 959 android_avdParams ); 960 961 if(ret == NULL) { 962 D("could not start virtual device\n"); 963 exit(1); 964 } 965 } 966 967 if (android_build_out) { 968 *inAndroidBuild = 1; 969 } else { 970 *inAndroidBuild = 0; 971 } 972 973 return ret; 974} 975 976static int 977_is_valid_hw_disk_path(const char* path) 978{ 979 if (path == NULL || '\0' == *path || !strcmp(path, "<init>")) { 980 return 0; 981 } 982 return 1; 983} 984 985static int 986_update_hwconfig_path(char** path, AvdInfo* avd, int image_type) 987{ 988 if (!_is_valid_hw_disk_path(*path)) { 989 *path = android_strdup(avdInfo_getImageFile(avd, image_type)); 990 if (!_is_valid_hw_disk_path(*path)) { 991 return -1; 992 } 993 } 994 return 0; 995} 996 997static uint64_t 998_adjustPartitionSize( const char* description, 999 uint64_t imageBytes, 1000 uint64_t defaultBytes, 1001 int inAndroidBuild ) 1002{ 1003 char temp[64]; 1004 unsigned imageMB; 1005 unsigned defaultMB; 1006 1007 if (imageBytes <= defaultBytes) 1008 return defaultBytes; 1009 1010 imageMB = convertBytesToMB(imageBytes); 1011 defaultMB = convertBytesToMB(defaultBytes); 1012 1013 if (imageMB > defaultMB) { 1014 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB); 1015 } else { 1016 snprintf(temp, sizeof temp, "(%lld bytes > %lld bytes)", imageBytes, defaultBytes); 1017 } 1018 1019 if (inAndroidBuild) { 1020 dwarning("%s partition size adjusted to match image file %s\n", description, temp); 1021 } 1022 1023 return convertMBToBytes(imageMB); 1024} 1025 1026void 1027updateHwConfigFromAVD(AndroidHwConfig* hwConfig, 1028 AvdInfo* avd, 1029 AndroidOptions* opts, 1030 int inAndroidBuild) 1031{ 1032 unsigned defaultPartitionSize = convertMBToBytes(66); 1033 1034 _update_hwconfig_path(&hwConfig->disk_dataPartition_path, avd, AVD_IMAGE_USERDATA); 1035 _update_hwconfig_path(&hwConfig->disk_dataPartition_path, avd, AVD_IMAGE_INITDATA); 1036 1037 if (opts->partition_size) { 1038 char* end; 1039 long sizeMB = strtol(opts->partition_size, &end, 0); 1040 long minSizeMB = 10; 1041 long maxSizeMB = LONG_MAX / ONE_MB; 1042 1043 if (sizeMB < 0 || *end != 0) { 1044 derror( "-partition-size must be followed by a positive integer" ); 1045 exit(1); 1046 } 1047 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) { 1048 derror( "partition-size (%d) must be between %dMB and %dMB", 1049 sizeMB, minSizeMB, maxSizeMB ); 1050 exit(1); 1051 } 1052 defaultPartitionSize = sizeMB * ONE_MB; 1053 } 1054 /* Check the size of the /data partition. The only interesting cases here are: 1055 * - when the USERDATA image already exists and is larger than the default 1056 * - when we're wiping data and the INITDATA is larger than the default. 1057 */ 1058 1059 { 1060 const char* dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA); 1061 uint64_t defaultBytes = defaultPartitionSize; 1062 1063 if (defaultBytes == 0 || opts->partition_size) 1064 defaultBytes = defaultPartitionSize; 1065 1066 if (dataPath == NULL || !path_exists(dataPath) || opts->wipe_data) { 1067 dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_INITDATA); 1068 } 1069 if (dataPath == NULL || !path_exists(dataPath)) { 1070 hwConfig->disk_dataPartition_size = defaultBytes; 1071 } 1072 else { 1073 uint64_t dataBytes; 1074 path_get_size(dataPath, &dataBytes); 1075 1076 hwConfig->disk_dataPartition_size = 1077 _adjustPartitionSize("data", dataBytes, defaultBytes, inAndroidBuild); 1078 } 1079 } 1080} 1081 1082 1083 1084#ifdef CONFIG_STANDALONE_UI 1085 1086#include "android/protocol/core-connection.h" 1087#include "android/protocol/fb-updates-impl.h" 1088#include "android/protocol/user-events-proxy.h" 1089#include "android/protocol/core-commands-proxy.h" 1090#include "android/protocol/ui-commands-impl.h" 1091#include "android/protocol/attach-ui-impl.h" 1092 1093/* Emulator's core port. */ 1094int android_base_port = 0; 1095 1096// Base console port 1097#define CORE_BASE_PORT 5554 1098 1099// Maximum number of core porocesses running simultaneously on a machine. 1100#define MAX_CORE_PROCS 16 1101 1102// Socket timeout in millisec (set to 5 seconds) 1103#define CORE_PORT_TIMEOUT_MS 5000 1104 1105#include "android/async-console.h" 1106 1107typedef struct { 1108 LoopIo io[1]; 1109 int port; 1110 int ok; 1111 AsyncConsoleConnector connector[1]; 1112} CoreConsole; 1113 1114static void 1115coreconsole_io_func(void* opaque, int fd, unsigned events) 1116{ 1117 CoreConsole* cc = opaque; 1118 AsyncStatus status; 1119 status = asyncConsoleConnector_run(cc->connector, cc->io); 1120 if (status == ASYNC_COMPLETE) { 1121 cc->ok = 1; 1122 } 1123} 1124 1125static void 1126coreconsole_init(CoreConsole* cc, const SockAddress* address, Looper* looper) 1127{ 1128 int fd = socket_create_inet(SOCKET_STREAM); 1129 AsyncStatus status; 1130 cc->port = sock_address_get_port(address); 1131 cc->ok = 0; 1132 loopIo_init(cc->io, looper, fd, coreconsole_io_func, cc); 1133 if (fd >= 0) { 1134 status = asyncConsoleConnector_connect(cc->connector, address, cc->io); 1135 if (status == ASYNC_ERROR) { 1136 cc->ok = 0; 1137 } 1138 } 1139} 1140 1141static void 1142coreconsole_done(CoreConsole* cc) 1143{ 1144 socket_close(cc->io->fd); 1145 loopIo_done(cc->io); 1146} 1147 1148/* List emulator core processes running on the given machine. 1149 * This routine is called from main() if -list-cores parameter is set in the 1150 * command line. 1151 * Param: 1152 * host Value passed with -list-core parameter. Must be either "localhost", or 1153 * an IP address of a machine where core processes must be enumerated. 1154 */ 1155static void 1156list_running_cores(const char* host) 1157{ 1158 Looper* looper; 1159 CoreConsole cores[MAX_CORE_PROCS]; 1160 SockAddress address; 1161 int nn, found; 1162 1163 if (sock_address_init_resolve(&address, host, CORE_BASE_PORT, 0) < 0) { 1164 derror("Unable to resolve hostname %s: %s", host, errno_str); 1165 return; 1166 } 1167 1168 looper = looper_newGeneric(); 1169 1170 for (nn = 0; nn < MAX_CORE_PROCS; nn++) { 1171 int port = CORE_BASE_PORT + nn*2; 1172 sock_address_set_port(&address, port); 1173 coreconsole_init(&cores[nn], &address, looper); 1174 } 1175 1176 looper_runWithTimeout(looper, CORE_PORT_TIMEOUT_MS*2); 1177 1178 found = 0; 1179 for (nn = 0; nn < MAX_CORE_PROCS; nn++) { 1180 int port = CORE_BASE_PORT + nn*2; 1181 if (cores[nn].ok) { 1182 if (found == 0) { 1183 fprintf(stdout, "Running emulator core processes:\n"); 1184 } 1185 fprintf(stdout, "Emulator console port %d\n", port); 1186 found++; 1187 } 1188 coreconsole_done(&cores[nn]); 1189 } 1190 looper_free(looper); 1191 1192 if (found == 0) { 1193 fprintf(stdout, "There were no running emulator core processes found on %s.\n", 1194 host); 1195 } 1196} 1197 1198/* Attaches starting UI to a running core process. 1199 * This routine is called from main() when -attach-core parameter is set, 1200 * indicating that this UI instance should attach to a running core, rather than 1201 * start a new core process. 1202 * Param: 1203 * opts Android options containing non-NULL attach_core. 1204 * Return: 1205 * 0 on success, or -1 on failure. 1206 */ 1207static int 1208attach_to_core(AndroidOptions* opts) { 1209 int iter; 1210 SockAddress console_socket; 1211 SockAddress** sockaddr_list; 1212 QEmulator* emulator; 1213 1214 // Parse attach_core param extracting the host name, and the port name. 1215 char* console_address = strdup(opts->attach_core); 1216 char* host_name = console_address; 1217 char* port_num = strchr(console_address, ':'); 1218 if (port_num == NULL) { 1219 // The host name is ommited, indicating the localhost 1220 host_name = "localhost"; 1221 port_num = console_address; 1222 } else if (port_num == console_address) { 1223 // Invalid. 1224 derror("Invalid value %s for -attach-core parameter\n", 1225 opts->attach_core); 1226 return -1; 1227 } else { 1228 *port_num = '\0'; 1229 port_num++; 1230 if (*port_num == '\0') { 1231 // Invalid. 1232 derror("Invalid value %s for -attach-core parameter\n", 1233 opts->attach_core); 1234 return -1; 1235 } 1236 } 1237 1238 /* Create socket address list for the given address, and pull appropriate 1239 * address to use for connection. Note that we're fine copying that address 1240 * out of the list, since INET and IN6 will entirely fit into SockAddress 1241 * structure. */ 1242 sockaddr_list = 1243 sock_address_list_create(host_name, port_num, SOCKET_LIST_FORCE_INET); 1244 free(console_address); 1245 if (sockaddr_list == NULL) { 1246 derror("Unable to resolve address %s: %s\n", 1247 opts->attach_core, errno_str); 1248 return -1; 1249 } 1250 for (iter = 0; sockaddr_list[iter] != NULL; iter++) { 1251 if (sock_address_get_family(sockaddr_list[iter]) == SOCKET_INET || 1252 sock_address_get_family(sockaddr_list[iter]) == SOCKET_IN6) { 1253 memcpy(&console_socket, sockaddr_list[iter], sizeof(SockAddress)); 1254 break; 1255 } 1256 } 1257 if (sockaddr_list[iter] == NULL) { 1258 derror("Unable to resolve address %s. Note that 'port' parameter passed to -attach-core\n" 1259 "must be resolvable into an IP address.\n", opts->attach_core); 1260 sock_address_list_free(sockaddr_list); 1261 return -1; 1262 } 1263 sock_address_list_free(sockaddr_list); 1264 1265 if (attachUiImpl_create(&console_socket)) { 1266 return -1; 1267 } 1268 1269 // Save core's port, and set the title. 1270 android_base_port = sock_address_get_port(&console_socket); 1271 emulator = qemulator_get(); 1272 qemulator_set_title(emulator); 1273 1274 return 0; 1275} 1276 1277 1278void handle_ui_options( AndroidOptions* opts ) 1279{ 1280 // Lets see if user just wants to list core process. 1281 if (opts->list_cores) { 1282 fprintf(stdout, "Enumerating running core processes.\n"); 1283 list_running_cores(opts->list_cores); 1284 exit(0); 1285 } 1286} 1287 1288int attach_ui_to_core( AndroidOptions* opts ) 1289{ 1290 // Lets see if we're attaching to a running core process here. 1291 if (opts->attach_core) { 1292 if (attach_to_core(opts)) { 1293 return -1; 1294 } 1295 // Connect to the core's UI control services. 1296 if (coreCmdProxy_create(attachUiImpl_get_console_socket())) { 1297 return -1; 1298 } 1299 // Connect to the core's user events service. 1300 if (userEventsProxy_create(attachUiImpl_get_console_socket())) { 1301 return -1; 1302 } 1303 } 1304 return 0; 1305} 1306 1307#else /* !CONFIG_STANDALONE_UI */ 1308 1309void handle_ui_options( AndroidOptions* opts ) 1310{ 1311 return; 1312} 1313 1314int attach_ui_to_core( AndroidOptions* opts ) 1315{ 1316 return 0; 1317} 1318 1319#endif /* CONFIG_STANDALONE_UI */ 1320