• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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( &params );
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