merge from tools_r13

Change-Id: Ia71bb88cacb09eccdc6281897bcc324487a23b01
diff --git a/Makefile.android b/Makefile.android
index 4139226..01cb35b 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -55,7 +55,7 @@
 endif
 
 ifeq ($(HOST_OS),windows)
-  MY_CFLAGS += -D_WIN32 -mno-cygwin
+  MY_CFLAGS += -D_WIN32
   # we need Win32 features  that are available since Windows 2000 Professional/Server (NT 5.0)
   MY_CFLAGS += -DWINVER=0x501
 endif
@@ -149,17 +149,17 @@
     $(eval LOCAL_LDLIBS := $(MY_LDLIBS)) \
     $(eval LOCAL_MODULE_TAGS := debug) \
     $(eval LOCAL_MODULE := $1) \
+    $(eval LOCAL_MODULE_CLASS := STATIC_LIBRARIES)
 
 # Used with start-emulator-library
 end-emulator-library = \
-    $(eval include $(BUILD_HOST_STATIC_LIBRARY)) \
-    $(eval EMULATOR_MODULE_TYPE := STATIC_LIBRARY)
+    $(eval include $(BUILD_HOST_STATIC_LIBRARY))
 
 # A variant of start-emulator-library to start the definition of a host
 # program instead. Use with end-emulator-program
 start-emulator-program = \
     $(call start-emulator-library,$1) \
-    $(eval EMULATOR_MODULE_TYPE := EXECUTABLES)
+    $(eval LOCAL_MODULE_CLASS := EXECUTABLES)
 
 # A varient of end-emulator-library for host programs instead
 end-emulator-program = \
@@ -242,6 +242,7 @@
     android/snapshot.c \
     android/main-common.c \
     android/main.c \
+    android/utils/setenv.c \
     vl-android-ui.c \
     android/protocol/core-connection.c \
     android/protocol/attach-ui-impl.c \
@@ -250,6 +251,8 @@
     android/protocol/core-commands-proxy.c \
     android/protocol/user-events-proxy.c \
 
+$(call gen-hw-config-defs,android/main-common.c)
+
 LOCAL_SRC_FILES += $(SDLMAIN_SOURCES)
 
 LOCAL_STATIC_LIBRARIES += $(SDL_STATIC_LIBRARIES)
diff --git a/Makefile.common b/Makefile.common
index 222a1ae..93f15be 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -13,6 +13,42 @@
 ##############################################################################
 ##############################################################################
 ###
+###  gen-hw-config-defs: Generate hardware configuration definitions header
+###
+###  The 'gen-hw-config.py' script is used to generate the hw-config-defs.h
+###  header from the an .ini file like android/avd/hardware-properties.ini
+###
+###  Due to the way the Android build system works, we need to regenerate
+###  it for each module (the output will go into a module-specific directory).
+###
+###  This defines a function that can be used inside a module definition
+###
+###  $(call gen-hw-config-defs)
+###
+
+# First, define a rule to generate a dummy "emulator_hw_config_defs" module
+# which purpose is simply to host the generated header in its output directory.
+intermediates := $(call intermediates-dir-for,SHARED_LIBRARIES,emulator_hw_config_defs,true)
+
+QEMU_HARDWARE_PROPERTIES_INI := $(LOCAL_PATH)/android/avd/hardware-properties.ini
+QEMU_HW_CONFIG_DEFS_H := $(intermediates)/android/avd/hw-config-defs.h
+$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_PATH := $(LOCAL_PATH)
+$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/android/tools/gen-hw-config.py $< $@
+$(QEMU_HW_CONFIG_DEFS_H): $(QEMU_HARDWARE_PROPERTIES_INI) $(LOCAL_PATH)/android/tools/gen-hw-config.py
+	$(hide) rm -f $@
+	$(transform-generated-source)
+
+QEMU_HW_CONFIG_DEFS_INCLUDES := $(intermediates)
+
+# Second, define a function that needs to be called inside each module that contains
+# a source file that includes the generated header file.
+gen-hw-config-defs = \
+  $(eval LOCAL_GENERATED_SOURCES += $(QEMU_HW_CONFIG_DEFS_H))\
+  $(eval LOCAL_C_INCLUDES += $(QEMU_HW_CONFIG_DEFS_INCLUDES))
+
+##############################################################################
+##############################################################################
+###
 ###  emulator-common: LIBRARY OF COMMON FUNCTIONS
 ###
 ###  THESE ARE POTENTIALLY USED BY ALL COMPONENTS
@@ -90,6 +126,8 @@
 	android/utils/tempfile.c \
 	android/utils/vector.c \
 
+$(call gen-hw-config-defs)
+
 LOCAL_CFLAGS += $(EMULATOR_COMMON_CFLAGS)
 
 $(call end-emulator-library)
@@ -215,6 +253,8 @@
              android/qemulator.c \
              android/keycode.c \
 
+$(call gen-hw-config-defs)
+
 # enable MMX code for our skin scaler
 ifeq ($(HOST_ARCH),x86)
 LOCAL_CFLAGS += -DUSE_MMX=1 -mmmx
@@ -383,6 +423,8 @@
     android/snapshot.c \
     android/utils/timezone.c \
 
+$(call gen-hw-config-defs)
+
 ifeq ($(HOST_ARCH),x86)
     CORE_MISC_SOURCES += i386-dis.c
 endif
@@ -475,19 +517,6 @@
     qlist.c \
     qstring.c \
 
-# hw-config-defs.h is generated from android/avd/hardware-properties.ini
-#
-QEMU_HARDWARE_PROPERTIES_INI := $(LOCAL_PATH)/android/avd/hardware-properties.ini
-QEMU_HW_CONFIG_DEFS_H := $(LOCAL_PATH)/android/avd/hw-config-defs.h
-$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_PATH := $(LOCAL_PATH)
-$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_SOURCES := $(QEMU_HARDWARE_PROPERTIES_INI)
-$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/android/tools/gen-hw-config.py $(QEMU_HARDWARE_PROPERTIES_INI) $@
-$(QEMU_HW_CONFIG_DEFS_H): $(QEMU_HARDWARE_PROPERTIES_INI) $(LOCAL_PATH)/android/tools/gen-hw-config.py
-	$(hide) rm -f $@
-	$(transform-generated-source)
-
-$(LOCAL_PATH)/android/avd/hw-config.h: $(QEMU_HW_CONFIG_DEFS_H)
-
 # gdbstub-xml.c contains C-compilable arrays corresponding to the content
 # of $(LOCAL_PATH)/gdb-xml/, and is generated with the 'feature_to_c.sh' script.
 #
@@ -603,7 +632,7 @@
 gen-hx-header = $(eval $(call gen-hx-header-ev,$1,$2,$3))
 
 define gen-hx-header-ev
-intermediates := $$(call intermediates-dir-for,$$(EMULATOR_MODULE_TYPE),$$(LOCAL_MODULE),true)
+intermediates := $$(call intermediates-dir-for,$$(LOCAL_MODULE_CLASS),$$(LOCAL_MODULE),true)
 
 QEMU_HEADER_H := $$(intermediates)/$$2
 $$(QEMU_HEADER_H): PRIVATE_PATH := $$(LOCAL_PATH)
@@ -613,7 +642,5 @@
 
 LOCAL_GENERATED_SOURCES += $$(QEMU_HEADER_H)
 LOCAL_C_INCLUDES += $$(intermediates)
