/* Copyright (C) 2011 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. */ /* This is the source code to the tiny "emulator" launcher program * that is in charge of starting the target-specific emulator binary * for a given AVD, i.e. either 'emulator-arm' or 'emulator-x86' * * This program will be replaced in the future by what is currently * known as 'emulator-ui', but is a good placeholder until this * migration is completed. */ #include #include #include #include #include #include #include #include #include /* Required by android/utils/debug.h */ int android_verbose; #define DEBUG 1 #if DEBUG # define D(...) do { if (android_verbose) printf("emulator:" __VA_ARGS__); } while (0) #else # define D(...) do{}while(0) #endif /* Forward declarations */ static char* getTargetEmulatorPath(const char* progName, const char* avdArch); /* Main routine */ int main(int argc, char** argv) { const char* avdName = NULL; char* avdArch = NULL; char* emulatorPath; /* Define ANDROID_EMULATOR_DEBUG to 1 in your environment if you want to * see the debug messages from this launcher program. */ const char* debug = getenv("ANDROID_EMULATOR_DEBUG"); if (debug != NULL && *debug && *debug != '0') android_verbose = 1; /* Parse command-line and look for an avd name * Either in the form or '-avd ' or '@' */ int nn; for (nn = 1; nn < argc; nn++) { const char* opt = argv[nn]; if (!strcmp(opt,"-qemu")) break; if (!strcmp(opt,"-avd") && nn+1 < argc) { avdName = argv[nn+1]; break; } else if (opt[0] == '@' && opt[1] != '\0') { avdName = opt+1; break; } } /* If there is an AVD name, we're going to extract its target architecture * by looking at its config.ini */ if (avdName != NULL) { D("Found AVD name '%s'\n", avdName); avdArch = path_getAvdTargetArch(avdName); D("Found AVD target architecture: %s\n", avdArch); } else { /* Otherwise, using the ANDROID_PRODUCT_OUT directory */ const char* androidOut = getenv("ANDROID_PRODUCT_OUT"); if (androidOut != NULL && *androidOut != '\0') { D("Found ANDROID_PRODUCT_OUT: %s\n", androidOut); avdArch = path_getBuildTargetArch(androidOut); D("Found build target architecture: %s\n", avdArch); } } if (avdArch == NULL) { avdArch = "arm"; D("Can't determine target AVD architecture: defaulting to %s\n", avdArch); } /* Find the architecture-specific program in the same directory */ emulatorPath = getTargetEmulatorPath(argv[0], avdArch); D("Found target-specific emulator binary: %s\n", emulatorPath); /* Replace it in our command-line */ argv[0] = emulatorPath; /* Launch it with the same set of options ! */ /* execv() should be available on Windows with mingw32 */ execv(emulatorPath, argv); /* We could not launch the program ! */ fprintf(stderr, "Could not launch '%s': %s\n", emulatorPath, strerror(errno)); return errno; } /* Find the target-specific emulator binary. This will be something * like /emulator-, where is * the directory of the current program. */ static char* getTargetEmulatorPath(const char* progName, const char* avdArch) { char* progDir; char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp); #ifdef _WIN32 const char* exeExt = ".exe"; #else const char* exeExt = ""; #endif /* Get program's directory name in progDir */ path_split(progName, &progDir, NULL); p = bufprint(temp, end, "%s/emulator-%s%s", progDir, avdArch, exeExt); free(progDir); if (p >= end) { APANIC("Path too long: %s\n", progName); } if (path_exists(temp)) { return strdup(temp); } /* Mmm, the file doesn't exist, If there is no slash / backslash * in our path, we're going to try to search it in our path. */ #ifdef _WIN32 if (strchr(progName, '/') == NULL && strchr(progName, '\\') == NULL) { #else if (strchr(progName, '/') == NULL) { #endif p = bufprint(temp, end, "emulator-%s%s", avdArch, exeExt); if (p < end) { char* resolved = path_search_exec(temp); if (resolved != NULL) return resolved; } } /* Otherwise, the program is missing */ APANIC("Missing arch-specific emulator program: %s\n", temp); return NULL; }