diff options
Diffstat (limited to 'android/main.c')
-rw-r--r-- | android/main.c | 2889 |
1 files changed, 0 insertions, 2889 deletions
diff --git a/android/main.c b/android/main.c deleted file mode 100644 index e1d983c..0000000 --- a/android/main.c +++ /dev/null @@ -1,2889 +0,0 @@ -/* Copyright (C) 2006-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -*/ - -#include <signal.h> -#include <unistd.h> -#include <string.h> -#include <sys/time.h> -#ifdef _WIN32 -#include <process.h> -#endif -#include "libslirp.h" -#include "sockets.h" - -#include "android/android.h" -#include "qemu-common.h" -#include "sysemu.h" -#include "console.h" - -#include <SDL.h> -#include <SDL_syswm.h> - -#include "math.h" - -#include "android/charmap.h" -#include "modem_driver.h" -#include "shaper.h" -#include "proxy_http.h" - -#include "android/utils/debug.h" -#include "android/resource.h" -#include "android/config.h" -#include "android/config/config.h" - -#include "android/skin/image.h" -#include "android/skin/trackball.h" -#include "android/skin/keyboard.h" -#include "android/skin/file.h" -#include "android/skin/window.h" -#include "android/skin/keyset.h" - -#include "android/gps.h" -#include "android/qemud.h" -#include "android/hw-kmsg.h" -#include "android/hw-control.h" -#include "android/utils/bufprint.h" -#include "android/utils/dirscanner.h" -#include "android/utils/path.h" -#include "android/utils/timezone.h" -#include "android/utils/display.h" - -#include "android/cmdline-option.h" -#include "android/help.h" -#include "hw/goldfish_nand.h" - -#include "android/globals.h" -#include "tcpdump.h" - -#include "framebuffer.h" -AndroidRotation android_framebuffer_rotation; - -#define STRINGIFY(x) _STRINGIFY(x) -#define _STRINGIFY(x) #x - -#define VERSION_STRING STRINGIFY(ANDROID_VERSION_MAJOR)"."STRINGIFY(ANDROID_VERSION_MINOR) - -#define KEYSET_FILE "default.keyset" -SkinKeyset* android_keyset; - -#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0) - -extern int control_console_start( int port ); /* in control.c */ - -extern int qemu_milli_needed; - -/* the default device DPI if none is specified by the skin - */ -#define DEFAULT_DEVICE_DPI 165 - -static const AKeyCharmap* android_charmap; - -int android_base_port; - -#if 0 -static int opts->flashkeys; /* forward */ -#endif - -static void handle_key_command( void* opaque, SkinKeyCommand command, int param ); - -#ifdef CONFIG_TRACE -extern void start_tracing(void); -extern void stop_tracing(void); -#endif - -unsigned long android_verbose; - -int qemu_cpu_delay = 0; -int qemu_cpu_delay_count; - -/***********************************************************************/ -/***********************************************************************/ -/***** *****/ -/***** U T I L I T Y R O U T I N E S *****/ -/***** *****/ -/***********************************************************************/ -/***********************************************************************/ - -/*** APPLICATION DIRECTORY - *** Where are we ? - ***/ - -const char* get_app_dir(void) -{ - char buffer[1024]; - char* p = buffer; - char* end = p + sizeof(buffer); - p = bufprint_app_dir(p, end); - if (p >= end) - return NULL; - - return strdup(buffer); -} - -/*** CONFIGURATION - ***/ - -static AConfig* emulator_config; -static int emulator_config_found; -static char emulator_configpath[256]; - -void -emulator_config_init( void ) -{ - char* end = emulator_configpath + sizeof(emulator_configpath); - char* p; - void* config; - - emulator_config = aconfig_node("",""); - - p = bufprint_config_file(emulator_configpath, end, "emulator.cfg"); - if (p >= end) { - dwarning( "emulator configuration path too long" ); - emulator_configpath[0] = 0; - return; - } - - config = path_load_file( emulator_configpath, NULL ); - if (config == NULL) - D( "cannot load emulator configuration at '%s'\n", - emulator_configpath ); - else { - aconfig_load( emulator_config, config ); - emulator_config_found = 1; - } -} - -/* only call this function on normal exits, so that ^C doesn't save the configuration */ -void -emulator_config_done( void ) -{ - int save = 0; /* only save config if we see changes */ - AConfig* guid_node; - char guid_value[32]; - AConfig* window_node; - int prev_x, prev_y, win_x, win_y; - - if (!emulator_configpath[0]) { - D("no config path ?"); - return; - } - - /* compare window positions */ - { - SDL_WM_GetPos( &win_x, &win_y ); - prev_x = win_x - 1; - prev_y = win_y - 1; - - window_node = aconfig_find( emulator_config, "window" ); - if (window_node == NULL) { - aconfig_set( emulator_config, "window", "" ); - window_node = aconfig_find( emulator_config, "window" ); - save = 1; - } - - prev_x = (int)aconfig_unsigned( window_node, "x", 0 ); - prev_y = (int)aconfig_unsigned( window_node, "y", 0 ); - - save = (prev_x != win_x) || (prev_y != win_y); - - /* Beware: If the new window position is definitely off-screen, - * we don't want to save it in the configuration file. This can - * happen for example on Linux where certain window managers - * will 'minimize' a window by moving it to coordinates like - * (-5000,-5000) - */ - if ( !SDL_WM_IsFullyVisible(0) ) { - D( "not saving new emulator window position since it is not fully visible" ); - save = 0; - } - else if (save) - D( "emulator window position changed and will be saved as (%d, %d)", win_x, win_y ); - } - - /* If there is no guid node, create one with the current time in - * milliseconds. Thus, the value doesn't correspond to any system or - * user-specific data - */ -#define GUID_NAME "unique-id" - - guid_node = aconfig_find( emulator_config, GUID_NAME ); - if (!guid_node) { - struct timeval tm; - gettimeofday( &tm, NULL ); - sprintf( guid_value, "%lld", (long long)tm.tv_sec*1000 + tm.tv_usec/1000 ); - save = 1; - aconfig_set( emulator_config, GUID_NAME, guid_value ); - } - - if (save) { - char xbuf[16], ybuf[16]; - - sprintf( xbuf, "%d", win_x ); - sprintf( ybuf, "%d", win_y ); - - aconfig_set( window_node, "x", xbuf ); - aconfig_set( window_node, "y", ybuf ); - - /* do we need to create the $HOME/.android directory ? */ - if ( !path_exists(emulator_configpath) ) { - char* dir = path_parent(emulator_configpath, 1); - if (dir == NULL) { - D("invalid user-specific config directory: '%s'", emulator_configpath); - return; - } - if ( path_mkdir_if_needed(dir, 0755) < 0 ) { - D("cannot create directory '%s', configuration lost", dir); - free(dir); - return; - } - free(dir); - } - if ( aconfig_save_file( emulator_config, emulator_configpath ) < 0 ) { - D( "cannot save configuration to %s", emulator_configpath); - } else - D( "configuration saved to %s", emulator_configpath ); - } -} - -void *loadpng(const char *fn, unsigned *_width, unsigned *_height); -void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height); - -#ifdef CONFIG_DARWIN -# define ANDROID_ICON_PNG "android_icon_256.png" -#else -# define ANDROID_ICON_PNG "android_icon_16.png" -#endif - -static void -sdl_set_window_icon( void ) -{ - static int window_icon_set; - - if (!window_icon_set) - { -#ifdef _WIN32 - HANDLE handle = GetModuleHandle( NULL ); - HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) ); - SDL_SysWMinfo wminfo; - - SDL_GetWMInfo(&wminfo); - - SetClassLong( wminfo.window, GCL_HICON, (LONG)icon ); -#else /* !_WIN32 */ - unsigned icon_w, icon_h; - size_t icon_bytes; - const unsigned char* icon_data; - void* icon_pixels; - - window_icon_set = 1; - - icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes ); - if ( !icon_data ) - return; - - icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h ); - if ( !icon_pixels ) - return; - - /* the data is loaded into memory as RGBA bytes by libpng. we want to manage - * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending - * on our CPU endianess - */ - { - unsigned* d = icon_pixels; - unsigned* d_end = d + icon_w*icon_h; - - for ( ; d < d_end; d++ ) { - unsigned pix = d[0]; -#if WORDS_BIGENDIAN - /* R,G,B,A read as RGBA => ARGB */ - pix = ((pix >> 8) & 0xffffff) | (pix << 24); -#else - /* R,G,B,A read as ABGR => ARGB */ - pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16); -#endif - d[0] = pix; - } - } - - SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h ); - if (icon != NULL) { - SDL_WM_SetIcon(icon, NULL); - SDL_FreeSurface(icon); - free( icon_pixels ); - } -#endif /* !_WIN32 */ - } -} - - -/***********************************************************************/ -/***********************************************************************/ -/***** *****/ -/***** S K I N I M A G E S *****/ -/***** *****/ -/***********************************************************************/ -/***********************************************************************/ - -void send_key_event(unsigned code, unsigned down) -{ - if(code == 0) { - return; - } - if (VERBOSE_CHECK(keys)) - printf(">> KEY [0x%03x,%s]\n", (code & 0x1ff), down ? "down" : " up " ); - kbd_put_keycode((code & 0x1ff) | (down ? 0x200 : 0)); -} - - - -typedef struct { - AConfig* aconfig; - SkinFile* layout_file; - SkinLayout* layout; - SkinKeyboard* keyboard; - SkinWindow* window; - int win_x; - int win_y; - int show_trackball; - SkinTrackBall* trackball; - int lcd_brightness; - SkinImage* onion; - SkinRotation onion_rotation; - int onion_alpha; - - AndroidOptions opts[1]; /* copy of options */ -} QEmulator; - -static QEmulator qemulator[1]; - -static void -qemulator_done( QEmulator* emulator ) -{ - if (emulator->window) { - skin_window_free(emulator->window); - emulator->window = NULL; - } - if (emulator->trackball) { - skin_trackball_destroy(emulator->trackball); - emulator->trackball = NULL; - } - if (emulator->keyboard) { - skin_keyboard_free(emulator->keyboard); - emulator->keyboard = NULL; - } - emulator->layout = NULL; - if (emulator->layout_file) { - skin_file_free(emulator->layout_file); - emulator->layout_file = NULL; - } -} - - -static void -qemulator_setup( QEmulator* emulator ); - -static void -qemulator_fb_update( void* _emulator, int x, int y, int w, int h ) -{ - QEmulator* emulator = _emulator; - - if (emulator->window) - skin_window_update_display( emulator->window, x, y, w, h ); -} - -static void -qemulator_fb_rotate( void* _emulator, int rotation ) -{ - QEmulator* emulator = _emulator; - - qemulator_setup( emulator ); -} - - - -static int -qemulator_init( QEmulator* emulator, - AConfig* aconfig, - const char* basepath, - int x, - int y, - AndroidOptions* opts ) -{ - emulator->aconfig = aconfig; - emulator->layout_file = skin_file_create_from_aconfig(aconfig, basepath); - emulator->layout = emulator->layout_file->layouts; - emulator->keyboard = skin_keyboard_create_from_aconfig(aconfig, opts->raw_keys); - emulator->window = NULL; - emulator->win_x = x; - emulator->win_y = y; - emulator->opts[0] = opts[0]; - - /* register as a framebuffer clients for all displays defined in the skin file */ - SKIN_FILE_LOOP_PARTS( emulator->layout_file, part ) - SkinDisplay* disp = part->display; - if (disp->valid) { - qframebuffer_add_client( disp->qfbuff, - emulator, - qemulator_fb_update, - qemulator_fb_rotate, - NULL ); - } - SKIN_FILE_LOOP_END_PARTS - return 0; -} - - -static AndroidKeyCode -qemulator_rotate_keycode( QEmulator* emulator, - AndroidKeyCode sym ) -{ - switch (skin_layout_get_dpad_rotation(emulator->layout)) { - case SKIN_ROTATION_90: - switch (sym) { - case kKeyCodeDpadLeft: sym = kKeyCodeDpadDown; break; - case kKeyCodeDpadRight: sym = kKeyCodeDpadUp; break; - case kKeyCodeDpadUp: sym = kKeyCodeDpadLeft; break; - case kKeyCodeDpadDown: sym = kKeyCodeDpadRight; break; - default: ; - } - break; - - case SKIN_ROTATION_180: - switch (sym) { - case kKeyCodeDpadLeft: sym = kKeyCodeDpadRight; break; - case kKeyCodeDpadRight: sym = kKeyCodeDpadLeft; break; - case kKeyCodeDpadUp: sym = kKeyCodeDpadDown; break; - case kKeyCodeDpadDown: sym = kKeyCodeDpadUp; break; - default: ; - } - break; - - case SKIN_ROTATION_270: - switch (sym) { - case kKeyCodeDpadLeft: sym = kKeyCodeDpadUp; break; - case kKeyCodeDpadRight: sym = kKeyCodeDpadDown; break; - case kKeyCodeDpadUp: sym = kKeyCodeDpadRight; break; - case kKeyCodeDpadDown: sym = kKeyCodeDpadLeft; break; - default: ; - } - break; - - default: ; - } - return sym; -} - -static int -get_device_dpi( AndroidOptions* opts ) -{ - int dpi_device = DEFAULT_DEVICE_DPI; - - if (opts->dpi_device != NULL) { - char* end; - dpi_device = strtol( opts->dpi_device, &end, 0 ); - if (end == NULL || *end != 0 || dpi_device <= 0) { - fprintf(stderr, "argument for -dpi-device must be a positive integer. Aborting\n" ); - exit(1); - } - } - return dpi_device; -} - -static double -get_default_scale( AndroidOptions* opts ) -{ - int dpi_device = get_device_dpi( opts ); - int dpi_monitor = -1; - double scale = 0.0; - - /* possible values for the 'scale' option are - * 'auto' : try to determine the scale automatically - * '<number>dpi' : indicates the host monitor dpi, compute scale accordingly - * '<fraction>' : use direct scale coefficient - */ - - if (opts->scale) { - if (!strcmp(opts->scale, "auto")) - { - /* we need to get the host dpi resolution ? */ - int xdpi, ydpi; - - if ( get_monitor_resolution( &xdpi, &ydpi ) < 0 ) { - fprintf(stderr, "could not get monitor DPI resolution from system. please use -dpi-monitor to specify one\n" ); - exit(1); - } - D( "system reported monitor resolutions: xdpi=%d ydpi=%d\n", xdpi, ydpi); - dpi_monitor = (xdpi + ydpi+1)/2; - } - else - { - char* end; - scale = strtod( opts->scale, &end ); - - if (end && end[0] == 'd' && end[1] == 'p' && end[2] == 'i' && end[3] == 0) { - if ( scale < 20 || scale > 1000 ) { - fprintf(stderr, "emulator: ignoring bad -scale argument '%s': %s\n", opts->scale, - "host dpi number must be between 20 and 1000" ); - exit(1); - } - dpi_monitor = scale; - scale = 0.0; - } - else if (end == NULL || *end != 0) { - fprintf(stderr, "emulator: ignoring bad -scale argument '%s': %s\n", opts->scale, - "not a number or the 'auto' keyword" ); - exit(1); - } - else if ( scale < 0.1 || scale > 3. ) { - fprintf(stderr, "emulator: ignoring bad -window-scale argument '%s': %s\n", opts->scale, - "must be between 0.1 and 3.0" ); - exit(1); - } - } - } - - if (scale == 0.0 && dpi_monitor > 0) - scale = dpi_monitor*1.0/dpi_device; - - if (scale == 0.0) - scale = 1.0; - - return scale; -} - -void -android_emulator_set_window_scale( double scale, int is_dpi ) -{ - QEmulator* emulator = qemulator; - - if (is_dpi) - scale /= get_device_dpi( emulator->opts ); - - if (emulator->window) - skin_window_set_scale( emulator->window, scale ); -} - - -static void -qemulator_set_title( QEmulator* emulator ) -{ - char temp[64]; - - if (emulator->window == NULL) - return; - - snprintf( temp, sizeof(temp), "Android Emulator (%s:%d)", - avdInfo_getName( android_avdInfo ), - android_base_port ); - - skin_window_set_title( emulator->window, temp ); -} - -/* called by the emulated framebuffer device each time the content of the - * framebuffer has changed. the rectangle is the bounding box of all changes - */ -static void -sdl_update(DisplayState *ds, int x, int y, int w, int h) -{ - /* this function is being called from the console code that is currently inactive - ** simple totally ignore it... - */ - (void)ds; - (void)x; - (void)y; - (void)w; - (void)h; -} - - - -static void -qemulator_light_brightness( void* opaque, const char* light, int value ) -{ - QEmulator* emulator = opaque; - - VERBOSE_PRINT(hw_control,"%s: light='%s' value=%d window=%p", __FUNCTION__, light, value, emulator->window); - if ( !strcmp(light, "lcd_backlight") ) { - emulator->lcd_brightness = value; - if (emulator->window) - skin_window_set_lcd_brightness( emulator->window, value ); - return; - } -} - - -static void -qemulator_setup( QEmulator* emulator ) -{ - AndroidOptions* opts = emulator->opts; - - if ( !emulator->window && !opts->no_window ) { - SkinLayout* layout = emulator->layout; - double scale = get_default_scale(emulator->opts); - - emulator->window = skin_window_create( layout, emulator->win_x, emulator->win_y, scale, 0); - if (emulator->window == NULL) - return; - - { - SkinTrackBall* ball; - SkinTrackBallParameters params; - - params.diameter = 30; - params.ring = 2; - params.ball_color = 0xffe0e0e0; - params.dot_color = 0xff202020; - params.ring_color = 0xff000000; - - ball = skin_trackball_create( ¶ms ); - emulator->trackball = ball; - skin_window_set_trackball( emulator->window, ball ); - - emulator->lcd_brightness = 128; /* 50% */ - skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness ); - } - - if ( emulator->onion != NULL ) - skin_window_set_onion( emulator->window, - emulator->onion, - emulator->onion_rotation, - emulator->onion_alpha ); - - qemulator_set_title( emulator ); - - skin_window_enable_touch ( emulator->window, android_hw->hw_touchScreen != 0 ); - skin_window_enable_dpad ( emulator->window, android_hw->hw_dPad != 0 ); - skin_window_enable_qwerty( emulator->window, android_hw->hw_keyboard != 0 ); - skin_window_enable_trackball( emulator->window, android_hw->hw_trackBall != 0 ); - } - - /* initialize hardware control support */ - { - AndroidHwControlFuncs funcs; - - funcs.light_brightness = qemulator_light_brightness; - android_hw_control_init( emulator, &funcs ); - } -} - - -/* called by the emulated framebuffer device each time the framebuffer - * is resized or rotated */ -static void -sdl_resize(DisplayState *ds, int w, int h) -{ - fprintf(stderr, "weird, sdl_resize being called with framebuffer interface\n"); - exit(1); -} - - -static void sdl_refresh(DisplayState *ds) -{ - QEmulator* emulator = ds->opaque; - SDL_Event ev; - SkinWindow* window = emulator->window; - SkinKeyboard* keyboard = emulator->keyboard; - - /* this will eventually call sdl_update if the content of the VGA framebuffer - * has changed */ - qframebuffer_check_updates(); - - if (window == NULL) - return; - - while(SDL_PollEvent(&ev)){ - switch(ev.type){ - case SDL_VIDEOEXPOSE: - skin_window_redraw( window, NULL ); - break; - - case SDL_KEYDOWN: -#ifdef _WIN32 - /* special code to deal with Alt-F4 properly */ - if (ev.key.keysym.sym == SDLK_F4 && - ev.key.keysym.mod & KMOD_ALT) { - goto CleanExit; - } -#endif -#ifdef __APPLE__ - /* special code to deal with Command-Q properly */ - if (ev.key.keysym.sym == SDLK_q && - ev.key.keysym.mod & KMOD_META) { - goto CleanExit; - } -#endif - skin_keyboard_process_event( keyboard, &ev, 1 ); - break; - - case SDL_KEYUP: - skin_keyboard_process_event( keyboard, &ev, 0 ); - break; - - case SDL_MOUSEMOTION: - skin_window_process_event( window, &ev ); - break; - - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - { - int down = (ev.type == SDL_MOUSEBUTTONDOWN); - if (ev.button.button == 4) - { - /* scroll-wheel simulates DPad up */ - AndroidKeyCode kcode; - - kcode = qemulator_rotate_keycode(emulator, kKeyCodeDpadUp); - send_key_event( kcode, down ); - } - else if (ev.button.button == 5) - { - /* scroll-wheel simulates DPad down */ - AndroidKeyCode kcode; - - kcode = qemulator_rotate_keycode(emulator, kKeyCodeDpadDown); - send_key_event( kcode, down ); - } - else if (ev.button.button == SDL_BUTTON_LEFT) { - skin_window_process_event( window, &ev ); - } -#if 0 - else { - fprintf(stderr, "... mouse button %s: button=%d state=%04x x=%d y=%d\n", - down ? "down" : "up ", - ev.button.button, ev.button.state, ev.button.x, ev.button.y); - } -#endif - } - break; - - case SDL_QUIT: -#if defined _WIN32 || defined __APPLE__ - CleanExit: -#endif - /* only save emulator config through clean exit */ - qemulator_done( emulator ); - qemu_system_shutdown_request(); - return; - } - } - - skin_keyboard_flush( keyboard ); -} - - -/* used to respond to a given keyboard command shortcut - */ -static void -handle_key_command( void* opaque, SkinKeyCommand command, int down ) -{ - static const struct { SkinKeyCommand cmd; AndroidKeyCode kcode; } keycodes[] = - { - { SKIN_KEY_COMMAND_BUTTON_CALL, kKeyCodeCall }, - { SKIN_KEY_COMMAND_BUTTON_HOME, kKeyCodeHome }, - { SKIN_KEY_COMMAND_BUTTON_BACK, kKeyCodeBack }, - { SKIN_KEY_COMMAND_BUTTON_HANGUP, kKeyCodeEndCall }, - { SKIN_KEY_COMMAND_BUTTON_POWER, kKeyCodePower }, - { SKIN_KEY_COMMAND_BUTTON_SEARCH, kKeyCodeSearch }, - { SKIN_KEY_COMMAND_BUTTON_MENU, kKeyCodeMenu }, - { SKIN_KEY_COMMAND_BUTTON_DPAD_UP, kKeyCodeDpadUp }, - { SKIN_KEY_COMMAND_BUTTON_DPAD_LEFT, kKeyCodeDpadLeft }, - { SKIN_KEY_COMMAND_BUTTON_DPAD_RIGHT, kKeyCodeDpadRight }, - { SKIN_KEY_COMMAND_BUTTON_DPAD_DOWN, kKeyCodeDpadDown }, - { SKIN_KEY_COMMAND_BUTTON_DPAD_CENTER, kKeyCodeDpadCenter }, - { SKIN_KEY_COMMAND_BUTTON_VOLUME_UP, kKeyCodeVolumeUp }, - { SKIN_KEY_COMMAND_BUTTON_VOLUME_DOWN, kKeyCodeVolumeDown }, - { SKIN_KEY_COMMAND_NONE, 0 } - }; - int nn; -#ifdef CONFIG_TRACE - static int tracing = 0; -#endif - QEmulator* emulator = opaque; - - - for (nn = 0; keycodes[nn].kcode != 0; nn++) { - if (command == keycodes[nn].cmd) { - unsigned code = keycodes[nn].kcode; - if (down) - code |= 0x200; - kbd_put_keycode( code ); - return; - } - } - - // for the show-trackball command, handle down events to enable, and - // up events to disable - if (command == SKIN_KEY_COMMAND_SHOW_TRACKBALL) { - emulator->show_trackball = (down != 0); - skin_window_show_trackball( emulator->window, emulator->show_trackball ); - //qemulator_set_title( emulator ); - return; - } - - // only handle down events for the rest - if (down == 0) - return; - - switch (command) - { - case SKIN_KEY_COMMAND_TOGGLE_NETWORK: - { - qemu_net_disable = !qemu_net_disable; - if (android_modem) { - amodem_set_data_registration( - android_modem, - qemu_net_disable ? A_REGISTRATION_UNREGISTERED - : A_REGISTRATION_HOME); - } - D( "network is now %s", qemu_net_disable ? "disconnected" : "connected" ); - } - break; - - case SKIN_KEY_COMMAND_TOGGLE_FULLSCREEN: - if (emulator->window) { - skin_window_toggle_fullscreen(emulator->window); - } - break; - - case SKIN_KEY_COMMAND_TOGGLE_TRACING: - { -#ifdef CONFIG_TRACE - tracing = !tracing; - if (tracing) - start_tracing(); - else - stop_tracing(); -#endif - } - break; - - case SKIN_KEY_COMMAND_TOGGLE_TRACKBALL: - emulator->show_trackball = !emulator->show_trackball; - skin_window_show_trackball( emulator->window, emulator->show_trackball ); - break; - - case SKIN_KEY_COMMAND_ONION_ALPHA_UP: - case SKIN_KEY_COMMAND_ONION_ALPHA_DOWN: - if (emulator->onion) - { - int alpha = emulator->onion_alpha; - - if (command == SKIN_KEY_COMMAND_ONION_ALPHA_UP) - alpha += 16; - else - alpha -= 16; - - if (alpha > 256) - alpha = 256; - else if (alpha < 0) - alpha = 0; - - emulator->onion_alpha = alpha; - skin_window_set_onion( emulator->window, emulator->onion, emulator->onion_rotation, alpha ); - skin_window_redraw( emulator->window, NULL ); - //dprint( "onion alpha set to %d (%.f %%)", alpha, alpha/2.56 ); - } - break; - - case SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV: - case SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT: - { - SkinLayout* layout = NULL; - - if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT) { - layout = emulator->layout->next; - if (layout == NULL) - layout = emulator->layout_file->layouts; - } - else if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV) { - layout = emulator->layout_file->layouts; - while (layout->next && layout->next != emulator->layout) - layout = layout->next; - } - if (layout != NULL) { - SkinRotation rotation; - - emulator->layout = layout; - skin_window_reset( emulator->window, layout ); - - rotation = skin_layout_get_dpad_rotation( layout ); - - if (emulator->keyboard) - skin_keyboard_set_rotation( emulator->keyboard, rotation ); - - if (emulator->trackball) { - skin_trackball_set_rotation( emulator->trackball, rotation ); - skin_window_set_trackball( emulator->window, emulator->trackball ); - skin_window_show_trackball( emulator->window, emulator->show_trackball ); - } - - skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness ); - - qframebuffer_invalidate_all(); - qframebuffer_check_updates(); - } - } - break; - - default: - /* XXX: TODO ? */ - ; - } -} - - -static void sdl_at_exit(void) -{ - emulator_config_done(); - qemulator_done( qemulator ); - SDL_Quit(); -} - - -void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) -{ - QEmulator* emulator = qemulator; - SkinDisplay* disp = skin_layout_get_display(emulator->layout); - -// fprintf(stderr,"*** sdl_display_init ***\n"); - ds->opaque = emulator; - - if (disp->rotation & 1) { - ds->width = disp->rect.size.h; - ds->height = disp->rect.size.w; - } else { - ds->width = disp->rect.size.w; - ds->height = disp->rect.size.h; - } - - ds->dpy_update = sdl_update; - ds->dpy_resize = sdl_resize; - ds->dpy_refresh = sdl_refresh; - - skin_keyboard_enable( emulator->keyboard, 1 ); - skin_keyboard_on_command( emulator->keyboard, handle_key_command, emulator ); -} - - -extern SkinKeyboard* android_emulator_get_keyboard(void) -{ - return qemulator->keyboard; -} - -static const char* skin_network_speed = NULL; -static const char* skin_network_delay = NULL; - -/* list of skin aliases */ -static const struct { - const char* name; - const char* alias; -} skin_aliases[] = { - { "QVGA-L", "320x240" }, - { "QVGA-P", "240x320" }, - { "HVGA-L", "480x320" }, - { "HVGA-P", "320x480" }, - { "QVGA", "320x240" }, - { "HVGA", "320x480" }, - { NULL, NULL } -}; - -/* this is used by hw/events_device.c to send the charmap name to the system */ -const char* android_skin_keycharmap = NULL; - -void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts) -{ - char tmp[1024]; - AConfig* root; - AConfig* n; - int win_x, win_y, flags; - - signal(SIGINT, SIG_DFL); -#ifndef _WIN32 - signal(SIGQUIT, SIG_DFL); -#endif - - /* we're not a game, so allow the screensaver to run */ - putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1"); - - flags = SDL_INIT_NOPARACHUTE; - if (!opts->no_window) - flags |= SDL_INIT_VIDEO; - - if(SDL_Init(flags)){ - fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() ); - exit(1); - } - - if (!opts->no_window) { - SDL_EnableUNICODE(!opts->raw_keys); - SDL_EnableKeyRepeat(0,0); - - sdl_set_window_icon(); - } - else - { -#ifndef _WIN32 - /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be - * able to run the emulator in the background (e.g. "emulator &"). - * despite the fact that the emulator should not grab input or try to - * write to the output in normal cases, we're stopped on some systems - * (e.g. OS X) - */ - signal(SIGTTIN, SIG_IGN); - signal(SIGTTOU, SIG_IGN); -#endif - } - atexit(sdl_at_exit); - - root = aconfig_node("", ""); - - if(name) { - /* Support skin aliases like QVGA-H QVGA-P, etc... - But first we check if it's a directory that exist before applying - the alias */ - int checkAlias = 1; - - if (path != NULL) { - bufprint(tmp, tmp+sizeof(tmp), "%s/%s", path, name); - if (path_exists(tmp)) { - checkAlias = 0; - } else { - D("there is no '%s' skin in '%s'", name, path); - } - } - - if (checkAlias) { - int nn; - - for (nn = 0; ; nn++ ) { - const char* skin_name = skin_aliases[nn].name; - const char* skin_alias = skin_aliases[nn].alias; - - if ( !skin_name ) - break; - - if ( !strcasecmp( skin_name, name ) ) { - D("skin name '%s' aliased to '%s'", name, skin_alias); - name = skin_alias; - break; - } - } - } - - /* Magically support skins like "320x240" */ - if(isdigit(name[0])) { - char *x = strchr(name, 'x'); - if(x && isdigit(x[1])) { - int width = atoi(name); - int height = atoi(x + 1); - sprintf(tmp,"display {\n width %d\n height %d\n}\n", - width, height); - aconfig_load(root, strdup(tmp)); - path = ":"; - goto found_a_skin; - } - } - - if (path == NULL) { - derror("unknown skin name '%s'", name); - exit(1); - } - - sprintf(tmp, "%s/%s/layout", path, name); - D("trying to load skin file '%s'", tmp); - - if(aconfig_load_file(root, tmp) >= 0) { - sprintf(tmp, "%s/%s/", path, name); - path = tmp; - goto found_a_skin; - } else { - dwarning("could not load skin file '%s', using built-in one\n", - tmp); - } - } - - { - const unsigned char* layout_base; - size_t layout_size; - - name = "<builtin>"; - - layout_base = android_resource_find( "layout", &layout_size ); - if (layout_base != NULL) { - char* base = malloc( layout_size+1 ); - memcpy( base, layout_base, layout_size ); - base[layout_size] = 0; - - D("parsing built-in skin layout file (size=%d)", (int)layout_size); - aconfig_load(root, base); - path = ":"; - } else { - fprintf(stderr, "Couldn't load builtin skin\n"); - exit(1); - } - } - -found_a_skin: - { - AConfig* node = aconfig_find( emulator_config, "window" ); - - win_x = 10; - win_y = 10; - - if (node == NULL) { - if (emulator_config_found) - dwarning( "broken configuration file doesn't have 'window' element" ); - } else { - win_x = aconfig_int( node, "x", win_x ); - win_y = aconfig_int( node, "y", win_y ); - } - } - if ( qemulator_init( qemulator, root, path, win_x, win_y, opts ) < 0 ) { - fprintf(stderr, "### Error: could not load emulator skin '%s'\n", name); - exit(1); - } - - android_skin_keycharmap = skin_keyboard_charmap_name(qemulator->keyboard); - - /* the default network speed and latency can now be specified by the device skin */ - n = aconfig_find(root, "network"); - if (n != NULL) { - skin_network_speed = aconfig_str(n, "speed", 0); - skin_network_delay = aconfig_str(n, "delay", 0); - } - -#if 0 - /* create a trackball if needed */ - n = aconfig_find(root, "trackball"); - if (n != NULL) { - SkinTrackBallParameters params; - - params.x = aconfig_unsigned(n, "x", 0); - params.y = aconfig_unsigned(n, "y", 0); - params.diameter = aconfig_unsigned(n, "diameter", 20); - params.ring = aconfig_unsigned(n, "ring", 1); - - params.ball_color = aconfig_unsigned(n, "ball-color", 0xffe0e0e0); - params.dot_color = aconfig_unsigned(n, "dot-color", 0xff202020 ); - params.ring_color = aconfig_unsigned(n, "ring-color", 0xff000000 ); - - qemu_disp->trackball = skin_trackball_create( ¶ms ); - skin_trackball_refresh( qemu_disp->trackball ); - } -#endif - - /* add an onion overlay image if needed */ - if (opts->onion) { - SkinImage* onion = skin_image_find_simple( opts->onion ); - int alpha, rotate; - - if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) { - alpha = (256*alpha)/100; - } else - alpha = 128; - - if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) { - rotate &= 3; - } else - rotate = SKIN_ROTATION_0; - - qemulator->onion = onion; - qemulator->onion_alpha = alpha; - qemulator->onion_rotation = rotate; - } -} - -int qemu_main(int argc, char **argv); - -/* this function dumps the QEMU help */ -extern void help( void ); -extern void emulator_help( void ); - -#define VERBOSE_OPT(str,var) { str, &var } - -#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y }, -static const struct { const char* name; int flag; const char* text; } -verbose_options[] = { - VERBOSE_TAG_LIST - { 0, 0, 0 } -}; - -int -android_parse_network_speed(const char* speed) -{ - int n; - char* end; - double sp; - - if (speed == NULL || speed[0] == 0) { - speed = DEFAULT_NETSPEED; - } - - for (n = 0; android_netspeeds[n].name != NULL; n++) { - if (!strcmp(android_netspeeds[n].name, speed)) { - qemu_net_download_speed = android_netspeeds[n].download; - qemu_net_upload_speed = android_netspeeds[n].upload; - return 0; - } - } - - /* is this a number ? */ - sp = strtod(speed, &end); - if (end == speed) { - return -1; - } - - qemu_net_download_speed = qemu_net_upload_speed = sp*1000.; - if (*end == ':') { - speed = end+1; - sp = strtod(speed, &end); - if (end > speed) { - qemu_net_download_speed = sp*1000.; - } - } - - if (android_modem) - amodem_set_data_network_type( android_modem, - android_parse_network_type(speed) ); - return 0; -} - - -int -android_parse_network_latency(const char* delay) -{ - int n; - char* end; - double sp; - - if (delay == NULL || delay[0] == 0) - delay = DEFAULT_NETDELAY; - - for (n = 0; android_netdelays[n].name != NULL; n++) { - if ( !strcmp( android_netdelays[n].name, delay ) ) { - qemu_net_min_latency = android_netdelays[n].min_ms; - qemu_net_max_latency = android_netdelays[n].max_ms; - return 0; - } - } - - /* is this a number ? */ - sp = strtod(delay, &end); - if (end == delay) { - return -1; - } - - qemu_net_min_latency = qemu_net_max_latency = (int)sp; - if (*end == ':') { - delay = (const char*)end+1; - sp = strtod(delay, &end); - if (end > delay) { - qemu_net_max_latency = (int)sp; - } - } - return 0; -} - - -static int -load_keyset(const char* path) -{ - if (path_can_read(path)) { - AConfig* root = aconfig_node("",""); - if (!aconfig_load_file(root, path)) { - android_keyset = skin_keyset_new(root); - if (android_keyset != NULL) { - D( "keyset loaded from: %s", path); - return 0; - } - } - } - return -1; -} - -static void -parse_keyset(const char* keyset, AndroidOptions* opts) -{ - char kname[MAX_PATH]; - char temp[MAX_PATH]; - char* p; - char* end; - - /* append .keyset suffix if needed */ - if (strchr(keyset, '.') == NULL) { - p = kname; - end = p + sizeof(kname); - p = bufprint(p, end, "%s.keyset", keyset); - if (p >= end) { - derror( "keyset name too long: '%s'\n", keyset); - exit(1); - } - keyset = kname; - } - - /* look for a the keyset file */ - p = temp; - end = p + sizeof(temp); - p = bufprint_config_file(p, end, keyset); - if (p < end && load_keyset(temp) == 0) - return; - - p = temp; - p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->system, keyset); - if (p < end && load_keyset(temp) == 0) - return; - - p = temp; - p = bufprint_app_dir(p, end); - p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset); - if (p < end && load_keyset(temp) == 0) - return; - - return; -} - -static void -write_default_keyset( void ) -{ - char path[MAX_PATH]; - - bufprint_config_file( path, path+sizeof(path), KEYSET_FILE ); - - /* only write if there is no file here */ - if ( !path_exists(path) ) { - int fd = open( path, O_WRONLY | O_CREAT, 0666 ); - int ret; - const char* ks = skin_keyset_get_default(); - - - D( "writing default keyset file to %s", path ); - - if (fd < 0) { - D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) ); - return; - } - CHECKED(ret, write(fd, ks, strlen(ks))); - close(fd); - } -} - -#ifdef CONFIG_NAND_LIMITS - -static uint64_t -parse_nand_rw_limit( const char* value ) -{ - char* end; - uint64_t val = strtoul( value, &end, 0 ); - - if (end == value) { - derror( "bad parameter value '%s': expecting unsigned integer", value ); - exit(1); - } - - switch (end[0]) { - case 'K': val <<= 10; break; - case 'M': val <<= 20; break; - case 'G': val <<= 30; break; - case 0: break; - default: - derror( "bad read/write limit suffix: use K, M or G" ); - exit(1); - } - return val; -} - -static void -parse_nand_limits(char* limits) -{ - int pid = -1, signal = -1; - int64_t reads = 0, writes = 0; - char* item = limits; - - /* parse over comma-separated items */ - while (item && *item) { - char* next = strchr(item, ','); - char* end; - - if (next == NULL) { - next = item + strlen(item); - } else { - *next++ = 0; - } - - if ( !memcmp(item, "pid=", 4) ) { - pid = strtol(item+4, &end, 10); - if (end == NULL || *end) { - derror( "bad parameter, expecting pid=<number>, got '%s'", - item ); - exit(1); - } - if (pid <= 0) { - derror( "bad parameter: process identifier must be > 0" ); - exit(1); - } - } - else if ( !memcmp(item, "signal=", 7) ) { - signal = strtol(item+7,&end, 10); - if (end == NULL || *end) { - derror( "bad parameter: expecting signal=<number>, got '%s'", - item ); - exit(1); - } - if (signal <= 0) { - derror( "bad parameter: signal number must be > 0" ); - exit(1); - } - } - else if ( !memcmp(item, "reads=", 6) ) { - reads = parse_nand_rw_limit(item+6); - } - else if ( !memcmp(item, "writes=", 7) ) { - writes = parse_nand_rw_limit(item+7); - } - else { - derror( "bad parameter '%s' (see -help-nand-limits)", item ); - exit(1); - } - item = next; - } - if (pid < 0) { - derror( "bad paramater: missing pid=<number>" ); - exit(1); - } - else if (signal < 0) { - derror( "bad parameter: missing signal=<number>" ); - exit(1); - } - else if (reads == 0 && writes == 0) { - dwarning( "no read or write limit specified. ignoring -nand-limits" ); - } else { - nand_threshold* t; - - t = &android_nand_read_threshold; - t->pid = pid; - t->signal = signal; - t->counter = 0; - t->limit = reads; - - t = &android_nand_write_threshold; - t->pid = pid; - t->signal = signal; - t->counter = 0; - t->limit = writes; - } -} -#endif /* CONFIG_NAND_LIMITS */ - -void emulator_help( void ) -{ - STRALLOC_DEFINE(out); - android_help_main(out); - printf( "%.*s", out->n, out->s ); - stralloc_reset(out); - exit(1); -} - -static int -add_dns_server( const char* server_name ) -{ - SockAddress addr; - - if (sock_address_init_resolve( &addr, server_name, 55, 0 ) < 0) { - fprintf(stderr, - "### WARNING: can't resolve DNS server name '%s'\n", - server_name ); - return -1; - } - - D( "DNS server name '%s' resolved to %s", server_name, sock_address_to_string(&addr) ); - - if ( slirp_add_dns_server( &addr ) < 0 ) { - fprintf(stderr, - "### WARNING: could not add DNS server '%s' to the network stack\n", server_name); - return -1; - } - return 0; -} - - -enum { - REPORT_CONSOLE_SERVER = (1 << 0), - REPORT_CONSOLE_MAX = (1 << 1) -}; - -static int -get_report_console_options( char* end, int *maxtries ) -{ - int flags = 0; - - if (end == NULL || *end == 0) - return 0; - - if (end[0] != ',') { - derror( "socket port/path can be followed by [,<option>]+ only\n"); - exit(3); - } - end += 1; - while (*end) { - char* p = strchr(end, ','); - if (p == NULL) - p = end + strlen(end); - - if (memcmp( end, "server", p-end ) == 0) - flags |= REPORT_CONSOLE_SERVER; - else if (memcmp( end, "max=", 4) == 0) { - end += 4; - *maxtries = strtol( end, NULL, 10 ); - flags |= REPORT_CONSOLE_MAX; - } else { - derror( "socket port/path can be followed by [,server][,max=<count>] only\n"); - exit(3); - } - - end = p; - if (*end) - end += 1; - } - return flags; -} - -static void -report_console( const char* proto_port, int console_port ) -{ - int s = -1, s2; - int maxtries = 10; - int flags = 0; - signal_state_t sigstate; - - disable_sigalrm( &sigstate ); - - if ( !strncmp( proto_port, "tcp:", 4) ) { - char* end; - long port = strtol(proto_port + 4, &end, 10); - - flags = get_report_console_options( end, &maxtries ); - - if (flags & REPORT_CONSOLE_SERVER) { - s = socket_loopback_server( port, SOCKET_STREAM ); - if (s < 0) { - fprintf(stderr, "could not create server socket on TCP:%ld: %s\n", - port, errno_str); - exit(3); - } - } else { - for ( ; maxtries > 0; maxtries-- ) { - D("trying to find console-report client on tcp:%d", port); - s = socket_loopback_client( port, SOCKET_STREAM ); - if (s >= 0) - break; - - sleep_ms(1000); - } - if (s < 0) { - fprintf(stderr, "could not connect to server on TCP:%ld: %s\n", - port, errno_str); - exit(3); - } - } - } else if ( !strncmp( proto_port, "unix:", 5) ) { -#ifdef _WIN32 - fprintf(stderr, "sorry, the unix: protocol is not supported on Win32\n"); - exit(3); -#else - char* path = strdup(proto_port+5); - char* end = strchr(path, ','); - if (end != NULL) { - flags = get_report_console_options( end, &maxtries ); - *end = 0; - } - if (flags & REPORT_CONSOLE_SERVER) { - s = socket_unix_server( path, SOCKET_STREAM ); - if (s < 0) { - fprintf(stderr, "could not bind unix socket on '%s': %s\n", - proto_port+5, errno_str); - exit(3); - } - } else { - for ( ; maxtries > 0; maxtries-- ) { - s = socket_unix_client( path, SOCKET_STREAM ); - if (s >= 0) - break; - - sleep_ms(1000); - } - if (s < 0) { - fprintf(stderr, "could not connect to unix socket on '%s': %s\n", - path, errno_str); - exit(3); - } - } - free(path); -#endif - } else { - fprintf(stderr, "-report-console must be followed by a 'tcp:<port>' or 'unix:<path>'\n"); - exit(3); - } - - if (flags & REPORT_CONSOLE_SERVER) { - int tries = 3; - D( "waiting for console-reporting client" ); - do { - s2 = socket_accept(s, NULL); - } while (s2 < 0 && --tries > 0); - - if (s2 < 0) { - fprintf(stderr, "could not accept console-reporting client connection: %s\n", - errno_str); - exit(3); - } - - socket_close(s); - s = s2; - } - - /* simply send the console port in text */ - { - char temp[12]; - snprintf( temp, sizeof(temp), "%d", console_port ); - - if (socket_send(s, temp, strlen(temp)) < 0) { - fprintf(stderr, "could not send console number report: %d: %s\n", - errno, errno_str ); - exit(3); - } - socket_close(s); - } - D( "console port number sent to remote. resuming boot" ); - - restore_sigalrm (&sigstate); -} - -/* this function is used to perform auto-detection of the - * system directory in the case of a SDK installation. - * - * we want to deal with several historical usages, hence - * the slightly complicated logic. - * - * NOTE: the function returns the path to the directory - * containing 'fileName'. this is *not* the full - * path to 'fileName'. - */ -static char* -_getSdkImagePath( const char* fileName ) -{ - char temp[MAX_PATH]; - char* p = temp; - char* end = p + sizeof(temp); - char* q; - char* app; - - static const char* const searchPaths[] = { - "", /* program's directory */ - "/lib/images", /* this is for SDK 1.0 */ - "/../platforms/android-1.1/images", /* this is for SDK 1.1 */ - NULL - }; - - app = bufprint_app_dir(temp, end); - if (app >= end) - return NULL; - - do { - int nn; - - /* first search a few well-known paths */ - for (nn = 0; searchPaths[nn] != NULL; nn++) { - p = bufprint(app, end, "%s", searchPaths[nn]); - q = bufprint(p, end, "/%s", fileName); - if (q < end && path_exists(temp)) { - *p = 0; - goto FOUND_IT; - } - } - - /* hmmm. let's assume that we are in a post-1.1 SDK - * scan ../platforms if it exists - */ - p = bufprint(app, end, "/../platforms"); - if (p < end) { - DirScanner* scanner = dirScanner_new(temp); - if (scanner != NULL) { - int found = 0; - const char* subdir; - - for (;;) { - subdir = dirScanner_next(scanner); - if (!subdir) break; - - q = bufprint(p, end, "/%s/images/%s", subdir, fileName); - if (q >= end || !path_exists(temp)) - continue; - - found = 1; - p = bufprint(p, end, "/%s/images", subdir); - break; - } - dirScanner_free(scanner); - if (found) - break; - } - } - - /* I'm out of ideas */ - return NULL; - - } while (0); - -FOUND_IT: - //D("image auto-detection: %s/%s", temp, fileName); - return qemu_strdup(temp); -} - -static char* -_getSdkImage( const char* path, const char* file ) -{ - char temp[MAX_PATH]; - char *p = temp, *end = p + sizeof(temp); - - p = bufprint(temp, end, "%s/%s", path, file); - if (p >= end || !path_exists(temp)) - return NULL; - - return qemu_strdup(temp); -} - -static char* -_getSdkSystemImage( const char* path, const char* optionName, const char* file ) -{ - char* image = _getSdkImage(path, file); - - if (image == NULL) { - derror("Your system directory is missing the '%s' image file.\n" - "Please specify one with the '%s <filepath>' option", - file, optionName); - exit(2); - } - return image; -} - -static void -_forceAvdImagePath( AvdImageType imageType, - const char* path, - const char* description, - int required ) -{ - if (path == NULL) - return; - - if (required && !path_exists(path)) { - derror("Cannot find %s image file: %s", description, path); - exit(1); - } - android_avdParams->forcePaths[imageType] = path; -} - -#ifdef _WIN32 -#undef main /* we don't want SDL to define main */ -#endif - -int main(int argc, char **argv) -{ - char tmp[MAX_PATH]; - char* tmpend = tmp + sizeof(tmp); - char* args[128]; - int n; - char* opt; - int use_sdcard_img = 0; - int serial = 0; - int gps_serial = 0; - int radio_serial = 0; - int qemud_serial = 0; - int shell_serial = 0; - int dns_count = 0; - unsigned cachePartitionSize = 0; - - AndroidHwConfig* hw; - - //const char *appdir = get_app_dir(); - char* android_build_root = NULL; - char* android_build_out = NULL; - - AndroidOptions opts[1]; - - args[0] = argv[0]; - - if ( android_parse_options( &argc, &argv, opts ) < 0 ) { - exit(1); - } - - while (argc-- > 1) { - opt = (++argv)[0]; - - if(!strcmp(opt, "-qemu")) { - argc--; - argv++; - break; - } - - if (!strcmp(opt, "-help")) { - emulator_help(); - } - - if (!strncmp(opt, "-help-",6)) { - STRALLOC_DEFINE(out); - opt += 6; - - if (!strcmp(opt, "all")) { - android_help_all(out); - } - else if (android_help_for_option(opt, out) == 0) { - /* ok */ - } - else if (android_help_for_topic(opt, out) == 0) { - /* ok */ - } - if (out->n > 0) { - printf("\n%.*s", out->n, out->s); - exit(0); - } - - fprintf(stderr, "unknown option: -help-%s\n", opt); - fprintf(stderr, "please use -help for a list of valid topics\n"); - exit(1); - } - - if (opt[0] == '-') { - fprintf(stderr, "unknown option: %s\n", opt); - fprintf(stderr, "please use -help for a list of valid options\n"); - exit(1); - } - - fprintf(stderr, "invalid command-line parameter: %s.\n", opt); - fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n"); - fprintf(stderr, "please use -help for more information\n"); - exit(1); - } - - android_charmap = android_charmaps[0]; - - if (opts->version) { - printf("Android emulator version %s\n" - "Copyright (C) 2006-2008 The Android Open Source Project and many others.\n" - "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n", -#if defined ANDROID_BUILD_ID - VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" ); -#else - VERSION_STRING); -#endif - printf(" This software is licensed under the terms of the GNU General Public\n" - " License version 2, as published by the Free Software Foundation, and\n" - " may be copied, distributed, and modified under those terms.\n\n" - " This program is distributed in the hope that it will be useful,\n" - " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - " GNU General Public License for more details.\n\n"); - - exit(0); - } - - if (opts->timezone) { - if ( timezone_set(opts->timezone) < 0 ) { - fprintf(stderr, "emulator: it seems the timezone '%s' is not in zoneinfo format\n", opts->timezone); - } - } - - /* If no AVD name was given, try to find the top of the - * Android build tree - */ - if (opts->avd == NULL) { - do { - char* out = getenv("ANDROID_PRODUCT_OUT"); - - if (out == NULL || out[0] == 0) - break; - - if (!path_exists(out)) { - derror("Can't access ANDROID_PRODUCT_OUT as '%s\n" - "You need to build the Android system before launching the emulator", - out); - exit(2); - } - - android_build_root = path_parent( out, 4 ); - if (android_build_root == NULL || !path_exists(android_build_root)) { - derror("Can't find the Android build root from '%s'\n" - "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n" - "It should point to your product-specific build output directory.\n", - out ); - exit(2); - } - android_build_out = out; - D( "found Android build root: %s", android_build_root ); - D( "found Android build out: %s", android_build_out ); - } while (0); - } - /* if no virtual device name is given, and we're not in the - * Android build system, we'll need to perform some auto-detection - * magic :-) - */ - if (opts->avd == NULL && !android_build_out) - { - char dataDirIsSystem = 0; - - if (!opts->system) { - opts->system = _getSdkImagePath("system.img"); - if (!opts->system) { - derror( - "You did not specify a virtual device name, and the system\n" - "directory could not be found.\n\n" - "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n" - "to start a given virtual device (see -help-avd for details).\n\n" - - "Otherwise, follow the instructions in -help-disk-images to start the emulator\n" - ); - exit(2); - } - D("autoconfig: -system %s", opts->system); - } - - if (!opts->image) { - opts->image = _getSdkSystemImage(opts->system, "-image", "system.img"); - D("autoconfig: -image %s", opts->image); - } - - if (!opts->kernel) { - opts->kernel = _getSdkSystemImage(opts->system, "-kernel", "kernel-qemu"); - D("autoconfig: -kernel %s", opts->kernel); - } - - if (!opts->ramdisk) { - opts->ramdisk = _getSdkSystemImage(opts->system, "-ramdisk", "ramdisk.img"); - D("autoconfig: -ramdisk %s", opts->ramdisk); - } - - /* if no data directory is specified, use the system directory */ - if (!opts->datadir) { - opts->datadir = qemu_strdup(opts->system); - dataDirIsSystem = 1; - D("autoconfig: -datadir %s", opts->system); - } - - if (!opts->data) { - /* check for userdata-qemu.img in the data directory */ - bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir); - if (!path_exists(tmp)) { - derror( - "There is no file named 'userdata-qemu.img' in your %s directory.\n" - "You should specify one with the '-data <filepath>' option.", - dataDirIsSystem ? "system" : "data" - ); - exit(2); - } - - opts->data = qemu_strdup(tmp); - D("autoconfig: -data %s", opts->data); - } - - if (!opts->sdcard && opts->datadir) { - bufprint(tmp, tmpend, "%s/sdcard.img", opts->datadir); - if (path_exists(tmp)) { - opts->sdcard = qemu_strdup(tmp); - D("autoconfig: -sdcard %s", opts->sdcard); - } - } - } - - /* setup the virtual device parameters from our options - */ - if (opts->nocache) { - android_avdParams->flags |= AVDINFO_NO_CACHE; - } - if (opts->wipe_data) { - android_avdParams->flags |= AVDINFO_WIPE_DATA | AVDINFO_WIPE_CACHE; - } - - /* if certain options are set, we can force the path of - * certain kernel/disk image files - */ - _forceAvdImagePath(AVD_IMAGE_KERNEL, opts->kernel, "kernel", 1); - _forceAvdImagePath(AVD_IMAGE_SYSTEM, opts->image, "system", 1); - _forceAvdImagePath(AVD_IMAGE_RAMDISK, opts->ramdisk,"ramdisk", 1); - _forceAvdImagePath(AVD_IMAGE_USERDATA,opts->data, "user data", 0); - _forceAvdImagePath(AVD_IMAGE_CACHE, opts->cache, "cache", 0); - _forceAvdImagePath(AVD_IMAGE_SDCARD, opts->sdcard, "SD Card", 0); - - /* we don't accept -skindir without -skin now - * to simplify the autoconfig stuff with virtual devices - */ - if (opts->noskin) { - opts->skin = "320x480"; - opts->skindir = NULL; - } - - if (opts->skindir) { - if (!opts->skin) { - derror( "the -skindir <path> option requires a -skin <name> option"); - exit(1); - } - } - else { - if (!opts->skin && android_build_out) { - /* select default skin based on product type */ - const char* p = strrchr(android_build_out,'/'); - if (p) { - if (p[1] == 's') { - opts->skin = "HVGA"; /* used to be QVGA-L */ - } else if (p[1] == 'd') { - opts->skin = "HVGA"; - } - } - D("autoconfig: -skin %s", opts->skin); - } - android_avdParams->skinName = opts->skin; - } - /* setup the virtual device differently depending on whether - * we are in the Android build system or not - */ - if (opts->avd != NULL) - { - android_avdInfo = avdInfo_new( opts->avd, android_avdParams ); - if (android_avdInfo == NULL) { - /* an error message has already been printed */ - dprint("could not find virtual device named '%s'", opts->avd); - exit(1); - } - } - else - { - if (!android_build_out) { - android_build_out = android_build_root = opts->system; - } - android_avdInfo = avdInfo_newForAndroidBuild( - android_build_root, - android_build_out, - android_avdParams ); - - if(android_avdInfo == NULL) { - D("could not start virtual device\n"); - exit(1); - } - } - - if (!opts->skindir) { - /* get the skin from the virtual device configuration */ - opts->skin = (char*) avdInfo_getSkinName( android_avdInfo ); - opts->skindir = (char*) avdInfo_getSkinDir( android_avdInfo ); - - if (opts->skin) { - D("autoconfig: -skin %s", opts->skin); - } - if (opts->skindir) { - D("autoconfig: -skindir %s", opts->skindir); - } - } - - /* Read hardware configuration */ - hw = android_hw; - if (avdInfo_getHwConfig(android_avdInfo, hw) < 0) { - derror("could not read hardware configuration ?"); - exit(1); - } - -#ifdef CONFIG_NAND_LIMITS - if (opts->nand_limits) - parse_nand_limits(opts->nand_limits); -#endif - - if (opts->keyset) { - parse_keyset(opts->keyset, opts); - if (!android_keyset) { - fprintf(stderr, - "emulator: WARNING: could not find keyset file named '%s'," - " using defaults instead\n", - opts->keyset); - } - } - if (!android_keyset) { - parse_keyset("default", opts); - if (!android_keyset) { - android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() ); - if (!android_keyset) { - fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" ); - fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" ); - exit(1); - } - if (!opts->keyset) - write_default_keyset(); - } - } - - if (opts->audio) { - if (opts->audio_in || opts->audio_out) { - derror( "you can't use -audio with -audio-in or -audio-out\n" ); - exit(1); - } - if ( !audio_check_backend_name( 0, opts->audio ) ) { - derror( "'%s' is not a valid audio output backend. see -help-audio-out\n", - opts->audio); - exit(1); - } - opts->audio_out = opts->audio; - opts->audio_in = opts->audio; - - if ( !audio_check_backend_name( 1, opts->audio ) ) { - fprintf(stderr, - "emulator: warning: '%s' is not a valid audio input backend. audio record disabled\n", - opts->audio); - opts->audio_in = "none"; - } - } - - if (opts->audio_in) { - static char env[64]; /* note: putenv needs a static unique string buffer */ - if ( !audio_check_backend_name( 1, opts->audio_in ) ) { - derror( "'%s' is not a valid audio input backend. see -help-audio-in\n", - opts->audio_in); - exit(1); - } - bufprint( env, env+sizeof(env), "QEMU_AUDIO_IN_DRV=%s", opts->audio_in ); - putenv( env ); - - if (!hw->hw_audioInput) { - dwarning( "Emulated hardware doesn't have audio input."); - } - } - if (opts->audio_out) { - static char env[64]; /* note: putenv needs a static unique string buffer */ - if ( !audio_check_backend_name( 0, opts->audio_out ) ) { - derror( "'%s' is not a valid audio output backend. see -help-audio-out\n", - opts->audio_out); - exit(1); - } - bufprint( env, env+sizeof(env), "QEMU_AUDIO_OUT_DRV=%s", opts->audio_out ); - putenv( env ); - if (!hw->hw_audioOutput) { - dwarning( "Emulated hardware doesn't have audio output"); - } - } - - if (opts->cpu_delay) { - char* end; - long delay = strtol(opts->cpu_delay, &end, 0); - if (end == NULL || *end || delay < 0 || delay > 1000 ) { - fprintf(stderr, "option -cpu-delay must be an integer between 0 and 1000\n" ); - exit(1); - } - if (delay > 0) - delay = (1000-delay); - - qemu_cpu_delay = (int) delay; - } - - emulator_config_init(); - init_skinned_ui(opts->skindir, opts->skin, opts); - - if (!opts->netspeed) { - if (skin_network_speed) - D("skin network speed: '%s'", skin_network_speed); - opts->netspeed = (char*)skin_network_speed; - } - if (!opts->netdelay) { - if (skin_network_delay) - D("skin network delay: '%s'", skin_network_delay); - opts->netdelay = (char*)skin_network_delay; - } - - if ( android_parse_network_speed(opts->netspeed) < 0 ) { - fprintf(stderr, "invalid -netspeed parameter '%s', see emulator -usage\n", opts->netspeed); - emulator_help(); - } - - if ( android_parse_network_latency(opts->netdelay) < 0 ) { - fprintf(stderr, "invalid -netdelay parameter '%s', see emulator -usage\n", opts->netdelay); - emulator_help(); - } - - if (opts->netfast) { - qemu_net_download_speed = 0; - qemu_net_upload_speed = 0; - qemu_net_min_latency = 0; - qemu_net_max_latency = 0; - } - - if (opts->trace) { - char* tracePath = avdInfo_getTracePath(android_avdInfo, opts->trace); - int ret; - - if (tracePath == NULL) { - derror( "bad -trace parameter" ); - exit(1); - } - ret = path_mkdir_if_needed( tracePath, 0755 ); - if (ret < 0) { - fprintf(stderr, "could not create directory '%s'\n", tmp); - exit(2); - } - opts->trace = tracePath; - } - - if (opts->tcpdump) { - if (qemu_tcpdump_start(opts->tcpdump) < 0) { - dwarning( "could not start packet capture: %s", strerror(errno)); - } - } - - if (opts->nocache) - opts->cache = 0; - - if (opts->dns_server) { - char* x = strchr(opts->dns_server, ','); - dns_count = 0; - if (x == NULL) - { - if ( add_dns_server( opts->dns_server ) == 0 ) - dns_count = 1; - } - else - { - x = strdup(opts->dns_server); - while (*x) { - char* y = strchr(x, ','); - - if (y != NULL) - *y = 0; - - if (y == NULL || y > x) { - if ( add_dns_server( x ) == 0 ) - dns_count += 1; - } - - if (y == NULL) - break; - - x = y+1; - } - } - if (dns_count == 0) - fprintf( stderr, "### WARNING: will use system default DNS server\n" ); - } - - if (dns_count == 0) - dns_count = slirp_get_system_dns_servers(); - - n = 1; - /* generate arguments for the underlying qemu main() */ - args[n++] = "-kernel"; - args[n++] = (char*) avdInfo_getImageFile(android_avdInfo, AVD_IMAGE_KERNEL); - - args[n++] = "-initrd"; - args[n++] = (char*) avdInfo_getImageFile(android_avdInfo, AVD_IMAGE_RAMDISK); - - { - const char* filetype = "file"; - - if (avdInfo_isImageReadOnly(android_avdInfo, AVD_IMAGE_SYSTEM)) - filetype = "initfile"; - - bufprint(tmp, tmpend, - "system,size=0x4200000,%s=%s", filetype, - avdInfo_getImageFile(android_avdInfo, AVD_IMAGE_SYSTEM)); - - args[n++] = "-nand"; - args[n++] = strdup(tmp); - } - - bufprint(tmp, tmpend, - "userdata,size=0x4200000,file=%s", - avdInfo_getImageFile(android_avdInfo, AVD_IMAGE_USERDATA)); - - args[n++] = "-nand"; - args[n++] = strdup(tmp); - - if (hw->disk_cachePartition) { - opts->cache = (char*) avdInfo_getImageFile(android_avdInfo, AVD_IMAGE_CACHE); - cachePartitionSize = hw->disk_cachePartition_size; - } - else if (opts->cache) { - dwarning( "Emulated hardware doesn't support a cache partition" ); - opts->cache = NULL; - opts->nocache = 1; - } - - if (opts->cache) { - /* use a specific cache file */ - sprintf(tmp, "cache,size=0x%0x,file=%s", cachePartitionSize, opts->cache); - args[n++] = "-nand"; - args[n++] = strdup(tmp); - } - else if (!opts->nocache) { - /* create a temporary cache partition file */ - sprintf(tmp, "cache,size=0x%0x", cachePartitionSize); - args[n++] = "-nand"; - args[n++] = strdup(tmp); - } - - if (hw->hw_sdCard != 0) - opts->sdcard = (char*) avdInfo_getImageFile(android_avdInfo, AVD_IMAGE_SDCARD); - else if (opts->sdcard) { - dwarning( "Emulated hardware doesn't support SD Cards" ); - opts->sdcard = NULL; - } - - if(opts->sdcard) { - uint64_t size; - if (path_get_size(opts->sdcard, &size) == 0) { - /* see if we have an sdcard image. get its size if it exists */ - if (size < 8*1024*1024ULL) { - fprintf(stderr, "### WARNING: SD Card files must be at least 8 MB, ignoring '%s'\n", opts->sdcard); - } else { - args[n++] = "-hda"; - args[n++] = opts->sdcard; - use_sdcard_img = 1; - } - } else { - D("no SD Card image at '%s'", opts->sdcard); - } - } - - if (!opts->logcat || opts->logcat[0] == 0) { - opts->logcat = getenv("ANDROID_LOG_TAGS"); - if (opts->logcat && opts->logcat[0] == 0) - opts->logcat = NULL; - } - -#if 0 - if (opts->console) { - derror( "option -console is obsolete. please use -shell instead" ); - exit(1); - } -#endif - - /* we always send the kernel messages from ttyS0 to android_kmsg */ - { - AndroidKmsgFlags flags = 0; - - if (opts->show_kernel) - flags |= ANDROID_KMSG_PRINT_MESSAGES; - - android_kmsg_init( flags ); - args[n++] = "-serial"; - args[n++] = "android-kmsg"; - serial++; - } - - /* XXXX: TODO: implement -shell and -logcat through qemud instead */ - if (!opts->shell_serial) { -#ifdef _WIN32 - opts->shell_serial = "con:"; -#else - opts->shell_serial = "stdio"; -#endif - } - else - opts->shell = 1; - - if (opts->shell || opts->logcat) { - args[n++] = "-serial"; - args[n++] = opts->shell_serial; - shell_serial = serial++; - } - - if (opts->old_system) - { - if (opts->radio) { - args[n++] = "-serial"; - args[n++] = opts->radio; - radio_serial = serial++; - } - else { - args[n++] = "-serial"; - args[n++] = "android-modem"; - radio_serial = serial++; - } - if (opts->gps) { - args[n++] = "-serial"; - args[n++] = opts->gps; - gps_serial = serial++; - } - } - else /* !opts->old_system */ - { - args[n++] = "-serial"; - args[n++] = "android-qemud"; - qemud_serial = serial++; - - if (opts->radio) { - CharDriverState* cs = qemu_chr_open(opts->radio); - if (cs == NULL) { - derror( "unsupported character device specification: %s\n" - "used -help-char-devices for list of available formats\n", opts->radio ); - exit(1); - } - android_qemud_set_channel( ANDROID_QEMUD_GSM, cs); - } - else if ( hw->hw_gsmModem != 0 ) { - if ( android_qemud_get_channel( ANDROID_QEMUD_GSM, &android_modem_cs ) < 0 ) { - derror( "could not initialize qemud 'gsm' channel" ); - exit(1); - } - } - - if (opts->gps) { - CharDriverState* cs = qemu_chr_open(opts->gps); - if (cs == NULL) { - derror( "unsupported character device specification: %s\n" - "used -help-char-devices for list of available formats\n", opts->gps ); - exit(1); - } - android_qemud_set_channel( ANDROID_QEMUD_GPS, cs); - } - else if ( hw->hw_gps != 0 ) { - if ( android_qemud_get_channel( "gps", &android_gps_cs ) < 0 ) { - derror( "could not initialize qemud 'gps' channel" ); - exit(1); - } - } - } - - if (opts->memory) { - char* end; - long ramSize = strtol(opts->memory, &end, 0); - if (ramSize < 0 || *end != 0) { - derror( "-memory must be followed by a positive integer" ); - exit(1); - } - if (ramSize < 32 || ramSize > 4096) { - derror( "physical memory size must be between 32 and 4096 MB" ); - exit(1); - } - } - if (!opts->memory) { - bufprint(tmp, tmpend, "%d", hw->hw_ramSize); - opts->memory = qemu_strdup(tmp); - } - - if (opts->noaudio) { - args[n++] = "-noaudio"; - } - -#if 0 - if (opts->mic) { - if (path_can_read(opts->mic)) { - args[n++] = "-mic"; - args[n++] = opts->mic; - } else { - dprint("could not find or access audio input at '%s'", opts->mic); - } - } -#endif - - if (opts->trace) { - args[n++] = "-trace"; - args[n++] = opts->trace; - args[n++] = "-tracing"; - args[n++] = "off"; - } - - args[n++] = "-append"; - - if (opts->bootchart) { - char* end; - int timeout = strtol(opts->bootchart, &end, 10); - if (timeout == 0) - opts->bootchart = NULL; - else if (timeout < 0 || timeout > 15*60) { - derror( "timeout specified for -bootchart option is invalid.\n" - "please use integers between 1 and 900\n"); - exit(1); - } - } - - { - static char params[1024]; - char *p = params, *end = p + sizeof(params); - - p = bufprint(p, end, "qemu=1 console=ttyS0" ); - - if (opts->shell || opts->logcat) { - p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial ); - } - - if (opts->trace) { - p = bufprint(p, end, " android.tracing=1"); - } - - if (!opts->nojni) { - p = bufprint(p, end, " android.checkjni=1"); - } - - if (opts->no_boot_anim) { - p = bufprint( p, end, " android.bootanim=0" ); - } - - if (opts->logcat) { - char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat); - - if (q < end) { - /* replace any space by a comma ! */ - { - int nn; - for (nn = 1; p[nn] != 0; nn++) - if (p[nn] == ' ' || p[nn] == '\t') - p[nn] = ','; - p += nn; - } - } - p = q; - } - - if (opts->old_system) - { - p = bufprint(p, end, " android.ril=ttyS%d", radio_serial); - - if (opts->gps) { - p = bufprint(p, end, " android.gps=ttyS%d", gps_serial); - } - } - else - { - p = bufprint(p, end, " android.qemud=ttyS%d", qemud_serial); - } - - if (dns_count > 0) { - p = bufprint(p, end, " android.ndns=%d", dns_count); - } - - if (opts->bootchart) { - p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart); - } - - if (p >= end) { - fprintf(stderr, "### ERROR: kernel parameters too long\n"); - exit(1); - } - - args[n++] = strdup(params); - } - - /* physical memory */ - args[n++] = "-m"; - args[n++] = opts->memory; - - /* on Linux, the 'dynticks' clock sometimes doesn't work - * properly. this results in the UI freezing while emulation - * continues, for several seconds... - */ -#ifdef __linux__ - args[n++] = "-clock"; - args[n++] = "unix"; -#endif - - while(argc-- > 0) { - args[n++] = *argv++; - } - args[n] = 0; - - if(VERBOSE_CHECK(init)) { - int i; - for(i = 0; i < n; i++) { - fprintf(stdout, "emulator: argv[%02d] = \"%s\"\n", i, args[i]); - } - } - return qemu_main(n, args); -} - -/* this function is called from qemu_main() once all arguments have been parsed - * it should be used to setup any Android-specific items in the emulation before the - * main loop runs - */ -void android_emulation_setup( void ) -{ - int tries = 16; - int base_port = 5554; - int success = 0; - int s; - uint32_t guest_ip; - - AndroidOptions* opts = qemulator->opts; - - inet_strtoip("10.0.2.15", &guest_ip); - -#if 0 - if (opts->adb_port) { - fprintf( stderr, "option -adb-port is obsolete, use -port instead\n" ); - exit(1); - } -#endif - - if (opts->port && opts->ports) { - fprintf( stderr, "options -port and -ports cannot be used together.\n"); - exit(1); - } - - if (opts->ports) { - char* comma_location; - char* end; - int console_port = strtol( opts->ports, &comma_location, 0 ); - - if ( comma_location == NULL || *comma_location != ',' ) { - derror( "option -ports must be followed by two comma separated positive integer numbers" ); - exit(1); - } - - int adb_port = strtol( comma_location+1, &end, 0 ); - - if ( end == NULL || *end ) { - derror( "option -ports must be followed by two comma separated positive integer numbers" ); - exit(1); - } - - if ( console_port == adb_port ) { - derror( "option -ports must be followed by two different integer numbers" ); - exit(1); - } - - slirp_redir( 0, adb_port, guest_ip, 5555 ); - if ( control_console_start( console_port ) < 0 ) { - slirp_unredir( 0, adb_port ); - } - - base_port = console_port; - } else { - if (opts->port) { - char* end; - int port = strtol( opts->port, &end, 0 ); - if ( end == NULL || *end || - (unsigned)((port - base_port) >> 1) >= (unsigned)tries ) { - derror( "option -port must be followed by an even integer number between %d and %d\n", - base_port, base_port + (tries-1)*2 ); - exit(1); - } - if ( (port & 1) != 0 ) { - port &= ~1; - dwarning( "option -port must be followed by an even integer, using port number %d\n", - port ); - } - base_port = port; - tries = 1; - } - - for ( ; tries > 0; tries--, base_port += 2 ) { - - /* setup first redirection for ADB, the Android Debug Bridge */ - if ( slirp_redir( 0, base_port+1, guest_ip, 5555 ) < 0 ) - continue; - - /* setup second redirection for the emulator console */ - if ( control_console_start( base_port ) < 0 ) { - slirp_unredir( 0, base_port+1 ); - continue; - } - - D( "control console listening on port %d, ADB on port %d", base_port, base_port+1 ); - success = 1; - break; - } - - if (!success) { - fprintf(stderr, "it seems too many emulator instances are running on this machine. Aborting\n" ); - exit(1); - } - } - - if (opts->report_console) { - report_console(opts->report_console, base_port); - } - - android_modem_init( base_port ); - - android_base_port = base_port; - /* send a simple message to the ADB host server to tell it we just started. - * it should be listening on port 5037. if we can't reach it, don't bother - */ - do - { - SockAddress addr; - char tmp[32]; - - s = socket_create_inet( SOCKET_STREAM ); - if (s < 0) { - D("can't create socket to talk to the ADB server"); - break; - } - - sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, 5037 ); - if (socket_connect( s, &addr ) < 0) { - D("can't connect to ADB server: %s", errno_str ); - break; - } - - sprintf(tmp,"0012host:emulator:%d",base_port+1); - socket_send(s, tmp, 18+4); - D("sent '%s' to ADB server", tmp); - } - while (0); - - if (s >= 0) - socket_close(s); - - /* setup the http proxy, if any */ - if (VERBOSE_CHECK(proxy)) - proxy_set_verbose(1); - - if (!opts->http_proxy) { - opts->http_proxy = getenv("http_proxy"); - } - - do - { - const char* env = opts->http_proxy; - int envlen; - ProxyOption option_tab[4]; - ProxyOption* option = option_tab; - char* p; - char* q; - const char* proxy_name; - int proxy_name_len; - int proxy_port; - - if (!env) - break; - - envlen = strlen(env); - - /* skip the 'http://' header, if present */ - if (envlen >= 7 && !memcmp(env, "http://", 7)) { - env += 7; - envlen -= 7; - } - - /* do we have a username:password pair ? */ - p = strchr(env, '@'); - if (p != 0) { - q = strchr(env, ':'); - if (q == NULL) { - BadHttpProxyFormat: - dprint("http_proxy format unsupported, try 'proxy:port' or 'username:password@proxy:port'"); - break; - } - - option->type = PROXY_OPTION_AUTH_USERNAME; - option->string = env; - option->string_len = q - env; - option++; - - option->type = PROXY_OPTION_AUTH_PASSWORD; - option->string = q+1; - option->string_len = p - (q+1); - option++; - - env = p+1; - } - - p = strchr(env,':'); - if (p == NULL) - goto BadHttpProxyFormat; - - proxy_name = env; - proxy_name_len = p - env; - proxy_port = atoi(p+1); - - D( "setting up http proxy: server=%.*s port=%d", - proxy_name_len, proxy_name, proxy_port ); - - if ( proxy_http_setup( proxy_name, proxy_name_len, proxy_port, - option - option_tab, option_tab ) < 0 ) - { - dprint( "http proxy setup failed, check your $http_proxy variable"); - } - } - while (0); - - /* cool, now try to run the "ddms ping" command, which will take care of pinging usage - * if the user agreed for it. the emulator itself never sends anything to any outside - * machine - */ - { -#ifdef _WIN32 -# define _ANDROID_PING_PROGRAM "ddms.bat" -#else -# define _ANDROID_PING_PROGRAM "ddms" -#endif - - char tmp[PATH_MAX]; - const char* appdir = get_app_dir(); - - if (snprintf( tmp, PATH_MAX, "%s%s%s", appdir, PATH_SEP, - _ANDROID_PING_PROGRAM ) >= PATH_MAX) { - dprint( "Application directory too long: %s", appdir); - return; - } - - /* if the program isn't there, don't bother */ - D( "ping program: %s", tmp); - if (path_exists(tmp)) { -#ifdef _WIN32 - STARTUPINFO startup; - PROCESS_INFORMATION pinfo; - - ZeroMemory( &startup, sizeof(startup) ); - startup.cb = sizeof(startup); - startup.dwFlags = STARTF_USESHOWWINDOW; - startup.wShowWindow = SW_SHOWMINIMIZED; - - ZeroMemory( &pinfo, sizeof(pinfo) ); - - char* comspec = getenv("COMSPEC"); - if (!comspec) comspec = "cmd.exe"; - - // Run - char args[PATH_MAX + 30]; - if (snprintf( args, PATH_MAX, "/C \"%s\" ping emulator " VERSION_STRING, - tmp) >= PATH_MAX ) { - D( "DDMS path too long: %s", tmp); - return; - } - - CreateProcess( - comspec, /* program path */ - args, /* command line args */ - NULL, /* process handle is not inheritable */ - NULL, /* thread handle is not inheritable */ - FALSE, /* no, don't inherit any handles */ - DETACHED_PROCESS, /* the new process doesn't have a console */ - NULL, /* use parent's environment block */ - NULL, /* use parent's starting directory */ - &startup, /* startup info, i.e. std handles */ - &pinfo ); - - D( "ping command: %s %s", comspec, args ); -#else - int pid = fork(); - if (pid == 0) { - int fd = open("/dev/null", O_WRONLY); - dup2(fd, 1); - dup2(fd, 2); - execl( tmp, _ANDROID_PING_PROGRAM, "ping", "emulator", VERSION_STRING, NULL ); - } - /* don't do anything in the parent or in case of error */ - strncat( tmp, " ping emulator " VERSION_STRING, PATH_MAX - strlen(tmp) ); - D( "ping command: %s", tmp ); -#endif - } - } -} - - -void android_emulation_teardown( void ) -{ -} |