1 /* Copyright (C) 2006-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 ** GNU General Public License for more details.
11 */
12
13 #include <signal.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <sys/time.h>
17 #ifdef _WIN32
18 #include <process.h>
19 #endif
20 #include "libslirp.h"
21 #include "sockets.h"
22
23 #include "android/android.h"
24 #include "qemu-common.h"
25 #include "sysemu.h"
26 #include "console.h"
27 #include "user-events.h"
28
29 #include <SDL.h>
30 #include <SDL_syswm.h>
31
32 #include "math.h"
33
34 #include "android/charmap.h"
35 #include "modem_driver.h"
36 #include "proxy_http.h"
37
38 #include "android/utils/debug.h"
39 #include "android/resource.h"
40 #include "android/config.h"
41 #include "android/config/config.h"
42
43 #include "android/skin/image.h"
44 #include "android/skin/trackball.h"
45 #include "android/skin/keyboard.h"
46 #include "android/skin/file.h"
47 #include "android/skin/window.h"
48 #include "android/skin/keyset.h"
49
50 #include "android/gps.h"
51 #include "android/hw-qemud.h"
52 #include "android/hw-kmsg.h"
53 #include "android/hw-lcd.h"
54 #include "android/hw-sensors.h"
55 #include "android/boot-properties.h"
56 #include "android/user-config.h"
57 #include "android/utils/bufprint.h"
58 #include "android/utils/dirscanner.h"
59 #include "android/utils/path.h"
60 #include "android/utils/timezone.h"
61
62 #include "android/cmdline-option.h"
63 #include "android/help.h"
64 #include "hw/goldfish_nand.h"
65 #ifdef CONFIG_MEMCHECK
66 #include "memcheck/memcheck.h"
67 #endif // CONFIG_MEMCHECK
68
69 #include "android/globals.h"
70 #include "tcpdump.h"
71
72 #include "android/qemulator.h"
73
74 /* in vl.c */
75 extern void qemu_help(int code);
76
77 #include "framebuffer.h"
78 AndroidRotation android_framebuffer_rotation;
79
80 #define STRINGIFY(x) _STRINGIFY(x)
81 #define _STRINGIFY(x) #x
82
83 #ifdef ANDROID_SDK_TOOLS_REVISION
84 # define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
85 #else
86 # define VERSION_STRING "standalone"
87 #endif
88
89 #define KEYSET_FILE "default.keyset"
90 SkinKeyset* android_keyset;
91
92 #define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
93
94 extern int control_console_start( int port ); /* in control.c */
95
96 extern int qemu_milli_needed;
97
98 /* the default device DPI if none is specified by the skin
99 */
100 #define DEFAULT_DEVICE_DPI 165
101
102 #if 0
103 static int opts->flashkeys; /* forward */
104 #endif
105
106 static void handle_key_command( void* opaque, SkinKeyCommand command, int param );
107
108 #ifdef CONFIG_TRACE
109 extern void start_tracing(void);
110 extern void stop_tracing(void);
111 #endif
112
113 unsigned long android_verbose;
114
115 int qemu_cpu_delay = 0;
116 int qemu_cpu_delay_count;
117
118 /***********************************************************************/
119 /***********************************************************************/
120 /***** *****/
121 /***** U T I L I T Y R O U T I N E S *****/
122 /***** *****/
123 /***********************************************************************/
124 /***********************************************************************/
125
126 /*** CONFIGURATION
127 ***/
128
129 static AUserConfig* userConfig;
130
131 void
emulator_config_init(void)132 emulator_config_init( void )
133 {
134 userConfig = auserConfig_new( android_avdInfo );
135 }
136
137 /* only call this function on normal exits, so that ^C doesn't save the configuration */
138 void
emulator_config_done(void)139 emulator_config_done( void )
140 {
141 int win_x, win_y;
142
143 if (!userConfig) {
144 D("no user configuration?");
145 return;
146 }
147
148 SDL_WM_GetPos( &win_x, &win_y );
149 auserConfig_setWindowPos(userConfig, win_x, win_y);
150 auserConfig_save(userConfig);
151 }
152
153 void *loadpng(const char *fn, unsigned *_width, unsigned *_height);
154 void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height);
155
156 #ifdef CONFIG_DARWIN
157 # define ANDROID_ICON_PNG "android_icon_256.png"
158 #else
159 # define ANDROID_ICON_PNG "android_icon_16.png"
160 #endif
161
162 static void
sdl_set_window_icon(void)163 sdl_set_window_icon( void )
164 {
165 static int window_icon_set;
166
167 if (!window_icon_set)
168 {
169 #ifdef _WIN32
170 HANDLE handle = GetModuleHandle( NULL );
171 HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) );
172 SDL_SysWMinfo wminfo;
173
174 SDL_GetWMInfo(&wminfo);
175
176 SetClassLong( wminfo.window, GCL_HICON, (LONG)icon );
177 #else /* !_WIN32 */
178 unsigned icon_w, icon_h;
179 size_t icon_bytes;
180 const unsigned char* icon_data;
181 void* icon_pixels;
182
183 window_icon_set = 1;
184
185 icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes );
186 if ( !icon_data )
187 return;
188
189 icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h );
190 if ( !icon_pixels )
191 return;
192
193 /* the data is loaded into memory as RGBA bytes by libpng. we want to manage
194 * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending
195 * on our CPU endianess
196 */
197 {
198 unsigned* d = icon_pixels;
199 unsigned* d_end = d + icon_w*icon_h;
200
201 for ( ; d < d_end; d++ ) {
202 unsigned pix = d[0];
203 #if HOST_WORDS_BIGENDIAN
204 /* R,G,B,A read as RGBA => ARGB */
205 pix = ((pix >> 8) & 0xffffff) | (pix << 24);
206 #else
207 /* R,G,B,A read as ABGR => ARGB */
208 pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16);
209 #endif
210 d[0] = pix;
211 }
212 }
213
214 SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h );
215 if (icon != NULL) {
216 SDL_WM_SetIcon(icon, NULL);
217 SDL_FreeSurface(icon);
218 free( icon_pixels );
219 }
220 #endif /* !_WIN32 */
221 }
222 }
223
224 #define ONE_MB (1024*1024)
225
convertBytesToMB(uint64_t size)226 unsigned convertBytesToMB( uint64_t size )
227 {
228 if (size == 0)
229 return 0;
230
231 size = (size + ONE_MB-1) >> 20;
232 if (size > UINT_MAX)
233 size = UINT_MAX;
234
235 return (unsigned) size;
236 }
237
convertMBToBytes(unsigned megaBytes)238 uint64_t convertMBToBytes( unsigned megaBytes )
239 {
240 return ((uint64_t)megaBytes << 20);
241 }
242
243 /***********************************************************************/
244 /***********************************************************************/
245 /***** *****/
246 /***** S K I N I M A G E S *****/
247 /***** *****/
248 /***********************************************************************/
249 /***********************************************************************/
250
251 /* called by the emulated framebuffer device each time the content of the
252 * framebuffer has changed. the rectangle is the bounding box of all changes
253 */
254 static void
sdl_update(DisplayState * ds,int x,int y,int w,int h)255 sdl_update(DisplayState *ds, int x, int y, int w, int h)
256 {
257 /* this function is being called from the console code that is currently inactive
258 ** simple totally ignore it...
259 */
260 (void)ds;
261 (void)x;
262 (void)y;
263 (void)w;
264 (void)h;
265 }
266
267
268
269
270 /* called by the emulated framebuffer device each time the framebuffer
271 * is resized or rotated */
272 static void
sdl_resize(DisplayState * ds)273 sdl_resize(DisplayState *ds)
274 {
275 //fprintf(stderr, "weird, sdl_resize being called with framebuffer interface\n");
276 //exit(1);
277 }
278
279
280 /* called periodically to poll for user input events */
sdl_refresh(DisplayState * ds)281 static void sdl_refresh(DisplayState *ds)
282 {
283 QEmulator* emulator = ds->opaque;
284 SDL_Event ev;
285 SkinWindow* window = emulator->window;
286 SkinKeyboard* keyboard = emulator->keyboard;
287
288 /* this will eventually call sdl_update if the content of the VGA framebuffer
289 * has changed */
290 qframebuffer_check_updates();
291
292 if (window == NULL)
293 return;
294
295 while(SDL_PollEvent(&ev)){
296 switch(ev.type){
297 case SDL_VIDEOEXPOSE:
298 skin_window_redraw( window, NULL );
299 break;
300
301 case SDL_KEYDOWN:
302 #ifdef _WIN32
303 /* special code to deal with Alt-F4 properly */
304 if (ev.key.keysym.sym == SDLK_F4 &&
305 ev.key.keysym.mod & KMOD_ALT) {
306 goto CleanExit;
307 }
308 #endif
309 #ifdef __APPLE__
310 /* special code to deal with Command-Q properly */
311 if (ev.key.keysym.sym == SDLK_q &&
312 ev.key.keysym.mod & KMOD_META) {
313 goto CleanExit;
314 }
315 #endif
316 skin_keyboard_process_event( keyboard, &ev, 1 );
317 break;
318
319 case SDL_KEYUP:
320 skin_keyboard_process_event( keyboard, &ev, 0 );
321 break;
322
323 case SDL_MOUSEMOTION:
324 skin_window_process_event( window, &ev );
325 break;
326
327 case SDL_MOUSEBUTTONDOWN:
328 case SDL_MOUSEBUTTONUP:
329 {
330 int down = (ev.type == SDL_MOUSEBUTTONDOWN);
331 if (ev.button.button == 4)
332 {
333 /* scroll-wheel simulates DPad up */
334 AndroidKeyCode kcode;
335
336 kcode = // qemulator_rotate_keycode(kKeyCodeDpadUp);
337 android_keycode_rotate(kKeyCodeDpadUp,
338 skin_layout_get_dpad_rotation(qemulator_get_layout(qemulator_get())));
339 user_event_key( kcode, down );
340 }
341 else if (ev.button.button == 5)
342 {
343 /* scroll-wheel simulates DPad down */
344 AndroidKeyCode kcode;
345
346 kcode = // qemulator_rotate_keycode(kKeyCodeDpadDown);
347 android_keycode_rotate(kKeyCodeDpadDown,
348 skin_layout_get_dpad_rotation(qemulator_get_layout(qemulator_get())));
349 user_event_key( kcode, down );
350 }
351 else if (ev.button.button == SDL_BUTTON_LEFT) {
352 skin_window_process_event( window, &ev );
353 }
354 #if 0
355 else {
356 fprintf(stderr, "... mouse button %s: button=%d state=%04x x=%d y=%d\n",
357 down ? "down" : "up ",
358 ev.button.button, ev.button.state, ev.button.x, ev.button.y);
359 }
360 #endif
361 }
362 break;
363
364 case SDL_QUIT:
365 #if defined _WIN32 || defined __APPLE__
366 CleanExit:
367 #endif
368 /* only save emulator config through clean exit */
369 qemulator_done(qemulator_get());
370 qemu_system_shutdown_request();
371 return;
372 }
373 }
374
375 skin_keyboard_flush( keyboard );
376 }
377
378
379 /* used to respond to a given keyboard command shortcut
380 */
381 static void
handle_key_command(void * opaque,SkinKeyCommand command,int down)382 handle_key_command( void* opaque, SkinKeyCommand command, int down )
383 {
384 static const struct { SkinKeyCommand cmd; AndroidKeyCode kcode; } keycodes[] =
385 {
386 { SKIN_KEY_COMMAND_BUTTON_CALL, kKeyCodeCall },
387 { SKIN_KEY_COMMAND_BUTTON_HOME, kKeyCodeHome },
388 { SKIN_KEY_COMMAND_BUTTON_BACK, kKeyCodeBack },
389 { SKIN_KEY_COMMAND_BUTTON_HANGUP, kKeyCodeEndCall },
390 { SKIN_KEY_COMMAND_BUTTON_POWER, kKeyCodePower },
391 { SKIN_KEY_COMMAND_BUTTON_SEARCH, kKeyCodeSearch },
392 { SKIN_KEY_COMMAND_BUTTON_MENU, kKeyCodeMenu },
393 { SKIN_KEY_COMMAND_BUTTON_DPAD_UP, kKeyCodeDpadUp },
394 { SKIN_KEY_COMMAND_BUTTON_DPAD_LEFT, kKeyCodeDpadLeft },
395 { SKIN_KEY_COMMAND_BUTTON_DPAD_RIGHT, kKeyCodeDpadRight },
396 { SKIN_KEY_COMMAND_BUTTON_DPAD_DOWN, kKeyCodeDpadDown },
397 { SKIN_KEY_COMMAND_BUTTON_DPAD_CENTER, kKeyCodeDpadCenter },
398 { SKIN_KEY_COMMAND_BUTTON_VOLUME_UP, kKeyCodeVolumeUp },
399 { SKIN_KEY_COMMAND_BUTTON_VOLUME_DOWN, kKeyCodeVolumeDown },
400 { SKIN_KEY_COMMAND_BUTTON_CAMERA, kKeyCodeCamera },
401 { SKIN_KEY_COMMAND_NONE, 0 }
402 };
403 int nn;
404 #ifdef CONFIG_TRACE
405 static int tracing = 0;
406 #endif
407 QEmulator* emulator = opaque;
408
409
410 for (nn = 0; keycodes[nn].kcode != 0; nn++) {
411 if (command == keycodes[nn].cmd) {
412 unsigned code = keycodes[nn].kcode;
413 if (down)
414 code |= 0x200;
415 kbd_put_keycode( code );
416 return;
417 }
418 }
419
420 // for the show-trackball command, handle down events to enable, and
421 // up events to disable
422 if (command == SKIN_KEY_COMMAND_SHOW_TRACKBALL) {
423 emulator->show_trackball = (down != 0);
424 skin_window_show_trackball( emulator->window, emulator->show_trackball );
425 //qemulator_set_title( emulator );
426 return;
427 }
428
429 // only handle down events for the rest
430 if (down == 0)
431 return;
432
433 switch (command)
434 {
435 case SKIN_KEY_COMMAND_TOGGLE_NETWORK:
436 {
437 qemu_net_disable = !qemu_net_disable;
438 if (android_modem) {
439 amodem_set_data_registration(
440 android_modem,
441 qemu_net_disable ? A_REGISTRATION_UNREGISTERED
442 : A_REGISTRATION_HOME);
443 }
444 D( "network is now %s", qemu_net_disable ? "disconnected" : "connected" );
445 }
446 break;
447
448 case SKIN_KEY_COMMAND_TOGGLE_FULLSCREEN:
449 if (emulator->window) {
450 skin_window_toggle_fullscreen(emulator->window);
451 }
452 break;
453
454 case SKIN_KEY_COMMAND_TOGGLE_TRACING:
455 {
456 #ifdef CONFIG_TRACE
457 tracing = !tracing;
458 if (tracing)
459 start_tracing();
460 else
461 stop_tracing();
462 #endif
463 }
464 break;
465
466 case SKIN_KEY_COMMAND_TOGGLE_TRACKBALL:
467 emulator->show_trackball = !emulator->show_trackball;
468 skin_window_show_trackball( emulator->window, emulator->show_trackball );
469 qemulator_set_title(emulator);
470 break;
471
472 case SKIN_KEY_COMMAND_ONION_ALPHA_UP:
473 case SKIN_KEY_COMMAND_ONION_ALPHA_DOWN:
474 if (emulator->onion)
475 {
476 int alpha = emulator->onion_alpha;
477
478 if (command == SKIN_KEY_COMMAND_ONION_ALPHA_UP)
479 alpha += 16;
480 else
481 alpha -= 16;
482
483 if (alpha > 256)
484 alpha = 256;
485 else if (alpha < 0)
486 alpha = 0;
487
488 emulator->onion_alpha = alpha;
489 skin_window_set_onion( emulator->window, emulator->onion, emulator->onion_rotation, alpha );
490 skin_window_redraw( emulator->window, NULL );
491 //dprint( "onion alpha set to %d (%.f %%)", alpha, alpha/2.56 );
492 }
493 break;
494
495 case SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV:
496 case SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT:
497 {
498 SkinLayout* layout = NULL;
499
500 if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT) {
501 layout = emulator->layout->next;
502 if (layout == NULL)
503 layout = emulator->layout_file->layouts;
504 }
505 else if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV) {
506 layout = emulator->layout_file->layouts;
507 while (layout->next && layout->next != emulator->layout)
508 layout = layout->next;
509 }
510 if (layout != NULL) {
511 SkinRotation rotation;
512
513 emulator->layout = layout;
514 skin_window_reset( emulator->window, layout );
515
516 rotation = skin_layout_get_dpad_rotation( layout );
517
518 if (emulator->keyboard)
519 skin_keyboard_set_rotation( emulator->keyboard, rotation );
520
521 if (emulator->trackball) {
522 skin_trackball_set_rotation( emulator->trackball, rotation );
523 skin_window_set_trackball( emulator->window, emulator->trackball );
524 skin_window_show_trackball( emulator->window, emulator->show_trackball );
525 }
526
527 skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness );
528
529 qframebuffer_invalidate_all();
530 qframebuffer_check_updates();
531 }
532 }
533 break;
534
535 default:
536 /* XXX: TODO ? */
537 ;
538 }
539 }
540
541
sdl_at_exit(void)542 static void sdl_at_exit(void)
543 {
544 emulator_config_done();
545 qemulator_done(qemulator_get());
546 SDL_Quit();
547 }
548
549
sdl_display_init(DisplayState * ds,int full_screen,int no_frame)550 void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
551 {
552 QEmulator* emulator = qemulator_get();
553 SkinDisplay* disp = skin_layout_get_display(emulator->layout);
554 DisplayChangeListener* dcl;
555 int width, height;
556
557 if (disp->rotation & 1) {
558 width = disp->rect.size.h;
559 height = disp->rect.size.w;
560 } else {
561 width = disp->rect.size.w;
562 height = disp->rect.size.h;
563 }
564
565 /* Register a display state object for the emulated framebuffer */
566 ds->allocator = &default_allocator;
567 ds->opaque = emulator;
568 ds->surface = qemu_create_displaysurface(ds, width, height);
569 register_displaystate(ds);
570
571 /* Register a change listener for it */
572 dcl = (DisplayChangeListener *) qemu_mallocz(sizeof(DisplayChangeListener));
573 dcl->dpy_update = sdl_update;
574 dcl->dpy_resize = sdl_resize;
575 dcl->dpy_refresh = sdl_refresh;
576 dcl->dpy_text_cursor = NULL;
577 register_displaychangelistener(ds, dcl);
578
579 skin_keyboard_enable( emulator->keyboard, 1 );
580 skin_keyboard_on_command( emulator->keyboard, handle_key_command, emulator );
581 }
582
583
584 static const char* skin_network_speed = NULL;
585 static const char* skin_network_delay = NULL;
586
587 /* list of skin aliases */
588 static const struct {
589 const char* name;
590 const char* alias;
591 } skin_aliases[] = {
592 { "QVGA-L", "320x240" },
593 { "QVGA-P", "240x320" },
594 { "HVGA-L", "480x320" },
595 { "HVGA-P", "320x480" },
596 { "QVGA", "320x240" },
597 { "HVGA", "320x480" },
598 { NULL, NULL }
599 };
600
601 /* this is used by hw/events_device.c to send the charmap name to the system */
602 const char* android_skin_keycharmap = NULL;
603
init_skinned_ui(const char * path,const char * name,AndroidOptions * opts)604 void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts)
605 {
606 char tmp[1024];
607 AConfig* root;
608 AConfig* n;
609 int win_x, win_y, flags;
610
611 signal(SIGINT, SIG_DFL);
612 #ifndef _WIN32
613 signal(SIGQUIT, SIG_DFL);
614 #endif
615
616 /* we're not a game, so allow the screensaver to run */
617 putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1");
618
619 flags = SDL_INIT_NOPARACHUTE;
620 if (!opts->no_window)
621 flags |= SDL_INIT_VIDEO;
622
623 if(SDL_Init(flags)){
624 fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() );
625 exit(1);
626 }
627
628 if (!opts->no_window) {
629 SDL_EnableUNICODE(!opts->raw_keys);
630 SDL_EnableKeyRepeat(0,0);
631
632 sdl_set_window_icon();
633 }
634 else
635 {
636 #ifndef _WIN32
637 /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be
638 * able to run the emulator in the background (e.g. "emulator &").
639 * despite the fact that the emulator should not grab input or try to
640 * write to the output in normal cases, we're stopped on some systems
641 * (e.g. OS X)
642 */
643 signal(SIGTTIN, SIG_IGN);
644 signal(SIGTTOU, SIG_IGN);
645 #endif
646 }
647 atexit(sdl_at_exit);
648
649 root = aconfig_node("", "");
650
651 if(name) {
652 /* Support skin aliases like QVGA-H QVGA-P, etc...
653 But first we check if it's a directory that exist before applying
654 the alias */
655 int checkAlias = 1;
656
657 if (path != NULL) {
658 bufprint(tmp, tmp+sizeof(tmp), "%s/%s", path, name);
659 if (path_exists(tmp)) {
660 checkAlias = 0;
661 } else {
662 D("there is no '%s' skin in '%s'", name, path);
663 }
664 }
665
666 if (checkAlias) {
667 int nn;
668
669 for (nn = 0; ; nn++ ) {
670 const char* skin_name = skin_aliases[nn].name;
671 const char* skin_alias = skin_aliases[nn].alias;
672
673 if ( !skin_name )
674 break;
675
676 if ( !strcasecmp( skin_name, name ) ) {
677 D("skin name '%s' aliased to '%s'", name, skin_alias);
678 name = skin_alias;
679 break;
680 }
681 }
682 }
683
684 /* Magically support skins like "320x240" */
685 if(isdigit(name[0])) {
686 char *x = strchr(name, 'x');
687 if(x && isdigit(x[1])) {
688 int width = atoi(name);
689 int height = atoi(x + 1);
690 sprintf(tmp,"display {\n width %d\n height %d\n}\n",
691 width, height);
692 aconfig_load(root, strdup(tmp));
693 path = ":";
694 goto found_a_skin;
695 }
696 }
697
698 if (path == NULL) {
699 derror("unknown skin name '%s'", name);
700 exit(1);
701 }
702
703 sprintf(tmp, "%s/%s/layout", path, name);
704 D("trying to load skin file '%s'", tmp);
705
706 if(aconfig_load_file(root, tmp) >= 0) {
707 sprintf(tmp, "%s/%s/", path, name);
708 path = tmp;
709 goto found_a_skin;
710 } else {
711 dwarning("could not load skin file '%s', using built-in one\n",
712 tmp);
713 }
714 }
715
716 {
717 const unsigned char* layout_base;
718 size_t layout_size;
719
720 name = "<builtin>";
721
722 layout_base = android_resource_find( "layout", &layout_size );
723 if (layout_base != NULL) {
724 char* base = malloc( layout_size+1 );
725 memcpy( base, layout_base, layout_size );
726 base[layout_size] = 0;
727
728 D("parsing built-in skin layout file (size=%d)", (int)layout_size);
729 aconfig_load(root, base);
730 path = ":";
731 } else {
732 fprintf(stderr, "Couldn't load builtin skin\n");
733 exit(1);
734 }
735 }
736
737 found_a_skin:
738 {
739 win_x = 10;
740 win_y = 10;
741
742 if (userConfig)
743 auserConfig_getWindowPos(userConfig, &win_x, &win_y);
744 }
745
746 if ( qemulator_init(qemulator_get(), root, path, win_x, win_y, opts ) < 0 ) {
747 fprintf(stderr, "### Error: could not load emulator skin '%s'\n", name);
748 exit(1);
749 }
750
751 android_skin_keycharmap = skin_keyboard_charmap_name(qemulator_get()->keyboard);
752
753 /* the default network speed and latency can now be specified by the device skin */
754 n = aconfig_find(root, "network");
755 if (n != NULL) {
756 skin_network_speed = aconfig_str(n, "speed", 0);
757 skin_network_delay = aconfig_str(n, "delay", 0);
758 }
759
760 #if 0
761 /* create a trackball if needed */
762 n = aconfig_find(root, "trackball");
763 if (n != NULL) {
764 SkinTrackBallParameters params;
765
766 params.x = aconfig_unsigned(n, "x", 0);
767 params.y = aconfig_unsigned(n, "y", 0);
768 params.diameter = aconfig_unsigned(n, "diameter", 20);
769 params.ring = aconfig_unsigned(n, "ring", 1);
770
771 params.ball_color = aconfig_unsigned(n, "ball-color", 0xffe0e0e0);
772 params.dot_color = aconfig_unsigned(n, "dot-color", 0xff202020 );
773 params.ring_color = aconfig_unsigned(n, "ring-color", 0xff000000 );
774
775 qemu_disp->trackball = skin_trackball_create( ¶ms );
776 skin_trackball_refresh( qemu_disp->trackball );
777 }
778 #endif
779
780 /* add an onion overlay image if needed */
781 if (opts->onion) {
782 SkinImage* onion = skin_image_find_simple( opts->onion );
783 int alpha, rotate;
784
785 if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) {
786 alpha = (256*alpha)/100;
787 } else
788 alpha = 128;
789
790 if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) {
791 rotate &= 3;
792 } else
793 rotate = SKIN_ROTATION_0;
794
795 qemulator_get()->onion = onion;
796 qemulator_get()->onion_alpha = alpha;
797 qemulator_get()->onion_rotation = rotate;
798 }
799 }
800
801 int qemu_main(int argc, char **argv);
802
803 /* this function dumps the QEMU help */
804 extern void help( void );
805 extern void emulator_help( void );
806
807 #define VERBOSE_OPT(str,var) { str, &var }
808
809 #define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y },
810 static const struct { const char* name; int flag; const char* text; }
811 verbose_options[] = {
812 VERBOSE_TAG_LIST
813 { 0, 0, 0 }
814 };
815
816 static int
load_keyset(const char * path)817 load_keyset(const char* path)
818 {
819 if (path_can_read(path)) {
820 AConfig* root = aconfig_node("","");
821 if (!aconfig_load_file(root, path)) {
822 android_keyset = skin_keyset_new(root);
823 if (android_keyset != NULL) {
824 D( "keyset loaded from: %s", path);
825 return 0;
826 }
827 }
828 }
829 return -1;
830 }
831
832 static void
parse_keyset(const char * keyset,AndroidOptions * opts)833 parse_keyset(const char* keyset, AndroidOptions* opts)
834 {
835 char kname[MAX_PATH];
836 char temp[MAX_PATH];
837 char* p;
838 char* end;
839
840 /* append .keyset suffix if needed */
841 if (strchr(keyset, '.') == NULL) {
842 p = kname;
843 end = p + sizeof(kname);
844 p = bufprint(p, end, "%s.keyset", keyset);
845 if (p >= end) {
846 derror( "keyset name too long: '%s'\n", keyset);
847 exit(1);
848 }
849 keyset = kname;
850 }
851
852 /* look for a the keyset file */
853 p = temp;
854 end = p + sizeof(temp);
855 p = bufprint_config_file(p, end, keyset);
856 if (p < end && load_keyset(temp) == 0)
857 return;
858
859 p = temp;
860 p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset);
861 if (p < end && load_keyset(temp) == 0)
862 return;
863
864 p = temp;
865 p = bufprint_app_dir(p, end);
866 p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset);
867 if (p < end && load_keyset(temp) == 0)
868 return;
869
870 return;
871 }
872
873 static void
write_default_keyset(void)874 write_default_keyset( void )
875 {
876 char path[MAX_PATH];
877
878 bufprint_config_file( path, path+sizeof(path), KEYSET_FILE );
879
880 /* only write if there is no file here */
881 if ( !path_exists(path) ) {
882 int fd = open( path, O_WRONLY | O_CREAT, 0666 );
883 int ret;
884 const char* ks = skin_keyset_get_default();
885
886
887 D( "writing default keyset file to %s", path );
888
889 if (fd < 0) {
890 D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) );
891 return;
892 }
893 CHECKED(ret, write(fd, ks, strlen(ks)));
894 close(fd);
895 }
896 }
897
898 #ifdef CONFIG_NAND_LIMITS
899
900 static uint64_t
parse_nand_rw_limit(const char * value)901 parse_nand_rw_limit( const char* value )
902 {
903 char* end;
904 uint64_t val = strtoul( value, &end, 0 );
905
906 if (end == value) {
907 derror( "bad parameter value '%s': expecting unsigned integer", value );
908 exit(1);
909 }
910
911 switch (end[0]) {
912 case 'K': val <<= 10; break;
913 case 'M': val <<= 20; break;
914 case 'G': val <<= 30; break;
915 case 0: break;
916 default:
917 derror( "bad read/write limit suffix: use K, M or G" );
918 exit(1);
919 }
920 return val;
921 }
922
923 static void
parse_nand_limits(char * limits)924 parse_nand_limits(char* limits)
925 {
926 int pid = -1, signal = -1;
927 int64_t reads = 0, writes = 0;
928 char* item = limits;
929
930 /* parse over comma-separated items */
931 while (item && *item) {
932 char* next = strchr(item, ',');
933 char* end;
934
935 if (next == NULL) {
936 next = item + strlen(item);
937 } else {
938 *next++ = 0;
939 }
940
941 if ( !memcmp(item, "pid=", 4) ) {
942 pid = strtol(item+4, &end, 10);
943 if (end == NULL || *end) {
944 derror( "bad parameter, expecting pid=<number>, got '%s'",
945 item );
946 exit(1);
947 }
948 if (pid <= 0) {
949 derror( "bad parameter: process identifier must be > 0" );
950 exit(1);
951 }
952 }
953 else if ( !memcmp(item, "signal=", 7) ) {
954 signal = strtol(item+7,&end, 10);
955 if (end == NULL || *end) {
956 derror( "bad parameter: expecting signal=<number>, got '%s'",
957 item );
958 exit(1);
959 }
960 if (signal <= 0) {
961 derror( "bad parameter: signal number must be > 0" );
962 exit(1);
963 }
964 }
965 else if ( !memcmp(item, "reads=", 6) ) {
966 reads = parse_nand_rw_limit(item+6);
967 }
968 else if ( !memcmp(item, "writes=", 7) ) {
969 writes = parse_nand_rw_limit(item+7);
970 }
971 else {
972 derror( "bad parameter '%s' (see -help-nand-limits)", item );
973 exit(1);
974 }
975 item = next;
976 }
977 if (pid < 0) {
978 derror( "bad paramater: missing pid=<number>" );
979 exit(1);
980 }
981 else if (signal < 0) {
982 derror( "bad parameter: missing signal=<number>" );
983 exit(1);
984 }
985 else if (reads == 0 && writes == 0) {
986 dwarning( "no read or write limit specified. ignoring -nand-limits" );
987 } else {
988 nand_threshold* t;
989
990 t = &android_nand_read_threshold;
991 t->pid = pid;
992 t->signal = signal;
993 t->counter = 0;
994 t->limit = reads;
995
996 t = &android_nand_write_threshold;
997 t->pid = pid;
998 t->signal = signal;
999 t->counter = 0;
1000 t->limit = writes;
1001 }
1002 }
1003 #endif /* CONFIG_NAND_LIMITS */
1004
emulator_help(void)1005 void emulator_help( void )
1006 {
1007 STRALLOC_DEFINE(out);
1008 android_help_main(out);
1009 printf( "%.*s", out->n, out->s );
1010 stralloc_reset(out);
1011 exit(1);
1012 }
1013
1014 static int
add_dns_server(const char * server_name)1015 add_dns_server( const char* server_name )
1016 {
1017 SockAddress addr;
1018
1019 if (sock_address_init_resolve( &addr, server_name, 55, 0 ) < 0) {
1020 fprintf(stderr,
1021 "### WARNING: can't resolve DNS server name '%s'\n",
1022 server_name );
1023 return -1;
1024 }
1025
1026 D( "DNS server name '%s' resolved to %s", server_name, sock_address_to_string(&addr) );
1027
1028 if ( slirp_add_dns_server( &addr ) < 0 ) {
1029 fprintf(stderr,
1030 "### WARNING: could not add DNS server '%s' to the network stack\n", server_name);
1031 return -1;
1032 }
1033 return 0;
1034 }
1035
1036
1037 /* this function is used to perform auto-detection of the
1038 * system directory in the case of a SDK installation.
1039 *
1040 * we want to deal with several historical usages, hence
1041 * the slightly complicated logic.
1042 *
1043 * NOTE: the function returns the path to the directory
1044 * containing 'fileName'. this is *not* the full
1045 * path to 'fileName'.
1046 */
1047 static char*
_getSdkImagePath(const char * fileName)1048 _getSdkImagePath( const char* fileName )
1049 {
1050 char temp[MAX_PATH];
1051 char* p = temp;
1052 char* end = p + sizeof(temp);
1053 char* q;
1054 char* app;
1055
1056 static const char* const searchPaths[] = {
1057 "", /* program's directory */
1058 "/lib/images", /* this is for SDK 1.0 */
1059 "/../platforms/android-1.1/images", /* this is for SDK 1.1 */
1060 NULL
1061 };
1062
1063 app = bufprint_app_dir(temp, end);
1064 if (app >= end)
1065 return NULL;
1066
1067 do {
1068 int nn;
1069
1070 /* first search a few well-known paths */
1071 for (nn = 0; searchPaths[nn] != NULL; nn++) {
1072 p = bufprint(app, end, "%s", searchPaths[nn]);
1073 q = bufprint(p, end, "/%s", fileName);
1074 if (q < end && path_exists(temp)) {
1075 *p = 0;
1076 goto FOUND_IT;
1077 }
1078 }
1079
1080 /* hmmm. let's assume that we are in a post-1.1 SDK
1081 * scan ../platforms if it exists
1082 */
1083 p = bufprint(app, end, "/../platforms");
1084 if (p < end) {
1085 DirScanner* scanner = dirScanner_new(temp);
1086 if (scanner != NULL) {
1087 int found = 0;
1088 const char* subdir;
1089
1090 for (;;) {
1091 subdir = dirScanner_next(scanner);
1092 if (!subdir) break;
1093
1094 q = bufprint(p, end, "/%s/images/%s", subdir, fileName);
1095 if (q >= end || !path_exists(temp))
1096 continue;
1097
1098 found = 1;
1099 p = bufprint(p, end, "/%s/images", subdir);
1100 break;
1101 }
1102 dirScanner_free(scanner);
1103 if (found)
1104 break;
1105 }
1106 }
1107
1108 /* I'm out of ideas */
1109 return NULL;
1110
1111 } while (0);
1112
1113 FOUND_IT:
1114 //D("image auto-detection: %s/%s", temp, fileName);
1115 return qemu_strdup(temp);
1116 }
1117
1118 static char*
_getSdkImage(const char * path,const char * file)1119 _getSdkImage( const char* path, const char* file )
1120 {
1121 char temp[MAX_PATH];
1122 char *p = temp, *end = p + sizeof(temp);
1123
1124 p = bufprint(temp, end, "%s/%s", path, file);
1125 if (p >= end || !path_exists(temp))
1126 return NULL;
1127
1128 return qemu_strdup(temp);
1129 }
1130
1131 static char*
_getSdkSystemImage(const char * path,const char * optionName,const char * file)1132 _getSdkSystemImage( const char* path, const char* optionName, const char* file )
1133 {
1134 char* image = _getSdkImage(path, file);
1135
1136 if (image == NULL) {
1137 derror("Your system directory is missing the '%s' image file.\n"
1138 "Please specify one with the '%s <filepath>' option",
1139 file, optionName);
1140 exit(2);
1141 }
1142 return image;
1143 }
1144
1145 static void
_forceAvdImagePath(AvdImageType imageType,const char * path,const char * description,int required)1146 _forceAvdImagePath( AvdImageType imageType,
1147 const char* path,
1148 const char* description,
1149 int required )
1150 {
1151 if (path == NULL)
1152 return;
1153
1154 if (required && !path_exists(path)) {
1155 derror("Cannot find %s image file: %s", description, path);
1156 exit(1);
1157 }
1158 android_avdParams->forcePaths[imageType] = path;
1159 }
1160
1161 static uint64_t
_adjustPartitionSize(const char * description,uint64_t imageBytes,uint64_t defaultBytes,int inAndroidBuild)1162 _adjustPartitionSize( const char* description,
1163 uint64_t imageBytes,
1164 uint64_t defaultBytes,
1165 int inAndroidBuild )
1166 {
1167 char temp[64];
1168 unsigned imageMB;
1169 unsigned defaultMB;
1170
1171 if (imageBytes <= defaultBytes)
1172 return defaultBytes;
1173
1174 imageMB = convertBytesToMB(imageBytes);
1175 defaultMB = convertBytesToMB(defaultBytes);
1176
1177 if (imageMB > defaultMB) {
1178 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
1179 } else {
1180 snprintf(temp, sizeof temp, "(%lld bytes > %lld bytes)", imageBytes, defaultBytes);
1181 }
1182
1183 if (inAndroidBuild) {
1184 dwarning("%s partition size adjusted to match image file %s\n", description, temp);
1185 }
1186
1187 return convertMBToBytes(imageMB);
1188 }
1189
1190
main(int argc,char ** argv)1191 int main(int argc, char **argv)
1192 {
1193 char tmp[MAX_PATH];
1194 char* tmpend = tmp + sizeof(tmp);
1195 char* args[128];
1196 int n;
1197 char* opt;
1198 int use_sdcard_img = 0;
1199 int serial = 0;
1200 int gps_serial = 0;
1201 int radio_serial = 0;
1202 int qemud_serial = 0;
1203 int shell_serial = 0;
1204 int dns_count = 0;
1205 unsigned cachePartitionSize = 0;
1206 unsigned systemPartitionSize = 0;
1207 unsigned dataPartitionSize = 0;
1208 unsigned defaultPartitionSize = convertMBToBytes(66);
1209
1210 AndroidHwConfig* hw;
1211 AvdInfo* avd;
1212
1213 //const char *appdir = get_app_dir();
1214 char* android_build_root = NULL;
1215 char* android_build_out = NULL;
1216
1217 AndroidOptions opts[1];
1218
1219 args[0] = argv[0];
1220
1221 if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
1222 exit(1);
1223 }
1224
1225 while (argc-- > 1) {
1226 opt = (++argv)[0];
1227
1228 if(!strcmp(opt, "-qemu")) {
1229 argc--;
1230 argv++;
1231 break;
1232 }
1233
1234 if (!strcmp(opt, "-help")) {
1235 emulator_help();
1236 }
1237
1238 if (!strncmp(opt, "-help-",6)) {
1239 STRALLOC_DEFINE(out);
1240 opt += 6;
1241
1242 if (!strcmp(opt, "all")) {
1243 android_help_all(out);
1244 }
1245 else if (android_help_for_option(opt, out) == 0) {
1246 /* ok */
1247 }
1248 else if (android_help_for_topic(opt, out) == 0) {
1249 /* ok */
1250 }
1251 if (out->n > 0) {
1252 printf("\n%.*s", out->n, out->s);
1253 exit(0);
1254 }
1255
1256 fprintf(stderr, "unknown option: -help-%s\n", opt);
1257 fprintf(stderr, "please use -help for a list of valid topics\n");
1258 exit(1);
1259 }
1260
1261 if (opt[0] == '-') {
1262 fprintf(stderr, "unknown option: %s\n", opt);
1263 fprintf(stderr, "please use -help for a list of valid options\n");
1264 exit(1);
1265 }
1266
1267 fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
1268 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
1269 fprintf(stderr, "please use -help for more information\n");
1270 exit(1);
1271 }
1272
1273 /* special case, if -qemu -h is used, directly invoke the QEMU-specific help */
1274 if (argc > 0) {
1275 int nn;
1276 for (nn = 0; nn < argc; nn++)
1277 if (!strcmp(argv[nn], "-h")) {
1278 qemu_help(0);
1279 break;
1280 }
1281 }
1282
1283 if (android_charmap_setup(opts->charmap)) {
1284 exit(1);
1285 }
1286
1287 if (opts->version) {
1288 printf("Android emulator version %s\n"
1289 "Copyright (C) 2006-2008 The Android Open Source Project and many others.\n"
1290 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
1291 #if defined ANDROID_BUILD_ID
1292 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
1293 #else
1294 VERSION_STRING);
1295 #endif
1296 printf(" This software is licensed under the terms of the GNU General Public\n"
1297 " License version 2, as published by the Free Software Foundation, and\n"
1298 " may be copied, distributed, and modified under those terms.\n\n"
1299 " This program is distributed in the hope that it will be useful,\n"
1300 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1301 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1302 " GNU General Public License for more details.\n\n");
1303
1304 exit(0);
1305 }
1306
1307 if (opts->timezone) {
1308 if ( timezone_set(opts->timezone) < 0 ) {
1309 fprintf(stderr, "emulator: it seems the timezone '%s' is not in zoneinfo format\n", opts->timezone);
1310 }
1311 }
1312
1313 /* legacy support: we used to use -system <dir> and -image <file>
1314 * instead of -sysdir <dir> and -system <file>, so handle this by checking
1315 * whether the options point to directories or files.
1316 */
1317 if (opts->image != NULL) {
1318 if (opts->system != NULL) {
1319 if (opts->sysdir != NULL) {
1320 derror( "You can't use -sysdir, -system and -image at the same time.\n"
1321 "You should probably use '-sysdir <path> -system <file>'.\n" );
1322 exit(2);
1323 }
1324 }
1325 dwarning( "Please note that -image is obsolete and that -system is now used to point\n"
1326 "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" );
1327 opts->sysdir = opts->system;
1328 opts->system = opts->image;
1329 opts->image = NULL;
1330 }
1331 else if (opts->system != NULL && path_is_dir(opts->system)) {
1332 if (opts->sysdir != NULL) {
1333 derror( "Option -system should now be followed by a file path, not a directory one.\n"
1334 "Please use '-sysdir <path>' to point to the system directory.\n" );
1335 exit(1);
1336 }
1337 dwarning( "Please note that the -system option should now be used to point to the initial\n"
1338 "system image (like the obsolete -image option). To point to the system directory\n"
1339 "please now use '-sysdir <path>' instead.\n" );
1340
1341 opts->sysdir = opts->system;
1342 opts->system = NULL;
1343 }
1344
1345 if (opts->nojni)
1346 opts->no_jni = opts->nojni;
1347
1348 if (opts->nocache)
1349 opts->no_cache = opts->nocache;
1350
1351 if (opts->noaudio)
1352 opts->no_audio = opts->noaudio;
1353
1354 if (opts->noskin)
1355 opts->no_skin = opts->noskin;
1356
1357 if (opts->initdata) {
1358 opts->init_data = opts->initdata;
1359 opts->initdata = NULL;
1360 }
1361
1362 /* If no AVD name was given, try to find the top of the
1363 * Android build tree
1364 */
1365 if (opts->avd == NULL) {
1366 do {
1367 char* out = getenv("ANDROID_PRODUCT_OUT");
1368
1369 if (out == NULL || out[0] == 0)
1370 break;
1371
1372 if (!path_exists(out)) {
1373 derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n"
1374 "You need to build the Android system before launching the emulator",
1375 out);
1376 exit(2);
1377 }
1378
1379 android_build_root = path_parent( out, 4 );
1380 if (android_build_root == NULL || !path_exists(android_build_root)) {
1381 derror("Can't find the Android build root from '%s'\n"
1382 "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n"
1383 "It should point to your product-specific build output directory.\n",
1384 out );
1385 exit(2);
1386 }
1387 android_build_out = out;
1388 D( "found Android build root: %s", android_build_root );
1389 D( "found Android build out: %s", android_build_out );
1390 } while (0);
1391 }
1392 /* if no virtual device name is given, and we're not in the
1393 * Android build system, we'll need to perform some auto-detection
1394 * magic :-)
1395 */
1396 if (opts->avd == NULL && !android_build_out)
1397 {
1398 char dataDirIsSystem = 0;
1399
1400 if (!opts->sysdir) {
1401 opts->sysdir = _getSdkImagePath("system.img");
1402 if (!opts->sysdir) {
1403 derror(
1404 "You did not specify a virtual device name, and the system\n"
1405 "directory could not be found.\n\n"
1406 "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n"
1407 "to start a given virtual device (see -help-avd for details).\n\n"
1408
1409 "Otherwise, follow the instructions in -help-disk-images to start the emulator\n"
1410 );
1411 exit(2);
1412 }
1413 D("autoconfig: -sysdir %s", opts->sysdir);
1414 }
1415
1416 if (!opts->system) {
1417 opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img");
1418 D("autoconfig: -image %s", opts->image);
1419 }
1420
1421 if (!opts->kernel) {
1422 opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu");
1423 D("autoconfig: -kernel %s", opts->kernel);
1424 }
1425
1426 if (!opts->ramdisk) {
1427 opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img");
1428 D("autoconfig: -ramdisk %s", opts->ramdisk);
1429 }
1430
1431 /* if no data directory is specified, use the system directory */
1432 if (!opts->datadir) {
1433 opts->datadir = qemu_strdup(opts->sysdir);
1434 dataDirIsSystem = 1;
1435 D("autoconfig: -datadir %s", opts->sysdir);
1436 }
1437
1438 if (!opts->data) {
1439 /* check for userdata-qemu.img in the data directory */
1440 bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir);
1441 if (!path_exists(tmp)) {
1442 derror(
1443 "You did not provide the name of an Android Virtual Device\n"
1444 "with the '-avd <name>' option. Read -help-avd for more information.\n\n"
1445
1446 "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n"
1447 "to specify a data partition image file (I hope you know what you're doing).\n"
1448 );
1449 exit(2);
1450 }
1451
1452 opts->data = qemu_strdup(tmp);
1453 D("autoconfig: -data %s", opts->data);
1454 }
1455
1456 if (!opts->sdcard && opts->datadir) {
1457 bufprint(tmp, tmpend, "%s/sdcard.img", opts->datadir);
1458 if (path_exists(tmp)) {
1459 opts->sdcard = qemu_strdup(tmp);
1460 D("autoconfig: -sdcard %s", opts->sdcard);
1461 }
1462 }
1463 }
1464
1465 /* setup the virtual device parameters from our options
1466 */
1467 if (opts->no_cache) {
1468 android_avdParams->flags |= AVDINFO_NO_CACHE;
1469 }
1470 if (opts->wipe_data) {
1471 android_avdParams->flags |= AVDINFO_WIPE_DATA | AVDINFO_WIPE_CACHE;
1472 }
1473
1474 /* if certain options are set, we can force the path of
1475 * certain kernel/disk image files
1476 */
1477 _forceAvdImagePath(AVD_IMAGE_KERNEL, opts->kernel, "kernel", 1);
1478 _forceAvdImagePath(AVD_IMAGE_INITSYSTEM, opts->system, "system", 1);
1479 _forceAvdImagePath(AVD_IMAGE_RAMDISK, opts->ramdisk,"ramdisk", 1);
1480 _forceAvdImagePath(AVD_IMAGE_USERDATA, opts->data, "user data", 0);
1481 _forceAvdImagePath(AVD_IMAGE_CACHE, opts->cache, "cache", 0);
1482 _forceAvdImagePath(AVD_IMAGE_SDCARD, opts->sdcard, "SD Card", 0);
1483
1484 /* we don't accept -skindir without -skin now
1485 * to simplify the autoconfig stuff with virtual devices
1486 */
1487 if (opts->no_skin) {
1488 opts->skin = "320x480";
1489 opts->skindir = NULL;
1490 }
1491
1492 if (opts->skindir) {
1493 if (!opts->skin) {
1494 derror( "the -skindir <path> option requires a -skin <name> option");
1495 exit(1);
1496 }
1497 }
1498 android_avdParams->skinName = opts->skin;
1499 android_avdParams->skinRootPath = opts->skindir;
1500
1501 /* setup the virtual device differently depending on whether
1502 * we are in the Android build system or not
1503 */
1504 if (opts->avd != NULL)
1505 {
1506 android_avdInfo = avdInfo_new( opts->avd, android_avdParams );
1507 if (android_avdInfo == NULL) {
1508 /* an error message has already been printed */
1509 dprint("could not find virtual device named '%s'", opts->avd);
1510 exit(1);
1511 }
1512 }
1513 else
1514 {
1515 if (!android_build_out) {
1516 android_build_out = android_build_root = opts->sysdir;
1517 }
1518 android_avdInfo = avdInfo_newForAndroidBuild(
1519 android_build_root,
1520 android_build_out,
1521 android_avdParams );
1522
1523 if(android_avdInfo == NULL) {
1524 D("could not start virtual device\n");
1525 exit(1);
1526 }
1527 }
1528
1529 avd = android_avdInfo;
1530
1531 /* get the skin from the virtual device configuration */
1532 opts->skin = (char*) avdInfo_getSkinName( avd );
1533 opts->skindir = (char*) avdInfo_getSkinDir( avd );
1534
1535 if (opts->skin) {
1536 D("autoconfig: -skin %s", opts->skin);
1537 }
1538 if (opts->skindir) {
1539 D("autoconfig: -skindir %s", opts->skindir);
1540 }
1541
1542 /* Read hardware configuration */
1543 hw = android_hw;
1544 if (avdInfo_getHwConfig(avd, hw) < 0) {
1545 derror("could not read hardware configuration ?");
1546 exit(1);
1547 }
1548
1549 #ifdef CONFIG_NAND_LIMITS
1550 if (opts->nand_limits)
1551 parse_nand_limits(opts->nand_limits);
1552 #endif
1553
1554 if (opts->keyset) {
1555 parse_keyset(opts->keyset, opts);
1556 if (!android_keyset) {
1557 fprintf(stderr,
1558 "emulator: WARNING: could not find keyset file named '%s',"
1559 " using defaults instead\n",
1560 opts->keyset);
1561 }
1562 }
1563 if (!android_keyset) {
1564 parse_keyset("default", opts);
1565 if (!android_keyset) {
1566 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
1567 if (!android_keyset) {
1568 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
1569 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
1570 exit(1);
1571 }
1572 if (!opts->keyset)
1573 write_default_keyset();
1574 }
1575 }
1576
1577 /* the purpose of -no-audio is to disable sound output from the emulator,
1578 * not to disable Audio emulation. So simply force the 'none' backends */
1579 if (opts->no_audio)
1580 opts->audio = "none";
1581
1582 if (opts->audio) {
1583 if (opts->audio_in || opts->audio_out) {
1584 derror( "you can't use -audio with -audio-in or -audio-out\n" );
1585 exit(1);
1586 }
1587 if ( !audio_check_backend_name( 0, opts->audio ) ) {
1588 derror( "'%s' is not a valid audio output backend. see -help-audio-out\n",
1589 opts->audio);
1590 exit(1);
1591 }
1592 opts->audio_out = opts->audio;
1593 opts->audio_in = opts->audio;
1594
1595 if ( !audio_check_backend_name( 1, opts->audio ) ) {
1596 fprintf(stderr,
1597 "emulator: warning: '%s' is not a valid audio input backend. audio record disabled\n",
1598 opts->audio);
1599 opts->audio_in = "none";
1600 }
1601 }
1602
1603 if (opts->audio_in) {
1604 static char env[64]; /* note: putenv needs a static unique string buffer */
1605 if ( !audio_check_backend_name( 1, opts->audio_in ) ) {
1606 derror( "'%s' is not a valid audio input backend. see -help-audio-in\n",
1607 opts->audio_in);
1608 exit(1);
1609 }
1610 bufprint( env, env+sizeof(env), "QEMU_AUDIO_IN_DRV=%s", opts->audio_in );
1611 putenv( env );
1612
1613 if (!hw->hw_audioInput) {
1614 dwarning( "Emulated hardware doesn't have audio input.");
1615 }
1616 }
1617 if (opts->audio_out) {
1618 static char env[64]; /* note: putenv needs a static unique string buffer */
1619 if ( !audio_check_backend_name( 0, opts->audio_out ) ) {
1620 derror( "'%s' is not a valid audio output backend. see -help-audio-out\n",
1621 opts->audio_out);
1622 exit(1);
1623 }
1624 bufprint( env, env+sizeof(env), "QEMU_AUDIO_OUT_DRV=%s", opts->audio_out );
1625 putenv( env );
1626 if (!hw->hw_audioOutput) {
1627 dwarning( "Emulated hardware doesn't have audio output");
1628 }
1629 }
1630
1631 if (opts->cpu_delay) {
1632 char* end;
1633 long delay = strtol(opts->cpu_delay, &end, 0);
1634 if (end == NULL || *end || delay < 0 || delay > 1000 ) {
1635 fprintf(stderr, "option -cpu-delay must be an integer between 0 and 1000\n" );
1636 exit(1);
1637 }
1638 if (delay > 0)
1639 delay = (1000-delay);
1640
1641 qemu_cpu_delay = (int) delay;
1642 }
1643
1644 if (opts->shared_net_id) {
1645 char* end;
1646 long shared_net_id = strtol(opts->shared_net_id, &end, 0);
1647 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
1648 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
1649 exit(1);
1650 }
1651 char ip[11];
1652 snprintf(ip, 11, "10.1.2.%ld", shared_net_id);
1653 boot_property_add("net.shared_net_ip",ip);
1654 }
1655
1656
1657 emulator_config_init();
1658 init_skinned_ui(opts->skindir, opts->skin, opts);
1659
1660 if (!opts->netspeed) {
1661 if (skin_network_speed)
1662 D("skin network speed: '%s'", skin_network_speed);
1663 opts->netspeed = (char*)skin_network_speed;
1664 }
1665 if (!opts->netdelay) {
1666 if (skin_network_delay)
1667 D("skin network delay: '%s'", skin_network_delay);
1668 opts->netdelay = (char*)skin_network_delay;
1669 }
1670
1671 if ( android_parse_network_speed(opts->netspeed) < 0 ) {
1672 fprintf(stderr, "invalid -netspeed parameter '%s', see emulator -usage\n", opts->netspeed);
1673 emulator_help();
1674 }
1675
1676 if ( android_parse_network_latency(opts->netdelay) < 0 ) {
1677 fprintf(stderr, "invalid -netdelay parameter '%s', see emulator -usage\n", opts->netdelay);
1678 emulator_help();
1679 }
1680
1681 if (opts->netfast) {
1682 qemu_net_download_speed = 0;
1683 qemu_net_upload_speed = 0;
1684 qemu_net_min_latency = 0;
1685 qemu_net_max_latency = 0;
1686 }
1687
1688 if (opts->trace) {
1689 char* tracePath = avdInfo_getTracePath(avd, opts->trace);
1690 int ret;
1691
1692 if (tracePath == NULL) {
1693 derror( "bad -trace parameter" );
1694 exit(1);
1695 }
1696 ret = path_mkdir_if_needed( tracePath, 0755 );
1697 if (ret < 0) {
1698 fprintf(stderr, "could not create directory '%s'\n", tmp);
1699 exit(2);
1700 }
1701 opts->trace = tracePath;
1702 }
1703
1704 #ifdef CONFIG_MEMCHECK
1705 if (opts->memcheck) {
1706 memcheck_init(opts->memcheck);
1707 }
1708 #endif // CONFIG_MEMCHECK
1709
1710 if (opts->tcpdump) {
1711 if (qemu_tcpdump_start(opts->tcpdump) < 0) {
1712 dwarning( "could not start packet capture: %s", strerror(errno));
1713 }
1714 }
1715
1716 if (opts->no_cache)
1717 opts->cache = 0;
1718
1719 if (opts->dns_server) {
1720 char* x = strchr(opts->dns_server, ',');
1721 dns_count = 0;
1722 if (x == NULL)
1723 {
1724 if ( add_dns_server( opts->dns_server ) == 0 )
1725 dns_count = 1;
1726 }
1727 else
1728 {
1729 x = strdup(opts->dns_server);
1730 while (*x) {
1731 char* y = strchr(x, ',');
1732
1733 if (y != NULL)
1734 *y = 0;
1735
1736 if (y == NULL || y > x) {
1737 if ( add_dns_server( x ) == 0 )
1738 dns_count += 1;
1739 }
1740
1741 if (y == NULL)
1742 break;
1743
1744 x = y+1;
1745 }
1746 }
1747 if (dns_count == 0)
1748 fprintf( stderr, "### WARNING: will use system default DNS server\n" );
1749 }
1750
1751 if (dns_count == 0)
1752 dns_count = slirp_get_system_dns_servers();
1753
1754 n = 1;
1755 /* generate arguments for the underlying qemu main() */
1756 {
1757 const char* kernelFile = avdInfo_getImageFile(avd, AVD_IMAGE_KERNEL);
1758 int kernelFileLen = strlen(kernelFile);
1759
1760 args[n++] = "-kernel";
1761 args[n++] = (char*)kernelFile;
1762
1763 /* If the kernel image name ends in "-armv7", then change the cpu
1764 * type automatically. This is a poor man's approach to configuration
1765 * management, but should allow us to get past building ARMv7
1766 * system images with dex preopt pass without introducing too many
1767 * changes to the emulator sources.
1768 *
1769 * XXX:
1770 * A 'proper' change would require adding some sort of hardware-property
1771 * to each AVD config file, then automatically determine its value for
1772 * full Android builds (depending on some environment variable), plus
1773 * some build system changes. I prefer not to do that for now for reasons
1774 * of simplicity.
1775 */
1776 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
1777 args[n++] = "-cpu";
1778 args[n++] = "cortex-a8";
1779 }
1780 }
1781
1782 args[n++] = "-initrd";
1783 args[n++] = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_RAMDISK);
1784
1785 if (opts->partition_size) {
1786 char* end;
1787 long sizeMB = strtol(opts->partition_size, &end, 0);
1788 long minSizeMB = 10;
1789 long maxSizeMB = LONG_MAX / ONE_MB;
1790
1791 if (sizeMB < 0 || *end != 0) {
1792 derror( "-partition-size must be followed by a positive integer" );
1793 exit(1);
1794 }
1795 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
1796 derror( "partition-size (%d) must be between %dMB and %dMB",
1797 sizeMB, minSizeMB, maxSizeMB );
1798 exit(1);
1799 }
1800 defaultPartitionSize = sizeMB * ONE_MB;
1801 }
1802
1803 /* Check the size of the system partition image.
1804 * If we have an AVD, it must be smaller than
1805 * the disk.systemPartition.size hardware property.
1806 *
1807 * Otherwise, we need to adjust the systemPartitionSize
1808 * automatically, and print a warning.
1809 *
1810 */
1811 {
1812 uint64_t systemBytes = avdInfo_getImageFileSize(avd, AVD_IMAGE_INITSYSTEM);
1813 uint64_t defaultBytes = defaultPartitionSize;
1814
1815 if (defaultBytes == 0 || opts->partition_size)
1816 defaultBytes = defaultPartitionSize;
1817
1818 systemPartitionSize = _adjustPartitionSize("system", systemBytes, defaultBytes,
1819 android_build_out != NULL);
1820 }
1821
1822 /* Check the size of the /data partition. The only interesting cases here are:
1823 * - when the USERDATA image already exists and is larger than the default
1824 * - when we're wiping data and the INITDATA is larger than the default.
1825 */
1826
1827 {
1828 const char* dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA);
1829 uint64_t defaultBytes = defaultPartitionSize;
1830
1831 if (defaultBytes == 0 || opts->partition_size)
1832 defaultBytes = defaultPartitionSize;
1833
1834 if (dataPath == NULL || !path_exists(dataPath) || opts->wipe_data) {
1835 dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_INITDATA);
1836 }
1837 if (dataPath == NULL || !path_exists(dataPath)) {
1838 dataPartitionSize = defaultBytes;
1839 }
1840 else {
1841 uint64_t dataBytes;
1842 path_get_size(dataPath, &dataBytes);
1843
1844 dataPartitionSize = _adjustPartitionSize("data", dataBytes, defaultBytes,
1845 android_build_out != NULL);
1846 }
1847 }
1848
1849 {
1850 const char* filetype = "file";
1851
1852 if (avdInfo_isImageReadOnly(avd, AVD_IMAGE_INITSYSTEM))
1853 filetype = "initfile";
1854
1855 bufprint(tmp, tmpend,
1856 "system,size=0x%x,%s=%s", systemPartitionSize, filetype,
1857 avdInfo_getImageFile(avd, AVD_IMAGE_INITSYSTEM));
1858
1859 args[n++] = "-nand";
1860 args[n++] = strdup(tmp);
1861 }
1862
1863 bufprint(tmp, tmpend,
1864 "userdata,size=0x%x,file=%s",
1865 dataPartitionSize,
1866 avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA));
1867
1868 args[n++] = "-nand";
1869 args[n++] = strdup(tmp);
1870
1871 if (hw->disk_cachePartition) {
1872 opts->cache = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_CACHE);
1873 cachePartitionSize = hw->disk_cachePartition_size;
1874 }
1875 else if (opts->cache) {
1876 dwarning( "Emulated hardware doesn't support a cache partition" );
1877 opts->cache = NULL;
1878 opts->no_cache = 1;
1879 }
1880
1881 if (opts->cache) {
1882 /* use a specific cache file */
1883 sprintf(tmp, "cache,size=0x%0x,file=%s", cachePartitionSize, opts->cache);
1884 args[n++] = "-nand";
1885 args[n++] = strdup(tmp);
1886 }
1887 else if (!opts->no_cache) {
1888 /* create a temporary cache partition file */
1889 sprintf(tmp, "cache,size=0x%0x", cachePartitionSize);
1890 args[n++] = "-nand";
1891 args[n++] = strdup(tmp);
1892 }
1893
1894 if (hw->hw_sdCard != 0)
1895 opts->sdcard = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SDCARD);
1896 else if (opts->sdcard) {
1897 dwarning( "Emulated hardware doesn't support SD Cards" );
1898 opts->sdcard = NULL;
1899 }
1900
1901 if(opts->sdcard) {
1902 uint64_t size;
1903 if (path_get_size(opts->sdcard, &size) == 0) {
1904 /* see if we have an sdcard image. get its size if it exists */
1905 /* due to what looks like limitations of the MMC protocol, one has
1906 * to use an SD Card image that is equal or larger than 9 MB
1907 */
1908 if (size < 9*1024*1024ULL) {
1909 fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard);
1910 } else {
1911 args[n++] = "-hda";
1912 args[n++] = opts->sdcard;
1913 use_sdcard_img = 1;
1914 }
1915 } else {
1916 D("no SD Card image at '%s'", opts->sdcard);
1917 }
1918 }
1919
1920 if (!opts->logcat || opts->logcat[0] == 0) {
1921 opts->logcat = getenv("ANDROID_LOG_TAGS");
1922 if (opts->logcat && opts->logcat[0] == 0)
1923 opts->logcat = NULL;
1924 }
1925
1926 #if 0
1927 if (opts->console) {
1928 derror( "option -console is obsolete. please use -shell instead" );
1929 exit(1);
1930 }
1931 #endif
1932
1933 /* we always send the kernel messages from ttyS0 to android_kmsg */
1934 {
1935 AndroidKmsgFlags flags = 0;
1936
1937 if (opts->show_kernel)
1938 flags |= ANDROID_KMSG_PRINT_MESSAGES;
1939
1940 android_kmsg_init( flags );
1941 args[n++] = "-serial";
1942 args[n++] = "android-kmsg";
1943 serial++;
1944 }
1945
1946 /* XXXX: TODO: implement -shell and -logcat through qemud instead */
1947 if (!opts->shell_serial) {
1948 #ifdef _WIN32
1949 opts->shell_serial = "con:";
1950 #else
1951 opts->shell_serial = "stdio";
1952 #endif
1953 }
1954 else
1955 opts->shell = 1;
1956
1957 if (opts->shell || opts->logcat) {
1958 args[n++] = "-serial";
1959 args[n++] = opts->shell_serial;
1960 shell_serial = serial++;
1961 }
1962
1963 if (opts->old_system)
1964 {
1965 if (opts->radio) {
1966 args[n++] = "-serial";
1967 args[n++] = opts->radio;
1968 radio_serial = serial++;
1969 }
1970 else {
1971 args[n++] = "-serial";
1972 args[n++] = "android-modem";
1973 radio_serial = serial++;
1974 }
1975 if (opts->gps) {
1976 args[n++] = "-serial";
1977 args[n++] = opts->gps;
1978 gps_serial = serial++;
1979 }
1980 }
1981 else /* !opts->old_system */
1982 {
1983 args[n++] = "-serial";
1984 args[n++] = "android-qemud";
1985 qemud_serial = serial++;
1986
1987 if (opts->radio) {
1988 CharDriverState* cs = qemu_chr_open("radio",opts->radio,NULL);
1989 if (cs == NULL) {
1990 derror( "unsupported character device specification: %s\n"
1991 "used -help-char-devices for list of available formats\n", opts->radio );
1992 exit(1);
1993 }
1994 android_qemud_set_channel( ANDROID_QEMUD_GSM, cs);
1995 }
1996 else if ( hw->hw_gsmModem != 0 ) {
1997 if ( android_qemud_get_channel( ANDROID_QEMUD_GSM, &android_modem_cs ) < 0 ) {
1998 derror( "could not initialize qemud 'gsm' channel" );
1999 exit(1);
2000 }
2001 }
2002
2003 if (opts->gps) {
2004 CharDriverState* cs = qemu_chr_open("gps",opts->gps,NULL);
2005 if (cs == NULL) {
2006 derror( "unsupported character device specification: %s\n"
2007 "used -help-char-devices for list of available formats\n", opts->gps );
2008 exit(1);
2009 }
2010 android_qemud_set_channel( ANDROID_QEMUD_GPS, cs);
2011 }
2012 else if ( hw->hw_gps != 0 ) {
2013 if ( android_qemud_get_channel( "gps", &android_gps_cs ) < 0 ) {
2014 derror( "could not initialize qemud 'gps' channel" );
2015 exit(1);
2016 }
2017 }
2018 }
2019
2020 if (opts->memory) {
2021 char* end;
2022 long ramSize = strtol(opts->memory, &end, 0);
2023 if (ramSize < 0 || *end != 0) {
2024 derror( "-memory must be followed by a positive integer" );
2025 exit(1);
2026 }
2027 if (ramSize < 32 || ramSize > 4096) {
2028 derror( "physical memory size must be between 32 and 4096 MB" );
2029 exit(1);
2030 }
2031 }
2032 if (!opts->memory) {
2033 bufprint(tmp, tmpend, "%d", hw->hw_ramSize);
2034 opts->memory = qemu_strdup(tmp);
2035 }
2036
2037 if (opts->trace) {
2038 args[n++] = "-trace";
2039 args[n++] = opts->trace;
2040 args[n++] = "-tracing";
2041 args[n++] = "off";
2042 }
2043
2044 args[n++] = "-append";
2045
2046 if (opts->bootchart) {
2047 char* end;
2048 int timeout = strtol(opts->bootchart, &end, 10);
2049 if (timeout == 0)
2050 opts->bootchart = NULL;
2051 else if (timeout < 0 || timeout > 15*60) {
2052 derror( "timeout specified for -bootchart option is invalid.\n"
2053 "please use integers between 1 and 900\n");
2054 exit(1);
2055 }
2056 }
2057
2058 /* start the 'boot-properties service, and parse the -prop
2059 * options, if any.
2060 */
2061 boot_property_init_service();
2062
2063 hwLcd_setBootProperty(get_device_dpi(opts));
2064
2065 /* Set the VM's max heap size, passed as a boot property */
2066 if (hw->vm_heapSize > 0) {
2067 char tmp[32], *p=tmp, *end=p + sizeof(tmp);
2068 p = bufprint(p, end, "%dm", hw->vm_heapSize);
2069
2070 boot_property_add("dalvik.vm.heapsize",tmp);
2071 }
2072
2073 if (opts->prop != NULL) {
2074 ParamList* pl = opts->prop;
2075 for ( ; pl != NULL; pl = pl->next ) {
2076 boot_property_parse_option(pl->param);
2077 }
2078 }
2079
2080 /* Setup the kernel init options
2081 */
2082 {
2083 static char params[1024];
2084 char *p = params, *end = p + sizeof(params);
2085
2086 p = bufprint(p, end, "qemu=1 console=ttyS0" );
2087
2088 if (opts->shell || opts->logcat) {
2089 p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial );
2090 }
2091
2092 if (opts->trace) {
2093 p = bufprint(p, end, " android.tracing=1");
2094 }
2095
2096 #ifdef CONFIG_MEMCHECK
2097 if (opts->memcheck) {
2098 /* This will set ro.kernel.memcheck system property
2099 * to memcheck's tracing flags. */
2100 p = bufprint(p, end, " memcheck=%s", opts->memcheck);
2101 }
2102 #endif // CONFIG_MEMCHECK
2103
2104 if (!opts->no_jni) {
2105 p = bufprint(p, end, " android.checkjni=1");
2106 }
2107
2108 if (opts->no_boot_anim) {
2109 p = bufprint( p, end, " android.bootanim=0" );
2110 }
2111
2112 if (opts->logcat) {
2113 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
2114
2115 if (q < end) {
2116 /* replace any space by a comma ! */
2117 {
2118 int nn;
2119 for (nn = 1; p[nn] != 0; nn++)
2120 if (p[nn] == ' ' || p[nn] == '\t')
2121 p[nn] = ',';
2122 p += nn;
2123 }
2124 }
2125 p = q;
2126 }
2127
2128 if (opts->old_system)
2129 {
2130 p = bufprint(p, end, " android.ril=ttyS%d", radio_serial);
2131
2132 if (opts->gps) {
2133 p = bufprint(p, end, " android.gps=ttyS%d", gps_serial);
2134 }
2135 }
2136 else
2137 {
2138 p = bufprint(p, end, " android.qemud=ttyS%d", qemud_serial);
2139 }
2140
2141 if (dns_count > 0) {
2142 p = bufprint(p, end, " android.ndns=%d", dns_count);
2143 }
2144
2145 if (opts->bootchart) {
2146 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
2147 }
2148
2149 if (p >= end) {
2150 fprintf(stderr, "### ERROR: kernel parameters too long\n");
2151 exit(1);
2152 }
2153
2154 args[n++] = strdup(params);
2155 }
2156
2157 if (opts->ports) {
2158 args[n++] = "-android-ports";
2159 args[n++] = opts->ports;
2160 }
2161
2162 if (opts->port) {
2163 args[n++] = "-android-port";
2164 args[n++] = opts->port;
2165 }
2166
2167 if (opts->report_console) {
2168 args[n++] = "-android-report-console";
2169 args[n++] = opts->report_console;
2170 }
2171
2172 if (opts->http_proxy) {
2173 args[n++] = "-http-proxy";
2174 args[n++] = opts->http_proxy;
2175 }
2176
2177 /* physical memory */
2178 args[n++] = "-m";
2179 args[n++] = opts->memory;
2180
2181 /* on Linux, the 'dynticks' clock sometimes doesn't work
2182 * properly. this results in the UI freezing while emulation
2183 * continues, for several seconds...
2184 */
2185 #ifdef __linux__
2186 args[n++] = "-clock";
2187 args[n++] = "unix";
2188 #endif
2189
2190 /* Set up the interfaces for inter-emulator networking */
2191 if (opts->shared_net_id) {
2192 unsigned int shared_net_id = atoi(opts->shared_net_id);
2193 char nic[37];
2194
2195 args[n++] = "-net";
2196 args[n++] = "nic,vlan=0";
2197 args[n++] = "-net";
2198 args[n++] = "user,vlan=0";
2199
2200 args[n++] = "-net";
2201 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
2202 args[n++] = strdup(nic);
2203 args[n++] = "-net";
2204 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
2205 }
2206
2207 while(argc-- > 0) {
2208 args[n++] = *argv++;
2209 }
2210 args[n] = 0;
2211
2212 if(VERBOSE_CHECK(init)) {
2213 int i;
2214 for(i = 0; i < n; i++) {
2215 fprintf(stdout, "emulator: argv[%02d] = \"%s\"\n", i, args[i]);
2216 }
2217 }
2218 return qemu_main(n, args);
2219 }
2220