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