diff options
author | David 'Digit' Turner <digit@android.com> | 2011-03-22 16:07:01 +0100 |
---|---|---|
committer | David 'Digit' Turner <digit@android.com> | 2011-03-22 16:11:08 +0100 |
commit | b64325d15d9e767c652491414c95f4fc148b0211 (patch) | |
tree | 4ea0f1174402e60adb5ec27615ca7d9af5118a28 /android | |
parent | 13705e8b2182da3e2d13bea5d074db77f4a92ab1 (diff) | |
download | external_qemu-b64325d15d9e767c652491414c95f4fc148b0211.zip external_qemu-b64325d15d9e767c652491414c95f4fc148b0211.tar.gz external_qemu-b64325d15d9e767c652491414c95f4fc148b0211.tar.bz2 |
Set hw.keyboard.lid default value to false for API level >= 12
This patch modifies the emulator to extract the target API level for
the AVD or the current platform release, and use it to set the
default value of hw.keyboard.lid.
This will *not* affect any existing AVD/platform that sets the value
explicitely in its config.ini (for AVDs) or hardware.ini (for platform
builds).
The change is beneficial for platform builds targetting API level >= 12,
because the input framework changed its the window orientation behaviour
depending on the availability of a hardware lid.
In short, this allows platform builds to be correctly oriented, even
if they don't provide a custom hardware.ini.
Fix for bug 4128604
Change-Id: I195135aae6f3c4cc11d2f01e1293f3cd6cad2f58
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); } |