Merge "Move targetSDK-specific tests to SELinux CTS."
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index 97d5838..407b30f 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -885,6 +885,7 @@
 java_system_modules {
     name: "art-module-public-api-stubs-system-modules",
     visibility: [
+        "//art/build/sdk",
         "//external/conscrypt",
         "//external/icu/android_icu4j",
         "//external/wycheproof",
diff --git a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
index f5136a4..d0a449b 100644
--- a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
@@ -159,6 +159,20 @@
     }
 
     /**
+     * Computes the classloader contexts for each classpath entry in {@code pathList.getDexPaths()}.
+     *
+     * Note that this method is not thread safe, i.e. it is the responsibility of the caller to
+     * ensure that {@code pathList.getDexPaths()} is not modified concurrently with this method
+     * being called.
+     *
+     * @return A non-null array of non-null strings of length
+     *   {@code 2 * pathList.getDexPaths().size()}. Every even index (0 is even here) is a dex file
+     *   path and every odd entry is the class loader context used to load the previously listed dex
+     *   file. E.g. a result might be {@code { "foo.dex", "PCL[]", "bar.dex", "PCL[foo.dex]" } }.
+     */
+    private native String[] computeClassLoaderContextsNative();
+
+    /**
      * Constructs an instance.
      *
      * dexFile must be an in-memory representation of a full dexFile.
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 6171cb6..863f85d 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -744,4 +744,15 @@
      */
     @libcore.api.CorePlatformApi
     public static native void setProcessDataDirectory(String dataDir);
+
+    /**
+     * Returns whether {@code encodedClassLoaderContext} is a valid encoded class loader context.
+     * A class loader context is an internal opaque format used by the runtime to encode the
+     * class loader hierarchy (including each ClassLoader's classpath) used to load a dex file.
+     *
+     * @return True if encodedClassLoaderContext is a non-null valid encoded class loader context.
+     *   Throws NullPointerException if encodedClassLoaderContext is null.
+     */
+    @libcore.api.CorePlatformApi
+    public static native boolean isValidClassLoaderContext(String encodedClassLoaderContext);
 }
