Merge "Snap for 6405781 from 802f224df604b8773c8f0d373a0d5d2c8da64f98 to sdk-release" into sdk-release
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index 8cacd37..f334613 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -533,8 +533,12 @@
         "xml/src/test/java/**/*.java",
     ],
     exclude_srcs: [
+        "harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/*.java",
         "luni/src/test/java/libcore/java/util/zip/Zip64Test.java",
         "luni/src/test/java/libcore/java/util/zip/Zip64FileTest.java",
+        "luni/src/test/java/libcore/javax/crypto/**/*.java",
+        "luni/src/test/java/libcore/javax/net/ssl/**/*.java",
+        "luni/src/test/java/org/apache/harmony/crypto/**/*.java",
     ],
 
     java_resource_dirs: [
@@ -566,6 +570,7 @@
         "core-test-rules",
         "core-tests-support",
         "junit-params",
+        "libcore-crypto-tests",
         "mockftpserver",
         "mockito-target",
         "mockwebserver",
@@ -586,6 +591,40 @@
     test_config: "AndroidTest-core-tests.xml",
 }
 
+java_test {
+    name: "libcore-crypto-tests",
+
+    visibility: [
+        "//art/build/sdk",
+        "//external/conscrypt/apex/tests",
+    ],
+    srcs: [
+        "harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/*.java",
+        "luni/src/test/java/libcore/javax/crypto/**/*.java",
+        "luni/src/test/java/libcore/javax/net/ssl/**/*.java",
+        "luni/src/test/java/org/apache/harmony/crypto/**/*.java",
+    ],
+    exclude_srcs: [
+        "luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/SealedObjectTest.java",
+    ],
+
+    java_resource_dirs: [
+        "luni/src/test/java",
+        "luni/src/test/resources",
+        "support/src/test/java",
+    ],
+
+    sdk_version: "none",
+    system_modules: "core-all-system-modules",
+
+    static_libs: [
+        "core-test-rules",
+        "core-tests-support",
+        "junit-params",
+        "mockito-target",
+    ],
+}
+
 // Builds the core-ojtests library that contains test code from OpenJDK.
 java_test {
     name: "core-ojtests",
diff --git a/NativeCode.bp b/NativeCode.bp
index 2041a92..7b86fef 100644
--- a/NativeCode.bp
+++ b/NativeCode.bp
@@ -37,7 +37,7 @@
 
 cc_defaults {
     name: "core_native_default_libs",
-
+    header_libs: ["jni_headers"],
     shared_libs: [
         "libbase",
         "liblog",
@@ -63,29 +63,17 @@
         "dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp",
     ],
     shared_libs: [
+        "libandroidicu",
         "libandroidio",
         "libbase",
         "libcrypto",
         "libexpat",
-        "libicuuc",
-        "libicui18n",
         "libnativehelper",
         "libz",
     ],
     static_libs: [
-        "libandroidicuinit",
         "libziparchive",
     ],
-    target: {
-        android: {
-            cflags: [
-                // -DANDROID_LINK_SHARED_ICU4C to enable access to the full ICU4C.
-                // See external/icu/android_icu4c/include/uconfig_local.h
-                // for more information.
-                "-DANDROID_LINK_SHARED_ICU4C",
-            ],
-        },
-    },
 }
 
 cc_library_shared {
@@ -142,7 +130,6 @@
     shared_libs: [
         "libandroidio",
         "libcrypto",
-        "libicuuc",
         "libnativehelper",
         "libz",
     ],
@@ -158,16 +145,16 @@
             ],
         },
         android: {
-            cflags: [
-                // -DANDROID_LINK_SHARED_ICU4C to enable access to the full ICU4C.
-                // See external/icu/android_icu4c/include/uconfig_local.h
-                // for more information.
-                "-DANDROID_LINK_SHARED_ICU4C",
-            ],
             shared_libs: [
+                "libandroidicu",
                 "libdl_android",
             ],
         },
+        host: {
+            shared_libs: [
+                "libicuuc",
+            ],
+        },
     },
 
     notice: "ojluni/NOTICE",
diff --git a/luni/src/main/native/ScopedIcuLocale.h b/luni/src/main/native/ScopedIcuLocale.h
deleted file mode 100644
index 851de76..0000000
--- a/luni/src/main/native/ScopedIcuLocale.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SCOPED_ICU_LOCALE_H_included
-#define SCOPED_ICU_LOCALE_H_included
-
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include "unicode/locid.h"
-
-class ScopedIcuLocale {
- public:
-  ScopedIcuLocale(JNIEnv* env, jstring javaLocaleName) : mEnv(env) {
-    mLocale.setToBogus();
-
-    if (javaLocaleName == NULL) {
-      jniThrowNullPointerException(mEnv, "javaLocaleName == null");
-      return;
-    }
-
-    const ScopedUtfChars localeName(env, javaLocaleName);
-    if (localeName.c_str() == NULL) {
-      return;
-    }
-
-    mLocale = icu::Locale::createFromName(localeName.c_str());
-  }
-
-  ~ScopedIcuLocale() {
-  }
-
-  bool valid() const {
-    return !mLocale.isBogus();
-  }
-
-  icu::Locale& locale() {
-    return mLocale;
-  }
-
- private:
-  JNIEnv* const mEnv;
-  icu::Locale mLocale;
-
-  // Disallow copy and assignment.
-  ScopedIcuLocale(const ScopedIcuLocale&);
-  void operator=(const ScopedIcuLocale&);
-};
-
-#endif  // SCOPED_ICU_LOCALE_H_included
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index aa3d5004..0fca74e 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -20,7 +20,8 @@
 #include <memory>
 #include <vector>
 
