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