-_objects := $$(patsubst %,$$(intermediates)/%,$$(3:.c=.o))
-$$(_objects): $$(QEMU_HEADER_H)
 endef
 
diff --git a/Makefile.target b/Makefile.target
index 5f7a8b2..ccc86b4 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -86,6 +86,8 @@
     usb.c \
     watchdog.c
 
+$(call gen-hw-config-defs)
+
 ifeq ($(EMULATOR_TARGET_ARCH),arm)
 HW_SOURCES += android_arm.c \
     arm_pic.c \
@@ -277,6 +279,7 @@
 
 $(call gen-hx-header,qemu-monitor.hx,qemu-monitor.h,monitor.c)
 $(call gen-hx-header,qemu-options.hx,qemu-options.def,vl-android.c qemu-options.h)
+$(call gen-hw-config-defs)
 
 ifeq ($(HOST_OS),darwin)
     FRAMEWORKS := OpenGL Cocoa QuickTime ApplicationServices Carbon IOKit
@@ -356,6 +359,7 @@
 
 $(call gen-hx-header,qemu-monitor.hx,qemu-monitor.h,monitor.c)
 $(call gen-hx-header,qemu-options.hx,qemu-options.def,vl-android.c qemu-options.h)
+$(call gen-hw-config-defs)
 
 # The following files cannot be in static libraries because they contain
 # constructor functions that are otherwise stripped by the final linker
diff --git a/android/avd/hardware-properties.ini b/android/avd/hardware-properties.ini
index dabf166..0e650bb 100644
--- a/android/avd/hardware-properties.ini
+++ b/android/avd/hardware-properties.ini
@@ -83,6 +83,18 @@
 abstract    = Keyboard lid support
 description = Whether the QWERTY keyboard can be opened/closed.
 
+# The name of the hardware charmap for this device.
+#
+# NOTE: This should always be the default 'qwerty2' unless you have
+#        modified the system image accordingly. This name is sent to
+#        the kernel at boot time. Using an incorrect name will result
+#        in an unusable machine.
+name        = hw.keyboard.charmap
+type        = string
+default     = qwerty2
+abstract    = Keyboard charmap name
+description = Name of the system keyboard charmap file.
+
 # DPad keys
 name        = hw.dPad
 type        = boolean
diff --git a/android/avd/hw-config-defs.h b/android/avd/hw-config-defs.h
deleted file mode 100644
index bb523d5..0000000
--- a/android/avd/hw-config-defs.h
+++ /dev/null
@@ -1,305 +0,0 @@
-/* this file is automatically generated from 'hardware-properties.ini'
- * DO NOT EDIT IT. To re-generate it, use android/tools/gen-hw-config.py'
- */
-#ifndef HWCFG_INT
-#error  HWCFG_INT not defined
-#endif
-#ifndef HWCFG_BOOL
-#error  HWCFG_BOOL not defined
-#endif
-#ifndef HWCFG_DISKSIZE
-#error  HWCFG_DISKSIZE not defined
-#endif
-#ifndef HWCFG_STRING
-#error  HWCFG_STRING not defined
-#endif
-#ifndef HWCFG_DOUBLE
-#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",
-  0,
-  "Device ram size",
-  "The amount of physical RAM on the device, in megabytes.")
-
-HWCFG_BOOL(
-  hw_touchScreen,
-  "hw.touchScreen",
-  "yes",
-  "Touch-screen support",
-  "Whether there is a touch screen or not on the device.")
-
-HWCFG_BOOL(
-  hw_trackBall,
-  "hw.trackBall",
-  "yes",
-  "Track-ball support",
-  "Whether there is a trackball on the device.")
-
-HWCFG_BOOL(
-  hw_keyboard,
-  "hw.keyboard",
-  "yes",
-  "Keyboard support",
-  "Whether the device has a QWERTY keyboard.")
-
-HWCFG_BOOL(
-  hw_keyboard_lid,
-  "hw.keyboard.lid",
-  "yes",
-  "Keyboard lid support",
-  "Whether the QWERTY keyboard can be opened/closed.")
-
-HWCFG_BOOL(
-  hw_dPad,
-  "hw.dPad",
-  "yes",
-  "DPad support",
-  "Whether the device has DPad keys")
-
-HWCFG_BOOL(
-  hw_gsmModem,
-  "hw.gsmModem",
-  "yes",
-  "GSM modem support",
-  "Whether there is a GSM modem in the device.")
-
-HWCFG_BOOL(
-  hw_camera,
-  "hw.camera",
-  "no",
-  "Camera support",
-  "Whether the device has a camera.")
-
-HWCFG_INT(
-  hw_camera_maxHorizontalPixels,
-  "hw.camera.maxHorizontalPixels",
-  640,
-  "Maximum horizontal camera pixels",
-  "")
-
-HWCFG_INT(
-  hw_camera_maxVerticalPixels,
-  "hw.camera.maxVerticalPixels",
-  480,
-  "Maximum vertical camera pixels",
-  "")
-
-HWCFG_BOOL(
-  hw_gps,
-  "hw.gps",
-  "yes",
-  "GPS support",
-  "Whether there is a GPS in the device.")
-
-HWCFG_BOOL(
-  hw_battery,
-  "hw.battery",
-  "yes",
-  "Battery support",
-  "Whether the device can run on a battery.")
-
-HWCFG_BOOL(
-  hw_accelerometer,
-  "hw.accelerometer",
-  "yes",
-  "Accelerometer",
-  "Whether there is an accelerometer in the device.")
-
-HWCFG_BOOL(
-  hw_audioInput,
-  "hw.audioInput",
-  "yes",
-  "Audio recording support",
-  "Whether the device can record audio")
-
-HWCFG_BOOL(
-  hw_audioOutput,
-  "hw.audioOutput",
-  "yes",
-  "Audio playback support",
-  "Whether the device can play audio")
-
-HWCFG_BOOL(
-  hw_sdCard,
-  "hw.sdCard",
-  "yes",
-  "SD Card support",
-  "Whether the device supports insertion/removal of virtual SD Cards.")
-
-HWCFG_STRING(
-  hw_sdCard_path,
-  "hw.sdCard.path",
-  "",
-  "SD Card image path",
-  "")
-
-HWCFG_BOOL(
-  disk_cachePartition,
-  "disk.cachePartition",
-  "yes",
-  "Cache partition support",
-  "Whether we use a /cache partition on the device.")
-
-HWCFG_STRING(
-  disk_cachePartition_path,
-  "disk.cachePartition.path",
-  "",
-  "Cache partition",
-  "Cache partition to use on the device. Ignored if disk.cachePartition is not 'yes'.")
-
-HWCFG_DISKSIZE(
-  disk_cachePartition_size,
-  "disk.cachePartition.size",
-  "66MB",
-  "Cache partition size",
-  "")
-
-HWCFG_INT(
-  hw_lcd_width,
-  "hw.lcd.width",
-  320,
-  "LCD pixel width",
-  "")
-
-HWCFG_INT(
-  hw_lcd_height,
-  "hw.lcd.height",
-  640,
-  "LCD pixel height",
-  "")
-
-HWCFG_INT(
-  hw_lcd_depth,
-  "hw.lcd.depth",
-  16,
-  "LCD color depth",
-  "Must be 16 or 32. Color bit depth of emulated framebuffer.")
-
-HWCFG_INT(
-  hw_lcd_density,
-  "hw.lcd.density",
-  160,
-  "Abstracted LCD density",
-  "Must be one of 120, 160 or 240. A value used to roughly describe the density of the LCD screen for automatic resource/asset selection.")
-
-HWCFG_BOOL(
-  hw_lcd_backlight,
-  "hw.lcd.backlight",
-  "yes",
-  "LCD backlight",
-  "Enable/Disable LCD backlight simulation,yes-enabled,no-disabled.")
-
-HWCFG_INT(
-  vm_heapSize,
-  "vm.heapSize",
-  0,
-  "Max VM application heap size",
-  "The maximum heap size a Dalvik application might allocate before being killed by the system. Value is in megabytes.")
-
-HWCFG_BOOL(
-  hw_sensors_proximity,
-  "hw.sensors.proximity",
-  "yes",
-  "Proximity support",
-  "Whether there is an proximity in the device.")
-
-HWCFG_STRING(
-  kernel_path,
-  "kernel.path",
-  "",
-  "Path to the kernel image",
-  "Path to the kernel image.")
-
-HWCFG_STRING(
-  kernel_parameters,
-  "kernel.parameters",
-  "",
-  "kernel boot parameters string.",
-  "")
-
-HWCFG_STRING(
-  disk_ramdisk_path,
-  "disk.ramdisk.path",
-  "",
-  "Path to the ramdisk image",
-  "Path to the ramdisk image.")
-
-HWCFG_STRING(
-  disk_systemPartition_path,
-  "disk.systemPartition.path",
-  "",
-  "Path to runtime system partition image",
-  "")
-
-HWCFG_STRING(
-  disk_systemPartition_initPath,
-  "disk.systemPartition.initPath",
-  "",
-  "Initial system partition image",
-  "")
-
-HWCFG_DISKSIZE(
-  disk_systemPartition_size,
-  "disk.systemPartition.size",
-  "0",
-  "Ideal size of system partition",
-  "")
-
-HWCFG_STRING(
-  disk_dataPartition_path,
-  "disk.dataPartition.path",
-  "<temp>",
-  "Path to data partition file",
-  "Path to data partition file. Cannot be empty. Special value <temp> means using a temporary file. If disk.dataPartition.initPath is not empty, its content will be copied to the disk.dataPartition.path file at boot-time.")
-
-HWCFG_STRING(
-  disk_dataPartition_initPath,
-  "disk.dataPartition.initPath",
-  "",
-  "Initial data partition",
-  "If not empty, its content will be copied to the disk.dataPartition.path file at boot-time.")
-
-HWCFG_DISKSIZE(
-  disk_dataPartition_size,
-  "disk.dataPartition.size",
-  "0",
-  "Ideal size of data partition",
-  "")
-
-HWCFG_STRING(
-  disk_snapStorage_path,
-  "disk.snapStorage.path",
-  "",
-  "Path to snapshot storage",
-  "Path to a 'snapshot storage' file, where all snapshots are stored.")
-
-HWCFG_STRING(
-  avd_name,
-  "avd.name",
-  "<build>",
-  "Name of the AVD being run",
-  "")
-
-#undef HWCFG_INT
-#undef HWCFG_BOOL
-#undef HWCFG_DISKSIZE
-#undef HWCFG_STRING
-#undef HWCFG_DOUBLE
-/* end of auto-generated file */
diff --git a/android/avd/info.c b/android/avd/info.c
index 1ab066c..7e4f93e 100644
--- a/android/avd/info.c
+++ b/android/avd/info.c
@@ -886,9 +886,20 @@
          * for our target architecture.
          */
         char temp[PATH_MAX], *p = temp, *end = p + sizeof(temp);
