diff options
author | David 'Digit' Turner <digit@android.com> | 2011-05-03 09:16:46 -0700 |
---|---|---|
committer | Android Code Review <code-review@android.com> | 2011-05-03 09:16:46 -0700 |
commit | d0f48c07a5bc47fb461aa5dc4e41e8d6798c8ccc (patch) | |
tree | c7323ffd476368c10c91f3ec12f3f66a766f33d2 /android/avd/util.c | |
parent | c9154bef9c32ddf269b078dd15d153fe1be1fa42 (diff) | |
parent | a3703225151c95a32017e66a3b56229059d78626 (diff) | |
download | external_qemu-d0f48c07a5bc47fb461aa5dc4e41e8d6798c8ccc.zip external_qemu-d0f48c07a5bc47fb461aa5dc4e41e8d6798c8ccc.tar.gz external_qemu-d0f48c07a5bc47fb461aa5dc4e41e8d6798c8ccc.tar.bz2 |
Merge "Add 'emulator' launcher program." into tools_r11
Diffstat (limited to 'android/avd/util.c')
-rw-r--r-- | android/avd/util.c | 304 |
1 files changed, 304 insertions, 0 deletions
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; +} + |