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
28#include <SDL.h>
29#include <SDL_syswm.h>
30
31#include "math.h"
32
33#include "android/charmap.h"
34#include "modem_driver.h"
35#include "shaper.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-control.h"
55#include "android/hw-sensors.h"
56#include "android/boot-properties.h"
57#include "android/user-config.h"
58#include "android/utils/bufprint.h"
59#include "android/utils/dirscanner.h"
60#include "android/utils/path.h"
61#include "android/utils/timezone.h"
62
63#include "android/cmdline-option.h"
64#include "android/help.h"
65#include "hw/goldfish_nand.h"
66#ifdef CONFIG_MEMCHECK
67#include "memcheck/memcheck.h"
68#endif  // CONFIG_MEMCHECK
69
70#include "android/globals.h"
71#include "tcpdump.h"
72
73/* in vl.c */
74extern void  qemu_help(int  code);
75
76#include "framebuffer.h"
77AndroidRotation  android_framebuffer_rotation;
78
79#define  STRINGIFY(x)   _STRINGIFY(x)
80#define  _STRINGIFY(x)  #x
81
82#ifdef ANDROID_SDK_TOOLS_REVISION
83#  define  VERSION_STRING  STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
84#else
85#  define  VERSION_STRING  "standalone"
86#endif
87
88#define  KEYSET_FILE    "default.keyset"
89SkinKeyset*      android_keyset;
90
91#define  D(...)  do {  if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
92
93extern int  control_console_start( int  port );  /* in control.c */
94
95extern int qemu_milli_needed;
96
97/* the default device DPI if none is specified by the skin
98 */
99#define  DEFAULT_DEVICE_DPI  165
100
101int    android_base_port;
102
103#if 0
104static int  opts->flashkeys;      /* forward */
105#endif
106
107static void  handle_key_command( void*  opaque, SkinKeyCommand  command, int  param );
108
109#ifdef CONFIG_TRACE
110extern void  start_tracing(void);
111extern void  stop_tracing(void);
112#endif
113
114unsigned long   android_verbose;
115
116int   qemu_cpu_delay = 0;
117int   qemu_cpu_delay_count;
118
119/***********************************************************************/
120/***********************************************************************/
121/*****                                                             *****/
122/*****            U T I L I T Y   R O U T I N E S                  *****/
123/*****                                                             *****/
124/***********************************************************************/
125/***********************************************************************/
126
127/*** APPLICATION DIRECTORY
128 *** Where are we ?
129 ***/
130
131const char*  get_app_dir(void)
132{
133    char  buffer[1024];
134    char* p   = buffer;
135    char* end = p + sizeof(buffer);
136    p = bufprint_app_dir(p, end);
137    if (p >= end)
138        return NULL;
139
140    return strdup(buffer);
141}
142
143/***  CONFIGURATION
144 ***/
145
146static AUserConfig*  userConfig;
147
148void
149emulator_config_init( void )
150{
151    userConfig = auserConfig_new( android_avdInfo );
152}
153
154/* only call this function on normal exits, so that ^C doesn't save the configuration */
155void
156emulator_config_done( void )
157{
158    int  win_x, win_y;
159
160    if (!userConfig) {
161        D("no user configuration?");
162        return;
163    }
164
165    SDL_WM_GetPos( &win_x, &win_y );
166    auserConfig_setWindowPos(userConfig, win_x, win_y);
167    auserConfig_save(userConfig);
168}
169
170void *loadpng(const char *fn, unsigned *_width, unsigned *_height);
171void *readpng(const unsigned char*  base, size_t  size, unsigned *_width, unsigned *_height);
172
173#ifdef CONFIG_DARWIN
174#  define  ANDROID_ICON_PNG  "android_icon_256.png"
175#else
176#  define  ANDROID_ICON_PNG  "android_icon_16.png"
177#endif
178
179static void
180sdl_set_window_icon( void )
181{
182    static int  window_icon_set;
183
184    if (!window_icon_set)
185    {
186#ifdef _WIN32
187        HANDLE         handle = GetModuleHandle( NULL );
188        HICON          icon   = LoadIcon( handle, MAKEINTRESOURCE(1) );
189        SDL_SysWMinfo  wminfo;
190
191        SDL_GetWMInfo(&wminfo);
192
193        SetClassLong( wminfo.window, GCL_HICON, (LONG)icon );
194#else  /* !_WIN32 */
195        unsigned              icon_w, icon_h;
196        size_t                icon_bytes;
197        const unsigned char*  icon_data;
198        void*                 icon_pixels;
199
200        window_icon_set = 1;
201
202        icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes );
203        if ( !icon_data )
204            return;
205
206        icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h );
207        if ( !icon_pixels )
208            return;
209
210       /* the data is loaded into memory as RGBA bytes by libpng. we want to manage
211        * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending
212        * on our CPU endianess
213        */
214        {
215            unsigned*  d     = icon_pixels;
216            unsigned*  d_end = d + icon_w*icon_h;
217
218            for ( ; d < d_end; d++ ) {
219                unsigned  pix = d[0];
220#if WORDS_BIGENDIAN
221                /* R,G,B,A read as RGBA => ARGB */
222                pix = ((pix >> 8) & 0xffffff) | (pix << 24);
223#else
224                /* R,G,B,A read as ABGR => ARGB */
225                pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16);
226#endif
227                d[0] = pix;
228            }
229        }
230
231        SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h );
232        if (icon != NULL) {
233            SDL_WM_SetIcon(icon, NULL);
234            SDL_FreeSurface(icon);
235            free( icon_pixels );
236        }
237#endif	/* !_WIN32 */
238    }
239}
240
241/* see http://en.wikipedia.org/wiki/List_of_device_bandwidths or a complete list */
242const NetworkSpeed  android_netspeeds[] = {
243    { "gsm", "GSM/CSD", 14400, 14400 },
244    { "hscsd", "HSCSD", 14400, 43200 },
245    { "gprs", "GPRS", 40000, 80000 },
246    { "edge", "EDGE/EGPRS", 118400, 236800 },
247    { "umts", "UMTS/3G", 128000, 1920000 },
248    { "hsdpa", "HSDPA", 348000, 14400000 },
249    { "full", "no limit", 0, 0 },
250    { NULL, NULL, 0, 0 }
251};
252
253const NetworkLatency  android_netdelays[] = {
254    /* FIXME: these numbers are totally imaginary */
255    { "gprs", "GPRS", 150, 550 },
256    { "edge", "EDGE/EGPRS", 80, 400 },
257    { "umts", "UMTS/3G", 35, 200 },
258    { "none", "no latency", 0, 0 },
259    { NULL, NULL, 0, 0 }
260};
261
262
263
264
265#define  ONE_MB  (1024*1024)
266
267unsigned convertBytesToMB( uint64_t  size )
268{
269    if (size == 0)
270        return 0;
271
272    size = (size + ONE_MB-1) >> 20;
273    if (size > UINT_MAX)
274        size = UINT_MAX;
275
276    return (unsigned) size;
277}
278
279uint64_t  convertMBToBytes( unsigned  megaBytes )
280{
281    return ((uint64_t)megaBytes << 20);
282}
283
284/***********************************************************************/
285/***********************************************************************/
286/*****                                                             *****/
287/*****            S K I N   I M A G E S                            *****/
288/*****                                                             *****/
289/***********************************************************************/
290/***********************************************************************/
291
292void send_key_event(unsigned code, unsigned down)
293{
294    if(code == 0) {
295        return;
296    }
297    if (VERBOSE_CHECK(keys))
298        printf(">> KEY [0x%03x,%s]\n", (code & 0x1ff), down ? "down" : " up " );
299    kbd_put_keycode((code & 0x1ff) | (down ? 0x200 : 0));
300}
301
302
303
304typedef struct {
305    AConfig*       aconfig;
306    SkinFile*      layout_file;
307    SkinLayout*    layout;
308    SkinKeyboard*  keyboard;
309    SkinWindow*    window;
310    int            win_x;
311    int            win_y;
312    int            show_trackball;
313    SkinTrackBall* trackball;
314    int            lcd_brightness;
315    SkinImage*     onion;
316    SkinRotation   onion_rotation;
317    int            onion_alpha;
318
319    AndroidOptions  opts[1];  /* copy of options */
320} QEmulator;
321
322static QEmulator   qemulator[1];
323
324static void
325qemulator_done( QEmulator*  emulator )
326{
327    if (emulator->window) {
328        skin_window_free(emulator->window);
329        emulator->window = NULL;
330    }
331    if (emulator->trackball) {
332        skin_trackball_destroy(emulator->trackball);
333        emulator->trackball = NULL;
334    }
335    if (emulator->keyboard) {
336        skin_keyboard_free(emulator->keyboard);
337        emulator->keyboard = NULL;
338    }
339    emulator->layout = NULL;
340    if (emulator->layout_file) {
341        skin_file_free(emulator->layout_file);
342        emulator->layout_file = NULL;
343    }
344}
345
346
347static void
348qemulator_setup( QEmulator*  emulator );
349
350static void
351qemulator_fb_update( void*   _emulator, int  x, int  y, int  w, int  h )
352{
353    QEmulator*  emulator = _emulator;
354
355    if (emulator->window)
356        skin_window_update_display( emulator->window, x, y, w, h );
357}
358
359static void
360qemulator_fb_rotate( void*  _emulator, int  rotation )
361{
362    QEmulator*     emulator = _emulator;
363
364    qemulator_setup( emulator );
365}
366
367
368
369static int
370qemulator_init( QEmulator*       emulator,
371                AConfig*         aconfig,
372                const char*      basepath,
373                int              x,
374                int              y,
375                AndroidOptions*  opts )
376{
377    emulator->aconfig     = aconfig;
378    emulator->layout_file = skin_file_create_from_aconfig(aconfig, basepath);
379    emulator->layout      = emulator->layout_file->layouts;
380    // If we have a custom charmap use it to initialize keyboard.
381    // Otherwise initialize keyboard from configuration settings.
382    // Another way to configure keyboard to use a custom charmap would
383    // be saving a custom charmap name into AConfig's keyboard->charmap
384    // property, and calling single skin_keyboard_create_from_aconfig
385    // routine to initialize keyboard.
386    if (NULL != opts->charmap) {
387        emulator->keyboard = skin_keyboard_create_from_kcm(opts->charmap, opts->raw_keys);
388    } else {
389        emulator->keyboard = skin_keyboard_create_from_aconfig(aconfig, opts->raw_keys);
390    }
391    emulator->window      = NULL;
392    emulator->win_x       = x;
393    emulator->win_y       = y;
394    emulator->opts[0]     = opts[0];
395
396    /* register as a framebuffer clients for all displays defined in the skin file */
397    SKIN_FILE_LOOP_PARTS( emulator->layout_file, part )
398        SkinDisplay*  disp = part->display;
399        if (disp->valid) {
400            qframebuffer_add_client( disp->qfbuff,
401                                        emulator,
402                                        qemulator_fb_update,
403                                        qemulator_fb_rotate,
404                                        NULL );
405        }
406    SKIN_FILE_LOOP_END_PARTS
407    return 0;
408}
409
410
411static AndroidKeyCode
412qemulator_rotate_keycode( QEmulator*      emulator,
413                          AndroidKeyCode  sym )
414{
415    return android_keycode_rotate( sym,
416                                   skin_layout_get_dpad_rotation(emulator->layout) );
417}
418
419static int
420get_device_dpi( AndroidOptions*  opts )
421{
422    int    dpi_device  = android_hw->hw_lcd_density;
423
424    if (opts->dpi_device != NULL) {
425        char*  end;
426        dpi_device = strtol( opts->dpi_device, &end, 0 );
427        if (end == NULL || *end != 0 || dpi_device <= 0) {
428            fprintf(stderr, "argument for -dpi-device must be a positive integer. Aborting\n" );
429            exit(1);
430        }
431    }
432    return  dpi_device;
433}
434
435static double
436get_default_scale( AndroidOptions*  opts )
437{
438    int     dpi_device  = get_device_dpi( opts );
439    int     dpi_monitor = -1;
440    double  scale       = 0.0;
441
442    /* possible values for the 'scale' option are
443     *   'auto'        : try to determine the scale automatically
444     *   '<number>dpi' : indicates the host monitor dpi, compute scale accordingly
445     *   '<fraction>'  : use direct scale coefficient
446     */
447
448    if (opts->scale) {
449        if (!strcmp(opts->scale, "auto"))
450        {
451            /* we need to get the host dpi resolution ? */
452            int   xdpi, ydpi;
453
454            if ( SDL_WM_GetMonitorDPI( &xdpi, &ydpi ) < 0 ) {
455                fprintf(stderr, "could not get monitor DPI resolution from system. please use -dpi-monitor to specify one\n" );
456                exit(1);
457            }
458            D( "system reported monitor resolutions: xdpi=%d ydpi=%d\n", xdpi, ydpi);
459            dpi_monitor = (xdpi + ydpi+1)/2;
460        }
461        else
462        {
463            char*   end;
464            scale = strtod( opts->scale, &end );
465
466            if (end && end[0] == 'd' && end[1] == 'p' && end[2] == 'i' && end[3] == 0) {
467                if ( scale < 20 || scale > 1000 ) {
468                    fprintf(stderr, "emulator: ignoring bad -scale argument '%s': %s\n", opts->scale,
469                            "host dpi number must be between 20 and 1000" );
470                    exit(1);
471                }
472                dpi_monitor = scale;
473                scale       = 0.0;
474            }
475            else if (end == NULL || *end != 0) {
476                fprintf(stderr, "emulator: ignoring bad -scale argument '%s': %s\n", opts->scale,
477                        "not a number or the 'auto' keyword" );
478                exit(1);
479            }
480            else if ( scale < 0.1 || scale > 3. ) {
481                fprintf(stderr, "emulator: ignoring bad -window-scale argument '%s': %s\n", opts->scale,
482                        "must be between 0.1 and 3.0" );
483                exit(1);
484            }
485        }
486    }
487
488    if (scale == 0.0 && dpi_monitor > 0)
489        scale = dpi_monitor*1.0/dpi_device;
490
491    if (scale == 0.0)
492        scale = 1.0;
493
494    return scale;
495}
496
497void
498android_emulator_set_window_scale( double  scale, int  is_dpi )
499{
500    QEmulator*  emulator = qemulator;
501
502    if (is_dpi)
503        scale /= get_device_dpi( emulator->opts );
504
505    if (emulator->window)
506        skin_window_set_scale( emulator->window, scale );
507}
508
509
510static void
511qemulator_set_title( QEmulator*  emulator )
512{
513    char  temp[128], *p=temp, *end=p+sizeof temp;;
514
515    if (emulator->window == NULL)
516        return;
517
518    if (emulator->show_trackball) {
519        SkinKeyBinding  bindings[ SKIN_KEY_COMMAND_MAX_BINDINGS ];
520        int             count;
521
522        count = skin_keyset_get_bindings( android_keyset,
523                                          SKIN_KEY_COMMAND_TOGGLE_TRACKBALL,
524                                          bindings );
525
526        if (count > 0) {
527            int  nn;
528            p = bufprint( p, end, "Press " );
529            for (nn = 0; nn < count; nn++) {
530                if (nn > 0) {
531                    if (nn < count-1)
532                        p = bufprint(p, end, ", ");
533                    else
534                        p = bufprint(p, end, " or ");
535                }
536                p = bufprint(p, end, "%s",
537                             skin_key_symmod_to_str( bindings[nn].sym,
538                                                     bindings[nn].mod ) );
539            }
540            p = bufprint(p, end, " to leave trackball mode. ");
541        }
542    }
543
544    p = bufprint(p, end, "%d:%s",
545                 android_base_port,
546                 avdInfo_getName( android_avdInfo ));
547
548    skin_window_set_title( emulator->window, temp );
549}
550
551/* called by the emulated framebuffer device each time the content of the
552 * framebuffer has changed. the rectangle is the bounding box of all changes
553 */
554static void
555sdl_update(DisplayState *ds, int x, int y, int w, int h)
556{
557    /* this function is being called from the console code that is currently inactive
558    ** simple totally ignore it...
559    */
560    (void)ds;
561    (void)x;
562    (void)y;
563    (void)w;
564    (void)h;
565}
566
567
568
569static void
570qemulator_light_brightness( void* opaque, const char*  light, int  value )
571{
572    QEmulator*  emulator = opaque;
573
574    VERBOSE_PRINT(hw_control,"%s: light='%s' value=%d window=%p", __FUNCTION__, light, value, emulator->window);
575    if ( !strcmp(light, "lcd_backlight") ) {
576        emulator->lcd_brightness = value;
577        if (emulator->window)
578            skin_window_set_lcd_brightness( emulator->window, value );
579        return;
580    }
581}
582
583
584static void
585qemulator_setup( QEmulator*  emulator )
586{
587    AndroidOptions*  opts = emulator->opts;
588
589    if ( !emulator->window && !opts->no_window ) {
590        SkinLayout*  layout = emulator->layout;
591        double       scale  = get_default_scale(emulator->opts);
592
593        emulator->window = skin_window_create( layout, emulator->win_x, emulator->win_y, scale, 0);
594        if (emulator->window == NULL)
595            return;
596
597        {
598            SkinTrackBall*           ball;
599            SkinTrackBallParameters  params;
600
601            params.diameter   = 30;
602            params.ring       = 2;
603            params.ball_color = 0xffe0e0e0;
604            params.dot_color  = 0xff202020;
605            params.ring_color = 0xff000000;
606
607            ball = skin_trackball_create( &params );
608            emulator->trackball = ball;
609            skin_window_set_trackball( emulator->window, ball );
610
611            emulator->lcd_brightness = 128;  /* 50% */
612            skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness );
613        }
614
615        if ( emulator->onion != NULL )
616            skin_window_set_onion( emulator->window,
617                                   emulator->onion,
618                                   emulator->onion_rotation,
619                                   emulator->onion_alpha );
620
621        qemulator_set_title( emulator );
622
623        skin_window_enable_touch ( emulator->window, android_hw->hw_touchScreen != 0 );
624        skin_window_enable_dpad  ( emulator->window, android_hw->hw_dPad != 0 );
625        skin_window_enable_qwerty( emulator->window, android_hw->hw_keyboard != 0 );
626        skin_window_enable_trackball( emulator->window, android_hw->hw_trackBall != 0 );
627    }
628
629    /* initialize hardware control support */
630    {
631        AndroidHwControlFuncs  funcs;
632
633        funcs.light_brightness = qemulator_light_brightness;
634        android_hw_control_init( emulator, &funcs );
635    }
636}
637
638
639/* called by the emulated framebuffer device each time the framebuffer
640 * is resized or rotated */
641static void
642sdl_resize(DisplayState *ds)
643{
644    //fprintf(stderr, "weird, sdl_resize being called with framebuffer interface\n");
645    //exit(1);
646}
647
648
649/* called periodically to poll for user input events */
650static void sdl_refresh(DisplayState *ds)
651{
652    QEmulator*     emulator = ds->opaque;
653    SDL_Event      ev;
654    SkinWindow*    window   = emulator->window;
655    SkinKeyboard*  keyboard = emulator->keyboard;
656
657   /* this will eventually call sdl_update if the content of the VGA framebuffer
658    * has changed */
659    qframebuffer_check_updates();
660
661    if (window == NULL)
662        return;
663
664    while(SDL_PollEvent(&ev)){
665        switch(ev.type){
666        case SDL_VIDEOEXPOSE:
667            skin_window_redraw( window, NULL );
668            break;
669
670        case SDL_KEYDOWN:
671#ifdef _WIN32
672            /* special code to deal with Alt-F4 properly */
673            if (ev.key.keysym.sym == SDLK_F4 &&
674                ev.key.keysym.mod & KMOD_ALT) {
675              goto CleanExit;
676            }
677#endif
678#ifdef __APPLE__
679            /* special code to deal with Command-Q properly */
680            if (ev.key.keysym.sym == SDLK_q &&
681                ev.key.keysym.mod & KMOD_META) {
682              goto CleanExit;
683            }
684#endif
685            skin_keyboard_process_event( keyboard, &ev, 1 );
686            break;
687
688        case SDL_KEYUP:
689            skin_keyboard_process_event( keyboard, &ev, 0 );
690            break;
691
692        case SDL_MOUSEMOTION:
693            skin_window_process_event( window, &ev );
694            break;
695
696        case SDL_MOUSEBUTTONDOWN:
697        case SDL_MOUSEBUTTONUP:
698            {
699                int  down = (ev.type == SDL_MOUSEBUTTONDOWN);
700                if (ev.button.button == 4)
701                {
702                    /* scroll-wheel simulates DPad up */
703                    AndroidKeyCode  kcode;
704
705                    kcode = qemulator_rotate_keycode(emulator, kKeyCodeDpadUp);
706                    send_key_event( kcode, down );
707                }
708                else if (ev.button.button == 5)
709                {
710                    /* scroll-wheel simulates DPad down */
711                    AndroidKeyCode  kcode;
712
713                    kcode = qemulator_rotate_keycode(emulator, kKeyCodeDpadDown);
714                    send_key_event( kcode, down );
715                }
716                else if (ev.button.button == SDL_BUTTON_LEFT) {
717                    skin_window_process_event( window, &ev );
718                }
719#if 0
720                else {
721                fprintf(stderr, "... mouse button %s: button=%d state=%04x x=%d y=%d\n",
722                                down ? "down" : "up  ",
723                                ev.button.button, ev.button.state, ev.button.x, ev.button.y);
724                }
725#endif
726            }
727            break;
728
729        case SDL_QUIT:
730#if defined _WIN32 || defined __APPLE__
731        CleanExit:
732#endif
733            /* only save emulator config through clean exit */
734            qemulator_done( emulator );
735            qemu_system_shutdown_request();
736            return;
737        }
738    }
739
740    skin_keyboard_flush( keyboard );
741}
742
743
744/* used to respond to a given keyboard command shortcut
745 */
746static void
747handle_key_command( void*  opaque, SkinKeyCommand  command, int  down )
748{
749    static const struct { SkinKeyCommand  cmd; AndroidKeyCode  kcode; }  keycodes[] =
750    {
751        { SKIN_KEY_COMMAND_BUTTON_CALL,   kKeyCodeCall },
752        { SKIN_KEY_COMMAND_BUTTON_HOME,   kKeyCodeHome },
753        { SKIN_KEY_COMMAND_BUTTON_BACK,   kKeyCodeBack },
754        { SKIN_KEY_COMMAND_BUTTON_HANGUP, kKeyCodeEndCall },
755        { SKIN_KEY_COMMAND_BUTTON_POWER,  kKeyCodePower },
756        { SKIN_KEY_COMMAND_BUTTON_SEARCH,      kKeyCodeSearch },
757        { SKIN_KEY_COMMAND_BUTTON_MENU,        kKeyCodeMenu },
758        { SKIN_KEY_COMMAND_BUTTON_DPAD_UP,     kKeyCodeDpadUp },
759        { SKIN_KEY_COMMAND_BUTTON_DPAD_LEFT,   kKeyCodeDpadLeft },
760        { SKIN_KEY_COMMAND_BUTTON_DPAD_RIGHT,  kKeyCodeDpadRight },
761        { SKIN_KEY_COMMAND_BUTTON_DPAD_DOWN,   kKeyCodeDpadDown },
762        { SKIN_KEY_COMMAND_BUTTON_DPAD_CENTER, kKeyCodeDpadCenter },
763        { SKIN_KEY_COMMAND_BUTTON_VOLUME_UP,   kKeyCodeVolumeUp },
764        { SKIN_KEY_COMMAND_BUTTON_VOLUME_DOWN, kKeyCodeVolumeDown },
765        { SKIN_KEY_COMMAND_BUTTON_CAMERA,      kKeyCodeCamera },
766        { SKIN_KEY_COMMAND_NONE, 0 }
767    };
768    int          nn;
769#ifdef CONFIG_TRACE
770    static int   tracing = 0;
771#endif
772    QEmulator*   emulator = opaque;
773
774
775    for (nn = 0; keycodes[nn].kcode != 0; nn++) {
776        if (command == keycodes[nn].cmd) {
777            unsigned  code = keycodes[nn].kcode;
778            if (down)
779                code |= 0x200;
780            kbd_put_keycode( code );
781            return;
782        }
783    }
784
785    // for the show-trackball command, handle down events to enable, and
786    // up events to disable
787    if (command == SKIN_KEY_COMMAND_SHOW_TRACKBALL) {
788        emulator->show_trackball = (down != 0);
789        skin_window_show_trackball( emulator->window, emulator->show_trackball );
790        //qemulator_set_title( emulator );
791        return;
792    }
793
794    // only handle down events for the rest
795    if (down == 0)
796        return;
797
798    switch (command)
799    {
800    case SKIN_KEY_COMMAND_TOGGLE_NETWORK:
801        {
802            qemu_net_disable = !qemu_net_disable;
803            if (android_modem) {
804                amodem_set_data_registration(
805                        android_modem,
806                qemu_net_disable ? A_REGISTRATION_UNREGISTERED
807                    : A_REGISTRATION_HOME);
808            }
809            D( "network is now %s", qemu_net_disable ? "disconnected" : "connected" );
810        }
811        break;
812
813    case SKIN_KEY_COMMAND_TOGGLE_FULLSCREEN:
814        if (emulator->window) {
815            skin_window_toggle_fullscreen(emulator->window);
816        }
817        break;
818
819    case SKIN_KEY_COMMAND_TOGGLE_TRACING:
820        {
821#ifdef CONFIG_TRACE
822            tracing = !tracing;
823            if (tracing)
824                start_tracing();
825            else
826                stop_tracing();
827#endif
828        }
829        break;
830
831    case SKIN_KEY_COMMAND_TOGGLE_TRACKBALL:
832        emulator->show_trackball = !emulator->show_trackball;
833        skin_window_show_trackball( emulator->window, emulator->show_trackball );
834        qemulator_set_title( emulator );
835        break;
836
837    case SKIN_KEY_COMMAND_ONION_ALPHA_UP:
838    case SKIN_KEY_COMMAND_ONION_ALPHA_DOWN:
839        if (emulator->onion)
840        {
841            int  alpha = emulator->onion_alpha;
842
843            if (command == SKIN_KEY_COMMAND_ONION_ALPHA_UP)
844                alpha += 16;
845            else
846                alpha -= 16;
847
848            if (alpha > 256)
849                alpha = 256;
850            else if (alpha < 0)
851                alpha = 0;
852
853            emulator->onion_alpha = alpha;
854            skin_window_set_onion( emulator->window, emulator->onion, emulator->onion_rotation, alpha );
855            skin_window_redraw( emulator->window, NULL );
856            //dprint( "onion alpha set to %d (%.f %%)", alpha, alpha/2.56 );
857        }
858        break;
859
860    case SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV:
861    case SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT:
862        {
863            SkinLayout*  layout = NULL;
864
865            if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT) {
866                layout = emulator->layout->next;
867                if (layout == NULL)
868                    layout = emulator->layout_file->layouts;
869            }
870            else if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV) {
871                layout = emulator->layout_file->layouts;
872                while (layout->next && layout->next != emulator->layout)
873                    layout = layout->next;
874            }
875            if (layout != NULL) {
876                SkinRotation  rotation;
877
878                emulator->layout = layout;
879                skin_window_reset( emulator->window, layout );
880
881                rotation = skin_layout_get_dpad_rotation( layout );
882
883                if (emulator->keyboard)
884                    skin_keyboard_set_rotation( emulator->keyboard, rotation );
885
886                if (emulator->trackball) {
887                    skin_trackball_set_rotation( emulator->trackball, rotation );
888                    skin_window_set_trackball( emulator->window, emulator->trackball );
889                    skin_window_show_trackball( emulator->window, emulator->show_trackball );
890                }
891
892                skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness );
893
894                qframebuffer_invalidate_all();
895                qframebuffer_check_updates();
896            }
897        }
898        break;
899
900    default:
901        /* XXX: TODO ? */
902        ;
903    }
904}
905
906
907static void sdl_at_exit(void)
908{
909    emulator_config_done();
910    qemulator_done( qemulator );
911    SDL_Quit();
912}
913
914
915void sdl_display_init(DisplayState *ds, int full_screen, int  no_frame)
916{
917    QEmulator*    emulator = qemulator;
918    SkinDisplay*  disp     = skin_layout_get_display(emulator->layout);
919    DisplayChangeListener*  dcl;
920    int           width, height;
921
922    if (disp->rotation & 1) {
923        width  = disp->rect.size.h;
924        height = disp->rect.size.w;
925    } else {
926        width  = disp->rect.size.w;
927        height = disp->rect.size.h;
928    }
929
930    /* Register a display state object for the emulated framebuffer */
931    ds->allocator = &default_allocator;
932    ds->opaque    = emulator;
933    ds->surface   = qemu_create_displaysurface(ds, width, height);
934    register_displaystate(ds);
935
936    /* Register a change listener for it */
937    dcl = (DisplayChangeListener *) qemu_mallocz(sizeof(DisplayChangeListener));
938    dcl->dpy_update      = sdl_update;
939    dcl->dpy_resize      = sdl_resize;
940    dcl->dpy_refresh     = sdl_refresh;
941    dcl->dpy_text_cursor = NULL;
942    register_displaychangelistener(ds, dcl);
943
944    skin_keyboard_enable( emulator->keyboard, 1 );
945    skin_keyboard_on_command( emulator->keyboard, handle_key_command, emulator );
946}
947
948
949extern SkinKeyboard*  android_emulator_get_keyboard(void)
950{
951    return qemulator->keyboard;
952}
953
954static const char*  skin_network_speed = NULL;
955static const char*  skin_network_delay = NULL;
956
957/* list of skin aliases */
958static const struct {
959    const char*  name;
960    const char*  alias;
961} skin_aliases[] = {
962    { "QVGA-L", "320x240" },
963    { "QVGA-P", "240x320" },
964    { "HVGA-L", "480x320" },
965    { "HVGA-P", "320x480" },
966    { "QVGA", "320x240" },
967    { "HVGA", "320x480" },
968    { NULL, NULL }
969};
970
971/* this is used by hw/events_device.c to send the charmap name to the system */
972const char*    android_skin_keycharmap = NULL;
973
974void init_skinned_ui(const char *path, const char *name, AndroidOptions*  opts)
975{
976    char      tmp[1024];
977    AConfig*  root;
978    AConfig*  n;
979    int       win_x, win_y, flags;
980
981    signal(SIGINT, SIG_DFL);
982#ifndef _WIN32
983    signal(SIGQUIT, SIG_DFL);
984#endif
985
986    /* we're not a game, so allow the screensaver to run */
987    putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1");
988
989    flags = SDL_INIT_NOPARACHUTE;
990    if (!opts->no_window)
991        flags |= SDL_INIT_VIDEO;
992
993    if(SDL_Init(flags)){
994        fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() );
995        exit(1);
996    }
997
998    if (!opts->no_window) {
999        SDL_EnableUNICODE(!opts->raw_keys);
1000        SDL_EnableKeyRepeat(0,0);
1001
1002        sdl_set_window_icon();
1003    }
1004    else
1005    {
1006#ifndef _WIN32
1007       /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be
1008        * able to run the emulator in the background (e.g. "emulator &").
1009        * despite the fact that the emulator should not grab input or try to
1010        * write to the output in normal cases, we're stopped on some systems
1011        * (e.g. OS X)
1012        */
1013        signal(SIGTTIN, SIG_IGN);
1014        signal(SIGTTOU, SIG_IGN);
1015#endif
1016    }
1017    atexit(sdl_at_exit);
1018
1019    root = aconfig_node("", "");
1020
1021    if(name) {
1022        /* Support skin aliases like QVGA-H QVGA-P, etc...
1023           But first we check if it's a directory that exist before applying
1024           the alias */
1025        int  checkAlias = 1;
1026
1027        if (path != NULL) {
1028            bufprint(tmp, tmp+sizeof(tmp), "%s/%s", path, name);
1029            if (path_exists(tmp)) {
1030                checkAlias = 0;
1031            } else {
1032                D("there is no '%s' skin in '%s'", name, path);
1033            }
1034        }
1035
1036        if (checkAlias) {
1037            int  nn;
1038
1039            for (nn = 0; ; nn++ ) {
1040                const char*  skin_name  = skin_aliases[nn].name;
1041                const char*  skin_alias = skin_aliases[nn].alias;
1042
1043                if ( !skin_name )
1044                    break;
1045
1046                if ( !strcasecmp( skin_name, name ) ) {
1047                    D("skin name '%s' aliased to '%s'", name, skin_alias);
1048                    name = skin_alias;
1049                    break;
1050                }
1051            }
1052        }
1053
1054        /* Magically support skins like "320x240" */
1055        if(isdigit(name[0])) {
1056            char *x = strchr(name, 'x');
1057            if(x && isdigit(x[1])) {
1058                int width = atoi(name);
1059                int height = atoi(x + 1);
1060                sprintf(tmp,"display {\n  width %d\n  height %d\n}\n",
1061                        width, height);
1062                aconfig_load(root, strdup(tmp));
1063                path = ":";
1064                goto found_a_skin;
1065            }
1066        }
1067
1068        if (path == NULL) {
1069            derror("unknown skin name '%s'", name);
1070            exit(1);
1071        }
1072
1073        sprintf(tmp, "%s/%s/layout", path, name);
1074        D("trying to load skin file '%s'", tmp);
1075
1076        if(aconfig_load_file(root, tmp) >= 0) {
1077            sprintf(tmp, "%s/%s/", path, name);
1078            path = tmp;
1079            goto found_a_skin;
1080        } else {
1081            dwarning("could not load skin file '%s', using built-in one\n",
1082                     tmp);
1083        }
1084    }
1085
1086    {
1087        const unsigned char*  layout_base;
1088        size_t                layout_size;
1089
1090        name = "<builtin>";
1091
1092        layout_base = android_resource_find( "layout", &layout_size );
1093        if (layout_base != NULL) {
1094            char*  base = malloc( layout_size+1 );
1095            memcpy( base, layout_base, layout_size );
1096            base[layout_size] = 0;
1097
1098            D("parsing built-in skin layout file (size=%d)", (int)layout_size);
1099            aconfig_load(root, base);
1100            path = ":";
1101        } else {
1102            fprintf(stderr, "Couldn't load builtin skin\n");
1103            exit(1);
1104        }
1105    }
1106
1107found_a_skin:
1108    {
1109        win_x = 10;
1110        win_y = 10;
1111
1112        if (userConfig)
1113            auserConfig_getWindowPos(userConfig, &win_x, &win_y);
1114    }
1115
1116    if ( qemulator_init( qemulator, root, path, win_x, win_y, opts ) < 0 ) {
1117        fprintf(stderr, "### Error: could not load emulator skin '%s'\n", name);
1118        exit(1);
1119    }
1120
1121    android_skin_keycharmap = skin_keyboard_charmap_name(qemulator->keyboard);
1122
1123    /* the default network speed and latency can now be specified by the device skin */
1124    n = aconfig_find(root, "network");
1125    if (n != NULL) {
1126        skin_network_speed = aconfig_str(n, "speed", 0);
1127        skin_network_delay = aconfig_str(n, "delay", 0);
1128    }
1129
1130#if 0
1131    /* create a trackball if needed */
1132    n = aconfig_find(root, "trackball");
1133    if (n != NULL) {
1134        SkinTrackBallParameters  params;
1135
1136        params.x        = aconfig_unsigned(n, "x", 0);
1137        params.y        = aconfig_unsigned(n, "y", 0);
1138        params.diameter = aconfig_unsigned(n, "diameter", 20);
1139        params.ring     = aconfig_unsigned(n, "ring", 1);
1140
1141        params.ball_color = aconfig_unsigned(n, "ball-color", 0xffe0e0e0);
1142        params.dot_color  = aconfig_unsigned(n, "dot-color",  0xff202020 );
1143        params.ring_color = aconfig_unsigned(n, "ring-color", 0xff000000 );
1144
1145        qemu_disp->trackball = skin_trackball_create( &params );
1146        skin_trackball_refresh( qemu_disp->trackball );
1147    }
1148#endif
1149
1150    /* add an onion overlay image if needed */
1151    if (opts->onion) {
1152        SkinImage*  onion = skin_image_find_simple( opts->onion );
1153        int         alpha, rotate;
1154
1155        if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) {
1156            alpha = (256*alpha)/100;
1157        } else
1158            alpha = 128;
1159
1160        if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) {
1161            rotate &= 3;
1162        } else
1163            rotate = SKIN_ROTATION_0;
1164
1165        qemulator->onion          = onion;
1166        qemulator->onion_alpha    = alpha;
1167        qemulator->onion_rotation = rotate;
1168    }
1169}
1170
1171int qemu_main(int argc, char **argv);
1172
1173/* this function dumps the QEMU help */
1174extern void  help( void );
1175extern void  emulator_help( void );
1176
1177#define  VERBOSE_OPT(str,var)   { str, &var }
1178
1179#define  _VERBOSE_TAG(x,y)   { #x, VERBOSE_##x, y },
1180static const struct { const char*  name; int  flag; const char*  text; }
1181verbose_options[] = {
1182    VERBOSE_TAG_LIST
1183    { 0, 0, 0 }
1184};
1185
1186int
1187android_parse_network_speed(const char*  speed)
1188{
1189    int          n;
1190    char*  end;
1191    double       sp;
1192
1193    if (speed == NULL || speed[0] == 0) {
1194        speed = DEFAULT_NETSPEED;
1195    }
1196
1197    for (n = 0; android_netspeeds[n].name != NULL; n++) {
1198        if (!strcmp(android_netspeeds[n].name, speed)) {
1199            qemu_net_download_speed = android_netspeeds[n].download;
1200            qemu_net_upload_speed   = android_netspeeds[n].upload;
1201            return 0;
1202        }
1203    }
1204
1205    /* is this a number ? */
1206    sp = strtod(speed, &end);
1207    if (end == speed) {
1208        return -1;
1209    }
1210
1211    qemu_net_download_speed = qemu_net_upload_speed = sp*1000.;
1212    if (*end == ':') {
1213        speed = end+1;
1214        sp = strtod(speed, &end);
1215        if (end > speed) {
1216            qemu_net_download_speed = sp*1000.;
1217        }
1218    }
1219
1220    if (android_modem)
1221        amodem_set_data_network_type( android_modem,
1222                                      android_parse_network_type(speed) );
1223    return 0;
1224}
1225
1226
1227int
1228android_parse_network_latency(const char*  delay)
1229{
1230    int  n;
1231    char*  end;
1232    double  sp;
1233
1234    if (delay == NULL || delay[0] == 0)
1235        delay = DEFAULT_NETDELAY;
1236
1237    for (n = 0; android_netdelays[n].name != NULL; n++) {
1238        if ( !strcmp( android_netdelays[n].name, delay ) ) {
1239            qemu_net_min_latency = android_netdelays[n].min_ms;
1240            qemu_net_max_latency = android_netdelays[n].max_ms;
1241            return 0;
1242        }
1243    }
1244
1245    /* is this a number ? */
1246    sp = strtod(delay, &end);
1247    if (end == delay) {
1248        return -1;
1249    }
1250
1251    qemu_net_min_latency = qemu_net_max_latency = (int)sp;
1252    if (*end == ':') {
1253        delay = (const char*)end+1;
1254        sp = strtod(delay, &end);
1255        if (end > delay) {
1256            qemu_net_max_latency = (int)sp;
1257        }
1258    }
1259    return 0;
1260}
1261
1262
1263static int
1264load_keyset(const char*  path)
1265{
1266    if (path_can_read(path)) {
1267        AConfig*  root = aconfig_node("","");
1268        if (!aconfig_load_file(root, path)) {
1269            android_keyset = skin_keyset_new(root);
1270            if (android_keyset != NULL) {
1271                D( "keyset loaded from: %s", path);
1272                return 0;
1273            }
1274        }
1275    }
1276    return -1;
1277}
1278
1279static void
1280parse_keyset(const char*  keyset, AndroidOptions*  opts)
1281{
1282    char   kname[MAX_PATH];
1283    char   temp[MAX_PATH];
1284    char*  p;
1285    char*  end;
1286
1287    /* append .keyset suffix if needed */
1288    if (strchr(keyset, '.') == NULL) {
1289        p   =  kname;
1290        end = p + sizeof(kname);
1291        p   = bufprint(p, end, "%s.keyset", keyset);
1292        if (p >= end) {
1293            derror( "keyset name too long: '%s'\n", keyset);
1294            exit(1);
1295        }
1296        keyset = kname;
1297    }
1298
1299    /* look for a the keyset file */
1300    p   = temp;
1301    end = p + sizeof(temp);
1302    p = bufprint_config_file(p, end, keyset);
1303    if (p < end && load_keyset(temp) == 0)
1304        return;
1305
1306    p = temp;
1307    p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset);
1308    if (p < end && load_keyset(temp) == 0)
1309        return;
1310
1311    p = temp;
1312    p = bufprint_app_dir(p, end);
1313    p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset);
1314    if (p < end && load_keyset(temp) == 0)
1315        return;
1316
1317    return;
1318}
1319
1320static void
1321write_default_keyset( void )
1322{
1323    char   path[MAX_PATH];
1324
1325    bufprint_config_file( path, path+sizeof(path), KEYSET_FILE );
1326
1327    /* only write if there is no file here */
1328    if ( !path_exists(path) ) {
1329        int          fd = open( path, O_WRONLY | O_CREAT, 0666 );
1330        int          ret;
1331        const char*  ks = skin_keyset_get_default();
1332
1333
1334        D( "writing default keyset file to %s", path );
1335
1336        if (fd < 0) {
1337            D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) );
1338            return;
1339        }
1340        CHECKED(ret, write(fd, ks, strlen(ks)));
1341        close(fd);
1342    }
1343}
1344
1345#ifdef CONFIG_NAND_LIMITS
1346
1347static uint64_t
1348parse_nand_rw_limit( const char*  value )
1349{
1350    char*     end;
1351    uint64_t  val = strtoul( value, &end, 0 );
1352
1353    if (end == value) {
1354        derror( "bad parameter value '%s': expecting unsigned integer", value );
1355        exit(1);
1356    }
1357
1358    switch (end[0]) {
1359        case 'K':  val <<= 10; break;
1360        case 'M':  val <<= 20; break;
1361        case 'G':  val <<= 30; break;
1362        case 0: break;
1363        default:
1364            derror( "bad read/write limit suffix: use K, M or G" );
1365            exit(1);
1366    }
1367    return val;
1368}
1369
1370static void
1371parse_nand_limits(char*  limits)
1372{
1373    int      pid = -1, signal = -1;
1374    int64_t  reads = 0, writes = 0;
1375    char*    item = limits;
1376
1377    /* parse over comma-separated items */
1378    while (item && *item) {
1379        char*  next = strchr(item, ',');
1380        char*  end;
1381
1382        if (next == NULL) {
1383            next = item + strlen(item);
1384        } else {
1385            *next++ = 0;
1386        }
1387
1388        if ( !memcmp(item, "pid=", 4) ) {
1389            pid = strtol(item+4, &end, 10);
1390            if (end == NULL || *end) {
1391                derror( "bad parameter, expecting pid=<number>, got '%s'",
1392                        item );
1393                exit(1);
1394            }
1395            if (pid <= 0) {
1396                derror( "bad parameter: process identifier must be > 0" );
1397                exit(1);
1398            }
1399        }
1400        else if ( !memcmp(item, "signal=", 7) ) {
1401            signal = strtol(item+7,&end, 10);
1402            if (end == NULL || *end) {
1403                derror( "bad parameter: expecting signal=<number>, got '%s'",
1404                        item );
1405                exit(1);
1406            }
1407            if (signal <= 0) {
1408                derror( "bad parameter: signal number must be > 0" );
1409                exit(1);
1410            }
1411        }
1412        else if ( !memcmp(item, "reads=", 6) ) {
1413            reads = parse_nand_rw_limit(item+6);
1414        }
1415        else if ( !memcmp(item, "writes=", 7) ) {
1416            writes = parse_nand_rw_limit(item+7);
1417        }
1418        else {
1419            derror( "bad parameter '%s' (see -help-nand-limits)", item );
1420            exit(1);
1421        }
1422        item = next;
1423    }
1424    if (pid < 0) {
1425        derror( "bad paramater: missing pid=<number>" );
1426        exit(1);
1427    }
1428    else if (signal < 0) {
1429        derror( "bad parameter: missing signal=<number>" );
1430        exit(1);
1431    }
1432    else if (reads == 0 && writes == 0) {
1433        dwarning( "no read or write limit specified. ignoring -nand-limits" );
1434    } else {
1435        nand_threshold*  t;
1436
1437        t  = &android_nand_read_threshold;
1438        t->pid     = pid;
1439        t->signal  = signal;
1440        t->counter = 0;
1441        t->limit   = reads;
1442
1443        t  = &android_nand_write_threshold;
1444        t->pid     = pid;
1445        t->signal  = signal;
1446        t->counter = 0;
1447        t->limit   = writes;
1448    }
1449}
1450#endif /* CONFIG_NAND_LIMITS */
1451
1452void emulator_help( void )
1453{
1454    STRALLOC_DEFINE(out);
1455    android_help_main(out);
1456    printf( "%.*s", out->n, out->s );
1457    stralloc_reset(out);
1458    exit(1);
1459}
1460
1461static int
1462add_dns_server( const char*  server_name )
1463{
1464    SockAddress   addr;
1465
1466    if (sock_address_init_resolve( &addr, server_name, 55, 0 ) < 0) {
1467        fprintf(stderr,
1468                "### WARNING: can't resolve DNS server name '%s'\n",
1469                server_name );
1470        return -1;
1471    }
1472
1473    D( "DNS server name '%s' resolved to %s", server_name, sock_address_to_string(&addr) );
1474
1475    if ( slirp_add_dns_server( &addr ) < 0 ) {
1476        fprintf(stderr,
1477                "### WARNING: could not add DNS server '%s' to the network stack\n", server_name);
1478        return -1;
1479    }
1480    return 0;
1481}
1482
1483
1484enum {
1485    REPORT_CONSOLE_SERVER = (1 << 0),
1486    REPORT_CONSOLE_MAX    = (1 << 1)
1487};
1488
1489static int
1490get_report_console_options( char*  end, int  *maxtries )
1491{
1492    int    flags = 0;
1493
1494    if (end == NULL || *end == 0)
1495        return 0;
1496
1497    if (end[0] != ',') {
1498        derror( "socket port/path can be followed by [,<option>]+ only\n");
1499        exit(3);
1500    }
1501    end += 1;
1502    while (*end) {
1503        char*  p = strchr(end, ',');
1504        if (p == NULL)
1505            p = end + strlen(end);
1506
1507        if (memcmp( end, "server", p-end ) == 0)
1508            flags |= REPORT_CONSOLE_SERVER;
1509        else if (memcmp( end, "max=", 4) == 0) {
1510            end  += 4;
1511            *maxtries = strtol( end, NULL, 10 );
1512            flags |= REPORT_CONSOLE_MAX;
1513        } else {
1514            derror( "socket port/path can be followed by [,server][,max=<count>] only\n");
1515            exit(3);
1516        }
1517
1518        end = p;
1519        if (*end)
1520            end += 1;
1521    }
1522    return flags;
1523}
1524
1525static void
1526report_console( const char*  proto_port, int  console_port )
1527{
1528    int   s = -1, s2;
1529    int   maxtries = 10;
1530    int   flags = 0;
1531    signal_state_t  sigstate;
1532
1533    disable_sigalrm( &sigstate );
1534
1535    if ( !strncmp( proto_port, "tcp:", 4) ) {
1536        char*  end;
1537        long   port = strtol(proto_port + 4, &end, 10);
1538
1539        flags = get_report_console_options( end, &maxtries );
1540
1541        if (flags & REPORT_CONSOLE_SERVER) {
1542            s = socket_loopback_server( port, SOCKET_STREAM );
1543            if (s < 0) {
1544                fprintf(stderr, "could not create server socket on TCP:%ld: %s\n",
1545                        port, errno_str);
1546                exit(3);
1547            }
1548        } else {
1549            for ( ; maxtries > 0; maxtries-- ) {
1550                D("trying to find console-report client on tcp:%d", port);
1551                s = socket_loopback_client( port, SOCKET_STREAM );
1552                if (s >= 0)
1553                    break;
1554
1555                sleep_ms(1000);
1556            }
1557            if (s < 0) {
1558                fprintf(stderr, "could not connect to server on TCP:%ld: %s\n",
1559                        port, errno_str);
1560                exit(3);
1561            }
1562        }
1563    } else if ( !strncmp( proto_port, "unix:", 5) ) {
1564#ifdef _WIN32
1565        fprintf(stderr, "sorry, the unix: protocol is not supported on Win32\n");
1566        exit(3);
1567#else
1568        char*  path = strdup(proto_port+5);
1569        char*  end  = strchr(path, ',');
1570        if (end != NULL) {
1571            flags = get_report_console_options( end, &maxtries );
1572            *end  = 0;
1573        }
1574        if (flags & REPORT_CONSOLE_SERVER) {
1575            s = socket_unix_server( path, SOCKET_STREAM );
1576            if (s < 0) {
1577                fprintf(stderr, "could not bind unix socket on '%s': %s\n",
1578                        proto_port+5, errno_str);
1579                exit(3);
1580            }
1581        } else {
1582            for ( ; maxtries > 0; maxtries-- ) {
1583                s = socket_unix_client( path, SOCKET_STREAM );
1584                if (s >= 0)
1585                    break;
1586
1587                sleep_ms(1000);
1588            }
1589            if (s < 0) {
1590                fprintf(stderr, "could not connect to unix socket on '%s': %s\n",
1591                        path, errno_str);
1592                exit(3);
1593            }
1594        }
1595        free(path);
1596#endif
1597    } else {
1598        fprintf(stderr, "-report-console must be followed by a 'tcp:<port>' or 'unix:<path>'\n");
1599        exit(3);
1600    }
1601
1602    if (flags & REPORT_CONSOLE_SERVER) {
1603        int  tries = 3;
1604        D( "waiting for console-reporting client" );
1605        do {
1606            s2 = socket_accept(s, NULL);
1607        } while (s2 < 0 && --tries > 0);
1608
1609        if (s2 < 0) {
1610            fprintf(stderr, "could not accept console-reporting client connection: %s\n",
1611                   errno_str);
1612            exit(3);
1613        }
1614
1615        socket_close(s);
1616        s = s2;
1617    }
1618
1619    /* simply send the console port in text */
1620    {
1621        char  temp[12];
1622        snprintf( temp, sizeof(temp), "%d", console_port );
1623
1624        if (socket_send(s, temp, strlen(temp)) < 0) {
1625            fprintf(stderr, "could not send console number report: %d: %s\n",
1626                    errno, errno_str );
1627            exit(3);
1628        }
1629        socket_close(s);
1630    }
1631    D( "console port number sent to remote. resuming boot" );
1632
1633    restore_sigalrm (&sigstate);
1634}
1635
1636/* this function is used to perform auto-detection of the
1637 * system directory in the case of a SDK installation.
1638 *
1639 * we want to deal with several historical usages, hence
1640 * the slightly complicated logic.
1641 *
1642 * NOTE: the function returns the path to the directory
1643 *       containing 'fileName'. this is *not* the full
1644 *       path to 'fileName'.
1645 */
1646static char*
1647_getSdkImagePath( const char*  fileName )
1648{
1649    char   temp[MAX_PATH];
1650    char*  p   = temp;
1651    char*  end = p + sizeof(temp);
1652    char*  q;
1653    char*  app;
1654
1655    static const char* const  searchPaths[] = {
1656        "",                                  /* program's directory */
1657        "/lib/images",                       /* this is for SDK 1.0 */
1658        "/../platforms/android-1.1/images",  /* this is for SDK 1.1 */
1659        NULL
1660    };
1661
1662    app = bufprint_app_dir(temp, end);
1663    if (app >= end)
1664        return NULL;
1665
1666    do {
1667        int  nn;
1668
1669        /* first search a few well-known paths */
1670        for (nn = 0; searchPaths[nn] != NULL; nn++) {
1671            p = bufprint(app, end, "%s", searchPaths[nn]);
1672            q = bufprint(p, end, "/%s", fileName);
1673            if (q < end && path_exists(temp)) {
1674                *p = 0;
1675                goto FOUND_IT;
1676            }
1677        }
1678
1679        /* hmmm. let's assume that we are in a post-1.1 SDK
1680         * scan ../platforms if it exists
1681         */
1682        p = bufprint(app, end, "/../platforms");
1683        if (p < end) {
1684            DirScanner*  scanner = dirScanner_new(temp);
1685            if (scanner != NULL) {
1686                int          found = 0;
1687                const char*  subdir;
1688
1689                for (;;) {
1690                    subdir = dirScanner_next(scanner);
1691                    if (!subdir) break;
1692
1693                    q = bufprint(p, end, "/%s/images/%s", subdir, fileName);
1694                    if (q >= end || !path_exists(temp))
1695                        continue;
1696
1697                    found = 1;
1698                    p = bufprint(p, end, "/%s/images", subdir);
1699                    break;
1700                }
1701                dirScanner_free(scanner);
1702                if (found)
1703                    break;
1704            }
1705        }
1706
1707        /* I'm out of ideas */
1708        return NULL;
1709
1710    } while (0);
1711
1712FOUND_IT:
1713    //D("image auto-detection: %s/%s", temp, fileName);
1714    return qemu_strdup(temp);
1715}
1716
1717static char*
1718_getSdkImage( const char*  path, const char*  file )
1719{
1720    char  temp[MAX_PATH];
1721    char  *p = temp, *end = p + sizeof(temp);
1722
1723    p = bufprint(temp, end, "%s/%s", path, file);
1724    if (p >= end || !path_exists(temp))
1725        return NULL;
1726
1727    return qemu_strdup(temp);
1728}
1729
1730static char*
1731_getSdkSystemImage( const char*  path, const char*  optionName, const char*  file )
1732{
1733    char*  image = _getSdkImage(path, file);
1734
1735    if (image == NULL) {
1736        derror("Your system directory is missing the '%s' image file.\n"
1737               "Please specify one with the '%s <filepath>' option",
1738               file, optionName);
1739        exit(2);
1740    }
1741    return image;
1742}
1743
1744static void
1745_forceAvdImagePath( AvdImageType  imageType,
1746                   const char*   path,
1747                   const char*   description,
1748                   int           required )
1749{
1750    if (path == NULL)
1751        return;
1752
1753    if (required && !path_exists(path)) {
1754        derror("Cannot find %s image file: %s", description, path);
1755        exit(1);
1756    }
1757    android_avdParams->forcePaths[imageType] = path;
1758}
1759
1760static uint64_t
1761_adjustPartitionSize( const char*  description,
1762                      uint64_t     imageBytes,
1763                      uint64_t     defaultBytes,
1764                      int          inAndroidBuild )
1765{
1766    char      temp[64];
1767    unsigned  imageMB;
1768    unsigned  defaultMB;
1769
1770    if (imageBytes <= defaultBytes)
1771        return defaultBytes;
1772
1773    imageMB   = convertBytesToMB(imageBytes);
1774    defaultMB = convertBytesToMB(defaultBytes);
1775
1776    if (imageMB > defaultMB) {
1777        snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
1778    } else {
1779        snprintf(temp, sizeof temp, "(%lld bytes > %lld bytes)", imageBytes, defaultBytes);
1780    }
1781
1782    if (inAndroidBuild) {
1783        dwarning("%s partition size adjusted to match image file %s\n", description, temp);
1784    }
1785
1786    return convertMBToBytes(imageMB);
1787}
1788
1789#ifdef _WIN32
1790#undef main  /* we don't want SDL to define main */
1791#endif
1792
1793int main(int argc, char **argv)
1794{
1795    char   tmp[MAX_PATH];
1796    char*  tmpend = tmp + sizeof(tmp);
1797    char*  args[128];
1798    int    n;
1799    char*  opt;
1800    int    use_sdcard_img = 0;
1801    int    serial = 0;
1802    int    gps_serial = 0;
1803    int    radio_serial = 0;
1804    int    qemud_serial = 0;
1805    int    shell_serial = 0;
1806    int    dns_count = 0;
1807    unsigned  cachePartitionSize = 0;
1808    unsigned  systemPartitionSize = 0;
1809    unsigned  dataPartitionSize = 0;
1810    unsigned  defaultPartitionSize = convertMBToBytes(66);
1811
1812    AndroidHwConfig*  hw;
1813    AvdInfo*          avd;
1814
1815    //const char *appdir = get_app_dir();
1816    char*       android_build_root = NULL;
1817    char*       android_build_out  = NULL;
1818
1819    AndroidOptions  opts[1];
1820
1821    args[0] = argv[0];
1822
1823    if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
1824        exit(1);
1825    }
1826
1827    while (argc-- > 1) {
1828        opt = (++argv)[0];
1829
1830        if(!strcmp(opt, "-qemu")) {
1831            argc--;
1832            argv++;
1833            break;
1834        }
1835
1836        if (!strcmp(opt, "-help")) {
1837            emulator_help();
1838        }
1839
1840        if (!strncmp(opt, "-help-",6)) {
1841            STRALLOC_DEFINE(out);
1842            opt += 6;
1843
1844            if (!strcmp(opt, "all")) {
1845                android_help_all(out);
1846            }
1847            else if (android_help_for_option(opt, out) == 0) {
1848                /* ok */
1849            }
1850            else if (android_help_for_topic(opt, out) == 0) {
1851                /* ok */
1852            }
1853            if (out->n > 0) {
1854                printf("\n%.*s", out->n, out->s);
1855                exit(0);
1856            }
1857
1858            fprintf(stderr, "unknown option: -help-%s\n", opt);
1859            fprintf(stderr, "please use -help for a list of valid topics\n");
1860            exit(1);
1861        }
1862
1863        if (opt[0] == '-') {
1864            fprintf(stderr, "unknown option: %s\n", opt);
1865            fprintf(stderr, "please use -help for a list of valid options\n");
1866            exit(1);
1867        }
1868
1869        fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
1870        fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
1871        fprintf(stderr, "please use -help for more information\n");
1872        exit(1);
1873    }
1874
1875    /* special case, if -qemu -h is used, directly invoke the QEMU-specific help */
1876    if (argc > 0) {
1877        int  nn;
1878        for (nn = 0; nn < argc; nn++)
1879            if (!strcmp(argv[nn], "-h")) {
1880                qemu_help(0);
1881                break;
1882            }
1883    }
1884
1885    if (android_charmap_setup(opts->charmap)) {
1886        exit(1);
1887    }
1888
1889    if (opts->version) {
1890        printf("Android emulator version %s\n"
1891               "Copyright (C) 2006-2008 The Android Open Source Project and many others.\n"
1892               "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
1893#if defined ANDROID_BUILD_ID
1894               VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
1895#else
1896               VERSION_STRING);
1897#endif
1898        printf("  This software is licensed under the terms of the GNU General Public\n"
1899               "  License version 2, as published by the Free Software Foundation, and\n"
1900               "  may be copied, distributed, and modified under those terms.\n\n"
1901               "  This program is distributed in the hope that it will be useful,\n"
1902               "  but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1903               "  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
1904               "  GNU General Public License for more details.\n\n");
1905
1906        exit(0);
1907    }
1908
1909    if (opts->timezone) {
1910        if ( timezone_set(opts->timezone) < 0 ) {
1911            fprintf(stderr, "emulator: it seems the timezone '%s' is not in zoneinfo format\n", opts->timezone);
1912        }
1913    }
1914
1915    /* legacy support: we used to use -system <dir> and -image <file>
1916     * instead of -sysdir <dir> and -system <file>, so handle this by checking
1917     * whether the options point to directories or files.
1918     */
1919    if (opts->image != NULL) {
1920        if (opts->system != NULL) {
1921            if (opts->sysdir != NULL) {
1922                derror( "You can't use -sysdir, -system and -image at the same time.\n"
1923                        "You should probably use '-sysdir <path> -system <file>'.\n" );
1924                exit(2);
1925            }
1926        }
1927        dwarning( "Please note that -image is obsolete and that -system is now used to point\n"
1928                  "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" );
1929        opts->sysdir = opts->system;
1930        opts->system = opts->image;
1931        opts->image  = NULL;
1932    }
1933    else if (opts->system != NULL && path_is_dir(opts->system)) {
1934        if (opts->sysdir != NULL) {
1935            derror( "Option -system should now be followed by a file path, not a directory one.\n"
1936                    "Please use '-sysdir <path>' to point to the system directory.\n" );
1937            exit(1);
1938        }
1939        dwarning( "Please note that the -system option should now be used to point to the initial\n"
1940                  "system image (like the obsolete -image option). To point to the system directory\n"
1941                  "please now use '-sysdir <path>' instead.\n" );
1942
1943        opts->sysdir = opts->system;
1944        opts->system = NULL;
1945    }
1946
1947    if (opts->nojni)
1948        opts->no_jni = opts->nojni;
1949
1950    if (opts->nocache)
1951        opts->no_cache = opts->nocache;
1952
1953    if (opts->noaudio)
1954        opts->no_audio = opts->noaudio;
1955
1956    if (opts->noskin)
1957        opts->no_skin = opts->noskin;
1958
1959    if (opts->initdata) {
1960        opts->init_data = opts->initdata;
1961        opts->initdata  = NULL;
1962    }
1963
1964    /* If no AVD name was given, try to find the top of the
1965     * Android build tree
1966     */
1967    if (opts->avd == NULL) {
1968        do {
1969            char*  out = getenv("ANDROID_PRODUCT_OUT");
1970
1971            if (out == NULL || out[0] == 0)
1972                break;
1973
1974            if (!path_exists(out)) {
1975                derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n"
1976                    "You need to build the Android system before launching the emulator",
1977                    out);
1978                exit(2);
1979            }
1980
1981            android_build_root = path_parent( out, 4 );
1982            if (android_build_root == NULL || !path_exists(android_build_root)) {
1983                derror("Can't find the Android build root from '%s'\n"
1984                    "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n"
1985                    "It should point to your product-specific build output directory.\n",
1986                    out );
1987                exit(2);
1988            }
1989            android_build_out = out;
1990            D( "found Android build root: %s", android_build_root );
1991            D( "found Android build out:  %s", android_build_out );
1992        } while (0);
1993    }
1994    /* if no virtual device name is given, and we're not in the
1995     * Android build system, we'll need to perform some auto-detection
1996     * magic :-)
1997     */
1998    if (opts->avd == NULL && !android_build_out)
1999    {
2000        char   dataDirIsSystem = 0;
2001
2002        if (!opts->sysdir) {
2003            opts->sysdir = _getSdkImagePath("system.img");
2004            if (!opts->sysdir) {
2005                derror(
2006                "You did not specify a virtual device name, and the system\n"
2007                "directory could not be found.\n\n"
2008                "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n"
2009                "to start a given virtual device (see -help-avd for details).\n\n"
2010
2011                "Otherwise, follow the instructions in -help-disk-images to start the emulator\n"
2012                );
2013                exit(2);
2014            }
2015            D("autoconfig: -sysdir %s", opts->sysdir);
2016        }
2017
2018        if (!opts->system) {
2019            opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img");
2020            D("autoconfig: -image %s", opts->image);
2021        }
2022
2023        if (!opts->kernel) {
2024            opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu");
2025            D("autoconfig: -kernel %s", opts->kernel);
2026        }
2027
2028        if (!opts->ramdisk) {
2029            opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img");
2030            D("autoconfig: -ramdisk %s", opts->ramdisk);
2031        }
2032
2033        /* if no data directory is specified, use the system directory */
2034        if (!opts->datadir) {
2035            opts->datadir   = qemu_strdup(opts->sysdir);
2036            dataDirIsSystem = 1;
2037            D("autoconfig: -datadir %s", opts->sysdir);
2038        }
2039
2040        if (!opts->data) {
2041            /* check for userdata-qemu.img in the data directory */
2042            bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir);
2043            if (!path_exists(tmp)) {
2044                derror(
2045                "You did not provide the name of an Android Virtual Device\n"
2046                "with the '-avd <name>' option. Read -help-avd for more information.\n\n"
2047
2048                "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n"
2049                "to specify a data partition image file (I hope you know what you're doing).\n"
2050                );
2051                exit(2);
2052            }
2053
2054            opts->data = qemu_strdup(tmp);
2055            D("autoconfig: -data %s", opts->data);
2056        }
2057
2058        if (!opts->sdcard && opts->datadir) {
2059            bufprint(tmp, tmpend, "%s/sdcard.img", opts->datadir);
2060            if (path_exists(tmp)) {
2061                opts->sdcard = qemu_strdup(tmp);
2062                D("autoconfig: -sdcard %s", opts->sdcard);
2063            }
2064        }
2065    }
2066
2067    /* setup the virtual device parameters from our options
2068     */
2069    if (opts->no_cache) {
2070        android_avdParams->flags |= AVDINFO_NO_CACHE;
2071    }
2072    if (opts->wipe_data) {
2073        android_avdParams->flags |= AVDINFO_WIPE_DATA | AVDINFO_WIPE_CACHE;
2074    }
2075
2076    /* if certain options are set, we can force the path of
2077        * certain kernel/disk image files
2078        */
2079    _forceAvdImagePath(AVD_IMAGE_KERNEL,     opts->kernel, "kernel", 1);
2080    _forceAvdImagePath(AVD_IMAGE_INITSYSTEM, opts->system, "system", 1);
2081    _forceAvdImagePath(AVD_IMAGE_RAMDISK,    opts->ramdisk,"ramdisk", 1);
2082    _forceAvdImagePath(AVD_IMAGE_USERDATA,   opts->data,   "user data", 0);
2083    _forceAvdImagePath(AVD_IMAGE_CACHE,      opts->cache,  "cache", 0);
2084    _forceAvdImagePath(AVD_IMAGE_SDCARD,     opts->sdcard, "SD Card", 0);
2085
2086    /* we don't accept -skindir without -skin now
2087     * to simplify the autoconfig stuff with virtual devices
2088     */
2089    if (opts->no_skin) {
2090        opts->skin    = "320x480";
2091        opts->skindir = NULL;
2092    }
2093
2094    if (opts->skindir) {
2095        if (!opts->skin) {
2096            derror( "the -skindir <path> option requires a -skin <name> option");
2097            exit(1);
2098        }
2099    }
2100    android_avdParams->skinName     = opts->skin;
2101    android_avdParams->skinRootPath = opts->skindir;
2102
2103    /* setup the virtual device differently depending on whether
2104     * we are in the Android build system or not
2105     */
2106    if (opts->avd != NULL)
2107    {
2108        android_avdInfo = avdInfo_new( opts->avd, android_avdParams );
2109        if (android_avdInfo == NULL) {
2110            /* an error message has already been printed */
2111            dprint("could not find virtual device named '%s'", opts->avd);
2112            exit(1);
2113        }
2114    }
2115    else
2116    {
2117        if (!android_build_out) {
2118            android_build_out = android_build_root = opts->sysdir;
2119        }
2120        android_avdInfo = avdInfo_newForAndroidBuild(
2121                            android_build_root,
2122                            android_build_out,
2123                            android_avdParams );
2124
2125        if(android_avdInfo == NULL) {
2126            D("could not start virtual device\n");
2127            exit(1);
2128        }
2129    }
2130
2131    avd = android_avdInfo;
2132
2133    /* get the skin from the virtual device configuration */
2134    opts->skin    = (char*) avdInfo_getSkinName( avd );
2135    opts->skindir = (char*) avdInfo_getSkinDir( avd );
2136
2137    if (opts->skin) {
2138        D("autoconfig: -skin %s", opts->skin);
2139    }
2140    if (opts->skindir) {
2141        D("autoconfig: -skindir %s", opts->skindir);
2142    }
2143
2144    /* Read hardware configuration */
2145    hw = android_hw;
2146    if (avdInfo_getHwConfig(avd, hw) < 0) {
2147        derror("could not read hardware configuration ?");
2148        exit(1);
2149    }
2150
2151#ifdef CONFIG_NAND_LIMITS
2152    if (opts->nand_limits)
2153        parse_nand_limits(opts->nand_limits);
2154#endif
2155
2156    if (opts->keyset) {
2157        parse_keyset(opts->keyset, opts);
2158        if (!android_keyset) {
2159            fprintf(stderr,
2160                    "emulator: WARNING: could not find keyset file named '%s',"
2161                    " using defaults instead\n",
2162                    opts->keyset);
2163        }
2164    }
2165    if (!android_keyset) {
2166        parse_keyset("default", opts);
2167        if (!android_keyset) {
2168            android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
2169            if (!android_keyset) {
2170                fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
2171                fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
2172                exit(1);
2173            }
2174            if (!opts->keyset)
2175                write_default_keyset();
2176        }
2177    }
2178
2179    /* the purpose of -no-audio is to disable sound output from the emulator,
2180     * not to disable Audio emulation. So simply force the 'none' backends */
2181    if (opts->no_audio)
2182        opts->audio = "none";
2183
2184    if (opts->audio) {
2185        if (opts->audio_in || opts->audio_out) {
2186            derror( "you can't use -audio with -audio-in or -audio-out\n" );
2187            exit(1);
2188        }
2189        if ( !audio_check_backend_name( 0, opts->audio ) ) {
2190            derror( "'%s' is not a valid audio output backend. see -help-audio-out\n",
2191                    opts->audio);
2192            exit(1);
2193        }
2194        opts->audio_out = opts->audio;
2195        opts->audio_in  = opts->audio;
2196
2197        if ( !audio_check_backend_name( 1, opts->audio ) ) {
2198            fprintf(stderr,
2199                    "emulator: warning: '%s' is not a valid audio input backend. audio record disabled\n",
2200                    opts->audio);
2201            opts->audio_in = "none";
2202        }
2203    }
2204
2205    if (opts->audio_in) {
2206        static char  env[64]; /* note: putenv needs a static unique string buffer */
2207        if ( !audio_check_backend_name( 1, opts->audio_in ) ) {
2208            derror( "'%s' is not a valid audio input backend. see -help-audio-in\n",
2209                    opts->audio_in);
2210            exit(1);
2211        }
2212        bufprint( env, env+sizeof(env), "QEMU_AUDIO_IN_DRV=%s", opts->audio_in );
2213        putenv( env );
2214
2215        if (!hw->hw_audioInput) {
2216            dwarning( "Emulated hardware doesn't have audio input.");
2217        }
2218    }
2219    if (opts->audio_out) {
2220        static char  env[64]; /* note: putenv needs a static unique string buffer */
2221        if ( !audio_check_backend_name( 0, opts->audio_out ) ) {
2222            derror( "'%s' is not a valid audio output backend. see -help-audio-out\n",
2223                    opts->audio_out);
2224            exit(1);
2225        }
2226        bufprint( env, env+sizeof(env), "QEMU_AUDIO_OUT_DRV=%s", opts->audio_out );
2227        putenv( env );
2228        if (!hw->hw_audioOutput) {
2229            dwarning( "Emulated hardware doesn't have audio output");
2230        }
2231    }
2232
2233    if (opts->cpu_delay) {
2234        char*   end;
2235        long    delay = strtol(opts->cpu_delay, &end, 0);
2236        if (end == NULL || *end || delay < 0 || delay > 1000 ) {
2237            fprintf(stderr, "option -cpu-delay must be an integer between 0 and 1000\n" );
2238            exit(1);
2239        }
2240        if (delay > 0)
2241            delay = (1000-delay);
2242
2243        qemu_cpu_delay = (int) delay;
2244    }
2245
2246    emulator_config_init();
2247    init_skinned_ui(opts->skindir, opts->skin, opts);
2248
2249    if (!opts->netspeed) {
2250        if (skin_network_speed)
2251            D("skin network speed: '%s'", skin_network_speed);
2252        opts->netspeed = (char*)skin_network_speed;
2253    }
2254    if (!opts->netdelay) {
2255        if (skin_network_delay)
2256            D("skin network delay: '%s'", skin_network_delay);
2257        opts->netdelay = (char*)skin_network_delay;
2258    }
2259
2260    if ( android_parse_network_speed(opts->netspeed) < 0 ) {
2261        fprintf(stderr, "invalid -netspeed parameter '%s', see emulator -usage\n", opts->netspeed);
2262        emulator_help();
2263    }
2264
2265    if ( android_parse_network_latency(opts->netdelay) < 0 ) {
2266        fprintf(stderr, "invalid -netdelay parameter '%s', see emulator -usage\n", opts->netdelay);
2267        emulator_help();
2268    }
2269
2270    if (opts->netfast) {
2271        qemu_net_download_speed = 0;
2272        qemu_net_upload_speed = 0;
2273        qemu_net_min_latency = 0;
2274        qemu_net_max_latency = 0;
2275    }
2276
2277    if (opts->trace) {
2278        char*   tracePath = avdInfo_getTracePath(avd, opts->trace);
2279        int     ret;
2280
2281        if (tracePath == NULL) {
2282            derror( "bad -trace parameter" );
2283            exit(1);
2284        }
2285        ret = path_mkdir_if_needed( tracePath, 0755 );
2286        if (ret < 0) {
2287            fprintf(stderr, "could not create directory '%s'\n", tmp);
2288            exit(2);
2289        }
2290        opts->trace = tracePath;
2291    }
2292
2293#ifdef CONFIG_MEMCHECK
2294    if (opts->memcheck) {
2295        memcheck_init(opts->memcheck);
2296    }
2297#endif  // CONFIG_MEMCHECK
2298
2299    if (opts->tcpdump) {
2300        if (qemu_tcpdump_start(opts->tcpdump) < 0) {
2301            dwarning( "could not start packet capture: %s", strerror(errno));
2302        }
2303    }
2304
2305    if (opts->no_cache)
2306        opts->cache = 0;
2307
2308    if (opts->dns_server) {
2309        char*  x = strchr(opts->dns_server, ',');
2310        dns_count = 0;
2311        if (x == NULL)
2312        {
2313            if ( add_dns_server( opts->dns_server ) == 0 )
2314                dns_count = 1;
2315        }
2316        else
2317        {
2318            x = strdup(opts->dns_server);
2319            while (*x) {
2320                char*  y = strchr(x, ',');
2321
2322                if (y != NULL)
2323                    *y = 0;
2324
2325                if (y == NULL || y > x) {
2326                    if ( add_dns_server( x ) == 0 )
2327                        dns_count += 1;
2328                }
2329
2330                if (y == NULL)
2331                    break;
2332
2333                x = y+1;
2334            }
2335        }
2336        if (dns_count == 0)
2337            fprintf( stderr, "### WARNING: will use system default DNS server\n" );
2338    }
2339
2340    if (dns_count == 0)
2341        dns_count = slirp_get_system_dns_servers();
2342
2343    n = 1;
2344    /* generate arguments for the underlying qemu main() */
2345    {
2346        const char*  kernelFile    = avdInfo_getImageFile(avd, AVD_IMAGE_KERNEL);
2347        int          kernelFileLen = strlen(kernelFile);
2348
2349        args[n++] = "-kernel";
2350        args[n++] = (char*)kernelFile;
2351
2352        /* If the kernel image name ends in "-armv7", then change the cpu
2353         * type automatically. This is a poor man's approach to configuration
2354         * management, but should allow us to get past building ARMv7
2355         * system images with dex preopt pass without introducing too many
2356         * changes to the emulator sources.
2357         *
2358         * XXX:
2359         * A 'proper' change would require adding some sort of hardware-property
2360         * to each AVD config file, then automatically determine its value for
2361         * full Android builds (depending on some environment variable), plus
2362         * some build system changes. I prefer not to do that for now for reasons
2363         * of simplicity.
2364         */
2365         if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
2366            args[n++] = "-cpu";
2367            args[n++] = "cortex-a8";
2368         }
2369    }
2370
2371    args[n++] = "-initrd";
2372    args[n++] = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_RAMDISK);
2373
2374    if (opts->partition_size) {
2375        char*  end;
2376        long   sizeMB = strtol(opts->partition_size, &end, 0);
2377        long   minSizeMB = 10;
2378        long   maxSizeMB = LONG_MAX / ONE_MB;
2379
2380        if (sizeMB < 0 || *end != 0) {
2381            derror( "-partition-size must be followed by a positive integer" );
2382            exit(1);
2383        }
2384        if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
2385            derror( "partition-size (%d) must be between %dMB and %dMB",
2386                    sizeMB, minSizeMB, maxSizeMB );
2387            exit(1);
2388        }
2389        defaultPartitionSize = sizeMB * ONE_MB;
2390    }
2391
2392    /* Check the size of the system partition image.
2393     * If we have an AVD, it must be smaller than
2394     * the disk.systemPartition.size hardware property.
2395     *
2396     * Otherwise, we need to adjust the systemPartitionSize
2397     * automatically, and print a warning.
2398     *
2399     */
2400    {
2401        uint64_t   systemBytes  = avdInfo_getImageFileSize(avd, AVD_IMAGE_INITSYSTEM);
2402        uint64_t   defaultBytes = defaultPartitionSize;
2403
2404        if (defaultBytes == 0 || opts->partition_size)
2405            defaultBytes = defaultPartitionSize;
2406
2407        systemPartitionSize = _adjustPartitionSize("system", systemBytes, defaultBytes,
2408                                                   android_build_out != NULL);
2409    }
2410
2411    /* Check the size of the /data partition. The only interesting cases here are:
2412     * - when the USERDATA image already exists and is larger than the default
2413     * - when we're wiping data and the INITDATA is larger than the default.
2414     */
2415
2416    {
2417        const char*  dataPath     = avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA);
2418        uint64_t     defaultBytes = defaultPartitionSize;
2419
2420        if (defaultBytes == 0 || opts->partition_size)
2421            defaultBytes = defaultPartitionSize;
2422
2423        if (dataPath == NULL || !path_exists(dataPath) || opts->wipe_data) {
2424            dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_INITDATA);
2425        }
2426        if (dataPath == NULL || !path_exists(dataPath)) {
2427            dataPartitionSize = defaultBytes;
2428        }
2429        else {
2430            uint64_t  dataBytes;
2431            path_get_size(dataPath, &dataBytes);
2432
2433            dataPartitionSize = _adjustPartitionSize("data", dataBytes, defaultBytes,
2434                                                     android_build_out != NULL);
2435        }
2436    }
2437
2438    {
2439        const char*  filetype = "file";
2440
2441        if (avdInfo_isImageReadOnly(avd, AVD_IMAGE_INITSYSTEM))
2442            filetype = "initfile";
2443
2444        bufprint(tmp, tmpend,
2445             "system,size=0x%x,%s=%s", systemPartitionSize, filetype,
2446             avdInfo_getImageFile(avd, AVD_IMAGE_INITSYSTEM));
2447
2448        args[n++] = "-nand";
2449        args[n++] = strdup(tmp);
2450    }
2451
2452    bufprint(tmp, tmpend,
2453             "userdata,size=0x%x,file=%s",
2454             dataPartitionSize,
2455             avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA));
2456
2457    args[n++] = "-nand";
2458    args[n++] = strdup(tmp);
2459
2460    if (hw->disk_cachePartition) {
2461        opts->cache = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_CACHE);
2462        cachePartitionSize = hw->disk_cachePartition_size;
2463    }
2464    else if (opts->cache) {
2465        dwarning( "Emulated hardware doesn't support a cache partition" );
2466        opts->cache    = NULL;
2467        opts->no_cache = 1;
2468    }
2469
2470    if (opts->cache) {
2471        /* use a specific cache file */
2472        sprintf(tmp, "cache,size=0x%0x,file=%s", cachePartitionSize, opts->cache);
2473        args[n++] = "-nand";
2474        args[n++] = strdup(tmp);
2475    }
2476    else if (!opts->no_cache) {
2477        /* create a temporary cache partition file */
2478        sprintf(tmp, "cache,size=0x%0x", cachePartitionSize);
2479        args[n++] = "-nand";
2480        args[n++] = strdup(tmp);
2481    }
2482
2483    if (hw->hw_sdCard != 0)
2484        opts->sdcard = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SDCARD);
2485    else if (opts->sdcard) {
2486        dwarning( "Emulated hardware doesn't support SD Cards" );
2487        opts->sdcard = NULL;
2488    }
2489
2490    if(opts->sdcard) {
2491        uint64_t  size;
2492        if (path_get_size(opts->sdcard, &size) == 0) {
2493            /* see if we have an sdcard image.  get its size if it exists */
2494            /* due to what looks like limitations of the MMC protocol, one has
2495             * to use an SD Card image that is equal or larger than 9 MB
2496             */
2497            if (size < 9*1024*1024ULL) {
2498                fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard);
2499            } else {
2500                args[n++] = "-hda";
2501                args[n++] = opts->sdcard;
2502                use_sdcard_img = 1;
2503            }
2504        } else {
2505            D("no SD Card image at '%s'", opts->sdcard);
2506        }
2507    }
2508
2509    if (!opts->logcat || opts->logcat[0] == 0) {
2510        opts->logcat = getenv("ANDROID_LOG_TAGS");
2511        if (opts->logcat && opts->logcat[0] == 0)
2512            opts->logcat = NULL;
2513    }
2514
2515#if 0
2516    if (opts->console) {
2517        derror( "option -console is obsolete. please use -shell instead" );
2518        exit(1);
2519    }
2520#endif
2521
2522    /* we always send the kernel messages from ttyS0 to android_kmsg */
2523    {
2524        AndroidKmsgFlags  flags = 0;
2525
2526        if (opts->show_kernel)
2527            flags |= ANDROID_KMSG_PRINT_MESSAGES;
2528
2529        android_kmsg_init( flags );
2530        args[n++] = "-serial";
2531        args[n++] = "android-kmsg";
2532        serial++;
2533    }
2534
2535    /* XXXX: TODO: implement -shell and -logcat through qemud instead */
2536    if (!opts->shell_serial) {
2537#ifdef _WIN32
2538        opts->shell_serial = "con:";
2539#else
2540        opts->shell_serial = "stdio";
2541#endif
2542    }
2543    else
2544        opts->shell = 1;
2545
2546    if (opts->shell || opts->logcat) {
2547        args[n++] = "-serial";
2548        args[n++] = opts->shell_serial;
2549        shell_serial = serial++;
2550    }
2551
2552    if (opts->old_system)
2553    {
2554        if (opts->radio) {
2555            args[n++] = "-serial";
2556            args[n++] = opts->radio;
2557            radio_serial = serial++;
2558        }
2559        else {
2560            args[n++] = "-serial";
2561            args[n++] = "android-modem";
2562            radio_serial = serial++;
2563        }
2564        if (opts->gps) {
2565            args[n++] = "-serial";
2566            args[n++] = opts->gps;
2567            gps_serial = serial++;
2568        }
2569    }
2570    else /* !opts->old_system */
2571    {
2572        args[n++] = "-serial";
2573        args[n++] = "android-qemud";
2574        qemud_serial = serial++;
2575
2576        if (opts->radio) {
2577            CharDriverState*  cs = qemu_chr_open("radio",opts->radio,NULL);
2578            if (cs == NULL) {
2579                derror( "unsupported character device specification: %s\n"
2580                        "used -help-char-devices for list of available formats\n", opts->radio );
2581                exit(1);
2582            }
2583            android_qemud_set_channel( ANDROID_QEMUD_GSM, cs);
2584        }
2585        else if ( hw->hw_gsmModem != 0 ) {
2586            if ( android_qemud_get_channel( ANDROID_QEMUD_GSM, &android_modem_cs ) < 0 ) {
2587                derror( "could not initialize qemud 'gsm' channel" );
2588                exit(1);
2589            }
2590        }
2591
2592        if (opts->gps) {
2593            CharDriverState*  cs = qemu_chr_open("gps",opts->gps,NULL);
2594            if (cs == NULL) {
2595                derror( "unsupported character device specification: %s\n"
2596                        "used -help-char-devices for list of available formats\n", opts->gps );
2597                exit(1);
2598            }
2599            android_qemud_set_channel( ANDROID_QEMUD_GPS, cs);
2600        }
2601        else if ( hw->hw_gps != 0 ) {
2602            if ( android_qemud_get_channel( "gps", &android_gps_cs ) < 0 ) {
2603                derror( "could not initialize qemud 'gps' channel" );
2604                exit(1);
2605            }
2606        }
2607    }
2608
2609    if (opts->memory) {
2610        char*  end;
2611        long   ramSize = strtol(opts->memory, &end, 0);
2612        if (ramSize < 0 || *end != 0) {
2613            derror( "-memory must be followed by a positive integer" );
2614            exit(1);
2615        }
2616        if (ramSize < 32 || ramSize > 4096) {
2617            derror( "physical memory size must be between 32 and 4096 MB" );
2618            exit(1);
2619        }
2620    }
2621    if (!opts->memory) {
2622        bufprint(tmp, tmpend, "%d", hw->hw_ramSize);
2623        opts->memory = qemu_strdup(tmp);
2624    }
2625
2626    if (opts->trace) {
2627        args[n++] = "-trace";
2628        args[n++] = opts->trace;
2629        args[n++] = "-tracing";
2630        args[n++] = "off";
2631    }
2632
2633    args[n++] = "-append";
2634
2635    if (opts->bootchart) {
2636        char*  end;
2637        int    timeout = strtol(opts->bootchart, &end, 10);
2638        if (timeout == 0)
2639            opts->bootchart = NULL;
2640        else if (timeout < 0 || timeout > 15*60) {
2641            derror( "timeout specified for -bootchart option is invalid.\n"
2642                    "please use integers between 1 and 900\n");
2643            exit(1);
2644        }
2645    }
2646
2647    /* start the 'boot-properties service, and parse the -prop
2648     * options, if any.
2649     */
2650    boot_property_init_service();
2651
2652    hwLcd_setBootProperty(get_device_dpi(opts));
2653
2654    /* Set the VM's max heap size, passed as a boot property */
2655    if (hw->vm_heapSize > 0) {
2656        char  tmp[32], *p=tmp, *end=p + sizeof(tmp);
2657        p = bufprint(p, end, "%dm", hw->vm_heapSize);
2658
2659        boot_property_add("dalvik.vm.heapsize",tmp);
2660    }
2661
2662    if (opts->prop != NULL) {
2663        ParamList*  pl = opts->prop;
2664        for ( ; pl != NULL; pl = pl->next ) {
2665            boot_property_parse_option(pl->param);
2666        }
2667    }
2668
2669    /* Setup the kernel init options
2670     */
2671    {
2672        static char  params[1024];
2673        char        *p = params, *end = p + sizeof(params);
2674
2675        p = bufprint(p, end, "qemu=1 console=ttyS0" );
2676
2677        if (opts->shell || opts->logcat) {
2678            p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial );
2679        }
2680
2681        if (opts->trace) {
2682            p = bufprint(p, end, " android.tracing=1");
2683        }
2684
2685#ifdef CONFIG_MEMCHECK
2686        if (opts->memcheck) {
2687            /* This will set ro.kernel.memcheck system property
2688             * to memcheck's tracing flags. */
2689            p = bufprint(p, end, " memcheck=%s", opts->memcheck);
2690        }
2691#endif  // CONFIG_MEMCHECK
2692
2693        if (!opts->no_jni) {
2694            p = bufprint(p, end, " android.checkjni=1");
2695        }
2696
2697        if (opts->no_boot_anim) {
2698            p = bufprint( p, end, " android.bootanim=0" );
2699        }
2700
2701        if (opts->logcat) {
2702            char*  q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
2703
2704            if (q < end) {
2705                /* replace any space by a comma ! */
2706                {
2707                    int  nn;
2708                    for (nn = 1; p[nn] != 0; nn++)
2709                        if (p[nn] == ' ' || p[nn] == '\t')
2710                            p[nn] = ',';
2711                    p += nn;
2712                }
2713            }
2714            p = q;
2715        }
2716
2717        if (opts->old_system)
2718        {
2719            p = bufprint(p, end, " android.ril=ttyS%d", radio_serial);
2720
2721            if (opts->gps) {
2722                p = bufprint(p, end, " android.gps=ttyS%d", gps_serial);
2723            }
2724        }
2725        else
2726        {
2727            p = bufprint(p, end, " android.qemud=ttyS%d", qemud_serial);
2728        }
2729
2730        if (dns_count > 0) {
2731            p = bufprint(p, end, " android.ndns=%d", dns_count);
2732        }
2733
2734        if (opts->bootchart) {
2735            p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
2736        }
2737
2738        if (p >= end) {
2739            fprintf(stderr, "### ERROR: kernel parameters too long\n");
2740            exit(1);
2741        }
2742
2743        args[n++] = strdup(params);
2744    }
2745
2746    /* physical memory */
2747    args[n++] = "-m";
2748    args[n++] = opts->memory;
2749
2750    /* on Linux, the 'dynticks' clock sometimes doesn't work
2751     * properly. this results in the UI freezing while emulation
2752     * continues, for several seconds...
2753     */
2754#ifdef __linux__
2755    args[n++] = "-clock";
2756    args[n++] = "unix";
2757#endif
2758
2759    while(argc-- > 0) {
2760        args[n++] = *argv++;
2761    }
2762    args[n] = 0;
2763
2764    if(VERBOSE_CHECK(init)) {
2765        int i;
2766        for(i = 0; i < n; i++) {
2767            fprintf(stdout, "emulator: argv[%02d] = \"%s\"\n", i, args[i]);
2768        }
2769    }
2770    return qemu_main(n, args);
2771}
2772
2773/* this function is called from qemu_main() once all arguments have been parsed
2774 * it should be used to setup any Android-specific items in the emulation before the
2775 * main loop runs
2776 */
2777void  android_emulation_setup( void )
2778{
2779    int   tries     = 16;
2780    int   base_port = 5554;
2781    int   success   = 0;
2782    int   s;
2783    uint32_t  guest_ip;
2784
2785    AndroidOptions*  opts = qemulator->opts;
2786
2787    inet_strtoip("10.0.2.15", &guest_ip);
2788
2789#if 0
2790    if (opts->adb_port) {
2791        fprintf( stderr, "option -adb-port is obsolete, use -port instead\n" );
2792        exit(1);
2793    }
2794#endif
2795
2796    if (opts->port && opts->ports) {
2797        fprintf( stderr, "options -port and -ports cannot be used together.\n");
2798        exit(1);
2799    }
2800
2801    if (opts->ports) {
2802        char* comma_location;
2803        char* end;
2804        int console_port = strtol( opts->ports, &comma_location, 0 );
2805
2806        if ( comma_location == NULL || *comma_location != ',' ) {
2807            derror( "option -ports must be followed by two comma separated positive integer numbers" );
2808            exit(1);
2809        }
2810
2811        int adb_port = strtol( comma_location+1, &end, 0 );
2812
2813        if ( end == NULL || *end ) {
2814            derror( "option -ports must be followed by two comma separated positive integer numbers" );
2815            exit(1);
2816        }
2817
2818        if ( console_port == adb_port ) {
2819            derror( "option -ports must be followed by two different integer numbers" );
2820            exit(1);
2821        }
2822
2823        slirp_redir( 0, adb_port, guest_ip, 5555 );
2824        if ( control_console_start( console_port ) < 0 ) {
2825            slirp_unredir( 0, adb_port );
2826        }
2827
2828        base_port = console_port;
2829    } else {
2830        if (opts->port) {
2831            char*  end;
2832            int    port = strtol( opts->port, &end, 0 );
2833            if ( end == NULL || *end ||
2834                (unsigned)((port - base_port) >> 1) >= (unsigned)tries ) {
2835                derror( "option -port must be followed by an even integer number between %d and %d\n",
2836                        base_port, base_port + (tries-1)*2 );
2837                exit(1);
2838            }
2839            if ( (port & 1) != 0 ) {
2840                port &= ~1;
2841                dwarning( "option -port must be followed by an even integer, using  port number %d\n",
2842                          port );
2843            }
2844            base_port = port;
2845            tries     = 1;
2846        }
2847
2848        for ( ; tries > 0; tries--, base_port += 2 ) {
2849
2850            /* setup first redirection for ADB, the Android Debug Bridge */
2851            if ( slirp_redir( 0, base_port+1, guest_ip, 5555 ) < 0 )
2852                continue;
2853
2854            /* setup second redirection for the emulator console */
2855            if ( control_console_start( base_port ) < 0 ) {
2856                slirp_unredir( 0, base_port+1 );
2857                continue;
2858            }
2859
2860            D( "control console listening on port %d, ADB on port %d", base_port, base_port+1 );
2861            success = 1;
2862            break;
2863        }
2864
2865        if (!success) {
2866            fprintf(stderr, "it seems too many emulator instances are running on this machine. Aborting\n" );
2867            exit(1);
2868        }
2869    }
2870
2871    if (opts->report_console) {
2872        report_console(opts->report_console, base_port);
2873    }
2874
2875    android_modem_init( base_port );
2876
2877    android_base_port = base_port;
2878   /* send a simple message to the ADB host server to tell it we just started.
2879    * it should be listening on port 5037. if we can't reach it, don't bother
2880    */
2881    do
2882    {
2883        SockAddress  addr;
2884        char         tmp[32];
2885
2886        s = socket_create_inet( SOCKET_STREAM );
2887        if (s < 0) {
2888            D("can't create socket to talk to the ADB server");
2889            break;
2890        }
2891
2892        sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, 5037 );
2893        if (socket_connect( s, &addr ) < 0) {
2894            D("can't connect to ADB server: %s", errno_str );
2895            break;
2896        }
2897
2898        sprintf(tmp,"0012host:emulator:%d",base_port+1);
2899        socket_send(s, tmp, 18+4);
2900        D("sent '%s' to ADB server", tmp);
2901    }
2902    while (0);
2903
2904    if (s >= 0)
2905        socket_close(s);
2906
2907    /* setup the http proxy, if any */
2908    if (VERBOSE_CHECK(proxy))
2909        proxy_set_verbose(1);
2910
2911    if (!opts->http_proxy) {
2912        opts->http_proxy = getenv("http_proxy");
2913    }
2914
2915    do
2916    {
2917        const char*  env = opts->http_proxy;
2918        int          envlen;
2919        ProxyOption  option_tab[4];
2920        ProxyOption* option = option_tab;
2921        char*        p;
2922        char*        q;
2923        const char*  proxy_name;
2924        int          proxy_name_len;
2925        int          proxy_port;
2926
2927        if (!env)
2928            break;
2929
2930        envlen = strlen(env);
2931
2932        /* skip the 'http://' header, if present */
2933        if (envlen >= 7 && !memcmp(env, "http://", 7)) {
2934            env    += 7;
2935            envlen -= 7;
2936        }
2937
2938        /* do we have a username:password pair ? */
2939        p = strchr(env, '@');
2940        if (p != 0) {
2941            q = strchr(env, ':');
2942            if (q == NULL) {
2943            BadHttpProxyFormat:
2944                dprint("http_proxy format unsupported, try 'proxy:port' or 'username:password@proxy:port'");
2945                break;
2946            }
2947
2948            option->type       = PROXY_OPTION_AUTH_USERNAME;
2949            option->string     = env;
2950            option->string_len = q - env;
2951            option++;
2952
2953            option->type       = PROXY_OPTION_AUTH_PASSWORD;
2954            option->string     = q+1;
2955            option->string_len = p - (q+1);
2956            option++;
2957
2958            env = p+1;
2959        }
2960
2961        p = strchr(env,':');
2962        if (p == NULL)
2963            goto BadHttpProxyFormat;
2964
2965        proxy_name     = env;
2966        proxy_name_len = p - env;
2967        proxy_port     = atoi(p+1);
2968
2969        D( "setting up http proxy:  server=%.*s port=%d",
2970                proxy_name_len, proxy_name, proxy_port );
2971
2972        if ( proxy_http_setup( proxy_name, proxy_name_len, proxy_port,
2973                               option - option_tab, option_tab ) < 0 )
2974        {
2975            dprint( "http proxy setup failed, check your $http_proxy variable");
2976        }
2977    }
2978    while (0);
2979
2980    /* initialize sensors, this must be done here due to timer issues */
2981    android_hw_sensors_init();
2982
2983   /* cool, now try to run the "ddms ping" command, which will take care of pinging usage
2984    * if the user agreed for it. the emulator itself never sends anything to any outside
2985    * machine
2986    */
2987    {
2988#ifdef _WIN32
2989#  define  _ANDROID_PING_PROGRAM   "ddms.bat"
2990#else
2991#  define  _ANDROID_PING_PROGRAM   "ddms"
2992#endif
2993
2994        char         tmp[PATH_MAX];
2995        const char*  appdir = get_app_dir();
2996
2997        if (snprintf( tmp, PATH_MAX, "%s%s%s", appdir, PATH_SEP,
2998                      _ANDROID_PING_PROGRAM ) >= PATH_MAX) {
2999            dprint( "Application directory too long: %s", appdir);
3000            return;
3001        }
3002
3003        /* if the program isn't there, don't bother */
3004        D( "ping program: %s", tmp);
3005        if (path_exists(tmp)) {
3006#ifdef _WIN32
3007            STARTUPINFO           startup;
3008            PROCESS_INFORMATION   pinfo;
3009
3010            ZeroMemory( &startup, sizeof(startup) );
3011            startup.cb = sizeof(startup);
3012            startup.dwFlags = STARTF_USESHOWWINDOW;
3013            startup.wShowWindow = SW_SHOWMINIMIZED;
3014
3015            ZeroMemory( &pinfo, sizeof(pinfo) );
3016
3017            char* comspec = getenv("COMSPEC");
3018            if (!comspec) comspec = "cmd.exe";
3019
3020            // Run
3021            char args[PATH_MAX + 30];
3022            if (snprintf( args, PATH_MAX, "/C \"%s\" ping emulator " VERSION_STRING,
3023                          tmp) >= PATH_MAX ) {
3024                D( "DDMS path too long: %s", tmp);
3025                return;
3026            }
3027
3028            CreateProcess(
3029                comspec,                                      /* program path */
3030                args,                                    /* command line args */
3031                NULL,                    /* process handle is not inheritable */
3032                NULL,                     /* thread handle is not inheritable */
3033                FALSE,                       /* no, don't inherit any handles */
3034                DETACHED_PROCESS,   /* the new process doesn't have a console */
3035                NULL,                       /* use parent's environment block */
3036                NULL,                      /* use parent's starting directory */
3037                &startup,                   /* startup info, i.e. std handles */
3038                &pinfo );
3039
3040            D( "ping command: %s %s", comspec, args );
3041#else
3042            int  pid;
3043
3044            /* disable SIGALRM for the fork(), the periodic signal seems to
3045             * interefere badly with the fork() implementation on Linux running
3046             * under VMWare.
3047             */
3048            BEGIN_NOSIGALRM
3049                pid = fork();
3050                if (pid == 0) {
3051                    int  fd = open("/dev/null", O_WRONLY);
3052                    dup2(fd, 1);
3053                    dup2(fd, 2);
3054                    execl( tmp, _ANDROID_PING_PROGRAM, "ping", "emulator", VERSION_STRING, NULL );
3055                }
3056            END_NOSIGALRM
3057
3058            /* don't do anything in the parent or in case of error */
3059            strncat( tmp, " ping emulator " VERSION_STRING, PATH_MAX - strlen(tmp) );
3060            D( "ping command: %s", tmp );
3061#endif
3062        }
3063    }
3064}
3065
3066
3067void  android_emulation_teardown( void )
3068{
3069    android_charmap_done();
3070}
3071