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