blob: 211291b909b7af0f9881d9908b0b859cd8a04866 [file] [log] [blame]
/* 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <android/utils/panic.h>
#include <android/utils/path.h>
#include <android/utils/bufprint.h>
#include <android/avd/util.h>
/* 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 <name>' or '@<name>'
*/
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 <programDir>/emulator-<targetArch>, where <programDir> 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;
}