diff --git a/luni/src/main/java/android/compat/TEST_MAPPING b/luni/src/main/java/android/compat/TEST_MAPPING
new file mode 100644
index 0000000..c8b07b4
--- /dev/null
+++ b/luni/src/main/java/android/compat/TEST_MAPPING
@@ -0,0 +1,17 @@
+{
+  "presubmit": [
+    // Unit tests for CoreCompatChangeRule
+    {
+      "name": "CtsLibcoreTestCases",
+      "options": [
+        {
+          "include-filter": "libcore.junit.util.compat"
+        }
+      ]
+    },
+    // CTS test for CompatChanges System
+    {
+      "name": "CtsAppCompatHostTestCases"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/javax/crypto/HardwareAesTest.java b/luni/src/test/java/libcore/javax/crypto/HardwareAesTest.java
new file mode 100644
index 0000000..f79bb81
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/crypto/HardwareAesTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 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 libcore.javax.crypto;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import libcore.java.security.CpuFeatures;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class HardwareAesTest {
+
+    @Test
+    public void hardwareAesAvailability() {
+        // Test is only applicable if we know for sure that the device should support
+        // hardware AES.  That covers the important cases (non-emulated ARM and x86_64),
+        // For everything else we assume BoringSSL does the right thing.
+        assumeTrue(CpuFeatures.isKnownToSupportHardwareAes());
+        assertTrue(CpuFeatures.isAesHardwareAccelerated());
+    }
+}
diff --git a/mmodules/core_platform_api/Android.bp b/mmodules/core_platform_api/Android.bp
index 0a8c381..f2a042b 100644
--- a/mmodules/core_platform_api/Android.bp
+++ b/mmodules/core_platform_api/Android.bp
@@ -85,6 +85,7 @@
 java_system_modules {
     name: "art-module-platform-api-stubs-system-modules",
     visibility: [
+        "//art/build/sdk",
         "//external/conscrypt",
         "//external/icu/android_icu4j",
         "//external/wycheproof",
diff --git a/mmodules/core_platform_api/api/platform/current-api.txt b/mmodules/core_platform_api/api/platform/current-api.txt
index c3a603c..707e3a3 100644
--- a/mmodules/core_platform_api/api/platform/current-api.txt
+++ b/mmodules/core_platform_api/api/platform/current-api.txt
@@ -698,6 +698,7 @@
     method public static boolean isBootClassPathOnDisk(String);
     method @dalvik.annotation.optimization.FastNative public boolean isCheckJniEnabled();
     method @dalvik.annotation.optimization.FastNative public boolean isNativeDebuggable();
+    method public static boolean isValidClassLoaderContext(String);
     method @dalvik.annotation.optimization.FastNative public Object newNonMovableArray(Class<?>, int);
     method @dalvik.annotation.optimization.FastNative public Object newUnpaddedArray(Class<?>, int);
     method public void notifyStartupCompleted();
diff --git a/mmodules/intracoreapi/Android.bp b/mmodules/intracoreapi/Android.bp
index f8454bb..c2a3de3 100644
--- a/mmodules/intracoreapi/Android.bp
+++ b/mmodules/intracoreapi/Android.bp
@@ -71,6 +71,7 @@
 java_system_modules {
     name: "art-module-intra-core-api-stubs-system-modules",
     visibility: [
+        "//art/build/sdk",
         "//external/bouncycastle",
         "//external/conscrypt",
         "//external/icu/android_icu4j",
diff --git a/ojluni/annotations/hiddenapi/java/lang/reflect/Field.java b/ojluni/annotations/hiddenapi/java/lang/reflect/Field.java
index 7e9b0b4..c11a65b 100644
--- a/ojluni/annotations/hiddenapi/java/lang/reflect/Field.java
+++ b/ojluni/annotations/hiddenapi/java/lang/reflect/Field.java
@@ -165,10 +165,6 @@
 
     public native java.lang.annotation.Annotation[] getDeclaredAnnotations();
 
-    public int getDexFieldIndex() {
-        throw new RuntimeException("Stub!");
-    }
-
     @UnsupportedAppUsage
     public int getOffset() {
         throw new RuntimeException("Stub!");
@@ -181,7 +177,7 @@
 
     private java.lang.Class<?> declaringClass;
 
-    private int dexFieldIndex;
+    private int artFieldIndex;
 
     private int offset;
 
diff --git a/ojluni/src/main/java/java/lang/reflect/Field.java b/ojluni/src/main/java/java/lang/reflect/Field.java
index 2bcf9e9..ca5857a 100644
--- a/ojluni/src/main/java/java/lang/reflect/Field.java
+++ b/ojluni/src/main/java/java/lang/reflect/Field.java
@@ -61,7 +61,7 @@
 
     private int accessFlags;
     private Class<?> declaringClass;
-    private int dexFieldIndex;
+    private int artFieldIndex;
     private int offset;
     private Class<?> type;
 
@@ -82,12 +82,17 @@
      */
     public String getName() {
         // Android-changed: getName() implemented differently.
-        if (dexFieldIndex == -1) {
+        if (declaringClass.isProxy()) {
             // Proxy classes have 1 synthesized static field with no valid dex index.
-            if (!declaringClass.isProxy()) {
-                throw new AssertionError();
+            if ((getModifiers() & Modifier.STATIC) == 0) {
+                throw new AssertionError("Invalid modifiers for proxy field: " + getModifiers());
             }
-            return "throws";
+            // Only 2 fields are present on proxy classes.
+            switch (artFieldIndex) {
+                case 0: return "interfaces";
+                case 1: return "throws";
+                default: throw new AssertionError("Invalid index for proxy: " + artFieldIndex);
+            }
         }
 
         return getNameInternal();
@@ -928,15 +933,6 @@
 
     // BEGIN Android-added: Methods for use by Android-specific code.
     /**
-     * Returns the index of this field's ID in its dex file.
-     *
-     * @hide
-     */
-    public int getDexFieldIndex() {
-        return dexFieldIndex;
-    }
-
-    /**
      * Returns the offset of the field within an instance, or for static fields, the class.
      *
      * @hide
diff --git a/ojluni/src/main/java/java/net/NetworkInterface.java b/ojluni/src/main/java/java/net/NetworkInterface.java
index c8044fd..d6cd330 100644
--- a/ojluni/src/main/java/java/net/NetworkInterface.java
+++ b/ojluni/src/main/java/java/net/NetworkInterface.java
@@ -47,7 +47,7 @@
 
 // Android-note: NetworkInterface has been rewritten to avoid native code.
 // Fix upstream bug not returning link-down interfaces. http://b/26238832
-// Android-added: Document restrictions for targetSdkVersion > 29. http://b/141455849
+// Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
 /**
  * This class represents a Network Interface made up of a name,
  * and a list of IP addresses assigned to this interface.
@@ -58,9 +58,9 @@
  * <p>
  * <a name="access-restrictions"></a>Note that information about
  * {@link NetworkInterface}s may be restricted. For example, non-system apps
- * with {@code targetSdkVersion > 29} will only have access to information
- * about {@link NetworkInterface}s that are associated with an
- * {@link InetAddress}.
+ * with {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R} will only
+ * have access to information about {@link NetworkInterface}s that are
+ * associated with an {@link Inet4Address}.
  *
  * @since 1.4
  */
@@ -272,7 +272,7 @@
         return "".equals(displayName) ? null : displayName;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion > 29. http://b/141455849
+    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
     /**
      * Searches for the network interface with the specified name.
      *
@@ -304,7 +304,7 @@
         return null;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion > 29. http://b/141455849
+    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
     /**
      * Get a network interface given its index.
      *
@@ -373,7 +373,7 @@
         return null;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion > 29. http://b/141455849
+    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
     /**
      * Returns all the interfaces on this machine. The {@code Enumeration}
      * contains at least one element, possibly representing a loopback
@@ -383,9 +383,10 @@
      * NOTE: can use getNetworkInterfaces()+getInetAddresses()
      *       to obtain all IP addresses for this node
      * <p>
-     * For non-system apps with {@code targetSdkVersion > 29}, this
+     * For non-system apps with
+     * {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R}, this
      * method will only return information for {@link NetworkInterface}s that
-     * are associated with an {@link InetAddress}.
+     * are associated with an {@link Inet4Address}.
      *
      * @return an Enumeration of NetworkInterfaces found on this machine
      *         that <a href="#access-restrictions">are accessible</a>.
@@ -558,7 +559,7 @@
         return (getFlags() & IFF_MULTICAST) != 0;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion > 29. http://b/141455849
+    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
     /**
      * Returns the hardware address (usually MAC) of the interface if it
      * has one and if it can be accessed given the current privileges.
@@ -570,7 +571,8 @@
      *          manager is set and the caller does not have the permission
      *          NetPermission("getNetworkInformation"). For example, this
      *          method will generally return {@code null} when called by
-     *          non-system apps targeting API levels > 29.
+     *          non-system apps having
+     *          {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R}.
      *
      * @exception       SocketException if an I/O error occurs.
      * @since 1.6
diff --git a/support/src/test/java/libcore/java/security/CpuFeatures.java b/support/src/test/java/libcore/java/security/CpuFeatures.java
index 8ab610f..df65ed2 100644
--- a/support/src/test/java/libcore/java/security/CpuFeatures.java
+++ b/support/src/test/java/libcore/java/security/CpuFeatures.java
@@ -16,47 +16,87 @@
 
 package libcore.java.security;
 
+import android.system.Os;
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import dalvik.system.VMRuntime;
 
-class CpuFeatures {
+public class CpuFeatures {
+    /** Machine architecture, determined from the "machine" value returned by uname() */
+    private enum Arch {
+        // 64bit ARM can return armv8 or aarch64.
+        // 32bit ARM should return armv7 or armv7a
+        ARM("^aarch.*|^arm.*"),
+        // 64bit Android and Linux generally return x86_64.
+        // 32bit Android and Linux generally return i686
+        // Other host architectures can potentially return x86 or i386.
+        X86("^x86.*|i386|i686");
+
+        private final String machineRegex;
+
+        Arch(String machineRegex) {
+            this.machineRegex = machineRegex;
+        }
+
+        /**
+         * Returns the architecture of this machine by matching against output from uname()
+         * against the regex for each known family.
+         */
+        public static Arch currentArch() {
+            String machine = Os.uname().machine;
+            for (Arch type : values()) {
+                if (machine.matches(type.machineRegex)) {
+                    return type;
+                }
+            }
+            throw new IllegalStateException("Unknown machine value: " + machine);
+        }
+    }
+
+    private enum InstructionSet {
+        ARM_32(Arch.ARM, "arm"),
+        ARM_64(Arch.ARM, "arm64"),
+        X86_32(Arch.X86, "x86"),
+        X86_64(Arch.X86, "x86_64");
+
+        private final Arch arch;
+        private final String name;
+
+        InstructionSet(Arch arch, String name) {
+            this.arch = arch;
+            this.name = name;
+        }
+
+        public Arch architecture() {
+            return arch;
+        }
+
+        /**
+         * Returns the current InstructionSet set by matching against the name fields above.
+         */
+        public static InstructionSet currentInstructionSet() {
+            // Always returns one of the values from VMRuntime.ABI_TO_INSTRUCTION_SET_MAP.
+            String instructionSet = VMRuntime.getCurrentInstructionSet();
+            for (InstructionSet set : values()) {
+                if (instructionSet.equals(set.name)) {
+                    return set;
+                }
+            }
+            throw new IllegalStateException("Unknown instruction set: " + instructionSet);
+        }
+    }
+
     private CpuFeatures() {
     }
 
-    static boolean isAESHardwareAccelerated() {
-        // Expectations based on CPU type: If these aren't met then Conscrypt
-        // integration tests will fail and the cause should be investigated.
-        String instructionSet = VMRuntime.getCurrentInstructionSet();
-        if (instructionSet.startsWith("arm")) {
-            // All ARM CPUs with the "aes" feature should have hardware AES.
-            List<String> features = getListFromCpuinfo("Features");
-            if (features != null && features.contains("aes")) {
-                return true;
-            }
-        } else if (instructionSet.startsWith("x86")) {
-            // x86 CPUs with the "aes" flag and running in 64bit mode should have hardware AES.
-            if ("x86_64".equals(instructionSet)) {
-                List<String> flags = getListFromCpuinfo("flags");
-                if (flags != null && flags.contains("aes")) {
-                    return true;
-                }
-            } else {
-                // Hardware AES not supported in 32bit mode.
-                return false;
-            }
-        }
-
-        // Otherwise trust Conscrypt NativeCrypto's own checks, for example if we're in an
-        // emulated ABI, it might bridge to a library that has accelerated AES instructions.
+    /**
+     * Returns true if this device has hardware AES support as determined by BoringSSL.
+     */
+    public static boolean isAesHardwareAccelerated() {
         try {
             Class<?> nativeCrypto = Class.forName("com.android.org.conscrypt.NativeCrypto");
             Method EVP_has_aes_hardware = nativeCrypto.getDeclaredMethod("EVP_has_aes_hardware");
@@ -71,33 +111,51 @@
         return false;
     }
 
-    private static String getFieldFromCpuinfo(String field) {
-        try {
-            BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo"));
-            Pattern p = Pattern.compile(field + "\\s*:\\s*(.*)");
+    /**
+     * Returns true if this device should have hardware AES support based on CPU information.
+     *
+     * A return value of false means that acceleration isn't expected, but it may still be available
+     * e.g. via bridging to a native library in an emulated environment.
+     */
+    public static boolean isKnownToSupportHardwareAes() {
+        Arch architecture = Arch.currentArch();
+        InstructionSet instructionSet = InstructionSet.currentInstructionSet();
 
-            try {
-                String line;
-                while ((line = br.readLine()) != null) {
-                    Matcher m = p.matcher(line);
-                    if (m.matches()) {
-                        return m.group(1);
-                    }
+        if (!instructionSet.architecture().equals(architecture)) {
+            // Different architectures imply an emulated environment, so unable to determine if
+            // hardware acceleration is expected.  Assume not.
+            return false;
+        }
+
+        if (architecture.equals(Arch.ARM)) {
+            // All ARM CPUs (32 and 64 bit) with the "aes" feature should have hardware AES.
+            return cpuFieldContainsAes("Features");
+        } else if (instructionSet.equals(InstructionSet.X86_64)) {
+            // x86 CPUs with the "aes" flag and running in 64bit mode should have hardware AES.
+            // Hardware AES is not *expected* in 32bit mode, but may be available.
+            return cpuFieldContainsAes("flags");
+        }
+        return false;
+    }
+
+
+    /**
+     * Returns true if any line in the output from /proc/cpuinfo matches the provided
+     * field name and contains the word "aes" in its list of values.
+     *
+     * Example line from /proc/cpuinfo: Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32
+     */
+    private static boolean cpuFieldContainsAes(String fieldName) {
+        try (BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo"))) {
+            String regex = "^" + fieldName + "\\s*:.*\\baes\\b.*";
+            String line;
+            while ((line = br.readLine()) != null) {
+                if (line.matches(regex)) {
+                    return true;
                 }
-            } finally {
-                br.close();
             }
         } catch (IOException ignored) {
         }
-
-        return null;
-    }
-
-    private static List<String> getListFromCpuinfo(String fieldName) {
-        String features = getFieldFromCpuinfo(fieldName);
-        if (features == null)
-            return null;
-
-        return Arrays.asList(features.split("\\s"));
+        return false;
     }
 }
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index d53117b..7521cf9 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -757,7 +757,7 @@
                             "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
                             "SSL_RSA_WITH_RC4_128_MD5",
                             "TLS_EMPTY_RENEGOTIATION_INFO_SCSV")
-            : CpuFeatures.isAESHardwareAccelerated() ? CIPHER_SUITES_ANDROID_AES_HARDWARE
+            : CpuFeatures.isAesHardwareAccelerated() ? CIPHER_SUITES_ANDROID_AES_HARDWARE
                     : CIPHER_SUITES_ANDROID_SOFTWARE;
 
     private static final Map<String, Class<? extends KeySpec>> PRIVATE_KEY_SPEC_CLASSES;