+        const char* suffix = "";
+        char* abi;
 
-        p = bufprint(temp, end, "%s/prebuilt/android-%s/kernel/kernel-qemu",
-                     i->androidBuildRoot, i->targetArch);
+        /* If the target ABI is armeabi-v7a, then look for
+         * kernel-qemu-armv7 instead of kernel-qemu in the prebuilt
+         * directory. */
+        abi = path_getBuildTargetAbi(i->androidOut);
+        if (!strcmp(abi,"armeabi-v7a")) {
+            suffix = "-armv7";
+        }
+        AFREE(abi);
+
+        p = bufprint(temp, end, "%s/prebuilt/android-%s/kernel/kernel-qemu%s",
+                     i->androidBuildRoot, i->targetArch, suffix);
         if (p >= end || !path_exists(temp)) {
             derror("bad workspace: cannot find prebuilt kernel in: %s", temp);
             exit(1);
@@ -1024,6 +1035,16 @@
 }
 
 char*
+avdInfo_getTargetAbi( AvdInfo* i )
+{
+    /* For now, we can't get the ABI from SDK AVDs */
+    if (!i->inAndroidBuild)
+        return NULL;
+
+    return path_getBuildTargetAbi(i->androidOut);
+}
+
+char*
 avdInfo_getTracePath( AvdInfo*  i, const char*  traceName )
 {
     char   tmp[MAX_PATH], *p=tmp, *end=p + sizeof(tmp);
@@ -1162,3 +1183,22 @@
     AFREE(skinPath);
     return;
 }
+
+char*
+avdInfo_getCharmapFile( AvdInfo* i, const char* charmapName )
+{
+    char        fileNameBuff[PATH_MAX];
+    const char* fileName;
+
+    if (charmapName == NULL || charmapName[0] == '\0')
+        return NULL;
+
+    if (strstr(charmapName, ".kcm") == NULL) {
+        snprintf(fileNameBuff, sizeof fileNameBuff, "%s.kcm", charmapName);
+        fileName = fileNameBuff;
+    } else {
+        fileName = charmapName;
+    }
+
+    return _avdInfo_getContentOrSdkFilePath(i, fileName);
+}
diff --git a/android/avd/info.h b/android/avd/info.h
index 2469f68..34997b4 100644
--- a/android/avd/info.h
+++ b/android/avd/info.h
@@ -215,9 +215,22 @@
  */
 void         avdInfo_getSkinInfo( AvdInfo*  i, char** pSkinName, char** pSkinDir );
 
+/* Find a charmap file named <charmapName>.kcm for this AVD.
+ * Returns the path of the file on success, or NULL if not found.
+ * The result string must be freed by the caller.
+ */
+char*        avdInfo_getCharmapFile( AvdInfo* i, const char* charmapName );
+
 /* Returns TRUE iff in the Android build system */
 int          avdInfo_inAndroidBuild( AvdInfo*  i );
 
+/* Returns the target ABI for the corresponding platform image.
+ * This may return NULL if it cannot be determined. Otherwise this is
+ * a string like "armeabi", "armeabi-v7a" or "x86" that must be freed
+ * by the caller.
+ */
+char*        avdInfo_getTargetAbi( AvdInfo*  i );
+
 /* Reads the AVD's hardware configuration into 'hw'. returns -1 on error, 0 otherwise */
 int          avdInfo_initHwConfig( AvdInfo*  i, AndroidHwConfig*  hw );
 
diff --git a/android/avd/util.c b/android/avd/util.c
index 2ba4117..304b98f 100644
--- a/android/avd/util.c
+++ b/android/avd/util.c
@@ -264,6 +264,24 @@
     return result;
 }
 
