blob: 0662bfe1cbeed834e8922e3d242119a9409fef56 [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
David 'Digit' Turner9b3a4b02014-01-23 00:52:54 +010021#include "config.h"
David 'Digit' Turnercc330d42013-12-14 23:26:42 +010022#include "android/sockets.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080023
24#include "android/android.h"
25#include "qemu-common.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010026#include "sysemu/sysemu.h"
David 'Digit' Turner1c31e3e2013-12-14 20:07:17 +010027#include "ui/console.h"
David 'Digit' Turnerd4e803c2013-12-14 23:45:50 +010028#include "android/user-events.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080029
30#include <SDL.h>
31#include <SDL_syswm.h>
32
33#include "math.h"
34
35#include "android/charmap.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080036#include "android/utils/debug.h"
David 'Digit' Turner73dd5fc2014-02-04 12:50:55 +010037#include "android/config-file.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080038#include "android/config/config.h"
39
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080040#include "android/user-config.h"
41#include "android/utils/bufprint.h"
David 'Digit' Turner26d41532011-03-01 15:03:07 +010042#include "android/utils/filelock.h"
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +020043#include "android/utils/lineinput.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080044#include "android/utils/path.h"
David 'Digit' Turner5ea91482014-02-13 18:02:56 +010045#include "android/utils/property_file.h"
David 'Digit' Turner622f1532011-02-01 17:48:37 +010046#include "android/utils/tempfile.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080047
David 'Digit' Turnerf8456272011-02-02 12:34:14 +010048#include "android/main-common.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080049#include "android/help.h"
David 'Digit' Turnerf0665422013-12-17 10:47:09 +010050#include "hw/android/goldfish/nand.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080051
52#include "android/globals.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080053
Xavier Ducrohetfc8ed802011-02-09 18:04:23 -080054#include "android/qemulator.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070055#include "android/display.h"
Vladimir Chtchetkine01193622010-05-11 13:07:22 -070056
Ot ten Thijeae835ac2010-10-18 13:37:37 +010057#include "android/snapshot.h"
58
David 'Digit' Turnere3fdd072011-02-02 14:43:23 +010059#include "android/framebuffer.h"
David 'Digit' Turnerd413fa52013-12-14 23:35:20 +010060#include "android/iolooper.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070061
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080062AndroidRotation android_framebuffer_rotation;
63
64#define STRINGIFY(x) _STRINGIFY(x)
65#define _STRINGIFY(x) #x
66
David 'Digit' Turnera383d022009-12-03 13:50:00 -080067#ifdef ANDROID_SDK_TOOLS_REVISION
68# define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
69#else
70# define VERSION_STRING "standalone"
71#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080072
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080073#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
74
75extern int control_console_start( int port ); /* in control.c */
76
77extern int qemu_milli_needed;
78
79/* the default device DPI if none is specified by the skin
80 */
81#define DEFAULT_DEVICE_DPI 165
82
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080083int qemu_main(int argc, char **argv);
84
85/* this function dumps the QEMU help */
86extern void help( void );
87extern void emulator_help( void );
88
89#define VERBOSE_OPT(str,var) { str, &var }
90
91#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y },
92static const struct { const char* name; int flag; const char* text; }
93verbose_options[] = {
94 VERBOSE_TAG_LIST
95 { 0, 0, 0 }
96};
97
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080098void emulator_help( void )
99{
100 STRALLOC_DEFINE(out);
101 android_help_main(out);
102 printf( "%.*s", out->n, out->s );
103 stralloc_reset(out);
104 exit(1);
105}
106
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100107/* TODO: Put in shared source file */
108static char*
109_getFullFilePath( const char* rootPath, const char* fileName )
110{
111 if (path_is_absolute(fileName)) {
112 return ASTRDUP(fileName);
113 } else {
114 char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
115
116 p = bufprint(temp, end, "%s/%s", rootPath, fileName);
117 if (p >= end) {
118 return NULL;
119 }
120 return ASTRDUP(temp);
121 }
122}
123
124static uint64_t
125_adjustPartitionSize( const char* description,
126 uint64_t imageBytes,
127 uint64_t defaultBytes,
128 int inAndroidBuild )
129{
130 char temp[64];
131 unsigned imageMB;
132 unsigned defaultMB;
133
134 if (imageBytes <= defaultBytes)
135 return defaultBytes;
136
137 imageMB = convertBytesToMB(imageBytes);
138 defaultMB = convertBytesToMB(defaultBytes);
139
140 if (imageMB > defaultMB) {
141 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
142 } else {
Andrew Hsiehc7389bd2012-03-13 02:13:40 -0700143 snprintf(temp, sizeof temp, "(%" PRIu64 " bytes > %" PRIu64 " bytes)", imageBytes, defaultBytes);
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100144 }
145
146 if (inAndroidBuild) {
147 dwarning("%s partition size adjusted to match image file %s\n", description, temp);
148 }
149
150 return convertMBToBytes(imageMB);
151}
152
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800153int main(int argc, char **argv)
154{
155 char tmp[MAX_PATH];
156 char* tmpend = tmp + sizeof(tmp);
157 char* args[128];
158 int n;
159 char* opt;
David 'Digit' Turner5e736932011-03-18 00:02:14 +0100160 /* The emulator always uses the first serial port for kernel messages
161 * and the second one for qemud. So start at the third if we need one
162 * for logcat or 'shell'
163 */
164 int serial = 2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800165 int shell_serial = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800166
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200167 int forceArmv7 = 0;
168
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800169 AndroidHwConfig* hw;
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200170 AvdInfo* avd;
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100171 AConfig* skinConfig;
172 char* skinPath;
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800173 int inAndroidBuild;
Vladimir Chtchetkine88078b82012-04-19 12:24:38 -0700174 uint64_t defaultPartitionSize = convertMBToBytes(200);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800175
176 AndroidOptions opts[1];
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700177 /* net.shared_net_ip boot property value. */
178 char boot_prop_ip[64];
179 boot_prop_ip[0] = '\0';
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800180
181 args[0] = argv[0];
182
183 if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
184 exit(1);
185 }
186
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100187#ifdef _WIN32
188 socket_init();
189#endif
190
191 handle_ui_options(opts);
192
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800193 while (argc-- > 1) {
194 opt = (++argv)[0];
195
196 if(!strcmp(opt, "-qemu")) {
197 argc--;
198 argv++;
199 break;
200 }
201
202 if (!strcmp(opt, "-help")) {
203 emulator_help();
204 }
205
206 if (!strncmp(opt, "-help-",6)) {
207 STRALLOC_DEFINE(out);
208 opt += 6;
209
210 if (!strcmp(opt, "all")) {
211 android_help_all(out);
212 }
213 else if (android_help_for_option(opt, out) == 0) {
214 /* ok */
215 }
216 else if (android_help_for_topic(opt, out) == 0) {
217 /* ok */
218 }
219 if (out->n > 0) {
220 printf("\n%.*s", out->n, out->s);
221 exit(0);
222 }
223
224 fprintf(stderr, "unknown option: -help-%s\n", opt);
225 fprintf(stderr, "please use -help for a list of valid topics\n");
226 exit(1);
227 }
228
229 if (opt[0] == '-') {
230 fprintf(stderr, "unknown option: %s\n", opt);
231 fprintf(stderr, "please use -help for a list of valid options\n");
232 exit(1);
233 }
234
235 fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
236 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
237 fprintf(stderr, "please use -help for more information\n");
238 exit(1);
239 }
240
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800241 if (opts->version) {
242 printf("Android emulator version %s\n"
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100243 "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800244 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
245#if defined ANDROID_BUILD_ID
246 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
247#else
248 VERSION_STRING);
249#endif
250 printf(" This software is licensed under the terms of the GNU General Public\n"
251 " License version 2, as published by the Free Software Foundation, and\n"
252 " may be copied, distributed, and modified under those terms.\n\n"
253 " This program is distributed in the hope that it will be useful,\n"
254 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
255 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
256 " GNU General Public License for more details.\n\n");
257
258 exit(0);
259 }
260
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100261 if (opts->snapshot_list) {
David 'Digit' Turnerd80a7862011-05-05 10:24:43 +0200262 if (opts->snapstorage == NULL) {
263 /* Need to find the default snapstorage */
264 avd = createAVD(opts, &inAndroidBuild);
265 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
266 if (opts->snapstorage != NULL) {
267 D("autoconfig: -snapstorage %s", opts->snapstorage);
268 } else {
269 if (inAndroidBuild) {
270 derror("You must use the -snapstorage <file> option to specify a snapshot storage file!\n");
271 } else {
272 derror("This AVD doesn't have snapshotting enabled!\n");
273 }
274 exit(1);
275 }
276 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100277 snapshot_print_and_exit(opts->snapstorage);
278 }
279
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100280 sanitizeOptions(opts);
281
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100282 /* Initialization of UI started with -attach-core should work differently
283 * than initialization of UI that starts the core. In particular....
284 */
285
286 /* -charmap is incompatible with -attach-core, because particular
287 * charmap gets set up in the running core. */
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100288 if (android_charmap_setup(opts->charmap)) {
289 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800290 }
291
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800292 /* Parses options and builds an appropriate AVD. */
David 'Digit' Turner462564f2011-02-23 13:32:37 +0100293 avd = android_avdInfo = createAVD(opts, &inAndroidBuild);
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200294
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800295 /* get the skin from the virtual device configuration */
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100296 if (opts->skindir != NULL) {
297 if (opts->skin == NULL) {
298 /* NOTE: Normally handled by sanitizeOptions(), just be safe */
299 derror("The -skindir <path> option requires a -skin <name> option");
300 exit(2);
301 }
302 } else {
303 char* skinName;
304 char* skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800305
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100306 avdInfo_getSkinInfo(avd, &skinName, &skinDir);
307
308 if (opts->skin == NULL) {
309 opts->skin = skinName;
310 D("autoconfig: -skin %s", opts->skin);
311 } else {
312 AFREE(skinName);
313 }
314
315 opts->skindir = skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800316 D("autoconfig: -skindir %s", opts->skindir);
Xavier Ducrohet689d1142012-04-19 12:54:08 -0700317
318 /* update the avd hw config from this new skin */
319 avdInfo_getSkinHardwareIni(avd, opts->skin, opts->skindir);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800320 }
321
Siva Velusamyd8999182012-10-08 18:02:30 -0700322 if (opts->dynamic_skin == 0) {
323 opts->dynamic_skin = avdInfo_shouldUseDynamicSkin(avd);
324 }
325
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800326 /* Read hardware configuration */
327 hw = android_hw;
David 'Digit' Turnerb64325d2011-03-22 16:07:01 +0100328 if (avdInfo_initHwConfig(avd, hw) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800329 derror("could not read hardware configuration ?");
330 exit(1);
331 }
332
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800333 if (opts->keyset) {
334 parse_keyset(opts->keyset, opts);
335 if (!android_keyset) {
336 fprintf(stderr,
337 "emulator: WARNING: could not find keyset file named '%s',"
338 " using defaults instead\n",
339 opts->keyset);
340 }
341 }
342 if (!android_keyset) {
343 parse_keyset("default", opts);
344 if (!android_keyset) {
345 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
346 if (!android_keyset) {
347 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
348 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
349 exit(1);
350 }
351 if (!opts->keyset)
352 write_default_keyset();
353 }
354 }
355
Dries Harnie40beab42010-05-15 17:04:47 +0200356 if (opts->shared_net_id) {
357 char* end;
358 long shared_net_id = strtol(opts->shared_net_id, &end, 0);
359 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
360 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
361 exit(1);
362 }
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700363 snprintf(boot_prop_ip, sizeof(boot_prop_ip),
364 "net.shared_net_ip=10.1.2.%ld", shared_net_id);
Dries Harnie40beab42010-05-15 17:04:47 +0200365 }
366
367
David 'Digit' Turner755811e2011-02-07 13:38:25 +0100368 user_config_init();
David 'Digit' Turner2507cab2011-02-10 16:29:17 +0100369 parse_skin_files(opts->skindir, opts->skin, opts, hw,
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100370 &skinConfig, &skinPath);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800371
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100372 if (!opts->netspeed && skin_network_speed) {
373 D("skin network speed: '%s'", skin_network_speed);
374 if (strcmp(skin_network_speed, NETWORK_SPEED_DEFAULT) != 0) {
375 opts->netspeed = (char*)skin_network_speed;
376 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800377 }
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100378 if (!opts->netdelay && skin_network_delay) {
379 D("skin network delay: '%s'", skin_network_delay);
380 if (strcmp(skin_network_delay, NETWORK_DELAY_DEFAULT) != 0) {
381 opts->netdelay = (char*)skin_network_delay;
382 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800383 }
384
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800385 if (opts->trace) {
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200386 char* tracePath = avdInfo_getTracePath(avd, opts->trace);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800387 int ret;
388
389 if (tracePath == NULL) {
390 derror( "bad -trace parameter" );
391 exit(1);
392 }
393 ret = path_mkdir_if_needed( tracePath, 0755 );
394 if (ret < 0) {
395 fprintf(stderr, "could not create directory '%s'\n", tmp);
396 exit(2);
397 }
398 opts->trace = tracePath;
399 }
400
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700401 /* Update CPU architecture for HW configs created from build dir. */
402 if (inAndroidBuild) {
403#if defined(TARGET_ARM)
404 free(android_hw->hw_cpu_arch);
405 android_hw->hw_cpu_arch = ASTRDUP("arm");
406#elif defined(TARGET_I386)
407 free(android_hw->hw_cpu_arch);
408 android_hw->hw_cpu_arch = ASTRDUP("x86");
Bhanu Chetlapalli741dc132012-05-08 17:16:03 -0700409#elif defined(TARGET_MIPS)
410 free(android_hw->hw_cpu_arch);
411 android_hw->hw_cpu_arch = ASTRDUP("mips");
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700412#endif
413 }
414
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800415 n = 1;
416 /* generate arguments for the underlying qemu main() */
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700417 {
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100418 char* kernelFile = opts->kernel;
419 int kernelFileLen;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700420
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100421 if (kernelFile == NULL) {
422 kernelFile = avdInfo_getKernelPath(avd);
423 if (kernelFile == NULL) {
424 derror( "This AVD's configuration is missing a kernel file!!" );
425 exit(2);
426 }
427 D("autoconfig: -kernel %s", kernelFile);
428 }
429 if (!path_exists(kernelFile)) {
430 derror( "Invalid or missing kernel image file: %s", kernelFile );
431 exit(2);
432 }
433
434 hw->kernel_path = kernelFile;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700435
436 /* If the kernel image name ends in "-armv7", then change the cpu
437 * type automatically. This is a poor man's approach to configuration
438 * management, but should allow us to get past building ARMv7
439 * system images with dex preopt pass without introducing too many
440 * changes to the emulator sources.
441 *
442 * XXX:
443 * A 'proper' change would require adding some sort of hardware-property
444 * to each AVD config file, then automatically determine its value for
445 * full Android builds (depending on some environment variable), plus
446 * some build system changes. I prefer not to do that for now for reasons
447 * of simplicity.
448 */
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100449 kernelFileLen = strlen(kernelFile);
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700450 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200451 forceArmv7 = 1;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700452 }
453 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800454
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700455 if (boot_prop_ip[0]) {
456 args[n++] = "-boot-property";
457 args[n++] = boot_prop_ip;
458 }
459
Vladimir Chtchetkine318f17a2010-08-27 09:09:45 -0700460 if (opts->tcpdump) {
461 args[n++] = "-tcpdump";
462 args[n++] = opts->tcpdump;
463 }
464
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700465#ifdef CONFIG_NAND_LIMITS
466 if (opts->nand_limits) {
467 args[n++] = "-nand-limits";
468 args[n++] = opts->nand_limits;
469 }
470#endif
471
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100472 if (opts->timezone) {
473 args[n++] = "-timezone";
474 args[n++] = opts->timezone;
475 }
476
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700477 if (opts->netspeed) {
478 args[n++] = "-netspeed";
479 args[n++] = opts->netspeed;
480 }
481 if (opts->netdelay) {
482 args[n++] = "-netdelay";
483 args[n++] = opts->netdelay;
484 }
485 if (opts->netfast) {
486 args[n++] = "-netfast";
487 }
488
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700489 if (opts->audio) {
490 args[n++] = "-audio";
491 args[n++] = opts->audio;
492 }
493
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700494 if (opts->cpu_delay) {
495 args[n++] = "-cpu-delay";
496 args[n++] = opts->cpu_delay;
497 }
498
Vladimir Chtchetkine7fbf4972010-08-11 15:30:32 -0700499 if (opts->dns_server) {
500 args[n++] = "-dns-server";
501 args[n++] = opts->dns_server;
502 }
503
David 'Digit' Turner9ff69722011-09-13 12:32:52 +0200504 /* opts->ramdisk is never NULL (see createAVD) here */
505 if (opts->ramdisk) {
506 AFREE(hw->disk_ramdisk_path);
507 hw->disk_ramdisk_path = ASTRDUP(opts->ramdisk);
508 }
509 else if (!hw->disk_ramdisk_path[0]) {
510 hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
511 D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path);
512 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800513
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100514 /* -partition-size is used to specify the max size of both the system
515 * and data partition sizes.
516 */
517 if (opts->partition_size) {
518 char* end;
519 long sizeMB = strtol(opts->partition_size, &end, 0);
520 long minSizeMB = 10;
521 long maxSizeMB = LONG_MAX / ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800522
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100523 if (sizeMB < 0 || *end != 0) {
524 derror( "-partition-size must be followed by a positive integer" );
525 exit(1);
526 }
527 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
528 derror( "partition-size (%d) must be between %dMB and %dMB",
529 sizeMB, minSizeMB, maxSizeMB );
530 exit(1);
531 }
532 defaultPartitionSize = (uint64_t) sizeMB * ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800533 }
534
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100535
536 /** SYSTEM PARTITION **/
537
538 if (opts->sysdir == NULL) {
539 if (avdInfo_inAndroidBuild(avd)) {
540 opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd));
541 D("autoconfig: -sysdir %s", opts->sysdir);
542 }
543 }
544
545 if (opts->sysdir != NULL) {
546 if (!path_exists(opts->sysdir)) {
547 derror("Directory does not exist: %s", opts->sysdir);
548 exit(1);
549 }
550 }
551
552 {
553 char* rwImage = NULL;
554 char* initImage = NULL;
555
556 do {
557 if (opts->system == NULL) {
558 /* If -system is not used, try to find a runtime system image
559 * (i.e. system-qemu.img) in the content directory.
560 */
561 rwImage = avdInfo_getSystemImagePath(avd);
562 if (rwImage != NULL) {
563 break;
564 }
565 /* Otherwise, try to find the initial system image */
566 initImage = avdInfo_getSystemInitImagePath(avd);
567 if (initImage == NULL) {
568 derror("No initial system image for this configuration!");
569 exit(1);
570 }
571 break;
572 }
573
574 /* If -system <name> is used, use it to find the initial image */
David 'Digit' Turnerea283772011-07-07 04:40:27 +0200575 if (opts->sysdir != NULL && !path_exists(opts->system)) {
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100576 initImage = _getFullFilePath(opts->sysdir, opts->system);
577 } else {
578 initImage = ASTRDUP(opts->system);
579 }
580 if (!path_exists(initImage)) {
581 derror("System image file doesn't exist: %s", initImage);
582 exit(1);
583 }
584
585 } while (0);
586
587 if (rwImage != NULL) {
588 /* Use the read/write image file directly */
589 hw->disk_systemPartition_path = rwImage;
590 hw->disk_systemPartition_initPath = NULL;
591 D("Using direct system image: %s", rwImage);
592 } else if (initImage != NULL) {
593 hw->disk_systemPartition_path = NULL;
594 hw->disk_systemPartition_initPath = initImage;
595 D("Using initial system image: %s", initImage);
596 }
597
598 /* Check the size of the system partition image.
599 * If we have an AVD, it must be smaller than
600 * the disk.systemPartition.size hardware property.
601 *
602 * Otherwise, we need to adjust the systemPartitionSize
603 * automatically, and print a warning.
604 *
605 */
606 const char* systemImage = hw->disk_systemPartition_path;
607 uint64_t systemBytes;
608
609 if (systemImage == NULL)
610 systemImage = hw->disk_systemPartition_initPath;
611
612 if (path_get_size(systemImage, &systemBytes) < 0) {
613 derror("Missing system image: %s", systemImage);
614 exit(1);
615 }
616
617 hw->disk_systemPartition_size =
618 _adjustPartitionSize("system", systemBytes, defaultPartitionSize,
619 avdInfo_inAndroidBuild(avd));
620 }
621
622 /** DATA PARTITION **/
623
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100624 if (opts->datadir) {
625 if (!path_exists(opts->datadir)) {
626 derror("Invalid -datadir directory: %s", opts->datadir);
627 }
628 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800629
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100630 {
631 char* dataImage = NULL;
632 char* initImage = NULL;
633
634 do {
635 if (!opts->data) {
636 dataImage = avdInfo_getDataImagePath(avd);
637 if (dataImage != NULL) {
638 D("autoconfig: -data %s", dataImage);
639 break;
640 }
641 dataImage = avdInfo_getDefaultDataImagePath(avd);
642 if (dataImage == NULL) {
643 derror("No data image path for this configuration!");
644 exit (1);
645 }
646 opts->wipe_data = 1;
647 break;
648 }
649
650 if (opts->datadir) {
651 dataImage = _getFullFilePath(opts->datadir, opts->data);
652 } else {
653 dataImage = ASTRDUP(opts->data);
654 }
655 } while (0);
656
657 if (opts->initdata != NULL) {
658 initImage = ASTRDUP(opts->initdata);
659 if (!path_exists(initImage)) {
660 derror("Invalid initial data image path: %s", initImage);
661 exit(1);
662 }
663 } else {
664 initImage = avdInfo_getDataInitImagePath(avd);
665 D("autoconfig: -initdata %s", initImage);
666 }
667
668 hw->disk_dataPartition_path = dataImage;
669 if (opts->wipe_data) {
670 hw->disk_dataPartition_initPath = initImage;
671 } else {
672 hw->disk_dataPartition_initPath = NULL;
673 }
674
Maciek Molerusf7584112011-06-15 22:26:35 +0200675 uint64_t defaultBytes =
676 hw->disk_dataPartition_size == 0 ?
677 defaultPartitionSize :
Vladimir Chtchetkined4f5a3a2012-03-08 14:20:20 -0800678 hw->disk_dataPartition_size;
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100679 uint64_t dataBytes;
680 const char* dataPath = hw->disk_dataPartition_initPath;
681
682 if (dataPath == NULL)
683 dataPath = hw->disk_dataPartition_path;
684
685 path_get_size(dataPath, &dataBytes);
686
687 hw->disk_dataPartition_size =
688 _adjustPartitionSize("data", dataBytes, defaultBytes,
689 avdInfo_inAndroidBuild(avd));
690 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800691
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100692 /** CACHE PARTITION **/
693
694 if (opts->no_cache) {
695 /* No cache partition at all */
696 hw->disk_cachePartition = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800697 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100698 else if (!hw->disk_cachePartition) {
699 if (opts->cache) {
700 dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" );
701 opts->cache = NULL;
702 }
703 }
704 else
705 {
706 if (!opts->cache) {
707 /* Find the current cache partition file */
708 opts->cache = avdInfo_getCachePath(avd);
709 if (opts->cache == NULL) {
710 /* The file does not exists, we will force its creation
711 * if we are not in the Android build system. Otherwise,
712 * a temporary file will be used.
713 */
714 if (!avdInfo_inAndroidBuild(avd)) {
715 opts->cache = avdInfo_getDefaultCachePath(avd);
716 }
717 }
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100718 if (opts->cache) {
719 D("autoconfig: -cache %s", opts->cache);
720 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100721 }
722
723 if (opts->cache) {
724 hw->disk_cachePartition_path = ASTRDUP(opts->cache);
725 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800726 }
727
Vladimir Chtchetkine6f50aa32012-04-26 08:20:18 -0700728 if (hw->disk_cachePartition_path && opts->cache_size) {
729 /* Set cache partition size per user options. */
730 char* end;
731 long sizeMB = strtol(opts->cache_size, &end, 0);
732
733 if (sizeMB < 0 || *end != 0) {
734 derror( "-cache-size must be followed by a positive integer" );
735 exit(1);
736 }
737 hw->disk_cachePartition_size = (uint64_t) sizeMB * ONE_MB;
738 }
739
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100740 /** SD CARD PARTITION */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800741
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100742 if (!hw->hw_sdCard) {
743 /* No SD Card emulation, so -sdcard will be ignored */
744 if (opts->sdcard) {
745 dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." );
746 opts->sdcard = NULL;
747 }
748 } else {
749 /* Auto-configure -sdcard if it is not available */
750 if (!opts->sdcard) {
751 do {
752 /* If -datadir <path> is used, look for a sdcard.img file here */
753 if (opts->datadir) {
754 bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img");
755 if (path_exists(tmp)) {
756 opts->sdcard = strdup(tmp);
757 break;
758 }
759 }
760
761 /* Otherwise, look at the AVD's content */
762 opts->sdcard = avdInfo_getSdCardPath(avd);
763 if (opts->sdcard != NULL) {
764 break;
765 }
766
767 /* Nothing */
768 } while (0);
769
770 if (opts->sdcard) {
771 D("autoconfig: -sdcard %s", opts->sdcard);
772 }
773 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800774 }
775
776 if(opts->sdcard) {
777 uint64_t size;
778 if (path_get_size(opts->sdcard, &size) == 0) {
779 /* see if we have an sdcard image. get its size if it exists */
David 'Digit' Turner8b657e52009-12-01 13:38:21 -0800780 /* due to what looks like limitations of the MMC protocol, one has
781 * to use an SD Card image that is equal or larger than 9 MB
782 */
783 if (size < 9*1024*1024ULL) {
784 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 -0800785 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100786 hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800787 }
788 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100789 dwarning("no SD Card image at '%s'", opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800790 }
791 }
792
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100793
794 /** SNAPSHOT STORAGE HANDLING */
795
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100796 /* Determine snapstorage path. -no-snapstorage disables all snapshotting
797 * support. This means you can't resume a snapshot at load, save it at
798 * exit, or even load/save them dynamically at runtime with the console.
799 */
800 if (opts->no_snapstorage) {
801
802 if (opts->snapshot) {
803 dwarning("ignoring -snapshot option due to the use of -no-snapstorage");
804 opts->snapshot = NULL;
805 }
806
807 if (opts->snapstorage) {
808 dwarning("ignoring -snapstorage option due to the use of -no-snapstorage");
809 opts->snapstorage = NULL;
810 }
811 }
812 else
813 {
Vladimir Chtchetkine873c3cb2012-03-14 12:46:51 -0700814 if (!opts->snapstorage && avdInfo_getSnapshotPresent(avd)) {
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100815 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
816 if (opts->snapstorage != NULL) {
817 D("autoconfig: -snapstorage %s", opts->snapstorage);
Ot ten Thije353b3b12010-10-05 17:53:30 +0100818 }
819 }
820
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100821 if (opts->snapstorage && !path_exists(opts->snapstorage)) {
822 D("no image at '%s', state snapshots disabled", opts->snapstorage);
823 opts->snapstorage = NULL;
Ot ten Thije353b3b12010-10-05 17:53:30 +0100824 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100825 }
826
827 /* If we have a valid snapshot storage path */
828
829 if (opts->snapstorage) {
830
831 hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage);
832
833 /* -no-snapshot is equivalent to using both -no-snapshot-load
834 * and -no-snapshot-save. You can still load/save snapshots dynamically
835 * from the console though.
836 */
837 if (opts->no_snapshot) {
838
839 opts->no_snapshot_load = 1;
840 opts->no_snapshot_save = 1;
841
842 if (opts->snapshot) {
843 dwarning("ignoring -snapshot option due to the use of -no-snapshot.");
844 }
845 }
846
847 if (!opts->no_snapshot_load || !opts->no_snapshot_save) {
848 if (opts->snapshot == NULL) {
849 opts->snapshot = "default-boot";
850 D("autoconfig: -snapshot %s", opts->snapshot);
851 }
852 }
853
854 /* We still use QEMU command-line options for the following since
855 * they can change from one invokation to the next and don't really
856 * correspond to the hardware configuration itself.
857 */
858 if (!opts->no_snapshot_load) {
859 args[n++] = "-loadvm";
860 args[n++] = ASTRDUP(opts->snapshot);
861 }
862
863 if (!opts->no_snapshot_save) {
864 args[n++] = "-savevm-on-exit";
865 args[n++] = ASTRDUP(opts->snapshot);
866 }
867
Tim Baverstock622b8f42010-12-07 11:36:59 +0000868 if (opts->no_snapshot_update_time) {
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100869 args[n++] = "-snapshot-no-time-update";
Tim Baverstock622b8f42010-12-07 11:36:59 +0000870 }
Ot ten Thijeae835ac2010-10-18 13:37:37 +0100871 }
Ot ten Thije353b3b12010-10-05 17:53:30 +0100872
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800873 if (!opts->logcat || opts->logcat[0] == 0) {
874 opts->logcat = getenv("ANDROID_LOG_TAGS");
875 if (opts->logcat && opts->logcat[0] == 0)
876 opts->logcat = NULL;
877 }
878
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800879 /* we always send the kernel messages from ttyS0 to android_kmsg */
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100880 if (opts->show_kernel) {
881 args[n++] = "-show-kernel";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800882 }
883
884 /* XXXX: TODO: implement -shell and -logcat through qemud instead */
885 if (!opts->shell_serial) {
886#ifdef _WIN32
887 opts->shell_serial = "con:";
888#else
889 opts->shell_serial = "stdio";
890#endif
891 }
892 else
893 opts->shell = 1;
894
895 if (opts->shell || opts->logcat) {
896 args[n++] = "-serial";
897 args[n++] = opts->shell_serial;
898 shell_serial = serial++;
899 }
900
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100901 if (opts->radio) {
902 args[n++] = "-radio";
903 args[n++] = opts->radio;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800904 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800905
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100906 if (opts->gps) {
907 args[n++] = "-gps";
908 args[n++] = opts->gps;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800909 }
910
Nick Kralevich185231a2013-10-07 13:54:31 -0700911 if (opts->selinux) {
912 if ((strcmp(opts->selinux, "permissive") != 0)
913 && (strcmp(opts->selinux, "disabled") != 0)) {
914 derror("-selinux must be \"disabled\" or \"permissive\"");
915 exit(1);
916 }
917 }
918
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800919 if (opts->memory) {
920 char* end;
921 long ramSize = strtol(opts->memory, &end, 0);
922 if (ramSize < 0 || *end != 0) {
923 derror( "-memory must be followed by a positive integer" );
924 exit(1);
925 }
926 if (ramSize < 32 || ramSize > 4096) {
927 derror( "physical memory size must be between 32 and 4096 MB" );
928 exit(1);
929 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100930 hw->hw_ramSize = ramSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800931 }
932 if (!opts->memory) {
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100933 int ramSize = hw->hw_ramSize;
934 if (ramSize <= 0) {
935 /* Compute the default RAM size based on the size of screen.
936 * This is only used when the skin doesn't provide the ram
937 * size through its hardware.ini (i.e. legacy ones) or when
938 * in the full Android build system.
939 */
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100940 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height;
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100941 /* The following thresholds are a bit liberal, but we
942 * essentially want to ensure the following mappings:
943 *
944 * 320x480 -> 96
945 * 800x600 -> 128
946 * 1024x768 -> 256
947 *
948 * These are just simple heuristics, they could change in
949 * the future.
950 */
951 if (pixels <= 250000)
952 ramSize = 96;
953 else if (pixels <= 500000)
954 ramSize = 128;
955 else
956 ramSize = 256;
957 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100958 hw->hw_ramSize = ramSize;
959 }
960
961 D("Physical RAM size: %dMB\n", hw->hw_ramSize);
962
963 if (hw->vm_heapSize == 0) {
964 /* Compute the default heap size based on the RAM size.
965 * Essentially, we want to ensure the following liberal mappings:
966 *
967 * 96MB RAM -> 16MB heap
968 * 128MB RAM -> 24MB heap
969 * 256MB RAM -> 48MB heap
970 */
971 int ramSize = hw->hw_ramSize;
972 int heapSize;
973
974 if (ramSize < 100)
975 heapSize = 16;
976 else if (ramSize < 192)
977 heapSize = 24;
978 else
979 heapSize = 48;
980
981 hw->vm_heapSize = heapSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800982 }
983
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800984 if (opts->trace) {
985 args[n++] = "-trace";
986 args[n++] = opts->trace;
987 args[n++] = "-tracing";
988 args[n++] = "off";
989 }
990
David 'Digit' Turnerc0052462014-02-25 18:39:29 +0100991 /* Pass boot properties to the core. First, those from boot.prop,
David 'Digit' Turner5ea91482014-02-13 18:02:56 +0100992 * then those from the command-line */
993 const FileData* bootProperties = avdInfo_getBootProperties(avd);
994 if (!fileData_isEmpty(bootProperties)) {
995 PropertyFileIterator iter[1];
996 propertyFileIterator_init(iter,
997 bootProperties->data,
998 bootProperties->size);
999 while (propertyFileIterator_next(iter)) {
1000 char temp[MAX_PROPERTY_NAME_LEN + MAX_PROPERTY_VALUE_LEN + 2];
1001 snprintf(temp, sizeof temp, "%s=%s", iter->name, iter->value);
1002 args[n++] = "-boot-property";
1003 args[n++] = ASTRDUP(temp);
1004 }
1005 }
David 'Digit' Turnerc0052462014-02-25 18:39:29 +01001006
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -07001007 if (opts->prop != NULL) {
1008 ParamList* pl = opts->prop;
1009 for ( ; pl != NULL; pl = pl->next ) {
1010 args[n++] = "-boot-property";
1011 args[n++] = pl->param;
1012 }
1013 }
1014
David 'Digit' Turner318e4f22009-05-25 18:01:03 +02001015 /* Setup the kernel init options
1016 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001017 {
1018 static char params[1024];
1019 char *p = params, *end = p + sizeof(params);
1020
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +01001021 /* Don't worry about having a leading space here, this is handled
1022 * by the core later. */
1023
Jun Nakajima334ab472011-02-02 23:49:59 -08001024#ifdef TARGET_I386
1025 p = bufprint(p, end, " androidboot.hardware=goldfish");
Jun Nakajimabac9add2011-02-08 22:10:52 -08001026 p = bufprint(p, end, " clocksource=pit");
Jun Nakajima334ab472011-02-02 23:49:59 -08001027#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001028
1029 if (opts->shell || opts->logcat) {
1030 p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial );
1031 }
1032
1033 if (opts->trace) {
1034 p = bufprint(p, end, " android.tracing=1");
1035 }
1036
1037 if (!opts->no_jni) {
1038 p = bufprint(p, end, " android.checkjni=1");
1039 }
1040
1041 if (opts->no_boot_anim) {
1042 p = bufprint( p, end, " android.bootanim=0" );
1043 }
1044
1045 if (opts->logcat) {
1046 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
1047
1048 if (q < end) {
1049 /* replace any space by a comma ! */
1050 {
1051 int nn;
1052 for (nn = 1; p[nn] != 0; nn++)
1053 if (p[nn] == ' ' || p[nn] == '\t')
1054 p[nn] = ',';
1055 p += nn;
1056 }
1057 }
1058 p = q;
1059 }
1060
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001061 if (opts->bootchart) {
1062 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
1063 }
1064
Nick Kralevich185231a2013-10-07 13:54:31 -07001065 if (opts->selinux) {
1066 p = bufprint(p, end, " androidboot.selinux=%s", opts->selinux);
1067 }
1068
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001069 if (p >= end) {
1070 fprintf(stderr, "### ERROR: kernel parameters too long\n");
1071 exit(1);
1072 }
1073
David 'Digit' Turner0b019492011-03-01 14:02:42 +01001074 hw->kernel_parameters = strdup(params);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001075 }
1076
Vladimir Chtchetkined81e6d12010-06-15 16:46:32 -07001077 if (opts->ports) {
1078 args[n++] = "-android-ports";
1079 args[n++] = opts->ports;
1080 }
1081
1082 if (opts->port) {
1083 args[n++] = "-android-port";
1084 args[n++] = opts->port;
1085 }
1086
1087 if (opts->report_console) {
1088 args[n++] = "-android-report-console";
1089 args[n++] = opts->report_console;
1090 }
1091
1092 if (opts->http_proxy) {
1093 args[n++] = "-http-proxy";
1094 args[n++] = opts->http_proxy;
1095 }
1096
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001097 if (!opts->charmap) {
1098 /* Try to find a valid charmap name */
1099 char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap);
1100 if (charmap != NULL) {
1101 D("autoconfig: -charmap %s", charmap);
1102 opts->charmap = charmap;
1103 }
1104 }
1105
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001106 if (opts->charmap) {
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001107 char charmap_name[AKEYCHARMAP_NAME_SIZE];
1108
1109 if (!path_exists(opts->charmap)) {
1110 derror("Charmap file does not exist: %s", opts->charmap);
1111 exit(1);
1112 }
1113 /* We need to store the charmap name in the hardware configuration.
1114 * However, the charmap file itself is only used by the UI component
1115 * and doesn't need to be set to the emulation engine.
1116 */
1117 kcm_extract_charmap_name(opts->charmap, charmap_name,
1118 sizeof(charmap_name));
1119 AFREE(hw->hw_keyboard_charmap);
1120 hw->hw_keyboard_charmap = ASTRDUP(charmap_name);
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001121 }
1122
Vladimir Chtchetkineb5365f32010-08-09 13:33:57 -07001123 if (opts->memcheck) {
1124 args[n++] = "-android-memcheck";
1125 args[n++] = opts->memcheck;
1126 }
1127
David Turner9da935d2011-09-12 21:27:56 +02001128 if (opts->gpu) {
1129 const char* gpu = opts->gpu;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001130 if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) {
David Turner9da935d2011-09-12 21:27:56 +02001131 hw->hw_gpu_enabled = 1;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001132 } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) {
David Turner9da935d2011-09-12 21:27:56 +02001133 hw->hw_gpu_enabled = 0;
1134 } else if (!strcmp(gpu,"auto")) {
1135 /* Nothing to do */
1136 } else {
1137 derror("Invalid value for -gpu <mode> parameter: %s\n", gpu);
1138 derror("Valid values are: on, off or auto\n");
1139 exit(1);
1140 }
1141 }
1142
Vladimir Chtchetkine9242b332012-02-10 08:29:22 -08001143 /* Quit emulator on condition that both, gpu and snapstorage are on. This is
1144 * a temporary solution preventing the emulator from crashing until GPU state
1145 * can be properly saved / resored in snapshot file. */
1146 if (hw->hw_gpu_enabled && opts->snapstorage && (!opts->no_snapshot_load ||
1147 !opts->no_snapshot_save)) {
1148 derror("Snapshots and gpu are mutually exclusive at this point. Please turn one of them off, and restart the emulator.");
1149 exit(1);
1150 }
1151
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001152 /* Deal with camera emulation */
1153 if (opts->webcam_list) {
1154 /* List connected webcameras */
1155 args[n++] = "-list-webcam";
1156 }
1157
1158 if (opts->camera_back) {
1159 /* Validate parameter. */
1160 if (memcmp(opts->camera_back, "webcam", 6) &&
1161 strcmp(opts->camera_back, "emulated") &&
1162 strcmp(opts->camera_back, "none")) {
1163 derror("Invalid value for -camera-back <mode> parameter: %s\n"
1164 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1165 opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001166 exit(1);
1167 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001168 hw->hw_camera_back = ASTRDUP(opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001169 }
1170
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001171 if (opts->camera_front) {
1172 /* Validate parameter. */
1173 if (memcmp(opts->camera_front, "webcam", 6) &&
1174 strcmp(opts->camera_front, "emulated") &&
1175 strcmp(opts->camera_front, "none")) {
1176 derror("Invalid value for -camera-front <mode> parameter: %s\n"
1177 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1178 opts->camera_front);
1179 exit(1);
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -07001180 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001181 hw->hw_camera_front = ASTRDUP(opts->camera_front);
Vladimir Chtchetkinef8675c22012-01-06 10:31:41 -08001182 }
1183
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +01001184 /* physical memory is now in hw->hw_ramSize */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001185
David 'Digit' Turner53eb66d2011-03-01 14:58:23 +01001186 hw->avd_name = ASTRDUP(avdInfo_getName(avd));
David 'Digit' Turner6b8555c2011-02-17 04:28:19 +01001187
Dries Harnie40beab42010-05-15 17:04:47 +02001188 /* Set up the interfaces for inter-emulator networking */
1189 if (opts->shared_net_id) {
1190 unsigned int shared_net_id = atoi(opts->shared_net_id);
1191 char nic[37];
Dries Harnie40beab42010-05-15 17:04:47 +02001192
1193 args[n++] = "-net";
1194 args[n++] = "nic,vlan=0";
1195 args[n++] = "-net";
1196 args[n++] = "user,vlan=0";
Dries Harnie111d6f82010-06-09 21:42:18 +02001197
1198 args[n++] = "-net";
1199 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
1200 args[n++] = strdup(nic);
1201 args[n++] = "-net";
1202 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
Dries Harnie40beab42010-05-15 17:04:47 +02001203 }
1204
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001205 /* Setup screen emulation */
1206 if (opts->screen) {
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001207 if (strcmp(opts->screen, "touch") &&
1208 strcmp(opts->screen, "multi-touch") &&
1209 strcmp(opts->screen, "no-touch")) {
1210
1211 derror("Invalid value for -screen <mode> parameter: %s\n"
1212 "Valid values are: touch, multi-touch, or no-touch\n",
1213 opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001214 exit(1);
1215 }
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001216 hw->hw_screen = ASTRDUP(opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001217 }
1218
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001219 while(argc-- > 0) {
1220 args[n++] = *argv++;
1221 }
1222 args[n] = 0;
1223
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +02001224 /* If the target ABI is armeabi-v7a, we can auto-detect the cpu model
1225 * as a cortex-a8, instead of the default (arm926) which only emulates
1226 * an ARMv5TE CPU.
1227 */
1228 if (!forceArmv7 && hw->hw_cpu_model[0] == '\0')
1229 {
1230 char* abi = avdInfo_getTargetAbi(avd);
1231 if (abi != NULL) {
1232 if (!strcmp(abi, "armeabi-v7a")) {
1233 forceArmv7 = 1;
1234 }
1235 AFREE(abi);
1236 }
1237 }
1238
1239 if (forceArmv7 != 0) {
1240 AFREE(hw->hw_cpu_model);
1241 hw->hw_cpu_model = ASTRDUP("cortex-a8");
1242 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
1243 }
1244
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001245 /* Generate a hardware-qemu.ini for this AVD. The real hardware
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001246 * configuration is ususally stored in several files, e.g. the AVD's
1247 * config.ini plus the skin-specific hardware.ini.
1248 *
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001249 * The new file will group all definitions and will be used to
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001250 * launch the core with the -android-hw <file> option.
1251 */
1252 {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001253 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
1254 IniFile* hwIni = iniFile_newFromMemory("", NULL);
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001255 androidHwConfig_write(hw, hwIni);
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001256
1257 if (filelock_create(coreHwIniPath) == NULL) {
1258 /* The AVD is already in use, we still support this as an
1259 * experimental feature. Use a temporary hardware-qemu.ini
1260 * file though to avoid overwriting the existing one. */
1261 TempFile* tempIni = tempfile_create();
1262 coreHwIniPath = tempfile_path(tempIni);
1263 }
1264
Vladimir Chtchetkinedb450d72012-01-12 13:37:40 -08001265 /* While saving HW config, ignore valueless entries. This will not break
1266 * anything, but will significantly simplify comparing the current HW
1267 * config with the one that has been associated with a snapshot (in case
1268 * VM starts from a snapshot for this instance of emulator). */
1269 if (iniFile_saveToFileClean(hwIni, coreHwIniPath) < 0) {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001270 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001271 exit(2);
1272 }
1273 args[n++] = "-android-hw";
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001274 args[n++] = strdup(coreHwIniPath);
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +02001275
1276 /* In verbose mode, dump the file's content */
1277 if (VERBOSE_CHECK(init)) {
1278 FILE* file = fopen(coreHwIniPath, "rt");
1279 if (file == NULL) {
1280 derror("Could not open hardware configuration file: %s\n",
1281 coreHwIniPath);
1282 } else {
1283 LineInput* input = lineInput_newFromStdFile(file);
1284 const char* line;
1285 printf("Content of hardware configuration file:\n");
1286 while ((line = lineInput_getLine(input)) != NULL) {
1287 printf(" %s\n", line);
1288 }
1289 printf(".\n");
1290 lineInput_free(input);
1291 fclose(file);
1292 }
1293 }
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001294 }
1295
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001296 if(VERBOSE_CHECK(init)) {
1297 int i;
David 'Digit' Turner33361762011-01-19 22:11:03 +01001298 printf("QEMU options list:\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001299 for(i = 0; i < n; i++) {
David 'Digit' Turner33361762011-01-19 22:11:03 +01001300 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001301 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001302 /* Dump final command-line option to make debugging the core easier */
1303 printf("Concatenated QEMU options:\n");
1304 for (i = 0; i < n; i++) {
David 'Digit' Turner26722dd2011-02-24 16:40:20 +01001305 /* To make it easier to copy-paste the output to a command-line,
1306 * quote anything that contains spaces.
1307 */
1308 if (strchr(args[i], ' ') != NULL) {
1309 printf(" '%s'", args[i]);
1310 } else {
1311 printf(" %s", args[i]);
1312 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001313 }
1314 printf("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001315 }
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +01001316
1317 /* Setup SDL UI just before calling the code */
1318 init_sdl_ui(skinConfig, skinPath, opts);
1319
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +01001320 if (attach_ui_to_core(opts) < 0) {
1321 derror("Can't attach to core!");
1322 exit(1);
1323 }
1324
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001325 return qemu_main(n, args);
1326}