Home | History | Annotate | Download | only in android
      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 */
     74 extern void  qemu_help(int  code);
     75 
     76 #include "framebuffer.h"
     77 AndroidRotation  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"
     89 SkinKeyset*      android_keyset;
     90 
     91 #define  D(...)  do {  if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
     92 
     93 extern int  control_console_start( int  port );  /* in control.c */
     94 
     95 extern 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 
    101 int    android_base_port;
    102 
    103 #if 0
    104 static int  opts->flashkeys;      /* forward */
    105 #endif
    106 
    107 static void  handle_key_command( void*  opaque, SkinKeyCommand  command, int  param );
    108 
    109 #ifdef CONFIG_TRACE
    110 extern void  start_tracing(void);
    111 extern void  stop_tracing(void);
    112 #endif
    113 
    114 unsigned long   android_verbose;
    115 
    116 int   qemu_cpu_delay = 0;
    117 int   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 
    131 const 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 
    146 static AUserConfig*  userConfig;
    147 
    148 void
    149 emulator_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 */
    155 void
    156 emulator_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 
    170 void *loadpng(const char *fn, unsigned *_width, unsigned *_height);
    171 void *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 
    179 static void
    180 sdl_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 */
    242 const 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 
    253 const 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 
    267 unsigned 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 
    279 uint64_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 
    292 void 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 
    304 typedef 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 
    322 static QEmulator   qemulator[1];
    323 
    324 static void
    325 qemulator_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 
    347 static void
    348 qemulator_setup( QEmulator*  emulator );
    349 
    350 static void
    351 qemulator_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 
    359 static void
    360 qemulator_fb_rotate( void*  _emulator, int  rotation )
    361 {
    362     QEmulator*     emulator = _emulator;
    363 
    364     qemulator_setup( emulator );
    365 }
    366 
    367 
    368 
    369 static int
    370 qemulator_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 
    411 static AndroidKeyCode
    412 qemulator_rotate_keycode( QEmulator*      emulator,
    413                           AndroidKeyCode  sym )
    414 {
    415     return android_keycode_rotate( sym,
    416                                    skin_layout_get_dpad_rotation(emulator->layout) );
    417 }
    418 
    419 static int
    420 get_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 
    435 static double
    436 get_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 
    497 void
    498 android_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 
    510 static void
    511 qemulator_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  */
    554 static void
    555 sdl_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 
    569 static void
    570 qemulator_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 
    584 static void
    585 qemulator_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 */
    641 static void
    642 sdl_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 */
    650 static 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  */
    746 static void
    747 handle_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 
    907 static void sdl_at_exit(void)
    908 {
    909     emulator_config_done();
    910     qemulator_done( qemulator );
    911     SDL_Quit();
    912 }
    913 
    914 
    915 void 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 
    949 extern SkinKeyboard*  android_emulator_get_keyboard(void)
    950 {
    951     return qemulator->keyboard;
    952 }
    953 
    954 static const char*  skin_network_speed = NULL;
    955 static const char*  skin_network_delay = NULL;
    956 
    957 /* list of skin aliases */
    958 static 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 */
    972 const char*    android_skin_keycharmap = NULL;
    973 
    974 void 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 
   1107 found_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 
   1171 int qemu_main(int argc, char **argv);
   1172 
   1173 /* this function dumps the QEMU help */
   1174 extern void  help( void );
   1175 extern void  emulator_help( void );
   1176 
   1177 #define  VERBOSE_OPT(str,var)   { str, &var }
   1178 
   1179 #define  _VERBOSE_TAG(x,y)   { #x, VERBOSE_##x, y },
   1180 static const struct { const char*  name; int  flag; const char*  text; }
   1181 verbose_options[] = {
   1182     VERBOSE_TAG_LIST
   1183     { 0, 0, 0 }
   1184 };
   1185 
   1186 int
   1187 android_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 
   1227 int
   1228 android_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 
   1263 static int
   1264 load_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 
   1279 static void
   1280 parse_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 
   1320 static void
   1321 write_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 
   1347 static uint64_t
   1348 parse_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 
   1370 static void
   1371 parse_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 
   1452 void 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 
   1461 static int
   1462 add_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 
   1484 enum {
   1485     REPORT_CONSOLE_SERVER = (1 << 0),
   1486     REPORT_CONSOLE_MAX    = (1 << 1)
   1487 };
   1488 
   1489 static int
   1490 get_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 
   1525 static void
   1526 report_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  */
   1646 static 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 
   1712 FOUND_IT:
   1713     //D("image auto-detection: %s/%s", temp, fileName);
   1714     return qemu_strdup(temp);
   1715 }
   1716 
   1717 static 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 
   1730 static 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 
   1744 static 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 
   1760 static 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 
   1793 int 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  */
   2777 void  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 
   3067 void  android_emulation_teardown( void )
   3068 {
   3069     android_charmap_done();
   3070 }
   3071