+char*
+path_getBuildTargetAbi( const char* androidOut )
+{
+    const char* defaultAbi = "armeabi";
+    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 ABI: %s", defaultAbi);
+        result = ASTRDUP(defaultAbi);
+    } else {
+        D("Found target ABI=%s", cpuAbi);
+        result = cpuAbi;
+    }
+    return result;
+}
+
 
 int
 path_getBuildTargetApiLevel( const char* androidOut )
diff --git a/android/avd/util.h b/android/avd/util.h
index 27f8f28..877d5aa 100644
--- a/android/avd/util.h
+++ b/android/avd/util.h
@@ -48,6 +48,16 @@
  */
 char* path_getBuildTargetArch( const char* androidOut );
 
+/* Retrieves a string corresponding to the target CPU ABI
+ * 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_getBuildTargetAbi( 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
diff --git a/android/build/binary.make b/android/build/binary.make
index f6542dc..3bc4fe9 100644
--- a/android/build/binary.make
+++ b/android/build/binary.make
@@ -25,6 +25,8 @@
 LOCAL_CXX_SOURCES := $(filter %$(LOCAL_CPP_EXTENSION),$(LOCAL_SRC_FILES) $(LOCAL_GENERATED_SOURCES))
 LOCAL_OBJC_SOURCES := $(filter %.m,$(LOCAL_SRC_FILES) $(LOCAL_GENERATED_SOURCES))
 
+LOCAL_CFLAGS := $(strip $(patsubst %,-I%,$(LOCAL_C_INCLUDES)) $(LOCAL_CFLAGS))
+
 $(foreach src,$(LOCAL_C_SOURCES), \
     $(eval $(call compile-c-source,$(src))) \
 )
@@ -41,4 +43,7 @@
     $(eval $(call compile-objc-source,$(src))) \
 )
 
+# Ensure that we build all generated sources before the objects
+$(LOCAL_OBJECTS): | $(LOCAL_GENERATED_SOURCES)
+
 CLEAN_OBJS_DIRS += $(LOCAL_OBJS_DIR)
diff --git a/android/build/common.sh b/android/build/common.sh
index 050fd90..de4e3c1 100644
--- a/android/build/common.sh
+++ b/android/build/common.sh
@@ -457,11 +457,11 @@
     unset ANDROID_TOP
     IN_ANDROID_BUILD=no
 
-    if [ -z "$ANDROID_PRODUCT_OUT" ] ; then
+    if [ -z "$ANDROID_BUILD_TOP" ] ; then
         return ;
     fi
 
-    ANDROID_TOP=`cd $ANDROID_PRODUCT_OUT/../../../.. && pwd`
+    ANDROID_TOP=$ANDROID_BUILD_TOP
     log "ANDROID_TOP found at $ANDROID_TOP"
     # $ANDROID_TOP/config/envsetup.make is for the old tree layout
     # $ANDROID_TOP/build/envsetup.sh is for the new one
diff --git a/android/build/definitions.make b/android/build/definitions.make
index e31131b..ddf9150 100644
--- a/android/build/definitions.make
+++ b/android/build/definitions.make
@@ -13,6 +13,19 @@
 # limitations under the License.
 #
 
+# this turns off the suffix rules built into make
+.SUFFIXES:
+
+# this turns off the RCS / SCCS implicit rules of GNU Make
+% : RCS/%,v
+% : RCS/%
+% : %,v
+% : s.%
+% : SCCS/s.%
+
+# If a rule fails, delete $@.
+.DELETE_ON_ERROR:
+
 # shared definitions
 ifeq ($(strip $(SHOW)),)
 define pretty
diff --git a/android/hw-pipe-net.c b/android/hw-pipe-net.c
index d83d8b1..dade446 100644
--- a/android/hw-pipe-net.c
+++ b/android/hw-pipe-net.c
@@ -68,7 +68,7 @@
     int             wakeWanted;
     LoopIo          io[1];
     AsyncConnector  connector[1];
-
+    int             shouldSetSocketOpt;
 } NetPipe;
 
 static void
@@ -192,6 +192,7 @@
 
     pipe->hwpipe = hwpipe;
     pipe->state  = STATE_INIT;
+    pipe->shouldSetSocketOpt = 0;
 
     {
         AsyncStatus  status;
@@ -245,13 +246,26 @@
     const GoldfishPipeBuffer* buff = buffers;
     const GoldfishPipeBuffer* buffEnd = buff + numBuffers;
 
+#ifdef _WIN32
+    if (pipe->shouldSetSocketOpt == 1) {
+        int sndbuf = 128 * 1024;
+        int len = sizeof(sndbuf);
+        if (setsockopt(pipe->io->fd, SOL_SOCKET, SO_SNDBUF,
+                       (char*)&sndbuf, len) == SOCKET_ERROR) {
+            D("Failed to set SO_SNDBUF to %d error=0x%x\n",
+               sndbuf, WSAGetLastError());
+        }
+        pipe->shouldSetSocketOpt = 0;
+    }
+#endif
+
     for (; buff < buffEnd; buff++)
         count += buff->size;
 
     buff = buffers;
     while (count > 0) {
         int  avail = buff->size - buffStart;
-        int  len = write(pipe->io->fd, buff->data + buffStart, avail);
+        int  len = socket_send(pipe->io->fd, buff->data + buffStart, avail);
 
         /* the write succeeded */
         if (len > 0) {
@@ -272,10 +286,6 @@
             break;
         }
 
