aboutsummaryrefslogtreecommitdiffstats
path: root/android
diff options
context:
space:
mode:
Diffstat (limited to 'android')
-rw-r--r--android/avd/hardware-properties.ini4
-rw-r--r--android/avd/hw-config.c78
-rw-r--r--android/avd/hw-config.h7
-rw-r--r--android/avd/info.c248
-rw-r--r--android/avd/info.h9
-rw-r--r--android/main.c2
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);
}