Update the version of cpu-features that we use for testing.

Review URL: https://codereview.chromium.org/858233003
diff --git a/platform_tools/android/third_party/cpufeatures/README b/platform_tools/android/third_party/cpufeatures/README
index 5815f0c..d92522e 100644
--- a/platform_tools/android/third_party/cpufeatures/README
+++ b/platform_tools/android/third_party/cpufeatures/README
@@ -1,5 +1,5 @@
 The contents of this directory are directly copied from the Android NDK to 
 avoid the need to have a dependency on the NDK directly.
 
-NDK_REVISION: 8d (December 2012)
-NDK_FILE_LOCAtION: ($NDK)/source/android/cpufeatures
+NDK_REVISION: 10c (October 2014)
+NDK_FILE_LOCAtION: ($NDK)/sources/android/cpufeatures
diff --git a/platform_tools/android/third_party/cpufeatures/cpu-features.c b/platform_tools/android/third_party/cpufeatures/cpu-features.c
index 5b0a9d9..2d23efb 100644
--- a/platform_tools/android/third_party/cpufeatures/cpu-features.c
+++ b/platform_tools/android/third_party/cpufeatures/cpu-features.c
@@ -28,6 +28,8 @@
 
 /* ChangeLog for this library:
  *
+ * NDK r9?: Support for 64-bit CPUs (Intel, ARM & MIPS).
+ *
  * NDK r8d: Add android_setCpu().
  *
  * NDK r8c: Add new ARM CPU features: VFPv2, VFP_D32, VFP_FP16,
@@ -56,16 +58,23 @@
  *
  * NDK r4: Initial release
  */
-#include <sys/system_properties.h>
-#ifdef __arm__
-#include <machine/cpu-features.h>
-#endif
-#include <pthread.h>
+
+#if defined(__le32__) || defined(__le64__)
+
+// When users enter this, we should only provide interface and
+// libportable will give the implementations.
+
+#else // !__le32__ && !__le64__
+
 #include "cpu-features.h"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
+#include <sys/system_properties.h>
 
 static  pthread_once_t     g_once;
 static  int                g_inited;
@@ -73,16 +82,12 @@
 static  uint64_t           g_cpuFeatures;
 static  int                g_cpuCount;
 
-static const int  android_cpufeatures_debug = 0;
-
 #ifdef __arm__
-#  define DEFAULT_CPU_FAMILY  ANDROID_CPU_FAMILY_ARM
-#elif defined __i386__
-#  define DEFAULT_CPU_FAMILY  ANDROID_CPU_FAMILY_X86
-#else
-#  define DEFAULT_CPU_FAMILY  ANDROID_CPU_FAMILY_UNKNOWN
+static  uint32_t           g_cpuIdArm;
 #endif
 