-        /* loop on EINTR */
-        if (errno == EINTR)
-            continue;
-
         /* if we already wrote some stuff, simply return */
         if (ret > 0) {
             break;
@@ -309,7 +319,7 @@
     buff = buffers;
     while (count > 0) {
         int  avail = buff->size - buffStart;
-        int  len = read(pipe->io->fd, buff->data + buffStart, avail);
+        int  len = socket_recv(pipe->io->fd, buff->data + buffStart, avail);
 
         /* the read succeeded */
         if (len > 0) {
@@ -330,10 +340,6 @@
             break;
         }
 
-        /* loop on EINTR */
-        if (errno == EINTR)
-            continue;
-
         /* if we already read some stuff, simply return */
         if (ret > 0) {
             break;
@@ -381,40 +387,17 @@
 netPipe_initTcp( void* hwpipe, void* _looper, const char* args )
 {
     /* Build SockAddress from arguments. Acceptable formats are:
-     *
      *   <port>
-     *   <host>:<port>
      */
     SockAddress  address;
+    uint16_t     port;
     void*        ret;
 
     if (args == NULL) {
         D("%s: Missing address!", __FUNCTION__);
         return NULL;
     }
-    D("%s: Address is '%s'", __FUNCTION__, args);
-
-    char        host[256];  /* max size of regular FDQN+1 */
-    int         hostlen = 0;
-    int         port;
-    const char* p;
-
-    /* Assume that anything after the last ':' is a port number
-        * And that what is before it is a port number. Should handle IPv6
-        * notation. */
-    p = strrchr(args, ':');
-    if (p != NULL) {
-        hostlen = p - args;
-        if (hostlen >= sizeof(host)) {
-            D("%s: Address too long!", __FUNCTION__);
-            return NULL;
-        }
-        memcpy(host, args, hostlen);
-        host[hostlen] = '\0';
-        args = p + 1;
-    } else {
-        snprintf(host, sizeof host, "127.0.0.1");
-    }
+    D("%s: Port is '%s'", __FUNCTION__, args);
 
     /* Now, look at the port number */
     {
@@ -423,12 +406,9 @@
         if (end == NULL || *end != '\0' || val <= 0 || val > 65535) {
             D("%s: Invalid port number: '%s'", __FUNCTION__, args);
         }
-        port = (int)val;
+        port = (uint16_t)val;
     }
-    if (sock_address_init_resolve(&address, host, port, 0) < 0) {
-        D("%s: Could not resolve address", __FUNCTION__);
-        return NULL;
-    }
+    sock_address_init_inet(&address, SOCK_ADDRESS_INET_LOOPBACK, port);
 
     ret = netPipe_initFromAddress(hwpipe, &address, _looper);
 
@@ -436,6 +416,7 @@
     return ret;
 }
 
+#ifndef _WIN32
 void*
 netPipe_initUnix( void* hwpipe, void* _looper, const char* args )
 {
@@ -459,7 +440,7 @@
     sock_address_done(&address);
     return ret;
 }
-
+#endif
 
 /**********************************************************************
  **********************************************************************
@@ -477,6 +458,7 @@
     netPipe_wakeOn,
 };
 
+#ifndef _WIN32
 static const GoldfishPipeFuncs  netPipeUnix_funcs = {
     netPipe_initUnix,
     netPipe_closeFromGuest,
@@ -485,7 +467,7 @@
     netPipe_poll,
     netPipe_wakeOn,
 };
-
+#endif
 
 #define DEFAULT_OPENGLES_PORT  22468
 
@@ -493,10 +475,14 @@
 openglesPipe_init( void* hwpipe, void* _looper, const char* args )
 {
     char temp[32];
+    NetPipe *pipe;
 
     /* For now, simply connect through tcp */
     snprintf(temp, sizeof temp, "%d", DEFAULT_OPENGLES_PORT);
-    return netPipe_initTcp(hwpipe, _looper, temp);
+    pipe = (NetPipe *)netPipe_initTcp(hwpipe, _looper, temp);
+    pipe->shouldSetSocketOpt = 1;
+
+    return pipe;
 }
 
 static const GoldfishPipeFuncs  openglesPipe_funcs = {
@@ -515,6 +501,8 @@
     Looper*  looper = looper_newCore();
 
     goldfish_pipe_add_type( "tcp", looper, &netPipeTcp_funcs );
+#ifndef _WIN32
     goldfish_pipe_add_type( "unix", looper, &netPipeUnix_funcs );
+#endif
     goldfish_pipe_add_type( "opengles", looper, &openglesPipe_funcs );
 }
diff --git a/android/keycode.h b/android/keycode.h
index a32ac0d..bbec160 100644
--- a/android/keycode.h
+++ b/android/keycode.h
@@ -101,6 +101,20 @@
     kKeyCodeMenu                    = KEY_SOFT1,
     kKeyCodeNotification            = KEY_NOTIFICATION,
     kKeyCodeSearch                  = KEY_SEARCH,
+    kKeyCodeTV                      = KEY_TV,
+    kKeyCodeEPG                     = KEY_PROGRAM,
+    kKeyCodeDVR                     = KEY_PVR,
+    kKeyCodePrevious                = KEY_PREVIOUS,
+    kKeyCodeNext                    = KEY_NEXT,
+    kKeyCodePlay                    = KEY_PLAY,
+    kKeyCodePause                   = KEY_PAUSE,
+    kKeyCodeStop                    = KEY_STOP,
+    kKeyCodeRewind                  = KEY_REWIND,
+    kKeyCodeFastForward             = KEY_FASTFORWARD,
+    kKeyCodeBookmarks               = KEY_BOOKMARKS,
+    kKeyCodeCycleWindows            = KEY_CYCLEWINDOWS,
+    kKeyCodeChannelUp               = KEY_CHANNELUP,
+    kKeyCodeChannelDown             = KEY_CHANNELDOWN,
 
 } AndroidKeyCode;
 
diff --git a/android/main-common.c b/android/main-common.c
index 94accf7..a662907 100644
--- a/android/main-common.c
+++ b/android/main-common.c
@@ -335,9 +335,6 @@
     { NULL, NULL }
 };
 
-/* this is used by hw/events_device.c to send the charmap name to the system */
-const char*    android_skin_keycharmap = NULL;
-
 void
 parse_skin_files(const char*      skinDirPath,
                  const char*      skinName,
@@ -524,7 +521,7 @@
 #endif
 
     /* we're not a game, so allow the screensaver to run */
-    putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1");
+    setenv("SDL_VIDEO_ALLOW_SCREENSAVER","1",1);
 
     flags = SDL_INIT_NOPARACHUTE;
     if (!opts->no_window)
@@ -563,8 +560,6 @@
         exit(1);
     }
 
-    android_skin_keycharmap = skin_keyboard_charmap_name(qemulator_get()->keyboard);
-
     /* add an onion overlay image if needed */
     if (opts->onion) {
         SkinImage*  onion = skin_image_find_simple( opts->onion );
diff --git a/android/main-emulator.c b/android/main-emulator.c
index 211291b..39e5e1e 100644
--- a/android/main-emulator.c
+++ b/android/main-emulator.c
@@ -44,6 +44,23 @@
 /* Forward declarations */
 static char* getTargetEmulatorPath(const char* progName, const char* avdArch);
 
+#ifdef _WIN32
+static char* quotePath(const char* path);
+#endif
+
+/* The execv() definition in mingw is slightly bogus.
+ * It takes a second argument of type 'const char* const*'
+ * while POSIX mandates char** instead.
+ *
+ * To avoid compiler warnings, define the safe_execv macro
+ * to perform an explicit cast with mingw.
+ */
+#ifdef _WIN32
+#  define safe_execv(_filepath,_argv)  execv((_filepath),(const char* const*)(_argv))
+#else
+#  define safe_execv(_filepath,_argv)  execv((_filepath),(_argv))
+#endif
+
 /* Main routine */
 int main(int argc, char** argv)
 {
@@ -109,9 +126,20 @@
     /* Replace it in our command-line */
     argv[0] = emulatorPath;
 
+#ifdef _WIN32
+    /* Looks like execv() in mingw (or is it MSVCRT.DLL?) doesn't
+     * support a space in argv[0] unless we explicitely quote it.
+     * IMPORTANT: do not quote the first argument to execv() or it will fail.
+     * This was tested on a 32-bit Vista installation.
+     */
+    if (strchr(emulatorPath, ' ')) {
+        argv[0] = quotePath(emulatorPath);
+        D("Quoted emulator binary path: %s\n", emulatorPath);
+    }
+#endif
+
     /* Launch it with the same set of options ! */
-    /* execv() should be available on Windows with mingw32 */
-    execv(emulatorPath, argv);
+    safe_execv(emulatorPath, argv);
 
     /* We could not launch the program ! */
     fprintf(stderr, "Could not launch '%s': %s\n", emulatorPath, strerror(errno));
@@ -167,3 +195,19 @@
     APANIC("Missing arch-specific emulator program: %s\n", temp);
     return NULL;
 }
+
+#ifdef _WIN32
+static char*
+quotePath(const char* path)
+{
+    int   len = strlen(path);
+    char* ret = malloc(len+3);
+
+    ret[0] = '"';
+    memcpy(ret+1, path, len);
+    ret[len+1] = '"';
+    ret[len+2] = '\0';
+
+    return ret;
+}
+#endif /* _WIN32 */
diff --git a/android/main.c b/android/main.c
index ec7ea61..f20ea7b 100644
--- a/android/main.c
+++ b/android/main.c
@@ -169,6 +169,8 @@
     int    serial = 2;
     int    shell_serial = 0;
 
+    int    forceArmv7 = 0;
+
     AndroidHwConfig*  hw;
     AvdInfo*          avd;
     AConfig*          skinConfig;
@@ -430,8 +432,7 @@
          */
          kernelFileLen = strlen(kernelFile);
          if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
-            args[n++] = "-cpu";
-            args[n++] = "cortex-a8";
+             forceArmv7 = 1;
          }
     }
 
