diff options
Diffstat (limited to 'android_main.c')
-rw-r--r-- | android_main.c | 785 |
1 files changed, 511 insertions, 274 deletions
diff --git a/android_main.c b/android_main.c index 72c9ef6..75d52c7 100644 --- a/android_main.c +++ b/android_main.c @@ -54,11 +54,15 @@ #include "android_gps.h" #include "android_qemud.h" #include "android_kmsg.h" +#include "android_hw_control.h" +#include "android/utils/dirscanner.h" #include "android_option.h" #include "android_help.h" #include "hw/goldfish_nand.h" +#include "android/globals.h" + #include "framebuffer.h" AndroidRotation android_framebuffer_rotation; @@ -351,6 +355,7 @@ typedef struct { int win_y; int show_trackball; SkinTrackBall* trackball; + int lcd_brightness; SkinImage* onion; SkinRotation onion_rotation; int onion_alpha; @@ -576,7 +581,10 @@ qemulator_set_title( QEmulator* emulator ) if (emulator->window == NULL) return; - snprintf( temp, sizeof(temp), "Android Emulator (%d)", android_base_port ); + snprintf( temp, sizeof(temp), "Android Emulator (%s:%d)", + avmInfo_getName( android_vmInfo ), + android_base_port ); + skin_window_set_title( emulator->window, temp ); } @@ -599,6 +607,21 @@ sdl_update(DisplayState *ds, int x, int y, int w, int h) static void +qemulator_light_brightness( void* opaque, const char* light, int value ) +{ + QEmulator* emulator = opaque; + + D("%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; @@ -624,6 +647,9 @@ qemulator_setup( QEmulator* emulator ) 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 ) @@ -633,6 +659,19 @@ qemulator_setup( QEmulator* emulator ) 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 ); } } @@ -779,11 +818,11 @@ handle_key_command( void* opaque, SkinKeyCommand command, int down ) } } - // for the trackball command, handle down events to enable, and + // for the show-trackball command, handle down events to enable, and // up events to disable - if (command == SKIN_KEY_COMMAND_TOGGLE_TRACKBALL) { - skin_window_toggle_trackball( emulator->window ); - emulator->show_trackball = !emulator->show_trackball; + 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; } @@ -825,6 +864,11 @@ handle_key_command( void* opaque, SkinKeyCommand command, int down ) } 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) @@ -864,14 +908,23 @@ handle_key_command( void* opaque, SkinKeyCommand command, int down ) 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, - skin_layout_get_dpad_rotation( layout ) ); - if (emulator->trackball) + 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(); @@ -993,11 +1046,22 @@ void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts) if(name) { /* Support skin aliases like QVGA-H QVGA-P, etc... - But first we check if it's a directory that exist before applyin the alias */ - sprintf(tmp, "%s/%s", path, name); - if (!path_exists(tmp)) { - /* directory is invalid, apply alias */ + 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; @@ -1006,6 +1070,7 @@ void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts) break; if ( !strcasecmp( skin_name, name ) ) { + D("skin name '%s' aliased to '%s'", name, skin_alias); name = skin_alias; break; } @@ -1018,13 +1083,19 @@ void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts) 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); + 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); @@ -1033,7 +1104,8 @@ void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts) path = tmp; goto found_a_skin; } else { - fprintf(stderr, "### WARNING: could not load skin file '%s', using built-in one\n", tmp); + dwarning("could not load skin file '%s', using built-in one\n", + tmp); } } @@ -1128,15 +1200,6 @@ found_a_skin: } } -/* where to look relative to appdir for system.img and friends */ -const char *sysdir_paths[] = { - "%s/lib/images/%s", /* emulator in <sdk>, images in <sdk>/lib/images */ - "%s/%s", /* emulator and images in the same directory */ - "%s/../%s", - "%s/../../%s", /* emulator in <build>/host/bin, images in <build> */ - 0 -}; - int qemu_main(int argc, char **argv); /* this function dumps the QEMU help */ @@ -1418,41 +1481,6 @@ parse_nand_limits(char* limits) } #endif /* CONFIG_NAND_LIMITS */ -/* If *arg isn't already set, and <dir>/<file> exists, use it. */ -static void default_file(char **arg, const char* option, const char *dir, const char *file) { - if (*arg == NULL || (*arg)[0] == '\0') { - *arg = malloc(strlen(dir) + strlen(PATH_SEP) + strlen(file) + 1); - sprintf(*arg, "%s%s%s", dir, PATH_SEP, file); - if (option) - D("autoconfig: -%s %s", option, *arg); - } -} - - -/* Call default_file() and also exit if the file doesn't exist. */ -static void require_file(char **arg, const char* option, const char *dir, const char *file) { - default_file(arg, option, dir, file); - if (!path_exists(*arg)) { - fprintf(stderr, "Cannot find file: %s\n", *arg); - if (option != NULL) - fprintf(stderr, "Please specify a valid -%s file\n", option); - exit(1); - } -} - - -/* If *arg is set, require it to exist, else use the default if it exists. */ -static void optional_file(char **arg, const char* option, const char *dir, const char *file) { - if (*arg == NULL) { - default_file(arg, option, dir, file); - if (!path_exists(*arg)) - *arg = NULL; - } else { - /* If it's supplied explciitly, it better be there. */ - require_file(arg, option, dir, file); - } -} - void emulator_help( void ) { STRALLOC_DEFINE(out); @@ -1642,6 +1670,120 @@ report_console( const char* proto_port, int console_port ) 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; + q = 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* pathText, 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)) { + derror("you %s directory is missing the '%s' image file.", + pathText, file); + exit(2); + } + + return qemu_strdup(temp); +} + + +static void +_forceVmImagePath( AvmImageType 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_vmParams->forcePaths[imageType] = path; +} + #ifdef _WIN32 #undef main /* we don't want SDL to define main */ #endif @@ -1660,8 +1802,11 @@ int main(int argc, char **argv) int qemud_serial = 0; int shell_serial = 0; int dns_count = 0; + unsigned cachePartitionSize = 0; + + AndroidHwConfig* hw; - const char *appdir = get_app_dir(); + //const char *appdir = get_app_dir(); char* android_build_root = NULL; char* android_build_out = NULL; @@ -1677,6 +1822,8 @@ int main(int argc, char **argv) opt = (++argv)[0]; if(!strcmp(opt, "-qemu")) { + argc--; + argv++; break; } @@ -1702,17 +1849,21 @@ int main(int argc, char **argv) exit(0); } - fprintf(stderr, "unknown option: -%s\n", opt); - emulator_help(); + 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); - emulator_help(); + fprintf(stderr, "please use -help for a list of valid options\n"); + exit(1); } - fprintf(stderr, "invalid command-line parameter: %s\n", opt); - emulator_help(); + fprintf(stderr, "invalid command-line parameter: %s.\n", opt); + fprintf(stderr, "Hint: use '@foo' to launch a virtual machine named 'foo'.\n"); + fprintf(stderr, "please use -help for more information\n"); + exit(1); } android_charmap = android_charmaps[0]; @@ -1743,9 +1894,9 @@ int main(int argc, char **argv) } } - //if(opts->nopoll) qemu_milli_needed = 0; - - /* try to find the top of the Android build tree */ + /* try to find the top of the Android build tree + * unless we have been given a virtual machine name + */ do { char* out = getenv("ANDROID_PRODUCT_OUT"); @@ -1772,149 +1923,164 @@ int main(int argc, char **argv) D( "found Android build out: %s", android_build_out ); } while (0); - /* if no opts->system was specified, try to find one */ - if (opts->system == NULL) { - for (n = 0; sysdir_paths[n]; n++) { - sprintf(tmp, sysdir_paths[n], appdir, "system.img"); - if (path_exists(tmp)) { - sprintf(tmp, sysdir_paths[n], appdir, ""); - opts->system = strdup(tmp); - break; + /* if no virtual machine name is given, and we're not in the + * Android build system, we'll need to perform some auto-detection + * magic :-) + */ + if (opts->vm == NULL && !android_build_out) { + if (!opts->system) { + opts->system = _getSdkImagePath("system.img"); + if (!opts->system) { + NO_VM_NAME: + derror( "you must provide the name of a virtual machine to start the emulator.\n" + "please see -help-vm for details." ); + exit(2); } + D("autoconfig: -system %s", opts->system); } - if (opts->system == NULL && android_build_out) { - sprintf(tmp, "%s/%s", android_build_out, "system.img"); - if (path_exists(tmp)) - opts->system = android_build_out; + if (!opts->image) { + opts->image = _getSdkImage(opts->system, "-system", "system.img"); + D("autoconfig: -image %s", opts->image); } - if (opts->system == NULL) { - fprintf(stderr, - "Cannot locate system directory, which " - "contains 'system.img' and other\n" - "system files. Please specify one by " - "using '-system <directory>' or by\n" - "defining the environment variable ANDROID_PRODUCT_OUT.\n"); - exit(1); + if (!opts->kernel) { + opts->kernel = _getSdkImage(opts->system, "-system", "kernel-qemu"); + D("autoconfig: -kernel %s", opts->kernel); } - D("autoconfig: -system %s", opts->system); - } + if (!opts->ramdisk) { + opts->ramdisk = _getSdkImage(opts->system, "-ramdisk", "ramdisk.img"); + D("autoconfig: -ramdisk %s", opts->ramdisk); + } - if (opts->datadir == NULL) { - if (android_build_out) - opts->datadir = android_build_out; - else { - bufprint_config_path( tmp, tmpend ); - opts->datadir = strdup(tmp); + if (!opts->data) { + /* we don't want new SDK users to keep using their + * obsolete data images. unless they specifically + * use -data or -datadir with an existing file, + * we're going to complain. + */ + if (!opts->datadir) { + goto NO_VM_NAME; + } + + /* here the user used -datadir, so check that there is a + * valid data partition file here, if not abort. + */ + bufprint(tmp, tmpend, opts->datadir, "/userdata-qemu.img"); + if (!path_exists(tmp)) + goto NO_VM_NAME; + + opts->data = qemu_strdup(tmp); + D("autoconfig: -data %s", opts->data); } - D("autoconfig: -datadir %s", opts->datadir); - } - sprintf(tmp, "%s%s.", opts->datadir, PATH_SEP); - if (!path_can_write(tmp)) { - if (path_mkdir_if_needed(opts->datadir, 0755) != 0) { - fprintf(stderr, - "Cannot create data directory: %s\n" - "Please specify a writable directory with -datadir.\n", opts->datadir); - exit(1); + if (!opts->sdcard && opts->datadir) { + bufprint(tmp, tmpend, opts->datadir, "/sdcard.img"); + if (path_exists(tmp)) { + opts->sdcard = qemu_strdup(tmp); + D("autoconfig: -sdcard %s", opts->sdcard); + } } } - /* try to find the qemu kernel in the system directory, - * otherwise, try to get it in the prebuilt directory */ - optional_file(&opts->kernel, "kernel", opts->system, "kernel-qemu"); - if (!opts->kernel && android_build_root) { - sprintf(tmp, "%s/prebuilt/android-arm/kernel", android_build_root); - optional_file(&opts->kernel, "kernel", tmp, "kernel-qemu"); + /* setup the virtual machine parameters from our options + */ + if (opts->nocache) { + android_vmParams->flags |= AVMINFO_NO_CACHE; } - - /* similar hack for emulator skins */ - if (!opts->noskin && opts->skindir == NULL) { - if (android_build_root) { - sprintf(tmp, "%s/development/emulator", android_build_root); - optional_file(&opts->skindir, "skindir", tmp, "skins"); - } + if (opts->wipe_data) { + android_vmParams->flags |= AVMINFO_WIPE_DATA | AVMINFO_WIPE_CACHE; } - require_file(&opts->kernel, "kernel", opts->system, "kernel-qemu"); - require_file(&opts->ramdisk, "ramdisk", opts->system, "ramdisk.img"); - require_file(&opts->image, "image", opts->system, "system.img"); - require_file(&opts->initdata, "initdata", opts->system, "userdata.img"); - - if (!opts->skindir) - optional_file(&opts->skindir, "skindir", opts->system, "skins"); - - optional_file(&opts->sdcard, "sdcard", opts->datadir, "sdcard.img"); + /* if certain options are set, we can force the path of + * certain kernel/disk image files + */ + _forceVmImagePath(AVM_IMAGE_KERNEL, opts->kernel, "kernel", 1); + _forceVmImagePath(AVM_IMAGE_SYSTEM, opts->image, "system", 1); + _forceVmImagePath(AVM_IMAGE_RAMDISK, opts->ramdisk,"ramdisk", 1); + _forceVmImagePath(AVM_IMAGE_USERDATA,opts->data, "user data", 0); + _forceVmImagePath(AVM_IMAGE_CACHE, opts->cache, "cache", 0); + _forceVmImagePath(AVM_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->data == NULL) { - if (strcmp(opts->datadir, opts->system) != 0) { - /* in the past, the writable image was called "userdata.img" */ - optional_file(&opts->data, "data", opts->datadir, "userdata.img"); + if (opts->skindir) { + if (!opts->skin) { + derror( "the -skindir <path> option requires a -skin <name> option"); + exit(1); } - default_file(&opts->data, "data", opts->datadir, "userdata-qemu.img"); - - if ( !path_exists(opts->data) ) { - /* if the file does not exist, imply a -wipe-data */ - opts->wipe_data = 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 = "QVGA-L"; + } else if (p[1] == 'd') { + opts->skin = "HVGA"; + } + } + D("autoconfig: -skin %s", opts->skin); } - } else if ( !path_exists(opts->data) ) { - /* if -data is used with a non-existent data file */ - opts->wipe_data = 1; + android_vmParams->skinName = opts->skin; } - + /* setup the virtual machine differently depending on whether + * we are in the Android build system or not + */ + if (opts->vm != NULL) { - FileLock* data_lock = filelock_create(opts->data); - if (data_lock == NULL) { - fprintf(stderr, "Cannot create /data image file lock\n"); - exit(2); - } - /* if the file is already used, use a temporary file instead */ - if (filelock_lock(data_lock) < 0) { - TempFile* data_tmp; - fprintf(stderr, - "### WARNING: Another emulator is running with our data file\n"); - - data_tmp = tempfile_create(); - if (data_tmp == NULL) { - fprintf(stderr, "annot create a new temporary user data file.\n" ); - exit(2); - } - fprintf(stderr, "### WARNING: User data changes will NOT be saved!\n"); - opts->data = (char*) tempfile_path(data_tmp); - opts->wipe_data = 1; + android_vmInfo = avmInfo_new( opts->vm, android_vmParams ); + if (android_vmInfo == NULL) { + /* an error message has already been printed */ + D("could not find virtual machine named '%s'", opts->vm); + exit(1); } } + else + { + if (!android_build_out) { + android_build_root = android_build_out = opts->system; + } + android_vmInfo = avmInfo_newForAndroidBuild( + android_build_root, + android_build_out, + android_vmParams ); - /* wipe the data file if necessary */ - if (opts->wipe_data || !path_exists(opts->data)) { - if (copy_file(opts->data, opts->initdata) >= 0) { - D("copied file '%s' from '%s'", opts->data, opts->initdata); - } else { - fprintf(stderr, - "### WARNING: Cannot write user data file '%s': %s\n", - opts->data, strerror(errno)); - exit(3); + if(android_vmInfo == NULL) { + D("could not start virtual machine\n"); + exit(1); } } - /* lock the SD card image file */ - if (opts->sdcard != NULL) { - FileLock* sdcard_lock = filelock_create( opts->sdcard ); - int free_sdcard = (sdcard_lock == NULL); + if (!opts->skindir) { + /* get the skin from the virtual machine configuration */ + opts->skin = (char*) avmInfo_getSkinName( android_vmInfo ); + opts->skindir = (char*) avmInfo_getSkinDir( android_vmInfo ); - if (sdcard_lock && filelock_lock(sdcard_lock) < 0) { - fprintf( stderr, "#### WARNING: SD Card emulation disabled. '%s' already in use\n", opts->sdcard ); - free_sdcard = 1; + if (opts->skin) { + D("autoconfig: -skin %s", opts->skin); } - - if (free_sdcard) { - opts->sdcard = NULL; + if (opts->skindir) { + D("autoconfig: -skindir %s", opts->skindir); } } + /* Read hardware configuration */ + hw = android_hw; + if (avmInfo_getHwConfig(android_vmInfo, hw) < 0) { + derror("could not read hardware configuration ?"); + exit(1); + } + #ifdef CONFIG_NAND_LIMITS if (opts->nand_limits) parse_nand_limits(opts->nand_limits); @@ -1924,7 +2090,8 @@ int main(int argc, char **argv) parse_keyset(opts->keyset, opts); if (!android_keyset) { fprintf(stderr, - "emulator: WARNING: could not find keyset file named '%s', using defaults instead\n", + "emulator: WARNING: could not find keyset file named '%s'," + " using defaults instead\n", opts->keyset); } } @@ -1969,6 +2136,10 @@ int main(int argc, char **argv) } 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 */ @@ -1979,26 +2150,8 @@ int main(int argc, char **argv) } bufprint( env, env+sizeof(env), "QEMU_AUDIO_OUT_DRV=%s", opts->audio_out ); putenv( env ); - } - - if (opts->noskin) { - opts->skin = "320x240"; - opts->skindir = NULL; - } else if (opts->skin == NULL) { - /* select default skin based on product type */ - const char* env = getenv("ANDROID_PRODUCT_OUT"); - if (env) { - const char* p = strrchr(env,'/'); - if (p) { - if (p[1] == 's') { - opts->skin = "QVGA-L"; - } else if (p[1] == 'd') { - opts->skin = "HVGA"; - } - } - } - if (opts->skin) { - D("autoconfig: -skin %s", opts->skin); + if (!hw->hw_audioOutput) { + dwarning( "Emulated hardware doesn't have audio output"); } } @@ -2047,41 +2200,24 @@ int main(int argc, char **argv) } if (opts->trace) { - int ret; - sprintf(tmp, "%s/traces", opts->system); - ret = path_mkdir_if_needed( tmp, 0755 ); + char* tracePath = avmInfo_getTracePath(android_vmInfo, 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); } - sprintf(tmp, "%s/traces/%s", opts->system, opts->trace); - opts->trace = strdup(tmp); + opts->trace = tracePath; } if (opts->nocache) opts->cache = 0; - if (opts->cache) { - FileLock* cache_lock = filelock_create(opts->cache); - if (cache_lock == NULL) { - fprintf(stderr, "Could not create cache image file lock\n" ); - exit(2); - } - if ( filelock_lock( cache_lock ) < 0 ) { - fprintf(stderr, "### WARNING: Another emulator instance is using our cache file. using temp file\n"); - opts->cache = NULL; - } - else if ( !path_exists(opts->cache) ) { - /* -cache <file> where <file> does not exit, we simply */ - /* create an empty file then */ - if ( make_empty_file( opts->cache ) < 0 ) { - fprintf(stderr, "could not create cache file '%s'\n", opts->cache); - exit(2); - } - D( "created non-existent cache image file: %s\n", opts->cache ); - } - } - if (opts->dns_server) { char* x = strchr(opts->dns_server, ','); dns_count = 0; @@ -2119,33 +2255,63 @@ int main(int argc, char **argv) n = 1; /* generate arguments for the underlying qemu main() */ - if(opts->kernel) { - args[n++] = "-kernel"; - args[n++] = opts->kernel; - } - if(opts->ramdisk) { - args[n++] = "-initrd"; - args[n++] = opts->ramdisk; - } - if(opts->image) { - sprintf(tmp, "system,size=0x4200000,initfile=%s", opts->image); + args[n++] = "-kernel"; + args[n++] = (char*) avmInfo_getImageFile(android_vmInfo, AVM_IMAGE_KERNEL); + + args[n++] = "-initrd"; + args[n++] = (char*) avmInfo_getImageFile(android_vmInfo, AVM_IMAGE_RAMDISK); + + { + const char* filetype = "file"; + + if (avmInfo_isImageReadOnly(android_vmInfo, AVM_IMAGE_SYSTEM)) + filetype = "initfile"; + + bufprint(tmp, tmpend, + "system,size=0x4200000,%s=%s", filetype, + avmInfo_getImageFile(android_vmInfo, AVM_IMAGE_SYSTEM)); + args[n++] = "-nand"; args[n++] = strdup(tmp); } - if(opts->data) { - sprintf(tmp, "userdata,size=0x4200000,file=%s", opts->data); - args[n++] = "-nand"; - args[n++] = strdup(tmp); + + bufprint(tmp, tmpend, + "userdata,size=0x4200000,file=%s", + avmInfo_getImageFile(android_vmInfo, AVM_IMAGE_USERDATA)); + + args[n++] = "-nand"; + args[n++] = strdup(tmp); + + if (hw->disk_cachePartition) { + opts->cache = (char*) avmInfo_getImageFile(android_vmInfo, AVM_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) { - sprintf(tmp, "cache,size=0x4200000,file=%s", 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) { - sprintf(tmp, "cache,size=0x4200000"); + } + 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*) avmInfo_getImageFile(android_vmInfo, AVM_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) { @@ -2158,7 +2324,7 @@ int main(int argc, char **argv) use_sdcard_img = 1; } } else { - dprint("could not find or access sdcard image at '%s'", opts->sdcard); + D("no SD Card image at '%s'", opts->sdcard); } } @@ -2233,7 +2399,7 @@ int main(int argc, char **argv) } android_qemud_set_channel( ANDROID_QEMUD_GSM, cs); } - else { + 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); @@ -2249,7 +2415,7 @@ int main(int argc, char **argv) } android_qemud_set_channel( ANDROID_QEMUD_GPS, cs); } - else { + 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); @@ -2257,6 +2423,23 @@ int main(int argc, char **argv) } } + 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"; } @@ -2281,6 +2464,18 @@ int main(int argc, char **argv) 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); @@ -2336,6 +2531,10 @@ int main(int argc, char **argv) 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); @@ -2344,6 +2543,10 @@ int main(int argc, char **argv) args[n++] = strdup(params); } + /* physical memory */ + args[n++] = "-m"; + args[n++] = opts->memory; + while(argc-- > 0) { args[n++] = *argv++; } @@ -2380,45 +2583,79 @@ void android_emulation_setup( void ) } #endif - 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 ); + 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); } - if ( (port & 1) != 0 ) { - port &= ~1; - dwarning( "option -port must be followed by an even integer, using port number %d\n", - port ); + + 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); } - base_port = port; - tries = 1; - } - for ( ; tries > 0; tries--, base_port += 2 ) { + if ( console_port == adb_port ) { + derror( "option -ports must be followed by two different integer numbers" ); + exit(1); + } - /* setup first redirection for ADB, the Android Debug Bridge */ - if ( slirp_redir( 0, base_port+1, guest_addr, 5555 ) < 0 ) - continue; + slirp_redir( 0, adb_port, guest_addr, 5555 ); + if ( control_console_start( console_port ) < 0 ) { + slirp_unredir( 0, adb_port ); + } - /* setup second redirection for the emulator console */ - if ( control_console_start( base_port ) < 0 ) { - slirp_unredir( 0, base_port+1 ); - continue; + 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; } - D( "control console listening on port %d, ADB on port %d", base_port, base_port+1 ); - success = 1; - break; - } + for ( ; tries > 0; tries--, base_port += 2 ) { - if (!success) { - fprintf(stderr, "it seems too many emulator instances are running on this machine. Aborting\n" ); - exit(1); + /* setup first redirection for ADB, the Android Debug Bridge */ + if ( slirp_redir( 0, base_port+1, guest_addr, 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) { |