Test for required hwcaps on ARMv8

Several optional ARMv7 features are now required on ARMv8.  Ensure
getauxval(AT_HWCAP) works on ARMv8 devices and reports the required
flags to 32-bit processes.

Bug: 13679666
Bug: 15940803

Change-Id: I2947809b3b1a09121765fc1adaf26e88ea639f04
Signed-off-by: Greg Hackmann <ghackmann@google.com>
diff --git a/tests/jni/android_os_cts_CpuFeatures.cpp b/tests/jni/android_os_cts_CpuFeatures.cpp
index 5276257..6b5950c 100644
--- a/tests/jni/android_os_cts_CpuFeatures.cpp
+++ b/tests/jni/android_os_cts_CpuFeatures.cpp
@@ -17,6 +17,7 @@
 #include <cpu-features.h>
 #include <jni.h>
 #include <string.h>
+#include <sys/auxv.h>
 
 jboolean android_os_cts_CpuFeatures_isArmCpu(JNIEnv* env, jobject thiz)
 {
@@ -60,6 +61,11 @@
     return cpuFamily == ANDROID_CPU_FAMILY_X86_64;
 }
 
+jint android_os_cts_CpuFeatures_getHwCaps(JNIEnv*, jobject)
+{
+    return (jint)getauxval(AT_HWCAP);
+}
+
 static JNINativeMethod gMethods[] = {
     {  "isArmCpu", "()Z",
             (void *) android_os_cts_CpuFeatures_isArmCpu  },
@@ -75,6 +81,8 @@
             (void *) android_os_cts_CpuFeatures_isMips64Cpu  },
     {  "isX86_64Cpu", "()Z",
             (void *) android_os_cts_CpuFeatures_isX86_64Cpu  },
+    {  "getHwCaps", "()I",
+            (void *) android_os_cts_CpuFeatures_getHwCaps  },
 };
 
 int register_android_os_cts_CpuFeatures(JNIEnv* env)
diff --git a/tests/src/android/os/cts/CpuFeatures.java b/tests/src/android/os/cts/CpuFeatures.java
index b767da2..fa6628b2 100644
--- a/tests/src/android/os/cts/CpuFeatures.java
+++ b/tests/src/android/os/cts/CpuFeatures.java
@@ -16,6 +16,8 @@
 
 package android.os.cts;
 
+import android.os.Build;
+
 public class CpuFeatures {
 
     public static final String ARMEABI_V7 = "armeabi-v7a";
@@ -26,6 +28,18 @@
 
     public static final  String X86ABI = "x86";
 
+    public static final int HWCAP_VFP = (1 << 6);
+
+    public static final int HWCAP_NEON = (1 << 12);
+
+    public static final int HWCAP_VFPv3 = (1 << 13);
+
+    public static final int HWCAP_VFPv4 = (1 << 16);
+
+    public static final int HWCAP_IDIVA = (1 << 17);
+
+    public static final int HWCAP_IDIVT = (1 << 18);
+
     static {
         System.loadLibrary("cts_jni");
     }
@@ -43,4 +57,20 @@
     public static native boolean isMips64Cpu();
 
     public static native boolean isX86_64Cpu();
+
+    public static native int getHwCaps();
+
+    public static boolean isArm64CpuIn32BitMode() {
+        if (!isArmCpu()) {
+            return false;
+        }
+
+        for (String abi : Build.SUPPORTED_64_BIT_ABIS) {
+            if (abi.equals("arm64-v8a")) {
+                return true;
+            }
+        }
+
+        return false;
+    }
 }
diff --git a/tests/tests/os/src/android/os/cts/CpuFeaturesTest.java b/tests/tests/os/src/android/os/cts/CpuFeaturesTest.java
new file mode 100644
index 0000000..61141e5
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/CpuFeaturesTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.os.cts;
+
+import android.os.cts.CpuFeatures;
+
+import junit.framework.TestCase;
+
+public class CpuFeaturesTest extends TestCase {
+
+    private static void assertHwCap(String name, int hwcaps, int flag) {
+        assertEquals("Machine does not advertise " + name + " support", flag,
+                hwcaps & flag);
+    }
+
+    public void testArm64RequiredHwCaps() {
+        if (!CpuFeatures.isArm64CpuIn32BitMode()) {
+            return;
+        }
+
+        int hwcaps = CpuFeatures.getHwCaps();
+
+        assertFalse("Machine does not support getauxval(AT_HWCAP)",
+                hwcaps == 0);
+
+        assertHwCap("VFP", hwcaps, CpuFeatures.HWCAP_VFP);
+        assertHwCap("NEON", hwcaps, CpuFeatures.HWCAP_NEON);
+        assertHwCap("VFPv3", hwcaps, CpuFeatures.HWCAP_VFPv3);
+        assertHwCap("VFPv4", hwcaps, CpuFeatures.HWCAP_VFPv4);
+        assertHwCap("IDIVA", hwcaps, CpuFeatures.HWCAP_IDIVA);
+        assertHwCap("IDIVT", hwcaps, CpuFeatures.HWCAP_IDIVT);
+    }
+}