@@ -1031,9 +1032,30 @@
         args[n++] = opts->http_proxy;
     }
 
+    if (!opts->charmap) {
+        /* Try to find a valid charmap name */
+        char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap);
+        if (charmap != NULL) {
+            D("autoconfig: -charmap %s", charmap);
+            opts->charmap = charmap;
+        }
+    }
+
     if (opts->charmap) {
-        args[n++] = "-charmap";
-        args[n++] = opts->charmap;
+        char charmap_name[AKEYCHARMAP_NAME_SIZE];
+
+        if (!path_exists(opts->charmap)) {
+            derror("Charmap file does not exist: %s", opts->charmap);
+            exit(1);
+        }
+        /* We need to store the charmap name in the hardware configuration.
+         * However, the charmap file itself is only used by the UI component
+         * and doesn't need to be set to the emulation engine.
+         */
+        kcm_extract_charmap_name(opts->charmap, charmap_name,
+                                 sizeof(charmap_name));
+        AFREE(hw->hw_keyboard_charmap);
+        hw->hw_keyboard_charmap = ASTRDUP(charmap_name);
     }
 
     if (opts->memcheck) {
@@ -1067,6 +1089,27 @@
     }
     args[n] = 0;
 
+    /* If the target ABI is armeabi-v7a, we can auto-detect the cpu model
+     * as a cortex-a8, instead of the default (arm926) which only emulates
+     * an ARMv5TE CPU.
+     */
+    if (!forceArmv7 && hw->hw_cpu_model[0] == '\0')
+    {
+        char* abi = avdInfo_getTargetAbi(avd);
+        if (abi != NULL) {
+            if (!strcmp(abi, "armeabi-v7a")) {
+                forceArmv7 = 1;
+            }
+            AFREE(abi);
+        }
+    }
+
+    if (forceArmv7 != 0) {
+        AFREE(hw->hw_cpu_model);
+        hw->hw_cpu_model = ASTRDUP("cortex-a8");
+        D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
+    }
+
     /* Generate a hardware-qemu.ini for this AVD. The real hardware
      * configuration is ususally stored in several files, e.g. the AVD's
      * config.ini plus the skin-specific hardware.ini.
diff --git a/android/qemulator.c b/android/qemulator.c
index d29ee94..35587ff 100644
--- a/android/qemulator.c
+++ b/android/qemulator.c
@@ -137,17 +137,7 @@
     emulator->aconfig     = aconfig;
     emulator->layout_file = skin_file_create_from_aconfig(aconfig, basepath);
     emulator->layout      = emulator->layout_file->layouts;
-    // If we have a custom charmap use it to initialize keyboard.
-    // Otherwise initialize keyboard from configuration settings.
-    // Another way to configure keyboard to use a custom charmap would
-    // be saving a custom charmap name into AConfig's keyboard->charmap
-    // property, and calling single skin_keyboard_create_from_aconfig
-    // routine to initialize keyboard.
-    if (NULL != opts->charmap) {
-        emulator->keyboard = skin_keyboard_create_from_kcm(opts->charmap, opts->raw_keys);
-    } else {
-        emulator->keyboard = skin_keyboard_create_from_aconfig(aconfig, opts->raw_keys);
-    }
+    emulator->keyboard    = skin_keyboard_create(opts->charmap, opts->raw_keys);
     emulator->window      = NULL;
     emulator->win_x       = x;
     emulator->win_y       = y;
@@ -340,11 +330,11 @@
 {
     static const struct { SkinKeyCommand  cmd; AndroidKeyCode  kcode; }  keycodes[] =
     {
-        { SKIN_KEY_COMMAND_BUTTON_CALL,   kKeyCodeCall },
-        { SKIN_KEY_COMMAND_BUTTON_HOME,   kKeyCodeHome },
-        { SKIN_KEY_COMMAND_BUTTON_BACK,   kKeyCodeBack },
-        { SKIN_KEY_COMMAND_BUTTON_HANGUP, kKeyCodeEndCall },
-        { SKIN_KEY_COMMAND_BUTTON_POWER,  kKeyCodePower },
+        { SKIN_KEY_COMMAND_BUTTON_CALL,        kKeyCodeCall },
+        { SKIN_KEY_COMMAND_BUTTON_HOME,        kKeyCodeHome },
+        { SKIN_KEY_COMMAND_BUTTON_BACK,        kKeyCodeBack },
+        { SKIN_KEY_COMMAND_BUTTON_HANGUP,      kKeyCodeEndCall },
+        { SKIN_KEY_COMMAND_BUTTON_POWER,       kKeyCodePower },
         { SKIN_KEY_COMMAND_BUTTON_SEARCH,      kKeyCodeSearch },
         { SKIN_KEY_COMMAND_BUTTON_MENU,        kKeyCodeMenu },
         { SKIN_KEY_COMMAND_BUTTON_DPAD_UP,     kKeyCodeDpadUp },
@@ -355,6 +345,20 @@
         { SKIN_KEY_COMMAND_BUTTON_VOLUME_UP,   kKeyCodeVolumeUp },
         { SKIN_KEY_COMMAND_BUTTON_VOLUME_DOWN, kKeyCodeVolumeDown },
         { SKIN_KEY_COMMAND_BUTTON_CAMERA,      kKeyCodeCamera },
+        { SKIN_KEY_COMMAND_BUTTON_TV,          kKeyCodeTV },
+        { SKIN_KEY_COMMAND_BUTTON_EPG,         kKeyCodeEPG },
+        { SKIN_KEY_COMMAND_BUTTON_DVR,         kKeyCodeDVR },
+        { SKIN_KEY_COMMAND_BUTTON_PREV,        kKeyCodePrevious },
+        { SKIN_KEY_COMMAND_BUTTON_NEXT,        kKeyCodeNext },
+        { SKIN_KEY_COMMAND_BUTTON_PLAY,        kKeyCodePlay },
+        { SKIN_KEY_COMMAND_BUTTON_PAUSE,       kKeyCodePause },
+        { SKIN_KEY_COMMAND_BUTTON_STOP,        kKeyCodeStop },
+        { SKIN_KEY_COMMAND_BUTTON_REWIND,      kKeyCodeRewind },
+        { SKIN_KEY_COMMAND_BUTTON_FFWD,        kKeyCodeFastForward },
+        { SKIN_KEY_COMMAND_BUTTON_BOOKMARKS,   kKeyCodeBookmarks },
+        { SKIN_KEY_COMMAND_BUTTON_WINDOW,      kKeyCodeCycleWindows },
+        { SKIN_KEY_COMMAND_BUTTON_CHANNELUP,   kKeyCodeChannelUp },
+        { SKIN_KEY_COMMAND_BUTTON_CHANNELDOWN, kKeyCodeChannelDown },
         { SKIN_KEY_COMMAND_NONE, 0 }
     };
     int          nn;
diff --git a/android/skin/file.c b/android/skin/file.c
index 252a7c4..d947ec2 100644
--- a/android/skin/file.c
+++ b/android/skin/file.c
@@ -187,6 +187,20 @@
     { "ALT",          kKeyCodeAltLeft },
     { "ALT2",         kKeyCodeAltRight },
     { "CAP2",         kKeyCodeCapRight },
+    { "tv",           kKeyCodeTV },
+    { "epg",          kKeyCodeEPG },
+    { "dvr",          kKeyCodeDVR },
+    { "prev",         kKeyCodePrevious },
+    { "next",         kKeyCodeNext },
+    { "play",         kKeyCodePlay },
+    { "pause",        kKeyCodePause },
+    { "stop",         kKeyCodeStop },
+    { "rev",          kKeyCodeRewind },
+    { "ffwd",         kKeyCodeFastForward },
+    { "bookmarks",    kKeyCodeBookmarks },
+    { "window",       kKeyCodeCycleWindows },
+    { "channel-up",   kKeyCodeChannelUp },
+    { "channel-down", kKeyCodeChannelDown },
     { 0, 0 },
 };
 
diff --git a/android/skin/keyboard.c b/android/skin/keyboard.c
index 3ee3366..3371799 100644
--- a/android/skin/keyboard.c
+++ b/android/skin/keyboard.c
@@ -72,15 +72,6 @@
 }
 
 
-const char*
-skin_keyboard_charmap_name( SkinKeyboard*  keyboard )
-{
-    if (keyboard && keyboard->charmap)
-        return keyboard->charmap->name;
-
-    return DEFAULT_ANDROID_CHARMAP;
-}
-
 void
 skin_keyboard_set_rotation( SkinKeyboard*     keyboard,
                             SkinRotation      rotation )
@@ -539,22 +530,15 @@
 }
 
 SkinKeyboard*
-skin_keyboard_create_from_aconfig( AConfig*  aconfig, int  use_raw_keys )
+skin_keyboard_create( const char*  kcm_file_path, int  use_raw_keys )
 {
-    const char*    charmap_name = DEFAULT_ANDROID_CHARMAP;
-    AConfig*       node = aconfig_find( aconfig, "keyboard" );
-    if (node != NULL) {
-        charmap_name = aconfig_str(node, "charmap", charmap_name);
-    }
-    return skin_keyboard_create_from_charmap_name(charmap_name, use_raw_keys);
-}
+    const char* charmap_name = DEFAULT_ANDROID_CHARMAP;
+    char        cmap_buff[AKEYCHARMAP_NAME_SIZE];
 
-SkinKeyboard*
-skin_keyboard_create_from_kcm( const char*  kcm_file_path, int  use_raw_keys )
-{
-    char charmap_name[AKEYCHARMAP_NAME_SIZE];
-    kcm_extract_charmap_name(kcm_file_path, charmap_name,
-                             sizeof(charmap_name));
+    if (kcm_file_path != NULL) {
+        kcm_extract_charmap_name(kcm_file_path, cmap_buff, sizeof cmap_buff);
+        charmap_name = cmap_buff;
+    }
     return skin_keyboard_create_from_charmap_name(charmap_name, use_raw_keys);
 }
 
diff --git a/android/skin/keyboard.h b/android/skin/keyboard.h
index a86b132..1c3b088 100644
--- a/android/skin/keyboard.h
+++ b/android/skin/keyboard.h
@@ -24,9 +24,8 @@
 
 typedef void (*SkinKeyEventFunc)( void*  opaque, AndroidKeyCode  code, int  down );
 
-extern SkinKeyboard*  skin_keyboard_create_from_aconfig( AConfig*  aconfig, int  use_raw_keys );
-
-extern SkinKeyboard*  skin_keyboard_create_from_kcm( const char*  kcm_file_path, int  use_raw_keys );
+/* If kcm_file_path is NULL, create a keyboard using the default built-in qwerty2 charmap */
+extern SkinKeyboard*  skin_keyboard_create( const char*  kcm_file_path, int  use_raw_keys );
 
 extern void           skin_keyboard_set_keyset( SkinKeyboard*  keyboard, SkinKeyset*  kset );
 
