Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 package android.os.cts;
     19 
     20 import java.io.BufferedReader;
     21 import java.io.FileReader;
     22 import java.io.IOException;
     23 import java.util.Arrays;
     24 import java.util.List;
     25 import java.util.regex.Matcher;
     26 import java.util.regex.Pattern;
     27 
     28 import com.android.compatibility.common.util.CpuFeatures;
     29 
     30 import junit.framework.TestCase;
     31 
     32 public class CpuFeaturesTest extends TestCase {
     33 
     34     private static void assertHwCap(String name, int hwcaps, int flag) {
     35         assertEquals("Machine does not advertise " + name + " support", flag,
     36                 hwcaps & flag);
     37     }
     38 
     39     public void testArm64RequiredHwCaps() {
     40         if (!CpuFeatures.isArm64CpuIn32BitMode()) {
     41             return;
     42         }
     43 
     44         int hwcaps = CpuFeatures.getHwCaps();
     45 
     46         assertFalse("Machine does not support getauxval(AT_HWCAP)",
     47                 hwcaps == 0);
     48 
     49         assertHwCap("VFP", hwcaps, CpuFeatures.HWCAP_VFP);
     50         assertHwCap("NEON", hwcaps, CpuFeatures.HWCAP_NEON);
     51         assertHwCap("VFPv3", hwcaps, CpuFeatures.HWCAP_VFPv3);
     52         assertHwCap("VFPv4", hwcaps, CpuFeatures.HWCAP_VFPv4);
     53         assertHwCap("IDIVA", hwcaps, CpuFeatures.HWCAP_IDIVA);
     54         assertHwCap("IDIVT", hwcaps, CpuFeatures.HWCAP_IDIVT);
     55     }
     56 
     57     private static String getFieldFromCpuinfo(String field) throws IOException {
     58         BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo"));
     59         Pattern p = Pattern.compile(field + "\\s*:\\s*(.*)");
     60 
     61         try {
     62             String line;
     63             while ((line = br.readLine()) != null) {
     64                 Matcher m = p.matcher(line);
     65                 if (m.matches()) {
     66                     return m.group(1);
     67                 }
     68             }
     69        } finally {
     70            br.close();
     71        }
     72 
     73        return null;
     74     }
     75 
     76     private static List<String> getFeaturesFromCpuinfo() throws IOException {
     77         String features = getFieldFromCpuinfo("Features");
     78         if (features == null)
     79             return null;
     80 
     81         return Arrays.asList(features.split("\\s"));
     82     }
     83 
     84     private static final String[] armv8RequiredFeatures = {
     85             "half", "thumb", "fastmult", "vfp", "edsp", "neon",
     86             "vfpv3", "vfpv4", "idiva", "idivt" };
     87 
     88     private static void assertInCpuinfo(List<String> features,
     89             String feature) {
     90         assertTrue("/proc/cpuinfo does not advertise required feature " + feature + " to 32-bit ARM processes",
     91                 features.contains(feature));
     92     }
     93 
     94     private static void assertNotInCpuinfo(List<String> features,
     95             String feature) {
     96         assertFalse("/proc/cpuinfo advertises required feature " + feature + " to 64-bit ARM processes",
     97                 features.contains(feature));
     98     }
     99 
    100     public void testArmCpuinfo() throws IOException {
    101         if (!CpuFeatures.isArmCpu())
    102             return;
    103 
    104         String cpuArch = getFieldFromCpuinfo("CPU architecture");
    105         /* When /proc/cpuinfo is read by 32-bit ARM processes, the CPU
    106          * architecture field must be present and contain an integer.
    107          */
    108         assertNotNull("Failed to read CPU architecture field from /proc/cpuinfo",
    109                 cpuArch);
    110 
    111         int cpuArchInt = 0;
    112         try {
    113             cpuArchInt = Integer.parseInt(cpuArch);
    114         } catch (NumberFormatException e) {
    115             fail("/proc/cpuinfo reported non-integer CPU architecture " + cpuArch);
    116         }
    117 
    118         if (CpuFeatures.isArm64CpuIn32BitMode()) {
    119             assertTrue("/proc/cpuinfo reported 32-bit only CPU architecture " + cpuArchInt + " on ARM64 CPU",
    120                     cpuArchInt >= 8);
    121         }
    122 
    123         List<String> features = getFeaturesFromCpuinfo();
    124         /* When /proc/cpuinfo is read by 32-bit ARM processes, the Features
    125          * field must be present.  On ARMv8+ devices specifically, it must
    126          * include ARMv7-optional features that are now required by ARMv8.
    127          */
    128         assertNotNull("Failed to read Features field from /proc/cpuinfo",
    129                 features);
    130 
    131         if (CpuFeatures.isArm64CpuIn32BitMode()) {
    132             for (String feature : armv8RequiredFeatures) {
    133                 assertInCpuinfo(features, feature);
    134             }
    135         }
    136     }
    137 
    138     public void testArm64Cpuinfo() throws IOException {
    139         if (!CpuFeatures.isArm64Cpu()) {
    140             return;
    141         }
    142 
    143         List<String> features = getFeaturesFromCpuinfo();
    144         /* When /proc/cpuinfo is read by 64-bit ARM processes, the Features
    145          * field in /proc/cpuinfo must not include ARMv8-required features.
    146          * This can be satisified either by not listing required features, or by
    147          * not having a Features field at all.
    148          */
    149         if (features == null) {
    150             return;
    151         }
    152 
    153         for (String feature : armv8RequiredFeatures) {
    154             assertNotInCpuinfo(features, feature);
    155         }
    156     }
    157 }
    158