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 58 static AUserConfig* userConfig; 59 60 void 61 user_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 */ 67 void 68 user_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 82 void 83 user_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 91 unsigned 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 103 uint64_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 119 SkinKeyset* android_keyset = NULL; 120 121 static int 122 load_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 137 void 138 parse_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 178 void 179 write_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 213 void *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 221 static void 222 sdl_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 291 const char* skin_network_speed = NULL; 292 const char* skin_network_delay = NULL; 293 294 295 static void sdl_at_exit(void) 296 { 297 user_config_done(); 298 qemulator_done(qemulator_get()); 299 SDL_Quit(); 300 } 301 302 303 void 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 */ 325 static 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 void 339 parse_skin_files(const char* skinDirPath, 340 const char* skinName, 341 AndroidOptions* opts, 342 AndroidHwConfig* hwConfig, 343 AConfig* *skinConfig, 344 char* *skinPath) 345 { 346 char tmp[1024]; 347 AConfig* root; 348 const char* path = NULL; 349 AConfig* n; 350 351 root = aconfig_node("", ""); 352 353 if (skinName == NULL) 354 goto DEFAULT_SKIN; 355 356 /* Support skin aliases like QVGA-H QVGA-P, etc... 357 But first we check if it's a directory that exist before applying 358 the alias */ 359 int checkAlias = 1; 360 361 if (skinDirPath != NULL) { 362 bufprint(tmp, tmp+sizeof(tmp), "%s/%s", skinDirPath, skinName); 363 if (path_exists(tmp)) { 364 checkAlias = 0; 365 } else { 366 D("there is no '%s' skin in '%s'", skinName, skinDirPath); 367 } 368 } 369 370 if (checkAlias) { 371 int nn; 372 373 for (nn = 0; ; nn++ ) { 374 const char* skin_name = skin_aliases[nn].name; 375 const char* skin_alias = skin_aliases[nn].alias; 376 377 if (!skin_name) 378 break; 379 380 if (!strcasecmp( skin_name, skinName )) { 381 D("skin name '%s' aliased to '%s'", skinName, skin_alias); 382 skinName = skin_alias; 383 break; 384 } 385 } 386 } 387 388 /* Magically support skins like "320x240" or "320x240x16" */ 389 if(isdigit(skinName[0])) { 390 char *x = strchr(skinName, 'x'); 391 if(x && isdigit(x[1])) { 392 int width = atoi(skinName); 393 int height = atoi(x+1); 394 int bpp = 16; 395 char* y = strchr(x+1, 'x'); 396 if (y && isdigit(y[1])) { 397 bpp = atoi(y+1); 398 } 399 snprintf(tmp, sizeof tmp, 400 "display {\n width %d\n height %d\n bpp %d}\n", 401 width, height,bpp); 402 aconfig_load(root, strdup(tmp)); 403 path = ":"; 404 D("found magic skin width=%d height=%d bpp=%d\n", width, height, bpp); 405 goto FOUND_SKIN; 406 } 407 } 408 409 if (skinDirPath == NULL) { 410 derror("unknown skin name '%s'", skinName); 411 exit(1); 412 } 413 414 snprintf(tmp, sizeof tmp, "%s/%s/layout", skinDirPath, skinName); 415 D("trying to load skin file '%s'", tmp); 416 417 if(aconfig_load_file(root, tmp) < 0) { 418 dwarning("could not load skin file '%s', using built-in one\n", 419 tmp); 420 goto DEFAULT_SKIN; 421 } 422 423 snprintf(tmp, sizeof tmp, "%s/%s/", skinDirPath, skinName); 424 path = tmp; 425 goto FOUND_SKIN; 426 427 FOUND_SKIN: 428 /* the default network speed and latency can now be specified by the device skin */ 429 n = aconfig_find(root, "network"); 430 if (n != NULL) { 431 skin_network_speed = aconfig_str(n, "speed", 0); 432 skin_network_delay = aconfig_str(n, "delay", 0); 433 } 434 435 /* extract framebuffer information from the skin. 436 * 437 * for version 1 of the skin format, they are in the top-level 438 * 'display' element. 439 * 440 * for version 2 of the skin format, they are under parts.device.display 441 */ 442 n = aconfig_find(root, "display"); 443 if (n == NULL) { 444 n = aconfig_find(root, "parts"); 445 if (n != NULL) { 446 n = aconfig_find(n, "device"); 447 if (n != NULL) { 448 n = aconfig_find(n, "display"); 449 } 450 } 451 } 452 453 if (n != NULL) { 454 int width = aconfig_int(n, "width", hwConfig->hw_lcd_width); 455 int height = aconfig_int(n, "height", hwConfig->hw_lcd_height); 456 int depth = aconfig_int(n, "bpp", hwConfig->hw_lcd_depth); 457 458 if (width > 0 && height > 0) { 459 /* The emulated framebuffer wants sizes that are multiples of 4 */ 460 if (((width|height) & 3) != 0) { 461 width = (width+3) & ~3; 462 height = (height+3) & ~3; 463 D("adjusting LCD dimensions to (%dx%dx)", width, height); 464 } 465 466 /* only depth values of 16 and 32 are correct. 16 is the default. */ 467 if (depth != 32 && depth != 16) { 468 depth = 16; 469 D("adjusting LCD bit depth to %d", depth); 470 } 471 472 hwConfig->hw_lcd_width = width; 473 hwConfig->hw_lcd_height = height; 474 hwConfig->hw_lcd_depth = depth; 475 } 476 else { 477 D("ignoring invalid skin LCD dimensions (%dx%dx%d)", 478 width, height, depth); 479 } 480 } 481 482 *skinConfig = root; 483 *skinPath = strdup(path); 484 return; 485 486 DEFAULT_SKIN: 487 { 488 const unsigned char* layout_base; 489 size_t layout_size; 490 char* base; 491 492 skinName = "<builtin>"; 493 494 layout_base = android_resource_find( "layout", &layout_size ); 495 if (layout_base == NULL) { 496 fprintf(stderr, "Couldn't load builtin skin\n"); 497 exit(1); 498 } 499 base = malloc( layout_size+1 ); 500 memcpy( base, layout_base, layout_size ); 501 base[layout_size] = 0; 502 503 D("parsing built-in skin layout file (%d bytes)", (int)layout_size); 504 aconfig_load(root, base); 505 path = ":"; 506 } 507 goto FOUND_SKIN; 508 } 509 510 511 void 512 init_sdl_ui(AConfig* skinConfig, 513 const char* skinPath, 514 AndroidOptions* opts) 515 { 516 int win_x, win_y, flags; 517 518 signal(SIGINT, SIG_DFL); 519 #ifndef _WIN32 520 signal(SIGQUIT, SIG_DFL); 521 #endif 522 523 /* we're not a game, so allow the screensaver to run */ 524 setenv("SDL_VIDEO_ALLOW_SCREENSAVER","1",1); 525 526 flags = SDL_INIT_NOPARACHUTE; 527 if (!opts->no_window) 528 flags |= SDL_INIT_VIDEO; 529 530 if(SDL_Init(flags)){ 531 fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() ); 532 exit(1); 533 } 534 535 if (!opts->no_window) { 536 SDL_EnableUNICODE(!opts->raw_keys); 537 SDL_EnableKeyRepeat(0,0); 538 539 sdl_set_window_icon(); 540 } 541 else 542 { 543 #ifndef _WIN32 544 /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be 545 * able to run the emulator in the background (e.g. "emulator &"). 546 * despite the fact that the emulator should not grab input or try to 547 * write to the output in normal cases, we're stopped on some systems 548 * (e.g. OS X) 549 */ 550 signal(SIGTTIN, SIG_IGN); 551 signal(SIGTTOU, SIG_IGN); 552 #endif 553 } 554 atexit(sdl_at_exit); 555 556 user_config_get_window_pos(&win_x, &win_y); 557 558 if ( qemulator_init(qemulator_get(), skinConfig, skinPath, win_x, win_y, opts) < 0 ) { 559 fprintf(stderr, "### Error: could not load emulator skin from '%s'\n", skinPath); 560 exit(1); 561 } 562 563 /* add an onion overlay image if needed */ 564 if (opts->onion) { 565 SkinImage* onion = skin_image_find_simple( opts->onion ); 566 int alpha, rotate; 567 568 if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) { 569 alpha = (256*alpha)/100; 570 } else 571 alpha = 128; 572 573 if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) { 574 rotate &= 3; 575 } else 576 rotate = SKIN_ROTATION_0; 577 578 qemulator_get()->onion = onion; 579 qemulator_get()->onion_alpha = alpha; 580 qemulator_get()->onion_rotation = rotate; 581 } 582 } 583 584 /* this function is used to perform auto-detection of the 585 * system directory in the case of a SDK installation. 586 * 587 * we want to deal with several historical usages, hence 588 * the slightly complicated logic. 589 * 590 * NOTE: the function returns the path to the directory 591 * containing 'fileName'. this is *not* the full 592 * path to 'fileName'. 593 */ 594 static char* 595 _getSdkImagePath( const char* fileName ) 596 { 597 char temp[MAX_PATH]; 598 char* p = temp; 599 char* end = p + sizeof(temp); 600 char* q; 601 char* app; 602 603 static const char* const searchPaths[] = { 604 "", /* program's directory */ 605 "/lib/images", /* this is for SDK 1.0 */ 606 "/../platforms/android-1.1/images", /* this is for SDK 1.1 */ 607 NULL 608 }; 609 610 app = bufprint_app_dir(temp, end); 611 if (app >= end) 612 return NULL; 613 614 do { 615 int nn; 616 617 /* first search a few well-known paths */ 618 for (nn = 0; searchPaths[nn] != NULL; nn++) { 619 p = bufprint(app, end, "%s", searchPaths[nn]); 620 q = bufprint(p, end, "/%s", fileName); 621 if (q < end && path_exists(temp)) { 622 *p = 0; 623 goto FOUND_IT; 624 } 625 } 626 627 /* hmmm. let's assume that we are in a post-1.1 SDK 628 * scan ../platforms if it exists 629 */ 630 p = bufprint(app, end, "/../platforms"); 631 if (p < end) { 632 DirScanner* scanner = dirScanner_new(temp); 633 if (scanner != NULL) { 634 int found = 0; 635 const char* subdir; 636 637 for (;;) { 638 subdir = dirScanner_next(scanner); 639 if (!subdir) break; 640 641 q = bufprint(p, end, "/%s/images/%s", subdir, fileName); 642 if (q >= end || !path_exists(temp)) 643 continue; 644 645 found = 1; 646 p = bufprint(p, end, "/%s/images", subdir); 647 break; 648 } 649 dirScanner_free(scanner); 650 if (found) 651 break; 652 } 653 } 654 655 /* I'm out of ideas */ 656 return NULL; 657 658 } while (0); 659 660 FOUND_IT: 661 //D("image auto-detection: %s/%s", temp, fileName); 662 return android_strdup(temp); 663 } 664 665 static char* 666 _getSdkImage( const char* path, const char* file ) 667 { 668 char temp[MAX_PATH]; 669 char *p = temp, *end = p + sizeof(temp); 670 671 p = bufprint(temp, end, "%s/%s", path, file); 672 if (p >= end || !path_exists(temp)) 673 return NULL; 674 675 return android_strdup(temp); 676 } 677 678 static char* 679 _getSdkSystemImage( const char* path, const char* optionName, const char* file ) 680 { 681 char* image = _getSdkImage(path, file); 682 683 if (image == NULL) { 684 derror("Your system directory is missing the '%s' image file.\n" 685 "Please specify one with the '%s <filepath>' option", 686 file, optionName); 687 exit(2); 688 } 689 return image; 690 } 691 692 void sanitizeOptions( AndroidOptions* opts ) 693 { 694 /* legacy support: we used to use -system <dir> and -image <file> 695 * instead of -sysdir <dir> and -system <file>, so handle this by checking 696 * whether the options point to directories or files. 697 */ 698 if (opts->image != NULL) { 699 if (opts->system != NULL) { 700 if (opts->sysdir != NULL) { 701 derror( "You can't use -sysdir, -system and -image at the same time.\n" 702 "You should probably use '-sysdir <path> -system <file>'.\n" ); 703 exit(2); 704 } 705 } 706 dwarning( "Please note that -image is obsolete and that -system is now used to point\n" 707 "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" ); 708 opts->sysdir = opts->system; 709 opts->system = opts->image; 710 opts->image = NULL; 711 } 712 else if (opts->system != NULL && path_is_dir(opts->system)) { 713 if (opts->sysdir != NULL) { 714 derror( "Option -system should now be followed by a file path, not a directory one.\n" 715 "Please use '-sysdir <path>' to point to the system directory.\n" ); 716 exit(1); 717 } 718 dwarning( "Please note that the -system option should now be used to point to the initial\n" 719 "system image (like the obsolete -image option). To point to the system directory\n" 720 "please now use '-sysdir <path>' instead.\n" ); 721 722 opts->sysdir = opts->system; 723 opts->system = NULL; 724 } 725 726 if (opts->nojni) { 727 opts->no_jni = opts->nojni; 728 opts->nojni = 0; 729 } 730 731 if (opts->nocache) { 732 opts->no_cache = opts->nocache; 733 opts->nocache = 0; 734 } 735 736 if (opts->noaudio) { 737 opts->no_audio = opts->noaudio; 738 opts->noaudio = 0; 739 } 740 741 if (opts->noskin) { 742 opts->no_skin = opts->noskin; 743 opts->noskin = 0; 744 } 745 746 /* If -no-cache is used, ignore any -cache argument */ 747 if (opts->no_cache) { 748 opts->cache = 0; 749 } 750 751 /* the purpose of -no-audio is to disable sound output from the emulator, 752 * not to disable Audio emulation. So simply force the 'none' backends */ 753 if (opts->no_audio) 754 opts->audio = "none"; 755 756 /* we don't accept -skindir without -skin now 757 * to simplify the autoconfig stuff with virtual devices 758 */ 759 if (opts->no_skin) { 760 opts->skin = "320x480"; 761 opts->skindir = NULL; 762 } 763 764 if (opts->skindir) { 765 if (!opts->skin) { 766 derror( "the -skindir <path> option requires a -skin <name> option"); 767 exit(1); 768 } 769 } 770 771 if (opts->bootchart) { 772 char* end; 773 int timeout = strtol(opts->bootchart, &end, 10); 774 if (timeout == 0) 775 opts->bootchart = NULL; 776 else if (timeout < 0 || timeout > 15*60) { 777 derror( "timeout specified for -bootchart option is invalid.\n" 778 "please use integers between 1 and 900\n"); 779 exit(1); 780 } 781 } 782 } 783 784 AvdInfo* createAVD(AndroidOptions* opts, int* inAndroidBuild) 785 { 786 AvdInfo* ret = NULL; 787 char tmp[MAX_PATH]; 788 char* tmpend = tmp + sizeof(tmp); 789 char* android_build_root = NULL; 790 char* android_build_out = NULL; 791 792 /* If no AVD name was given, try to find the top of the 793 * Android build tree 794 */ 795 if (opts->avd == NULL) { 796 do { 797 char* out = getenv("ANDROID_PRODUCT_OUT"); 798 799 if (out == NULL || out[0] == 0) 800 break; 801 802 if (!path_exists(out)) { 803 derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n" 804 "You need to build the Android system before launching the emulator", 805 out); 806 exit(2); 807 } 808 809 android_build_root = path_parent( out, 4 ); 810 if (android_build_root == NULL || !path_exists(android_build_root)) { 811 derror("Can't find the Android build root from '%s'\n" 812 "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n" 813 "It should point to your product-specific build output directory.\n", 814 out ); 815 exit(2); 816 } 817 android_build_out = out; 818 D( "found Android build root: %s", android_build_root ); 819 D( "found Android build out: %s", android_build_out ); 820 } while (0); 821 } 822 /* if no virtual device name is given, and we're not in the 823 * Android build system, we'll need to perform some auto-detection 824 * magic :-) 825 */ 826 if (opts->avd == NULL && !android_build_out) 827 { 828 char dataDirIsSystem = 0; 829 830 if (!opts->sysdir) { 831 opts->sysdir = _getSdkImagePath("system.img"); 832 if (!opts->sysdir) { 833 derror( 834 "You did not specify a virtual device name, and the system\n" 835 "directory could not be found.\n\n" 836 "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n" 837 "to start a given virtual device (see -help-avd for details).\n\n" 838 839 "Otherwise, follow the instructions in -help-disk-images to start the emulator\n" 840 ); 841 exit(2); 842 } 843 D("autoconfig: -sysdir %s", opts->sysdir); 844 } 845 846 if (!opts->system) { 847 opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img"); 848 D("autoconfig: -system %s", opts->system); 849 } 850 851 if (!opts->kernel) { 852 opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu"); 853 D("autoconfig: -kernel %s", opts->kernel); 854 } 855 856 if (!opts->ramdisk) { 857 opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img"); 858 D("autoconfig: -ramdisk %s", opts->ramdisk); 859 } 860 861 /* if no data directory is specified, use the system directory */ 862 if (!opts->datadir) { 863 opts->datadir = android_strdup(opts->sysdir); 864 dataDirIsSystem = 1; 865 D("autoconfig: -datadir %s", opts->sysdir); 866 } 867 868 if (!opts->data) { 869 /* check for userdata-qemu.img in the data directory */ 870 bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir); 871 if (!path_exists(tmp)) { 872 derror( 873 "You did not provide the name of an Android Virtual Device\n" 874 "with the '-avd <name>' option. Read -help-avd for more information.\n\n" 875 876 "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n" 877 "to specify a data partition image file (I hope you know what you're doing).\n" 878 ); 879 exit(2); 880 } 881 882 opts->data = android_strdup(tmp); 883 D("autoconfig: -data %s", opts->data); 884 } 885 886 if (!opts->snapstorage && opts->datadir) { 887 bufprint(tmp, tmpend, "%s/snapshots.img", opts->datadir); 888 if (path_exists(tmp)) { 889 opts->snapstorage = android_strdup(tmp); 890 D("autoconfig: -snapstorage %s", opts->snapstorage); 891 } 892 } 893 } 894 895 /* setup the virtual device differently depending on whether 896 * we are in the Android build system or not 897 */ 898 if (opts->avd != NULL) 899 { 900 ret = avdInfo_new( opts->avd, android_avdParams ); 901 if (ret == NULL) { 902 /* an error message has already been printed */ 903 dprint("could not find virtual device named '%s'", opts->avd); 904 exit(1); 905 } 906 } 907 else 908 { 909 if (!android_build_out) { 910 android_build_out = android_build_root = opts->sysdir; 911 } 912 ret = avdInfo_newForAndroidBuild( 913 android_build_root, 914 android_build_out, 915 android_avdParams ); 916 917 if(ret == NULL) { 918 D("could not start virtual device\n"); 919 exit(1); 920 } 921 } 922 923 if (android_build_out) { 924 *inAndroidBuild = 1; 925 } else { 926 *inAndroidBuild = 0; 927 } 928 929 return ret; 930 } 931 932 933 934 935 #ifdef CONFIG_STANDALONE_UI 936 937 #include "android/protocol/core-connection.h" 938 #include "android/protocol/fb-updates-impl.h" 939 #include "android/protocol/user-events-proxy.h" 940 #include "android/protocol/core-commands-proxy.h" 941 #include "android/protocol/ui-commands-impl.h" 942 #include "android/protocol/attach-ui-impl.h" 943 944 /* Emulator's core port. */ 945 int android_base_port = 0; 946 947 // Base console port 948 #define CORE_BASE_PORT 5554 949 950 // Maximum number of core porocesses running simultaneously on a machine. 951 #define MAX_CORE_PROCS 16 952 953 // Socket timeout in millisec (set to 5 seconds) 954 #define CORE_PORT_TIMEOUT_MS 5000 955 956 #include "android/async-console.h" 957 958 typedef struct { 959 LoopIo io[1]; 960 int port; 961 int ok; 962 AsyncConsoleConnector connector[1]; 963 } CoreConsole; 964 965 static void 966 coreconsole_io_func(void* opaque, int fd, unsigned events) 967 { 968 CoreConsole* cc = opaque; 969 AsyncStatus status; 970 status = asyncConsoleConnector_run(cc->connector); 971 if (status == ASYNC_COMPLETE) { 972 cc->ok = 1; 973 } 974 } 975 976 static void 977 coreconsole_init(CoreConsole* cc, const SockAddress* address, Looper* looper) 978 { 979 int fd = socket_create_inet(SOCKET_STREAM); 980 AsyncStatus status; 981 cc->port = sock_address_get_port(address); 982 cc->ok = 0; 983 loopIo_init(cc->io, looper, fd, coreconsole_io_func, cc); 984 if (fd >= 0) { 985 status = asyncConsoleConnector_connect(cc->connector, address, cc->io); 986 if (status == ASYNC_ERROR) { 987 cc->ok = 0; 988 } 989 } 990 } 991 992 static void 993 coreconsole_done(CoreConsole* cc) 994 { 995 socket_close(cc->io->fd); 996 loopIo_done(cc->io); 997 } 998 999 /* List emulator core processes running on the given machine. 1000 * This routine is called from main() if -list-cores parameter is set in the 1001 * command line. 1002 * Param: 1003 * host Value passed with -list-core parameter. Must be either "localhost", or 1004 * an IP address of a machine where core processes must be enumerated. 1005 */ 1006 static void 1007 list_running_cores(const char* host) 1008 { 1009 Looper* looper; 1010 CoreConsole cores[MAX_CORE_PROCS]; 1011 SockAddress address; 1012 int nn, found; 1013 1014 if (sock_address_init_resolve(&address, host, CORE_BASE_PORT, 0) < 0) { 1015 derror("Unable to resolve hostname %s: %s", host, errno_str); 1016 return; 1017 } 1018 1019 looper = looper_newGeneric(); 1020 1021 for (nn = 0; nn < MAX_CORE_PROCS; nn++) { 1022 int port = CORE_BASE_PORT + nn*2; 1023 sock_address_set_port(&address, port); 1024 coreconsole_init(&cores[nn], &address, looper); 1025 } 1026 1027 looper_runWithTimeout(looper, CORE_PORT_TIMEOUT_MS*2); 1028 1029 found = 0; 1030 for (nn = 0; nn < MAX_CORE_PROCS; nn++) { 1031 int port = CORE_BASE_PORT + nn*2; 1032 if (cores[nn].ok) { 1033 if (found == 0) { 1034 fprintf(stdout, "Running emulator core processes:\n"); 1035 } 1036 fprintf(stdout, "Emulator console port %d\n", port); 1037 found++; 1038 } 1039 coreconsole_done(&cores[nn]); 1040 } 1041 looper_free(looper); 1042 1043 if (found == 0) { 1044 fprintf(stdout, "There were no running emulator core processes found on %s.\n", 1045 host); 1046 } 1047 } 1048 1049 /* Attaches starting UI to a running core process. 1050 * This routine is called from main() when -attach-core parameter is set, 1051 * indicating that this UI instance should attach to a running core, rather than 1052 * start a new core process. 1053 * Param: 1054 * opts Android options containing non-NULL attach_core. 1055 * Return: 1056 * 0 on success, or -1 on failure. 1057 */ 1058 static int 1059 attach_to_core(AndroidOptions* opts) { 1060 int iter; 1061 SockAddress console_socket; 1062 SockAddress** sockaddr_list; 1063 QEmulator* emulator; 1064 1065 // Parse attach_core param extracting the host name, and the port name. 1066 char* console_address = strdup(opts->attach_core); 1067 char* host_name = console_address; 1068 char* port_num = strchr(console_address, ':'); 1069 if (port_num == NULL) { 1070 // The host name is ommited, indicating the localhost 1071 host_name = "localhost"; 1072 port_num = console_address; 1073 } else if (port_num == console_address) { 1074 // Invalid. 1075 derror("Invalid value %s for -attach-core parameter\n", 1076 opts->attach_core); 1077 return -1; 1078 } else { 1079 *port_num = '\0'; 1080 port_num++; 1081 if (*port_num == '\0') { 1082 // Invalid. 1083 derror("Invalid value %s for -attach-core parameter\n", 1084 opts->attach_core); 1085 return -1; 1086 } 1087 } 1088 1089 /* Create socket address list for the given address, and pull appropriate 1090 * address to use for connection. Note that we're fine copying that address 1091 * out of the list, since INET and IN6 will entirely fit into SockAddress 1092 * structure. */ 1093 sockaddr_list = 1094 sock_address_list_create(host_name, port_num, SOCKET_LIST_FORCE_INET); 1095 free(console_address); 1096 if (sockaddr_list == NULL) { 1097 derror("Unable to resolve address %s: %s\n", 1098 opts->attach_core, errno_str); 1099 return -1; 1100 } 1101 for (iter = 0; sockaddr_list[iter] != NULL; iter++) { 1102 if (sock_address_get_family(sockaddr_list[iter]) == SOCKET_INET || 1103 sock_address_get_family(sockaddr_list[iter]) == SOCKET_IN6) { 1104 memcpy(&console_socket, sockaddr_list[iter], sizeof(SockAddress)); 1105 break; 1106 } 1107 } 1108 if (sockaddr_list[iter] == NULL) { 1109 derror("Unable to resolve address %s. Note that 'port' parameter passed to -attach-core\n" 1110 "must be resolvable into an IP address.\n", opts->attach_core); 1111 sock_address_list_free(sockaddr_list); 1112 return -1; 1113 } 1114 sock_address_list_free(sockaddr_list); 1115 1116 if (attachUiImpl_create(&console_socket)) { 1117 return -1; 1118 } 1119 1120 // Save core's port, and set the title. 1121 android_base_port = sock_address_get_port(&console_socket); 1122 emulator = qemulator_get(); 1123 qemulator_set_title(emulator); 1124 1125 return 0; 1126 } 1127 1128 1129 void handle_ui_options( AndroidOptions* opts ) 1130 { 1131 // Lets see if user just wants to list core process. 1132 if (opts->list_cores) { 1133 fprintf(stdout, "Enumerating running core processes.\n"); 1134 list_running_cores(opts->list_cores); 1135 exit(0); 1136 } 1137 } 1138 1139 int attach_ui_to_core( AndroidOptions* opts ) 1140 { 1141 // Lets see if we're attaching to a running core process here. 1142 if (opts->attach_core) { 1143 if (attach_to_core(opts)) { 1144 return -1; 1145 } 1146 // Connect to the core's UI control services. 1147 if (coreCmdProxy_create(attachUiImpl_get_console_socket())) { 1148 return -1; 1149 } 1150 // Connect to the core's user events service. 1151 if (userEventsProxy_create(attachUiImpl_get_console_socket())) { 1152 return -1; 1153 } 1154 } 1155 return 0; 1156 } 1157 1158 #else /* !CONFIG_STANDALONE_UI */ 1159 1160 void handle_ui_options( AndroidOptions* opts ) 1161 { 1162 return; 1163 } 1164 1165 int attach_ui_to_core( AndroidOptions* opts ) 1166 { 1167 return 0; 1168 } 1169 1170 #endif /* CONFIG_STANDALONE_UI */ 1171