aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.android13
-rw-r--r--Makefile.common1
-rw-r--r--Makefile.target5
-rw-r--r--android/avd/hardware-properties.ini16
-rw-r--r--android/avd/hw-config-defs.h14
-rw-r--r--android/avd/info.c226
-rw-r--r--android/avd/util.c304
-rw-r--r--android/avd/util.h57
-rw-r--r--android/main-emulator.c169
-rw-r--r--android/utils/path.c86
-rw-r--r--android/utils/path.h9
-rw-r--r--vl-android.c23
12 files changed, 694 insertions, 229 deletions
diff --git a/Makefile.android b/Makefile.android
index 4b6e211..efc6fc3 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -202,6 +202,19 @@ include $(LOCAL_PATH)/Makefile.target
##############################################################################
##############################################################################
###
+### emulator: LAUNCHER FOR TARGET-SPECIFIC EMULATOR
+###
+###
+$(call start-emulator-program, emulator)
+
+LOCAL_SRC_FILES := android/main-emulator.c
+LOCAL_STATIC_LIBRARIES := emulator-common
+
+$(call end-emulator-program)
+
+##############################################################################
+##############################################################################
+###
### emulator-ui: UI FRONT-END PROGRAM
###
###
diff --git a/Makefile.common b/Makefile.common
index 4bdc8ec..05497c8 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -69,6 +69,7 @@ LOCAL_SRC_FILES += \
android/keycode-array.c \
android/avd/hw-config.c \
android/avd/info.c \
+ android/avd/util.c \
android/sync-utils.c \
android/utils/assert.c \
android/utils/bufprint.c \
diff --git a/Makefile.target b/Makefile.target
index 77f08c3..8006c8d 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -289,12 +289,7 @@ $(call end-emulator-program)
###
###
-# Special case, "emulator-arm" is named "emulator" for now.
-ifeq ($(EMULATOR_TARGET_ARCH),arm)
-$(call start-emulator-program, emulator)
-else
$(call start-emulator-program, emulator-$(EMULATOR_TARGET_ARCH))
-endif
LOCAL_STATIC_LIBRARIES := \
emulator-libui \
diff --git a/android/avd/hardware-properties.ini b/android/avd/hardware-properties.ini
index 151d3df..65ba61d 100644
--- a/android/avd/hardware-properties.ini
+++ b/android/avd/hardware-properties.ini
@@ -23,6 +23,22 @@
# the emulator build.
#
+# CPU Architecture
+name = hw.cpu.arch
+type = string
+default = arm
+abstract = CPU Architecture
+description = The CPU Architecture to emulator
+
+# CPU Model
+# Leave it empty, and the default value will be computed from
+# hw.cpu.arch. This is only useful for experimentation for now.
+name = hw.cpu.model
+type = string
+default =
+abstract = CPU model
+description = The CPU model (QEMU-specific string)
+
# Ram size
# Default value will be computed based on screen pixels
# or skin version
diff --git a/android/avd/hw-config-defs.h b/android/avd/hw-config-defs.h
index 6308bd5..bb523d5 100644
--- a/android/avd/hw-config-defs.h
+++ b/android/avd/hw-config-defs.h
@@ -17,6 +17,20 @@
#error HWCFG_DOUBLE not defined
#endif
+HWCFG_STRING(
+ hw_cpu_arch,
+ "hw.cpu.arch",
+ "arm",
+ "CPU Architecture",
+ "The CPU Architecture to emulator")
+
+HWCFG_STRING(
+ hw_cpu_model,
+ "hw.cpu.model",
+ "",
+ "CPU model",
+ "The CPU model (QEMU-specific string)")
+
HWCFG_INT(
hw_ramSize,
"hw.ramSize",
diff --git a/android/avd/info.c b/android/avd/info.c
index 6f7c904..a9fc711 100644
--- a/android/avd/info.c
+++ b/android/avd/info.c
@@ -10,6 +10,7 @@
** GNU General Public License for more details.
*/
#include "android/avd/info.h"
+#include "android/avd/util.h"
#include "android/config/config.h"
#include "android/utils/path.h"
#include "android/utils/bufprint.h"
@@ -63,12 +64,6 @@ AvdInfo* android_avdInfo;
* with one of the usual options.
*/
-/* this is the subdirectory of $HOME/.android where all
- * root configuration files (and default content directories)
- * are located.
- */
-#define ANDROID_AVD_DIR "avd"
-
/* the prefix of config.ini keys that will be used for search directories
* of system images.
*/
@@ -230,50 +225,6 @@ static const char* const _imageFileText[ AVD_IMAGE_MAX ] = {
*****
*****/
-/* Return the path to the Android SDK root installation.
- *
- * (*pFromEnv) will be set to 1 if it comes from the $ANDROID_SDK_ROOT
- * environment variable, or 0 otherwise.
- *
- * Caller must free() returned string.
- */
-static char*
-_getSdkRoot( char *pFromEnv )
-{
- const char* env;
- char* sdkPath;
- char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
-
- /* If ANDROID_SDK_ROOT is defined is must point to a directory
- * containing a valid SDK installation.
- */
-#define SDK_ROOT_ENV "ANDROID_SDK_ROOT"
-
- env = getenv(SDK_ROOT_ENV);
- if (env != NULL && env[0] != 0) {
- if (path_exists(env)) {
- D("found " SDK_ROOT_ENV ": %s", env);
- *pFromEnv = 1;
- return ASTRDUP(env);
- }
- D(SDK_ROOT_ENV " points to unknown directory: %s", env);
- }
-
- *pFromEnv = 0;
-
- /* We assume the emulator binary is under tools/ so use its
- * parent as the Android SDK root.
- */
- (void) bufprint_app_dir(temp, end);
- sdkPath = path_parent(temp, 1);
- if (sdkPath == NULL) {
- derror("can't find root of SDK directory");
- return NULL;
- }
- D("found SDK root at %s", sdkPath);
- return sdkPath;
-}
-
/* Parse a given config.ini file and extract the list of SDK search paths
* from it. Returns the number of valid paths stored in 'searchPaths', or -1
* in case of problem.
@@ -326,171 +277,6 @@ _checkAvdName( const char* name )
return (len == len2);
}
-/* Return the path to the AVD's root configuration .ini file. it is located in
- * ~/.android/avd/<name>.ini or Windows equivalent
- *
- * This file contains the path to the AVD's content directory, which
- * includes its own config.ini.
- */
-static char*
-_getRootIniPath( const char* avdName )
-{
- char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
-
- p = bufprint_config_path(temp, end);
- p = bufprint(p, end, "/" ANDROID_AVD_DIR "/%s.ini", avdName);
- if (p >= end) {
- return NULL;
- }
- if (!path_exists(temp)) {
- return NULL;
- }
- return ASTRDUP(temp);
-}
-
-
-/* Retrieves the value of a given system property defined in a .prop
- * file. This is a text file that contains definitions of the format:
- * <name>=<value>
- *
- * Returns NULL if property <name> is undefined or empty.
- * Returned string must be freed by the caller.
- */
-static char*
-_getSystemProperty( const char* propFile, const char* propName )
-{
- FILE* file;
- char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
- int propNameLen = strlen(propName);
- char* result = NULL;
-
- file = fopen(propFile, "rb");
- if (file == NULL) {
- D("Could not open file: %s: %s", temp, strerror(errno));
- return NULL;
- }
-
- while (fgets(temp, sizeof temp, file) != NULL) {
- /* Trim trailing newlines, if any */
- p = memchr(temp, '\0', sizeof temp);
- if (p == NULL)
- p = end;
- if (p > temp && p[-1] == '\n') {
- *--p = '\0';
- }
- if (p > temp && p[-1] == '\r') {
- *--p = '\0';
- }
- /* force zero-termination in case of full-buffer */
- if (p == end)
- *--p = '\0';
-
- /* check that the line starts with the property name */
- if (memcmp(temp, propName, propNameLen) != 0) {
- continue;
- }
- p = temp + propNameLen;
-
- /* followed by an equal sign */
- if (p >= end || *p != '=')
- continue;
- p++;
-
- /* followed by something */
- if (p >= end || !*p)
- break;
-
- result = ASTRDUP(p);
- break;
- }
- fclose(file);
- return result;
-}
-
-/* Return a build property. This is a system property defined in a file
- * named $ANDROID_PRODUCT_OUT/system/build.prop
- *
- * Returns NULL if undefined or empty. Returned string must be freed
- * by the caller.
- */
-static char*
-_getBuildProperty( const char* androidOut, const char* propName )
-{
- char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
-
- p = bufprint(temp, end, "%s/system/build.prop", androidOut);
- if (p >= end) {
- D("%s: ANDROID_PRODUCT_OUT too long: %s", __FUNCTION__, androidOut);
- return NULL;
- }
- return _getSystemProperty(temp, propName);
-}
-
-/* Retrieves a string corresponding to the target architecture
- * when in the Android platform tree. The only way to do that
- * properly for now is to look at $OUT/system/build.prop:
- *
- * ro.product.cpu-abi=<abi>
- *
- * Where <abi> can be 'armeabi', 'armeabi-v7a' or 'x86'.
- */
-static char*
-_getBuildTargetArch( const char* androidOut )
-{
- const char* defaultArch = "arm";
- char* result = NULL;
- char* cpuAbi = _getBuildProperty(androidOut, "ro.product.cpu.abi");
-
- if (cpuAbi == NULL) {
- D("Coult not find CPU ABI in build properties!");
- D("Default target architecture=%s", defaultArch);
- result = ASTRDUP(defaultArch);
- } else {
- /* Translate ABI to cpu arch if necessary */
- if (!strcmp("armeabi",cpuAbi))
- result = "arm";
- else if (!strcmp("armeabi-v7a", cpuAbi))
- result = "arm";
- else
- result = cpuAbi;
-
- D("Found target ABI=%s, architecture=%s", cpuAbi, result);
- result = ASTRDUP(result);
- AFREE(cpuAbi);
- }
- return result;
-}
-
-static int
-_getBuildTargetApiLevel( const char* androidOut )
-{
- const int defaultLevel = 1000;
- int level = defaultLevel;
- char* sdkVersion = _getBuildProperty(androidOut, "ro.build.version.sdk");
-
- if (sdkVersion != NULL) {
- long value;
- char* end;
- value = strtol(sdkVersion, &end, 10);
- if (end == NULL || *end != '\0' || value != (int)value) {
- D("Invalid SDK version build property: '%s'", sdkVersion);
- D("Defaulting to target API level %d", level);
- } else {
- level = (int)value;
- /* Sanity check, the Android SDK doesn't support anything
- * before Android 1.5, a.k.a API level 3 */
- if (level < 3)
- level = 3;
- D("Found target API level: %d", level);
- }
- AFREE(sdkVersion);
- } else {
- D("Could not find target API level / SDK version in build properties!");
- D("Default target API level: %d", level);
- }
- return level;
-}
-
/* Returns the full path of a given file.
*
* If 'fileName' is an absolute path, this returns a simple copy.
@@ -536,7 +322,7 @@ _checkSkinPath( const char* skinPath )
*/
static char*
_checkSkinSkinsDir( const char* skinDirRoot,
- const char* skinName )
+ const char* skinName )
{
DirScanner* scanner;
char* result;
@@ -649,7 +435,7 @@ static int
_avdInfo_getSdkRoot( AvdInfo* i )
{
- i->sdkRootPath = _getSdkRoot(&i->sdkRootPathFromEnv);
+ i->sdkRootPath = path_getSdkRoot(&i->sdkRootPathFromEnv);
if (i->sdkRootPath == NULL)
return -1;
@@ -662,7 +448,7 @@ _avdInfo_getSdkRoot( AvdInfo* i )
static int
_avdInfo_getRootIni( AvdInfo* i )
{
- char* iniPath = _getRootIniPath( i->deviceName );
+ char* iniPath = path_getRootIniPath( i->deviceName );
if (iniPath == NULL) {
derror("unknown virtual device name: '%s'", i->deviceName);
@@ -1027,8 +813,8 @@ avdInfo_newForAndroidBuild( const char* androidBuildRoot,
i->androidBuildRoot = ASTRDUP(androidBuildRoot);
i->androidOut = ASTRDUP(androidOut);
i->contentPath = ASTRDUP(androidOut);
- i->targetArch = _getBuildTargetArch(i->androidOut);
- i->apiLevel = _getBuildTargetApiLevel(i->androidOut);
+ i->targetArch = path_getBuildTargetArch(i->androidOut);
+ i->apiLevel = path_getBuildTargetApiLevel(i->androidOut);
/* TODO: find a way to provide better information from the build files */
i->deviceName = ASTRDUP("<build>");
diff --git a/android/avd/util.c b/android/avd/util.c
new file mode 100644
index 0000000..fdeb0fe
--- /dev/null
+++ b/android/avd/util.c
@@ -0,0 +1,304 @@
+/* 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.
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include "android/utils/debug.h"
+#include "android/utils/bufprint.h"
+#include "android/utils/ini.h"
+#include "android/utils/panic.h"
+#include "android/utils/path.h"
+#include "android/utils/system.h"
+#include "android/avd/util.h"
+
+#define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
+
+/* this is the subdirectory of $HOME/.android where all
+ * root configuration files (and default content directories)
+ * are located.
+ */
+#define ANDROID_AVD_DIR "avd"
+
+
+/* Return the path to the Android SDK root installation.
+ *
+ * (*pFromEnv) will be set to 1 if it comes from the $ANDROID_SDK_ROOT
+ * environment variable, or 0 otherwise.
+ *
+ * Caller must free() returned string.
+ */
+char*
+path_getSdkRoot( char *pFromEnv )
+{
+ const char* env;
+ char* sdkPath;
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+
+ /* If ANDROID_SDK_ROOT is defined is must point to a directory
+ * containing a valid SDK installation.
+ */
+#define SDK_ROOT_ENV "ANDROID_SDK_ROOT"
+
+ env = getenv(SDK_ROOT_ENV);
+ if (env != NULL && env[0] != 0) {
+ if (path_exists(env)) {
+ D("found " SDK_ROOT_ENV ": %s", env);
+ *pFromEnv = 1;
+ return ASTRDUP(env);
+ }
+ D(SDK_ROOT_ENV " points to unknown directory: %s", env);
+ }
+
+ *pFromEnv = 0;
+
+ /* We assume the emulator binary is under tools/ so use its
+ * parent as the Android SDK root.
+ */
+ (void) bufprint_app_dir(temp, end);
+ sdkPath = path_parent(temp, 1);
+ if (sdkPath == NULL) {
+ derror("can't find root of SDK directory");
+ return NULL;
+ }
+ D("found SDK root at %s", sdkPath);
+ return sdkPath;
+}
+
+
+/* Return the path to the AVD's root configuration .ini file. it is located in
+ * ~/.android/avd/<name>.ini or Windows equivalent
+ *
+ * This file contains the path to the AVD's content directory, which
+ * includes its own config.ini.
+ */
+char*
+path_getRootIniPath( const char* avdName )
+{
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+
+ p = bufprint_config_path(temp, end);
+ p = bufprint(p, end, "/" ANDROID_AVD_DIR "/%s.ini", avdName);
+ if (p >= end) {
+ return NULL;
+ }
+ if (!path_exists(temp)) {
+ return NULL;
+ }
+ return ASTRDUP(temp);
+}
+
+
+char*
+path_getSdkHome(void)
+{
+ const char* sdkHome = getenv("ANDROID_SDK_HOME");
+
+ if (sdkHome == NULL || *sdkHome == '\0') {
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+ p = bufprint_config_path(temp, end);
+ if (p >= end) {
+ APANIC("User path too long!: %s\n", temp);
+ }
+ sdkHome = strdup(temp);
+ } else {
+ sdkHome = strdup(sdkHome);
+ }
+ return (char*)sdkHome;
+}
+
+
+static char*
+_getAvdContentPath(const char* avdName)
+{
+ char* sdkHome = path_getSdkHome();
+ char* avdPath = NULL;
+ IniFile* ini;
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+
+ /* Look for the root .ini file */
+ p = bufprint(temp, end, "%s/avd/%s.ini", sdkHome, avdName);
+ if (p >= end) {
+ APANIC("AVD Name too long: %s\n", avdName);
+ }
+
+ ini = iniFile_newFromFile(temp);
+ if (ini == NULL) {
+ APANIC("Could not open: %s", temp);
+ }
+
+ avdPath = iniFile_getString(ini, "path", NULL);
+
+ iniFile_free(ini);
+ AFREE(sdkHome);
+
+ return avdPath;
+}
+
+
+static char*
+_getAvdTargetArch(const char* avdPath)
+{
+ IniFile* ini;
+ char* targetArch = NULL;
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+ p = bufprint(temp, end, "%s/config.ini", avdPath);
+ if (p >= end) {
+ APANIC("AVD path too long: %s\n", avdPath);
+ }
+ ini = iniFile_newFromFile(temp);
+ if (ini == NULL) {
+ APANIC("Could not open AVD config file: %s", temp);
+ }
+ targetArch = iniFile_getString(ini, "hw.cpu.arch", "arm");
+ iniFile_free(ini);
+
+ return targetArch;
+}
+
+char*
+path_getAvdTargetArch( const char* avdName )
+{
+ char* avdPath = _getAvdContentPath(avdName);
+ char* avdArch = _getAvdTargetArch(avdPath);
+
+ return avdArch;
+}
+
+/* Retrieves the value of a given system property defined in a .prop
+ * file. This is a text file that contains definitions of the format:
+ * <name>=<value>
+ *
+ * Returns NULL if property <name> is undefined or empty.
+ * Returned string must be freed by the caller.
+ */
+static char*
+_getSystemProperty( const char* propFile, const char* propName )
+{
+ FILE* file;
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+ int propNameLen = strlen(propName);
+ char* result = NULL;
+
+ file = fopen(propFile, "rb");
+ if (file == NULL) {
+ D("Could not open file: %s: %s", temp, strerror(errno));
+ return NULL;
+ }
+
+ while (fgets(temp, sizeof temp, file) != NULL) {
+ /* Trim trailing newlines, if any */
+ p = memchr(temp, '\0', sizeof temp);
+ if (p == NULL)
+ p = end;
+ if (p > temp && p[-1] == '\n') {
+ *--p = '\0';
+ }
+ if (p > temp && p[-1] == '\r') {
+ *--p = '\0';
+ }
+ /* force zero-termination in case of full-buffer */
+ if (p == end)
+ *--p = '\0';
+
+ /* check that the line starts with the property name */
+ if (memcmp(temp, propName, propNameLen) != 0) {
+ continue;
+ }
+ p = temp + propNameLen;
+
+ /* followed by an equal sign */
+ if (p >= end || *p != '=')
+ continue;
+ p++;
+
+ /* followed by something */
+ if (p >= end || !*p)
+ break;
+
+ result = ASTRDUP(p);
+ break;
+ }
+ fclose(file);
+ return result;
+}
+
+static char*
+_getBuildProperty( const char* androidOut, const char* propName )
+{
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+
+ p = bufprint(temp, end, "%s/system/build.prop", androidOut);
+ if (p >= end) {
+ D("%s: ANDROID_PRODUCT_OUT too long: %s", __FUNCTION__, androidOut);
+ return NULL;
+ }
+ return _getSystemProperty(temp, propName);
+}
+
+char*
+path_getBuildTargetArch( const char* androidOut )
+{
+ const char* defaultArch = "arm";
+ char* result = NULL;
+ char* cpuAbi = _getBuildProperty(androidOut, "ro.product.cpu.abi");
+
+ if (cpuAbi == NULL) {
+ D("Coult not find CPU ABI in build properties!");
+ D("Default target architecture=%s", defaultArch);
+ result = ASTRDUP(defaultArch);
+ } else {
+ /* Translate ABI to cpu arch if necessary */
+ if (!strcmp("armeabi",cpuAbi))
+ result = "arm";
+ else if (!strcmp("armeabi-v7a", cpuAbi))
+ result = "arm";
+ else
+ result = cpuAbi;
+
+ D("Found target ABI=%s, architecture=%s", cpuAbi, result);
+ result = ASTRDUP(result);
+ AFREE(cpuAbi);
+ }
+ return result;
+}
+
+
+int
+path_getBuildTargetApiLevel( const char* androidOut )
+{
+ const int defaultLevel = 1000;
+ int level = defaultLevel;
+ char* sdkVersion = _getBuildProperty(androidOut, "ro.build.version.sdk");
+
+ if (sdkVersion != NULL) {
+ long value;
+ char* end;
+ value = strtol(sdkVersion, &end, 10);
+ if (end == NULL || *end != '\0' || value != (int)value) {
+ D("Invalid SDK version build property: '%s'", sdkVersion);
+ D("Defaulting to target API level %d", level);
+ } else {
+ level = (int)value;
+ /* Sanity check, the Android SDK doesn't support anything
+ * before Android 1.5, a.k.a API level 3 */
+ if (level < 3)
+ level = 3;
+ D("Found target API level: %d", level);
+ }
+ AFREE(sdkVersion);
+ } else {
+ D("Could not find target API level / SDK version in build properties!");
+ D("Default target API level: %d", level);
+ }
+ return level;
+}
+
diff --git a/android/avd/util.h b/android/avd/util.h
new file mode 100644
index 0000000..27f8f28
--- /dev/null
+++ b/android/avd/util.h
@@ -0,0 +1,57 @@
+/* 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.
+*/
+#ifndef _ANDROID_AVD_UTIL_H
+#define _ANDROID_AVD_UTIL_H
+
+/* A collection of simple functions to extract relevant AVD-related
+ * information either from an SDK AVD or a platform build.
+ */
+
+/* Return the path to the Android SDK root installation.
+ *
+ * (*pFromEnv) will be set to 1 if it comes from the $ANDROID_SDK_ROOT
+ * environment variable, or 0 otherwise.
+ *
+ * Caller must free() returned string.
+ */
+char* path_getSdkRoot( char *pFromEnv );
+
+/* Return the path to the AVD's root configuration .ini file. it is located in
+ * ~/.android/avd/<name>.ini or Windows equivalent
+ *
+ * This file contains the path to the AVD's content directory, which
+ * includes its own config.ini.
+ */
+char* path_getRootIniPath( const char* avdName );
+
+/* Return the target architecture for a given AVD.
+ * Called must free() returned string.
+ */
+char* path_getAvdTargetArch( const char* avdName );
+
+/* Retrieves a string corresponding to the target architecture
+ * when in the Android platform tree. The only way to do that
+ * properly for now is to look at $OUT/system/build.prop:
+ *
+ * ro.product.cpu-abi=<abi>
+ *
+ * Where <abi> can be 'armeabi', 'armeabi-v7a' or 'x86'.
+ */
+char* path_getBuildTargetArch( const char* androidOut );
+
+/* Retrieve the target API level when in the Android platform tree.
+ * This can be a very large number like 1000 if the value cannot
+ * be extracted from the appropriate file
+ */
+int path_getBuildTargetApiLevel( const char* androidOut );
+
+#endif /* _ANDROID_AVD_UTIL_H */
diff --git a/android/main-emulator.c b/android/main-emulator.c
new file mode 100644
index 0000000..211291b
--- /dev/null
+++ b/android/main-emulator.c
@@ -0,0 +1,169 @@
+/* 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;
+}
diff --git a/android/utils/path.c b/android/utils/path.c
index e7ef2b0..f64e517 100644
--- a/android/utils/path.c
+++ b/android/utils/path.c
@@ -265,6 +265,14 @@ path_can_write( const char* path )
return (ret == 0);
}
+ABool
+path_can_exec( const char* path )
+{
+ int ret;
+ CHECKED(ret, access(path, X_OK));
+ return (ret == 0);
+}
+
/* try to make a directory. returns 0 on success, -1 on failure
* (error code in errno) */
APosixStatus
@@ -325,7 +333,7 @@ path_mkdir_recursive( char* path, unsigned len, int mode )
return ret;
}
-/* ensure that a given directory exists, create it if not,
+/* ensure that a given directory exists, create it if not,
0 on success, -1 on failure (error code in errno) */
APosixStatus
path_mkdir_if_needed( const char* path, int mode )
@@ -363,9 +371,9 @@ path_get_size( const char* path, uint64_t *psize )
/* result in getting the size of a different file */
LARGE_INTEGER size;
HANDLE file = CreateFile( /* lpFilename */ path,
- /* dwDesiredAccess */ GENERIC_READ,
- /* dwSharedMode */ FILE_SHARE_READ|FILE_SHARE_WRITE,
- /* lpSecurityAttributes */ NULL,
+ /* dwDesiredAccess */ GENERIC_READ,
+ /* dwSharedMode */ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ /* lpSecurityAttributes */ NULL,
/* dwCreationDisposition */ OPEN_EXISTING,
/* dwFlagsAndAttributes */ 0,
/* hTemplateFile */ NULL );
@@ -564,3 +572,73 @@ path_load_file(const char *fn, size_t *pSize)
return NULL;
}
+#ifdef _WIN32
+# define DIR_SEP ';'
+#else
+# define DIR_SEP ':'
+#endif
+
+char*
+path_search_exec( const char* filename )
+{
+ const char* sysPath = getenv("PATH");
+ char temp[PATH_MAX];
+ int count;
+ int slen;
+ const char* p;
+
+ /* If the file contains a directory separator, don't search */
+#ifdef _WIN32
+ if (strchr(filename, '/') != NULL || strchr(filename, '\\') != NULL) {
+#else
+ if (strchr(filename, '/') != NULL) {
+#endif
+ if (path_exists(filename)) {
+ return strdup(filename);
+ } else {
+ return NULL;
+ }
+ }
+
+ /* If system path is empty, don't search */
+ if (sysPath == NULL || sysPath[0] == '\0') {
+ return NULL;
+ }
+
+ /* Count the number of non-empty items in the system path
+ * Items are separated by DIR_SEP, and two successive separators
+ * correspond to an empty item that will be ignored.
+ * Also compute the required string storage length. */
+ count = 0;
+ slen = 0;
+ p = sysPath;
+
+ while (*p) {
+ char* p2 = strchr(p, DIR_SEP);
+ int len;
+ if (p2 == NULL) {
+ len = strlen(p);
+ } else {
+ len = p2 - p;
+ }
+
+ do {
+ if (len <= 0)
+ break;
+
+ snprintf(temp, sizeof(temp), "%.*s/%s", len, p, filename);
+
+ if (path_exists(temp) && path_can_exec(temp)) {
+ return strdup(temp);
+ }
+
+ } while (0);
+
+ p += len;
+ if (*p == DIR_SEP)
+ p++;
+ }
+
+ /* Nothing, really */
+ return NULL;
+}
diff --git a/android/utils/path.h b/android/utils/path.h
index e15e6ed..419e6bf 100644
--- a/android/utils/path.h
+++ b/android/utils/path.h
@@ -64,6 +64,9 @@ extern ABool path_is_absolute( const char* path );
extern ABool path_can_read( const char* path );
extern ABool path_can_write( const char* path );
+/* checks that one can execute a given file */
+extern ABool path_can_exec( const char* path );
+
/* try to make a directory */
extern APosixStatus path_mkdir( const char* path, int mode );
@@ -109,6 +112,12 @@ extern char* path_dirname( const char* path );
*/
extern char* path_basename( const char* path );
+/* look for a given executable in the system path and return its full path.
+ * Returns NULL if not found. Note that on Windows this doesn't not append
+ * an .exe prefix, or other magical thing like Cygwin usually does.
+ */
+extern char* path_search_exec( const char* filename );
+
/** OTHER FILE UTILITIES
**
** path_empty_file() creates an empty file at a given path location.
diff --git a/vl-android.c b/vl-android.c
index 6653286..abfa423 100644
--- a/vl-android.c
+++ b/vl-android.c
@@ -5629,6 +5629,29 @@ int main(int argc, char **argv, char **envp)
}
#endif
+ /* Check the CPU Architecture value */
+#if defined(TARGET_ARM)
+ if (strcmp(android_hw->hw_cpu_arch,"arm") != 0) {
+ fprintf(stderr, "-- Invalid CPU architecture: %s, expected 'arm'\n",
+ android_hw->hw_cpu_arch);
+ exit(1);
+ }
+#elif defined(TARGET_X86)
+ if (strcmp(android_hw->hw_cpu_arch,"x86") != 0) {
+ fprintf(stderr, "-- Invalid CPU architecture: %s, expected 'x86'\n",
+ android_hw->hw_cpu_arch);
+ exit(1);
+ }
+#endif
+
+ /* Grab CPU model if provided in hardware.ini */
+ if ( !cpu_model
+ && android_hw->hw_cpu_model
+ && android_hw->hw_cpu_model[0] != '\0')
+ {
+ cpu_model = android_hw->hw_cpu_model;
+ }
+
/* Combine kernel command line passed from the UI with parameters
* collected during initialization.
*