+static const int android_cpufeatures_debug = 0;
+
 #define  D(...) \
     do { \
         if (android_cpufeatures_debug) { \
@@ -123,22 +128,22 @@
 
     fd = open(pathname, O_RDONLY);
     if (fd < 0) {
-      D("Can't open %s: %s\n", pathname, strerror(errno));
-      return -1;
+        D("Can't open %s: %s\n", pathname, strerror(errno));
+        return -1;
     }
 
     for (;;) {
-      int ret = read(fd, buffer, sizeof buffer);
-      if (ret < 0) {
-        if (errno == EINTR)
-          continue;
-        D("Error while reading %s: %s\n", pathname, strerror(errno));
-        break;
-      }
-      if (ret == 0)
-        break;
+        int ret = read(fd, buffer, sizeof buffer);
+        if (ret < 0) {
+            if (errno == EINTR)
+                continue;
+            D("Error while reading %s: %s\n", pathname, strerror(errno));
+            break;
+        }
+        if (ret == 0)
+            break;
 
-      result += ret;
+        result += ret;
     }
     close(fd);
     return result;
@@ -185,17 +190,16 @@
  * Return NULL if not found
  */
 static char*
-extract_cpuinfo_field(char* buffer, int buflen, const char* field)
+extract_cpuinfo_field(const char* buffer, int buflen, const char* field)
 {
     int  fieldlen = strlen(field);
-    char* bufend = buffer + buflen;
+    const char* bufend = buffer + buflen;
     char* result = NULL;
     int len, ignore;
     const char *p, *q;
 
     /* Look for first field occurence, and ensures it starts the line. */
     p = buffer;
-    bufend = buffer + buflen;
     for (;;) {
         p = memmem(p, bufend-p, field, fieldlen);
         if (p == NULL)
@@ -232,10 +236,6 @@
     return result;
 }
 
-/* Like strlen(), but for constant string literals */
-#define STRLEN_CONST(x)  ((sizeof(x)-1)
-
-
 /* Checks that a space-separated list of items contains one given 'item'.
  * Returns 1 if found, 0 otherwise.
  */
@@ -269,7 +269,7 @@
     return 0;
 }
 
-/* Parse an decimal integer starting from 'input', but not going further
+/* Parse a number starting from 'input', but not going further
  * than 'limit'. Return the value into '*result'.
  *
  * NOTE: Does not skip over leading spaces, or deal with sign characters.
@@ -280,15 +280,23 @@
  * be <= 'limit').
  */
 static const char*
-parse_decimal(const char* input, const char* limit, int* result)
+parse_number(const char* input, const char* limit, int base, int* result)
 {
     const char* p = input;
     int val = 0;
     while (p < limit) {
         int d = (*p - '0');
-        if ((unsigned)d >= 10U)
-            break;
-        val = val*10 + d;
+        if ((unsigned)d >= 10U) {
+            d = (*p - 'a');
+            if ((unsigned)d >= 6U)
+              d = (*p - 'A');
+            if ((unsigned)d >= 6U)
+              break;
+            d += 10;
+        }
+        if (d >= base)
+          break;
+        val = val*base + d;
         p++;
     }
     if (p == input)
@@ -298,6 +306,18 @@
     return p;
 }
 
+static const char*
+parse_decimal(const char* input, const char* limit, int* result)
+{
+    return parse_number(input, limit, 10, result);
+}
+
+static const char*
+parse_hexadecimal(const char* input, const char* limit, int* result)
+{
+    return parse_number(input, limit, 16, result);
+}
+
 /* This small data type is used to represent a CPU list / mask, as read
  * from sysfs on Linux. See http://www.kernel.org/doc/Documentation/cputopology.txt
  *
@@ -408,6 +428,18 @@
 
     cpulist_parse(list, file, filelen);
 }
+#if defined(__aarch64__)
+// see <uapi/asm/hwcap.h> kernel header
+#define HWCAP_FP                (1 << 0)
+#define HWCAP_ASIMD             (1 << 1)
+#define HWCAP_AES               (1 << 3)
+#define HWCAP_PMULL             (1 << 4)
+#define HWCAP_SHA1              (1 << 5)
+#define HWCAP_SHA2              (1 << 6)
+#define HWCAP_CRC32             (1 << 7)
+#endif
+
+#if defined(__arm__)
 
 // See <asm/hwcap.h> kernel header.
 #define HWCAP_VFP       (1 << 6)
@@ -419,16 +451,78 @@
 #define HWCAP_IDIVA     (1 << 17)
 #define HWCAP_IDIVT     (1 << 18)
 
-#define AT_HWCAP 16
+// see <uapi/asm/hwcap.h> kernel header
+#define HWCAP2_AES     (1 << 0)
+#define HWCAP2_PMULL   (1 << 1)
+#define HWCAP2_SHA1    (1 << 2)
+#define HWCAP2_SHA2    (1 << 3)
+#define HWCAP2_CRC32   (1 << 4)
 
-/* Read the ELF HWCAP flags by parsing /proc/self/auxv
- */
+// This is the list of 32-bit ARMv7 optional features that are _always_
+// supported by ARMv8 CPUs, as mandated by the ARM Architecture Reference
+// Manual.
+#define HWCAP_SET_FOR_ARMV8  \
+  ( HWCAP_VFP | \
+    HWCAP_NEON | \
+    HWCAP_VFPv3 | \
+    HWCAP_VFPv4 | \
+    HWCAP_IDIVA | \
+    HWCAP_IDIVT )
+#endif
+
+#if defined(__arm__) || defined(__aarch64__)
+
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+
+// Probe the system's C library for a 'getauxval' function and call it if
+// it exits, or return 0 for failure. This function is available since API
+// level 20.
+//
+// This code does *NOT* check for '__ANDROID_API__ >= 20' to support the
+// edge case where some NDK developers use headers for a platform that is
+// newer than the one really targetted by their application.
+// This is typically done to use newer native APIs only when running on more
+// recent Android versions, and requires careful symbol management.
+//
+// Note that getauxval() can't really be re-implemented here, because
+// its implementation does not parse /proc/self/auxv. Instead it depends
+// on values  that are passed by the kernel at process-init time to the
+// C runtime initialization layer.
 static uint32_t
-get_elf_hwcap(void)
-{
-    uint32_t result = 0;
+get_elf_hwcap_from_getauxval(int hwcap_type) {
+    typedef unsigned long getauxval_func_t(unsigned long);
+
+    dlerror();
+    void* libc_handle = dlopen("libc.so", RTLD_NOW);
+    if (!libc_handle) {
+        D("Could not dlopen() C library: %s\n", dlerror());
+        return 0;
+    }
+
+    uint32_t ret = 0;
+    getauxval_func_t* func = (getauxval_func_t*)
+            dlsym(libc_handle, "getauxval");
+    if (!func) {
+        D("Could not find getauxval() in C library\n");
+    } else {
+        // Note: getauxval() returns 0 on failure. Doesn't touch errno.
+        ret = (uint32_t)(*func)(hwcap_type);
+    }
+    dlclose(libc_handle);
+    return ret;
+}
+#endif
+
+#if defined(__arm__)
+// Parse /proc/self/auxv to extract the ELF HW capabilities bitmap for the
+// current CPU. Note that this file is not accessible from regular
+// application processes on some Android platform releases.
+// On success, return new ELF hwcaps, or 0 on failure.
+static uint32_t
+get_elf_hwcap_from_proc_self_auxv(void) {
     const char filepath[] = "/proc/self/auxv";
-    int fd = open(filepath, O_RDONLY);
+    int fd = TEMP_FAILURE_RETRY(open(filepath, O_RDONLY));
     if (fd < 0) {
         D("Could not open %s: %s\n", filepath, strerror(errno));
         return 0;
@@ -436,11 +530,10 @@
 
     struct { uint32_t tag; uint32_t value; } entry;
 
+    uint32_t result = 0;
     for (;;) {
-        int ret = read(fd, (char*)&entry, sizeof entry);
+        int ret = TEMP_FAILURE_RETRY(read(fd, (char*)&entry, sizeof entry));
         if (ret < 0) {
-            if (errno == EINTR)
-                continue;
             D("Error while reading %s: %s\n", filepath, strerror(errno));
             break;
         }
@@ -456,6 +549,74 @@
     return result;
 }
 
+/* Compute the ELF HWCAP flags from the content of /proc/cpuinfo.
+ * This works by parsing the 'Features' line, which lists which optional
+ * features the device's CPU supports, on top of its reference
+ * architecture.
+ */
+static uint32_t
+get_elf_hwcap_from_proc_cpuinfo(const char* cpuinfo, int cpuinfo_len) {
+    uint32_t hwcaps = 0;
+    long architecture = 0;
+    char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture");
+    if (cpuArch) {
+        architecture = strtol(cpuArch, NULL, 10);
+        free(cpuArch);
+
+        if (architecture >= 8L) {
+            // This is a 32-bit ARM binary running on a 64-bit ARM64 kernel.
+            // The 'Features' line only lists the optional features that the
+            // device's CPU supports, compared to its reference architecture
+            // which are of no use for this process.
+            D("Faking 32-bit ARM HWCaps on ARMv%ld CPU\n", architecture);
+            return HWCAP_SET_FOR_ARMV8;
+        }
+    }
+
+    char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features");
+    if (cpuFeatures != NULL) {
+        D("Found cpuFeatures = '%s'\n", cpuFeatures);
+
+        if (has_list_item(cpuFeatures, "vfp"))
+            hwcaps |= HWCAP_VFP;
+        if (has_list_item(cpuFeatures, "vfpv3"))
+            hwcaps |= HWCAP_VFPv3;
+        if (has_list_item(cpuFeatures, "vfpv3d16"))
+            hwcaps |= HWCAP_VFPv3D16;
+        if (has_list_item(cpuFeatures, "vfpv4"))
+            hwcaps |= HWCAP_VFPv4;
+        if (has_list_item(cpuFeatures, "neon"))
+            hwcaps |= HWCAP_NEON;
+        if (has_list_item(cpuFeatures, "idiva"))
+            hwcaps |= HWCAP_IDIVA;
+        if (has_list_item(cpuFeatures, "idivt"))
+            hwcaps |= HWCAP_IDIVT;
+        if (has_list_item(cpuFeatures, "idiv"))
+            hwcaps |= HWCAP_IDIVA | HWCAP_IDIVT;
+        if (has_list_item(cpuFeatures, "iwmmxt"))
+            hwcaps |= HWCAP_IWMMXT;
+
+        free(cpuFeatures);
+    }
+    return hwcaps;
+}
+
+/* Check Houdini Binary Translator is installed on the system.
+ *
+ * If this function returns 1, get_elf_hwcap_from_getauxval() function
+ * will causes SIGSEGV while calling getauxval() function.
+ */
+static int
+has_houdini_binary_translator(void) {
+    int found = 0;
+    if (access("/system/lib/libhoudini.so", F_OK) != -1) {
+        D("Found Houdini binary translator\n");
+        found = 1;
+    }
+    return found;
+}
+#endif  /* __arm__ */
+
 /* Return the number of cpus present on a given device.
  *
  * To handle all weird kernel configurations, we need to compute the
@@ -482,12 +643,19 @@
 static void
 android_cpuInitFamily(void)
 {
-#if defined(__ARM_ARCH__)
+#if defined(__arm__)
     g_cpuFamily = ANDROID_CPU_FAMILY_ARM;
 #elif defined(__i386__)
     g_cpuFamily = ANDROID_CPU_FAMILY_X86;
-#elif defined(_MIPS_ARCH)
+#elif defined(__mips64)
+/* Needs to be before __mips__ since the compiler defines both */
+    g_cpuFamily = ANDROID_CPU_FAMILY_MIPS64;
+#elif defined(__mips__)
     g_cpuFamily = ANDROID_CPU_FAMILY_MIPS;
+#elif defined(__aarch64__)
+    g_cpuFamily = ANDROID_CPU_FAMILY_ARM64;
+#elif defined(__x86_64__)
+    g_cpuFamily = ANDROID_CPU_FAMILY_X86_64;
 #else
     g_cpuFamily = ANDROID_CPU_FAMILY_UNKNOWN;
 #endif
@@ -532,11 +700,8 @@
 
     D("found cpuCount = %d\n", g_cpuCount);
 
-#ifdef __ARM_ARCH__
+#ifdef __arm__
     {
-        char*  features = NULL;
-        char*  architecture = NULL;
-
         /* Extract architecture from the "CPU Architecture" field.
          * The list is well-known, unlike the the output of
          * the 'Processor' field which can vary greatly.
@@ -557,10 +722,7 @@
             /* read the initial decimal number, ignore the rest */
             archNumber = strtol(cpuArch, &end, 10);
 
-            /* Here we assume that ARMv8 will be upwards compatible with v7
-             * in the future. Unfortunately, there is no 'Features' field to
-             * indicate that Thumb-2 is supported.
-             */
+            /* Note that ARMv8 is upwards compatible with ARMv7. */
             if (end > cpuArch && archNumber >= 7) {
                 hasARMv7 = 1;
             }
@@ -600,8 +762,25 @@
             free(cpuArch);
         }
 
+        /* Check Houdini binary translator is installed */
+        int has_houdini = has_houdini_binary_translator();
+
         /* Extract the list of CPU features from ELF hwcaps */
-        uint32_t hwcaps = get_elf_hwcap();
+        uint32_t hwcaps = 0;
+        if (!has_houdini) {
+            hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP);
+        }
+        if (!hwcaps) {
+            D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
+            hwcaps = get_elf_hwcap_from_proc_self_auxv();
+        }
+        if (!hwcaps) {
+            // Parsing /proc/self/auxv will fail from regular application
+            // processes on some Android platform versions, when this happens
+            // parse proc/cpuinfo instead.
+            D("Parsing /proc/cpuinfo to extract ELF hwcaps!\n");
+            hwcaps = get_elf_hwcap_from_proc_cpuinfo(cpuinfo, cpuinfo_len);
+        }
 
         if (hwcaps != 0) {
             int has_vfp = (hwcaps & HWCAP_VFP);
@@ -618,9 +797,9 @@
 
             // 'vfpv4' implies VFPv3|VFP_FMA|FP16
             if (has_vfpv4)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3    |
-                               ANDROID_CPU_ARM_FEATURE_VFP_FP16 |
-                               ANDROID_CPU_ARM_FEATURE_VFP_FMA;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3    |
+                                 ANDROID_CPU_ARM_FEATURE_VFP_FP16 |
+                                 ANDROID_CPU_ARM_FEATURE_VFP_FMA;
 
             // 'vfpv3' or 'vfpv3d16' imply VFPv3. Note that unlike GCC,
             // a value of 'vfpv3' doesn't necessarily mean that the D32
@@ -628,45 +807,188 @@
             // field that support D32 also support NEON, so this should
             // not be a problem in practice.
             if (has_vfpv3 || has_vfpv3d16)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
 
             // 'vfp' is super ambiguous. Depending on the kernel, it can
             // either mean VFPv2 or VFPv3. Make it depend on ARMv7.
             if (has_vfp) {
               if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7)
-                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+                  g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
               else
-                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
+                  g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
             }
 
             // Neon implies VFPv3|D32, and if vfpv4 is detected, NEON_FMA
             if (has_neon) {
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
-                               ANDROID_CPU_ARM_FEATURE_NEON |
-                               ANDROID_CPU_ARM_FEATURE_VFP_D32;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
+                                 ANDROID_CPU_ARM_FEATURE_NEON |
+                                 ANDROID_CPU_ARM_FEATURE_VFP_D32;
               if (has_vfpv4)
-                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
+                  g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
             }
 
             // VFPv3 implies VFPv2 and ARMv7
             if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_VFPv3)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 |
-                               ANDROID_CPU_ARM_FEATURE_ARMv7;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 |
+                                 ANDROID_CPU_ARM_FEATURE_ARMv7;
 
-            // Note that some buggy kernels do not report these even when
-            // the CPU actually support the division instructions. However,
-            // assume that if 'vfpv4' is detected, then the CPU supports
-            // sdiv/udiv properly.
-            if (has_idiva || has_vfpv4)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
-            if (has_idivt || has_vfpv4)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
+            if (has_idiva)
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
+            if (has_idivt)
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
 
             if (has_iwmmxt)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt;
+        }
+
+        /* Extract the list of CPU features from ELF hwcaps2 */
+        uint32_t hwcaps2 = 0;
+        if (!has_houdini) {
+            hwcaps2 = get_elf_hwcap_from_getauxval(AT_HWCAP2);
+        }
+        if (hwcaps2 != 0) {
+            int has_aes     = (hwcaps2 & HWCAP2_AES);
+            int has_pmull   = (hwcaps2 & HWCAP2_PMULL);
+            int has_sha1    = (hwcaps2 & HWCAP2_SHA1);
+            int has_sha2    = (hwcaps2 & HWCAP2_SHA2);
+            int has_crc32   = (hwcaps2 & HWCAP2_CRC32);
+
+            if (has_aes)
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_AES;
+            if (has_pmull)
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_PMULL;
+            if (has_sha1)
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA1;
+            if (has_sha2)
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA2;
+            if (has_crc32)
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32;
+        }
+        /* Extract the cpuid value from various fields */
+        // The CPUID value is broken up in several entries in /proc/cpuinfo.
+        // This table is used to rebuild it from the entries.
+        static const struct CpuIdEntry {
+            const char* field;
+            char        format;
+            char        bit_lshift;
+            char        bit_length;
+        } cpu_id_entries[] = {
+            { "CPU implementer", 'x', 24, 8 },
+            { "CPU variant", 'x', 20, 4 },
+            { "CPU part", 'x', 4, 12 },
+            { "CPU revision", 'd', 0, 4 },
+        };
+        size_t i;
+        D("Parsing /proc/cpuinfo to recover CPUID\n");
+        for (i = 0;
+             i < sizeof(cpu_id_entries)/sizeof(cpu_id_entries[0]);
+             ++i) {
+            const struct CpuIdEntry* entry = &cpu_id_entries[i];
+            char* value = extract_cpuinfo_field(cpuinfo,
+                                                cpuinfo_len,
+                                                entry->field);
+            if (value == NULL)
+                continue;
+
+            D("field=%s value='%s'\n", entry->field, value);
+            char* value_end = value + strlen(value);
+            int val = 0;
+            const char* start = value;
+            const char* p;
+            if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
+              start += 2;
+              p = parse_hexadecimal(start, value_end, &val);
+            } else if (entry->format == 'x')
+              p = parse_hexadecimal(value, value_end, &val);
+            else
+              p = parse_decimal(value, value_end, &val);
+
+            if (p > (const char*)start) {
+              val &= ((1 << entry->bit_length)-1);
+              val <<= entry->bit_lshift;
+              g_cpuIdArm |= (uint32_t) val;
+            }
+
+            free(value);
+        }
+
+        // Handle kernel configuration bugs that prevent the correct
+        // reporting of CPU features.
+        static const struct CpuFix {
+            uint32_t  cpuid;
+            uint64_t  or_flags;
+        } cpu_fixes[] = {
+            /* The Nexus 4 (Qualcomm Krait) kernel configuration
+             * forgets to report IDIV support. */
+            { 0x510006f2, ANDROID_CPU_ARM_FEATURE_IDIV_ARM |
+                          ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 },
+            { 0x510006f3, ANDROID_CPU_ARM_FEATURE_IDIV_ARM |
+                          ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 },
+        };
+        size_t n;
+        for (n = 0; n < sizeof(cpu_fixes)/sizeof(cpu_fixes[0]); ++n) {
+            const struct CpuFix* entry = &cpu_fixes[n];
+
+            if (g_cpuIdArm == entry->cpuid)
+                g_cpuFeatures |= entry->or_flags;
+        }
+
+        // Special case: The emulator-specific Android 4.2 kernel fails
+        // to report support for the 32-bit ARM IDIV instruction.
+        // Technically, this is a feature of the virtual CPU implemented
+        // by the emulator. Note that it could also support Thumb IDIV
+        // in the future, and this will have to be slightly updated.
+        char* hardware = extract_cpuinfo_field(cpuinfo,
+                                               cpuinfo_len,
+                                               "Hardware");
+        if (hardware) {
+            if (!strcmp(hardware, "Goldfish") &&
+                g_cpuIdArm == 0x4100c080 &&
+                (g_cpuFamily & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0) {
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
+            }
+            free(hardware);
         }
     }
-#endif /* __ARM_ARCH__ */
+#endif /* __arm__ */
+#ifdef __aarch64__
+    {
+        /* Extract the list of CPU features from ELF hwcaps */
+        uint32_t hwcaps = 0;
+        hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP);
+        if (hwcaps != 0) {
+            int has_fp      = (hwcaps & HWCAP_FP);
+            int has_asimd   = (hwcaps & HWCAP_ASIMD);
+            int has_aes     = (hwcaps & HWCAP_AES);
+            int has_pmull   = (hwcaps & HWCAP_PMULL);
+            int has_sha1    = (hwcaps & HWCAP_SHA1);
+            int has_sha2    = (hwcaps & HWCAP_SHA2);
+            int has_crc32   = (hwcaps & HWCAP_CRC32);
+
+            if(has_fp == 0) {
+                D("ERROR: Floating-point unit missing, but is required by Android on AArch64 CPUs\n");
+            }
+            if(has_asimd == 0) {
+                D("ERROR: ASIMD unit missing, but is required by Android on AArch64 CPUs\n");
+            }
+
+            if (has_fp)
+                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_FP;
+            if (has_asimd)
+                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_ASIMD;
+            if (has_aes)
+                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_AES;
+            if (has_pmull)
+                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_PMULL;
+            if (has_sha1)
+                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA1;
+            if (has_sha2)
+                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA2;
+            if (has_crc32)
+                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_CRC32;
+        }
+    }
+#endif /* __aarch64__ */
 
 #ifdef __i386__
     int regs[4];