diff --git a/android/skin/keyset.h b/android/skin/keyset.h
index d68d6a7..81eb2e7 100644
--- a/android/skin/keyset.h
+++ b/android/skin/keyset.h
@@ -33,20 +33,34 @@
     _SKIN_KEY_COMMAND(BUTTON_VOLUME_UP,"Volume up button")         \
     _SKIN_KEY_COMMAND(BUTTON_VOLUME_DOWN,"Volume down button")       \
     _SKIN_KEY_COMMAND(BUTTON_CAMERA,"Camera button")            \
-    _SKIN_KEY_COMMAND(CHANGE_LAYOUT_PREV,"switch to previous layout")       \
-    _SKIN_KEY_COMMAND(CHANGE_LAYOUT_NEXT,"switch to next layout")       \
-    _SKIN_KEY_COMMAND(TOGGLE_NETWORK,"toggle cell network on/off")           \
-    _SKIN_KEY_COMMAND(TOGGLE_TRACING,"toggle code profiling")           \
-    _SKIN_KEY_COMMAND(TOGGLE_FULLSCREEN,"toggle fullscreen mode")        \
-    _SKIN_KEY_COMMAND(TOGGLE_TRACKBALL,"toggle trackball mode")         \
-    _SKIN_KEY_COMMAND(SHOW_TRACKBALL,"show trackball") \
+    _SKIN_KEY_COMMAND(CHANGE_LAYOUT_PREV,"Switch to previous layout")       \
+    _SKIN_KEY_COMMAND(CHANGE_LAYOUT_NEXT,"Switch to next layout")       \
+    _SKIN_KEY_COMMAND(TOGGLE_NETWORK,"Toggle cell network on/off")           \
+    _SKIN_KEY_COMMAND(TOGGLE_TRACING,"Toggle code profiling")           \
+    _SKIN_KEY_COMMAND(TOGGLE_FULLSCREEN,"Toggle fullscreen mode")        \
+    _SKIN_KEY_COMMAND(TOGGLE_TRACKBALL,"Toggle trackball mode")         \
+    _SKIN_KEY_COMMAND(SHOW_TRACKBALL,"Show trackball") \
     _SKIN_KEY_COMMAND(BUTTON_DPAD_CENTER,"DPad center")       \
     _SKIN_KEY_COMMAND(BUTTON_DPAD_LEFT,"DPad left") \
     _SKIN_KEY_COMMAND(BUTTON_DPAD_RIGHT,"DPad right")        \
     _SKIN_KEY_COMMAND(BUTTON_DPAD_UP,"DPad up")           \
     _SKIN_KEY_COMMAND(BUTTON_DPAD_DOWN,"DPad down")         \
