diff options
Diffstat (limited to 'android')
-rw-r--r-- | android/avd/hardware-properties.ini | 4 | ||||
-rw-r--r-- | android/avd/hw-config.c | 78 | ||||
-rw-r--r-- | android/avd/hw-config.h | 7 | ||||
-rw-r--r-- | android/avd/info.c | 248 | ||||
-rw-r--r-- | android/avd/info.h | 9 | ||||
-rw-r--r-- | android/main.c | 2 |
6 files changed, 288 insertions, 60 deletions
diff --git a/android/avd/hardware-properties.ini b/android/avd/hardware-properties.ini index 6b5caae..7d2e7f6 100644 --- a/android/avd/hardware-properties.ini +++ b/android/avd/hardware-properties.ini @@ -57,6 +57,10 @@ description = Whether the device has a QWERTY keyboard. # (I.e. can the qwerty keyboard be closed/hidden or opened/visible) # this will be ignored if hw.keyboard is false # +# NOTE: As a special case, the default value will be 'false' if the +# AVD targets API level 12 or higher. See hwConfig_init() +# in external/qemu/android/avd/hw-config.c for more details. +# name = hw.keyboard.lid type = boolean default = yes diff --git a/android/avd/hw-config.c b/android/avd/hw-config.c index b449bb3..65796d9 100644 --- a/android/avd/hw-config.c +++ b/android/avd/hw-config.c @@ -11,6 +11,7 @@ */ #include "android/avd/hw-config.h" #include "android/utils/ini.h" +#include "android/utils/system.h" #include <string.h> #include <stdlib.h> @@ -18,6 +19,61 @@ /* the global variable containing the hardware config for this device */ AndroidHwConfig android_hw[1]; +static int +stringToBoolean( const char* value ) +{ + if (!strcmp(value,"1") || + !strcmp(value,"yes") || + !strcmp(value,"YES") || + !strcmp(value,"true") || + !strcmp(value,"TRUE")) + { + return 1; + } + else + return 0; +} + +static int64_t +diskSizeToInt64( const char* diskSize ) +{ + char* end; + int64_t value; + + value = strtoll(diskSize, &end, 10); + if (*end == 'k' || *end == 'K') + value *= 1024ULL; + else if (*end == 'm' || *end == 'M') + value *= 1024*1024ULL; + else if (*end == 'g' || *end == 'G') + value *= 1024*1024*1024ULL; + + return value; +} + + +void +androidHwConfig_init( AndroidHwConfig* config, + int apiLevel ) +{ +#define HWCFG_BOOL(n,s,d,a,t) config->n = stringToBoolean(d); +#define HWCFG_INT(n,s,d,a,t) config->n = d; +#define HWCFG_STRING(n,s,d,a,t) config->n = ASTRDUP(d); +#define HWCFG_DOUBLE(n,s,d,a,t) config->n = d; +#define HWCFG_DISKSIZE(n,s,d,a,t) config->n = diskSizeToInt64(d); + +#include "android/avd/hw-config-defs.h" + + /* Special case for hw.keyboard.lid, we need to set the + * default to FALSE for apiLevel >= 12. This allows platform builds + * to get correct orientation emulation even if they don't bring + * a custom hardware.ini + */ + if (apiLevel >= 12) { + config->hw_keyboard_lid = 0; + } +} + int androidHwConfig_read( AndroidHwConfig* config, IniFile* ini ) @@ -27,11 +83,11 @@ androidHwConfig_read( AndroidHwConfig* config, /* use the magic of macros to implement the hardware configuration loaded */ -#define HWCFG_BOOL(n,s,d,a,t) config->n = iniFile_getBoolean(ini, s, d); -#define HWCFG_INT(n,s,d,a,t) config->n = iniFile_getInteger(ini, s, d); -#define HWCFG_STRING(n,s,d,a,t) config->n = iniFile_getString(ini, s, d); -#define HWCFG_DOUBLE(n,s,d,a,t) config->n = iniFile_getDouble(ini, s, d); -#define HWCFG_DISKSIZE(n,s,d,a,t) config->n = iniFile_getDiskSize(ini, s, d); +#define HWCFG_BOOL(n,s,d,a,t) if (iniFile_getValue(ini, s)) { config->n = iniFile_getBoolean(ini, s, d); } +#define HWCFG_INT(n,s,d,a,t) if (iniFile_getValue(ini, s)) { config->n = iniFile_getInteger(ini, s, d); } +#define HWCFG_STRING(n,s,d,a,t) if (iniFile_getValue(ini, s)) { AFREE(config->n); config->n = iniFile_getString(ini, s, d); } +#define HWCFG_DOUBLE(n,s,d,a,t) if (iniFile_getValue(ini, s)) { config->n = iniFile_getDouble(ini, s, d); } +#define HWCFG_DISKSIZE(n,s,d,a,t) if (iniFile_getValue(ini, s)) { config->n = iniFile_getDiskSize(ini, s, d); } #include "android/avd/hw-config-defs.h" @@ -57,3 +113,15 @@ androidHwConfig_write( AndroidHwConfig* config, return 0; } + +void +androidHwConfig_done( AndroidHwConfig* config ) +{ +#define HWCFG_BOOL(n,s,d,a,t) config->n = 0; +#define HWCFG_INT(n,s,d,a,t) config->n = 0; +#define HWCFG_STRING(n,s,d,a,t) AFREE(config->n); +#define HWCFG_DOUBLE(n,s,d,a,t) config->n = 0.0; +#define HWCFG_DISKSIZE(n,s,d,a,t) config->n = 0; + +#include "android/avd/hw-config-defs.h" +} diff --git a/android/avd/hw-config.h b/android/avd/hw-config.h index c79ccad..3c2480a 100644 --- a/android/avd/hw-config.h +++ b/android/avd/hw-config.h @@ -34,6 +34,10 @@ typedef struct { #include "android/avd/hw-config-defs.h" } AndroidHwConfig; +/* Set all default values, based on the target API level */ +void androidHwConfig_init( AndroidHwConfig* hwConfig, + int apiLevel ); + /* reads a hardware configuration file from disk. * returns -1 if the file could not be read, or 0 in case of success. * @@ -50,4 +54,7 @@ int androidHwConfig_read( AndroidHwConfig* hwConfig, int androidHwConfig_write( AndroidHwConfig* hwConfig, IniFile* configFile ); +/* Finalize a given hardware configuration */ +void androidHwConfig_done( AndroidHwConfig* config ); + #endif /* _ANDROID_AVD_HW_CONFIG_H */ diff --git a/android/avd/info.c b/android/avd/info.c index aaf1111..6f7c904 100644 --- a/android/avd/info.c +++ b/android/avd/info.c @@ -149,6 +149,7 @@ struct AvdInfo { IniFile* skinHardwareIni; /* skin-specific hardware.ini */ /* for both */ + int apiLevel; char* skinName; /* skin name */ char* skinDirPath; /* skin directory */ char* coreHardwareIniPath; /* core hardware.ini path */ @@ -348,34 +349,25 @@ _getRootIniPath( 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: +/* 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> * - * ro.product.cpu-abi=<abi> - * - * Where <abi> can be 'armeabi', 'armeabi-v7a' or 'x86'. + * Returns NULL if property <name> is undefined or empty. + * Returned string must be freed by the caller. */ -static const char* -_getBuildTargetArch( const char* androidOut ) +static char* +_getSystemProperty( const char* propFile, const char* propName ) { - const char* arch = "arm"; - char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp); FILE* file; + char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp); + int propNameLen = strlen(propName); + char* result = NULL; -#define ABI_PREFIX "ro.product.cpu.abi=" -#define ABI_PREFIX_LEN (sizeof(ABI_PREFIX)-1) - - p = bufprint(temp, end, "%s/system/build.prop", androidOut); - if (p >= end) { - D("%s: ANDROID_PRODUCT_OUT too long: %s", __FUNCTION__, androidOut); - goto EXIT; - } - file = fopen(temp, "rb"); + file = fopen(propFile, "rb"); if (file == NULL) { D("Could not open file: %s: %s", temp, strerror(errno)); - D("Default target architecture=%s", arch); - goto EXIT; + return NULL; } while (fgets(temp, sizeof temp, file) != NULL) { @@ -393,29 +385,110 @@ _getBuildTargetArch( const char* androidOut ) if (p == end) *--p = '\0'; - if (memcmp(temp, ABI_PREFIX, ABI_PREFIX_LEN) != 0) { + /* check that the line starts with the property name */ + if (memcmp(temp, propName, propNameLen) != 0) { continue; } - p = temp + ABI_PREFIX_LEN; + p = temp + propNameLen; + + /* followed by an equal sign */ + if (p >= end || *p != '=') + continue; + p++; + + /* followed by something */ if (p >= end || !*p) - goto EXIT2; + break; + + result = ASTRDUP(p); + break; + } + fclose(file); + return result; +} - if (!strcmp("armeabi",p)) - arch = "arm"; - else if (!strcmp("armeabi-v7a",p)) - arch = "arm"; +/* 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 - arch = p; + result = cpuAbi; - D("Found target ABI=%s, architecture=%s", p, arch); - goto EXIT2; + D("Found target ABI=%s, architecture=%s", cpuAbi, result); + result = ASTRDUP(result); + AFREE(cpuAbi); } + return result; +} - D("Could not find target architecture, defaulting to %s", arch); -EXIT2: - fclose(file); -EXIT: - return arch; +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. @@ -630,6 +703,76 @@ _avdInfo_getContentPath( AvdInfo* i ) return 0; } +static int +_avdInfo_getApiLevel( AvdInfo* i ) +{ + char* target; + const char* p; + const int defaultLevel = 1000; + int level = defaultLevel; + +# define ROOT_TARGET_KEY "target" + + target = iniFile_getString(i->rootIni, ROOT_TARGET_KEY, NULL); + if (target == NULL) { + D("No target field in root AVD .ini file?"); + D("Defaulting to API level %d", level); + return level; + } + + DD("Found target field in root AVD .ini file: '%s'", target); + + /* There are two acceptable formats for the target key. + * + * 1/ android-<level> + * 2/ <vendor-name>:<add-on-name>:<level> + * + * Where <level> can be either a _name_ (for experimental/preview SDK builds) + * or a decimal number. Note that if a _name_, it can start with a digit. + */ + + /* First, extract the level */ + if (!memcmp(target, "android-", 8)) + p = target + 8; + else { + /* skip two columns */ + p = strchr(target, ':'); + if (p != NULL) { + p = strchr(p+1, ':'); + if (p != NULL) + p += 1; + } + } + if (p == NULL || !isdigit(*p)) { + goto NOT_A_NUMBER; + } else { + char* end; + long val = strtol(p, &end, 10); + if (end == NULL || *end != '\0' || val != (int)val) { + goto NOT_A_NUMBER; + } + level = (int)val; + + /* Sanity check, we don't support anything prior to Android 1.5 */ + if (level < 3) + level = 3; + + D("Found AVD target API level: %d", level); + } +EXIT: + AFREE(target); + return level; + +NOT_A_NUMBER: + if (p == NULL) { + D("Invalid target field in root AVD .ini file"); + } else { + D("Target AVD api level is not a number"); + } + D("Defaulting to API level %d", level); + goto EXIT; +} + /* Look for a named file inside the AVD's content directory. * Returns NULL if it doesn't exist, or a strdup() copy otherwise. */ @@ -803,6 +946,8 @@ avdInfo_new( const char* name, AvdInfoParams* params ) _avdInfo_getCoreHwIniPath(i, i->contentPath) < 0 ) goto FAIL; + i->apiLevel = _avdInfo_getApiLevel(i); + /* look for image search paths. handle post 1.1/pre cupcake * obsolete SDKs. */ @@ -882,7 +1027,8 @@ avdInfo_newForAndroidBuild( const char* androidBuildRoot, i->androidBuildRoot = ASTRDUP(androidBuildRoot); i->androidOut = ASTRDUP(androidOut); i->contentPath = ASTRDUP(androidOut); - i->targetArch = ASTRDUP(_getBuildTargetArch(i->androidOut)); + i->targetArch = _getBuildTargetArch(i->androidOut); + i->apiLevel = _getBuildTargetApiLevel(i->androidOut); /* TODO: find a way to provide better information from the build files */ i->deviceName = ASTRDUP("<build>"); @@ -1052,31 +1198,27 @@ avdInfo_getDataInitImagePath( AvdInfo* i ) } int -avdInfo_getHwConfig( AvdInfo* i, AndroidHwConfig* hw ) +avdInfo_initHwConfig( AvdInfo* i, AndroidHwConfig* hw ) { - IniFile* ini = i->configIni; - int ret; - - if (ini == NULL) - ini = iniFile_newFromMemory("", 0); + int ret = 0; - ret = androidHwConfig_read(hw, ini); + androidHwConfig_init(hw, i->apiLevel); - if (ini != i->configIni) - iniFile_free(ini); + /* First read the config.ini, if any */ + if (i->configIni != NULL) { + ret = androidHwConfig_read(hw, i->configIni); + } + /* The skin's hardware.ini can override values */ if (ret == 0 && i->skinHardwareIni != NULL) { ret = androidHwConfig_read(hw, i->skinHardwareIni); } - /* special product-specific hardware configuration */ - if (i->androidOut != NULL) - { + /* Auto-disable keyboard emulation on sapphire platform builds */ + if (i->androidOut != NULL) { char* p = strrchr(i->androidOut, '/'); - if (p != NULL && p[0] != 0) { - if (p[1] == 's') { - hw->hw_keyboard = 0; - } + if (p != NULL && !strcmp(p,"sapphire")) { + hw->hw_keyboard = 0; } } diff --git a/android/avd/info.h b/android/avd/info.h index aa3ddcd..2469f68 100644 --- a/android/avd/info.h +++ b/android/avd/info.h @@ -130,6 +130,13 @@ void avdInfo_free( AvdInfo* i ); */ const char* avdInfo_getName( AvdInfo* i ); +/* Return the target API level for this AVD. + * Note that this will be some ridiculously large + * value (e.g. 1000) if this value cannot be properly + * determined (e.g. you're using an AVD from a preview SDK) + */ +int avdInfo_getApiLevel( AvdInfo* i ); + /* Returns the path to various images corresponding to a given AVD. * NULL if the image cannot be found. Returned strings must be freed * by the caller. @@ -212,7 +219,7 @@ void avdInfo_getSkinInfo( AvdInfo* i, char** pSkinName, char** pSkinDir int avdInfo_inAndroidBuild( AvdInfo* i ); /* Reads the AVD's hardware configuration into 'hw'. returns -1 on error, 0 otherwise */ -int avdInfo_getHwConfig( AvdInfo* i, AndroidHwConfig* hw ); +int avdInfo_initHwConfig( AvdInfo* i, AndroidHwConfig* hw ); /* Returns a *copy* of the path used to store trace 'foo'. result must be freed by caller */ char* avdInfo_getTracePath( AvdInfo* i, const char* traceName ); diff --git a/android/main.c b/android/main.c index 7b6ea03..0682497 100644 --- a/android/main.c +++ b/android/main.c @@ -305,7 +305,7 @@ int main(int argc, char **argv) /* Read hardware configuration */ hw = android_hw; - if (avdInfo_getHwConfig(avd, hw) < 0) { + if (avdInfo_initHwConfig(avd, hw) < 0) { derror("could not read hardware configuration ?"); exit(1); } |