Merge "arm: Automic ARMv7-A support for platform builds."
diff --git a/android/avd/info.c b/android/avd/info.c
index a9fc711..4df5969 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);
diff --git a/android/avd/info.h b/android/avd/info.h
index 2469f68..5192bb9 100644
--- a/android/avd/info.h
+++ b/android/avd/info.h
@@ -218,6 +218,13 @@
 /* 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/main.c b/android/main.c
index 37bf34a..77d3c69 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;
          }
     }
 
@@ -1064,6 +1065,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.