main.c revision 873c3cb5688092d2822837511cfb2b330d265801
1/* Copyright (C) 2006-2008 The Android Open Source Project 2** 3** This software is licensed under the terms of the GNU General Public 4** License version 2, as published by the Free Software Foundation, and 5** may be copied, distributed, and modified under those terms. 6** 7** This program is distributed in the hope that it will be useful, 8** but WITHOUT ANY WARRANTY; without even the implied warranty of 9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10** GNU General Public License for more details. 11*/ 12 13#include <signal.h> 14#include <unistd.h> 15#include <string.h> 16#include <sys/time.h> 17#ifdef _WIN32 18#include <process.h> 19#endif 20 21#include "sockets.h" 22 23#include "android/android.h" 24#include "qemu-common.h" 25#include "sysemu.h" 26#include "console.h" 27#include "user-events.h" 28 29#include <SDL.h> 30#include <SDL_syswm.h> 31 32#include "math.h" 33 34#include "android/charmap.h" 35#include "android/utils/debug.h" 36#include "android/config.h" 37#include "android/config/config.h" 38 39#include "android/user-config.h" 40#include "android/utils/bufprint.h" 41#include "android/utils/filelock.h" 42#include "android/utils/lineinput.h" 43#include "android/utils/path.h" 44#include "android/utils/tempfile.h" 45 46#include "android/main-common.h" 47#include "android/help.h" 48#include "hw/goldfish_nand.h" 49 50#include "android/globals.h" 51 52#include "android/qemulator.h" 53#include "android/display.h" 54 55#include "android/snapshot.h" 56 57#include "android/framebuffer.h" 58#include "iolooper.h" 59 60AndroidRotation android_framebuffer_rotation; 61 62#define STRINGIFY(x) _STRINGIFY(x) 63#define _STRINGIFY(x) #x 64 65#ifdef ANDROID_SDK_TOOLS_REVISION 66# define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0" 67#else 68# define VERSION_STRING "standalone" 69#endif 70 71#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0) 72 73extern int control_console_start( int port ); /* in control.c */ 74 75extern int qemu_milli_needed; 76 77/* the default device DPI if none is specified by the skin 78 */ 79#define DEFAULT_DEVICE_DPI 165 80 81#ifdef CONFIG_TRACE 82extern void start_tracing(void); 83extern void stop_tracing(void); 84#endif 85 86unsigned long android_verbose; 87 88int qemu_main(int argc, char **argv); 89 90/* this function dumps the QEMU help */ 91extern void help( void ); 92extern void emulator_help( void ); 93 94#define VERBOSE_OPT(str,var) { str, &var } 95 96#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y }, 97static const struct { const char* name; int flag; const char* text; } 98verbose_options[] = { 99 VERBOSE_TAG_LIST 100 { 0, 0, 0 } 101}; 102 103void emulator_help( void ) 104{ 105 STRALLOC_DEFINE(out); 106 android_help_main(out); 107 printf( "%.*s", out->n, out->s ); 108 stralloc_reset(out); 109 exit(1); 110} 111 112/* TODO: Put in shared source file */ 113static char* 114_getFullFilePath( const char* rootPath, const char* fileName ) 115{ 116 if (path_is_absolute(fileName)) { 117 return ASTRDUP(fileName); 118 } else { 119 char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp); 120 121 p = bufprint(temp, end, "%s/%s", rootPath, fileName); 122 if (p >= end) { 123 return NULL; 124 } 125 return ASTRDUP(temp); 126 } 127} 128 129static uint64_t 130_adjustPartitionSize( const char* description, 131 uint64_t imageBytes, 132 uint64_t defaultBytes, 133 int inAndroidBuild ) 134{ 135 char temp[64]; 136 unsigned imageMB; 137 unsigned defaultMB; 138 139 if (imageBytes <= defaultBytes) 140 return defaultBytes; 141 142 imageMB = convertBytesToMB(imageBytes); 143 defaultMB = convertBytesToMB(defaultBytes); 144 145 if (imageMB > defaultMB) { 146 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB); 147 } else { 148 snprintf(temp, sizeof temp, "(%lld bytes > %lld bytes)", imageBytes, defaultBytes); 149 } 150 151 if (inAndroidBuild) { 152 dwarning("%s partition size adjusted to match image file %s\n", description, temp); 153 } 154 155 return convertMBToBytes(imageMB); 156} 157 158/* Parses a -webcam option, extracting 'name', and 'dir' values. 159 * Param: 160 * param - -webcam option, that should be formatted as such: 161 * name=<name>[,dir=<direction>] 162 * name, name_size - buffer (and its size) where to receive <name> 163 * dir, dir_size - buffer (and its size) where to receive <direction> 164 */ 165static void 166_parseWebcamOption(const char* param, 167 char* name, size_t name_size, 168 char* dir, size_t dir_size) 169{ 170 const char* dr; 171 const char* wc_opt = param; 172 173 /* Must start with 'name=' */ 174 if (strlen(wc_opt) <= 5 || memcmp(wc_opt, "name=", 5)) { 175 derror("Invalid value for -webcam parameter: %s\n", param); 176 exit(1); 177 } 178 179 /* Move on to 'name' value. */ 180 wc_opt += 5; 181 dr = strchr(wc_opt, ','); 182 if (dr == NULL) { 183 dr = wc_opt + strlen(wc_opt); 184 } 185 186 /* Make sure that <name> fits */ 187 if ((dr - wc_opt) < name_size) { 188 memcpy(name, wc_opt, dr - wc_opt); 189 name[dr - wc_opt] = '\0'; 190 if (*dr == '\0') { 191 /* Default direction value is 'front' */ 192 strcpy(dir, "front"); 193 return; 194 } else { 195 dr++; 196 } 197 } else { 198 derror("Invalid <name> value for -webcam parameter: %s\n", param); 199 exit(1); 200 } 201 202 /* Parse 'dir'. Must begin with 'dir=' */ 203 if (strlen(dr) <= 4 || memcmp(dr, "dir=", 4)) { 204 derror("Invalid value for -webcam parameter: %s\n", param); 205 exit(1); 206 } 207 dr += 4; 208 /* Check the bounds, and the values */ 209 if (strlen(dr) >= dir_size || (strcmp(dr, "front") && strcmp(dr, "back"))) { 210 derror("Invalid <direction> value for -webcam parameter: %s\n" 211 "Valid values are: 'front', or 'back'\n", param); 212 exit(1); 213 } 214 strcpy(dir, dr); 215} 216 217int main(int argc, char **argv) 218{ 219 char tmp[MAX_PATH]; 220 char* tmpend = tmp + sizeof(tmp); 221 char* args[128]; 222 int n; 223 char* opt; 224 /* The emulator always uses the first serial port for kernel messages 225 * and the second one for qemud. So start at the third if we need one 226 * for logcat or 'shell' 227 */ 228 int serial = 2; 229 int shell_serial = 0; 230 231 int forceArmv7 = 0; 232 233 AndroidHwConfig* hw; 234 AvdInfo* avd; 235 AConfig* skinConfig; 236 char* skinPath; 237 int inAndroidBuild; 238 uint64_t defaultPartitionSize = convertMBToBytes(66); 239 240 AndroidOptions opts[1]; 241 /* net.shared_net_ip boot property value. */ 242 char boot_prop_ip[64]; 243 boot_prop_ip[0] = '\0'; 244 245 args[0] = argv[0]; 246 247 if ( android_parse_options( &argc, &argv, opts ) < 0 ) { 248 exit(1); 249 } 250 251#ifdef _WIN32 252 socket_init(); 253#endif 254 255 handle_ui_options(opts); 256 257 while (argc-- > 1) { 258 opt = (++argv)[0]; 259 260 if(!strcmp(opt, "-qemu")) { 261 argc--; 262 argv++; 263 break; 264 } 265 266 if (!strcmp(opt, "-help")) { 267 emulator_help(); 268 } 269 270 if (!strncmp(opt, "-help-",6)) { 271 STRALLOC_DEFINE(out); 272 opt += 6; 273 274 if (!strcmp(opt, "all")) { 275 android_help_all(out); 276 } 277 else if (android_help_for_option(opt, out) == 0) { 278 /* ok */ 279 } 280 else if (android_help_for_topic(opt, out) == 0) { 281 /* ok */ 282 } 283 if (out->n > 0) { 284 printf("\n%.*s", out->n, out->s); 285 exit(0); 286 } 287 288 fprintf(stderr, "unknown option: -help-%s\n", opt); 289 fprintf(stderr, "please use -help for a list of valid topics\n"); 290 exit(1); 291 } 292 293 if (opt[0] == '-') { 294 fprintf(stderr, "unknown option: %s\n", opt); 295 fprintf(stderr, "please use -help for a list of valid options\n"); 296 exit(1); 297 } 298 299 fprintf(stderr, "invalid command-line parameter: %s.\n", opt); 300 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n"); 301 fprintf(stderr, "please use -help for more information\n"); 302 exit(1); 303 } 304 305 if (opts->version) { 306 printf("Android emulator version %s\n" 307 "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n" 308 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n", 309#if defined ANDROID_BUILD_ID 310 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" ); 311#else 312 VERSION_STRING); 313#endif 314 printf(" This software is licensed under the terms of the GNU General Public\n" 315 " License version 2, as published by the Free Software Foundation, and\n" 316 " may be copied, distributed, and modified under those terms.\n\n" 317 " This program is distributed in the hope that it will be useful,\n" 318 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 319 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 320 " GNU General Public License for more details.\n\n"); 321 322 exit(0); 323 } 324 325 if (opts->snapshot_list) { 326 if (opts->snapstorage == NULL) { 327 /* Need to find the default snapstorage */ 328 avd = createAVD(opts, &inAndroidBuild); 329 opts->snapstorage = avdInfo_getSnapStoragePath(avd); 330 if (opts->snapstorage != NULL) { 331 D("autoconfig: -snapstorage %s", opts->snapstorage); 332 } else { 333 if (inAndroidBuild) { 334 derror("You must use the -snapstorage <file> option to specify a snapshot storage file!\n"); 335 } else { 336 derror("This AVD doesn't have snapshotting enabled!\n"); 337 } 338 exit(1); 339 } 340 } 341 snapshot_print_and_exit(opts->snapstorage); 342 } 343 344 sanitizeOptions(opts); 345 346 /* Initialization of UI started with -attach-core should work differently 347 * than initialization of UI that starts the core. In particular.... 348 */ 349 350 /* -charmap is incompatible with -attach-core, because particular 351 * charmap gets set up in the running core. */ 352 if (android_charmap_setup(opts->charmap)) { 353 exit(1); 354 } 355 356 /* Parses options and builds an appropriate AVD. */ 357 avd = android_avdInfo = createAVD(opts, &inAndroidBuild); 358 359 /* get the skin from the virtual device configuration */ 360 if (opts->skindir != NULL) { 361 if (opts->skin == NULL) { 362 /* NOTE: Normally handled by sanitizeOptions(), just be safe */ 363 derror("The -skindir <path> option requires a -skin <name> option"); 364 exit(2); 365 } 366 } else { 367 char* skinName; 368 char* skinDir; 369 370 avdInfo_getSkinInfo(avd, &skinName, &skinDir); 371 372 if (opts->skin == NULL) { 373 opts->skin = skinName; 374 D("autoconfig: -skin %s", opts->skin); 375 } else { 376 AFREE(skinName); 377 } 378 379 opts->skindir = skinDir; 380 D("autoconfig: -skindir %s", opts->skindir); 381 } 382 383 /* Read hardware configuration */ 384 hw = android_hw; 385 if (avdInfo_initHwConfig(avd, hw) < 0) { 386 derror("could not read hardware configuration ?"); 387 exit(1); 388 } 389 390 if (opts->keyset) { 391 parse_keyset(opts->keyset, opts); 392 if (!android_keyset) { 393 fprintf(stderr, 394 "emulator: WARNING: could not find keyset file named '%s'," 395 " using defaults instead\n", 396 opts->keyset); 397 } 398 } 399 if (!android_keyset) { 400 parse_keyset("default", opts); 401 if (!android_keyset) { 402 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() ); 403 if (!android_keyset) { 404 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" ); 405 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" ); 406 exit(1); 407 } 408 if (!opts->keyset) 409 write_default_keyset(); 410 } 411 } 412 413 if (opts->shared_net_id) { 414 char* end; 415 long shared_net_id = strtol(opts->shared_net_id, &end, 0); 416 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) { 417 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n"); 418 exit(1); 419 } 420 snprintf(boot_prop_ip, sizeof(boot_prop_ip), 421 "net.shared_net_ip=10.1.2.%ld", shared_net_id); 422 } 423 424 425 user_config_init(); 426 parse_skin_files(opts->skindir, opts->skin, opts, hw, 427 &skinConfig, &skinPath); 428 429 if (!opts->netspeed && skin_network_speed) { 430 D("skin network speed: '%s'", skin_network_speed); 431 if (strcmp(skin_network_speed, NETWORK_SPEED_DEFAULT) != 0) { 432 opts->netspeed = (char*)skin_network_speed; 433 } 434 } 435 if (!opts->netdelay && skin_network_delay) { 436 D("skin network delay: '%s'", skin_network_delay); 437 if (strcmp(skin_network_delay, NETWORK_DELAY_DEFAULT) != 0) { 438 opts->netdelay = (char*)skin_network_delay; 439 } 440 } 441 442 if (opts->trace) { 443 char* tracePath = avdInfo_getTracePath(avd, opts->trace); 444 int ret; 445 446 if (tracePath == NULL) { 447 derror( "bad -trace parameter" ); 448 exit(1); 449 } 450 ret = path_mkdir_if_needed( tracePath, 0755 ); 451 if (ret < 0) { 452 fprintf(stderr, "could not create directory '%s'\n", tmp); 453 exit(2); 454 } 455 opts->trace = tracePath; 456 } 457 458 /* Update CPU architecture for HW configs created from build dir. */ 459 if (inAndroidBuild) { 460#if defined(TARGET_ARM) 461 free(android_hw->hw_cpu_arch); 462 android_hw->hw_cpu_arch = ASTRDUP("arm"); 463#elif defined(TARGET_I386) 464 free(android_hw->hw_cpu_arch); 465 android_hw->hw_cpu_arch = ASTRDUP("x86"); 466#endif 467 } 468 469 n = 1; 470 /* generate arguments for the underlying qemu main() */ 471 { 472 char* kernelFile = opts->kernel; 473 int kernelFileLen; 474 475 if (kernelFile == NULL) { 476 kernelFile = avdInfo_getKernelPath(avd); 477 if (kernelFile == NULL) { 478 derror( "This AVD's configuration is missing a kernel file!!" ); 479 exit(2); 480 } 481 D("autoconfig: -kernel %s", kernelFile); 482 } 483 if (!path_exists(kernelFile)) { 484 derror( "Invalid or missing kernel image file: %s", kernelFile ); 485 exit(2); 486 } 487 488 hw->kernel_path = kernelFile; 489 490 /* If the kernel image name ends in "-armv7", then change the cpu 491 * type automatically. This is a poor man's approach to configuration 492 * management, but should allow us to get past building ARMv7 493 * system images with dex preopt pass without introducing too many 494 * changes to the emulator sources. 495 * 496 * XXX: 497 * A 'proper' change would require adding some sort of hardware-property 498 * to each AVD config file, then automatically determine its value for 499 * full Android builds (depending on some environment variable), plus 500 * some build system changes. I prefer not to do that for now for reasons 501 * of simplicity. 502 */ 503 kernelFileLen = strlen(kernelFile); 504 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) { 505 forceArmv7 = 1; 506 } 507 } 508 509 if (boot_prop_ip[0]) { 510 args[n++] = "-boot-property"; 511 args[n++] = boot_prop_ip; 512 } 513 514 if (opts->tcpdump) { 515 args[n++] = "-tcpdump"; 516 args[n++] = opts->tcpdump; 517 } 518 519#ifdef CONFIG_NAND_LIMITS 520 if (opts->nand_limits) { 521 args[n++] = "-nand-limits"; 522 args[n++] = opts->nand_limits; 523 } 524#endif 525 526 if (opts->timezone) { 527 args[n++] = "-timezone"; 528 args[n++] = opts->timezone; 529 } 530 531 if (opts->netspeed) { 532 args[n++] = "-netspeed"; 533 args[n++] = opts->netspeed; 534 } 535 if (opts->netdelay) { 536 args[n++] = "-netdelay"; 537 args[n++] = opts->netdelay; 538 } 539 if (opts->netfast) { 540 args[n++] = "-netfast"; 541 } 542 543 if (opts->audio) { 544 args[n++] = "-audio"; 545 args[n++] = opts->audio; 546 } 547 548 if (opts->cpu_delay) { 549 args[n++] = "-cpu-delay"; 550 args[n++] = opts->cpu_delay; 551 } 552 553 if (opts->dns_server) { 554 args[n++] = "-dns-server"; 555 args[n++] = opts->dns_server; 556 } 557 558 /* opts->ramdisk is never NULL (see createAVD) here */ 559 if (opts->ramdisk) { 560 AFREE(hw->disk_ramdisk_path); 561 hw->disk_ramdisk_path = ASTRDUP(opts->ramdisk); 562 } 563 else if (!hw->disk_ramdisk_path[0]) { 564 hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd); 565 D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path); 566 } 567 568 /* -partition-size is used to specify the max size of both the system 569 * and data partition sizes. 570 */ 571 if (opts->partition_size) { 572 char* end; 573 long sizeMB = strtol(opts->partition_size, &end, 0); 574 long minSizeMB = 10; 575 long maxSizeMB = LONG_MAX / ONE_MB; 576 577 if (sizeMB < 0 || *end != 0) { 578 derror( "-partition-size must be followed by a positive integer" ); 579 exit(1); 580 } 581 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) { 582 derror( "partition-size (%d) must be between %dMB and %dMB", 583 sizeMB, minSizeMB, maxSizeMB ); 584 exit(1); 585 } 586 defaultPartitionSize = (uint64_t) sizeMB * ONE_MB; 587 } 588 589 590 /** SYSTEM PARTITION **/ 591 592 if (opts->sysdir == NULL) { 593 if (avdInfo_inAndroidBuild(avd)) { 594 opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd)); 595 D("autoconfig: -sysdir %s", opts->sysdir); 596 } 597 } 598 599 if (opts->sysdir != NULL) { 600 if (!path_exists(opts->sysdir)) { 601 derror("Directory does not exist: %s", opts->sysdir); 602 exit(1); 603 } 604 } 605 606 { 607 char* rwImage = NULL; 608 char* initImage = NULL; 609 610 do { 611 if (opts->system == NULL) { 612 /* If -system is not used, try to find a runtime system image 613 * (i.e. system-qemu.img) in the content directory. 614 */ 615 rwImage = avdInfo_getSystemImagePath(avd); 616 if (rwImage != NULL) { 617 break; 618 } 619 /* Otherwise, try to find the initial system image */ 620 initImage = avdInfo_getSystemInitImagePath(avd); 621 if (initImage == NULL) { 622 derror("No initial system image for this configuration!"); 623 exit(1); 624 } 625 break; 626 } 627 628 /* If -system <name> is used, use it to find the initial image */ 629 if (opts->sysdir != NULL && !path_exists(opts->system)) { 630 initImage = _getFullFilePath(opts->sysdir, opts->system); 631 } else { 632 initImage = ASTRDUP(opts->system); 633 } 634 if (!path_exists(initImage)) { 635 derror("System image file doesn't exist: %s", initImage); 636 exit(1); 637 } 638 639 } while (0); 640 641 if (rwImage != NULL) { 642 /* Use the read/write image file directly */ 643 hw->disk_systemPartition_path = rwImage; 644 hw->disk_systemPartition_initPath = NULL; 645 D("Using direct system image: %s", rwImage); 646 } else if (initImage != NULL) { 647 hw->disk_systemPartition_path = NULL; 648 hw->disk_systemPartition_initPath = initImage; 649 D("Using initial system image: %s", initImage); 650 } 651 652 /* Check the size of the system partition image. 653 * If we have an AVD, it must be smaller than 654 * the disk.systemPartition.size hardware property. 655 * 656 * Otherwise, we need to adjust the systemPartitionSize 657 * automatically, and print a warning. 658 * 659 */ 660 const char* systemImage = hw->disk_systemPartition_path; 661 uint64_t systemBytes; 662 663 if (systemImage == NULL) 664 systemImage = hw->disk_systemPartition_initPath; 665 666 if (path_get_size(systemImage, &systemBytes) < 0) { 667 derror("Missing system image: %s", systemImage); 668 exit(1); 669 } 670 671 hw->disk_systemPartition_size = 672 _adjustPartitionSize("system", systemBytes, defaultPartitionSize, 673 avdInfo_inAndroidBuild(avd)); 674 } 675 676 /** DATA PARTITION **/ 677 678 if (opts->datadir) { 679 if (!path_exists(opts->datadir)) { 680 derror("Invalid -datadir directory: %s", opts->datadir); 681 } 682 } 683 684 { 685 char* dataImage = NULL; 686 char* initImage = NULL; 687 688 do { 689 if (!opts->data) { 690 dataImage = avdInfo_getDataImagePath(avd); 691 if (dataImage != NULL) { 692 D("autoconfig: -data %s", dataImage); 693 break; 694 } 695 dataImage = avdInfo_getDefaultDataImagePath(avd); 696 if (dataImage == NULL) { 697 derror("No data image path for this configuration!"); 698 exit (1); 699 } 700 opts->wipe_data = 1; 701 break; 702 } 703 704 if (opts->datadir) { 705 dataImage = _getFullFilePath(opts->datadir, opts->data); 706 } else { 707 dataImage = ASTRDUP(opts->data); 708 } 709 } while (0); 710 711 if (opts->initdata != NULL) { 712 initImage = ASTRDUP(opts->initdata); 713 if (!path_exists(initImage)) { 714 derror("Invalid initial data image path: %s", initImage); 715 exit(1); 716 } 717 } else { 718 initImage = avdInfo_getDataInitImagePath(avd); 719 D("autoconfig: -initdata %s", initImage); 720 } 721 722 hw->disk_dataPartition_path = dataImage; 723 if (opts->wipe_data) { 724 hw->disk_dataPartition_initPath = initImage; 725 } else { 726 hw->disk_dataPartition_initPath = NULL; 727 } 728 729 uint64_t defaultBytes = 730 hw->disk_dataPartition_size == 0 ? 731 defaultPartitionSize : 732 convertMBToBytes(hw->disk_dataPartition_size); 733 uint64_t dataBytes; 734 const char* dataPath = hw->disk_dataPartition_initPath; 735 736 if (dataPath == NULL) 737 dataPath = hw->disk_dataPartition_path; 738 739 path_get_size(dataPath, &dataBytes); 740 741 hw->disk_dataPartition_size = 742 _adjustPartitionSize("data", dataBytes, defaultBytes, 743 avdInfo_inAndroidBuild(avd)); 744 } 745 746 /** CACHE PARTITION **/ 747 748 if (opts->no_cache) { 749 /* No cache partition at all */ 750 hw->disk_cachePartition = 0; 751 } 752 else if (!hw->disk_cachePartition) { 753 if (opts->cache) { 754 dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" ); 755 opts->cache = NULL; 756 } 757 } 758 else 759 { 760 if (!opts->cache) { 761 /* Find the current cache partition file */ 762 opts->cache = avdInfo_getCachePath(avd); 763 if (opts->cache == NULL) { 764 /* The file does not exists, we will force its creation 765 * if we are not in the Android build system. Otherwise, 766 * a temporary file will be used. 767 */ 768 if (!avdInfo_inAndroidBuild(avd)) { 769 opts->cache = avdInfo_getDefaultCachePath(avd); 770 } 771 } 772 if (opts->cache) { 773 D("autoconfig: -cache %s", opts->cache); 774 } 775 } 776 777 if (opts->cache) { 778 hw->disk_cachePartition_path = ASTRDUP(opts->cache); 779 } 780 } 781 782 /** SD CARD PARTITION */ 783 784 if (!hw->hw_sdCard) { 785 /* No SD Card emulation, so -sdcard will be ignored */ 786 if (opts->sdcard) { 787 dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." ); 788 opts->sdcard = NULL; 789 } 790 } else { 791 /* Auto-configure -sdcard if it is not available */ 792 if (!opts->sdcard) { 793 do { 794 /* If -datadir <path> is used, look for a sdcard.img file here */ 795 if (opts->datadir) { 796 bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img"); 797 if (path_exists(tmp)) { 798 opts->sdcard = strdup(tmp); 799 break; 800 } 801 } 802 803 /* Otherwise, look at the AVD's content */ 804 opts->sdcard = avdInfo_getSdCardPath(avd); 805 if (opts->sdcard != NULL) { 806 break; 807 } 808 809 /* Nothing */ 810 } while (0); 811 812 if (opts->sdcard) { 813 D("autoconfig: -sdcard %s", opts->sdcard); 814 } 815 } 816 } 817 818 if(opts->sdcard) { 819 uint64_t size; 820 if (path_get_size(opts->sdcard, &size) == 0) { 821 /* see if we have an sdcard image. get its size if it exists */ 822 /* due to what looks like limitations of the MMC protocol, one has 823 * to use an SD Card image that is equal or larger than 9 MB 824 */ 825 if (size < 9*1024*1024ULL) { 826 fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard); 827 } else { 828 hw->hw_sdCard_path = ASTRDUP(opts->sdcard); 829 } 830 } else { 831 dwarning("no SD Card image at '%s'", opts->sdcard); 832 } 833 } 834 835 836 /** SNAPSHOT STORAGE HANDLING */ 837 838 /* Determine snapstorage path. -no-snapstorage disables all snapshotting 839 * support. This means you can't resume a snapshot at load, save it at 840 * exit, or even load/save them dynamically at runtime with the console. 841 */ 842 if (opts->no_snapstorage) { 843 844 if (opts->snapshot) { 845 dwarning("ignoring -snapshot option due to the use of -no-snapstorage"); 846 opts->snapshot = NULL; 847 } 848 849 if (opts->snapstorage) { 850 dwarning("ignoring -snapstorage option due to the use of -no-snapstorage"); 851 opts->snapstorage = NULL; 852 } 853 } 854 else 855 { 856 if (!opts->snapstorage && avdInfo_getSnapshotPresent(avd)) { 857 opts->snapstorage = avdInfo_getSnapStoragePath(avd); 858 if (opts->snapstorage != NULL) { 859 D("autoconfig: -snapstorage %s", opts->snapstorage); 860 } 861 } 862 863 if (opts->snapstorage && !path_exists(opts->snapstorage)) { 864 D("no image at '%s', state snapshots disabled", opts->snapstorage); 865 opts->snapstorage = NULL; 866 } 867 } 868 869 /* If we have a valid snapshot storage path */ 870 871 if (opts->snapstorage) { 872 873 hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage); 874 875 /* -no-snapshot is equivalent to using both -no-snapshot-load 876 * and -no-snapshot-save. You can still load/save snapshots dynamically 877 * from the console though. 878 */ 879 if (opts->no_snapshot) { 880 881 opts->no_snapshot_load = 1; 882 opts->no_snapshot_save = 1; 883 884 if (opts->snapshot) { 885 dwarning("ignoring -snapshot option due to the use of -no-snapshot."); 886 } 887 } 888 889 if (!opts->no_snapshot_load || !opts->no_snapshot_save) { 890 if (opts->snapshot == NULL) { 891 opts->snapshot = "default-boot"; 892 D("autoconfig: -snapshot %s", opts->snapshot); 893 } 894 } 895 896 /* We still use QEMU command-line options for the following since 897 * they can change from one invokation to the next and don't really 898 * correspond to the hardware configuration itself. 899 */ 900 if (!opts->no_snapshot_load) { 901 args[n++] = "-loadvm"; 902 args[n++] = ASTRDUP(opts->snapshot); 903 } 904 905 if (!opts->no_snapshot_save) { 906 args[n++] = "-savevm-on-exit"; 907 args[n++] = ASTRDUP(opts->snapshot); 908 } 909 910 if (opts->no_snapshot_update_time) { 911 args[n++] = "-snapshot-no-time-update"; 912 } 913 } 914 915 if (!opts->logcat || opts->logcat[0] == 0) { 916 opts->logcat = getenv("ANDROID_LOG_TAGS"); 917 if (opts->logcat && opts->logcat[0] == 0) 918 opts->logcat = NULL; 919 } 920 921 /* we always send the kernel messages from ttyS0 to android_kmsg */ 922 if (opts->show_kernel) { 923 args[n++] = "-show-kernel"; 924 } 925 926 /* XXXX: TODO: implement -shell and -logcat through qemud instead */ 927 if (!opts->shell_serial) { 928#ifdef _WIN32 929 opts->shell_serial = "con:"; 930#else 931 opts->shell_serial = "stdio"; 932#endif 933 } 934 else 935 opts->shell = 1; 936 937 if (opts->shell || opts->logcat) { 938 args[n++] = "-serial"; 939 args[n++] = opts->shell_serial; 940 shell_serial = serial++; 941 } 942 943 if (opts->radio) { 944 args[n++] = "-radio"; 945 args[n++] = opts->radio; 946 } 947 948 if (opts->gps) { 949 args[n++] = "-gps"; 950 args[n++] = opts->gps; 951 } 952 953 if (opts->memory) { 954 char* end; 955 long ramSize = strtol(opts->memory, &end, 0); 956 if (ramSize < 0 || *end != 0) { 957 derror( "-memory must be followed by a positive integer" ); 958 exit(1); 959 } 960 if (ramSize < 32 || ramSize > 4096) { 961 derror( "physical memory size must be between 32 and 4096 MB" ); 962 exit(1); 963 } 964 hw->hw_ramSize = ramSize; 965 } 966 if (!opts->memory) { 967 int ramSize = hw->hw_ramSize; 968 if (ramSize <= 0) { 969 /* Compute the default RAM size based on the size of screen. 970 * This is only used when the skin doesn't provide the ram 971 * size through its hardware.ini (i.e. legacy ones) or when 972 * in the full Android build system. 973 */ 974 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height; 975 /* The following thresholds are a bit liberal, but we 976 * essentially want to ensure the following mappings: 977 * 978 * 320x480 -> 96 979 * 800x600 -> 128 980 * 1024x768 -> 256 981 * 982 * These are just simple heuristics, they could change in 983 * the future. 984 */ 985 if (pixels <= 250000) 986 ramSize = 96; 987 else if (pixels <= 500000) 988 ramSize = 128; 989 else 990 ramSize = 256; 991 } 992 hw->hw_ramSize = ramSize; 993 } 994 995 D("Physical RAM size: %dMB\n", hw->hw_ramSize); 996 997 if (hw->vm_heapSize == 0) { 998 /* Compute the default heap size based on the RAM size. 999 * Essentially, we want to ensure the following liberal mappings: 1000 * 1001 * 96MB RAM -> 16MB heap 1002 * 128MB RAM -> 24MB heap 1003 * 256MB RAM -> 48MB heap 1004 */ 1005 int ramSize = hw->hw_ramSize; 1006 int heapSize; 1007 1008 if (ramSize < 100) 1009 heapSize = 16; 1010 else if (ramSize < 192) 1011 heapSize = 24; 1012 else 1013 heapSize = 48; 1014 1015 hw->vm_heapSize = heapSize; 1016 } 1017 1018 if (opts->trace) { 1019 args[n++] = "-trace"; 1020 args[n++] = opts->trace; 1021 args[n++] = "-tracing"; 1022 args[n++] = "off"; 1023 } 1024 1025 /* Pass boot properties to the core. */ 1026 if (opts->prop != NULL) { 1027 ParamList* pl = opts->prop; 1028 for ( ; pl != NULL; pl = pl->next ) { 1029 args[n++] = "-boot-property"; 1030 args[n++] = pl->param; 1031 } 1032 } 1033 1034 /* Setup the kernel init options 1035 */ 1036 { 1037 static char params[1024]; 1038 char *p = params, *end = p + sizeof(params); 1039 1040 /* Don't worry about having a leading space here, this is handled 1041 * by the core later. */ 1042 1043#ifdef TARGET_I386 1044 p = bufprint(p, end, " androidboot.hardware=goldfish"); 1045 p = bufprint(p, end, " clocksource=pit"); 1046#endif 1047 1048 if (opts->shell || opts->logcat) { 1049 p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial ); 1050 } 1051 1052 if (opts->trace) { 1053 p = bufprint(p, end, " android.tracing=1"); 1054 } 1055 1056 if (!opts->no_jni) { 1057 p = bufprint(p, end, " android.checkjni=1"); 1058 } 1059 1060 if (opts->no_boot_anim) { 1061 p = bufprint( p, end, " android.bootanim=0" ); 1062 } 1063 1064 if (opts->logcat) { 1065 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat); 1066 1067 if (q < end) { 1068 /* replace any space by a comma ! */ 1069 { 1070 int nn; 1071 for (nn = 1; p[nn] != 0; nn++) 1072 if (p[nn] == ' ' || p[nn] == '\t') 1073 p[nn] = ','; 1074 p += nn; 1075 } 1076 } 1077 p = q; 1078 } 1079 1080 if (opts->bootchart) { 1081 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart); 1082 } 1083 1084 if (p >= end) { 1085 fprintf(stderr, "### ERROR: kernel parameters too long\n"); 1086 exit(1); 1087 } 1088 1089 hw->kernel_parameters = strdup(params); 1090 } 1091 1092 if (opts->ports) { 1093 args[n++] = "-android-ports"; 1094 args[n++] = opts->ports; 1095 } 1096 1097 if (opts->port) { 1098 args[n++] = "-android-port"; 1099 args[n++] = opts->port; 1100 } 1101 1102 if (opts->report_console) { 1103 args[n++] = "-android-report-console"; 1104 args[n++] = opts->report_console; 1105 } 1106 1107 if (opts->http_proxy) { 1108 args[n++] = "-http-proxy"; 1109 args[n++] = opts->http_proxy; 1110 } 1111 1112 if (!opts->charmap) { 1113 /* Try to find a valid charmap name */ 1114 char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap); 1115 if (charmap != NULL) { 1116 D("autoconfig: -charmap %s", charmap); 1117 opts->charmap = charmap; 1118 } 1119 } 1120 1121 if (opts->charmap) { 1122 char charmap_name[AKEYCHARMAP_NAME_SIZE]; 1123 1124 if (!path_exists(opts->charmap)) { 1125 derror("Charmap file does not exist: %s", opts->charmap); 1126 exit(1); 1127 } 1128 /* We need to store the charmap name in the hardware configuration. 1129 * However, the charmap file itself is only used by the UI component 1130 * and doesn't need to be set to the emulation engine. 1131 */ 1132 kcm_extract_charmap_name(opts->charmap, charmap_name, 1133 sizeof(charmap_name)); 1134 AFREE(hw->hw_keyboard_charmap); 1135 hw->hw_keyboard_charmap = ASTRDUP(charmap_name); 1136 } 1137 1138 if (opts->memcheck) { 1139 args[n++] = "-android-memcheck"; 1140 args[n++] = opts->memcheck; 1141 } 1142 1143 if (opts->gpu) { 1144 const char* gpu = opts->gpu; 1145 if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) { 1146 hw->hw_gpu_enabled = 1; 1147 } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) { 1148 hw->hw_gpu_enabled = 0; 1149 } else if (!strcmp(gpu,"auto")) { 1150 /* Nothing to do */ 1151 } else { 1152 derror("Invalid value for -gpu <mode> parameter: %s\n", gpu); 1153 derror("Valid values are: on, off or auto\n"); 1154 exit(1); 1155 } 1156 } 1157 1158 /* Quit emulator on condition that both, gpu and snapstorage are on. This is 1159 * a temporary solution preventing the emulator from crashing until GPU state 1160 * can be properly saved / resored in snapshot file. */ 1161 if (hw->hw_gpu_enabled && opts->snapstorage && (!opts->no_snapshot_load || 1162 !opts->no_snapshot_save)) { 1163 derror("Snapshots and gpu are mutually exclusive at this point. Please turn one of them off, and restart the emulator."); 1164 exit(1); 1165 } 1166 1167 if (opts->fake_camera) { 1168 if (!strcmp(opts->fake_camera, "back") || 1169 !strcmp(opts->fake_camera, "front") || 1170 !strcmp(opts->fake_camera, "off")) { 1171 hw->hw_fakeCamera = ASTRDUP(opts->fake_camera); 1172 } else { 1173 derror("Invalid value for -fake-camera <mode> parameter: %s\n", 1174 opts->fake_camera); 1175 derror("Valid values are: back, front, or off\n"); 1176 exit(1); 1177 } 1178 } 1179 1180 int webcam_num = 0; 1181 if (opts->webcam != NULL) { 1182 ParamList* pl = opts->webcam; 1183 for ( ; pl != NULL; pl = pl->next ) { 1184 char webcam_name[64]; 1185 char webcam_dir[16]; 1186 if (!strcmp(pl->param, "off")) { 1187 /* If 'off' is passed, there must be no other -webcam options. */ 1188 if (webcam_num || pl->next != NULL) { 1189 derror("'-webcam off' cannot be combined with other -webcam otions\n"); 1190 exit(1); 1191 } 1192 break; 1193 } 1194 if (!strcmp(pl->param, "list")) { 1195 /* If 'list' is passed, there must be no other -webcam options. */ 1196 if (webcam_num || pl->next != NULL) { 1197 derror("'-webcam list' cannot be combined with other -webcam otions\n"); 1198 exit(1); 1199 } 1200 args[n++] = "-list-webcam"; 1201 break; 1202 } 1203 /* Extract name, and direction */ 1204 _parseWebcamOption(pl->param, webcam_name, sizeof(webcam_name), 1205 webcam_dir, sizeof(webcam_dir)); 1206 /* Save them to appropriate field in hw.ini */ 1207 switch (webcam_num) { 1208 case 0: 1209 hw->hw_webcam_0_name = ASTRDUP(webcam_name); 1210 hw->hw_webcam_0_direction = ASTRDUP(webcam_dir); 1211 break; 1212 case 1: 1213 hw->hw_webcam_1_name = ASTRDUP(webcam_name); 1214 hw->hw_webcam_1_direction = ASTRDUP(webcam_dir); 1215 break; 1216 case 2: 1217 hw->hw_webcam_2_name = ASTRDUP(webcam_name); 1218 hw->hw_webcam_2_direction = ASTRDUP(webcam_dir); 1219 break; 1220 case 3: 1221 hw->hw_webcam_3_name = ASTRDUP(webcam_name); 1222 hw->hw_webcam_3_direction = ASTRDUP(webcam_dir); 1223 break; 1224 case 4: 1225 hw->hw_webcam_4_name = ASTRDUP(webcam_name); 1226 hw->hw_webcam_4_direction = ASTRDUP(webcam_dir); 1227 break; 1228 case 5: 1229 hw->hw_webcam_5_name = ASTRDUP(webcam_name); 1230 hw->hw_webcam_5_direction = ASTRDUP(webcam_dir); 1231 break; 1232 default: 1233 derror("Too many -webcam options. Maximum number of -webcam options is 6\n"); 1234 exit(1); 1235 } 1236 webcam_num++; 1237 } 1238 hw->hw_webcam_count = webcam_num; 1239 } 1240 1241 /* Command line options related to webcam, and fake camera should 1242 * override camera emulation flag, set in AVD. */ 1243 if (hw->hw_camera == 0) { 1244 /* Camera emulation is disabled in AVD. Lets see if command line enables 1245 * webcam, or fake camera emulation. */ 1246 if (webcam_num != 0 || 1247 (opts->fake_camera && strcmp(hw->hw_fakeCamera, "off") != 0)) { 1248 /* Command line parameters enable camera emulation. */ 1249 hw->hw_camera = 1; 1250 } 1251 } 1252 1253 /* physical memory is now in hw->hw_ramSize */ 1254 1255 hw->avd_name = ASTRDUP(avdInfo_getName(avd)); 1256 1257 /* Set up the interfaces for inter-emulator networking */ 1258 if (opts->shared_net_id) { 1259 unsigned int shared_net_id = atoi(opts->shared_net_id); 1260 char nic[37]; 1261 1262 args[n++] = "-net"; 1263 args[n++] = "nic,vlan=0"; 1264 args[n++] = "-net"; 1265 args[n++] = "user,vlan=0"; 1266 1267 args[n++] = "-net"; 1268 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id); 1269 args[n++] = strdup(nic); 1270 args[n++] = "-net"; 1271 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234"; 1272 } 1273 1274 /* Setup screen emulation */ 1275 if (opts->screen) { 1276 if (!strcmp(opts->screen, "touch")) { 1277 hw->hw_touchScreen = 1; 1278 hw->hw_multiTouch = 0; 1279 } else if (!strcmp(opts->screen, "multi-touch")) { 1280 hw->hw_multiTouch = 1; 1281 hw->hw_touchScreen = 0; 1282 } else if (!strcmp(opts->screen, "off")) { 1283 hw->hw_touchScreen = 0; 1284 hw->hw_multiTouch = 0; 1285 } else { 1286 derror("Invalid value for -screen <mode> parameter: %s\n", opts->screen); 1287 derror("Valid values are: touch, multi-touch, or off\n"); 1288 exit(1); 1289 } 1290 } else { 1291 /* If both, touch and multitouch are set in hw.ini, choose multi-touch 1292 * for screen emulation. */ 1293 if (hw->hw_touchScreen && hw->hw_multiTouch) { 1294 hw->hw_touchScreen = 0; 1295 } 1296 } 1297 1298 while(argc-- > 0) { 1299 args[n++] = *argv++; 1300 } 1301 args[n] = 0; 1302 1303 /* If the target ABI is armeabi-v7a, we can auto-detect the cpu model 1304 * as a cortex-a8, instead of the default (arm926) which only emulates 1305 * an ARMv5TE CPU. 1306 */ 1307 if (!forceArmv7 && hw->hw_cpu_model[0] == '\0') 1308 { 1309 char* abi = avdInfo_getTargetAbi(avd); 1310 if (abi != NULL) { 1311 if (!strcmp(abi, "armeabi-v7a")) { 1312 forceArmv7 = 1; 1313 } 1314 AFREE(abi); 1315 } 1316 } 1317 1318 if (forceArmv7 != 0) { 1319 AFREE(hw->hw_cpu_model); 1320 hw->hw_cpu_model = ASTRDUP("cortex-a8"); 1321 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model); 1322 } 1323 1324 /* Generate a hardware-qemu.ini for this AVD. The real hardware 1325 * configuration is ususally stored in several files, e.g. the AVD's 1326 * config.ini plus the skin-specific hardware.ini. 1327 * 1328 * The new file will group all definitions and will be used to 1329 * launch the core with the -android-hw <file> option. 1330 */ 1331 { 1332 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd); 1333 IniFile* hwIni = iniFile_newFromMemory("", NULL); 1334 androidHwConfig_write(hw, hwIni); 1335 1336 if (filelock_create(coreHwIniPath) == NULL) { 1337 /* The AVD is already in use, we still support this as an 1338 * experimental feature. Use a temporary hardware-qemu.ini 1339 * file though to avoid overwriting the existing one. */ 1340 TempFile* tempIni = tempfile_create(); 1341 coreHwIniPath = tempfile_path(tempIni); 1342 } 1343 1344 /* While saving HW config, ignore valueless entries. This will not break 1345 * anything, but will significantly simplify comparing the current HW 1346 * config with the one that has been associated with a snapshot (in case 1347 * VM starts from a snapshot for this instance of emulator). */ 1348 if (iniFile_saveToFileClean(hwIni, coreHwIniPath) < 0) { 1349 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno)); 1350 exit(2); 1351 } 1352 args[n++] = "-android-hw"; 1353 args[n++] = strdup(coreHwIniPath); 1354 1355 /* In verbose mode, dump the file's content */ 1356 if (VERBOSE_CHECK(init)) { 1357 FILE* file = fopen(coreHwIniPath, "rt"); 1358 if (file == NULL) { 1359 derror("Could not open hardware configuration file: %s\n", 1360 coreHwIniPath); 1361 } else { 1362 LineInput* input = lineInput_newFromStdFile(file); 1363 const char* line; 1364 printf("Content of hardware configuration file:\n"); 1365 while ((line = lineInput_getLine(input)) != NULL) { 1366 printf(" %s\n", line); 1367 } 1368 printf(".\n"); 1369 lineInput_free(input); 1370 fclose(file); 1371 } 1372 } 1373 } 1374 1375 if(VERBOSE_CHECK(init)) { 1376 int i; 1377 printf("QEMU options list:\n"); 1378 for(i = 0; i < n; i++) { 1379 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]); 1380 } 1381 /* Dump final command-line option to make debugging the core easier */ 1382 printf("Concatenated QEMU options:\n"); 1383 for (i = 0; i < n; i++) { 1384 /* To make it easier to copy-paste the output to a command-line, 1385 * quote anything that contains spaces. 1386 */ 1387 if (strchr(args[i], ' ') != NULL) { 1388 printf(" '%s'", args[i]); 1389 } else { 1390 printf(" %s", args[i]); 1391 } 1392 } 1393 printf("\n"); 1394 } 1395 1396 /* Setup SDL UI just before calling the code */ 1397 init_sdl_ui(skinConfig, skinPath, opts); 1398 1399 if (attach_ui_to_core(opts) < 0) { 1400 derror("Can't attach to core!"); 1401 exit(1); 1402 } 1403 1404 return qemu_main(n, args); 1405} 1406