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