@@ -741,6 +1063,25 @@
     return 1;
 }
 
+#ifdef __arm__
+uint32_t
+android_getCpuIdArm(void)
+{
+    pthread_once(&g_once, android_cpuInit);
+    return g_cpuIdArm;
+}
+
+int
+android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id)
+{
+    if (!android_setCpu(cpu_count, cpu_features))
+        return 0;
+
+    g_cpuIdArm = cpu_id;
+    return 1;
+}
+#endif  /* __arm__ */
+
 /*
  * Technical note: Making sense of ARM's FPU architecture versions.
  *
@@ -925,3 +1266,5 @@
  * ARCH_NEON_FP16 (+EXT_FP16)
  *
  */
+
+#endif // defined(__le32__) || defined(__le64__)
diff --git a/platform_tools/android/third_party/cpufeatures/cpu-features.h b/platform_tools/android/third_party/cpufeatures/cpu-features.h
index f8553e8..e86cba8 100644
--- a/platform_tools/android/third_party/cpufeatures/cpu-features.h
+++ b/platform_tools/android/third_party/cpufeatures/cpu-features.h
@@ -33,21 +33,48 @@
 
 __BEGIN_DECLS
 
+/* A list of valid values returned by android_getCpuFamily().
+ * They describe the CPU Architecture of the current process.
+ */
 typedef enum {
     ANDROID_CPU_FAMILY_UNKNOWN = 0,
     ANDROID_CPU_FAMILY_ARM,
     ANDROID_CPU_FAMILY_X86,
     ANDROID_CPU_FAMILY_MIPS,
+    ANDROID_CPU_FAMILY_ARM64,
+    ANDROID_CPU_FAMILY_X86_64,
+    ANDROID_CPU_FAMILY_MIPS64,
 
     ANDROID_CPU_FAMILY_MAX  /* do not remove */
 
 } AndroidCpuFamily;
 