-#include <androidicuinit/IcuRegistration.h>
+#include <aicu/AIcu.h>
+
 #include <log/log.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedStringChars.h>
@@ -31,11 +32,13 @@
 #include "IcuUtilities.h"
 #include "JniException.h"
 #include "ScopedIcuULoc.h"
+#include "unicode/char16ptr.h"
 #include "unicode/udatpg.h"
 #include "unicode/uloc.h"
 #include "unicode/ures.h"
 #include "unicode/ustring.h"
-#include "ureslocs.h"
+
+#define U_ICUDATA_CURR U_ICUDATA_NAME "-" "curr"
 
 class ScopedResourceBundle {
  public:
@@ -235,7 +238,7 @@
 
 // Init ICU, configuring it and loading the data files.
 void register_libcore_icu_ICU(JNIEnv* env) {
-  androidicuinit::IcuRegistration::Register();
+  AIcu_register();
 
   jniRegisterNativeMethods(env, "libcore/icu/ICU", gMethods, NELEM(gMethods));
 }
@@ -244,6 +247,5 @@
 void unregister_libcore_icu_ICU() {
   // Skip unregistering JNI methods explicitly, class unloading takes care of
   // it.
-
-  androidicuinit::IcuRegistration::Deregister();
+  AIcu_deregister();
 }
diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp
index a99b862..6d18996 100644
--- a/luni/src/main/native/libcore_io_Linux.cpp
+++ b/luni/src/main/native/libcore_io_Linux.cpp
@@ -1112,7 +1112,9 @@
     jniSetFileDescriptorOfFD(env, javaFd, -1);
 
 #if defined(__BIONIC__)
-    jlong ownerId = jniGetOwnerIdFromFileDescriptor(env, javaFd);
+    static jmethodID getOwnerId = env->GetMethodID(JniConstants::GetFileDescriptorClass(env),
+                                                   "getOwnerId$", "()J");
+    jlong ownerId = env->CallLongMethod(javaFd, getOwnerId);
 
     // Close with bionic's fd ownership tracking (which returns 0 in the case of EINTR).
     throwIfMinusOne(env, "close", android_fdsan_close_with_tag(fd, ownerId));
diff --git a/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java b/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java
index 1836aac..94399b3 100644
--- a/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java
@@ -16,16 +16,38 @@
 
 package libcore.java.security.cert;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import java.security.InvalidAlgorithmParameterException;
 import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.PKIXCertPathChecker;
 import java.security.cert.PKIXParameters;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
 import libcore.java.security.TestKeyStore;
-import libcore.junit.junit3.TestCaseWithRules;
 import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
 import org.junit.Rule;
+import org.junit.Test;
 import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
-public class PKIXParametersTest extends TestCaseWithRules {
+@RunWith(JUnit4.class)
+public class PKIXParametersTest {
+    private  static final DummyCertPathChecker CHECK_ONE = new DummyCertPathChecker("One");
+    private  static final DummyCertPathChecker CHECK_TWO = new DummyCertPathChecker("Two");
+    private  static final DummyCertPathChecker CHECK_THREE = new DummyCertPathChecker("Three");
+    private static final List<PKIXCertPathChecker> CHECK_LIST
+        = List.of(CHECK_ONE, CHECK_TWO, CHECK_THREE);
 
     // Allow access to deprecated BC algorithms in this test, so we can ensure they
     // continue to work
@@ -33,7 +55,8 @@
     public TestRule enableDeprecatedBCAlgorithmsRule =
             EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
-    public void testKeyStoreConstructor() throws Exception {
+    @Test
+    public void keyStoreConstructor() throws Exception {
         TestKeyStore server = TestKeyStore.getServer();
         KeyStore.PrivateKeyEntry pke = server.getPrivateKey("RSA", "RSA");
         char[] password = "password".toCharArray();
@@ -63,4 +86,139 @@
         } catch (InvalidAlgorithmParameterException expected) {
         }
     }
+
+    @Test
+    public void addCertPathChecker() throws Exception {
+        PKIXParameters parameters = newPkixParameters();
+        for (PKIXCertPathChecker pathChecker : CHECK_LIST) {
+            parameters.addCertPathChecker(pathChecker);
+        }
+
+        List<PKIXCertPathChecker> actualCheckers = parameters.getCertPathCheckers();
+        assertEquals(CHECK_LIST, actualCheckers);
+    }
+
+    @Test
+    public void addCertPathChecker_Null() throws Exception {
+        PKIXParameters parameters = newPkixParameters();
+
+        parameters.addCertPathChecker(null);
+        assertEquals(0, parameters.getCertPathCheckers().size());
+    }
+
+    @Test
+    public void setCertPathCheckers() throws Exception {
+        PKIXParameters parameters = newPkixParameters();
+        parameters.setCertPathCheckers(CHECK_LIST);
+
+        List<PKIXCertPathChecker> actualCheckers = parameters.getCertPathCheckers();
+        assertEquals(CHECK_LIST, actualCheckers);
+        assertNotSame(CHECK_LIST, actualCheckers);
+    }
+
+    @Test
+    public void setCertPathCheckers_NullEmpty() throws Exception {
+        PKIXParameters parameters = newPkixParameters();
+
+        parameters.setCertPathCheckers(null);
+        assertEquals(0, parameters.getCertPathCheckers().size());
+
+        parameters.setCertPathCheckers(new ArrayList<>());
+        assertEquals(0, parameters.getCertPathCheckers().size());
+    }
+
+    @Test
+    public void setCertPathCheckers_Replacement() throws Exception {
+        PKIXParameters parameters = newPkixParameters(CHECK_LIST);
+        parameters.setCertPathCheckers(null);
+        assertEquals(0, parameters.getCertPathCheckers().size());
+
+        parameters = newPkixParameters(CHECK_LIST);
+        parameters.setCertPathCheckers(new ArrayList<>());
+        assertEquals(0, parameters.getCertPathCheckers().size());
+
+        parameters = newPkixParameters(CHECK_LIST);
+        List<PKIXCertPathChecker> reversed = new ArrayList<>(CHECK_LIST);
+        Collections.reverse(reversed);
+        parameters.setCertPathCheckers(reversed);
+        assertEquals(reversed, parameters.getCertPathCheckers());
+    }
+
+    @Test
+    public void setCertPathCheckers_Error() throws Exception {
+        PKIXParameters parameters = newPkixParameters();
+        List badList = List.of("Wrong class");
+        try {
+            parameters.setCertPathCheckers(badList);
+            fail();
+        } catch (ClassCastException expected) {
+        }
+    }
+
+    @Test
+    public void toStringContainsPathCheckers() throws Exception {
+        PKIXParameters parameters = newPkixParameters(CHECK_LIST);
+
+        String regex = ".*" + CHECK_ONE + ".*" + CHECK_TWO + ".*" + CHECK_THREE + ".*";
+        Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
+        assertTrue(pattern.matcher(parameters.toString()).matches());
+    }
+
+    private PKIXParameters newPkixParameters() throws Exception {
+        PKIXParameters parameters = new PKIXParameters(TestKeyStore.getServer().keyStore);
+
+        List<PKIXCertPathChecker> pathCheckers = parameters.getCertPathCheckers();
+        assertEquals(0, pathCheckers.size());
+        return parameters;
+    }
+
+    private PKIXParameters newPkixParameters(List<PKIXCertPathChecker> pathCheckers)
+        throws Exception {
+
+        PKIXParameters parameters = newPkixParameters();
+        parameters.setCertPathCheckers(pathCheckers);
+        assertEquals(pathCheckers, parameters.getCertPathCheckers());
+        return parameters;
+    }
+
+    private static class DummyCertPathChecker extends PKIXCertPathChecker {
+        private final String tag;
+
+        DummyCertPathChecker(String tag) {
+            this.tag = tag;
+        }
+
+        @Override
+        public void init(boolean forward) {
+            // No-op
+        }
+
+        @Override
+        public boolean isForwardCheckingSupported() {
+            return false;
+        }
+
+        @Override
+        public Set<String> getSupportedExtensions() {
+            return new HashSet<>();
+        }
+
+        @Override
+        public void check(Certificate cert, Collection<String> unresolvedCritExts) {
+            // No-op
+        }
+
+        @Override
+        public String toString() {
+            return "DummyCertPathChecker: " + tag;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (other instanceof DummyCertPathChecker) {
+                return tag.equals(((DummyCertPathChecker) other).tag);
+            }
+            return false;
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/ArraysTest.java b/luni/src/test/java/libcore/java/util/ArraysTest.java
index b48e8ea..5a2bfe2 100644
--- a/luni/src/test/java/libcore/java/util/ArraysTest.java
+++ b/luni/src/test/java/libcore/java/util/ArraysTest.java
@@ -16,15 +16,31 @@
 
 package libcore.java.util;
 
-import java.util.Arrays;
-import java.util.Random;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
-public class ArraysTest extends junit.framework.TestCase {
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ArraysTest {
+    private static final int[] TEST_ARRAY_SIZES = { 0, 1, 2, 10, 100, 1000 };
+
 
     /**
      * java.util.Arrays#setAll(int[], java.util.function.IntUnaryOperator)
      */
-    public void test_setAll$I() {
+    @Test
+    public void setAll$I() {
         int[] list = new int[3];
         list[0] = 0;
         list[1] = 1;
@@ -51,7 +67,8 @@
     /**
      * java.util.Arrays#parallelSetAll(int[], java.util.function.IntUnaryOperator)
      */
-    public void test_parallelSetAll$I() {
+    @Test
+    public void parallelSetAll$I() {
         int[] list = new int[3];
         list[0] = 0;
         list[1] = 1;
@@ -78,7 +95,8 @@
     /**
      * java.util.Arrays#setAll(long[], java.util.function.IntToLongFunction)
      */
-    public void test_setAll$L() {
+    @Test
+    public void setAll$L() {
         long[] list = new long[3];
         list[0] = 0;
         list[1] = 1;
@@ -105,7 +123,8 @@
     /**
      * java.util.Arrays#parallelSetAll(long[], java.util.function.IntToLongFunction)
      */
-    public void test_parallelSetAll$L() {
+    @Test
+    public void parallelSetAll$L() {
         long[] list = new long[3];
         list[0] = 0;
         list[1] = 1;
@@ -132,16 +151,17 @@
     /**
      * java.util.Arrays#setAll(double[], java.util.function.IntToDoubleFunction)
      */
-    public void test_setAll$D() {
+    @Test
+    public void setAll$D() {
         double[] list = new double[3];
         list[0] = 0.0d;
         list[1] = 1.0d;
         list[2] = 2.0d;
 
         Arrays.setAll(list, x -> x + 0.5);
-        assertEquals(0.5d, list[0]);
-        assertEquals(1.5d, list[1]);
-        assertEquals(2.5d, list[2]);
+        assertEquals(0.5d, list[0], 0.0);
+        assertEquals(1.5d, list[1], 0.0);
+        assertEquals(2.5d, list[2], 0.0);
 
         try {
             Arrays.setAll(list, null);
@@ -159,16 +179,17 @@
     /**
      * java.util.Arrays#parallelSetAll(double[], java.util.function.IntToDoubleFunction)
      */
-    public void test_parallelSetAll$D() {
+    @Test
+    public void parallelSetAll$D() {
         double[] list = new double[3];
         list[0] = 0.0d;
         list[1] = 1.0d;
         list[2] = 2.0d;
 
         Arrays.parallelSetAll(list, x -> x + 0.5);
-        assertEquals(0.5d, list[0]);
-        assertEquals(1.5d, list[1]);
-        assertEquals(2.5d, list[2]);
+        assertEquals(0.5d, list[0], 0.0);
+        assertEquals(1.5d, list[1], 0.0);
+        assertEquals(2.5d, list[2], 0.0);
 
         try {
             Arrays.parallelSetAll(list, null);
@@ -186,7 +207,8 @@
     /**
      * java.util.Array#setAll(T[], java.util.function.IntFunction<\? extends T>)
      */
-    public void test_setAll$T() {
+    @Test
+    public void setAll$T() {
         String[] strings = new String[3];
         strings[0] = "a";
         strings[0] = "b";
@@ -213,7 +235,8 @@
     /**
      * java.util.Array#parallelSetAll(T[], java.util.function.IntFunction<\? extends T>)
      */
-    public void test_parallelSetAll$T() {
+    @Test
+    public void parallelSetAll$T() {
         String[] strings = new String[3];
         strings[0] = "a";
         strings[0] = "b";
@@ -240,7 +263,8 @@
     /**
      * java.util.Array#parallelPrefix(int[], java.util.function.IntBinaryOperator)
      */
-    public void test_parallelPrefix$I() {
+    @Test
+    public void parallelPrefix$I() {
         // Get an arbitrary array of ints.
         Random rand = new Random(0);
         int[] list = new int[1000];
@@ -256,7 +280,7 @@
         }
 
         Arrays.parallelPrefix(list, (x, y) -> x + y);
-        assertTrue(Arrays.equals(seqResult, list));
+        assertArrayEquals(seqResult, list);
 
         try {
             Arrays.parallelPrefix(list, null);
@@ -274,7 +298,8 @@
     /**
      * java.util.Array#parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator)
      */
-    public void test_parallelPrefix$III() {
+    @Test
+    public void parallelPrefix$III() {
         // Get an arbitrary array of ints.
         Random rand = new Random(0);
         int[] list = new int[1000];
@@ -291,7 +316,7 @@
         }
 
         Arrays.parallelPrefix(list, begin, end, (x, y) -> x + y);
-        assertTrue(Arrays.equals(seqResult, list));
+        assertArrayEquals(seqResult, list);
 
         try {
             Arrays.parallelPrefix(list, begin, end, null);
@@ -315,7 +340,8 @@
     /**
      * java.util.Array#parallelPrefix(long[], java.util.function.LongBinaryOperator)
      */
-    public void test_parallelPrefix$L() {
+    @Test
+    public void parallelPrefix$L() {
         // Get an arbitrary array of ints.
         Random rand = new Random(0);
         long[] list = new long[1000];
@@ -331,7 +357,7 @@
         }
 
         Arrays.parallelPrefix(list, (x, y) -> x + y);
-        assertTrue(Arrays.equals(seqResult, list));
+        assertArrayEquals(seqResult, list);
 
         try {
             Arrays.parallelPrefix(list, null);
@@ -349,7 +375,8 @@
     /**
      * java.util.Array#parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator)
      */
-    public void test_parallelPrefix$LII() {
+    @Test
+    public void parallelPrefix$LII() {
         // Get an arbitrary array of ints.
         Random rand = new Random(0);
         long[] list = new long[1000];
@@ -366,7 +393,7 @@
         }
 
         Arrays.parallelPrefix(list, begin, end, (x, y) -> x + y);
-        assertTrue(Arrays.equals(seqResult, list));
+        assertArrayEquals(seqResult, list);
 
         try {
             Arrays.parallelPrefix(list, begin, end, null);
@@ -390,7 +417,8 @@
     /**
      * java.util.Array#parallelPrefix(double[], java.util.function.DoubleBinaryOperator)
      */
-    public void test_parallelPrefix$D() {
+    @Test
+    public void parallelPrefix$D() {
         // Get an arbitrary array of ints.
         Random rand = new Random(0);
         double[] list = new double[1000];
@@ -410,7 +438,7 @@
         // Parallel double arithmetic contains error, reduce to integer for comparison.
         int[] listInInt = Arrays.stream(list).mapToInt(x -> (int) x).toArray();
         int[] seqResultInInt = Arrays.stream(seqResult).mapToInt(x -> (int) x).toArray();
-        assertTrue(Arrays.equals(seqResultInInt, listInInt));
+        assertArrayEquals(seqResultInInt, listInInt);
 
         try {
             Arrays.parallelPrefix(list, null);
@@ -428,7 +456,8 @@
     /**
      * java.util.Array#parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator)
      */
-    public void test_parallelPrefix$DII() {
+    @Test
+    public void parallelPrefix$DII() {
         // Get an arbitrary array of ints.
         Random rand = new Random(0);
         double[] list = new double[1000];
@@ -449,7 +478,7 @@
         // Parallel double arithmetic contains error, reduce to integer for comparison.
         int[] listInInt = Arrays.stream(list).mapToInt(x -> (int) x).toArray();
         int[] seqResultInInt = Arrays.stream(seqResult).mapToInt(x -> (int) x).toArray();
-        assertTrue(Arrays.equals(seqResultInInt, listInInt));
+        assertArrayEquals(seqResultInInt, listInInt);
 
         try {
             Arrays.parallelPrefix(list, begin, end, null);
@@ -473,7 +502,8 @@
     /**
      * java.util.Array#parallelPrefix(T[], java.util.function.BinaryOperator<T>)
      */
-    public void test_parallelPrefix$T() {
+    @Test
+    public void parallelPrefix$T() {
         String[] strings = new String[3];
         strings[0] = "a";
         strings[1] = "b";
@@ -500,7 +530,8 @@
     /**
      * java.util.Array#parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>)
      */
-    public void test_parallelPrefix$TII() {
+    @Test
+    public void parallelPrefix$TII() {
         String[] strings = new String[5];
         strings[0] = "a";
         strings[1] = "b";
@@ -536,9 +567,389 @@
     }
 
     // http://b/74236526
-    public void test_deepEquals_nestedArraysOfDifferentTypesButEqualValues() {
+    @Test
+    public void deepEquals_nestedArraysOfDifferentTypesButEqualValues() {
         assertTrue(Arrays.deepEquals(
             new Object[] { new Object[] { "Hello", "world" } },
             new Object[] { new String[] { "Hello", "world" } }));
     }
+
+    @Test
+    public void streamInt() {
+        for (int size : TEST_ARRAY_SIZES) {
+            int[] sourceArray = intTestArray(size);
+
+            // Stream, map, accumulate
+            int sum = Arrays.stream(sourceArray)
+                .map(i -> i + i)
+                .sum();
+            assertEquals(size * (size - 1), sum);
+
+            // Stream, collect as array again
+            int[] destArray = Arrays.stream(sourceArray)
+                .toArray();
+            assertArrayEquals(sourceArray, destArray);
+            assertNotSame(sourceArray, destArray);
+
+            // Stream, box, collect as list
+            List<Integer> destList = Arrays.stream(sourceArray)
+                .boxed()
+                .collect(Collectors.toList());
+
+            assertEquals(size, destList.size());
+            for (int i = 0; i < size; i++) {
+                assertEquals((int) destList.get(i), i);
+            }
+        }
+    }
+
+    @Test
+    public void streamIntStartEnd() {
+        final int size = 10;
+        int[] sourceArray = intTestArray(size);
+        for (int start = 0; start < size - 1; start++) {
+            for (int end = start; end < size; end++) {
+                int[] destArray = Arrays.stream(sourceArray, start, end)
+                    .toArray();
+                int len = end - start;
+                assertEquals(len, destArray.length);
+                if (len > 0) {
+                    assertEquals(start, destArray[0]);
+                    assertEquals(end - 1, destArray[len - 1]);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void streamIntStartEnd_Exceptions() {
+        int[] sourceArray = intTestArray(10);
+        try {
+            int unused = Arrays.stream(sourceArray, -1, 9)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            int unused = Arrays.stream(sourceArray, 0, 11)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            int unused = Arrays.stream(sourceArray, 11, 11)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            int unused = Arrays.stream(sourceArray, 0, -1)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            int unused = Arrays.stream(sourceArray, 4, 3)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @Test
+    public void streamLong() {
+        for (int size : TEST_ARRAY_SIZES) {
+            long[] sourceArray = longTestArray(size);
+
+            // Stream, map, accumulate
+            long sum = Arrays.stream(sourceArray)
+                .map(i -> i + i)
+                .sum();
+            assertEquals(size * (size - 1), sum);
+
+            // Stream, collect as array again
+            long[] destArray = Arrays.stream(sourceArray)
+                .toArray();
+            assertArrayEquals(sourceArray, destArray);
+            assertNotSame(sourceArray, destArray);
+
+            // Stream, box, collect as list
+            List<Long> destList = Arrays.stream(sourceArray)
+                .boxed()
+                .collect(Collectors.toList());
+
+            assertEquals(size, destList.size());
+            for (int i = 0; i < size; i++) {
+                assertEquals((long) destList.get(i), i);
+            }
+        }
+    }
+
+    @Test
+    public void streamLongStartEnd() {
+        final int size = 10;
+        long[] sourceArray = longTestArray(size);
+        for (int start = 0; start < size - 1; start++) {
+            for (int end = start; end < size; end++) {
+                long[] destArray = Arrays.stream(sourceArray, start, end)
+                    .toArray();
+                int len = end - start;
+                assertEquals(len, destArray.length);
+                if (len > 0) {
+                    assertEquals(start, destArray[0]);
+                    assertEquals(end - 1, destArray[len - 1]);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void streamLongStartEnd_Exceptions() {
+        long[] sourceArray = longTestArray(10);
+        try {
+            long unused = Arrays.stream(sourceArray, -1, 9)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            long unused = Arrays.stream(sourceArray, 0, 11)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            long unused = Arrays.stream(sourceArray, 11, 11)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            long unused = Arrays.stream(sourceArray, 0, -1)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            long unused = Arrays.stream(sourceArray, 4, 3)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @Test
+    public void streamDouble() {
+        for (int size : TEST_ARRAY_SIZES) {
+            double[] sourceArray = doubleTestArray(size);
+
+            // Stream, map, accumulate
+            double sum = Arrays.stream(sourceArray)
+                .map(i -> i + i)
+                .sum();
+            assertEquals(size * (size - 1), sum, 0.001);
+
+            // Stream, collect as array again
+            double[] destArray = Arrays.stream(sourceArray)
+                .toArray();
+            assertArrayEquals(sourceArray, destArray, 0.001);
+            assertNotSame(sourceArray, destArray);
+
+            // Stream, box, collect as list
+            List<Double> destList = Arrays.stream(sourceArray)
+                .boxed()
+                .collect(Collectors.toList());
+
+            assertEquals(size, destList.size());
+            for (int i = 0; i < size; i++) {
+                assertEquals(destList.get(i), i, 0.001);
+            }
+        }
+    }
+
+    @Test
+    public void streamDoubleStartEnd() {
+        final int size = 10;
+        double[] sourceArray = doubleTestArray(size);
+        for (int start = 0; start < size - 1; start++) {
+            for (int end = start; end < size; end++) {
+                double[] destArray = Arrays.stream(sourceArray, start, end)
+                    .toArray();
+                int len = end - start;
+                assertEquals(len, destArray.length);
+                if (len > 0) {
+                    assertEquals(start, destArray[0], 0.0);
+                    assertEquals(end - 1, destArray[len - 1], 0.0);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void streamDoubleStartEnd_Exceptions() {
+        double[] sourceArray = doubleTestArray(10);
+        try {
+            double unused = Arrays.stream(sourceArray, -1, 9)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            double unused = Arrays.stream(sourceArray, 0, 11)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            double unused = Arrays.stream(sourceArray, 11, 11)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            double unused = Arrays.stream(sourceArray, 0, -1)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            double unused = Arrays.stream(sourceArray, 4, 3)
+                .sum();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @Test
+    public void streamObject() {
+      for (int size : TEST_ARRAY_SIZES) {
+        String[] sourceArray = stringTestArray(size);
+
+        // Stream, map, accumulate
+        int sum = Arrays.stream(sourceArray)
+            .mapToInt(i -> Integer.parseInt(i) * 2)
+            .sum();
+        assertEquals(size * (size - 1), sum);
+
+        // Stream, collect as array again
+        String[] destArray = Arrays.stream(sourceArray)
+            .toArray(String[]::new);
+        assertArrayEquals(sourceArray, destArray);
+        assertNotSame(sourceArray, destArray);
+
+        // Stream, collect as list
+        List<String> destList = Arrays.stream(sourceArray)
+            .collect(Collectors.toList());
+
+        assertEquals(size, destList.size());
+        for (int i = 0; i < size; i++) {
+          assertSame(destList.get(i), sourceArray[i]);
+        }
+      }
+    }
+
+    @Test
+    public void streamObjectStartEnd() {
+        final int size = 10;
+        String[] sourceArray = stringTestArray(size);
+        for (int start = 0; start < size - 1; start++) {
+            for (int end = start; end < size; end++) {
+                String[] destArray = Arrays.stream(sourceArray, start, end)
+                    .toArray(String[]::new);
+                int len = end - start;
+                assertEquals(len, destArray.length);
+                if (len > 0) {
+                    assertSame(sourceArray[start], destArray[0]);
+                    assertSame(sourceArray[end - 1], destArray[len - 1]);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void streamObjectStartEnd_Exceptions() {
+        String[] sourceArray = stringTestArray(10);
+        try {
+            long unused = Arrays.stream(sourceArray, -1, 9)
+                .count();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            long unused = Arrays.stream(sourceArray, 0, 11)
+                .count();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            long unused = Arrays.stream(sourceArray, 11, 11)
+                .count();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            long unused = Arrays.stream(sourceArray, 0, -1)
+                .count();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            long unused = Arrays.stream(sourceArray, 4, 3)
+                .count();
+            fail();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    private int[] intTestArray(int size) {
+        int[] array = new int[size];
+        for (int i = 0; i < size; i++) {
+            array[i] = i;
+        }
+        return array;
+    }
+
+    private long[] longTestArray(int size) {
+        long[] array = new long[size];
+        for (int i = 0; i < size; i++) {
+            array[i] = i;
+        }
+        return array;
+    }
+
+    private double[] doubleTestArray(int size) {
+        double[] array = new double[size];
+        for (int i = 0; i < size; i++) {
+            array[i] = i;
+        }
+        return array;
+    }
+
+    private String[] stringTestArray(int size) {
+        String[] array = new String[size];
+        for (int i = 0; i < size; i++) {
+            array[i] = String.valueOf(i);
+        }
+        return array;
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/stream/StreamTest.java b/luni/src/test/java/libcore/java/util/stream/StreamTest.java
new file mode 100644
index 0000000..5f8f254
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/stream/StreamTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.java.util.stream;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+import java.util.stream.Stream;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Streams tests required for Mainline coverage.
+ *
+ * TODO(b/153297830): Use existing CtsLibcoreOjTestCases for coverage instead.
+ */
+
+@RunWith(JUnit4.class)
+public class StreamTest {
+  private static final int[] TEST_ARRAY_SIZES = { 0, 1, 2, 10, 100, 1000 };
+
+  /**
+   * Stream<T>.of() has two overloads, Stream.of(T t) and Stream.of(T... values)
+   *
+   * The first builds a Stream<T> whose functionality is tested in CtsLibcoreOjTestCases, so we
+   * just check the contents are as expected
+   *
+   * The second is a thin wrapper around Arrays.Stream(), which is tested in ArraysTest,
+   * so again we just check the contents are as expected.
+   *
+   */
+  @Test
+  public void streamOfSingleObject() {
+    String object = "string";
+    String[] array = Stream.of(object).toArray(String[]::new);
+    assertEquals(1, array.length);
+    assertSame(object, array[0]);
+  }
+
+  @Test
+  public void streamOfObjects() {
+    for (int size : TEST_ARRAY_SIZES) {
+      String[] sourceArray = stringTestArray(size);
+
+      // Stream.of(T[] t) is equivalent to Stream.of(T... t)
+      String[] destArray = Stream.of(sourceArray)
+          .toArray(String[]::new);
+      assertNotSame(sourceArray, destArray);
+      assertArrayEquals(sourceArray, destArray);
+    }
+  }
+
+  private String[] stringTestArray(int size) {
+    String[] array = new String[size];
+    for (int i = 0; i < size; i++) {
+      array[i] = String.valueOf(i);
+    }
+    return array;
+  }
+}
diff --git a/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java b/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java
index 8485874..8a33f6f 100644
--- a/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java
@@ -143,6 +143,19 @@
         zis.close();
     }
 
+    private static final byte[] ZIP_WITH_DATA_DESCRIPTOR = new byte[] {
+(byte) 80, 75, 3, 4, 10, 0, 8, 0, 0, 0, -51, 90, -121, 80, -20, 62, -84, -103, 2, 0, 0, 0, 2, 0, 0, 0, 8, 0, 28, 0, 116, 101, 115, 116, 46, 116, 120, 116, 85, 84, 9, 0, 3, 97, 84, -116, 94, 102, 84, -116, 94, 117, 120, 11, 0, 1, 4, -119, 66, 0, 0, 4, 83, 95, 1, 0, 72, 10, 80, 75, 7, 8, -20, 62, -84, -103, 2, 0, 0, 0, 2, 0, 0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, -51, 90, -121, 80, -20, 62, -84, -103, 2, 0, 0, 0, 2, 0, 0, 0, 8, 0, 24, 0, 0, 0, 0, 0, 1, 0, 0, 0, -92, -127, 0, 0, 0, 0, 116, 101, 115, 116, 46, 116, 120, 116, 85, 84, 5, 0, 3, 97, 84, -116, 94, 117, 120, 11, 0, 1, 4, -119, 66, 0, 0, 4, 83, 95, 1, 0, 80, 75, 5, 6, 0, 0, 0, 0, 1, 0, 1, 0, 78, 0, 0, 0, 84, 0, 0, 0, 0, 0 };
+
+    public void testDataDescriptorOnStoredEntry() throws Exception {
+        ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(
+                ZIP_WITH_DATA_DESCRIPTOR));
+
+        ZipEntry entry = zis.getNextEntry();
+        assertEquals("test.txt", entry.getName());
+
+        zis.close();
+    }
+
     private static byte[] zip(String[] names, byte[] bytes) throws IOException {
         ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
         ZipOutputStream zippedOut = new ZipOutputStream(bytesOut);
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementThread.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementThread.java
index 480ea7f..33e9c21 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementThread.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementThread.java
@@ -15,7 +15,6 @@
  */
 package org.apache.harmony.crypto.tests.javax.crypto.func;
 
-import com.android.org.bouncycastle.util.Arrays;
 import java.security.AlgorithmParameterGenerator;
 import java.security.AlgorithmParameters;
 import java.security.KeyFactory;
@@ -25,6 +24,7 @@
 import java.security.PublicKey;
 import java.security.SecureRandom;
 import java.security.spec.X509EncodedKeySpec;
+import java.util.Arrays;
 import javax.crypto.KeyAgreement;
 import javax.crypto.spec.DHParameterSpec;
 
@@ -80,7 +80,7 @@
         byte[] sk1 = kag1.getSecretKey(algName, bArray2);
         byte[] sk2 = kag2.getSecretKey(algName, bArray1);
 
-        if (Arrays.areEqual(sk1, sk2) == false) {
+        if (!Arrays.equals(sk1, sk2)) {
             throw new Exception ("Generated keys are not the same");
         }
     }
diff --git a/ojluni/src/main/java/java/lang/System.java b/ojluni/src/main/java/java/lang/System.java
index a67bb0b..b915031 100644
--- a/ojluni/src/main/java/java/lang/System.java
+++ b/ojluni/src/main/java/java/lang/System.java
@@ -26,6 +26,7 @@
 package java.lang;
 
 import com.android.icu.util.Icu4cMetadata;
+import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
 import android.system.ErrnoException;
 import android.system.StructPasswd;
@@ -294,6 +295,7 @@
      *          the current time and midnight, January 1, 1970 UTC.
      * @see     java.util.Date
      */
+    @CriticalNative
     public static native long currentTimeMillis();
 
     /**
@@ -340,6 +342,7 @@
      *         high-resolution time source, in nanoseconds
      * @since 1.5
      */
+    @CriticalNative
     public static native long nanoTime();
 
     /**
diff --git a/ojluni/src/main/java/java/util/zip/ZipInputStream.java b/ojluni/src/main/java/java/util/zip/ZipInputStream.java
index 0413f47..aaebb49 100644
--- a/ojluni/src/main/java/java/util/zip/ZipInputStream.java
+++ b/ojluni/src/main/java/java/util/zip/ZipInputStream.java
@@ -323,11 +323,16 @@
         e.method = get16(tmpbuf, LOCHOW);
         e.xdostime = get32(tmpbuf, LOCTIM);
         if ((flag & 8) == 8) {
-            /* "Data Descriptor" present */
-            if (e.method != DEFLATED) {
-                throw new ZipException(
-                        "only DEFLATED entries can have EXT descriptor");
-            }
+            // Android-Changed: Remove the requirement that only DEFLATED entries
+            // can have data descriptors. This is not required by the ZIP spec and
+            // is inconsistent with the behaviour of ZipFile and versions of Android
+            // prior to Android N.
+            //
+            // /* "Data Descriptor" present */
+            // if (e.method != DEFLATED) {
+            //     throw new ZipException(
+            //             "only DEFLATED entries can have EXT descriptor");
+            // }
         } else {
             e.crc = get32(tmpbuf, LOCCRC);
             e.csize = get32(tmpbuf, LOCSIZ);