blob: 6ce18e2d24db678deed581c67554c460dd84852f [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/* 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
Vladimir Chtchetkine7fbf4972010-08-11 15:30:32 -070020
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080021#include "sockets.h"
22
23#include "android/android.h"
24#include "qemu-common.h"
25#include "sysemu.h"
26#include "console.h"
David 'Digit' Turner34f29742010-05-25 18:16:10 -070027#include "user-events.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080028
29#include <SDL.h>
30#include <SDL_syswm.h>
31
32#include "math.h"
33
34#include "android/charmap.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080035#include "android/utils/debug.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080036#include "android/config.h"
37#include "android/config/config.h"
38
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080039#include "android/user-config.h"
40#include "android/utils/bufprint.h"
David 'Digit' Turner26d41532011-03-01 15:03:07 +010041#include "android/utils/filelock.h"
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +020042#include "android/utils/lineinput.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080043#include "android/utils/path.h"
David 'Digit' Turner622f1532011-02-01 17:48:37 +010044#include "android/utils/tempfile.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080045
David 'Digit' Turnerf8456272011-02-02 12:34:14 +010046#include "android/main-common.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080047#include "android/help.h"
48#include "hw/goldfish_nand.h"
49
50#include "android/globals.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080051
Xavier Ducrohetfc8ed802011-02-09 18:04:23 -080052#include "android/qemulator.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070053#include "android/display.h"
Vladimir Chtchetkine01193622010-05-11 13:07:22 -070054
Ot ten Thijeae835ac2010-10-18 13:37:37 +010055#include "android/snapshot.h"
56
David 'Digit' Turnere3fdd072011-02-02 14:43:23 +010057#include "android/framebuffer.h"
Vladimir Chtchetkine9a33e852010-11-08 16:52:04 -080058#include "iolooper.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070059
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080060AndroidRotation android_framebuffer_rotation;
61
62#define STRINGIFY(x) _STRINGIFY(x)
63#define _STRINGIFY(x) #x
64
David 'Digit' Turnera383d022009-12-03 13:50:00 -080065#ifdef ANDROID_SDK_TOOLS_REVISION
66# define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
67#else
68# define VERSION_STRING "standalone"
69#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080070
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080071#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
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080081#ifdef CONFIG_TRACE
82extern void start_tracing(void);
83extern void stop_tracing(void);
84#endif
85
86unsigned long android_verbose;
87
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080088int 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
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800103void 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
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100112/* 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 {
Andrew Hsiehc7389bd2012-03-13 02:13:40 -0700148 snprintf(temp, sizeof temp, "(%" PRIu64 " bytes > %" PRIu64 " bytes)", imageBytes, defaultBytes);
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100149 }
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
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -0700158/* 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
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800217int 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;
David 'Digit' Turner5e736932011-03-18 00:02:14 +0100224 /* 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;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800229 int shell_serial = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800230
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200231 int forceArmv7 = 0;
232
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800233 AndroidHwConfig* hw;
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200234 AvdInfo* avd;
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100235 AConfig* skinConfig;
236 char* skinPath;
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800237 int inAndroidBuild;
Vladimir Chtchetkined4f5a3a2012-03-08 14:20:20 -0800238 uint64_t defaultPartitionSize = convertMBToBytes(128);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800239
240 AndroidOptions opts[1];
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700241 /* net.shared_net_ip boot property value. */
242 char boot_prop_ip[64];
243 boot_prop_ip[0] = '\0';
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800244
245 args[0] = argv[0];
246
247 if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
248 exit(1);
249 }
250
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100251#ifdef _WIN32
252 socket_init();
253#endif
254
255 handle_ui_options(opts);
256
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800257 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
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800305 if (opts->version) {
306 printf("Android emulator version %s\n"
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100307 "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800308 "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
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100325 if (opts->snapshot_list) {
David 'Digit' Turnerd80a7862011-05-05 10:24:43 +0200326 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 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100341 snapshot_print_and_exit(opts->snapstorage);
342 }
343
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100344 sanitizeOptions(opts);
345
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100346 /* 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. */
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100352 if (android_charmap_setup(opts->charmap)) {
353 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800354 }
355
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800356 /* Parses options and builds an appropriate AVD. */
David 'Digit' Turner462564f2011-02-23 13:32:37 +0100357 avd = android_avdInfo = createAVD(opts, &inAndroidBuild);
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200358
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800359 /* get the skin from the virtual device configuration */
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100360 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;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800369
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100370 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;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800380 D("autoconfig: -skindir %s", opts->skindir);
381 }
382
383 /* Read hardware configuration */
384 hw = android_hw;
David 'Digit' Turnerb64325d2011-03-22 16:07:01 +0100385 if (avdInfo_initHwConfig(avd, hw) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800386 derror("could not read hardware configuration ?");
387 exit(1);
388 }
389
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800390 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
Dries Harnie40beab42010-05-15 17:04:47 +0200413 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 }
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700420 snprintf(boot_prop_ip, sizeof(boot_prop_ip),
421 "net.shared_net_ip=10.1.2.%ld", shared_net_id);
Dries Harnie40beab42010-05-15 17:04:47 +0200422 }
423
424
David 'Digit' Turner755811e2011-02-07 13:38:25 +0100425 user_config_init();
David 'Digit' Turner2507cab2011-02-10 16:29:17 +0100426 parse_skin_files(opts->skindir, opts->skin, opts, hw,
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100427 &skinConfig, &skinPath);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800428
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100429 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 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800434 }
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100435 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 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800440 }
441
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800442 if (opts->trace) {
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200443 char* tracePath = avdInfo_getTracePath(avd, opts->trace);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800444 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
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700458 /* 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
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800469 n = 1;
470 /* generate arguments for the underlying qemu main() */
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700471 {
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100472 char* kernelFile = opts->kernel;
473 int kernelFileLen;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700474
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100475 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;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700489
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 */
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100503 kernelFileLen = strlen(kernelFile);
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700504 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200505 forceArmv7 = 1;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700506 }
507 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800508
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700509 if (boot_prop_ip[0]) {
510 args[n++] = "-boot-property";
511 args[n++] = boot_prop_ip;
512 }
513
Vladimir Chtchetkine318f17a2010-08-27 09:09:45 -0700514 if (opts->tcpdump) {
515 args[n++] = "-tcpdump";
516 args[n++] = opts->tcpdump;
517 }
518
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700519#ifdef CONFIG_NAND_LIMITS
520 if (opts->nand_limits) {
521 args[n++] = "-nand-limits";
522 args[n++] = opts->nand_limits;
523 }
524#endif
525
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100526 if (opts->timezone) {
527 args[n++] = "-timezone";
528 args[n++] = opts->timezone;
529 }
530
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700531 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
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700543 if (opts->audio) {
544 args[n++] = "-audio";
545 args[n++] = opts->audio;
546 }
547
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700548 if (opts->cpu_delay) {
549 args[n++] = "-cpu-delay";
550 args[n++] = opts->cpu_delay;
551 }
552
Vladimir Chtchetkine7fbf4972010-08-11 15:30:32 -0700553 if (opts->dns_server) {
554 args[n++] = "-dns-server";
555 args[n++] = opts->dns_server;
556 }
557
David 'Digit' Turner9ff69722011-09-13 12:32:52 +0200558 /* 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 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800567
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100568 /* -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;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800576
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100577 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;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800587 }
588
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100589
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 */
David 'Digit' Turnerea283772011-07-07 04:40:27 +0200629 if (opts->sysdir != NULL && !path_exists(opts->system)) {
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100630 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
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100678 if (opts->datadir) {
679 if (!path_exists(opts->datadir)) {
680 derror("Invalid -datadir directory: %s", opts->datadir);
681 }
682 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800683
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100684 {
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
Maciek Molerusf7584112011-06-15 22:26:35 +0200729 uint64_t defaultBytes =
730 hw->disk_dataPartition_size == 0 ?
731 defaultPartitionSize :
Vladimir Chtchetkined4f5a3a2012-03-08 14:20:20 -0800732 hw->disk_dataPartition_size;
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100733 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 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800745
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100746 /** CACHE PARTITION **/
747
748 if (opts->no_cache) {
749 /* No cache partition at all */
750 hw->disk_cachePartition = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800751 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100752 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 }
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100772 if (opts->cache) {
773 D("autoconfig: -cache %s", opts->cache);
774 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100775 }
776
777 if (opts->cache) {
778 hw->disk_cachePartition_path = ASTRDUP(opts->cache);
779 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800780 }
781
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100782 /** SD CARD PARTITION */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800783
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100784 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 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800816 }
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 */
David 'Digit' Turner8b657e52009-12-01 13:38:21 -0800822 /* 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);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800827 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100828 hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800829 }
830 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100831 dwarning("no SD Card image at '%s'", opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800832 }
833 }
834
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100835
836 /** SNAPSHOT STORAGE HANDLING */
837
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100838 /* 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) {
857 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
858 if (opts->snapstorage != NULL) {
859 D("autoconfig: -snapstorage %s", opts->snapstorage);
Ot ten Thije353b3b12010-10-05 17:53:30 +0100860 }
861 }
862
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100863 if (opts->snapstorage && !path_exists(opts->snapstorage)) {
864 D("no image at '%s', state snapshots disabled", opts->snapstorage);
865 opts->snapstorage = NULL;
Ot ten Thije353b3b12010-10-05 17:53:30 +0100866 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100867 }
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
Tim Baverstock622b8f42010-12-07 11:36:59 +0000910 if (opts->no_snapshot_update_time) {
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100911 args[n++] = "-snapshot-no-time-update";
Tim Baverstock622b8f42010-12-07 11:36:59 +0000912 }
Ot ten Thijeae835ac2010-10-18 13:37:37 +0100913 }
Ot ten Thije353b3b12010-10-05 17:53:30 +0100914
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800915 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
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800921 /* we always send the kernel messages from ttyS0 to android_kmsg */
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100922 if (opts->show_kernel) {
923 args[n++] = "-show-kernel";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800924 }
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
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100943 if (opts->radio) {
944 args[n++] = "-radio";
945 args[n++] = opts->radio;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800946 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800947
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100948 if (opts->gps) {
949 args[n++] = "-gps";
950 args[n++] = opts->gps;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800951 }
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 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100964 hw->hw_ramSize = ramSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800965 }
966 if (!opts->memory) {
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100967 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 */
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100974 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height;
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100975 /* 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 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100992 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;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001016 }
1017
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001018 if (opts->trace) {
1019 args[n++] = "-trace";
1020 args[n++] = opts->trace;
1021 args[n++] = "-tracing";
1022 args[n++] = "off";
1023 }
1024
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -07001025 /* 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
David 'Digit' Turner318e4f22009-05-25 18:01:03 +02001034 /* Setup the kernel init options
1035 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001036 {
1037 static char params[1024];
1038 char *p = params, *end = p + sizeof(params);
1039
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +01001040 /* Don't worry about having a leading space here, this is handled
1041 * by the core later. */
1042
Jun Nakajima334ab472011-02-02 23:49:59 -08001043#ifdef TARGET_I386
1044 p = bufprint(p, end, " androidboot.hardware=goldfish");
Jun Nakajimabac9add2011-02-08 22:10:52 -08001045 p = bufprint(p, end, " clocksource=pit");
Jun Nakajima334ab472011-02-02 23:49:59 -08001046#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001047
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
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001080 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
David 'Digit' Turner0b019492011-03-01 14:02:42 +01001089 hw->kernel_parameters = strdup(params);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001090 }
1091
Vladimir Chtchetkined81e6d12010-06-15 16:46:32 -07001092 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
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001112 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
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001121 if (opts->charmap) {
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001122 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);
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001136 }
1137
Vladimir Chtchetkineb5365f32010-08-09 13:33:57 -07001138 if (opts->memcheck) {
1139 args[n++] = "-android-memcheck";
1140 args[n++] = opts->memcheck;
1141 }
1142
David Turner9da935d2011-09-12 21:27:56 +02001143 if (opts->gpu) {
1144 const char* gpu = opts->gpu;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001145 if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) {
David Turner9da935d2011-09-12 21:27:56 +02001146 hw->hw_gpu_enabled = 1;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001147 } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) {
David Turner9da935d2011-09-12 21:27:56 +02001148 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
Vladimir Chtchetkine9242b332012-02-10 08:29:22 -08001158 /* 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
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001167 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
Vladimir Chtchetkinef8675c22012-01-06 10:31:41 -08001180 int webcam_num = 0;
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -07001181 if (opts->webcam != NULL) {
1182 ParamList* pl = opts->webcam;
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -07001183 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
Vladimir Chtchetkinef8675c22012-01-06 10:31:41 -08001241 /* 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
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +01001253 /* physical memory is now in hw->hw_ramSize */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001254
David 'Digit' Turner53eb66d2011-03-01 14:58:23 +01001255 hw->avd_name = ASTRDUP(avdInfo_getName(avd));
David 'Digit' Turner6b8555c2011-02-17 04:28:19 +01001256
Dries Harnie40beab42010-05-15 17:04:47 +02001257 /* 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];
Dries Harnie40beab42010-05-15 17:04:47 +02001261
1262 args[n++] = "-net";
1263 args[n++] = "nic,vlan=0";
1264 args[n++] = "-net";
1265 args[n++] = "user,vlan=0";
Dries Harnie111d6f82010-06-09 21:42:18 +02001266
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";
Dries Harnie40beab42010-05-15 17:04:47 +02001272 }
1273
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001274 /* 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
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001298 while(argc-- > 0) {
1299 args[n++] = *argv++;
1300 }
1301 args[n] = 0;
1302
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +02001303 /* 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
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001324 /* Generate a hardware-qemu.ini for this AVD. The real hardware
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001325 * configuration is ususally stored in several files, e.g. the AVD's
1326 * config.ini plus the skin-specific hardware.ini.
1327 *
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001328 * The new file will group all definitions and will be used to
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001329 * launch the core with the -android-hw <file> option.
1330 */
1331 {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001332 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
1333 IniFile* hwIni = iniFile_newFromMemory("", NULL);
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001334 androidHwConfig_write(hw, hwIni);
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001335
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
Vladimir Chtchetkinedb450d72012-01-12 13:37:40 -08001344 /* 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) {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001349 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001350 exit(2);
1351 }
1352 args[n++] = "-android-hw";
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001353 args[n++] = strdup(coreHwIniPath);
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +02001354
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 }
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001373 }
1374
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001375 if(VERBOSE_CHECK(init)) {
1376 int i;
David 'Digit' Turner33361762011-01-19 22:11:03 +01001377 printf("QEMU options list:\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001378 for(i = 0; i < n; i++) {
David 'Digit' Turner33361762011-01-19 22:11:03 +01001379 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001380 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001381 /* Dump final command-line option to make debugging the core easier */
1382 printf("Concatenated QEMU options:\n");
1383 for (i = 0; i < n; i++) {
David 'Digit' Turner26722dd2011-02-24 16:40:20 +01001384 /* 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 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001392 }
1393 printf("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001394 }
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +01001395
1396 /* Setup SDL UI just before calling the code */
1397 init_sdl_ui(skinConfig, skinPath, opts);
1398
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +01001399 if (attach_ui_to_core(opts) < 0) {
1400 derror("Can't attach to core!");
1401 exit(1);
1402 }
1403
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001404 return qemu_main(n, args);
1405}