-/* Return family of the device's CPU */
-extern AndroidCpuFamily   android_getCpuFamily(void);
+/* Return the CPU family of the current process.
+ *
+ * Note that this matches the bitness of the current process. I.e. when
+ * running a 32-bit binary on a 64-bit capable CPU, this will return the
+ * 32-bit CPU family value.
+ */
+extern AndroidCpuFamily android_getCpuFamily(void);
 
-/* The list of feature flags for ARM CPUs that can be recognized by the
- * library. Value details are:
+/* Return a bitmap describing a set of optional CPU features that are
+ * supported by the current device's CPU. The exact bit-flags returned
+ * depend on the value returned by android_getCpuFamily(). See the
+ * documentation for the ANDROID_CPU_*_FEATURE_* flags below for details.
+ *
+ * NOTE: This will return 0 for the following architectures that don't have
+ *       optional features listed at the moment:
+ *
+ *   ANDROID_CPU_FAMILY_MIPS
+ *   ANDROID_CPU_FAMILY_ARM64
+ *   ANDROID_CPU_FAMILY_X86_64
+ *   ANDROID_CPU_FAMILY_MIPS64
+ */
+extern uint64_t android_getCpuFeatures(void);
+
+/* The list of feature flags for ANDROID_CPU_FAMILY_ARM that can be
+ * recognized by the library (see note below for 64-bit ARM). Value details
+ * are:
  *
  *   VFPv2:
  *     CPU supports the VFPv2 instruction set. Many, but not all, ARMv6 CPUs
@@ -103,6 +130,27 @@
  *     ARM CPU. This is only available on a few XScale-based CPU designs
  *     sold by Marvell. Pretty rare in practice.
  *
+ *   AES:
+ *     CPU supports AES instructions. These instructions are only
+ *     available for 32-bit applications running on ARMv8 CPU.
+ *
+ *   CRC32:
+ *     CPU supports CRC32 instructions. These instructions are only
+ *     available for 32-bit applications running on ARMv8 CPU.
+ *
+ *   SHA2:
+ *     CPU supports SHA2 instructions. These instructions are only
+ *     available for 32-bit applications running on ARMv8 CPU.
+ *
+ *   SHA1:
+ *     CPU supports SHA1 instructions. These instructions are only
+ *     available for 32-bit applications running on ARMv8 CPU.
+ *
+ *   PMULL:
+ *     CPU supports 64-bit PMULL and PMULL2 instructions. These
+ *     instructions are only available for 32-bit applications
+ *     running on ARMv8 CPU.
+ *
  * If you want to tell the compiler to generate code that targets one of
  * the feature set above, you should probably use one of the following
  * flags (for more details, see technical note at the end of this file):
@@ -150,6 +198,13 @@
  *
  *   -mcpu=iwmmxt
  *     Allows the use of iWMMXt instrinsics with GCC.
+ *
+ * IMPORTANT NOTE: These flags should only be tested when
+ * android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM, i.e. this is a
+ * 32-bit process.
+ *
+ * When running a 64-bit ARM process on an ARMv8 CPU,
+ * android_getCpuFeatures() will return a different set of bitflags
  */
 enum {
     ANDROID_CPU_ARM_FEATURE_ARMv7       = (1 << 0),
@@ -164,18 +219,58 @@
     ANDROID_CPU_ARM_FEATURE_IDIV_ARM    = (1 << 9),
     ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 = (1 << 10),
     ANDROID_CPU_ARM_FEATURE_iWMMXt      = (1 << 11),
+    ANDROID_CPU_ARM_FEATURE_AES         = (1 << 12),
+    ANDROID_CPU_ARM_FEATURE_PMULL       = (1 << 13),
+    ANDROID_CPU_ARM_FEATURE_SHA1        = (1 << 14),
+    ANDROID_CPU_ARM_FEATURE_SHA2        = (1 << 15),
+    ANDROID_CPU_ARM_FEATURE_CRC32       = (1 << 16),
 };
 
