Revert "Revert "Merge c80340 from master to r13: Move charmap to hardware properties"..."

This reverts commit cccd28ca5064a7bd14282cd774ee5bb7126d5845.

c80340 add a CL to tools_r13 that broken the build. It was therefore reverted
with cccd28. This revert was merged into tools_r13 but shouldn't have been.

This reverts the revert to put back the CL in master.

Change-Id: I95fcefedb77596cfdf76269f248b2ae80c85c830
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/info.c b/android/avd/info.c
index f1514f2..7e4f93e 100644
--- a/android/avd/info.c
+++ b/android/avd/info.c
@@ -1183,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 5192bb9..34997b4 100644
--- a/android/avd/info.h
+++ b/android/avd/info.h
@@ -215,6 +215,12 @@
  */
 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 );
 
diff --git a/android/main-common.c b/android/main-common.c
index a0e5f56..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,
@@ -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.c b/android/main.c
index 814d2ec..f20ea7b 100644
--- a/android/main.c
+++ b/android/main.c
@@ -1032,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) {
diff --git a/android/qemulator.c b/android/qemulator.c
index 9e88356..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;
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 );