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 = getenv("ANDROID_BUILD_TOP"); 810 if (android_build_root == NULL || android_build_root[0] == 0) 811 break; 812 813 if (!path_exists(android_build_root)) { 814 derror("Can't find the Android build root '%s'\n" 815 "Please check the definition of the ANDROID_BUILD_TOP variable.\n" 816 "It should point to the root of your source tree.\n", 817 android_build_root ); 818 exit(2); 819 } 820 android_build_out = out; 821 D( "found Android build root: %s", android_build_root ); 822 D( "found Android build out: %s", android_build_out ); 823 } while (0); 824 } 825 /* if no virtual device name is given, and we're not in the 826 * Android build system, we'll need to perform some auto-detection 827 * magic :-) 828 */ 829 if (opts->avd == NULL && !android_build_out) 830 { 831 char dataDirIsSystem = 0; 832 833 if (!opts->sysdir) { 834 opts->sysdir = _getSdkImagePath("system.img"); 835 if (!opts->sysdir) { 836 derror( 837 "You did not specify a virtual device name, and the system\n" 838 "directory could not be found.\n\n" 839 "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n" 840 "to start a given virtual device (see -help-avd for details).\n\n" 841 842 "Otherwise, follow the instructions in -help-disk-images to start the emulator\n" 843 ); 844 exit(2); 845 } 846 D("autoconfig: -sysdir %s", opts->sysdir); 847 } 848 849 if (!opts->system) { 850 opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img"); 851 D("autoconfig: -system %s", opts->system); 852 } 853 854 if (!opts->kernel) { 855 opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu"); 856 D("autoconfig: -kernel %s", opts->kernel); 857 } 858 859 if (!opts->ramdisk) { 860 opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img"); 861 D("autoconfig: -ramdisk %s", opts->ramdisk); 862 } 863 864 /* if no data directory is specified, use the system directory */ 865 if (!opts->datadir) { 866 opts->datadir = android_strdup(opts->sysdir); 867 dataDirIsSystem = 1; 868 D("autoconfig: -datadir %s", opts->sysdir); 869 } 870 871 if (!opts->data) { 872 /* check for userdata-qemu.img in the data directory */ 873 bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir); 874 if (!path_exists(tmp)) { 875 derror( 876 "You did not provide the name of an Android Virtual Device\n" 877 "with the '-avd <name>' option. Read -help-avd for more information.\n\n" 878 879 "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n" 880 "to specify a data partition image file (I hope you know what you're doing).\n" 881 ); 882 exit(2); 883 } 884 885 opts->data = android_strdup(tmp); 886 D("autoconfig: -data %s", opts->data); 887 } 888 889 if (!opts->snapstorage && opts->datadir) { 890 bufprint(tmp, tmpend, "%s/snapshots.img", opts->datadir); 891 if (path_exists(tmp)) { 892 opts->snapstorage = android_strdup(tmp); 893 D("autoconfig: -snapstorage %s", opts->snapstorage); 894 } 895 } 896 } 897 898 /* setup the virtual device differently depending on whether 899 * we are in the Android build system or not 900 */ 901 if (opts->avd != NULL) 902 { 903 ret = avdInfo_new( opts->avd, android_avdParams ); 904 if (ret == NULL) { 905 /* an error message has already been printed */ 906 dprint("could not find virtual device named '%s'", opts->avd); 907 exit(1); 908 } 909 } 910 else 911 { 912 if (!android_build_out) { 913 android_build_out = android_build_root = opts->sysdir; 914 } 915 ret = avdInfo_newForAndroidBuild( 916 android_build_root, 917 android_build_out, 918 android_avdParams ); 919 920 if(ret == NULL) { 921 D("could not start virtual device\n"); 922 exit(1); 923 } 924 } 925 926 if (android_build_out) { 927 *inAndroidBuild = 1; 928 } else { 929 *inAndroidBuild = 0; 930 } 931 932 return ret; 933 } 934 935 936 937 938 #ifdef CONFIG_STANDALONE_UI 939 940 #include "android/protocol/core-connection.h" 941 #include "android/protocol/fb-updates-impl.h" 942 #include "android/protocol/user-events-proxy.h" 943 #include "android/protocol/core-commands-proxy.h" 944 #include "android/protocol/ui-commands-impl.h" 945 #include "android/protocol/attach-ui-impl.h" 946 947 /* Emulator's core port. */ 948 int android_base_port = 0; 949 950 // Base console port 951 #define CORE_BASE_PORT 5554 952 953 // Maximum number of core porocesses running simultaneously on a machine. 954 #define MAX_CORE_PROCS 16 955 956 // Socket timeout in millisec (set to 5 seconds) 957 #define CORE_PORT_TIMEOUT_MS 5000 958 959 #include "android/async-console.h" 960 961 typedef struct { 962 LoopIo io[1]; 963 int port; 964 int ok; 965 AsyncConsoleConnector connector[1]; 966 } CoreConsole; 967 968 static void 969 coreconsole_io_func(void* opaque, int fd, unsigned events) 970 { 971 CoreConsole* cc = opaque; 972 AsyncStatus status; 973 status = asyncConsoleConnector_run(cc->connector); 974 if (status == ASYNC_COMPLETE) { 975 cc->ok = 1; 976 } 977 } 978 979 static void 980 coreconsole_init(CoreConsole* cc, const SockAddress* address, Looper* looper) 981 { 982 int fd = socket_create_inet(SOCKET_STREAM); 983 AsyncStatus status; 984 cc->port = sock_address_get_port(address); 985 cc->ok = 0; 986 loopIo_init(cc->io, looper, fd, coreconsole_io_func, cc); 987 if (fd >= 0) { 988 status = asyncConsoleConnector_connect(cc->connector, address, cc->io); 989 if (status == ASYNC_ERROR) { 990 cc->ok = 0; 991 } 992 } 993 } 994 995 static void 996 coreconsole_done(CoreConsole* cc) 997 { 998 socket_close(cc->io->fd); 999 loopIo_done(cc->io); 1000 } 1001 1002 /* List emulator core processes running on the given machine. 1003 * This routine is called from main() if -list-cores parameter is set in the 1004 * command line. 1005 * Param: 1006 * host Value passed with -list-core parameter. Must be either "localhost", or 1007 * an IP address of a machine where core processes must be enumerated. 1008 */ 1009 static void 1010 list_running_cores(const char* host) 1011 { 1012 Looper* looper; 1013 CoreConsole cores[MAX_CORE_PROCS]; 1014 SockAddress address; 1015 int nn, found; 1016 1017 if (sock_address_init_resolve(&address, host, CORE_BASE_PORT, 0) < 0) { 1018 derror("Unable to resolve hostname %s: %s", host, errno_str); 1019 return; 1020 } 1021 1022 looper = looper_newGeneric(); 1023 1024 for (nn = 0; nn < MAX_CORE_PROCS; nn++) { 1025 int port = CORE_BASE_PORT + nn*2; 1026 sock_address_set_port(&address, port); 1027 coreconsole_init(&cores[nn], &address, looper); 1028 } 1029 1030 looper_runWithTimeout(looper, CORE_PORT_TIMEOUT_MS*2); 1031 1032 found = 0; 1033 for (nn = 0; nn < MAX_CORE_PROCS; nn++) { 1034 int port = CORE_BASE_PORT + nn*2; 1035 if (cores[nn].ok) { 1036 if (found == 0) { 1037 fprintf(stdout, "Running emulator core processes:\n"); 1038 } 1039 fprintf(stdout, "Emulator console port %d\n", port); 1040 found++; 1041 } 1042 coreconsole_done(&cores[nn]); 1043 } 1044 looper_free(looper); 1045 1046 if (found == 0) { 1047 fprintf(stdout, "There were no running emulator core processes found on %s.\n", 1048 host); 1049 } 1050 } 1051 1052 /* Attaches starting UI to a running core process. 1053 * This routine is called from main() when -attach-core parameter is set, 1054 * indicating that this UI instance should attach to a running core, rather than 1055 * start a new core process. 1056 * Param: 1057 * opts Android options containing non-NULL attach_core. 1058 * Return: 1059 * 0 on success, or -1 on failure. 1060 */ 1061 static int 1062 attach_to_core(AndroidOptions* opts) { 1063 int iter; 1064 SockAddress console_socket; 1065 SockAddress** sockaddr_list; 1066 QEmulator* emulator; 1067 1068 // Parse attach_core param extracting the host name, and the port name. 1069 char* console_address = strdup(opts->attach_core); 1070 char* host_name = console_address; 1071 char* port_num = strchr(console_address, ':'); 1072 if (port_num == NULL) { 1073 // The host name is ommited, indicating the localhost 1074 host_name = "localhost"; 1075 port_num = console_address; 1076 } else if (port_num == console_address) { 1077 // Invalid. 1078 derror("Invalid value %s for -attach-core parameter\n", 1079 opts->attach_core); 1080 return -1; 1081 } else { 1082 *port_num = '\0'; 1083 port_num++; 1084 if (*port_num == '\0') { 1085 // Invalid. 1086 derror("Invalid value %s for -attach-core parameter\n", 1087 opts->attach_core); 1088 return -1; 1089 } 1090 } 1091 1092 /* Create socket address list for the given address, and pull appropriate 1093 * address to use for connection. Note that we're fine copying that address 1094 * out of the list, since INET and IN6 will entirely fit into SockAddress 1095 * structure. */ 1096 sockaddr_list = 1097 sock_address_list_create(host_name, port_num, SOCKET_LIST_FORCE_INET); 1098 free(console_address); 1099 if (sockaddr_list == NULL) { 1100 derror("Unable to resolve address %s: %s\n", 1101 opts->attach_core, errno_str); 1102 return -1; 1103 } 1104 for (iter = 0; sockaddr_list[iter] != NULL; iter++) { 1105 if (sock_address_get_family(sockaddr_list[iter]) == SOCKET_INET || 1106 sock_address_get_family(sockaddr_list[iter]) == SOCKET_IN6) { 1107 memcpy(&console_socket, sockaddr_list[iter], sizeof(SockAddress)); 1108 break; 1109 } 1110 } 1111 if (sockaddr_list[iter] == NULL) { 1112 derror("Unable to resolve address %s. Note that 'port' parameter passed to -attach-core\n" 1113 "must be resolvable into an IP address.\n", opts->attach_core); 1114 sock_address_list_free(sockaddr_list); 1115 return -1; 1116 } 1117 sock_address_list_free(sockaddr_list); 1118 1119 if (attachUiImpl_create(&console_socket)) { 1120 return -1; 1121 } 1122 1123 // Save core's port, and set the title. 1124 android_base_port = sock_address_get_port(&console_socket); 1125 emulator = qemulator_get(); 1126 qemulator_set_title(emulator); 1127 1128 return 0; 1129 } 1130 1131 1132 void handle_ui_options( AndroidOptions* opts ) 1133 { 1134 // Lets see if user just wants to list core process. 1135 if (opts->list_cores) { 1136 fprintf(stdout, "Enumerating running core processes.\n"); 1137 list_running_cores(opts->list_cores); 1138 exit(0); 1139 } 1140 } 1141 1142 int attach_ui_to_core( AndroidOptions* opts ) 1143 { 1144 // Lets see if we're attaching to a running core process here. 1145 if (opts->attach_core) { 1146 if (attach_to_core(opts)) { 1147 return -1; 1148 } 1149 // Connect to the core's UI control services. 1150 if (coreCmdProxy_create(attachUiImpl_get_console_socket())) { 1151 return -1; 1152 } 1153 // Connect to the core's user events service. 1154 if (userEventsProxy_create(attachUiImpl_get_console_socket())) { 1155 return -1; 1156 } 1157 } 1158 return 0; 1159 } 1160 1161 #else /* !CONFIG_STANDALONE_UI */ 1162 1163 void handle_ui_options( AndroidOptions* opts ) 1164 { 1165 return; 1166 } 1167 1168 int attach_ui_to_core( AndroidOptions* opts ) 1169 { 1170 return 0; 1171 } 1172 1173 #endif /* CONFIG_STANDALONE_UI */ 1174