+/* The bit flags corresponding to the output of android_getCpuFeatures()
+ * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM64. Value details
+ * are:
+ *
+ *   FP:
+ *     CPU has Floating-point unit.
+ *
+ *   ASIMD:
+ *     CPU has Advanced SIMD unit.
+ *
+ *   AES:
+ *     CPU supports AES instructions.
+ *
+ *   CRC32:
+ *     CPU supports CRC32 instructions.
+ *
+ *   SHA2:
+ *     CPU supports SHA2 instructions.
+ *
+ *   SHA1:
+ *     CPU supports SHA1 instructions.
+ *
+ *   PMULL:
+ *     CPU supports 64-bit PMULL and PMULL2 instructions.
+ */
+enum {
+    ANDROID_CPU_ARM64_FEATURE_FP      = (1 << 0),
+    ANDROID_CPU_ARM64_FEATURE_ASIMD   = (1 << 1),
+    ANDROID_CPU_ARM64_FEATURE_AES     = (1 << 2),
+    ANDROID_CPU_ARM64_FEATURE_PMULL   = (1 << 3),
+    ANDROID_CPU_ARM64_FEATURE_SHA1    = (1 << 4),
+    ANDROID_CPU_ARM64_FEATURE_SHA2    = (1 << 5),
+    ANDROID_CPU_ARM64_FEATURE_CRC32   = (1 << 6),
+};
+/* The bit flags corresponding to the output of android_getCpuFeatures()
+ * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_X86.
+ */
 enum {
     ANDROID_CPU_X86_FEATURE_SSSE3  = (1 << 0),
     ANDROID_CPU_X86_FEATURE_POPCNT = (1 << 1),
     ANDROID_CPU_X86_FEATURE_MOVBE  = (1 << 2),
 };
 
-extern uint64_t    android_getCpuFeatures(void);
-
 /* Return the number of CPU cores detected on this device. */
-extern int         android_getCpuCount(void);
+extern int android_getCpuCount(void);
 
 /* The following is used to force the CPU count and features
  * mask in sandboxed processes. Under 4.1 and higher, these processes
@@ -190,6 +285,21 @@
 extern int android_setCpu(int      cpu_count,
                           uint64_t cpu_features);
 
+#ifdef __arm__
+/* Retrieve the ARM 32-bit CPUID value from the kernel.
+ * Note that this cannot work on sandboxed processes under 4.1 and
+ * higher, unless you called android_setCpuArm() before.
+ */
+extern uint32_t android_getCpuIdArm(void);
+
+/* An ARM-specific variant of android_setCpu() that also allows you
+ * to set the ARM CPUID field.
+ */
+extern int android_setCpuArm(int      cpu_count,
+                             uint64_t cpu_features,
+                             uint32_t cpu_id);
+#endif
+
 __END_DECLS
 
 #endif /* CPU_FEATURES_H */