-    _SKIN_KEY_COMMAND(ONION_ALPHA_UP,"increase onion alpha")           \
-    _SKIN_KEY_COMMAND(ONION_ALPHA_DOWN,"decrease onion alpha")         \
+    _SKIN_KEY_COMMAND(ONION_ALPHA_UP,"Increase onion alpha")           \
+    _SKIN_KEY_COMMAND(ONION_ALPHA_DOWN,"Decrease onion alpha")         \
+    _SKIN_KEY_COMMAND(BUTTON_TV,"TV button")         \
+    _SKIN_KEY_COMMAND(BUTTON_EPG,"EPG button")         \
+    _SKIN_KEY_COMMAND(BUTTON_DVR,"DVR button")         \
+    _SKIN_KEY_COMMAND(BUTTON_PREV,"Previous button")         \
+    _SKIN_KEY_COMMAND(BUTTON_NEXT,"Next button")         \
+    _SKIN_KEY_COMMAND(BUTTON_PLAY,"Play button")         \
+    _SKIN_KEY_COMMAND(BUTTON_PAUSE,"Pause button")         \
+    _SKIN_KEY_COMMAND(BUTTON_STOP,"Stop button")         \
+    _SKIN_KEY_COMMAND(BUTTON_REWIND,"Rewind button")         \
+    _SKIN_KEY_COMMAND(BUTTON_FFWD,"Fast forward button")         \
+    _SKIN_KEY_COMMAND(BUTTON_BOOKMARKS,"Bookmarks button")         \
+    _SKIN_KEY_COMMAND(BUTTON_WINDOW,"Window button")         \
+    _SKIN_KEY_COMMAND(BUTTON_CHANNELUP,"Channel up button")         \
+    _SKIN_KEY_COMMAND(BUTTON_CHANNELDOWN,"Channel down button")         \
 
 
 /* the list of commands in the emulator */
diff --git a/android/skin/window.c b/android/skin/window.c
index c1bf23f..9a72db5 100644
--- a/android/skin/window.c
+++ b/android/skin/window.c
@@ -1074,6 +1074,20 @@
                 case kKeyCodeBack:
                 case kKeyCodeCall:
                 case kKeyCodeEndCall:
+                case kKeyCodeTV:
+                case kKeyCodeEPG:
+                case kKeyCodeDVR:
+                case kKeyCodePrevious:
+                case kKeyCodeNext:
+                case kKeyCodePlay:
+                case kKeyCodePause:
+                case kKeyCodeStop:
+                case kKeyCodeRewind:
+                case kKeyCodeFastForward:
+                case kKeyCodeBookmarks:
+                case kKeyCodeCycleWindows:
+                case kKeyCodeChannelUp:
+                case kKeyCodeChannelDown:
                     break;
 
                 /* all the rest is assumed to be qwerty */
@@ -1301,15 +1315,9 @@
 
         {
             char temp[32];
-#ifdef HAVE_SETENV
             sprintf(temp, "%d,%d", window_x, window_y);
             setenv("SDL_VIDEO_WINDOW_POS", temp, 1);
             setenv("SDL_VIDEO_WINDOW_FORCE_VISIBLE", "1", 1);
-#else
-            sprintf(temp,"SDL_VIDEO_WINDOW_POS=%d,%d",window_x,window_y);
-            putenv(temp);
-            putenv("SDL_VIDEO_WINDOW_FORCE_VISIBLE=1");
-#endif
         }
 
         flags = SDL_SWSURFACE;
diff --git a/android/utils/setenv.c b/android/utils/setenv.c
new file mode 100644
index 0000000..916c5f3
--- /dev/null
+++ b/android/utils/setenv.c
@@ -0,0 +1,18 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef _WIN32
+int setenv(const char *name, const char *value, int overwrite)
+{
+    int result = 0;
+    if (overwrite || !getenv(name)) {
+        size_t length = strlen(name) + strlen(value) + 2;
+        char *string = malloc(length);
+        snprintf(string, length, "%s=%s", name, value);
+        result = putenv(string);
+    }
+    return result;
+}
+
+#endif
diff --git a/hw/goldfish_events_device.c b/hw/goldfish_events_device.c
index 3072e3b..a5b2a21 100644
--- a/hw/goldfish_events_device.c
+++ b/hw/goldfish_events_device.c
@@ -102,8 +102,6 @@
     return qemu_get_struct(f, events_state_fields, s);
 }
 
-extern const char*  android_skin_keycharmap;
-
 static void enqueue_event(events_state *s, unsigned int type, unsigned int code, int value)
 {
     int  enqueued = s->last - s->first;
@@ -169,22 +167,11 @@
     return n;
 }
 
-static const char*
-get_charmap_name(events_state *s)
-{
-    if (s->name != NULL)
-        return s->name;
-
-    s->name = android_get_charmap_name();
-    return s->name;
-}
-
-
 static int get_page_len(events_state *s)
 {
     int page = s->page;
     if (page == PAGE_NAME) {
-        const char* name = get_charmap_name(s);
+        const char* name = s->name;
         return strlen(name);
     } if (page >= PAGE_EVBITS && page <= PAGE_EVBITS + EV_MAX)
         return s->ev_bits[page - PAGE_EVBITS].len;
@@ -200,7 +187,7 @@
     if (offset > page_len)
         return 0;
     if (page == PAGE_NAME) {
-        const char* name = get_charmap_name(s);
+        const char* name = s->name;
         return name[offset];
     } if (page >= PAGE_EVBITS && page <= PAGE_EVBITS + EV_MAX)
         return s->ev_bits[page - PAGE_EVBITS].bits[offset];
@@ -347,9 +334,6 @@
 
     s = (events_state *) qemu_mallocz(sizeof(events_state));
 
-    // charmap name will be determined on demand
-    s->name = NULL;
-
     /* now set the events capability bits depending on hardware configuration */
     /* apparently, the EV_SYN array is used to indicate which other
      * event classes to consider.
@@ -514,6 +498,7 @@
     s->first = 0;
     s->last = 0;
     s->state = STATE_INIT;
+    s->name = qemu_strdup(config->hw_keyboard_charmap);
 
     /* This function migh fire buffered events to the device, so
      * ensure that it is called after initialization is complete
diff --git a/images/android_icon.ico b/images/android_icon.ico
index bd25179..798d96b 100644
--- a/images/android_icon.ico
+++ b/images/android_icon.ico
Binary files differ
diff --git a/images/android_icon_16.png b/images/android_icon_16.png
index 0b0744b..5df26d4 100644
--- a/images/android_icon_16.png
+++ b/images/android_icon_16.png
Binary files differ
diff --git a/images/android_icon_256.png b/images/android_icon_256.png
index 2d1dc05..0fcac26 100644
--- a/images/android_icon_256.png
+++ b/images/android_icon_256.png
Binary files differ
diff --git a/images/android_icon_32.png b/images/android_icon_32.png
index 72aa861..4ba97a5 100644
--- a/images/android_icon_32.png
+++ b/images/android_icon_32.png
Binary files differ
diff --git a/vl-android.c b/vl-android.c
index 8436d68..32b5eac 100644
--- a/vl-android.c
+++ b/vl-android.c
@@ -3721,13 +3721,11 @@
 
     /* Initialize audio. */
     if (android_op_audio) {
-        char temp[128];
         if ( !audio_check_backend_name( 0, android_op_audio ) ) {
             PANIC("'%s' is not a valid audio output backend. see -help-audio-out",
                     android_op_audio);
         }
-        snprintf(temp, sizeof temp, "QEMU_AUDIO_DRV=%s", android_op_audio);
-        putenv(temp);
+        setenv("QEMU_AUDIO_DRV", android_op_audio, 1);
     }
 
     /* Initialize OpenGLES emulation */