Merge "Remove IoUtils#deleteContents from CorePlatformApi set"
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index 4837be7..5fcdd4c 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -649,11 +649,9 @@
         "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/libcore/libcore/util/SerializationTester.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",
diff --git a/NativeCode.bp b/NativeCode.bp
index dac2387..228a284 100644
--- a/NativeCode.bp
+++ b/NativeCode.bp
@@ -202,10 +202,6 @@
         "liblog",
         "libnativehelper",
     ],
-
-    strip: {
-        keep_symbols: true,
-    },
 }
 
 // Set of gtest unit tests.
diff --git a/OWNERS b/OWNERS
index 2de3abb..56d718b 100644
--- a/OWNERS
+++ b/OWNERS
@@ -6,7 +6,6 @@
 # People who can approve changes for submission; don't send review emails to them
 # unless you know what you're doing.
 dauletz@google.com
-mast@google.com
 mingaleev@google.com
 nfuller@google.com
 nikitai@google.com
diff --git a/api/current.txt b/api/current.txt
index 659c529..d91a31b 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -46,6 +46,7 @@
     method public static int getpid();
     method public static int getppid();
     method public static java.net.SocketAddress getsockname(java.io.FileDescriptor) throws android.system.ErrnoException;
+    method @Nullable public static android.system.StructLinger getsockoptLinger(@NonNull java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
     method @NonNull public static android.system.StructTimeval getsockoptTimeval(@NonNull java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
     method public static int gettid();
     method public static int getuid();
@@ -100,6 +101,7 @@
     method @Deprecated public static void setgid(int) throws android.system.ErrnoException;
     method public static int setsid() throws android.system.ErrnoException;
     method public static void setsockoptInt(java.io.FileDescriptor, int, int, int) throws android.system.ErrnoException;
+    method public static void setsockoptLinger(@NonNull java.io.FileDescriptor, int, int, @NonNull android.system.StructLinger) throws android.system.ErrnoException;
     method public static void setsockoptTimeval(@NonNull java.io.FileDescriptor, int, int, @NonNull android.system.StructTimeval) throws android.system.ErrnoException;
     method @Deprecated public static void setuid(int) throws android.system.ErrnoException;
     method public static void setxattr(String, String, byte[], int) throws android.system.ErrnoException;
@@ -651,6 +653,13 @@
     field public final int cmsg_type;
   }
 
+  public final class StructLinger {
+    ctor public StructLinger(int, int);
+    method public boolean isOn();
+    field public final int l_linger;
+    field public final int l_onoff;
+  }
+
   public final class StructMsghdr {
     ctor public StructMsghdr(@Nullable java.net.SocketAddress, @NonNull java.nio.ByteBuffer[], @Nullable android.system.StructCmsghdr[], int);
     field @Nullable public android.system.StructCmsghdr[] msg_control;
@@ -2962,7 +2971,7 @@
     method public static void enable();
   }
 
-  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PACKAGE, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.TYPE}) public @interface Deprecated {
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PACKAGE, java.lang.annotation.ElementType.MODULE, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.TYPE}) public @interface Deprecated {
     method public abstract boolean forRemoval() default false;
     method public abstract String since() default "";
   }
diff --git a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
index afbc9ec..aef8adf 100644
--- a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
@@ -29,6 +29,8 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import libcore.util.NonNull;
+import libcore.util.Nullable;
 import sun.misc.CompoundEnumeration;
 
 /**
@@ -228,7 +230,7 @@
      */
     @UnsupportedAppUsage
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-    public void addDexPath(String dexPath) {
+    public void addDexPath(@Nullable String dexPath) {
         addDexPath(dexPath, false /*isTrusted*/);
     }
 
@@ -249,7 +251,7 @@
      * @hide
      */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-    public void addNativePath(Collection<String> libPaths) {
+    public void addNativePath(@NonNull Collection<String> libPaths) {
         pathList.addNativePath(libPaths);
     }
 
@@ -345,7 +347,7 @@
      */
     @UnsupportedAppUsage
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-    public String getLdLibraryPath() {
+    public @NonNull String getLdLibraryPath() {
         StringBuilder result = new StringBuilder();
         for (File directory : pathList.getNativeLibraryDirectories()) {
             if (result.length() > 0) {
@@ -366,11 +368,11 @@
      * Once set, all new instances of BaseDexClassLoader will report upon
      * constructions the loaded dex files.
      *
-     * @param newReporter the new Reporter. Setting null will cancel reporting.
+     * @param newReporter the new Reporter. Setting {@code null} will cancel reporting.
      * @hide
      */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-    public static void setReporter(Reporter newReporter) {
+    public static void setReporter(@Nullable Reporter newReporter) {
         reporter = newReporter;
     }
 
@@ -400,6 +402,6 @@
          *     each dex file.
          */
         @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-        void report(Map<String, String> contextsMap);
+        void report(@NonNull Map<String, String> contextsMap);
     }
 }
diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java
index 93a4865..a4ad9ce 100644
--- a/dalvik/src/main/java/dalvik/system/BlockGuard.java
+++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java
@@ -118,7 +118,7 @@
          *            for reading or writing.
          */
         @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-        void onPathAccess(String path);
+        void onPathAccess(@NonNull String path);
     }
 
     /**
diff --git a/dalvik/src/main/java/dalvik/system/VMDebug.java b/dalvik/src/main/java/dalvik/system/VMDebug.java
index 149f757..a705e24 100644
--- a/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -41,6 +41,7 @@
      * startAllocCounting to the trace key file.
      */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
+    // Must match android.os.Debug.TRACE_COUNT_ALLOCS.
     public static final int TRACE_COUNT_ALLOCS = 1;
 
     /* constants for getAllocCount */
@@ -496,6 +497,8 @@
         runtimeStatsMap.put("art.gc.blocking-gc-time", 5);
         runtimeStatsMap.put("art.gc.gc-count-rate-histogram", 6);
         runtimeStatsMap.put("art.gc.blocking-gc-count-rate-histogram", 7);
+        runtimeStatsMap.put("art.gc.objects-allocated", 8);
+        runtimeStatsMap.put("art.gc.total-time-waiting-for-gc", 9);
     }
 
     /**
diff --git a/json/src/main/java/org/json/JSONObject.java b/json/src/main/java/org/json/JSONObject.java
index 40d15bb..2a2df62 100644
--- a/json/src/main/java/org/json/JSONObject.java
+++ b/json/src/main/java/org/json/JSONObject.java
@@ -674,11 +674,13 @@
      *
      * See {@link #keys()}.
      *
+     * @return set of keys in this object
+     *
      * @hide.
      */
     @UnsupportedAppUsage
-    @libcore.api.CorePlatformApi
-    public Set<String> keySet() {
+    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
+    @NonNull public Set<@NonNull String> keySet() {
         return nameValuePairs.keySet();
     }
 
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 4a26c4b..21b035b 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -186,6 +186,7 @@
      * @hide
      */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
+    // Must match android.os.Build.VERSION_CODES.CUR_DEVELOPMENT.
     public static final int SDK_VERSION_CUR_DEVELOPMENT = 10000;
 
     private static Consumer<String> nonSdkApiUsageConsumer = null;
@@ -651,7 +652,6 @@
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void requestConcurrentGC();
 
-    public native void concurrentGC();
     public native void requestHeapTrim();
     public native void trimHeap();
     public native void startHeapTaskProcessor();
diff --git a/luni/src/main/java/android/compat/Compatibility.java b/luni/src/main/java/android/compat/Compatibility.java
index 5d472bb..317ed07 100644
--- a/luni/src/main/java/android/compat/Compatibility.java
+++ b/luni/src/main/java/android/compat/Compatibility.java
@@ -25,6 +25,7 @@
 import java.util.HashSet;
 import java.util.Objects;
 import java.util.Set;
+import libcore.util.NonNull;
 
 /**
  * Internal APIs for logging and gating compatibility changes.
@@ -55,8 +56,8 @@
      */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @IntraCoreApi
-    public static void reportChange(@ChangeId long changeId) {
-        sCallbacks.reportChange(changeId);
+    public static void reportUnconditionalChange(@ChangeId long changeId) {
+        sCallbacks.onChangeReported(changeId);
     }
 
     /**
@@ -68,7 +69,7 @@
      * {@code false}, the calling code should behave as it did in earlier releases.
      *
      * <p>When this method returns {@code true}, it will also report the change as
-     * {@link #reportChange(long)} would, so there is no need to call that method directly.
+     * {@link #reportUnconditionalChange(long)} would, so there is no need to call that method directly.
      *
      * @param changeId The ID of the compatibility change in question.
      * @return {@code true} if the change is enabled for the current app.
@@ -79,13 +80,32 @@
         return sCallbacks.isChangeEnabled(changeId);
     }
 
-    private volatile static Callbacks sCallbacks = new Callbacks();
+    private static final BehaviorChangeDelegate DEFAULT_CALLBACKS = new BehaviorChangeDelegate(){};
 
+    private volatile static BehaviorChangeDelegate sCallbacks = DEFAULT_CALLBACKS;
+
+    /**
+     * Sets the behavior change delegate.
+     *
+     * All changes reported via the {@link Compatibility} class will be forwarded to this class.
+     */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-    public static void setCallbacks(Callbacks callbacks) {
+    public static void setBehaviorChangeDelegate(BehaviorChangeDelegate callbacks) {
         sCallbacks = Objects.requireNonNull(callbacks);
     }
 
+    /**
+     * Removes a behavior change delegate previously set via {@link #setBehaviorChangeDelegate}.
+     */
+    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
+    public static void clearBehaviorChangeDelegate() {
+        sCallbacks = DEFAULT_CALLBACKS;
+    }
+
+    /**
+     * For use by tests only. Causes values from {@code overrides} to be returned instead of the
+     * real value.
+     */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static void setOverrides(ChangeConfig overrides) {
         // Setting overrides twice in a row does not need to be supported because
@@ -99,6 +119,9 @@
         sCallbacks = new OverrideCallbacks(sCallbacks, overrides);
     }
 
+    /**
+     * For use by tests only. Removes overrides set by {@link #setOverrides}.
+     */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static void clearOverrides() {
         if (!(sCallbacks instanceof OverrideCallbacks)) {
@@ -115,17 +138,21 @@
      * breaking @CorePlatformApi binary compatibility.
      */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-    public static class Callbacks {
+    public interface BehaviorChangeDelegate {
+        /**
+         * Called when a change is reported via {@link Compatibility#reportUnconditionalChange}
+         */
         @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-        protected Callbacks() {
-        }
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-        protected void reportChange(long changeId) {
+        default void onChangeReported(long changeId) {
             // Do not use String.format here (b/160912695)
             System.logW("No Compatibility callbacks set! Reporting change " + changeId);
         }
+
+        /**
+         * Called when a change is queried via {@link Compatibility#isChangeEnabled}
+         */
         @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-        protected boolean isChangeEnabled(long changeId) {
+        default boolean isChangeEnabled(long changeId) {
             // Do not use String.format here (b/160912695)
             System.logW("No Compatibility callbacks set! Querying change " + changeId);
             return true;
@@ -138,7 +165,7 @@
         private final Set<Long> enabled;
         private final Set<Long> disabled;
 
-        public ChangeConfig(Set<Long> enabled, Set<Long> disabled) {
+        public ChangeConfig(@NonNull Set<@NonNull Long> enabled, @NonNull Set<@NonNull Long> disabled) {
             this.enabled = Objects.requireNonNull(enabled);
             this.disabled = Objects.requireNonNull(disabled);
             if (enabled.contains(null)) {
@@ -168,19 +195,19 @@
             return result;
         }
 
-        public long[] forceEnabledChangesArray() {
+        public @NonNull long[] getEnabledChangesArray() {
             return toLongArray(enabled);
         }
 
-        public long[] forceDisabledChangesArray() {
+        public @NonNull long[] getDisabledChangesArray() {
             return toLongArray(disabled);
         }
 
-        public Set<Long> forceEnabledSet() {
+        public @NonNull Set<@NonNull Long> getEnabledSet() {
             return Collections.unmodifiableSet(enabled);
         }
 
-        public Set<Long> forceDisabledSet() {
+        public @NonNull Set<@NonNull Long> getDisabledSet() {
             return Collections.unmodifiableSet(disabled);
         }
 
@@ -214,16 +241,16 @@
         }
     }
 
-    private static class OverrideCallbacks extends Callbacks {
-        private final Callbacks delegate;
+    private static class OverrideCallbacks implements BehaviorChangeDelegate {
+        private final BehaviorChangeDelegate delegate;
         private final ChangeConfig changeConfig;
 
-        private OverrideCallbacks(Callbacks delegate, ChangeConfig changeConfig) {
+        private OverrideCallbacks(BehaviorChangeDelegate delegate, ChangeConfig changeConfig) {
             this.delegate = Objects.requireNonNull(delegate);
             this.changeConfig = Objects.requireNonNull(changeConfig);
         }
         @Override
-        protected boolean isChangeEnabled(long changeId) {
+        public boolean isChangeEnabled(long changeId) {
            if (changeConfig.isForceEnabled(changeId)) {
                return true;
            }
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java
index 437edc6..6f1a131 100755
--- a/luni/src/main/java/android/system/Os.java
+++ b/luni/src/main/java/android/system/Os.java
@@ -82,7 +82,7 @@
      * @hide
      */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-    public static @Nullable StructCapUserData[] capget(@NonNull StructCapUserHeader hdr) throws ErrnoException {
+    public static @Nullable StructUserCapData[] capget(@NonNull StructUserCapHeader hdr) throws ErrnoException {
         return Libcore.os.capget(hdr);
     }
 
@@ -97,7 +97,7 @@
      *                        set, or to set a capability in the effective set that is
      *                        not in the permitted set; or
      *                        the caller attempted to use
-     *                        {@link capset(StructCapUserHeader, StructCapUserData[])}
+     *                        {@link capset( StructUserCapHeader , StructUserCapData[])}
      *                        to modify the capabilities of a thread other than itself,
      *                        but lacked sufficient privilege;
      *                        or there is no such thread.
@@ -105,7 +105,7 @@
      * @hide
      */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-    public static void capset(@NonNull StructCapUserHeader hdr, @NonNull StructCapUserData[] data)
+    public static void capset(@NonNull StructUserCapHeader hdr, @NonNull StructUserCapData[] data)
             throws ErrnoException {
         Libcore.os.capset(hdr, data);
     }
@@ -331,8 +331,6 @@
      * @param option name of the option to get
      * @return       {@link StructLinger} associated with given {@code fd}
      * @throws ErrnoException
-     *
-     * @hide
      */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @Nullable StructLinger getsockoptLinger(@NonNull FileDescriptor fd, int level, int option) throws ErrnoException { return Libcore.os.getsockoptLinger(fd, level, option); }
@@ -793,8 +791,6 @@
      * @param value  {@link StructLinger} to set for {@code fd}
      * @throws ErrnoException if {@code fd} is invalid; or
      *                        {@code option} is unknown at given {@code level}
-     *
-     * @hide
      */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setsockoptLinger(@NonNull FileDescriptor fd, int level, int option, @NonNull StructLinger value) throws ErrnoException { Libcore.os.setsockoptLinger(fd, level, option, value); }
diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java
index dabb41a..ce8747f 100644
--- a/luni/src/main/java/android/system/OsConstants.java
+++ b/luni/src/main/java/android/system/OsConstants.java
@@ -27,11 +27,11 @@
     }
 
     /**
-     * Returns the index of the element in the {@link StructCapUserData} (cap_user_data)
+     * Returns the index of the element in the {@link StructUserCapData} (cap_user_data)
      * array that this capability is stored in.
      *
      * @param x capability
-     * @return index of the element in the {@link StructCapUserData} array storing this capability
+     * @return index of the element in the {@link StructUserCapData} array storing this capability
      *
      * @hide
      */
@@ -41,7 +41,7 @@
 
     /**
      * Returns the mask for the given capability. This is relative to the capability's
-     * {@link StructCapUserData} (cap_user_data) element, the index of which can be
+     * {@link StructUserCapData} (cap_user_data) element, the index of which can be
      * retrieved with {@link CAP_TO_INDEX}.
      *
      * @param x capability
@@ -412,9 +412,9 @@
     public static final int IP_TOS = placeholder();
     public static final int IP_TTL = placeholder();
     /**
-     * Version constant to be used in {@link StructCapUserHeader} with
-     * {@link Os#capset(StructCapUserHeader, StructCapUserData[])} and
-     * {@link Os#capget(StructCapUserHeader)}.
+     * Version constant to be used in {@link StructUserCapHeader} with
+     * {@link Os#capset(StructUserCapHeader, StructUserCapData[])} and
+     * {@link Os#capget(StructUserCapHeader)}.
      *
      * See <a href="https://man7.org/linux/man-pages/man2/capget.2.html">capget(2)</a>.
      *
diff --git a/luni/src/main/java/android/system/StructLinger.java b/luni/src/main/java/android/system/StructLinger.java
index 6726d59..8622dfa 100644
--- a/luni/src/main/java/android/system/StructLinger.java
+++ b/luni/src/main/java/android/system/StructLinger.java
@@ -22,8 +22,8 @@
  * Corresponds to C's {@code struct linger} from
  * <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html">&lt;sys/socket.h&gt;</a>
  *
- * When enabled, a {@link Os.close(java.io.FileDescriptor) or
- * {@link Os.shutdown(java.io.FileDescriptor, int)} will
+ * When enabled, a {@link Os#close(java.io.FileDescriptor)} or
+ * {@link Os#shutdown(java.io.FileDescriptor, int)} will
  * not return until all queued messages for the socket have been successfully sent or the
  * linger timeout has been reached. Otherwise, the call returns immediately and the closing is
  * done in the background.
@@ -31,18 +31,14 @@
  * See <a href="https://man7.org/linux/man-pages/man7/socket.7.html">socket(7)</a>
  * for linger struct description.
  *
- * @see {@link Os.getsockoptLinger(java.io.FileDescriptor, int, int)}.
- * @see {@link OsConstants.SO_LINGER}.
- *
- * @hide
+ * @see Os#getsockoptLinger(java.io.FileDescriptor, int, int).
+ * @see OsConstants#SO_LINGER
  */
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class StructLinger {
     /** Whether or not linger is enabled. Non-zero is on. */
     public final int l_onoff;
 
     /** Linger time in seconds. */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final int l_linger;
 
     /**
@@ -51,7 +47,6 @@
      * @param l_onoff  whether or not linger is enabled, non-zero is on
      * @param l_linger linger time, in seconds
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public StructLinger(int l_onoff, int l_linger) {
         this.l_onoff = l_onoff;
         this.l_linger = l_linger;
@@ -62,7 +57,6 @@
      *
      * @return {@code true} if linger is enabled, and {@code false} otherwise
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public boolean isOn() {
         return l_onoff != 0;
     }
diff --git a/luni/src/main/java/android/system/StructCapUserData.java b/luni/src/main/java/android/system/StructUserCapData.java
similarity index 89%
rename from luni/src/main/java/android/system/StructCapUserData.java
rename to luni/src/main/java/android/system/StructUserCapData.java
index f8865fa..ce9691f 100644
--- a/luni/src/main/java/android/system/StructCapUserData.java
+++ b/luni/src/main/java/android/system/StructUserCapData.java
@@ -20,15 +20,15 @@
 
 /**
  * Corresponds to Linux' __user_cap_data_struct for capget and capset.
- * Used in {@link Os.capget(StructCapUserHeader)} and
- * {@link Os.capset(StructCapUserHeader, StructCapUserData[])}.
+ * Used in {@link Os.capget( StructUserCapHeader )} and
+ * {@link Os.capset( StructUserCapHeader , StructUserCapData[])}.
  *
  * See <a href="https://man7.org/linux/man-pages/man2/capget.2.html">capget(2)</a>.
  *
  * @hide
  */
 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-public final class StructCapUserData {
+public final class StructUserCapData {
     /** Effective capability mask. */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final int effective; /* __u32 */
@@ -49,7 +49,7 @@
      * @param inheritable inheritable capability mask
      */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-    public StructCapUserData(int effective, int permitted, int inheritable) {
+    public StructUserCapData(int effective, int permitted, int inheritable) {
         this.effective = effective;
         this.permitted = permitted;
         this.inheritable = inheritable;
diff --git a/luni/src/main/java/android/system/StructCapUserHeader.java b/luni/src/main/java/android/system/StructUserCapHeader.java
similarity index 88%
rename from luni/src/main/java/android/system/StructCapUserHeader.java
rename to luni/src/main/java/android/system/StructUserCapHeader.java
index 424db1b..42108e8 100644
--- a/luni/src/main/java/android/system/StructCapUserHeader.java
+++ b/luni/src/main/java/android/system/StructUserCapHeader.java
@@ -20,14 +20,14 @@
 
 /**
  * Corresponds to Linux' __user_cap_header_struct for capget and capset.
- * Used in {@link Os.capget(StructCapUserHeader)} and
- * {@link Os.capset(StructCapUserHeader, StructCapUserData[])}.
+ * Used in {@link Os.capget( StructUserCapHeader )} and
+ * {@link Os.capset( StructUserCapHeader , StructUserCapData[])}.
  *
  * Capabilities defined in <a href="https://man7.org/linux/man-pages/man7/capabilities.7.html">capabilities(7)</a>
  * @hide
  */
 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-public final class StructCapUserHeader {
+public final class StructUserCapHeader {
     /**
      * Version of the header. Note this is not final as capget() may mutate the field when an
      * invalid version is provided.
@@ -48,7 +48,7 @@
      * @param pid     process id
      */
     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-    public StructCapUserHeader(int version, int pid) {
+    public StructUserCapHeader(int version, int pid) {
         this.version = version;
         this.pid = pid;
     }
diff --git a/luni/src/main/java/java/lang/ref/FinalizerReference.java b/luni/src/main/java/java/lang/ref/FinalizerReference.java
index 037af4a..a71044c 100644
--- a/luni/src/main/java/java/lang/ref/FinalizerReference.java
+++ b/luni/src/main/java/java/lang/ref/FinalizerReference.java
@@ -160,16 +160,15 @@
 
         synchronized void awaitFinalization(long timeout) throws InterruptedException {
             final long startTime = System.nanoTime();
-            final long endTime = startTime + timeout;
+            final long endTime = startTime + timeout;  // May wrap.
             while (!finalized) {
                 // 0 signifies no timeout.
                 if (timeout != 0) {
-                    final long currentTime = System.nanoTime();
-                    if (currentTime >= endTime) {
+                    final long deltaTime = endTime - System.nanoTime();
+                    if (deltaTime <= 0) {
                         break;
                     } else {
-                        final long deltaTime = endTime - currentTime;
-                        wait(deltaTime / 1000000, (int)(deltaTime % 1000000));
+                        wait(deltaTime / 1_000_000, (int)(deltaTime % 1_000_000));
                     }
                 } else {
                     wait();
diff --git a/luni/src/main/java/libcore/content/type/MimeMap.java b/luni/src/main/java/libcore/content/type/MimeMap.java
index 3822022..8931524 100644
--- a/luni/src/main/java/libcore/content/type/MimeMap.java
+++ b/luni/src/main/java/libcore/content/type/MimeMap.java
@@ -42,10 +42,10 @@
      *
      * @return builder
      *
-     * @see {@link MimeMap.Builder}
+     * @see MimeMap.Builder
      */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-    public static Builder builder() {
+    public static @NonNull Builder builder() {
         return new Builder();
     }
 
@@ -55,10 +55,10 @@
      *
      * @return builder
      *
-     * @see {@link MimeMap.Builder}
+     * @see MimeMap.Builder
      */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-    public Builder buildUpon() {
+    public @NonNull Builder buildUpon() {
         return new Builder(mimeToExt, extToMime);
     }
 
@@ -75,12 +75,12 @@
     private static volatile MemoizingSupplier<@NonNull MimeMap> instanceSupplier =
             new MemoizingSupplier<>(
                     () -> builder()
-                            .put("application/pdf", "pdf")
-                            .put("image/jpeg", "jpg")
-                            .put("image/x-ms-bmp", "bmp")
-                            .put("text/html", Arrays.asList("htm", "html"))
-                            .put("text/plain", Arrays.asList("text", "txt"))
-                            .put("text/x-java", "java")
+                            .addMimeMapping("application/pdf", "pdf")
+                            .addMimeMapping("image/jpeg", "jpg")
+                            .addMimeMapping("image/x-ms-bmp", "bmp")
+                            .addMimeMapping("text/html", Arrays.asList("htm", "html"))
+                            .addMimeMapping("text/plain", Arrays.asList("text", "txt"))
+                            .addMimeMapping("text/x-java", "java")
                             .build());
 
     private MimeMap(Map<String, String> mimeToExt, Map<String, String> extToMime) {
@@ -245,7 +245,7 @@
 
     /**
      * A builder for mapping of MIME types to extensions and back.
-     * Use {@link #put(String, List)} and {@link #put(String, String)} to add
+     * Use {@link #addMimeMapping(String, List)} and {@link #addMimeMapping(String, String)} to add
      * mapping entries and build final {@link MimeMap} with {@link #build()}.
      *
      * @hide
@@ -353,7 +353,7 @@
          * @return This builder.
          */
         @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-        public Builder put(@NonNull String mimeSpec, @NonNull List<@NonNull String> extensionSpecs)
+        public @NonNull Builder addMimeMapping(@NonNull String mimeSpec, @NonNull List<@NonNull String> extensionSpecs)
         {
             Element mimeElement = Element.ofMimeSpec(mimeSpec); // validate mimeSpec unconditionally
             if (extensionSpecs.isEmpty()) {
@@ -374,8 +374,8 @@
          *
          * @hide
          */
-        public Builder put(@NonNull String mimeSpec, @NonNull String extensionSpec) {
-            return put(mimeSpec, Collections.singletonList(extensionSpec));
+        public @NonNull Builder addMimeMapping(@NonNull String mimeSpec, @NonNull String extensionSpec) {
+            return addMimeMapping(mimeSpec, Collections.singletonList(extensionSpec));
         }
 
         /**
@@ -384,7 +384,7 @@
          * @return {@link MimeMap} containing previously added MIME mapping entries
          */
         @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-        public MimeMap build() {
+        public @NonNull MimeMap build() {
             return new MimeMap(mimeToExt, extToMime);
         }
 
diff --git a/luni/src/main/java/libcore/internal/StringPool.java b/luni/src/main/java/libcore/internal/StringPool.java
index 546a404..fccc354 100644
--- a/luni/src/main/java/libcore/internal/StringPool.java
+++ b/luni/src/main/java/libcore/internal/StringPool.java
@@ -23,12 +23,10 @@
  *
  * @hide
  */
-@libcore.api.CorePlatformApi
 public final class StringPool {
 
     private final String[] pool = new String[512];
 
-    @libcore.api.CorePlatformApi
     public StringPool() {
     }
 
@@ -47,7 +45,6 @@
     /**
      * Returns a string equal to {@code new String(array, start, length)}.
      */
-    @libcore.api.CorePlatformApi
     public String get(char[] array, int start, int length) {
         // Compute an arbitrary hash of the content
         int hashCode = 0;
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index 4ae124e..702b62c 100755
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -21,8 +21,8 @@
 import android.system.Int32Ref;
 import android.system.Int64Ref;
 import android.system.StructAddrinfo;
-import android.system.StructCapUserData;
-import android.system.StructCapUserHeader;
+import android.system.StructUserCapData;
+import android.system.StructUserCapHeader;
 import android.system.StructGroupReq;
 import android.system.StructIfaddrs;
 import android.system.StructLinger;
@@ -111,11 +111,11 @@
     public void bind(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException { os.bind(fd, address, port); }
     public void bind(FileDescriptor fd, SocketAddress address) throws ErrnoException, SocketException { os.bind(fd, address); }
     @Override
-    public StructCapUserData[] capget(StructCapUserHeader hdr) throws ErrnoException {
+    public StructUserCapData[] capget(StructUserCapHeader hdr) throws ErrnoException {
         return os.capget(hdr);
     }
     @Override
-    public void capset(StructCapUserHeader hdr, StructCapUserData[] data) throws ErrnoException {
+    public void capset(StructUserCapHeader hdr, StructUserCapData[] data) throws ErrnoException {
         os.capset(hdr, data);
     }
     @UnsupportedAppUsage
diff --git a/luni/src/main/java/libcore/io/Linux.java b/luni/src/main/java/libcore/io/Linux.java
index 4ecb785..0cc032e 100755
--- a/luni/src/main/java/libcore/io/Linux.java
+++ b/luni/src/main/java/libcore/io/Linux.java
@@ -21,8 +21,8 @@
 import android.system.Int32Ref;
 import android.system.Int64Ref;
 import android.system.StructAddrinfo;
-import android.system.StructCapUserData;
-import android.system.StructCapUserHeader;
+import android.system.StructUserCapData;
+import android.system.StructUserCapHeader;
 import android.system.StructGroupReq;
 import android.system.StructIfaddrs;
 import android.system.StructLinger;
@@ -54,9 +54,9 @@
     public native void bind(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException;
     public native void bind(FileDescriptor fd, SocketAddress address) throws ErrnoException, SocketException;
     @Override
-    public native StructCapUserData[] capget(StructCapUserHeader hdr) throws ErrnoException;
+    public native StructUserCapData[] capget(StructUserCapHeader hdr) throws ErrnoException;
     @Override
-    public native void capset(StructCapUserHeader hdr, StructCapUserData[] data)
+    public native void capset(StructUserCapHeader hdr, StructUserCapData[] data)
             throws ErrnoException;
     public native void chmod(String path, int mode) throws ErrnoException;
     public native void chown(String path, int uid, int gid) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/Memory.java b/luni/src/main/java/libcore/io/Memory.java
index b760919..4af1675 100644
--- a/luni/src/main/java/libcore/io/Memory.java
+++ b/luni/src/main/java/libcore/io/Memory.java
@@ -23,21 +23,23 @@
 
 import dalvik.annotation.optimization.FastNative;
 
+import libcore.api.CorePlatformApi;
 import libcore.util.NonNull;
-import libcore.util.Nullable;
 
 /**
  * Unsafe access to memory.
  *
  * @hide
  */
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
+@CorePlatformApi(status = CorePlatformApi.Status.STABLE)
 public final class Memory {
     private Memory() { }
 
     /**
      * Used to optimize nio heap buffer bulk get operations. 'dst' must be a primitive array.
      * 'dstOffset' is measured in units of 'sizeofElements' bytes.
+     *
+     * @hide
      */
     public static native void unsafeBulkGet(Object dst, int dstOffset, int byteCount,
             byte[] src, int srcOffset, int sizeofElements, boolean swap);
@@ -45,6 +47,7 @@
     /**
      * Used to optimize nio heap buffer bulk put operations. 'src' must be a primitive array.
      * 'srcOffset' is measured in units of 'sizeofElements' bytes.
+     * @hide
      */
     public static native void unsafeBulkPut(byte[] dst, int dstOffset, int byteCount,
             Object src, int srcOffset, int sizeofElements, boolean swap);
@@ -57,8 +60,10 @@
      * @param offset offset in {@code src} to get bytes from
      * @param order  byte order
      * @return int value
+     *
+     * @hide
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
+    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static int peekInt(@NonNull byte[] src, int offset, @NonNull ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
             return (((src[offset++] & 0xff) << 24) |
@@ -73,6 +78,9 @@
         }
     }
 
+    /**
+     * @hide
+     */
     public static long peekLong(byte[] src, int offset, ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
             int h = ((src[offset++] & 0xff) << 24) |
@@ -105,8 +113,10 @@
      * @param offset offset in {@code src} to get bytes from
      * @param order  byte order
      * @return short value
+     *
+     * @hide
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
+    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static short peekShort(@NonNull byte[] src, int offset, @NonNull ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
             return (short) ((src[offset] << 8) | (src[offset + 1] & 0xff));
@@ -123,8 +133,10 @@
      * @param offset offset in {@code dst} to put value to
      * @param value  int value to write
      * @param order  byte order
+     *
+     * @hide
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
+    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static void pokeInt(@NonNull byte[] dst, int offset, int value, @NonNull ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
             dst[offset++] = (byte) ((value >> 24) & 0xff);
@@ -147,8 +159,10 @@
      * @param offset offset in {@code dst} to put value to
      * @param value  long value to write
      * @param order  byte order
+     *
+     * @hide
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
+    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static void pokeLong(@NonNull byte[] dst, int offset, long value, @NonNull ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
             int i = (int) (value >> 32);
@@ -183,8 +197,10 @@
      * @param offset offset in {@code dst} to put value to
      * @param value  short value to write
      * @param order  byte order
+     *
+     * @hide
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
+    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static void pokeShort(@NonNull byte[] dst, int offset, short value, @NonNull ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
             dst[offset++] = (byte) ((value >> 8) & 0xff);
@@ -214,13 +230,19 @@
      *
      * @hide make type-safe before making public?
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
+    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static native void memmove(@NonNull Object dstObject, int dstOffset, @NonNull Object srcObject, int srcOffset, long byteCount);
 
+    /**
+     * @hide
+     */
     @UnsupportedAppUsage
     @FastNative
     public static native byte peekByte(long address);
 
+    /**
+     * @hide
+     */
     @UnsupportedAppUsage
     public static int peekInt(long address, boolean swap) {
         int result = peekIntNative(address);
@@ -232,6 +254,9 @@
     @FastNative
     private static native int peekIntNative(long address);
 
+    /**
+     * @hide
+     */
     @UnsupportedAppUsage
     public static long peekLong(long address, boolean swap) {
         long result = peekLongNative(address);
@@ -243,6 +268,9 @@
     @FastNative
     private static native long peekLongNative(long address);
 
+    /**
+     * @hide
+     */
     public static short peekShort(long address, boolean swap) {
         short result = peekShortNative(address);
         if (swap) {
@@ -253,19 +281,52 @@
     @FastNative
     private static native short peekShortNative(long address);
 
+    /**
+     * @hide
+     */
     @UnsupportedAppUsage
     public static native void peekByteArray(long address, byte[] dst, int dstOffset, int byteCount);
+
+    /**
+     * @hide
+     */
     public static native void peekCharArray(long address, char[] dst, int dstOffset, int charCount, boolean swap);
+
+    /**
+     * @hide
+     */
     public static native void peekDoubleArray(long address, double[] dst, int dstOffset, int doubleCount, boolean swap);
+
+    /**
+     * @hide
+     */
     public static native void peekFloatArray(long address, float[] dst, int dstOffset, int floatCount, boolean swap);
+
+    /**
+     * @hide
+     */
     public static native void peekIntArray(long address, int[] dst, int dstOffset, int intCount, boolean swap);
+
+    /**
+     * @hide
+     */
     public static native void peekLongArray(long address, long[] dst, int dstOffset, int longCount, boolean swap);
+
+    /**
+     * @hide
+     */
     public static native void peekShortArray(long address, short[] dst, int dstOffset, int shortCount, boolean swap);
 
+    /**
+     * @hide
+     */
     @UnsupportedAppUsage
     @FastNative
     public static native void pokeByte(long address, byte value);
 
+    /**
+     * @hide
+     */
     @UnsupportedAppUsage
     public static void pokeInt(long address, int value, boolean swap) {
         if (swap) {
@@ -276,6 +337,9 @@
     @FastNative
     private static native void pokeIntNative(long address, int value);
 
+    /**
+     * @hide
+     */
     @UnsupportedAppUsage
     public static void pokeLong(long address, long value, boolean swap) {
         if (swap) {
@@ -286,6 +350,9 @@
     @FastNative
     private static native void pokeLongNative(long address, long value);
 
+    /**
+     * @hide
+     */
     public static void pokeShort(long address, short value, boolean swap) {
         if (swap) {
             value = Short.reverseBytes(value);
@@ -295,12 +362,39 @@
     @FastNative
     private static native void pokeShortNative(long address, short value);
 
+    /**
+     * @hide
+     */
     @UnsupportedAppUsage
     public static native void pokeByteArray(long address, byte[] src, int offset, int count);
+
+    /**
+     * @hide
+     */
     public static native void pokeCharArray(long address, char[] src, int offset, int count, boolean swap);
+
+    /**
+     * @hide
+     */
     public static native void pokeDoubleArray(long address, double[] src, int offset, int count, boolean swap);
+
+    /**
+     * @hide
+     */
     public static native void pokeFloatArray(long address, float[] src, int offset, int count, boolean swap);
+
+    /**
+     * @hide
+     */
     public static native void pokeIntArray(long address, int[] src, int offset, int count, boolean swap);
+
+    /**
+     * @hide
+     */
     public static native void pokeLongArray(long address, long[] src, int offset, int count, boolean swap);
+
+    /**
+     * @hide
+     */
     public static native void pokeShortArray(long address, short[] src, int offset, int count, boolean swap);
 }
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index fe02877..b127275 100755
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -21,8 +21,8 @@
 import android.system.Int32Ref;
 import android.system.Int64Ref;
 import android.system.StructAddrinfo;
-import android.system.StructCapUserData;
-import android.system.StructCapUserHeader;
+import android.system.StructUserCapData;
+import android.system.StructUserCapHeader;
 import android.system.StructGroupReq;
 import android.system.StructIfaddrs;
 import android.system.StructLinger;
@@ -62,8 +62,8 @@
     public InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException;
     public void bind(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException;
     public void bind(FileDescriptor fd, SocketAddress address) throws ErrnoException, SocketException;
-    public StructCapUserData[] capget(StructCapUserHeader hdr) throws ErrnoException;
-    public void capset(StructCapUserHeader hdr, StructCapUserData[] data) throws ErrnoException;
+    public StructUserCapData[] capget(StructUserCapHeader hdr) throws ErrnoException;
+    public void capset(StructUserCapHeader hdr, StructUserCapData[] data) throws ErrnoException;
     @UnsupportedAppUsage
     public void chmod(String path, int mode) throws ErrnoException;
     public void chown(String path, int uid, int gid) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/net/http/Dns.java b/luni/src/main/java/libcore/net/http/Dns.java
index 7a14aad..9526211 100644
--- a/luni/src/main/java/libcore/net/http/Dns.java
+++ b/luni/src/main/java/libcore/net/http/Dns.java
@@ -21,6 +21,8 @@
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.List;
+import libcore.util.NonNull;
+import libcore.util.Nullable;
 
 /**
  * A domain name service that resolves IP addresses for host names.
@@ -30,10 +32,10 @@
 public interface Dns extends com.android.okhttp.internalandroidapi.Dns {
     /**
      * Returns the IP addresses of {@code hostname}, in the order they should
-     * be attempted.
+     * be attempted. Returns loopback addresses for {@code null} host.
      *
      * @param hostname The host name will be looked up.
      */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-    List<InetAddress> lookup(String hostname) throws UnknownHostException;
+    @NonNull List<@NonNull InetAddress> lookup(@Nullable String hostname) throws UnknownHostException;
 }
\ No newline at end of file
diff --git a/luni/src/main/java/libcore/net/http/HttpURLConnectionFactory.java b/luni/src/main/java/libcore/net/http/HttpURLConnectionFactory.java
index 1c46020..b54f5f8 100644
--- a/luni/src/main/java/libcore/net/http/HttpURLConnectionFactory.java
+++ b/luni/src/main/java/libcore/net/http/HttpURLConnectionFactory.java
@@ -25,6 +25,7 @@
 import java.util.concurrent.TimeUnit;
 
 import javax.net.SocketFactory;
+import libcore.util.NonNull;
 
 /**
  * A HttpURLConnectionFactory that supports some configuration on a per-factory or per-connection
@@ -41,7 +42,7 @@
      * Create a new {@link HttpURLConnectionFactory} instance.
      */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-    public static HttpURLConnectionFactory createInstance() {
+    @NonNull public static HttpURLConnectionFactory createInstance() {
         return new HttpURLConnectionFactory();
     }
 
@@ -59,7 +60,7 @@
      */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public void setNewConnectionPool(int maxIdleConnections, long keepAliveDuration,
-            TimeUnit timeUnit) {
+            @NonNull TimeUnit timeUnit) {
         mFactory.setNewConnectionPool(maxIdleConnections, keepAliveDuration, timeUnit);
     }
 
@@ -69,7 +70,7 @@
      * @param dns the dns resolver for looking up.
      */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-    public void setDns(Dns dns) {
+    public void setDns(@NonNull Dns dns) {
         mFactory.setDns(dns);
     }
 
@@ -85,8 +86,8 @@
      *         configuration.
      */
     @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
-    public URLConnection openConnection(URL url, SocketFactory socketFactory, Proxy proxy) throws
-            IOException {
+    public URLConnection openConnection(@NonNull URL url, @NonNull SocketFactory socketFactory,
+            @NonNull Proxy proxy) throws IOException {
         return mFactory.openConnection(url, socketFactory, proxy);
     }
 }
diff --git a/luni/src/main/java/libcore/util/FP16.java b/luni/src/main/java/libcore/util/FP16.java
index cc1d4d6..49fd926 100644
--- a/luni/src/main/java/libcore/util/FP16.java
+++ b/luni/src/main/java/libcore/util/FP16.java
@@ -87,7 +87,7 @@
  */
 
 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
-public class FP16 {
+public final class FP16 {
     /**
      * The number of bits used to represent a half-precision float value.
      */
diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp
index d7b6c22..7c47129 100755
--- a/luni/src/main/native/libcore_io_Linux.cpp
+++ b/luni/src/main/native/libcore_io_Linux.cpp
@@ -878,14 +878,14 @@
 // We assume the calls are rare enough that it does not make sense to cache class objects. The
 // advantage is lower maintenance burden.
 
-static bool ReadStructCapUserHeader(
+static bool ReadStructUserCapHeader(
         JNIEnv* env, jobject java_header, __user_cap_header_struct* c_header) {
     if (java_header == nullptr) {
         jniThrowNullPointerException(env, "header is null");
         return false;
     }
 
-    ScopedLocalRef<jclass> header_class(env, env->FindClass("android/system/StructCapUserHeader"));
+    ScopedLocalRef<jclass> header_class(env, env->FindClass("android/system/StructUserCapHeader"));
     if (header_class.get() == nullptr) {
         return false;
     }
@@ -909,9 +909,9 @@
     return true;
 }
 
-static void SetStructCapUserHeaderVersion(
+static void SetStructUserCapHeaderVersion(
         JNIEnv* env, jobject java_header, __user_cap_header_struct* c_header) {
-    ScopedLocalRef<jclass> header_class(env, env->FindClass("android/system/StructCapUserHeader"));
+    ScopedLocalRef<jclass> header_class(env, env->FindClass("android/system/StructUserCapHeader"));
     if (header_class.get() == nullptr) {
         env->ExceptionClear();
         return;
@@ -925,7 +925,7 @@
     env->SetIntField(java_header, version_fid, c_header->version);
 }
 
-static jobject CreateStructCapUserData(
+static jobject CreateStructUserCapData(
         JNIEnv* env, jclass data_class, __user_cap_data_struct* c_data) {
     if (c_data == nullptr) {
         // Should not happen.
@@ -944,13 +944,13 @@
     return env->NewObject(data_class, data_cons, e, p, i);
 }
 
-static bool ReadStructCapUserData(JNIEnv* env, jobject java_data, __user_cap_data_struct* c_data) {
+static bool ReadStructUserCapData(JNIEnv* env, jobject java_data, __user_cap_data_struct* c_data) {
     if (java_data == nullptr) {
         jniThrowNullPointerException(env, "data is null");
         return false;
     }
 
-    ScopedLocalRef<jclass> data_class(env, env->FindClass("android/system/StructCapUserData"));
+    ScopedLocalRef<jclass> data_class(env, env->FindClass("android/system/StructUserCapData"));
     if (data_class.get() == nullptr) {
         return false;
     }
@@ -1072,7 +1072,7 @@
 static jobjectArray Linux_capget(JNIEnv* env, jobject, jobject header) {
     // Convert Java header struct to kernel datastructure.
     __user_cap_header_struct cap_header;
-    if (!ReadStructCapUserHeader(env, header, &cap_header)) {
+    if (!ReadStructUserCapHeader(env, header, &cap_header)) {
         AssertException(env);
         return nullptr;
     }
@@ -1083,7 +1083,7 @@
         // Check for EINVAL. In that case, mutate the header.
         if (errno == EINVAL) {
             int saved_errno = errno;
-            SetStructCapUserHeaderVersion(env, header, &cap_header);
+            SetStructUserCapHeaderVersion(env, header, &cap_header);
             errno = saved_errno;
         }
         throwErrnoException(env, "capget");
@@ -1091,7 +1091,7 @@
     }
 
     // Create the result array.
-    ScopedLocalRef<jclass> data_class(env, env->FindClass("android/system/StructCapUserData"));
+    ScopedLocalRef<jclass> data_class(env, env->FindClass("android/system/StructUserCapData"));
     if (data_class.get() == nullptr) {
         return nullptr;
     }
@@ -1104,7 +1104,7 @@
     // Translate the values we got.
     for (size_t i = 0; i < result_size; ++i) {
         ScopedLocalRef<jobject> value(
-                env, CreateStructCapUserData(env, data_class.get(), &cap_data[i]));
+                env, CreateStructUserCapData(env, data_class.get(), &cap_data[i]));
         if (value.get() == nullptr) {
             AssertException(env);
             return nullptr;
@@ -1118,7 +1118,7 @@
         JNIEnv* env, jobject, jobject header, jobjectArray data) {
     // Convert Java header struct to kernel datastructure.
     __user_cap_header_struct cap_header;
-    if (!ReadStructCapUserHeader(env, header, &cap_header)) {
+    if (!ReadStructUserCapHeader(env, header, &cap_header)) {
         AssertException(env);
         return;
     }
@@ -1137,7 +1137,7 @@
     // Translate the values we got.
     for (size_t i = 0; i < result_size; ++i) {
         ScopedLocalRef<jobject> value(env, env->GetObjectArrayElement(data, i));
-        if (!ReadStructCapUserData(env, value.get(), &cap_data[i])) {
+        if (!ReadStructUserCapData(env, value.get(), &cap_data[i])) {
             AssertException(env);
             return;
         }
@@ -2752,9 +2752,9 @@
     NATIVE_METHOD(Linux, bind, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"),
     NATIVE_METHOD_OVERLOAD(Linux, bind, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress),
     NATIVE_METHOD(Linux, capget,
-                  "(Landroid/system/StructCapUserHeader;)[Landroid/system/StructCapUserData;"),
+                  "(Landroid/system/StructUserCapHeader;)[Landroid/system/StructUserCapData;"),
     NATIVE_METHOD(Linux, capset,
-                  "(Landroid/system/StructCapUserHeader;[Landroid/system/StructCapUserData;)V"),
+                  "(Landroid/system/StructUserCapHeader;[Landroid/system/StructUserCapData;)V"),
     NATIVE_METHOD(Linux, chmod, "(Ljava/lang/String;I)V"),
     NATIVE_METHOD(Linux, chown, "(Ljava/lang/String;II)V"),
     NATIVE_METHOD(Linux, close, "(Ljava/io/FileDescriptor;)V"),
diff --git a/luni/src/test/java/libcore/java/lang/BootstrapMethodErrorTest.java b/luni/src/test/java/libcore/java/lang/BootstrapMethodErrorTest.java
new file mode 100644
index 0000000..613ad00
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/BootstrapMethodErrorTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2021 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.lang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class BootstrapMethodErrorTest {
+
+    private final String causeMessage = "Cause";
+    private final String errorMessage = "Error message";
+
+    @Test
+    public void constructor() {
+        BootstrapMethodError error = new BootstrapMethodError();
+
+        assertNull(error.getCause());
+        assertNull(error.getMessage());
+    }
+
+    @Test
+    public void constructorLString() {
+        BootstrapMethodError error = new BootstrapMethodError(errorMessage);
+
+        assertEquals(errorMessage, error.getMessage());
+        assertNull(error.getCause());
+    }
+
+    @Test
+    public void constructorLString_withNull() {
+        BootstrapMethodError error = new BootstrapMethodError((String) null);
+
+        assertNull(error.getMessage());
+        assertNull(error.getCause());
+    }
+
+    @Test
+    public void constructorLString_LThrowable() {
+        Exception cause = new Exception(causeMessage);
+        BootstrapMethodError error = new BootstrapMethodError(errorMessage, cause);
+
+        assertEquals(cause, error.getCause());
+        assertEquals(errorMessage, error.getMessage());
+    }
+
+    @Test
+    public void constructorLString_LThrowable_nullMessage() {
+        Exception cause = new Exception(causeMessage);
+        BootstrapMethodError error = new BootstrapMethodError(null, cause);
+
+        assertNull(error.getMessage());
+        assertEquals(cause, error.getCause());
+    }
+
+    @Test
+    public void constructorLString_LThrowable_nullCause() {
+        BootstrapMethodError error = new BootstrapMethodError(errorMessage, null /* cause */);
+
+        assertNull(error.getCause());
+        assertEquals(errorMessage, error.getMessage());
+    }
+
+    @Test
+    public void constructorLString_LThrowable_bothArgumentsNull() {
+        BootstrapMethodError error = new BootstrapMethodError(null, null);
+
+        assertNull(error.getCause());
+        assertNull(error.getMessage());
+    }
+
+    @Test
+    public void constructorLThrowable() {
+        Exception cause = new Exception(causeMessage);
+        BootstrapMethodError error = new BootstrapMethodError(cause);
+
+        assertEquals(cause, error.getCause());
+        assertEquals(cause.toString(), error.getMessage());
+    }
+
+    @Test
+    public void constructorLThrowable_withNull() {
+        BootstrapMethodError error = new BootstrapMethodError((Throwable) null /* cause */);
+
+        assertNull(error.getCause());
+        assertNull(error.getMessage());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/ErrorTest.java b/luni/src/test/java/libcore/java/lang/ErrorTest.java
new file mode 100644
index 0000000..1962b07
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/ErrorTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2021 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.lang;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ErrorTest {
+
+    @Test
+    public void withNonWritableStackTrace_getStackTraceIsEmpty() {
+        Error error = new TestError("message", null /* cause */,
+                false /* enableSuppression */,
+                false /* writableStackTrace */);
+
+        assertEquals(0, error.getStackTrace().length);
+    }
+
+    @Test
+    public void withWritableStackTrace_nonEmptyGetStackTrace() {
+        Error error = new TestError("message", null /* cause */,
+                false /* enableSuppression */,
+                true /* writableStackTrace */);
+
+        assertNotEquals(0, error.getStackTrace().length);
+
+        StackTraceElement topStackTraceElement = error.getStackTrace()[0];
+        assertEquals("withWritableStackTrace_nonEmptyGetStackTrace",
+                topStackTraceElement.getMethodName());
+    }
+
+    @Test
+    public void whenSuppressionDisabled_addSuppressHasNoEffect() {
+        Error error = new TestError("Message", null, false /* enableSuppression */, true);
+
+        assertEquals(0, error.getSuppressed().length);
+        error.addSuppressed(new Exception("suppressed exception"));
+        assertEquals(0, error.getSuppressed().length);
+    }
+
+    @Test
+    public void whenSuppressionEnabled_addsSuppressed() {
+        Error error = new TestError("message", null /* cause */, true /* enableSuppression */,
+                true /* writableStackTrace */);
+
+        assertEquals(0, error.getSuppressed().length);
+
+        Exception suppressed = new Exception("suppressed");
+        error.addSuppressed(suppressed);
+        assertArrayEquals(new Throwable[] {suppressed}, error.getSuppressed());
+    }
+
+
+    private static final class TestError extends Error {
+        protected TestError(String message, Throwable cause, boolean enableSuppression,
+                boolean writableStackTrace) {
+            super(message, cause, enableSuppression, writableStackTrace);
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/InheritableThreadLocalTest.java b/luni/src/test/java/libcore/java/lang/InheritableThreadLocalTest.java
new file mode 100644
index 0000000..afba40a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/InheritableThreadLocalTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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.lang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class InheritableThreadLocalTest {
+
+    @Test
+    public void childValue_shouldReturnInputArgument() {
+        TestInheritableThreadLocal<Object> threadLocal = new TestInheritableThreadLocal<>();
+
+        assertNull(threadLocal.childValue(null));
+        Object parentValue = new Object();
+        assertEquals(parentValue, threadLocal.childValue(parentValue));
+    }
+
+    private static final class TestInheritableThreadLocal<T> extends InheritableThreadLocal<T> {
+
+        @Override
+        public T childValue(T parentValue) {
+            return super.childValue(parentValue);
+        }
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/lang/InternalErrorTest.java b/luni/src/test/java/libcore/java/lang/InternalErrorTest.java
new file mode 100644
index 0000000..acf588e
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/InternalErrorTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 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.lang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class InternalErrorTest {
+
+    @Test
+    public void constructorLThrowable() {
+        Throwable cause = new Exception("cause");
+        InternalError error = new InternalError(cause);
+
+        assertEquals(cause, error.getCause());
+        assertEquals("java.lang.Exception: cause", error.getMessage());
+    }
+
+    @Test
+    public void constructorLThrowable_withNull() {
+        InternalError error = new InternalError((Throwable) null);
+
+        assertNull(error.getCause());
+        assertNull(error.getMessage());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/LinkageErrorTest.java b/luni/src/test/java/libcore/java/lang/LinkageErrorTest.java
new file mode 100644
index 0000000..2a853d7
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/LinkageErrorTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 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.lang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class LinkageErrorTest {
+
+    private final String errorMessage = "error message";
+
+    @Test
+    public void constructorLString_LThrowable() {
+        Exception cause = new Exception();
+        LinkageError error = new LinkageError(errorMessage, cause);
+
+        assertEquals(cause, error.getCause());
+        assertEquals(errorMessage, error.getMessage());
+    }
+
+    @Test
+    public void constructorLString_LThrowable_nullMessage() {
+        Exception cause = new Exception();
+        LinkageError error = new LinkageError(null, cause);
+
+        assertNull(error.getMessage());
+        assertEquals(cause, error.getCause());
+    }
+
+    @Test
+    public void constructorLString_LThrowable_nullCause() {
+        LinkageError error = new LinkageError(errorMessage, null /* cause */);
+
+        assertEquals(errorMessage, error.getMessage());
+        assertNull(error.getCause());
+    }
+
+    @Test
+    public void constructorLString_LThrowable_bothArgumentsNull() {
+        LinkageError error = new LinkageError(null, null);
+
+        assertNull(error.getCause());
+        assertNull(error.getMessage());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/lang/PackageTest.java b/luni/src/test/java/libcore/java/lang/PackageTest.java
index 0ea412c..ff1a9c3 100644
--- a/luni/src/test/java/libcore/java/lang/PackageTest.java
+++ b/luni/src/test/java/libcore/java/lang/PackageTest.java
@@ -17,6 +17,8 @@
 package libcore.java.lang;
 
 import dalvik.system.VMRuntime;
+
+import java.net.URL;
 import java.util.Arrays;
 import java.util.List;
 import libcore.junit.junit3.TestCaseWithRules;
@@ -24,6 +26,7 @@
 import libcore.junit.util.SwitchTargetSdkVersionRule.TargetSdkVersion;
 import org.junit.Rule;
 import org.junit.rules.TestRule;
+import org.mockito.internal.matchers.Null;
 
 public final class PackageTest extends TestCaseWithRules {
 
@@ -70,4 +73,137 @@
     public void testGetPackages() {
         assertTrue(packages.contains(getClass().getPackage()));
     }
+
+    public void testGetAnnotationsByType() {
+        Package libcoreJavaLang = Package.getPackage("libcore.java.lang");
+
+        assertEquals(1, libcoreJavaLang.getAnnotationsByType(TestPackageAnnotation.class).length);
+        assertEquals(0, libcoreJavaLang.getAnnotationsByType(Override.class).length);
+    }
+
+    public void testGetAnnotationsByType_shouldThrowNPE_whenNullIsPassed() {
+        Package libcoreJavaLang = Package.getPackage("libcore.java.lang");
+
+        try {
+            libcoreJavaLang.getAnnotationsByType(null);
+            fail();
+        } catch (NullPointerException ignored) {
+            // expected
+        }
+    }
+
+    public void testIsSealed_nonSealedPackage() throws Exception {
+        TestClassLoader testClassLoader = new TestClassLoader();
+        Package nonSealedPackage = testClassLoader.definePackage(
+                "libcore.java.lang.nonsealed",
+                "spec title",
+                "spec version",
+                "spec vendor",
+                "impl title",
+                "impl version",
+                "impl vendor",
+                null /* sealBase */);
+
+        assertFalse(nonSealedPackage.isSealed());
+        assertFalse(nonSealedPackage.isSealed(new URL("file://libcore/java/lang/nonsealed")));
+    }
+
+    public void testIsSealed_sealedPackage() throws Exception {
+        TestClassLoader testClassLoader = new TestClassLoader();
+        URL sealBase = new URL("file://libcore/java/lang/sealed");
+        Package sealedPackage = testClassLoader.definePackage(
+                "libcore.java.lang.sealed",
+                "spec title",
+                "spec version",
+                "spec vendor",
+                "impl title",
+                "impl version",
+                "impl vendor",
+                sealBase);
+
+        assertTrue(sealedPackage.isSealed());
+        assertTrue(sealedPackage.isSealed(sealBase));
+        assertFalse(sealedPackage.isSealed(new URL("file://libcore/java/lang")));
+        try {
+            sealedPackage.isSealed(null);
+            fail();
+        } catch (NullPointerException ignored) {
+            // expected
+        }
+    }
+
+    public void testGetSpecificationVendor() {
+        String specVendor = "specification vendor";
+        TestClassLoader testClassLoader = new TestClassLoader();
+        Package aPackage = testClassLoader.definePackage(
+                "libcore.java.lang.nonsealed",
+                "spec title",
+                "spec version",
+                specVendor,
+                "impl title",
+                "impl version",
+                "impl vendor",
+                null /* sealBase */);
+
+        assertEquals(specVendor, aPackage.getSpecificationVendor());
+    }
+
+    public void testGetSpecificationVersion() {
+        String specVersion = "specification version";
+        TestClassLoader testClassLoader = new TestClassLoader();
+        Package aPackage = testClassLoader.definePackage(
+                "libcore.java.lang.nonsealed",
+                "spec title",
+                specVersion,
+                "spec vendor",
+                "impl title",
+                "impl version",
+                "impl vendor",
+                null /* sealBase */);
+
+        assertEquals(specVersion, aPackage.getSpecificationVersion());
+    }
+
+    public void testIsCompatibleWith() {
+        String specVersion = "2.3.1";
+        TestClassLoader testClassLoader = new TestClassLoader();
+        Package aPackage = testClassLoader.definePackage(
+                "libcore.java.lang.nonsealed",
+                "spec title",
+                specVersion,
+                "spec vendor",
+                "impl title",
+                "impl version",
+                "impl vendor",
+                null /* sealBase */);
+
+        assertTrue(aPackage.isCompatibleWith(specVersion));
+        assertTrue(aPackage.isCompatibleWith("2.2.99.1"));
+        assertTrue(aPackage.isCompatibleWith("1.0"));
+        assertTrue(aPackage.isCompatibleWith("2.3.1.0"));
+        assertTrue(aPackage.isCompatibleWith("2.3"));
+        assertFalse(aPackage.isCompatibleWith("2.4"));
+        try {
+            aPackage.isCompatibleWith(null);
+            fail();
+        } catch (NullPointerException ignored) {
+            // expected
+        }
+    }
+
+
+    /**
+     * {@link java.lang.Package} constructors are package-private and
+     * {@link java.lang.ClassLoader#definePackage(String, String, String, String, String, String, String, URL)}
+     * is other way to create instance of {@link java.lang.Package}
+     */
+    private static final class TestClassLoader extends ClassLoader {
+        @Override
+        public Package definePackage(String name, String specTitle, String specVersion,
+                String specVendor, String implTitle, String implVersion, String implVendor,
+                URL sealBase) throws IllegalArgumentException {
+            return super.definePackage(name, specTitle, specVersion, specVendor, implTitle,
+                    implVersion, implVendor, sealBase);
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/RuntimeExceptionTest.java b/luni/src/test/java/libcore/java/lang/RuntimeExceptionTest.java
new file mode 100644
index 0000000..35ab3d4
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/RuntimeExceptionTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2021 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.lang;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class RuntimeExceptionTest {
+
+    @Test
+    public void withNonWritableStackTrace_getStackTraceIsEmpty() {
+        RuntimeException exception = new TestRuntimeException("message", null /* cause */,
+                false /* enableSuppression */,
+                false /* writableStackTrace */);
+
+        assertEquals(0, exception.getStackTrace().length);
+    }
+
+    @Test
+    public void withWritableStackTrace_nonEmptyGetStackTrace() {
+        RuntimeException exception = new TestRuntimeException("message", null /* cause */,
+                false /* enableSuppression */,
+                true /* writableStackTrace */);
+
+        assertNotEquals(0, exception.getStackTrace().length);
+
+        StackTraceElement topStackTraceElement = exception.getStackTrace()[0];
+        assertEquals("withWritableStackTrace_nonEmptyGetStackTrace",
+                topStackTraceElement.getMethodName());
+    }
+
+    @Test
+    public void whenSuppressionDisabled_addSuppressHasNoEffect() {
+        RuntimeException exception = new TestRuntimeException("Message", null,
+                false /* enableSuppression */, true /* writableStackTrace */);
+
+        assertEquals(0, exception.getSuppressed().length);
+        exception.addSuppressed(new Exception("suppressed exception"));
+        assertEquals(0, exception.getSuppressed().length);
+    }
+
+    @Test
+    public void whenSuppressionEnabled_addsSuppressed() {
+        RuntimeException error = new TestRuntimeException("message", null /* cause */,
+                true /* enableSuppression */, true /* writableStackTrace */);
+
+        assertEquals(0, error.getSuppressed().length);
+
+        Exception suppressed = new Exception("suppressed");
+        error.addSuppressed(suppressed);
+        assertArrayEquals(new Throwable[] {suppressed}, error.getSuppressed());
+    }
+
+    private static final class TestRuntimeException extends RuntimeException {
+        TestRuntimeException(String message, Throwable cause, boolean enableSuppression,
+                boolean writableStackTrace) {
+            super(message, cause, enableSuppression, writableStackTrace);
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/RuntimePermissionTest.java b/luni/src/test/java/libcore/java/lang/RuntimePermissionTest.java
new file mode 100644
index 0000000..33c0898
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/RuntimePermissionTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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.lang;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class RuntimePermissionTest {
+
+    @Test
+    public void constructorLString_LString() {
+        RuntimePermission runtimePermission = new RuntimePermission(null, null);
+        assertEquals("", runtimePermission.getActions());
+        assertEquals("", runtimePermission.getName());
+
+        runtimePermission = new RuntimePermission("non empty", "non empty");
+        assertEquals("", runtimePermission.getActions());
+        assertEquals("", runtimePermission.getName());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/SystemTest.java b/luni/src/test/java/libcore/java/lang/SystemTest.java
index fa69c07..258f8a1 100644
--- a/luni/src/test/java/libcore/java/lang/SystemTest.java
+++ b/luni/src/test/java/libcore/java/lang/SystemTest.java
@@ -273,4 +273,12 @@
         } catch (SecurityException expected) {
         }
     }
+
+    /**
+     * Overall {@link System#console()} return value depends on how exactly runtime was started, but
+     * for Android apps it will be null.
+     */
+    public void testSystem_console() {
+        assertNull(System.console());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/ThreadGroupTest.java b/luni/src/test/java/libcore/java/lang/ThreadGroupTest.java
new file mode 100644
index 0000000..4076bd1
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/ThreadGroupTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2021 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.lang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(JUnit4.class)
+public class ThreadGroupTest {
+
+    private CountDownLatch mLatch;
+
+    @Before
+    public void setup() {
+        mLatch = new CountDownLatch(2);
+    }
+
+    @Test
+    public void interrupt_shouldInterruptAllThreadsInAGroup() throws Exception {
+        ThreadGroup group = new ThreadGroup("group under test");
+
+        Thread first = createHangThread(group);
+        Thread second = createHangThread(group);
+
+        first.start();
+        second.start();
+
+        group.interrupt();
+
+        assertTrue("Some thread was not interrupted", mLatch.await(5, TimeUnit.SECONDS));
+    }
+
+    @Test
+    public void interrupt_shouldInterruptThreadsInSubgroups() throws Exception {
+        ThreadGroup parentGroup = new ThreadGroup("parent thread group");
+        ThreadGroup childGroup = new ThreadGroup(parentGroup, "child thread group");
+
+        Thread first = createHangThread(parentGroup);
+        Thread second = createHangThread(childGroup);
+
+        first.start();
+        second.start();
+
+        parentGroup.interrupt();
+
+        assertTrue("Some thread was not interrupted", mLatch.await(5, TimeUnit.SECONDS));
+    }
+
+    @Test
+    public void interrupt_shouldNotInterruptThreadsInParentGroup() throws Exception {
+        ThreadGroup parentGroup = new ThreadGroup("parent thread group");
+        ThreadGroup childGroup = new ThreadGroup(parentGroup, "child thread group");
+
+        Thread first = createHangThread(parentGroup);
+        Thread second = createHangThread(childGroup);
+
+        first.start();
+        second.start();
+
+        childGroup.interrupt();
+
+        assertFalse("Both threads were interrupted", mLatch.await(5, TimeUnit.SECONDS));
+
+        assertEquals("Thread from parent group was interrupted", 1, mLatch.getCount());
+    }
+
+    @Test
+    public void suspend_shouldThrowUnsupportedOperationException() throws Exception {
+        ThreadGroup threadGroup = new ThreadGroup("test group");
+
+        Thread thread = createHangThread(threadGroup);
+        thread.start();
+
+        try {
+            threadGroup.suspend();
+            fail("suspend() didn't throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException ignored) {
+            // expected
+        } finally {
+            thread.join();
+        }
+    }
+
+    @Test
+    public void stop_shouldThrowUnsupportedOperationException() throws Exception {
+        ThreadGroup threadGroup = new ThreadGroup("test group");
+
+        Thread thread = createHangThread(threadGroup);
+        thread.start();
+
+        try {
+            threadGroup.stop();
+            fail("stop() didn't throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException ignored) {
+            // expected
+        } finally {
+            thread.join();
+        }
+    }
+
+    private Thread createHangThread(ThreadGroup threadGroup) {
+        return new Thread(threadGroup, () -> {
+            try {
+                Thread.sleep(20_000);
+            } catch (InterruptedException e) {
+                mLatch.countDown();
+            }
+        });
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/lang/ThreadTest.java b/luni/src/test/java/libcore/java/lang/ThreadTest.java
index e91e567..19ca2b6 100644
--- a/luni/src/test/java/libcore/java/lang/ThreadTest.java
+++ b/luni/src/test/java/libcore/java/lang/ThreadTest.java
@@ -16,6 +16,13 @@
 
 package libcore.java.lang;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertNotNull;
+
 import dalvik.system.InMemoryDexClassLoader;
 
 import java.io.InputStream;
@@ -31,13 +38,17 @@
 import junit.framework.Assert;
 import junit.framework.TestCase;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 import org.mockito.InOrder;
 import org.mockito.Mockito;
 
 import libcore.io.Streams;
 import libcore.java.lang.ref.FinalizationTester;
 
-public final class ThreadTest extends TestCase {
+@RunWith(JUnit4.class)
+public final class ThreadTest {
     static {
         System.loadLibrary("javacoretests");
     }
@@ -46,12 +57,14 @@
      * getContextClassLoader returned a non-application class loader.
      * http://code.google.com/p/android/issues/detail?id=5697
      */
-    public void testJavaContextClassLoader() throws Exception {
+    @Test
+    public void javaContextClassLoader() throws Exception {
         Assert.assertNotNull("Must have a Java context ClassLoader",
                 Thread.currentThread().getContextClassLoader());
     }
 
-    public void testLeakingStartedThreads() {
+    @Test
+    public void leakingStartedThreads() {
         final AtomicInteger finalizedThreadsCount = new AtomicInteger();
         for (int i = 0; true; i++) {
             try {
@@ -64,7 +77,8 @@
         assertTrue("Started threads were never finalized!", finalizedThreadsCount.get() > 0);
     }
 
-    public void testLeakingUnstartedThreads() {
+    @Test
+    public void leakingUnstartedThreads() {
         final AtomicInteger finalizedThreadsCount = new AtomicInteger();
         for (int i = 0; true; i++) {
             try {
@@ -77,7 +91,8 @@
         assertTrue("Unstarted threads were never finalized!", finalizedThreadsCount.get() > 0);
     }
 
-    public void testThreadSleep() throws Exception {
+    @Test
+    public void threadSleep() throws Exception {
         int millis = 1000;
         long start = System.currentTimeMillis();
 
@@ -89,7 +104,8 @@
         assertTrue("Actual sleep off by " + offBy + " ms", offBy <= 250);
     }
 
-    public void testThreadInterrupted() throws Exception {
+    @Test
+    public void threadInterrupted() throws Exception {
         Thread.currentThread().interrupt();
         try {
             Thread.sleep(0);
@@ -99,7 +115,8 @@
         }
     }
 
-    public void testThreadSleepIllegalArguments() throws Exception {
+    @Test
+    public void threadSleepIllegalArguments() throws Exception {
 
         try {
             Thread.sleep(-1);
@@ -120,7 +137,8 @@
         }
     }
 
-    public void testThreadWakeup() throws Exception {
+    @Test
+    public void threadWakeup() throws Exception {
         WakeupTestThread t1 = new WakeupTestThread();
         WakeupTestThread t2 = new WakeupTestThread();
 
@@ -135,22 +153,26 @@
         assertTrue("Threads did not finish", t1.done && t2.done);
     }
 
-    public void testContextClassLoaderIsNotNull() {
+    @Test
+    public void contextClassLoaderIsNotNull() {
         assertNotNull(Thread.currentThread().getContextClassLoader());
     }
 
-    public void testContextClassLoaderIsInherited() {
+    @Test
+    public void contextClassLoaderIsInherited() {
         Thread other = new Thread();
         assertSame(Thread.currentThread().getContextClassLoader(), other.getContextClassLoader());
     }
 
-    public void testSetPriority_unstarted() throws Exception {
+    @Test
+    public void setPriority_unstarted() {
         Thread thread = new Thread();
         checkSetPriority_inBounds_succeeds(thread);
         checkSetPriority_outOfBounds_fails(thread);
     }
 
-    public void testSetPriority_starting() throws Exception {
+    @Test
+    public void setPriority_starting() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         Thread thread = new Thread("starting thread") {
             @Override public void run() { try { latch.await(); } catch (Exception e) { } }
@@ -167,7 +189,8 @@
         thread.join();
     }
 
-    public void testSetPriority_started() throws Exception {
+    @Test
+    public void setPriority_started() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         Thread startedThread = new Thread("started thread") {
             @Override public void run() { try { latch.await(); } catch (Exception e) { } }
@@ -179,7 +202,8 @@
         startedThread.join();
     }
 
-    public void testSetPriority_joined() throws Exception {
+    @Test
+    public void setPriority_joined() throws Exception {
         Thread joinedThread = new Thread();
         joinedThread.start();
         joinedThread.join();
@@ -223,7 +247,8 @@
         assertEquals(oldPriority, thread.getPriority()); // priority shouldn't have changed
     }
 
-    public void testUncaughtExceptionPreHandler_calledBeforeDefaultHandler() {
+    @Test
+    public void uncaughtExceptionPreHandler_calledBeforeDefaultHandler() {
         UncaughtExceptionHandler initialHandler = Mockito.mock(UncaughtExceptionHandler.class);
         UncaughtExceptionHandler defaultHandler = Mockito.mock(UncaughtExceptionHandler.class);
         InOrder inOrder = Mockito.inOrder(initialHandler, defaultHandler);
@@ -245,7 +270,8 @@
         }
     }
 
-    public void testUncaughtExceptionPreHandler_noDefaultHandler() {
+    @Test
+    public void uncaughtExceptionPreHandler_noDefaultHandler() {
         UncaughtExceptionHandler initialHandler = Mockito.mock(UncaughtExceptionHandler.class);
         UncaughtExceptionHandler originalDefaultHandler
                 = Thread.getDefaultUncaughtExceptionHandler();
@@ -266,7 +292,8 @@
     /**
      * Thread.getStackTrace() is broken. http://b/1252043
      */
-    public void testGetStackTrace() throws Exception {
+    @Test
+    public void getStackTrace() throws Exception {
         Thread t1 = new Thread("t1") {
             @Override public void run() {
                 doSomething();
@@ -294,7 +321,8 @@
      * (source-filename, line number) hard-coded in a class loaded from
      * pre-built test resources.
      */
-    public void testGetStackTrace_debugInfo() throws Exception {
+    @Test
+    public void getStackTrace_debugInfo() throws Exception {
         StackTraceElement ste = getStackTraceElement("debugInfo");
 
         // Verify that this StackTraceElement appears as we expect it to
@@ -315,7 +343,8 @@
      * a line number when debug info is missing for a method; the method is
      * declared on a class loaded from pre-built test resources.
      */
-    public void testGetStackTrace_noDebugInfo() throws Exception {
+    @Test
+    public void getStackTrace_noDebugInfo() throws Exception {
         StackTraceElement ste = getStackTraceElement("noDebugInfo");
 
         // Verify that this StackTraceElement appears as we expect it to
@@ -367,7 +396,8 @@
         return result;
     }
 
-    public void testGetAllStackTracesIncludesAllGroups() throws Exception {
+    @Test
+    public void getAllStackTracesIncludesAllGroups() throws Exception {
         final AtomicInteger visibleTraces = new AtomicInteger();
         ThreadGroup group = new ThreadGroup("1");
         Thread t2 = new Thread(group, "t2") {
@@ -383,7 +413,8 @@
     }
 
     // http://b/27748318
-    public void testNativeThreadNames() throws Exception {
+    @Test
+    public void nativeThreadNames() {
         String testResult = nativeTestNativeThreadNames();
         // Not using assertNull here because this results in a better error message.
         if (testResult != null) {
@@ -392,7 +423,8 @@
     }
 
     // http://b/29746125
-    public void testParkUntilWithUnderflowValue() throws Exception {
+    @Test
+    public void parkUntilWithUnderflowValue() throws Exception {
         final Thread current = Thread.currentThread();
 
         // watchdog to unpark the tread in case it will be parked
@@ -449,7 +481,8 @@
     /**
      * Test that large timeout arguments don't cause crashes. b/161006928 .
      */
-    public void testParkNanosHugeTimeout() throws InterruptedException {
+    @Test
+    public void parkNanosHugeTimeout() throws InterruptedException {
         for (long i = 0; i < 5; ++i) {
             LongParker p = new LongParker(Long.MAX_VALUE - 800_000_000L * i);
             Thread.sleep(10);
@@ -467,7 +500,8 @@
      * Check that call Thread.start for already started thread
      * throws {@code IllegalThreadStateException}
      */
-    public void testThreadDoubleStart() {
+    @Test
+    public void threadDoubleStart() {
         final ReentrantLock lock = new ReentrantLock();
         Thread thread = new Thread() {
             public void run() {
@@ -499,7 +533,8 @@
      * Check that call Thread.start for already finished thread
      * throws {@code IllegalThreadStateException}
      */
-    public void testThreadRestart() {
+    @Test
+    public void threadRestart() {
         Thread thread = new Thread();
         thread.start();
         try {
@@ -513,6 +548,18 @@
         }
     }
 
+    @Test
+    public void resume_shouldThrowUnsupportedOperationException() {
+        Thread thread = new Thread();
+
+        try {
+            thread.resume();
+            fail();
+        } catch (UnsupportedOperationException ignored) {
+            // expected
+        }
+    }
+
     // This method returns {@code null} if all tests pass, or a non-null String containing
     // failure details if an error occured.
     private static native String nativeTestNativeThreadNames();
@@ -528,7 +575,7 @@
     }
 
     private class WakeupTestThread extends Thread {
-        public boolean done;
+        public volatile boolean done;
 
         public void run() {
             done = false;
diff --git a/luni/src/test/java/libcore/java/lang/UnicodeScriptTest.java b/luni/src/test/java/libcore/java/lang/UnicodeScriptTest.java
new file mode 100644
index 0000000..1ea57ab
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/UnicodeScriptTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 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.lang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.lang.Character.UnicodeScript;
+
+@RunWith(JUnit4.class)
+public class UnicodeScriptTest {
+
+    @Test
+    public void forName_shouldThrowIllegalArgumentException_whenNameIsUnknown() {
+        try {
+            UnicodeScript.forName("NON EXISTING SCRIPT NAME");
+            fail();
+        } catch (IllegalArgumentException ignored) {
+            // expected
+        }
+    }
+
+    @Test
+    public void forName_shouldThrowNPE_whenNullIsPassed() {
+        try {
+            UnicodeScript.forName(null);
+            fail();
+        } catch (NullPointerException ignored) {
+            // expected
+        }
+    }
+
+    @Test
+    public void forName_shouldAcceptAllEnumValues() {
+        for (UnicodeScript unicodeScript : UnicodeScript.values()) {
+            assertEquals(unicodeScript, UnicodeScript.forName(unicodeScript.name()));
+        }
+    }
+
+    @Test
+    public void of_shouldThrowIllegalArgumentException_whenInvalidUnicodePointPassed() {
+        try {
+            UnicodeScript.of(-1);
+            fail();
+        } catch (IllegalArgumentException ignored) {
+            // expected
+        }
+
+        try {
+            UnicodeScript.of(Character.MAX_CODE_POINT + 1);
+            fail();
+        } catch (IllegalArgumentException ignored) {
+            // expected
+        }
+    }
+
+    @Test
+    public void of_onWellKnownScripts() {
+        int asciiZero = '\u0030';
+        assertEquals(UnicodeScript.COMMON, UnicodeScript.of(asciiZero));
+        int asciiA = '\u0041';
+        assertEquals(UnicodeScript.LATIN, UnicodeScript.of(asciiA));
+        int asciiTilda = '\u007E';
+        assertEquals(UnicodeScript.COMMON, UnicodeScript.of(asciiTilda));
+        int asciiGbp = '\u00A3';
+        assertEquals(UnicodeScript.COMMON, UnicodeScript.of(asciiGbp));
+        int greekCapitalAlpha = '\u0391';
+        assertEquals(UnicodeScript.GREEK, UnicodeScript.of(greekCapitalAlpha));
+        int cyrillicCapitalA = '\u0410';
+        assertEquals(UnicodeScript.CYRILLIC, UnicodeScript.of(cyrillicCapitalA));
+        assertEquals(UnicodeScript.HAN, UnicodeScript.of('\u4E00'));
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/VirtualMachineErrorTest.java b/luni/src/test/java/libcore/java/lang/VirtualMachineErrorTest.java
new file mode 100644
index 0000000..268584f
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/VirtualMachineErrorTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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.lang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class VirtualMachineErrorTest {
+    @Test
+    public void constructorLThrowable() {
+        Throwable cause = new Exception("cause");
+        VirtualMachineError error = new TestVirtualMachineError(cause);
+
+        assertEquals(cause, error.getCause());
+        assertEquals("java.lang.Exception: cause", error.getMessage());
+    }
+
+    @Test
+    public void constructorLThrowable_withNull() {
+        VirtualMachineError error = new TestVirtualMachineError(null /* cause */);
+
+        assertNull(error.getCause());
+        assertNull(error.getMessage());
+    }
+
+    private static final class TestVirtualMachineError extends VirtualMachineError {
+        public TestVirtualMachineError(Throwable cause) {
+            super(cause);
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/ref/ReferenceQueueTest.java b/luni/src/test/java/libcore/java/lang/ref/ReferenceQueueTest.java
index b059b6c..399b360 100644
--- a/luni/src/test/java/libcore/java/lang/ref/ReferenceQueueTest.java
+++ b/luni/src/test/java/libcore/java/lang/ref/ReferenceQueueTest.java
@@ -91,7 +91,8 @@
         final long enqueueDelayMsec = 500L;
         final long startNanos = System.nanoTime();
         enqueueLater(referenceQueue, enqueueDelayMsec);
-        referenceQueue.remove();
+        Object result = referenceQueue.remove();
+        assertNotNull(result);
         final long durationNanos = System.nanoTime() - startNanos;
         final long durationMillis = TimeUnit.NANOSECONDS.toMillis(durationNanos);
         checkDuration(enqueueDelayMsec, durationMillis);
@@ -102,7 +103,12 @@
         final long enqueueDelayMsec = 500L;
         final long startNanos = System.nanoTime();
         enqueueLater(referenceQueue, enqueueDelayMsec);
-        referenceQueue.remove(1000);
+        Object result = referenceQueue.remove(1000);
+        if (result == null) {
+          // Also report the actual queue status.
+          assertNotNull(referenceQueue.poll());
+          assertNotNull(result);
+        }
         final long durationNanos = System.nanoTime() - startNanos;
         final long durationMillis = TimeUnit.NANOSECONDS.toMillis(durationNanos);
         checkDuration(enqueueDelayMsec, durationMillis);
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index dda8499..aecc1ad 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -900,9 +900,9 @@
 
     @Test public void getFileNameMap_compositeExtension_customMimeMap() {
         MimeMap testMimeMap = MimeMap.builder()
-                .put("text/html", "html")
-                .put("application/gzip", "gz")
-                .put("application/tar+gzip", "tar.gz")
+                .addMimeMapping("text/html", "html")
+                .addMimeMapping("application/gzip", "gz")
+                .addMimeMapping("application/tar+gzip", "tar.gz")
                 .build();
         MimeMap defaultMimeMap = MimeMap.getDefault();
         MimeMap.setDefaultSupplier(() -> testMimeMap);
diff --git a/luni/src/test/java/libcore/java/util/ConcurrentHashMapTest.java b/luni/src/test/java/libcore/java/util/ConcurrentHashMapTest.java
deleted file mode 100644
index 397108c..0000000
--- a/luni/src/test/java/libcore/java/util/ConcurrentHashMapTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-public class ConcurrentHashMapTest extends junit.framework.TestCase {
-
-    public void test_getOrDefault() {
-        MapDefaultMethodTester.test_getOrDefault(new ConcurrentHashMap<>(),
-                false /*doesNotAcceptNullKey*/, false /*doesNotAcceptNullValue*/,
-                true /*getAcceptsAnyObject*/);
-    }
-
-    public void test_forEach() {
-        MapDefaultMethodTester.test_forEach(new ConcurrentHashMap<>());
-    }
-
-    public void test_putIfAbsent() {
-        MapDefaultMethodTester
-                .test_putIfAbsent(new ConcurrentHashMap<>(), false /*doesNotAcceptNullKey*/,
-                        false /*doesNotAcceptNullValue*/);
-    }
-
-    public void test_remove() {
-        MapDefaultMethodTester
-                .test_remove(new ConcurrentHashMap<>(), false /*doesNotAcceptNullKey*/,
-                        false /*doesNotAcceptNullValue*/);
-    }
-
-    public void test_replace$K$V$V() {
-        MapDefaultMethodTester
-                .test_replace$K$V$V(new ConcurrentHashMap<>(), false /*doesNotAcceptNullKey*/,
-                        false /*doesNotAcceptNullValue*/);
-    }
-
-    public void test_replace$K$V() {
-        MapDefaultMethodTester.test_replace$K$V(new ConcurrentHashMap<>(),
-                false /*doesNotAcceptNullKey*/, false /*doesNotAcceptNullValue*/);
-    }
-
-    public void test_computeIfAbsent() {
-        MapDefaultMethodTester.test_computeIfAbsent(new ConcurrentHashMap<>(),
-                false /*doesNotAcceptNullKey*/, false /*doesNotAcceptNullValue*/);
-    }
-
-    public void test_computeIfPresent() {
-        MapDefaultMethodTester.test_computeIfPresent(new ConcurrentHashMap<>(),
-                false /*doesNotAcceptNullKey*/);
-    }
-
-    public void test_compute() {
-        MapDefaultMethodTester
-                .test_compute(new ConcurrentHashMap<>(), false /*doesNotAcceptNullKey*/);
-    }
-
-    public void test_merge() {
-        MapDefaultMethodTester.test_merge(new ConcurrentHashMap<>(),
-                false /*doesNotAcceptNullKey*/);
-    }
-}
diff --git a/luni/src/test/java/libcore/java/util/beans/PropertyChangeSupportTest.java b/luni/src/test/java/libcore/java/util/beans/PropertyChangeSupportTest.java
index 1c9b399..3ae0acc 100644
--- a/luni/src/test/java/libcore/java/util/beans/PropertyChangeSupportTest.java
+++ b/luni/src/test/java/libcore/java/util/beans/PropertyChangeSupportTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.util.beans;
 
+import java.beans.IndexedPropertyChangeEvent;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeListenerProxy;
@@ -246,6 +247,68 @@
         }.test();
     }
 
+    public void testFireIndexedPropertyChange_intUpdate() {
+        Object bean = "bean";
+        PropertyChangeSupport support = new PropertyChangeSupport(bean);
+
+        EventLog listenerToIntProperty = new EventLog();
+        support.addPropertyChangeListener("intProperty", listenerToIntProperty);
+
+        support.fireIndexedPropertyChange("intProperty", 10, 1, 2);
+
+        List<PropertyChangeEvent> events = listenerToIntProperty.log;
+        assertEquals(1, events.size());
+        assertEquals(1, events.get(0).getOldValue());
+        assertEquals(2, events.get(0).getNewValue());
+        assertEquals("intProperty", events.get(0).getPropertyName());
+        assertTrue(events.get(0) instanceof IndexedPropertyChangeEvent);
+        assertEquals(10, ((IndexedPropertyChangeEvent) events.get(0)).getIndex());
+    }
+
+    public void testFireIndexedPropertyChange_intUpdate_noEventWhenOldIsEqualToNew() {
+        Object bean = "bean";
+        PropertyChangeSupport support = new PropertyChangeSupport(bean);
+
+        EventLog listenerToIntProperty = new EventLog();
+        support.addPropertyChangeListener("intProperty", listenerToIntProperty);
+
+        support.fireIndexedPropertyChange("intProperty", 0, 1, 1);
+
+        List<PropertyChangeEvent> events = listenerToIntProperty.log;
+        assertTrue(events.isEmpty());
+    }
+
+    public void testFireIndexedPropertyChange_booleanUpdate() {
+        Object bean = "bean";
+        PropertyChangeSupport support = new PropertyChangeSupport(bean);
+
+        EventLog listenerToBooleanProperty = new EventLog();
+        support.addPropertyChangeListener("booleanProperty", listenerToBooleanProperty);
+
+        support.fireIndexedPropertyChange("booleanProperty", 11, true, false);
+
+        List<PropertyChangeEvent> events = listenerToBooleanProperty.log;
+        assertEquals(1, events.size());
+        assertEquals(true, events.get(0).getOldValue());
+        assertEquals(false, events.get(0).getNewValue());
+        assertEquals("booleanProperty", events.get(0).getPropertyName());
+        assertTrue(events.get(0) instanceof IndexedPropertyChangeEvent);
+        assertEquals(11, ((IndexedPropertyChangeEvent) events.get(0)).getIndex());
+    }
+
+    public void testFireIndexedPropertyChange_booleanUpdate_noEventWhenOldIsEqualToNew() {
+        Object bean = "bean";
+        PropertyChangeSupport support = new PropertyChangeSupport(bean);
+
+        EventLog listenerToBooleanProperty = new EventLog();
+        support.addPropertyChangeListener("booleanProperty", listenerToBooleanProperty);
+
+        support.fireIndexedPropertyChange("booleanProperty", 0, true, true);
+
+        List<PropertyChangeEvent> events = listenerToBooleanProperty.log;
+        assertTrue(events.isEmpty());
+    }
+
     private String describe(PropertyChangeListener[] listeners) {
         List<String> result = new ArrayList<String>();
         for (PropertyChangeListener listener : listeners) {
diff --git a/luni/src/test/java/libcore/java/util/concurrent/AbstractExecutorServiceTest.java b/luni/src/test/java/libcore/java/util/concurrent/AbstractExecutorServiceTest.java
new file mode 100644
index 0000000..c4ed1e6
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/AbstractExecutorServiceTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.RunnableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AbstractExecutorServiceTest {
+
+    static class TestExecutorService extends AbstractExecutorService {
+
+        public volatile boolean isRunning = true;
+
+        public boolean awaitTermination(long timeout, TimeUnit unit) {
+            return isShutdown();
+        }
+
+        public boolean isShutdown() {
+            return !isRunning;
+        }
+
+        public boolean isTerminated() {
+            return isShutdown();
+        }
+
+        public void shutdown() {
+            isRunning = false;
+        }
+
+        public List<Runnable> shutdownNow() {
+            shutdown();
+            return Collections.emptyList();
+        }
+
+        public void execute(Runnable command) {
+            command.run();
+        }
+
+        public <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
+            return super.newTaskFor(runnable, value);
+        }
+    }
+
+    @Test
+    public void testSubmitRunnableWithValue() throws Exception {
+        Integer value = Integer.valueOf(42);
+        ExecutorService service = new TestExecutorService();
+        AtomicBoolean didRun = new AtomicBoolean(false);
+        Future<Integer> future = service.submit(() -> didRun.set(true), value);
+        Integer result = future.get();
+        assertSame(value, result);
+        assertTrue(didRun.get());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/AbstractQueuedLongSynchronizerTest.java b/luni/src/test/java/libcore/java/util/concurrent/AbstractQueuedLongSynchronizerTest.java
new file mode 100644
index 0000000..2735eab
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/AbstractQueuedLongSynchronizerTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AbstractQueuedLongSynchronizerTest {
+
+    class DefaultMutex extends AbstractQueuedLongSynchronizer {
+
+        @Override
+        public boolean isHeldExclusively() {
+            return super.isHeldExclusively();
+        }
+
+        @Override
+        public boolean tryAcquire(long acquires) {
+            return super.tryAcquire(acquires);
+        }
+
+        @Override
+        public long tryAcquireShared(long acquires) {
+            return super.tryAcquireShared(acquires);
+        }
+
+        @Override
+        public boolean tryRelease(long releases) {
+            return super.tryRelease(releases);
+        }
+
+        @Override
+        public boolean tryReleaseShared(long releases) {
+            return super.tryReleaseShared(releases);
+        }
+
+        public AbstractQueuedLongSynchronizer.ConditionObject newCondition() {
+            return new AbstractQueuedLongSynchronizer.ConditionObject();
+        }
+
+    }
+
+    @Test
+    public void testDefaultIsHeldExclusivelyFails() {
+        DefaultMutex mutex = new DefaultMutex();
+        try {
+            mutex.isHeldExclusively();
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testDefaultTryAcquireFails() {
+        DefaultMutex mutex = new DefaultMutex();
+        try {
+            mutex.tryAcquire(1);
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testDefaultTryAcquireSharedFails() {
+        DefaultMutex mutex = new DefaultMutex();
+        try {
+            mutex.tryAcquireShared(1);
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testDefaultTryReleaseFails() {
+        DefaultMutex mutex = new DefaultMutex();
+        try {
+            mutex.tryRelease(1);
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testDefaultTryReleaseSharedFails() {
+        DefaultMutex mutex = new DefaultMutex();
+        try {
+            mutex.tryReleaseShared(1);
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testConditionObjectCreation() {
+        DefaultMutex mutex = new DefaultMutex();
+        AbstractQueuedLongSynchronizer.ConditionObject condition = mutex.newCondition();
+        assertTrue(mutex.owns(condition));
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/AbstractQueuedSynchronizerTest.java b/luni/src/test/java/libcore/java/util/concurrent/AbstractQueuedSynchronizerTest.java
new file mode 100644
index 0000000..0c0b98a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/AbstractQueuedSynchronizerTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AbstractQueuedSynchronizerTest {
+
+    class DefaultMutex extends AbstractQueuedSynchronizer {
+
+        @Override
+        public boolean isHeldExclusively() {
+            return super.isHeldExclusively();
+        }
+
+        @Override
+        public boolean tryAcquire(int acquires) {
+            return super.tryAcquire(acquires);
+        }
+
+        @Override
+        public int tryAcquireShared(int acquires) {
+            return super.tryAcquireShared(acquires);
+        }
+
+        @Override
+        public boolean tryRelease(int releases) {
+            return super.tryRelease(releases);
+        }
+
+        @Override
+        public boolean tryReleaseShared(int releases) {
+            return super.tryReleaseShared(releases);
+        }
+
+        public AbstractQueuedSynchronizer.ConditionObject newCondition() {
+            return new AbstractQueuedSynchronizer.ConditionObject();
+        }
+
+    }
+
+    @Test
+    public void testDefaultIsHeldExclusivelyFails() {
+        DefaultMutex mutex = new DefaultMutex();
+        try {
+            mutex.isHeldExclusively();
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testDefaultTryAcquireFails() {
+        DefaultMutex mutex = new DefaultMutex();
+        try {
+            mutex.tryAcquire(1);
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testDefaultTryAcquireSharedFails() {
+        DefaultMutex mutex = new DefaultMutex();
+        try {
+            mutex.tryAcquireShared(1);
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testDefaultTryReleaseFails() {
+        DefaultMutex mutex = new DefaultMutex();
+        try {
+            mutex.tryRelease(1);
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testDefaultTryReleaseSharedFails() {
+        DefaultMutex mutex = new DefaultMutex();
+        try {
+            mutex.tryReleaseShared(1);
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testConditionObjectCreation() {
+        DefaultMutex mutex = new DefaultMutex();
+        AbstractQueuedSynchronizer.ConditionObject condition = mutex.newCondition();
+        assertTrue(mutex.owns(condition));
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/BrokenBarrierExceptionTest.java b/luni/src/test/java/libcore/java/util/concurrent/BrokenBarrierExceptionTest.java
new file mode 100644
index 0000000..3632c09
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/BrokenBarrierExceptionTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.concurrent.BrokenBarrierException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class BrokenBarrierExceptionTest {
+
+    /**
+     * constructor creates exception with detail message
+     */
+    @Test
+    public void testConstructWithMessage() {
+        BrokenBarrierException exception = new BrokenBarrierException("test");
+        assertEquals("test", exception.getMessage());
+        assertNull(exception.getCause());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/CompletionExceptionTest.java b/luni/src/test/java/libcore/java/util/concurrent/CompletionExceptionTest.java
new file mode 100644
index 0000000..956026c
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/CompletionExceptionTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.concurrent.CompletionException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+public class CompletionExceptionTest {
+
+    // Adding derived class to be able to test the protected constructors
+    private class TestCompletionException extends CompletionException {
+        public TestCompletionException() {
+            super();
+        }
+        public TestCompletionException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * constructor creates exception without any details
+     */
+    @Test
+    public void testConstructNoMessage() {
+        CompletionException exception = new TestCompletionException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+
+    /**
+     * constructor creates exception with detail message
+     */
+    @Test
+    public void testConstructWithMessage() {
+        CompletionException exception = new TestCompletionException("test");
+        assertEquals("test", exception.getMessage());
+        assertNull(exception.getCause());
+    }
+
+    /**
+     * constructor creates exception with detail message and cause
+     */
+    @Test
+    public void testConstructWithMessageAndCause() {
+        Throwable cause = new Exception();
+        CompletionException exception = new CompletionException("test", cause);
+        assertEquals("test", exception.getMessage());
+        assertEquals(cause, exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ConcurrentHashMapTest.java b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentHashMapTest.java
new file mode 100644
index 0000000..233e6d3
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentHashMapTest.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2016 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.AbstractMap;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.LongAdder;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.ToDoubleBiFunction;
+import java.util.function.ToDoubleFunction;
+import java.util.function.ToIntBiFunction;
+import java.util.function.ToIntFunction;
+import java.util.function.ToLongBiFunction;
+import java.util.function.ToLongFunction;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import libcore.java.util.MapDefaultMethodTester;
+
+@RunWith(JUnit4.class)
+public class ConcurrentHashMapTest {
+
+    // Constants that dictate parallelism for 'reduce' calls. The value represents the number of
+    // elements needed for the operation to be executed in parallel.
+    static final long IN_PARALLEL = 1L;
+    static final long SEQUENTIALLY = Long.MAX_VALUE;
+
+    static final int MAP_SIZE = 100;
+
+    static class SumKeys implements BiFunction<Map.Entry<Long,Long>,
+                 Map.Entry<Long,Long>, Map.Entry<Long,Long>> {
+        public Map.Entry<Long,Long> apply(Map.Entry<Long,Long> x, Map.Entry<Long,Long> y) {
+            return new AbstractMap.SimpleEntry<Long,Long>
+             (Long.valueOf(x.getKey().longValue() + y.getKey().longValue()),
+              Long.valueOf(1L));
+        }
+    }
+
+    static class IncrementKey implements Function<Map.Entry<Long, Long>, Map.Entry<Long, Long>> {
+        public Map.Entry<Long, Long> apply(Map.Entry<Long, Long> in) {
+            return new AbstractMap.SimpleEntry<Long, Long>
+                (Long.valueOf(in.getKey().longValue() + 1),
+                 Long.valueOf(1L));
+        }
+    }
+
+    static class KeyAsDouble implements ToDoubleFunction<Map.Entry<Long, Long>> {
+        public double applyAsDouble(Map.Entry<Long, Long> in) {
+            return in.getKey().doubleValue();
+        }
+    }
+
+    static class KeyAsInt implements ToIntFunction<Map.Entry<Long, Long>> {
+        public int applyAsInt(Map.Entry<Long, Long> in) {
+            return in.getKey().intValue();
+        }
+    }
+
+    static class KeyAsLong implements ToLongFunction<Map.Entry<Long, Long>> {
+        public long applyAsLong(Map.Entry<Long, Long> in) {
+            return in.getKey().longValue();
+        }
+    }
+
+    static class IncrementKeyToDouble implements ToDoubleBiFunction<Long, Long> {
+        public double applyAsDouble(Long key, Long value) {
+            return (key.doubleValue() + 1);
+        }
+    }
+
+    static class IncrementKeyToInt implements ToIntBiFunction<Long, Long> {
+        public int applyAsInt(Long key, Long value) {
+            return (key.intValue() + 1);
+        }
+    }
+
+    static class IncrementKeyToLong implements ToLongBiFunction<Long, Long> {
+        public long applyAsLong(Long key, Long value) {
+            return (key.longValue() + 1);
+        }
+    }
+
+    static ConcurrentHashMap<Long, Long> createMap() {
+        ConcurrentHashMap<Long, Long> map = new ConcurrentHashMap<Long, Long>(MAP_SIZE);
+        for (int i = 0; i < MAP_SIZE; ++i) {
+            map.put(Long.valueOf(i), Long.valueOf(-i));
+        }
+        return map;
+    }
+
+    @Test
+    public void testReduceEntriesToDoubleSequentially() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        double result = map.reduceEntriesToDouble(SEQUENTIALLY,
+                new KeyAsDouble(), 0.0, Double::sum);
+        assertEquals((double)MAP_SIZE * (MAP_SIZE - 1) / 2, result, 0.5);
+    }
+
+    @Test
+    public void testReduceEntriesToDoubleInParallel() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        double result = map.reduceEntriesToDouble(IN_PARALLEL,
+                new KeyAsDouble(), 0.0, Double::sum);
+        assertEquals((double)MAP_SIZE * (MAP_SIZE - 1) / 2, result, 0.5);
+    }
+
+    @Test
+    public void testReduceEntriesToIntSequentially() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        int result = map.reduceEntriesToInt(SEQUENTIALLY, new KeyAsInt(), 0, Integer::sum);
+        assertEquals((int)MAP_SIZE * (MAP_SIZE - 1) / 2, result);
+    }
+
+    @Test
+    public void testReduceEntriesToIntInParallel() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        int result = map.reduceEntriesToInt(IN_PARALLEL, new KeyAsInt(), 0, Integer::sum);
+        assertEquals(MAP_SIZE * (MAP_SIZE - 1) / 2, result);
+    }
+
+    @Test
+    public void testReduceEntriesToLongSequentially() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        long result = map.reduceEntriesToLong(SEQUENTIALLY, new KeyAsLong(), 0L, Long::sum);
+        assertEquals((long)MAP_SIZE * (MAP_SIZE - 1) / 2, result);
+    }
+
+    @Test
+    public void testReduceEntriesToLongInParallel() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        long result = map.reduceEntriesToLong(IN_PARALLEL, new KeyAsLong(), 0L, Long::sum);
+        assertEquals((long)MAP_SIZE * (MAP_SIZE - 1) / 2, result);
+    }
+
+    @Test
+    public void testTransformReduceEntriesSequentially() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        Map.Entry<Long, Long> result;
+        result = map.reduceEntries(SEQUENTIALLY, new IncrementKey(), new SumKeys());
+        assertEquals((long)MAP_SIZE * (MAP_SIZE + 1) / 2, result.getKey().longValue());
+    }
+
+    @Test
+    public void testTransformReduceEntriesInParallel() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        Map.Entry<Long, Long> result;
+        result = map.reduceEntries(IN_PARALLEL, new IncrementKey(), new SumKeys());
+        assertEquals((long)MAP_SIZE * (MAP_SIZE + 1) / 2, result.getKey().longValue());
+    }
+
+    @Test
+    public void testTransformReduceEntriesToDoubleSequentially() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        double result = map.reduceToDouble(SEQUENTIALLY,
+                new IncrementKeyToDouble(), 0.0, Double::sum);
+        assertEquals((double)MAP_SIZE * (MAP_SIZE + 1) / 2, result, 0.5);
+    }
+
+    @Test
+    public void testTransformReduceEntriesToDoubleInParallel() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        double result = map.reduceToDouble(IN_PARALLEL,
+                new IncrementKeyToDouble(), 0.0, Double::sum);
+        assertEquals((double)MAP_SIZE * (MAP_SIZE + 1) / 2, result, 0.5);
+    }
+
+    @Test
+    public void testTransformReduceEntriesToIntSequentially() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        int result = map.reduceToInt(SEQUENTIALLY, new IncrementKeyToInt(), 0, Integer::sum);
+        assertEquals(MAP_SIZE * (MAP_SIZE + 1) / 2, result);
+    }
+
+    @Test
+    public void testTransformReduceEntriesToIntInParallel() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        int result = map.reduceToInt(IN_PARALLEL, new IncrementKeyToInt(), 0, Integer::sum);
+        assertEquals(MAP_SIZE * (MAP_SIZE + 1) / 2, result);
+    }
+
+    @Test
+    public void testTransformReduceEntriesToLongSequentially() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        long result = map.reduceToLong(SEQUENTIALLY, new IncrementKeyToLong(), 0L, Long::sum);
+        assertEquals((long)MAP_SIZE * (MAP_SIZE + 1) / 2, result);
+    }
+
+    @Test
+    public void testTransformReduceEntriesToLongInParallel() {
+        ConcurrentHashMap<Long, Long> map = createMap();
+        long result = map.reduceToLong(IN_PARALLEL, new IncrementKeyToLong(), 0L, Long::sum);
+        assertEquals((long)MAP_SIZE * (MAP_SIZE + 1) / 2, result);
+    }
+
+    @Test
+    public void testNewKeySetWithCapacity() {
+        final int capacity = 10;
+        Set<Long> set = ConcurrentHashMap.<Long>newKeySet(capacity);
+        assertTrue(set.isEmpty());
+        for (long i = 0; i < capacity; ++i) {
+            assertTrue(set.add(i));
+        }
+        assertFalse(set.isEmpty());
+        assertEquals(capacity, set.size());
+    }
+
+    @Test
+    public void testNewKeySetWithZeroCapacity() {
+        final int capacity = 0;
+        final int elements = 10;
+        Set<Long> set = ConcurrentHashMap.<Long>newKeySet(capacity);
+        assertTrue(set.isEmpty());
+        for (long i = 0; i < elements; ++i) {
+            assertTrue(set.add(i));
+        }
+        assertFalse(set.isEmpty());
+        assertEquals(elements, set.size());
+    }
+
+    @Test
+    public void testNewKeySetWithInvalidCapacity() {
+        try {
+            final int capacity = -10;
+            Set<Long> set = ConcurrentHashMap.<Long>newKeySet(capacity);
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testGetOrDefault() {
+        MapDefaultMethodTester.test_getOrDefault(new ConcurrentHashMap<>(),
+                false /*doesNotAcceptNullKey*/, false /*doesNotAcceptNullValue*/,
+                true /*getAcceptsAnyObject*/);
+    }
+
+    @Test
+    public void testForEach() {
+        MapDefaultMethodTester.test_forEach(new ConcurrentHashMap<>());
+    }
+
+    @Test
+    public void testPutIfAbsent() {
+        MapDefaultMethodTester
+                .test_putIfAbsent(new ConcurrentHashMap<>(), false /*doesNotAcceptNullKey*/,
+                        false /*doesNotAcceptNullValue*/);
+    }
+
+    @Test
+    public void testRemove() {
+        MapDefaultMethodTester
+                .test_remove(new ConcurrentHashMap<>(), false /*doesNotAcceptNullKey*/,
+                        false /*doesNotAcceptNullValue*/);
+    }
+
+    @Test
+    public void testReplace$K$V$V() {
+        MapDefaultMethodTester
+                .test_replace$K$V$V(new ConcurrentHashMap<>(), false /*doesNotAcceptNullKey*/,
+                        false /*doesNotAcceptNullValue*/);
+    }
+
+    @Test
+    public void testReplace$K$V() {
+        MapDefaultMethodTester.test_replace$K$V(new ConcurrentHashMap<>(),
+                false /*doesNotAcceptNullKey*/, false /*doesNotAcceptNullValue*/);
+    }
+
+    @Test
+    public void testComputeIfAbsent() {
+        MapDefaultMethodTester.test_computeIfAbsent(new ConcurrentHashMap<>(),
+                false /*doesNotAcceptNullKey*/, false /*doesNotAcceptNullValue*/);
+    }
+
+    @Test
+    public void testComputeIfPresent() {
+        MapDefaultMethodTester.test_computeIfPresent(new ConcurrentHashMap<>(),
+                false /*doesNotAcceptNullKey*/);
+    }
+
+    @Test
+    public void testCompute() {
+        MapDefaultMethodTester
+                .test_compute(new ConcurrentHashMap<>(), false /*doesNotAcceptNullKey*/);
+    }
+
+    @Test
+    public void testMerge() {
+        MapDefaultMethodTester.test_merge(new ConcurrentHashMap<>(),
+                false /*doesNotAcceptNullKey*/);
+    }
+
+    private ConcurrentHashMap.KeySetView<String, Boolean> createKeySet() {
+        final int count = 5;
+        ConcurrentHashMap.KeySetView<String, Boolean> set =
+            ConcurrentHashMap.<String>newKeySet(count);
+        assertTrue(set.isEmpty());
+        set.add("A");
+        set.add("B");
+        set.add("C");
+        set.add("D");
+        set.add("E");
+        assertFalse(set.isEmpty());
+        assertEquals(count, set.size());
+        return set;
+    }
+
+    @Test
+    public void testKeySetViewClear() {
+        ConcurrentHashMap.KeySetView set = createKeySet();
+        assertFalse(set.isEmpty());
+        set.clear();
+        assertEquals(0, set.size());
+        assertTrue(set.isEmpty());
+    }
+
+    @Test
+    public void testKeySetViewContainsAll() {
+        ConcurrentHashMap.KeySetView set = createKeySet();
+        assertTrue(set.containsAll(Arrays.asList()));
+        assertTrue(set.containsAll(Arrays.asList("A")));
+        assertTrue(set.containsAll(Arrays.asList("A", "E")));
+        assertTrue(set.containsAll(Arrays.asList("A", "B", "C", "D", "E")));
+        assertFalse(set.containsAll(Arrays.asList("A", "B", "F")));
+        assertFalse(set.containsAll(Arrays.asList("F")));
+    }
+
+    @Test
+    public void testKeySetViewForEach() {
+        final int count = 8;
+        ConcurrentHashMap.KeySetView<Integer, Boolean> set =
+            ConcurrentHashMap.<Integer>newKeySet(count);
+        for(int i = 0; i < count; ++i) {
+            set.add(i+1);
+        }
+        LongAdder adder = new LongAdder();
+        set.forEach((Integer x) -> adder.add(x.longValue()));
+        // The size is small enough for the sum not to overflow
+        assertEquals(set.size() * (set.size() + 1) / 2, adder.sum());
+    }
+
+    @Test
+    public void testKeySetViewRemoveAll() {
+        ConcurrentHashMap.KeySetView set = createKeySet();
+        assertTrue(set.removeAll(Arrays.asList("A", "C")));
+        assertEquals(set.size(), 3);
+        assertTrue(set.containsAll(Arrays.asList("B", "D", "E")));
+        assertFalse(set.removeAll(Arrays.asList("A", "C")));
+        assertEquals(set.size(), 3);
+        assertTrue(set.containsAll(Arrays.asList("B", "D", "E")));
+    }
+
+    @Test
+    public void testKeySetViewRetainAll() {
+        ConcurrentHashMap.KeySetView set = createKeySet();
+        assertTrue(set.retainAll(Arrays.asList("A", "C")));
+        assertEquals(set.size(), 2);
+        assertTrue(set.containsAll(Arrays.asList("A", "C")));
+        assertFalse(set.retainAll(Arrays.asList("A", "C")));
+        assertEquals(set.size(), 2);
+        assertTrue(set.containsAll(Arrays.asList("A", "C")));
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListMapTest.java b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListMapTest.java
index 54b354e..c175d0b 100644
--- a/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListMapTest.java
+++ b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListMapTest.java
@@ -16,62 +16,212 @@
 
 package libcore.java.util.concurrent;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.ConcurrentNavigableMap;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
 import libcore.java.util.MapDefaultMethodTester;
 
-public class ConcurrentSkipListMapTest extends junit.framework.TestCase {
+@RunWith(JUnit4.class)
+public class ConcurrentSkipListMapTest {
 
-    public void test_getOrDefault() {
+    @Test
+    public void testGetOrDefault() {
         MapDefaultMethodTester.test_getOrDefault(new ConcurrentSkipListMap<>(),
                 false /*doesNotAcceptNullKey*/, false /*doesNotAcceptNullValue*/,
                 false /*getAcceptsAnyObject*/);
     }
 
-    public void test_forEach() {
+    @Test
+    public void testForEach() {
         MapDefaultMethodTester.test_forEach(new ConcurrentSkipListMap<>());
     }
 
-    public void test_putIfAbsent() {
+    @Test
+    public void testPutIfAbsent() {
         MapDefaultMethodTester
                 .test_putIfAbsent(new ConcurrentSkipListMap<>(), false /*doesNotAcceptNullKey*/,
                         false /*doesNotAcceptNullValue*/);
     }
 
-    public void test_remove() {
+    @Test
+    public void testRemove() {
         MapDefaultMethodTester
                 .test_remove(new ConcurrentSkipListMap<>(), false /*doesNotAcceptNullKey*/,
                         false /*doesNotAcceptNullValue*/);
     }
 
-    public void test_replace$K$V$V() {
+    @Test
+    public void testReplace$K$V$V() {
         MapDefaultMethodTester
                 .test_replace$K$V$V(new ConcurrentSkipListMap<>(), false /*doesNotAcceptNullKey*/,
                         false /*doesNotAcceptNullValue*/);
     }
 
-    public void test_replace$K$V() {
+    @Test
+    public void testReplace$K$V() {
         MapDefaultMethodTester.test_replace$K$V(new ConcurrentSkipListMap<>(),
                 false /*doesNotAcceptNullKey*/, false /*doesNotAcceptNullValue*/);
     }
 
-    public void test_computeIfAbsent() {
+    @Test
+    public void testComputeIfAbsent() {
         MapDefaultMethodTester.test_computeIfAbsent(new ConcurrentSkipListMap<>(),
                 false /*doesNotAcceptNullKey*/, false /*doesNotAcceptNullValue*/);
     }
 
-    public void test_computeIfPresent() {
+    @Test
+    public void testComputeIfPresent() {
         MapDefaultMethodTester.test_computeIfPresent(new ConcurrentSkipListMap<>(),
                 false /*doesNotAcceptNullKey*/);
     }
 
-    public void test_compute() {
+    @Test
+    public void testCompute() {
         MapDefaultMethodTester.test_compute(new ConcurrentSkipListMap<>(),
                 false /*doesNotAcceptNullKey*/);
     }
 
-    public void test_merge() {
+    @Test
+    public void testMerge() {
         MapDefaultMethodTester.test_merge(new ConcurrentSkipListMap<>(),
                 false /*doesNotAcceptNullKey*/);
     }
+
+    private ConcurrentSkipListMap createPopulatedMap() {
+        ConcurrentSkipListMap map = new ConcurrentSkipListMap();
+        map.put("A", "a");
+        map.put("B", "b");
+        map.put("C", "c");
+        map.put("D", "d");
+        map.put("E", "e");
+        map.put("F", "f");
+        assertFalse(map.isEmpty());
+        return map;
+    }
+
+    @Test
+    public void testCloneFromSorted() {
+        ConcurrentSkipListMap map = createPopulatedMap();
+        ConcurrentSkipListMap mapClone = map.clone();
+        assertNotSame(map, mapClone);
+        Set set = map.entrySet();
+        Set setOfClone = mapClone.entrySet();
+        Iterator it = set.iterator();
+        Iterator itOfClone = setOfClone.iterator();
+        while ( it.hasNext() && itOfClone.hasNext() ) {
+            Map.Entry entry = (Map.Entry) it.next();
+            Map.Entry entryOfClone = (Map.Entry) itOfClone.next();
+            assertSame(entry.getKey(), entryOfClone.getKey());
+            assertSame(entry.getValue(), entryOfClone.getValue());
+        }
+        assertFalse(it.hasNext());
+        assertFalse(itOfClone.hasNext());
+    }
+
+    @Test
+    public void testFirstEntry() {
+        ConcurrentSkipListMap map = createPopulatedMap();
+        assertEquals("A", map.firstEntry().getKey());
+        assertEquals("a", map.firstEntry().getValue());
+    }
+
+    @Test
+    public void testLastEntry() {
+        ConcurrentSkipListMap map = createPopulatedMap();
+        assertEquals("F", map.lastEntry().getKey());
+        assertEquals("f", map.lastEntry().getValue());
+    }
+
+    @Test
+    public void testSubMap() {
+        ConcurrentSkipListMap map = createPopulatedMap();
+        ConcurrentNavigableMap subMap = map.subMap("B", "D");
+        assertEquals(2, subMap.size());
+        assertFalse(subMap.containsKey("A"));
+        assertTrue(subMap.containsKey("B"));
+        assertTrue(subMap.containsKey("C"));
+        assertFalse(subMap.containsKey("D"));
+        assertFalse(subMap.containsKey("E"));
+        assertFalse(subMap.containsKey("F"));
+    }
+
+    @Test
+    public void testSubMapEmpty() {
+        ConcurrentSkipListMap map = createPopulatedMap();
+        ConcurrentNavigableMap subMap = map.subMap("A", "A");
+        assertTrue(subMap.isEmpty());
+        assertFalse(subMap.containsKey("A"));
+        assertFalse(subMap.containsKey("B"));
+        assertFalse(subMap.containsKey("C"));
+        assertFalse(subMap.containsKey("D"));
+        assertFalse(subMap.containsKey("E"));
+        assertFalse(subMap.containsKey("F"));
+    }
+
+    @Test
+    public void testHeadMap() {
+        ConcurrentSkipListMap map = createPopulatedMap();
+        ConcurrentNavigableMap subMap = map.headMap("D");
+        assertEquals(3, subMap.size());
+        assertTrue(subMap.containsKey("A"));
+        assertTrue(subMap.containsKey("B"));
+        assertTrue(subMap.containsKey("C"));
+        assertFalse(subMap.containsKey("D"));
+        assertFalse(subMap.containsKey("E"));
+        assertFalse(subMap.containsKey("F"));
+    }
+
+    @Test
+    public void testHeadMapEmpty() {
+        ConcurrentSkipListMap map = createPopulatedMap();
+        ConcurrentNavigableMap subMap = map.headMap("A");
+        assertTrue(subMap.isEmpty());
+        assertFalse(subMap.containsKey("A"));
+        assertFalse(subMap.containsKey("B"));
+        assertFalse(subMap.containsKey("C"));
+        assertFalse(subMap.containsKey("D"));
+        assertFalse(subMap.containsKey("E"));
+        assertFalse(subMap.containsKey("F"));
+    }
+
+    @Test
+    public void testTailMap() {
+        ConcurrentSkipListMap map = createPopulatedMap();
+        ConcurrentNavigableMap subMap = map.tailMap("C");
+        assertEquals(4, subMap.size());
+        assertFalse(subMap.containsKey("A"));
+        assertFalse(subMap.containsKey("B"));
+        assertTrue(subMap.containsKey("C"));
+        assertTrue(subMap.containsKey("D"));
+        assertTrue(subMap.containsKey("E"));
+        assertTrue(subMap.containsKey("F"));
+    }
+
+    @Test
+    public void testTailMapSingleElement() {
+        ConcurrentSkipListMap map = createPopulatedMap();
+        ConcurrentNavigableMap subMap = map.tailMap("F");
+        assertEquals(1, subMap.size());
+        assertFalse(subMap.containsKey("A"));
+        assertFalse(subMap.containsKey("B"));
+        assertFalse(subMap.containsKey("C"));
+        assertFalse(subMap.containsKey("D"));
+        assertFalse(subMap.containsKey("E"));
+        assertTrue(subMap.containsKey("F"));
+    }
+
 }
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListSetTest.java b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListSetTest.java
new file mode 100644
index 0000000..bd858b0
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListSetTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Iterator;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ConcurrentSkipListSetTest {
+
+    private ConcurrentSkipListSet createPopulatedSet() {
+        ConcurrentSkipListSet set = new ConcurrentSkipListSet();
+        set.add("A");
+        set.add("B");
+        set.add("C");
+        set.add("D");
+        set.add("E");
+        set.add("F");
+        assertFalse(set.isEmpty());
+        return set;
+    }
+
+    @Test
+    public void testConstructorFromSortedSet() {
+        TreeSet treeSet = new TreeSet();
+        treeSet.add("A");
+        treeSet.add("B");
+        treeSet.add("C");
+        treeSet.add("D");
+        treeSet.add("E");
+        treeSet.add("F");
+        ConcurrentSkipListSet skipListSet = new ConcurrentSkipListSet(treeSet);
+        assertEquals(treeSet.size(), skipListSet.size());
+        while (!treeSet.isEmpty()) {
+            assertFalse(skipListSet.isEmpty());
+            assertEquals(treeSet.pollFirst(), skipListSet.pollFirst());
+        }
+    }
+
+    @Test
+    public void testClone() {
+        ConcurrentSkipListSet set = createPopulatedSet();
+        ConcurrentSkipListSet setClone = set.clone();
+        assertNotSame(set, setClone);
+        Iterator it = set.iterator();
+        Iterator itOfClone = setClone.iterator();
+        while (it.hasNext() && itOfClone.hasNext()) {
+            String entry = (String) it.next();
+            String entryOfClone = (String) itOfClone.next();
+            assertSame(entry, entryOfClone);
+        }
+        assertFalse(it.hasNext());
+        assertFalse(itOfClone.hasNext());
+    }
+
+    @Test
+    public void testDescendingIterator() {
+        ConcurrentSkipListSet set = createPopulatedSet();
+        int size = set.size();
+        int i;
+        Iterator it = set.descendingIterator();
+        String lastVal = null;
+        for (i = 0; it.hasNext(); i++) {
+            String val = (String) it.next();
+            assertTrue(set.contains(val));
+            if(lastVal != null) {
+                assertTrue(0 <= lastVal.compareTo(val));
+            }
+            lastVal = val;
+        }
+        assertEquals(i, size);
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/CopyOnWriteArrayListTest.java b/luni/src/test/java/libcore/java/util/concurrent/CopyOnWriteArrayListTest.java
index fc783c0..80005df 100644
--- a/luni/src/test/java/libcore/java/util/concurrent/CopyOnWriteArrayListTest.java
+++ b/luni/src/test/java/libcore/java/util/concurrent/CopyOnWriteArrayListTest.java
@@ -101,6 +101,15 @@
         assertEquals(Arrays.asList("a", "d"), list);
     }
 
+    public void testRetainAll() {
+        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
+        list.addAll(Arrays.asList("a", "b", "c", "d", "e"));
+        assertTrue(list.retainAll(Arrays.asList("b", "d")));
+        assertEquals(2, list.size());
+        assertFalse(list.retainAll(Arrays.asList("b", "d")));
+        assertEquals(2, list.size());
+    }
+
     public void testSubListClear() {
         CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
         list.addAll(Arrays.asList("a", "b", "c", "d", "e"));
diff --git a/luni/src/test/java/libcore/java/util/concurrent/CountedCompleterTest.java b/luni/src/test/java/libcore/java/util/concurrent/CountedCompleterTest.java
new file mode 100644
index 0000000..3f14d14
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/CountedCompleterTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.CountedCompleter;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class CountedCompleterTest {
+
+    /**
+     * Exercises the completion of all tasks once one of them has a result.
+     *
+     * Instead of needing all tasks to be performed to get a result, this will only expect one of
+     * them to provide it. That task, given by choiceIndex, will just complete the root completer.
+     * All other tasks will remain "unfinished".
+     *
+     * The result is passed through setRawResult().
+     */
+    private static int chooseOne(Integer[] array, int choiceIndex) {
+        class Task extends CountedCompleter<Integer> {
+            final int lo;
+            final int hi;
+            AtomicInteger ai = new AtomicInteger(0);
+
+            Task(Task parent, int lo, int hi) {
+                super(parent);
+                this.lo = lo;
+                this.hi = hi;
+            }
+
+            @Override
+            public void compute() {
+                if (hi - lo >= 2) {
+                    int mid = (lo + hi) >>> 1;
+                    // must set pending count before fork
+                    setPendingCount(2);
+                    new Task(this, mid, hi).fork(); // right child
+                    new Task(this, lo, mid).fork(); // left child
+                } else if (hi > lo) {
+                    if (choiceIndex == lo) {
+                        final CountedCompleter root = getRoot();
+                        final Integer val = Integer.valueOf(array[lo]);
+                        if (root != null) {
+                            root.complete(val);
+                        } else {
+                            complete(val); // the current task is the root
+                        }
+                    }
+                }
+            }
+
+            public Integer getRawResult() {
+                return new Integer(ai.intValue());
+            }
+
+            protected void setRawResult(Integer val) {
+                ai.addAndGet(val.intValue());
+            }
+        }
+        return new Task(null, 0, array.length).invoke().intValue();
+    }
+
+    /**
+     * complete marks a task as complete regardless of the pending count.
+     *
+     * The test will only require one task to complete.
+     */
+    @Test
+    public void testRecursiveChoice() {
+        int n = 7;
+        Integer[] a = new Integer[n];
+        for (int i = 0; i < n; i++) {
+            a[i] = i + 1;
+        }
+        for (int chosenOne = 0; chosenOne < n; ++chosenOne) {
+            final int result = chooseOne(a, chosenOne);
+            assertEquals(chosenOne + 1, result);
+        }
+    }
+
+    /**
+     * Forces a task to complete all its children by running them its own pool.
+     *
+     * After a parent task adds its children tasks to it's own pool queue, it uses helpComplete to
+     * ensure that those tasks are run before it returns. As all tasks are queued to the same pool
+     * and the parallelism is set to 1, this will make the pool execute the children tasks from
+     * within the execution of the parent.
+     */
+    private static void completeAllChildren(Integer[] array, Consumer<Integer> action) {
+
+        /**
+         * Leaf task that just runs the action and then completes.
+         */
+        class Task extends CountedCompleter<Integer> {
+            final int idx;
+
+            Task(CountedCompleter<Integer> parent, int idx) {
+                super(parent);
+                this.idx = idx;
+            }
+
+            @Override
+            public void compute() {
+                action.accept(array[idx]);
+                tryComplete();
+            }
+        }
+
+        /**
+         * The parent task that creates and queues its children, then executes them on its own pool
+         * before completing.
+         */
+        class MainTask extends CountedCompleter<Integer> {
+            final ForkJoinPool pool;
+            final int lo;
+            final int hi;
+
+            MainTask(ForkJoinPool pool, int lo, int hi) {
+                super(null);
+                this.pool = pool;
+                this.lo = lo;
+                this.hi = hi;
+            }
+
+            @Override
+            public void compute() {
+                final int count = hi - lo;
+                setPendingCount(count);
+
+                for (int idx = lo; idx < hi; ++idx) {
+                    // Do not fork the task, rather add it to the parent's pool so that it is
+                    // guaranteed not to be running before this compute() returns, unless
+                    // helpComplete() is called.
+                    pool.submit(new Task(this, idx));
+                }
+
+                // Make the pool run all the children tasks before moving one
+                helpComplete(count);
+
+                // If helpComplete() worked properly, by this point the pending count should be back
+                // to 0, so the tryComplete will terminate this task. Otherwise, the task will not
+                // get completed.
+                if (getPendingCount() == 0) {
+                    tryComplete();
+                }
+            }
+        }
+
+        // Use a pool with parallelism set to 1 so the children tasks cannot run before the main
+        // task, unless helpComplete is used.
+        ForkJoinPool pool = new ForkJoinPool(1);
+        MainTask task = new MainTask(pool, 0, array.length);
+        pool.submit(task);
+        task.join();
+    }
+
+    /**
+     * helpComplete attempts to process at most a given number of unprocessed children tasks.
+     */
+    @Test
+    public void testHelpComplete() {
+        int n = 7;
+        Integer[] a = new Integer[n];
+        for (int i = 0; i < n; i++) {
+            a[i] = i + 1;
+        }
+        AtomicInteger ai = new AtomicInteger(0);
+        // Use an atomic add as the action for each task. This will add all the elements of the
+        // array into the ai variable. Since the elements are between 1 and 7, the number does not
+        // overflow.
+        completeAllChildren(a, ai::addAndGet);
+        assertEquals(n * (n + 1) / 2, ai.get());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ExecutionExceptionTest.java b/luni/src/test/java/libcore/java/util/concurrent/ExecutionExceptionTest.java
new file mode 100644
index 0000000..d848403
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ExecutionExceptionTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.concurrent.ExecutionException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+public class ExecutionExceptionTest {
+
+    // Adding derived class to be able to test the protected constructors
+    private class TestExecutionException extends ExecutionException {
+        public TestExecutionException() {
+            super();
+        }
+        public TestExecutionException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * constructor creates exception without any details
+     */
+    @Test
+    public void testConstructNoMessage() {
+        ExecutionException exception = new TestExecutionException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+
+    /**
+     * constructor creates exception with detail message
+     */
+    @Test
+    public void testConstructWithMessage() {
+        ExecutionException exception = new TestExecutionException("test");
+        assertEquals("test", exception.getMessage());
+        assertNull(exception.getCause());
+    }
+
+    /**
+     * constructor creates exception with detail message and cause
+     */
+    @Test
+    public void testConstructWithMessageAndCause() {
+        Throwable cause = new Exception();
+        ExecutionException exception = new ExecutionException("test", cause);
+        assertEquals("test", exception.getMessage());
+        assertEquals(cause, exception.getCause());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ExecutorServiceAutoCloseable.java b/luni/src/test/java/libcore/java/util/concurrent/ExecutorServiceAutoCloseable.java
new file mode 100644
index 0000000..2df0b29
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ExecutorServiceAutoCloseable.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.fail;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+
+final class ExecutorServiceAutoCloseable implements AutoCloseable {
+    private final ExecutorService service;
+
+    public ExecutorServiceAutoCloseable(ExecutorService service) {
+        this.service = service;
+    }
+
+    @Override
+    public void close() {
+        try {
+            service.shutdown();
+
+            if(!service.awaitTermination(5000, TimeUnit.MILLISECONDS)) {
+                service.shutdownNow();
+                service.awaitTermination(1000, TimeUnit.MILLISECONDS);
+                fail();
+            }
+        } catch(InterruptedException e) {
+            fail("Unexpected InterruptedException: " + e.getMessage());
+        }
+    };
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ExecutorsTest.java b/luni/src/test/java/libcore/java/util/concurrent/ExecutorsTest.java
new file mode 100644
index 0000000..dc44a81
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ExecutorsTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ExecutorsTest {
+
+    class TestRunnable implements Runnable {
+        public void run() { }
+    }
+
+    @Test
+    public void testNewWorkStealingPoolDefault() {
+        final ExecutorService e = Executors.newWorkStealingPool();
+        try (ExecutorServiceAutoCloseable cleaner = new ExecutorServiceAutoCloseable(e)) {
+            e.execute(new TestRunnable());
+            e.execute(new TestRunnable());
+            e.execute(new TestRunnable());
+        }
+    }
+
+    @Test
+    public void testNewWorkStealingPoolWithParallelism() {
+        final ExecutorService e = Executors.newWorkStealingPool(2);
+        try (ExecutorServiceAutoCloseable cleaner = new ExecutorServiceAutoCloseable(e)) {
+            e.execute(new TestRunnable());
+            e.execute(new TestRunnable());
+            e.execute(new TestRunnable());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/FlowTest.java b/luni/src/test/java/libcore/java/util/concurrent/FlowTest.java
new file mode 100644
index 0000000..b6e564b
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/FlowTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.Flow;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class FlowTest {
+
+    @Test
+    /**
+     * defaultBufferSize returns default value for Publisher or Subscriber buffering.
+     */
+    public void testDefaultBufferSize() {
+        // Currently the implementation always returns 256, as documented in the API. If this
+        // changes, the test would need to be adjusted as well. This, at least, can serve as a
+        // reminder to update the documentation.
+        assertEquals(256, Flow.defaultBufferSize());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ForkJoinPoolTest.java b/luni/src/test/java/libcore/java/util/concurrent/ForkJoinPoolTest.java
new file mode 100644
index 0000000..578970e
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ForkJoinPoolTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.fail;
+
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ForkJoinPoolTest {
+
+    @Test
+    public void testSubmit() {
+        final ForkJoinPool pool = new ForkJoinPool();
+        try (ExecutorServiceAutoCloseable cleaner = new ExecutorServiceAutoCloseable(pool)) {
+            final AtomicInteger result = new AtomicInteger(0);
+            ForkJoinTask task = pool.submit(() -> result.addAndGet(42), result);
+            assertSame(result, task.get());
+            assertEquals(42, result.get());
+        } catch(Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testGetRunningThreadCount() {
+        final ForkJoinPool pool = new ForkJoinPool();
+        try (ExecutorServiceAutoCloseable cleaner = new ExecutorServiceAutoCloseable(pool)) {
+            assertEquals(0, pool.getRunningThreadCount());
+
+            final AtomicInteger value = new AtomicInteger(0);
+            final AtomicBoolean stop = new AtomicBoolean(false);
+            ForkJoinTask task = pool.submit(new Runnable() {
+                    public void run() {
+                        while(!stop.get()) {
+                            value.incrementAndGet();
+                        }
+                        stop.set(false);
+                    }
+                });
+            assertEquals(1, pool.getRunningThreadCount());
+            stop.set(true);
+            task.join();
+            pool.awaitTermination(2000, TimeUnit.MILLISECONDS);
+            assertEquals(0, pool.getRunningThreadCount());
+        } catch(Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ForkJoinTaskTest.java b/luni/src/test/java/libcore/java/util/concurrent/ForkJoinTaskTest.java
new file mode 100644
index 0000000..264aa6a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ForkJoinTaskTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ForkJoinTaskTest {
+
+    /**
+     * adapt uses a Runnable to perform a task, returning as the result the provided object
+     */
+    @Test
+    public void testAdaptToRunnableWithResult() {
+
+        final AtomicInteger result = new AtomicInteger(0);
+        final ForkJoinTask task = ForkJoinTask.adapt(() -> result.addAndGet(42), result);
+        final ForkJoinPool pool = new ForkJoinPool(1);
+        try (ExecutorServiceAutoCloseable cleaner = new ExecutorServiceAutoCloseable(pool)) {
+            pool.execute(task);
+            assertSame(result, task.join());
+            assertEquals(42, result.get());
+        } catch(Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    /**
+     * adapt uses a Callable to perform a task, returning as the result the value returned from the
+     * call() function
+     */
+    @Test
+    public void testAdaptToCallable() {
+
+        Callable callable = () -> { return Integer.valueOf(42); };
+        final ForkJoinTask task = ForkJoinTask.adapt(callable);
+        final ForkJoinPool pool = new ForkJoinPool(1);
+        try (ExecutorServiceAutoCloseable cleaner = new ExecutorServiceAutoCloseable(pool)) {
+            pool.execute(task);
+            Integer result = (Integer)task.join();
+            assertEquals(42, result.intValue());
+        } catch(Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    /**
+     * adapt uses a Callable to perform a task, converting any checked exception into
+     * RuntimeException
+     */
+    @Test
+    public void testAdaptToCallableThrowsException() {
+
+        Callable callable = () -> { throw new Exception("Test passed"); };
+        final ForkJoinTask task = ForkJoinTask.adapt(callable);
+        final ForkJoinPool pool = new ForkJoinPool(1);
+        try (ExecutorServiceAutoCloseable cleaner = new ExecutorServiceAutoCloseable(pool)) {
+            pool.execute(task);
+            Integer result = (Integer)task.join();
+            fail("Expected RuntimeException");
+        } catch(RuntimeException e) {
+            assertTrue(e.getMessage().contains("Test passed"));
+        } catch(Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/PhaserTest.java b/luni/src/test/java/libcore/java/util/concurrent/PhaserTest.java
new file mode 100644
index 0000000..c489a2f
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/PhaserTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertSame;
+
+import java.util.concurrent.Phaser;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class PhaserTest {
+
+    /**
+     * The root ancestor of a phaser should be returned from getRoot
+     */
+    @Test
+    public void testGetRoot() {
+        Phaser root = new Phaser();
+        Phaser parent = new Phaser(root);
+        Phaser child = new Phaser(parent);
+        assertSame(root, root.getRoot());
+        assertSame(root, parent.getRoot());
+        assertSame(root, child.getRoot());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/RecursiveTaskTest.java b/luni/src/test/java/libcore/java/util/concurrent/RecursiveTaskTest.java
new file mode 100644
index 0000000..38d5b45
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/RecursiveTaskTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.fail;
+
+import java.time.Duration;
+import java.util.concurrent.RecursiveTask;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class RecursiveTaskTest {
+
+    static final long MILLIS_TO_NANO = (1000 * 1000);
+
+    final class SumTask extends RecursiveTask<Integer> {
+        final int value;
+
+        SumTask(int value) {
+            this.value = value;
+        }
+
+        @Override
+        protected Integer compute() {
+            if (value <= 1)
+                return value;
+            SumTask subTask = new SumTask(value - 1);
+            subTask.fork();
+            return subTask.join() + value;
+        }
+
+        public void waitForCompletion(Integer forceResult) {
+            if(!TestUtils.waitWhileTrueOrTimeout(Duration.ofSeconds(2),
+                        () -> { return !isDone(); })) {
+                fail("timed out waiting for task completion");
+            }
+            if (forceResult != null) {
+                super.setRawResult(forceResult);
+            }
+        }
+    }
+
+    @Test
+    public void testSetRawResult() {
+        SumTask task = new SumTask(10);
+        final Integer expected = Integer.valueOf(-1);
+        task.fork();
+        task.waitForCompletion(expected);
+        Integer result = task.join();
+        assertSame(expected, result);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ReentrantReadWriteLockTest.java b/luni/src/test/java/libcore/java/util/concurrent/ReentrantReadWriteLockTest.java
new file mode 100644
index 0000000..4497157
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ReentrantReadWriteLockTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.time.Duration;
+import java.util.Collection;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ReentrantReadWriteLockTest {
+
+    class ReadLockRunnable implements Runnable {
+        final ReentrantReadWriteLock lock;
+
+        ReadLockRunnable(ReentrantReadWriteLock lock) {
+            this.lock = lock;
+        }
+
+        @Override
+        public void run() {
+            lock.readLock().lock();
+            lock.readLock().unlock();
+        }
+    }
+
+    class WriteLockRunnable implements Runnable {
+        final ReentrantReadWriteLock lock;
+
+        WriteLockRunnable(ReentrantReadWriteLock lock) {
+            this.lock = lock;
+        }
+
+        @Override
+        public void run() {
+            lock.writeLock().lock();
+            lock.writeLock().unlock();
+        }
+    }
+
+    static class DefaultReentrantReadWriteLock extends ReentrantReadWriteLock {
+
+        DefaultReentrantReadWriteLock() {
+            super();
+        }
+
+        @Override
+        public Collection<Thread> getQueuedReaderThreads() {
+            return super.getQueuedReaderThreads();
+        }
+
+        @Override
+        public Collection<Thread> getQueuedWriterThreads() {
+            return super.getQueuedWriterThreads();
+        }
+    }
+
+    private void waitForQueuedThread(DefaultReentrantReadWriteLock lock, Thread thread) {
+        if(!TestUtils.waitWhileTrueOrTimeout(Duration.ofSeconds(2),
+                    () -> { return !lock.hasQueuedThread(thread); })) {
+            fail("timed out waiting for queued thread");
+        }
+    }
+
+    @Test
+    public void testReadLockCondition() {
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+        try {
+            final Condition condition = lock.readLock().newCondition();
+            fail("Expected UnsupportedOperationException");
+        } catch (UnsupportedOperationException success) {
+        } catch (Throwable t) {
+            fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    @Test
+    public void testGetQueuedReaderThreads() {
+        final DefaultReentrantReadWriteLock lock = new DefaultReentrantReadWriteLock();
+        Thread thread1 = new Thread(new ReadLockRunnable(lock));
+        Thread thread2 = new Thread(new ReadLockRunnable(lock));
+        lock.writeLock().lock();
+        assertTrue(lock.getQueuedReaderThreads().isEmpty());
+        thread1.start();
+        waitForQueuedThread(lock, thread1);
+        assertTrue(lock.getQueuedReaderThreads().contains(thread1));
+        thread2.start();
+        waitForQueuedThread(lock, thread2);
+        assertTrue(lock.getQueuedReaderThreads().contains(thread2));
+        lock.writeLock().unlock();
+        TestUtils.joinThreadOrFail(2000, thread1);
+        TestUtils.joinThreadOrFail(2000, thread2);
+        assertTrue(lock.getQueuedReaderThreads().isEmpty());
+    }
+
+    @Test
+    public void testGetQueuedWriterThreads() {
+        final DefaultReentrantReadWriteLock lock = new DefaultReentrantReadWriteLock();
+        Thread thread1 = new Thread(new WriteLockRunnable(lock));
+        Thread thread2 = new Thread(new WriteLockRunnable(lock));
+        lock.writeLock().lock();
+        assertTrue(lock.getQueuedWriterThreads().isEmpty());
+        thread1.start();
+        waitForQueuedThread(lock, thread1);
+        assertTrue(lock.getQueuedWriterThreads().contains(thread1));
+        thread2.start();
+        waitForQueuedThread(lock, thread2);
+        assertTrue(lock.getQueuedWriterThreads().contains(thread2));
+        lock.writeLock().unlock();
+        TestUtils.joinThreadOrFail(2000, thread1);
+        TestUtils.joinThreadOrFail(2000, thread2);
+        assertTrue(lock.getQueuedWriterThreads().isEmpty());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/RejectedExecutionExceptionTest.java b/luni/src/test/java/libcore/java/util/concurrent/RejectedExecutionExceptionTest.java
new file mode 100644
index 0000000..14c1408
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/RejectedExecutionExceptionTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+public class RejectedExecutionExceptionTest {
+
+    // Adding derived class to be able to test the protected constructors
+    private class TestExecutionException extends RejectedExecutionException {
+        public TestExecutionException() {
+            super();
+        }
+        public TestExecutionException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * constructor creates exception without any details
+     */
+    @Test
+    public void testConstructDefault() {
+        RejectedExecutionException exception = new TestExecutionException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+
+    /**
+     * constructor creates exception with detail message and cause
+     */
+    @Test
+    public void testConstructWithMessageAndCause() {
+        Throwable cause = new Exception();
+        RejectedExecutionException exception = new RejectedExecutionException("test", cause);
+        assertEquals("test", exception.getMessage());
+        assertEquals(cause, exception.getCause());
+    }
+
+    /**
+     * constructor creates exception with cause
+     */
+    @Test
+    public void testConstructWithCause() {
+        Throwable cause = new Exception("root");
+        RejectedExecutionException exception = new RejectedExecutionException(cause);
+        assertEquals(cause.toString(), exception.getMessage());
+        assertEquals(cause, exception.getCause());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/TestUtils.java b/luni/src/test/java/libcore/java/util/concurrent/TestUtils.java
new file mode 100644
index 0000000..eaa4330
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/TestUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.fail;
+
+import java.time.Duration;
+import java.util.function.BooleanSupplier;
+
+class TestUtils {
+
+    public static final long MILLIS_TO_NANO = (1000 * 1000);
+
+    public static void joinThreadOrFail(long timeoutMillis, Thread thread) {
+        try {
+            thread.join(timeoutMillis);
+        } catch (InterruptedException fail) {
+            fail("InterruptedException when joining thread");
+        } finally {
+            if (thread.getState() != Thread.State.TERMINATED) {
+                thread.interrupt();
+                fail("timed out waiting to join thread");
+            }
+        }
+    }
+
+    public static boolean waitWhileTrueOrTimeout(Duration timeout, BooleanSupplier conditionFn) {
+        Duration startTime = Duration.ofNanos(System.nanoTime());
+        while (conditionFn.getAsBoolean()) {
+            Duration now = Duration.ofNanos(System.nanoTime());
+            if (now.minus(startTime).compareTo(timeout) >= 0) {
+                return false;
+            }
+            Thread.yield();
+        }
+        return true;
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/stream/CollectorsTest.java b/luni/src/test/java/libcore/java/util/stream/CollectorsTest.java
new file mode 100644
index 0000000..afe097c
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/stream/CollectorsTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2021 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.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import static java.util.stream.Collectors.counting;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+import java.util.stream.Collector;
+import java.util.stream.Stream;
+
+@RunWith(JUnit4.class)
+public class CollectorsTest {
+
+    @Test
+    public void counting_countsNulls() {
+        long count = Stream.of(null, null, null).collect(counting());
+
+        assertEquals(3, count);
+    }
+
+    @Test
+    public void counting_emptyStream() {
+        assertEquals(0L, (long) Stream.empty().collect(counting()));
+    }
+
+    @Test
+    public void counting_nonEmptyStream() {
+        long count = Stream.of(null, 1, 2, "").collect(counting());
+
+        assertEquals(4, count);
+    }
+
+    @Test
+    public void counting_largeStream() {
+        int size = 10_000_000;
+
+        long actual = Stream.generate(() -> 1)
+                .limit(size)
+                .collect(counting());
+
+        assertEquals(size, actual);
+    }
+
+    @Test
+    public void collectorOf() {
+        Collector<Integer, int[], int[]> sqSumCollector =
+                Collector.of(
+                        () -> new int[] {0},
+                        (sum, next) -> sum[0] = sum[0] + next * next,
+                        (a, b) -> new int[] {a[0] + b[0]},
+                        Collector.Characteristics.UNORDERED);
+
+        int[] anArray = new int[] {10};
+        assertSame("Finisher is identity fn", anArray, sqSumCollector.finisher().apply(anArray));
+
+        assertArrayEquals(new int[]{0}, sqSumCollector.supplier().get());
+        assertArrayEquals(new int[] {20}, sqSumCollector.combiner().apply(anArray, anArray));
+
+        sqSumCollector.accumulator().accept(anArray, 10);
+        assertArrayEquals(new int[] {110}, anArray);
+        assertTrue(sqSumCollector.characteristics().contains(Collector.Characteristics.UNORDERED));
+
+        assertArrayEquals(new int[] {30}, Stream.of(1, 2, 3, 4).collect(sqSumCollector));
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/stream/LongStreamTest.java b/luni/src/test/java/libcore/java/util/stream/LongStreamTest.java
new file mode 100644
index 0000000..3c36aa7
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/stream/LongStreamTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 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.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.stream.LongStream;
+
+@RunWith(JUnit4.class)
+public class LongStreamTest {
+
+    private static final int[] TEST_SIZES = {0, 1, 2, 10, 20, 100, 1000};
+
+    @Test
+    public void ofArraysWithDifferentSizes() {
+        for (int size : TEST_SIZES) {
+            long[] sourceArray = generate(size);
+            LongStream stream = LongStream.of(sourceArray);
+
+            long[] destArray = stream.toArray();
+
+            assertFalse("By default stream should be sequential", stream.isParallel());
+            assertNotSame("New array should be generated", sourceArray, destArray);
+            assertArrayEquals(sourceArray, destArray);
+        }
+    }
+
+    @Test
+    public void ofNullArray_shouldThrowNPE() {
+        try {
+            LongStream.of((long[]) null);
+            fail();
+        } catch (NullPointerException ignored) {
+            // expected
+        }
+    }
+
+    private long[] generate(int size) {
+        long[] array = new long[size];
+
+        for (int index = 0; index < size; ++index) {
+            array[index] = index + 1;
+        }
+
+        return array;
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
index 2175289..ae07e02 100644
--- a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
@@ -26,6 +26,7 @@
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.charset.Charset;
 import java.util.Enumeration;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
@@ -85,4 +86,40 @@
             fail();
         } catch(FileNotFoundException expected) {}
     }
+
+    /**
+     * cp1251.zip archive has single empty file with cp1251 encoding name.
+     * Its name is 'имя файла'('file name' in Russian), but in cp1251.
+     * It was created using "convmv -f utf-8 -t cp1251 &lt;file&gt; --notest".
+     */
+    public void test_zipFileWith_cp1251_fileNames() throws Exception {
+        String resourceName = "/libcore/java/util/zip/cp1251.zip";
+
+        File tempFile = createTemporaryZipFile();
+        try (
+            InputStream is = ZipFileTest.class.getResourceAsStream(resourceName);
+            FileOutputStream fos = new FileOutputStream(tempFile)) {
+
+            int read;
+            byte[] arr = new byte[1024];
+
+            while ((read = is.read(arr)) > 0) {
+                fos.write(arr, 0, read);
+            }
+            fos.flush();
+
+            Charset cp1251 = Charset.forName("cp1251");
+            try (ZipFile zipFile = new ZipFile(tempFile, cp1251)) {
+                ZipEntry zipEntry = zipFile.entries().nextElement();
+
+                assertEquals("имя файла", zipEntry.getName());
+            }
+
+            try (ZipFile zipFile = new ZipFile(tempFile.getAbsolutePath(), cp1251)) {
+                ZipEntry zipEntry = zipFile.entries().nextElement();
+
+                assertEquals("имя файла", zipEntry.getName());
+            }
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLPermissionTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLPermissionTest.java
new file mode 100644
index 0000000..d0217b4
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLPermissionTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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.net.ssl;
+
+import junit.framework.TestCase;
+
+import javax.net.ssl.SSLPermission;
+
+public final class SSLPermissionTest extends TestCase {
+
+    public void testSslPermissions_constructor_LString() {
+        SSLPermission permission = new SSLPermission("name");
+
+        assertEquals("", permission.getName());
+        assertEquals("", permission.getActions());
+    }
+
+    public void testSslPermission_constructor_LString_LString() {
+        SSLPermission permission = new SSLPermission("name", "actions");
+
+        assertEquals("", permission.getName());
+        assertEquals("", permission.getActions());
+    }
+}
diff --git a/luni/src/test/java/libcore/libcore/content/type/MimeMapTest.java b/luni/src/test/java/libcore/libcore/content/type/MimeMapTest.java
index 764bad2..405aa84 100644
--- a/luni/src/test/java/libcore/libcore/content/type/MimeMapTest.java
+++ b/luni/src/test/java/libcore/libcore/content/type/MimeMapTest.java
@@ -70,7 +70,7 @@
 
     @Test public void caseNormalization_key() {
         mimeMap = MimeMap.builder()
-                .put("application/msWord", Arrays.asList("Doc"))
+                .addMimeMapping("application/msWord", Arrays.asList("Doc"))
                 .build();
         assertEquals("application/msword", mimeMap.guessMimeTypeFromExtension("dOc"));
         assertEquals("doc", mimeMap.guessExtensionFromMimeType("appliCATion/mSWOrd"));
@@ -93,7 +93,7 @@
 
         // Known keys for a custom map
         mimeMap = MimeMap.builder()
-                .put("application/msWord", Arrays.asList("Doc"))
+                .addMimeMapping("application/msWord", Arrays.asList("Doc"))
                 .build();
         assertEquals("doc", mimeMap.guessExtensionFromMimeType("Application/mSWord"));
         assertEquals("application/msword", mimeMap.guessMimeTypeFromExtension("DoC"));
@@ -105,7 +105,7 @@
 
     @Test public void unmapped() {
         mimeMap = MimeMap.builder()
-                .put("mime/test", Arrays.asList("test", "tst"))
+                .addMimeMapping("mime/test", Arrays.asList("test", "tst"))
                 .build();
         assertNull(mimeMap.guessExtensionFromMimeType("mime/unknown"));
         assertFalse(mimeMap.hasMimeType("mime/unknown"));
@@ -122,7 +122,7 @@
         MimeMap originalDefault = MimeMap.getDefault();
         try {
             // Constructs a new instance every time it is called
-            MimeMap.setDefaultSupplier(() -> MimeMap.builder().put("mime/sup", "sup").build());
+            MimeMap.setDefaultSupplier(() -> MimeMap.builder().addMimeMapping("mime/sup", "sup").build());
             // Same instance is returned both times
             assertSame(MimeMap.getDefault(), MimeMap.getDefault());
             // Check that the supplier is in effect
@@ -165,7 +165,7 @@
                 mimeMap);
 
         mimeMap = mimeMap.buildUpon()
-                .put("text/plain", "txt")
+                .addMimeMapping("text/plain", "txt")
                 .build();
         assertMap(
                 makeMap("text/plain", "txt"),
@@ -173,7 +173,7 @@
                 mimeMap);
 
         mimeMap = mimeMap.buildUpon()
-                .put("audio/mpeg", Arrays.asList("mp2", "mp3"))
+                .addMimeMapping("audio/mpeg", Arrays.asList("mp2", "mp3"))
                 .build();
         assertMap(
                 makeMap("audio/mpeg", "mp2",
@@ -184,7 +184,7 @@
                 mimeMap);
 
         mimeMap = mimeMap.buildUpon()
-                .put("text/plain", "text")
+                .addMimeMapping("text/plain", "text")
                 .build();
         assertMap(
                 makeMap("audio/mpeg", "mp2",
@@ -198,12 +198,12 @@
 
     @Test public void put() {
         MimeMap a = MimeMap.builder()
-                .put("text/plain", Arrays.asList("txt", "text"))
-                .put("application/msword", "doc")
+                .addMimeMapping("text/plain", Arrays.asList("txt", "text"))
+                .addMimeMapping("application/msword", "doc")
                 .build();
         MimeMap b = MimeMap.builder()
-                .put("text/plain", Arrays.asList("txt", "text"))
-                .put("application/msword", "doc")
+                .addMimeMapping("text/plain", Arrays.asList("txt", "text"))
+                .addMimeMapping("application/msword", "doc")
                 .build();
         assertEqualsButNotSame(a, b);
         assertEqualsButNotSame(a, a.buildUpon().build());
@@ -219,7 +219,7 @@
 
     @Test public void put_noExtensions() {
         checkPut_noExtensions(emptyMap);
-        checkPut_noExtensions(MimeMap.builder().put("text/plain", "txt").build());
+        checkPut_noExtensions(MimeMap.builder().addMimeMapping("text/plain", "txt").build());
         checkPut_noExtensions(mimeMap);
     }
 
@@ -228,7 +228,7 @@
      */
     private static void checkPut_noExtensions(MimeMap baseMap) {
         MimeMap mimeMap = baseMap.buildUpon()
-                .put("mime/type", Collections.emptyList())
+                .addMimeMapping("mime/type", Collections.emptyList())
                 .build();
         assertEquals(baseMap, mimeMap);
     }
@@ -249,11 +249,11 @@
     }
 
     @Test public void put_String_String_nullOrEmpty() {
-        assertThrowsNpe(() -> MimeMap.builder().put(null, "ext"));
-        assertThrowsIae(() -> MimeMap.builder().put("", "ext"));
+        assertThrowsNpe(() -> MimeMap.builder().addMimeMapping(null, "ext"));
+        assertThrowsIae(() -> MimeMap.builder().addMimeMapping("", "ext"));
 
-        assertThrowsNpe(() -> MimeMap.builder().put("mime/type", (String) null));
-        assertThrowsIae(() -> MimeMap.builder().put("mime/type", ""));
+        assertThrowsNpe(() -> MimeMap.builder().addMimeMapping("mime/type", (String) null));
+        assertThrowsIae(() -> MimeMap.builder().addMimeMapping("mime/type", ""));
     }
 
     /**
@@ -262,8 +262,8 @@
     @Test public void putIfAbsent() {
         // Starting from an empty mapping, add a bunch more, some with and some without '?'.
         mimeMap = MimeMap.builder()
-                .put("?text/plain", "?txt")
-                .put("audio/mpeg", Arrays.asList("mpga", "mpega", "?mp2", "mp3"))
+                .addMimeMapping("?text/plain", "?txt")
+                .addMimeMapping("audio/mpeg", Arrays.asList("mpga", "mpega", "?mp2", "mp3"))
                 .build();
         assertEquals("txt", mimeMap.guessExtensionFromMimeType("text/plain"));
         assertEquals("text/plain", mimeMap.guessMimeTypeFromExtension("txt"));
@@ -273,14 +273,14 @@
 
         // Override a ext -> MIME mapping without overriding the MIME -> ext mapping.
         mimeMap = mimeMap.buildUpon()
-                .put("?audio/mpeg", "m4a")
+                .addMimeMapping("?audio/mpeg", "m4a")
                 .build();
         assertEquals("mpga", mimeMap.guessExtensionFromMimeType("audio/mpeg"));
         assertEquals("audio/mpeg", mimeMap.guessMimeTypeFromExtension("m4a"));
 
         // Override a MIME -> ext mapping without overriding the ext -> MIME mapping.
         mimeMap = mimeMap.buildUpon()
-                .put("audio/mpeg", "?txt")
+                .addMimeMapping("audio/mpeg", "?txt")
                 .build();
         assertEquals("txt", mimeMap.guessExtensionFromMimeType("audio/mpeg"));
         assertEquals("text/plain", mimeMap.guessMimeTypeFromExtension("txt"));
@@ -307,10 +307,10 @@
     @Test public void extensions() {
         assertEquals(Collections.emptySet(), emptyMap.extensions());
         mimeMap = MimeMap.builder()
-                .put("text/plain", Arrays.asList("txt", "text"))
-                .put("audi/mpeg", "m4a")
-                .put("application/msword", "doc")
-                .put("text/plain", "tx")
+                .addMimeMapping("text/plain", Arrays.asList("txt", "text"))
+                .addMimeMapping("audi/mpeg", "m4a")
+                .addMimeMapping("application/msword", "doc")
+                .addMimeMapping("text/plain", "tx")
                 .build();
         Set<String> extensions = new HashSet<>(Arrays.asList(
                 "txt", "text", "m4a", "doc", "tx"));
@@ -326,10 +326,10 @@
     @Test public void mimeTypes() {
         assertEquals(Collections.emptySet(), emptyMap.mimeTypes());
         mimeMap = MimeMap.builder()
-                .put("text/plain", Arrays.asList("txt", "text"))
-                .put("audio/mpeg", "m4a")
-                .put("application/msword", "doc")
-                .put("text/plain", "tx")
+                .addMimeMapping("text/plain", Arrays.asList("txt", "text"))
+                .addMimeMapping("audio/mpeg", "m4a")
+                .addMimeMapping("application/msword", "doc")
+                .addMimeMapping("text/plain", "tx")
                 .build();
         Set<String> mimeTypes = new HashSet<>(Arrays.asList(
                 "text/plain",
@@ -362,17 +362,17 @@
         assertPutThrowsIae("invalidmime", "ext");
 
         // During lookups, wrong arguments return null rather than throwing.
-        mimeMap = MimeMap.builder().put("mime/type", "ext").build();
+        mimeMap = MimeMap.builder().addMimeMapping("mime/type", "ext").build();
         assertNull(mimeMap.guessExtensionFromMimeType("ext")); // ext is no mime type
         assertNull(mimeMap.guessMimeTypeFromExtension("mime/type")); // mime/type is no extension
     }
 
     private static void assertPutThrowsNpe(String mime, String... exts) {
-        assertThrowsNpe(() -> MimeMap.builder().put(mime, Arrays.asList(exts)));
+        assertThrowsNpe(() -> MimeMap.builder().addMimeMapping(mime, Arrays.asList(exts)));
     }
 
     private static void assertPutThrowsIae(final String mime, final String... exts) {
-        assertThrowsIae(() -> MimeMap.builder().put(mime, Arrays.asList(exts)));
+        assertThrowsIae(() -> MimeMap.builder().addMimeMapping(mime, Arrays.asList(exts)));
     }
 
     private static void assertThrowsNpe(Runnable runnable) {
@@ -393,8 +393,8 @@
 
     @Test public void hashCodeValue() {
         assertEquals(0, emptyMap.hashCode());
-        MimeMap a = MimeMap.builder().put("mime/test", "test").build();
-        MimeMap b = a.buildUpon().put("foo/bar", "baz").build();
+        MimeMap a = MimeMap.builder().addMimeMapping("mime/test", "test").build();
+        MimeMap b = a.buildUpon().addMimeMapping("foo/bar", "baz").build();
         assertTrue(0 != a.hashCode());
         assertTrue((a.hashCode() != b.hashCode()));
     }
@@ -434,13 +434,13 @@
             String ext = entry.getKey();
             String mime = entry.getValue();
             assertEquals(ext + ": " + mimeMap, mime, mimeMap.guessMimeTypeFromExtension(ext));
-            expectedBuilder.put("?" + mime, ext);
+            expectedBuilder.addMimeMapping("?" + mime, ext);
         }
         for (Map.Entry<String, String> entry : expectedMimeToExt.entrySet()) {
             String mime = entry.getKey();
             String ext = entry.getValue();
             assertEquals(mime + ": "  + mimeMap, ext, mimeMap.guessExtensionFromMimeType(mime));
-            expectedBuilder.put(mime, "?" + ext);
+            expectedBuilder.addMimeMapping(mime, "?" + ext);
         }
         // Check that there are no unexpected additional mappings.
         assertEqualsButNotSame(expectedBuilder.build(), mimeMap);
diff --git a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
index adbf399..02da02b 100644
--- a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
+++ b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
@@ -233,8 +233,8 @@
                 "android_fdsan_get_tag_value(long)",
                 "bind(java.io.FileDescriptor,java.net.InetAddress,int)",
                 "bind(java.io.FileDescriptor,java.net.SocketAddress)",
-                "capget(android.system.StructCapUserHeader)",
-                "capset(android.system.StructCapUserHeader,android.system.StructCapUserData[])",
+                "capget(android.system.StructUserCapHeader)",
+                "capset(android.system.StructUserCapHeader,android.system.StructUserCapData[])",
                 "dup(java.io.FileDescriptor)",
                 "dup2(java.io.FileDescriptor,int)",
                 "environ()",
diff --git a/luni/src/test/java/libcore/libcore/util/NativeAllocationRegistryTest.java b/luni/src/test/java/libcore/libcore/util/NativeAllocationRegistryTest.java
index e5ef07c..9190452 100644
--- a/luni/src/test/java/libcore/libcore/util/NativeAllocationRegistryTest.java
+++ b/luni/src/test/java/libcore/libcore/util/NativeAllocationRegistryTest.java
@@ -61,11 +61,11 @@
         assertEquals("Native bytes already allocated", 0, nativeBytes);
         long max = Runtime.getRuntime().maxMemory();
         long total = Runtime.getRuntime().totalMemory();
-        int size = 1024*1024;
-        final int nativeSize = size/2;
-        int javaSize = size/2;
-        int expectedMaxNumAllocations = (int)(max-total)/javaSize;
-        int numSavedAllocations = expectedMaxNumAllocations/2;
+        int size = 1024 * 1024;
+        final int nativeSize = size / 2;
+        int javaSize = size / 2;
+        int expectedMaxNumAllocations = (int)(max-total) / javaSize;
+        int numSavedAllocations = expectedMaxNumAllocations / 2;
         Allocation[] saved = new Allocation[numSavedAllocations];
 
         NativeAllocationRegistry registry = null;
@@ -90,21 +90,31 @@
             alloc.nativeAllocation = doNativeAllocation(nativeSize);
             registry.registerNativeAllocation(alloc, alloc.nativeAllocation);
 
-            saved[i%numSavedAllocations] = alloc;
+            saved[i % numSavedAllocations] = alloc;
         }
 
-        // Verify most of the allocations have been freed.
-        // Since we use fairly large Java objects, this doesn't test the GC triggering
-        // effect; we do that elsewhere.
-        // Since native and java objects have the same size, and we can only have max
-        // Java bytes in use, there should be no more than max native bytes in use,
-        // once all enqueued deallocations have been processed. First make sure
-        // that the ReferenceQueueDaemon has processed all pending requests, and then
-        // check.
+        // Verify most of the allocations have been freed.  Since we use fairly large Java
+        // objects, this doesn't test the GC triggering effect; we do that elsewhere.
+        //
+        // Since native and java objects have the same size, and we can only have max Java bytes
+        // in use, there should ideally be no more than max native bytes in use, once all enqueued
+        // deallocations have been processed. We call runFinalization() to make sure that the
+        // ReferenceQueueDaemon has processed all pending requests, and then check.
+        // (runFinalization() isn't documented to guarantee this, but it waits for a sentinel
+        // object to make it all the way through the pending reference queue, and hence has that
+        // effect.)
+        //
+        // However the garbage collector enqueues references asynchronously, by enqueuing
+        // another heap task. If the GC runs before we finish our allocation, but reference
+        // enqueueing is delayed, and runFinalization() runs between the time the GC reclaims
+        // memory and the references are enqueued, then runFinalization() may complete
+        // immediately, and further allocation may have occurred between the GC and the invocation
+        // of runFinalization(). Thus, under unlikely conditions, we may see up to twice as much
+        // native memory as the Java heap, and that's the actual condition we test.
         System.runFinalization();
         nativeBytes = getNumNativeBytesAllocated();
         assertTrue("Excessive native bytes still allocated (" + nativeBytes + ")"
-                + " given max memory of (" + max + ")", nativeBytes <= max);
+                + " given max memory of (" + max + ")", nativeBytes <= 2 * max);
         // Check that the array is fully populated, and sufficiently many native bytes
         // are live.
         long nativeReachableBytes = numSavedAllocations * nativeSize;
diff --git a/luni/src/test/resources/libcore/java/util/zip/cp1251.zip b/luni/src/test/resources/libcore/java/util/zip/cp1251.zip
new file mode 100644
index 0000000..30426f9
--- /dev/null
+++ b/luni/src/test/resources/libcore/java/util/zip/cp1251.zip
Binary files differ
diff --git a/mmodules/core_platform_api/api/legacy_platform/current.txt b/mmodules/core_platform_api/api/legacy_platform/current.txt
index 368bfa6..a915845 100644
--- a/mmodules/core_platform_api/api/legacy_platform/current.txt
+++ b/mmodules/core_platform_api/api/legacy_platform/current.txt
@@ -2,25 +2,25 @@
 package android.compat {
 
   public final class Compatibility {
+    method public static void clearBehaviorChangeDelegate();
     method public static void clearOverrides();
     method public static boolean isChangeEnabled(long);
-    method public static void reportChange(long);
-    method public static void setCallbacks(android.compat.Compatibility.Callbacks);
+    method public static void reportUnconditionalChange(long);
+    method public static void setBehaviorChangeDelegate(android.compat.Compatibility.BehaviorChangeDelegate);
     method public static void setOverrides(android.compat.Compatibility.ChangeConfig);
   }
 
-  public static class Compatibility.Callbacks {
-    ctor protected Compatibility.Callbacks();
-    method protected boolean isChangeEnabled(long);
-    method protected void reportChange(long);
+  public static interface Compatibility.BehaviorChangeDelegate {
+    method public default boolean isChangeEnabled(long);
+    method public default void onChangeReported(long);
   }
 
   public static final class Compatibility.ChangeConfig {
-    ctor public Compatibility.ChangeConfig(java.util.Set<java.lang.Long>, java.util.Set<java.lang.Long>);
-    method public long[] forceDisabledChangesArray();
-    method public java.util.Set<java.lang.Long> forceDisabledSet();
-    method public long[] forceEnabledChangesArray();
-    method public java.util.Set<java.lang.Long> forceEnabledSet();
+    ctor public Compatibility.ChangeConfig(@NonNull java.util.Set<java.lang.Long>, @NonNull java.util.Set<java.lang.Long>);
+    method @NonNull public long[] getDisabledChangesArray();
+    method @NonNull public java.util.Set<java.lang.Long> getDisabledSet();
+    method @NonNull public long[] getEnabledChangesArray();
+    method @NonNull public java.util.Set<java.lang.Long> getEnabledSet();
     method public boolean isEmpty();
     method public boolean isForceDisabled(long);
     method public boolean isForceEnabled(long);
@@ -37,8 +37,8 @@
   }
 
   public final class Os {
-    method @Nullable public static android.system.StructCapUserData[] capget(@NonNull android.system.StructCapUserHeader) throws android.system.ErrnoException;
-    method public static void capset(@NonNull android.system.StructCapUserHeader, @NonNull android.system.StructCapUserData[]) throws android.system.ErrnoException;
+    method @Nullable public static android.system.StructUserCapData[] capget(@NonNull android.system.StructUserCapHeader) throws android.system.ErrnoException;
+    method public static void capset(@NonNull android.system.StructUserCapHeader, @NonNull android.system.StructUserCapData[]) throws android.system.ErrnoException;
     method public static int getpgid(int) throws android.system.ErrnoException;
     method @Nullable public static android.system.StructRlimit getrlimit(int) throws android.system.ErrnoException;
     method public static int getsockoptInt(@NonNull java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
@@ -80,25 +80,19 @@
     ctor public PacketSocketAddress(int, int, byte[]);
   }
 
-  public final class StructCapUserData {
-    ctor public StructCapUserData(int, int, int);
+  public final class StructRlimit {
+    field public final long rlim_cur;
+  }
+
+  public final class StructUserCapData {
+    ctor public StructUserCapData(int, int, int);
     field public final int effective;
     field public final int inheritable;
     field public final int permitted;
   }
 
-  public final class StructCapUserHeader {
-    ctor public StructCapUserHeader(int, int);
-  }
-
-  public final class StructLinger {
-    ctor public StructLinger(int, int);
-    method public boolean isOn();
-    field public final int l_linger;
-  }
-
-  public final class StructRlimit {
-    field public final long rlim_cur;
+  public final class StructUserCapHeader {
+    ctor public StructUserCapHeader(int, int);
   }
 
   public final class UnixSocketAddress extends java.net.SocketAddress {
@@ -188,15 +182,15 @@
   }
 
   public class BaseDexClassLoader extends java.lang.ClassLoader {
-    method public void addDexPath(String);
-    method public void addNativePath(java.util.Collection<java.lang.String>);
-    method public String getLdLibraryPath();
+    method public void addDexPath(@Nullable String);
+    method public void addNativePath(@NonNull java.util.Collection<java.lang.String>);
+    method @NonNull public String getLdLibraryPath();
     method public void reportClassLoaderChain();
-    method public static void setReporter(dalvik.system.BaseDexClassLoader.Reporter);
+    method public static void setReporter(@Nullable dalvik.system.BaseDexClassLoader.Reporter);
   }
 
   public static interface BaseDexClassLoader.Reporter {
-    method public void report(java.util.Map<java.lang.String,java.lang.String>);
+    method public void report(@NonNull java.util.Map<java.lang.String,java.lang.String>);
   }
 
   public final class BlockGuard {
@@ -216,7 +210,7 @@
   }
 
   public static interface BlockGuard.VmPolicy {
-    method public void onPathAccess(String);
+    method public void onPathAccess(@NonNull String);
   }
 
   public final class CloseGuard {
@@ -548,8 +542,8 @@
 package libcore.content.type {
 
   public final class MimeMap {
-    method public libcore.content.type.MimeMap.Builder buildUpon();
-    method public static libcore.content.type.MimeMap.Builder builder();
+    method @NonNull public libcore.content.type.MimeMap.Builder buildUpon();
+    method @NonNull public static libcore.content.type.MimeMap.Builder builder();
     method @NonNull public java.util.Set<java.lang.String> extensions();
     method @NonNull public static libcore.content.type.MimeMap getDefault();
     method @Nullable public String guessExtensionFromMimeType(@Nullable String);
@@ -561,17 +555,8 @@
   }
 
   public static final class MimeMap.Builder {
-    method public libcore.content.type.MimeMap build();
-    method public libcore.content.type.MimeMap.Builder put(@NonNull String, @NonNull java.util.List<java.lang.String>);
-  }
-
-}
-
-package libcore.internal {
-
-  public final class StringPool {
-    ctor public StringPool();
-    method public String get(char[], int, int);
+    method @NonNull public libcore.content.type.MimeMap.Builder addMimeMapping(@NonNull String, @NonNull java.util.List<java.lang.String>);
+    method @NonNull public libcore.content.type.MimeMap build();
   }
 
 }
@@ -671,10 +656,10 @@
   }
 
   public class HttpURLConnectionFactory {
-    method public static libcore.net.http.HttpURLConnectionFactory createInstance();
-    method public java.net.URLConnection openConnection(java.net.URL, javax.net.SocketFactory, java.net.Proxy) throws java.io.IOException;
-    method public void setDns(libcore.net.http.Dns);
-    method public void setNewConnectionPool(int, long, java.util.concurrent.TimeUnit);
+    method @NonNull public static libcore.net.http.HttpURLConnectionFactory createInstance();
+    method public java.net.URLConnection openConnection(@NonNull java.net.URL, @NonNull javax.net.SocketFactory, @NonNull java.net.Proxy) throws java.io.IOException;
+    method public void setDns(@NonNull libcore.net.http.Dns);
+    method public void setNewConnectionPool(int, long, @NonNull java.util.concurrent.TimeUnit);
   }
 
 }
@@ -691,7 +676,7 @@
     field public static final String[] STRING;
   }
 
-  public class FP16 {
+  public final class FP16 {
     method public static short ceil(short);
     method public static int compare(short, short);
     method public static boolean equals(short, short);
@@ -804,7 +789,7 @@
 package org.json {
 
   public class JSONObject {
-    method public java.util.Set<java.lang.String> keySet();
+    method @NonNull public java.util.Set<java.lang.String> keySet();
   }
 
 }
diff --git a/mmodules/core_platform_api/api/stable_platform/current.txt b/mmodules/core_platform_api/api/stable_platform/current.txt
index dffea52..729e4e7 100644
--- a/mmodules/core_platform_api/api/stable_platform/current.txt
+++ b/mmodules/core_platform_api/api/stable_platform/current.txt
@@ -2,25 +2,25 @@
 package android.compat {
 
   public final class Compatibility {
+    method public static void clearBehaviorChangeDelegate();
     method public static void clearOverrides();
     method public static boolean isChangeEnabled(long);
-    method public static void reportChange(long);
-    method public static void setCallbacks(android.compat.Compatibility.Callbacks);
+    method public static void reportUnconditionalChange(long);
+    method public static void setBehaviorChangeDelegate(android.compat.Compatibility.BehaviorChangeDelegate);
     method public static void setOverrides(android.compat.Compatibility.ChangeConfig);
   }
 
-  public static class Compatibility.Callbacks {
-    ctor protected Compatibility.Callbacks();
-    method protected boolean isChangeEnabled(long);
-    method protected void reportChange(long);
+  public static interface Compatibility.BehaviorChangeDelegate {
+    method public default boolean isChangeEnabled(long);
+    method public default void onChangeReported(long);
   }
 
   public static final class Compatibility.ChangeConfig {
-    ctor public Compatibility.ChangeConfig(java.util.Set<java.lang.Long>, java.util.Set<java.lang.Long>);
-    method public long[] forceDisabledChangesArray();
-    method public java.util.Set<java.lang.Long> forceDisabledSet();
-    method public long[] forceEnabledChangesArray();
-    method public java.util.Set<java.lang.Long> forceEnabledSet();
+    ctor public Compatibility.ChangeConfig(@NonNull java.util.Set<java.lang.Long>, @NonNull java.util.Set<java.lang.Long>);
+    method @NonNull public long[] getDisabledChangesArray();
+    method @NonNull public java.util.Set<java.lang.Long> getDisabledSet();
+    method @NonNull public long[] getEnabledChangesArray();
+    method @NonNull public java.util.Set<java.lang.Long> getEnabledSet();
     method public boolean isEmpty();
     method public boolean isForceDisabled(long);
     method public boolean isForceEnabled(long);
@@ -37,8 +37,8 @@
   }
 
   public final class Os {
-    method @Nullable public static android.system.StructCapUserData[] capget(@NonNull android.system.StructCapUserHeader) throws android.system.ErrnoException;
-    method public static void capset(@NonNull android.system.StructCapUserHeader, @NonNull android.system.StructCapUserData[]) throws android.system.ErrnoException;
+    method @Nullable public static android.system.StructUserCapData[] capget(@NonNull android.system.StructUserCapHeader) throws android.system.ErrnoException;
+    method public static void capset(@NonNull android.system.StructUserCapHeader, @NonNull android.system.StructUserCapData[]) throws android.system.ErrnoException;
     method public static int getpgid(int) throws android.system.ErrnoException;
     method @Nullable public static android.system.StructRlimit getrlimit(int) throws android.system.ErrnoException;
     method public static int getsockoptInt(@NonNull java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
@@ -80,25 +80,19 @@
     ctor public PacketSocketAddress(int, int, byte[]);
   }
 
-  public final class StructCapUserData {
-    ctor public StructCapUserData(int, int, int);
+  public final class StructRlimit {
+    field public final long rlim_cur;
+  }
+
+  public final class StructUserCapData {
+    ctor public StructUserCapData(int, int, int);
     field public final int effective;
     field public final int inheritable;
     field public final int permitted;
   }
 
-  public final class StructCapUserHeader {
-    ctor public StructCapUserHeader(int, int);
-  }
-
-  public final class StructLinger {
-    ctor public StructLinger(int, int);
-    method public boolean isOn();
-    field public final int l_linger;
-  }
-
-  public final class StructRlimit {
-    field public final long rlim_cur;
+  public final class StructUserCapHeader {
+    ctor public StructUserCapHeader(int, int);
   }
 
   public final class UnixSocketAddress extends java.net.SocketAddress {
@@ -126,15 +120,15 @@
   }
 
   public class BaseDexClassLoader extends java.lang.ClassLoader {
-    method public void addDexPath(String);
-    method public void addNativePath(java.util.Collection<java.lang.String>);
-    method public String getLdLibraryPath();
+    method public void addDexPath(@Nullable String);
+    method public void addNativePath(@NonNull java.util.Collection<java.lang.String>);
+    method @NonNull public String getLdLibraryPath();
     method public void reportClassLoaderChain();
-    method public static void setReporter(dalvik.system.BaseDexClassLoader.Reporter);
+    method public static void setReporter(@Nullable dalvik.system.BaseDexClassLoader.Reporter);
   }
 
   public static interface BaseDexClassLoader.Reporter {
-    method public void report(java.util.Map<java.lang.String,java.lang.String>);
+    method public void report(@NonNull java.util.Map<java.lang.String,java.lang.String>);
   }
 
   public final class BlockGuard {
@@ -154,7 +148,7 @@
   }
 
   public static interface BlockGuard.VmPolicy {
-    method public void onPathAccess(String);
+    method public void onPathAccess(@NonNull String);
   }
 
   public final class CloseGuard {
@@ -454,8 +448,8 @@
 package libcore.content.type {
 
   public final class MimeMap {
-    method public libcore.content.type.MimeMap.Builder buildUpon();
-    method public static libcore.content.type.MimeMap.Builder builder();
+    method @NonNull public libcore.content.type.MimeMap.Builder buildUpon();
+    method @NonNull public static libcore.content.type.MimeMap.Builder builder();
     method @NonNull public java.util.Set<java.lang.String> extensions();
     method @NonNull public static libcore.content.type.MimeMap getDefault();
     method @Nullable public String guessExtensionFromMimeType(@Nullable String);
@@ -467,8 +461,8 @@
   }
 
   public static final class MimeMap.Builder {
-    method public libcore.content.type.MimeMap build();
-    method public libcore.content.type.MimeMap.Builder put(@NonNull String, @NonNull java.util.List<java.lang.String>);
+    method @NonNull public libcore.content.type.MimeMap.Builder addMimeMapping(@NonNull String, @NonNull java.util.List<java.lang.String>);
+    method @NonNull public libcore.content.type.MimeMap build();
   }
 
 }
@@ -554,21 +548,21 @@
 package libcore.net.http {
 
   public interface Dns {
-    method public java.util.List<java.net.InetAddress> lookup(String) throws java.net.UnknownHostException;
+    method @NonNull public java.util.List<java.net.InetAddress> lookup(@Nullable String) throws java.net.UnknownHostException;
   }
 
   public class HttpURLConnectionFactory {
-    method public static libcore.net.http.HttpURLConnectionFactory createInstance();
-    method public java.net.URLConnection openConnection(java.net.URL, javax.net.SocketFactory, java.net.Proxy) throws java.io.IOException;
-    method public void setDns(libcore.net.http.Dns);
-    method public void setNewConnectionPool(int, long, java.util.concurrent.TimeUnit);
+    method @NonNull public static libcore.net.http.HttpURLConnectionFactory createInstance();
+    method public java.net.URLConnection openConnection(@NonNull java.net.URL, @NonNull javax.net.SocketFactory, @NonNull java.net.Proxy) throws java.io.IOException;
+    method public void setDns(@NonNull libcore.net.http.Dns);
+    method public void setNewConnectionPool(int, long, @NonNull java.util.concurrent.TimeUnit);
   }
 
 }
 
 package libcore.util {
 
-  public class FP16 {
+  public final class FP16 {
     method public static short ceil(short);
     method public static int compare(short, short);
     method public static boolean equals(short, short);
@@ -643,6 +637,14 @@
 
 }
 
+package org.json {
+
+  public class JSONObject {
+    method @NonNull public java.util.Set<java.lang.String> keySet();
+  }
+
+}
+
 package sun.misc {
 
   public class Cleaner extends java.lang.ref.PhantomReference<java.lang.Object> {
@@ -725,6 +727,7 @@
 package sun.security.x509 {
 
   public class AlgorithmId implements java.io.Serializable {
+    ctor public AlgorithmId(sun.security.util.ObjectIdentifier);
     method public String getName();
   }
 
diff --git a/mmodules/intracoreapi/api/intra/current.txt b/mmodules/intracoreapi/api/intra/current.txt
index fab4f37..d6676bc 100644
--- a/mmodules/intracoreapi/api/intra/current.txt
+++ b/mmodules/intracoreapi/api/intra/current.txt
@@ -3,15 +3,15 @@
 
   @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public final class Compatibility {
     method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static boolean isChangeEnabled(long);
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static void reportChange(long);
+    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static void reportUnconditionalChange(long);
   }
 
   @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static final class Compatibility.ChangeConfig {
-    ctor public Compatibility.ChangeConfig(java.util.Set<java.lang.Long>, java.util.Set<java.lang.Long>);
-    method public long[] forceDisabledChangesArray();
-    method public java.util.Set<java.lang.Long> forceDisabledSet();
-    method public long[] forceEnabledChangesArray();
-    method public java.util.Set<java.lang.Long> forceEnabledSet();
+    ctor public Compatibility.ChangeConfig(@NonNull java.util.Set<java.lang.Long>, @NonNull java.util.Set<java.lang.Long>);
+    method @NonNull public long[] getDisabledChangesArray();
+    method @NonNull public java.util.Set<java.lang.Long> getDisabledSet();
+    method @NonNull public long[] getEnabledChangesArray();
+    method @NonNull public java.util.Set<java.lang.Long> getEnabledSet();
     method public boolean isEmpty();
     method public boolean isForceDisabled(long);
     method public boolean isForceEnabled(long);
diff --git a/non_openjdk_java_files.bp b/non_openjdk_java_files.bp
index 4e37283..8b67ef7 100755
--- a/non_openjdk_java_files.bp
+++ b/non_openjdk_java_files.bp
@@ -138,8 +138,6 @@
         "luni/src/main/java/android/system/OsConstants.java",
         "luni/src/main/java/android/system/PacketSocketAddress.java",
         "luni/src/main/java/android/system/StructAddrinfo.java",
-        "luni/src/main/java/android/system/StructCapUserData.java",
-        "luni/src/main/java/android/system/StructCapUserHeader.java",
         "luni/src/main/java/android/system/StructCmsghdr.java",
         "luni/src/main/java/android/system/StructGroupReq.java",
         "luni/src/main/java/android/system/StructIfaddrs.java",
@@ -153,6 +151,8 @@
         "luni/src/main/java/android/system/StructTimespec.java",
         "luni/src/main/java/android/system/StructTimeval.java",
         "luni/src/main/java/android/system/StructUcred.java",
+        "luni/src/main/java/android/system/StructUserCapData.java",
+        "luni/src/main/java/android/system/StructUserCapHeader.java",
         "luni/src/main/java/android/system/StructUtsname.java",
         "luni/src/main/java/android/system/UnixSocketAddress.java",
         "luni/src/main/java/android/system/VmSocketAddress.java",
@@ -224,7 +224,6 @@
         "luni/src/main/java/libcore/icu/ICU.java",
         "luni/src/main/java/libcore/icu/LocaleData.java",
         "luni/src/main/java/libcore/icu/TimeZoneNames.java",
-        "luni/src/main/java/libcore/internal/StringPool.java",
         "luni/src/main/java/libcore/io/AsynchronousCloseMonitor.java",
         "luni/src/main/java/libcore/io/ForwardingOs.java",
         "luni/src/main/java/libcore/io/IoBridge.java",
@@ -353,6 +352,7 @@
         "luni/src/main/java/libcore/icu/CollationKeyICU.java",
         "luni/src/main/java/libcore/icu/DateUtilsBridge.java",
         "luni/src/main/java/libcore/internal/Java9LanguageFeatures.java",
+        "luni/src/main/java/libcore/internal/StringPool.java",
         "luni/src/main/java/libcore/io/ClassPathURLStreamHandler.java",
         "luni/src/main/java/libcore/io/BlockGuardOs.java",
         "luni/src/main/java/libcore/io/BufferIterator.java",
diff --git a/ojluni/Android.bp b/ojluni/Android.bp
index 12ae7d7..4c9e703 100644
--- a/ojluni/Android.bp
+++ b/ojluni/Android.bp
@@ -12,10 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Phony target that causes the build to check the license file in this
-// directory, detect that it is a GPL license and then copy all the files
-// from this directory and its subdirectories in to the
-// ${OUT}/obj/PACKAGING/gpl_source_intermediates/gpl_source.tgz file.
 package {
     default_applicable_licenses: ["libcore_ojluni_license"],
 }
@@ -48,11 +44,15 @@
     ],
 }
 
+// Phony target that causes the build to check the license file in this
+// directory, detect that it is a GPL license and then copy all the files
+// from this directory and its subdirectories in to the
+// ${OUT}/obj/PACKAGING/gpl_source_intermediates/gpl_source.tgz file.
 phony {
     name: "ojluni-phony",
 
     // A phony module must have at least one dependency.
     required: [
-        "art-notices-for-framework-stubs-jar",
+        "core-all",
     ],
 }
diff --git a/ojluni/annotations/hiddenapi/java/net/InetAddress.java b/ojluni/annotations/hiddenapi/java/net/InetAddress.java
index 2e1376f..4951374 100644
--- a/ojluni/annotations/hiddenapi/java/net/InetAddress.java
+++ b/ojluni/annotations/hiddenapi/java/net/InetAddress.java
@@ -182,7 +182,7 @@
     }
 
     @UnsupportedAppUsage(maxTargetSdk = VersionCodes.P, trackingBug = 78686891,
-        publicAlternatives = "Use {@link android.net.InetAddresses#isNumericAddress} "
+        publicAlternatives = "Use {@code android.net.InetAddresses#isNumericAddress} "
         + "instead. There is a behavioural difference between the original method and its "
         + "replacement.")
     public static boolean isNumeric(java.lang.String address) {
@@ -202,7 +202,7 @@
      * @deprecated Use {@code android.net.InetAddresses.parseNumericAddress(String)} instead.
      */
     @UnsupportedAppUsage(maxTargetSdk = VersionCodes.P, trackingBug = 78686891,
-        publicAlternatives = "Use {@link android.net.InetAddresses#parseNumericAddress} "
+        publicAlternatives = "Use {@code android.net.InetAddresses#parseNumericAddress} "
         + "instead. There is a behavioural difference between the original method and its "
         + "replacement.")
     public static java.net.InetAddress parseNumericAddress(java.lang.String numericAddress) {
diff --git a/ojluni/annotations/mmodule/sun/security/x509/AlgorithmId.annotated.java b/ojluni/annotations/mmodule/sun/security/x509/AlgorithmId.annotated.java
index dc2baf6..1fc8d82 100644
--- a/ojluni/annotations/mmodule/sun/security/x509/AlgorithmId.annotated.java
+++ b/ojluni/annotations/mmodule/sun/security/x509/AlgorithmId.annotated.java
@@ -31,17 +31,17 @@
 import sun.security.util.DerEncoder;
 import sun.security.util.ObjectIdentifier;
 
-@libcore.api.CorePlatformApi
+@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.IntraCoreApi
 @libcore.api.Hide
 public class AlgorithmId implements Serializable, DerEncoder {
 
-    @libcore.api.CorePlatformApi
+    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public AlgorithmId(ObjectIdentifier oid) {
         throw new RuntimeException("Stub!");
     }
 
-    @libcore.api.CorePlatformApi
+    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public String getName() {
         throw new RuntimeException("Stub!");
diff --git a/ojluni/src/main/java/java/lang/Deprecated.java b/ojluni/src/main/java/java/lang/Deprecated.java
index 17f9dd9..3735f59 100644
--- a/ojluni/src/main/java/java/lang/Deprecated.java
+++ b/ojluni/src/main/java/java/lang/Deprecated.java
@@ -79,9 +79,7 @@
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
-// Androrid-changed: Modules not supported yet
-// @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
-@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
+@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
 public @interface Deprecated {
     /**
      * Returns the version in which the annotated element became deprecated.
diff --git a/ojluni/src/main/java/java/net/NetworkInterface.java b/ojluni/src/main/java/java/net/NetworkInterface.java
index e56e0cb..587d19b 100644
--- a/ojluni/src/main/java/java/net/NetworkInterface.java
+++ b/ojluni/src/main/java/java/net/NetworkInterface.java
@@ -37,7 +37,11 @@
 import java.util.Map;
 import java.util.NoSuchElementException;
 
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.system.StructIfaddrs;
+import dalvik.annotation.compat.VersionCodes;
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
 import sun.security.action.*;
@@ -47,7 +51,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 >= R. http://b/141455849
+// Android-added: Document restrictions for non-system apps. http://b/170188668
 /**
  * This class represents a Network Interface made up of a name,
  * and a list of IP addresses assigned to this interface.
@@ -58,13 +62,28 @@
  * <p>
  * <a name="access-restrictions"></a>Note that information about
  * {@link NetworkInterface}s may be restricted. For example, non-system apps
- * with {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R} will only
- * have access to information about {@link NetworkInterface}s that are
+ * will only have access to information about {@link NetworkInterface}s that are
  * associated with an {@link InetAddress}.
  *
  * @since 1.4
  */
 public final class NetworkInterface {
+    // Android-added: Anonymized address for apps targeting old API versions. http://b/170188668
+    /**
+     * If this change is enabled, {@link #getHardwareAddress()} returns null when the hardware
+     * address is <a href="#access-restrictions">inaccessible</a>. If the change is disabled, the
+     * default MAC address (02:00:00:00:00:00) is returned instead.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion=VersionCodes.R)
+    static final long RETURN_NULL_HARDWARE_ADDRESS = 170188668L;
+    // The default hardware address is a zeroed-out MAC address with only its
+    // locally-administered bit set, returned to apps targeting older API versions if they would
+    // otherwise see a null MAC address.
+    // Matches android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS
+    private static final byte[] DEFAULT_MAC_ADDRESS = {
+        0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
     private String name;
     private String displayName;
     private int index;
@@ -272,7 +291,7 @@
         return "".equals(displayName) ? null : displayName;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
+    // Android-added: Document restrictions for non-system apps. http://b/170188668
     /**
      * Searches for the network interface with the specified name.
      *
@@ -304,7 +323,7 @@
         return null;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
+    // Android-added: Document restrictions for non-system apps. http://b/170188668
     /**
      * Get a network interface given its index.
      *
@@ -373,7 +392,7 @@
         return null;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
+    // Android-added: Document restrictions for non-system apps. http://b/170188668
     /**
      * Returns all the interfaces on this machine. The {@code Enumeration}
      * contains at least one element, possibly representing a loopback
@@ -383,10 +402,8 @@
      * NOTE: can use getNetworkInterfaces()+getInetAddresses()
      *       to obtain all IP addresses for this node
      * <p>
-     * 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}.
+     * For non-system apps, this method will only return information for
+     * {@link NetworkInterface}s associated with an {@link InetAddress}.
      *
      * @return an Enumeration of NetworkInterfaces found on this machine
      *         that <a href="#access-restrictions">are accessible</a>.
@@ -562,7 +579,7 @@
         return (getFlags() & IFF_MULTICAST) != 0;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
+    // Android-added: Restrictions for non-system apps. http://b/170188668
     /**
      * Returns the hardware address (usually MAC) of the interface if it
      * has one and if it can be accessed given the current privileges.
@@ -574,8 +591,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 having
-     *          {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R}.
+     *          non-system apps (or 02:00:00:00:00:00 for apps having
+     *          {@code targetSdkVersion < android.os.Build.VERSION_CODES.R}).
      *
      * @exception       SocketException if an I/O error occurs.
      * @since 1.6
@@ -594,6 +611,12 @@
         if (ni == null) {
             throw new SocketException("NetworkInterface doesn't exist anymore");
         }
+        // Return 02:00:00:00:00:00 for apps having a target SDK version < R if they would have
+        // otherwise gotten a null MAC address.
+        if (ni.hardwareAddr == null &&
+                !Compatibility.isChangeEnabled(RETURN_NULL_HARDWARE_ADDRESS)) {
+            return DEFAULT_MAC_ADDRESS.clone();
+        }
         return ni.hardwareAddr;
         // END Android-changed: Fix upstream not returning link-down interfaces. http://b/26238832
     }
diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index 718c95f..36a4601 100644
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -43,7 +43,7 @@
 import android.icu.util.ULocale;
 
 import com.android.icu.text.ExtendedTimeZoneNames;
-import com.android.icu.text.ExtendedTimeZoneNames.MatchedTimeZone;
+import com.android.icu.text.ExtendedTimeZoneNames.Match;
 
 import java.io.IOException;
 import java.io.InvalidObjectException;
@@ -2011,27 +2011,26 @@
     private int subParseZoneStringFromICU(String text, int start, CalendarBuilder calb) {
         String currentTimeZoneID = android.icu.util.TimeZone.getCanonicalID(getTimeZone().getID());
 
-        MatchedTimeZone matchedTimeZone = getExtendedTimeZoneNames().matchName(text, start,
-                currentTimeZoneID);
-        if (matchedTimeZone == null) {
+        Match matchedName = getExtendedTimeZoneNames().matchName(text, start, currentTimeZoneID);
+        if (matchedName == null) {
             // No match found, return error.
             return -start;
         }
 
-        String tzId = matchedTimeZone.getTzId();
+        String tzId = matchedName.getTzId();
         TimeZone newTimeZone = TimeZone.getTimeZone(tzId);
         if (!currentTimeZoneID.equals(tzId)) {
             setTimeZone(newTimeZone);
         }
 
         // Same logic as in subParseZoneStringFromSymbols, see below for details.
-        boolean isDst = matchedTimeZone.isDst();
+        boolean isDst = matchedName.isDst();
         int dstAmount = isDst ? newTimeZone.getDSTSavings() : 0;
         if (!isDst || dstAmount != 0) {
             calb.clear(Calendar.ZONE_OFFSET).set(Calendar.DST_OFFSET, dstAmount);
         }
 
-        return matchedTimeZone.getMatchLength() + start;
+        return matchedName.getMatchLength() + start;
     }
 
     /**
diff --git a/ojluni/src/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java b/ojluni/src/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java
index 5c76697..438ea56 100644
--- a/ojluni/src/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java
@@ -180,6 +180,11 @@
         assertEquals(expected.length == 0, actual.isEmpty());
         assertEquals(new HashSet<Thread>(actual),
                      new HashSet<Thread>(Arrays.asList(expected)));
+        // Android-added: Since we check queued threads, also check queued predecessors
+        final boolean expectedQueuedPredecessors =
+            sync.getFirstQueuedThread() != Thread.currentThread() &&
+            sync.hasQueuedThreads();
+        assertEquals(expectedQueuedPredecessors, sync.hasQueuedPredecessors());
     }
 
     /**
diff --git a/ojluni/src/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java b/ojluni/src/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java
index 1f79e2c..a1f36ba 100644
--- a/ojluni/src/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java
@@ -183,6 +183,11 @@
         assertEquals(expected.length == 0, actual.isEmpty());
         assertEquals(new HashSet<Thread>(actual),
                      new HashSet<Thread>(Arrays.asList(expected)));
+        // Android-added: Since we check queued threads, also check queued predecessors
+        final boolean expectedQueuedPredecessors =
+            sync.getFirstQueuedThread() != Thread.currentThread() &&
+            sync.hasQueuedThreads();
+        assertEquals(expectedQueuedPredecessors, sync.hasQueuedPredecessors());
     }
 
     /**
diff --git a/ojluni/src/test/java/util/concurrent/tck/BrokenBarrierExceptionTest.java b/ojluni/src/test/java/util/concurrent/tck/BrokenBarrierExceptionTest.java
deleted file mode 100644
index 88dc86a..0000000
--- a/ojluni/src/test/java/util/concurrent/tck/BrokenBarrierExceptionTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/publicdomain/zero/1.0/
- * Other contributors include Andrew Wright, Jeffrey Hayes,
- * Pat Fisher, Mike Judd.
- */
-
-package test.java.util.concurrent.tck;
-
-import java.util.concurrent.BrokenBarrierException;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class BrokenBarrierExceptionTest extends JSR166TestCase {
-    public static void main(String[] args) {
-        main(suite(), args);
-    }
-    public static Test suite() {
-        return new TestSuite(BrokenBarrierExceptionTest.class);
-    }
-
-    /**
-     * constructor creates exception with detail message
-     */
-    public void testConstructWithMessage() {
-        BrokenBarrierException exception = new BrokenBarrierException("test");
-        assertEquals("test", exception.getMessage());
-        assertNull(exception.getCause());
-    }
-
-}
diff --git a/ojluni/src/test/java/util/concurrent/tck/CompletionExceptionTest.java b/ojluni/src/test/java/util/concurrent/tck/CompletionExceptionTest.java
deleted file mode 100644
index 0a25ac2..0000000
--- a/ojluni/src/test/java/util/concurrent/tck/CompletionExceptionTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/publicdomain/zero/1.0/
- * Other contributors include Andrew Wright, Jeffrey Hayes,
- * Pat Fisher, Mike Judd.
- */
-
-package test.java.util.concurrent.tck;
-
-import java.util.concurrent.CompletionException;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class CompletionExceptionTest extends JSR166TestCase {
-    public static void main(String[] args) {
-        main(suite(), args);
-    }
-    public static Test suite() {
-        return new TestSuite(CompletionExceptionTest.class);
-    }
-
-    // Adding derived class to be able to test the protected constructors
-    private class TestCompletionException extends CompletionException {
-        public TestCompletionException() {
-            super();
-        }
-        public TestCompletionException(String message) {
-            super(message);
-        }
-    }
-
-    /**
-     * constructor creates exception without any details
-     */
-    public void testConstructNoMessage() {
-        CompletionException exception = new TestCompletionException();
-        assertNull(exception.getMessage());
-        assertNull(exception.getCause());
-    }
-
-    /**
-     * constructor creates exception with detail message
-     */
-    public void testConstructWithMessage() {
-        CompletionException exception = new TestCompletionException("test");
-        assertEquals("test", exception.getMessage());
-        assertNull(exception.getCause());
-    }
-
-    /**
-     * constructor creates exception with detail message and cause
-     */
-    public void testConstructWithMessageAndCause() {
-        Throwable cause = new Exception();
-        CompletionException exception = new CompletionException("test", cause);
-        assertEquals("test", exception.getMessage());
-        assertEquals(cause, exception.getCause());
-    }
-}
diff --git a/ojluni/src/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java b/ojluni/src/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java
index 25ba7a1..324a5ef 100644
--- a/ojluni/src/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java
+++ b/ojluni/src/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java
@@ -49,13 +49,6 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.LongAdder;
 import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.function.ToDoubleBiFunction;
-import java.util.function.ToDoubleFunction;
-import java.util.function.ToIntBiFunction;
-import java.util.function.ToIntFunction;
-import java.util.function.ToLongBiFunction;
-import java.util.function.ToLongFunction;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -196,8 +189,7 @@
     }
 
     static Set<Integer> populatedSet(int n) {
-        // Android-changed: Use the overload of newKeySet with specified initial capacity.
-        Set<Integer> a = ConcurrentHashMap.<Integer>newKeySet(n);
+        Set<Integer> a = ConcurrentHashMap.<Integer>newKeySet();
         assertTrue(a.isEmpty());
         for (int i = 0; i < n; i++)
             assertTrue(a.add(i));
@@ -614,52 +606,6 @@
         }
     }
 
-    // BEGIN Android-added: More explicit function classes to avoid type inference problems.
-    static class IncrementKey implements Function<Map.Entry<Long,Long>, Map.Entry<Long,Long>> {
-        public Map.Entry<Long,Long> apply(Map.Entry<Long,Long> in) {
-            return new AbstractMap.SimpleEntry<Long,Long>
-             (Long.valueOf(in.getKey().longValue() + 1),
-              Long.valueOf(1L));
-        }
-    }
-
-    static class KeyAsDouble implements ToDoubleFunction<Map.Entry<Long,Long>> {
-        public double applyAsDouble(Map.Entry<Long,Long> in) {
-            return in.getKey().doubleValue();
-        }
-    }
-
-    static class KeyAsInt implements ToIntFunction<Map.Entry<Long,Long>> {
-        public int applyAsInt(Map.Entry<Long,Long> in) {
-            return in.getKey().intValue();
-        }
-    }
-
-    static class KeyAsLong implements ToLongFunction<Map.Entry<Long,Long>> {
-        public long applyAsLong(Map.Entry<Long,Long> in) {
-            return in.getKey().longValue();
-        }
-    }
-
-    static class IncrementKeyToDouble implements ToDoubleBiFunction<Long, Long> {
-        public double applyAsDouble(Long key, Long value) {
-            return (key.doubleValue() + 1);
-        }
-    }
-
-    static class IncrementKeyToInt implements ToIntBiFunction<Long, Long> {
-        public int applyAsInt(Long key, Long value) {
-            return (key.intValue() + 1);
-        }
-    }
-
-    static class IncrementKeyToLong implements ToLongBiFunction<Long, Long> {
-        public long applyAsLong(Long key, Long value) {
-            return (key.longValue() + 1);
-        }
-    }
-    // END Android-added: More explicit function classes to avoid type inference problems.
-
     /**
      * forEachKeySequentially traverses all keys
      */
@@ -866,136 +812,6 @@
         assertEquals(r.getKey().longValue(), (long)SIZE * (SIZE - 1) / 2);
     }
 
-    // BEGIN Android-added: Extra unit tests to cover missing APIs.
-    /**
-     * transformReduceEntriesSequentially accumulates across all entries
-     */
-    public void testTransformReduceEntriesSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Map.Entry<Long,Long> r;
-        r = m.reduceEntries(Long.MAX_VALUE, new IncrementKey(), new AddKeys());
-        assertEquals(r.getKey().longValue(), (long)SIZE * (SIZE + 1) / 2);
-    }
-
-    /**
-     * reduceEntriesToDoubleSequentially accumulates across all entries
-     */
-    public void testReduceEntriesToDoubleSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        double dr = m.reduceEntriesToDouble(Long.MAX_VALUE, new KeyAsDouble(), 0.0, Double::sum);
-        assertEquals(dr, (double)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceEntriesToIntSequentially accumulates across all entries
-     */
-    public void testReduceEntriesToIntSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        int ir = m.reduceEntriesToInt(Long.MAX_VALUE, new KeyAsInt(), 0, Integer::sum);
-        assertEquals(ir, (int)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceEntriesToLongSequentially accumulates across all entries
-     */
-    public void testReduceEntriesToLongSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        long lr = m.reduceEntriesToLong(Long.MAX_VALUE, new KeyAsLong(), 0L, Long::sum);
-        assertEquals(lr, (long)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * transformReduceEntriesToDoubleSequentially accumulates across all entries
-     */
-    public void testTransformReduceEntriesToDoubleSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        double dr = m.reduceToDouble(Long.MAX_VALUE, new IncrementKeyToDouble(), 0.0, Double::sum);
-        assertEquals(dr, (double)SIZE * (SIZE + 1) / 2);
-    }
-
-    /**
-     * transformReduceEntriesToIntSequentially accumulates across all entries
-     */
-    public void testTransformReduceEntriesToIntSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        int ir = m.reduceToInt(Long.MAX_VALUE, new IncrementKeyToInt(), 0, Integer::sum);
-        assertEquals(ir, SIZE * (SIZE + 1) / 2);
-    }
-
-    /**
-     * transformReduceEntriesToLongSequentially accumulates across all entries
-     */
-    public void testTransformReduceEntriesToLongSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        long lr = m.reduceToLong(Long.MAX_VALUE, new IncrementKeyToLong(), 0L, Long::sum);
-        assertEquals(lr, (long)SIZE * (SIZE + 1) / 2);
-    }
-
-    /**
-     * transformReduceEntriesInParallel accumulates across all entries
-     */
-    public void testTransformReduceEntriesInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Map.Entry<Long,Long> r;
-        r = m.reduceEntries(1L, new IncrementKey(), new AddKeys());
-        assertEquals(r.getKey().longValue(), (long)SIZE * (SIZE + 1) / 2);
-    }
-
-    /**
-     * reduceEntriesToDoubleInParallel accumulates across all entries
-     */
-    public void testReduceEntriesToDoubleInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        double dr = m.reduceEntriesToDouble(1L, new KeyAsDouble(), 0.0, Double::sum);
-        assertEquals(dr, (double)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceEntriesToIntInParallel accumulates across all entries
-     */
-    public void testReduceEntriesToIntInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        int ir = m.reduceEntriesToInt(1L, new KeyAsInt(), 0, Integer::sum);
-        assertEquals(ir, SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceEntriesToLongInParallel accumulates across all entries
-     */
-    public void testReduceEntriesToLongInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        long lr = m.reduceEntriesToLong(1L, new KeyAsLong(), 0L, Long::sum);
-        assertEquals(lr, (long)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * transformReduceEntriesToDoubleInParallel accumulates across all entries
-     */
-    public void testTransformReduceEntriesToDoubleInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        double dr = m.reduceToDouble(1L, new IncrementKeyToDouble(), 0.0, Double::sum);
-        assertEquals(dr, (double)SIZE * (SIZE + 1) / 2);
-    }
-
-    /**
-     * transformReduceEntriesToIntInParallel accumulates across all entries
-     */
-    public void testTransformReduceEntriesToIntInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        int ir = m.reduceToInt(1L, new IncrementKeyToInt(), 0, Integer::sum);
-        assertEquals(ir, SIZE * (SIZE + 1) / 2);
-    }
-
-    /**
-     * transformReduceEntriesToLongInParallel accumulates across all entries
-     */
-    public void testTransformReduceEntriesToLongInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        long lr = m.reduceToLong(1L, new IncrementKeyToLong(), 0L, Long::sum);
-        assertEquals(lr, (long)SIZE * (SIZE + 1) / 2);
-    }
-    // END Android-added: Extra unit tests to cover missing APIs.
-
     /**
      * reduceKeysInParallel accumulates across all keys
      */
diff --git a/ojluni/src/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java b/ojluni/src/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java
index 5218e1a..7e8594d 100644
--- a/ojluni/src/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java
@@ -171,47 +171,6 @@
         assertFalse(s.containsAll(Arrays.asList(ar)));
     }
 
-    // BEGIN Android-added: Extra unit tests for missing APIs.
-    /**
-     * clone creates map with a shallow copy of the source map
-     */
-    public void testCloneFromSorted() {
-        ConcurrentSkipListMap map = map5();
-        ConcurrentSkipListMap map2 = map.clone();
-        assertNotSame(map, map2);
-        Set s = map.entrySet();
-        Set s2 = map2.entrySet();
-        Iterator it = s.iterator();
-        Iterator it2 = s2.iterator();
-        while(it.hasNext() && it2.hasNext()) {
-            Map.Entry e = (Map.Entry) it.next();
-            Map.Entry e2 = (Map.Entry) it2.next();
-            assertSame(e.getKey(), e2.getKey());
-            assertSame(e.getValue(), e2.getValue());
-        }
-        assertFalse(it.hasNext());
-        assertFalse(it2.hasNext());
-    }
-
-    /**
-     * firstEntry returns first key-value entry
-     */
-    public void testFirstEntry() {
-        ConcurrentSkipListMap map = map5();
-        assertEquals(one, map.firstEntry().getKey());
-        assertEquals("A", map.firstEntry().getValue());
-    }
-
-    /**
-     * lastEntry returns last key-value entry
-     */
-    public void testLastEntry() {
-        ConcurrentSkipListMap map = map5();
-        assertEquals(five, map.lastEntry().getKey());
-        assertEquals("E", map.lastEntry().getValue());
-    }
-    // END Android-added: Extra unit tests for missing APIs.
-
     /**
      * descendingkeySet.toArray returns contains all keys
      */
@@ -888,8 +847,7 @@
      */
     public void testSubMapContents() {
         ConcurrentSkipListMap map = map5();
-        // Android-changed: Use the "default" subMap overload.
-        NavigableMap sm = map.subMap(two, four);
+        NavigableMap sm = map.subMap(two, true, four, false);
         assertEquals(two, sm.firstKey());
         assertEquals(three, sm.lastKey());
         assertEquals(2, sm.size());
@@ -927,8 +885,7 @@
 
     public void testSubMapContents2() {
         ConcurrentSkipListMap map = map5();
-        // Android-changed: Use the "default" subMap overload.
-        NavigableMap sm = map.subMap(two, three);
+        NavigableMap sm = map.subMap(two, true, three, false);
         assertEquals(1, sm.size());
         assertEquals(two, sm.firstKey());
         assertEquals(two, sm.lastKey());
@@ -963,8 +920,7 @@
      */
     public void testHeadMapContents() {
         ConcurrentSkipListMap map = map5();
-        // Android-changed: Use the "default" headMap overload.
-        NavigableMap sm = map.headMap(four);
+        NavigableMap sm = map.headMap(four, false);
         assertTrue(sm.containsKey(one));
         assertTrue(sm.containsKey(two));
         assertTrue(sm.containsKey(three));
@@ -990,8 +946,7 @@
      */
     public void testTailMapContents() {
         ConcurrentSkipListMap map = map5();
-        // Android-changed: Use the "default" tailMap overload.
-        NavigableMap sm = map.tailMap(two);
+        NavigableMap sm = map.tailMap(two, true);
         assertFalse(sm.containsKey(one));
         assertTrue(sm.containsKey(two));
         assertTrue(sm.containsKey(three));
diff --git a/ojluni/src/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java b/ojluni/src/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java
index 4c16ace..d27c10f 100644
--- a/ojluni/src/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java
@@ -42,7 +42,6 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.SortedSet;
-import java.util.TreeSet;
 import java.util.concurrent.ConcurrentSkipListSet;
 
 import junit.framework.Test;
@@ -161,45 +160,6 @@
             assertEquals(ints[i], q.pollFirst());
     }
 
-    // BEGIN Android-added: Extra unit tests for covering constructor and clone APIs.
-    /**
-     * A sorted set is used in constructor - the new set will contain the same elements and using the
-     * same ordering as the source
-     */
-    public void testConstructorFromSortedSet() {
-        TreeSet ts = new TreeSet();
-        ts.add(one);
-        ts.add(two);
-        ts.add(three);
-        ts.add(four);
-        ts.add(five);
-        ConcurrentSkipListSet q = new ConcurrentSkipListSet(ts);
-        assertEquals(ts.size(), q.size());
-        while(!ts.isEmpty()) {
-            assertFalse(q.isEmpty());
-            assertEquals(ts.pollFirst(), q.pollFirst());
-        }
-    }
-
-    /**
-     * clone creates set with a shallow copy of the source set
-     */
-    public void testClone() {
-        ConcurrentSkipListSet x = set5();
-        ConcurrentSkipListSet y = x.clone();
-        assertNotSame(x, y);
-        Iterator itX = x.iterator();
-        Iterator itY = y.iterator();
-        while(itX.hasNext() && itY.hasNext()) {
-            Integer iX = (Integer) itX.next();
-            Integer iY = (Integer) itY.next();
-            assertSame(iX, iY);
-        }
-        assertFalse(itX.hasNext());
-        assertFalse(itY.hasNext());
-    }
-    // END Android-added: Extra unit tests for covering constructor and clone APIs.
-
     /**
      * isEmpty is true before add, false after
      */
@@ -548,41 +508,12 @@
         ConcurrentSkipListSet q = populatedSet(SIZE);
         Iterator it = q.iterator();
         int i;
-        Integer lastVal = null;
-        for (i = 0; it.hasNext(); i++) {
-            Integer val = (Integer) it.next();
-            assertTrue(q.contains(val));
-            if(lastVal != null) {
-                assertTrue(0 >= lastVal.compareTo(val));
-            }
-            lastVal = val;
-        }
+        for (i = 0; it.hasNext(); i++)
+            assertTrue(q.contains(it.next()));
         assertEquals(i, SIZE);
         assertIteratorExhausted(it);
     }
 
-    // BEGIN Android-added: Unit test for descending iterator API.
-    /**
-     * descendingIterator iterates through all elements
-     */
-    public void testDescendingIterator() {
-        ConcurrentSkipListSet q = populatedSet(SIZE);
-        Iterator it = q.descendingIterator();
-        int i;
-        Integer lastVal = null;
-        for (i = 0; it.hasNext(); i++) {
-            Integer val = (Integer) it.next();
-            assertTrue(q.contains(val));
-            if(lastVal != null) {
-                assertTrue(0 <= lastVal.compareTo(val));
-            }
-            lastVal = val;
-        }
-        assertEquals(i, SIZE);
-        assertIteratorExhausted(it);
-    }
-    // END Android-added: Unit test for descending iterator API.
-
     /**
      * iterator of empty set has no elements
      */
diff --git a/ojluni/src/test/java/util/concurrent/tck/ExecutionExceptionTest.java b/ojluni/src/test/java/util/concurrent/tck/ExecutionExceptionTest.java
deleted file mode 100644
index 7cf1fa1..0000000
--- a/ojluni/src/test/java/util/concurrent/tck/ExecutionExceptionTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/publicdomain/zero/1.0/
- * Other contributors include Andrew Wright, Jeffrey Hayes,
- * Pat Fisher, Mike Judd.
- */
-
-package test.java.util.concurrent.tck;
-
-import java.util.concurrent.ExecutionException;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class ExecutionExceptionTest extends JSR166TestCase {
-    public static void main(String[] args) {
-        main(suite(), args);
-    }
-    public static Test suite() {
-        return new TestSuite(ExecutionExceptionTest.class);
-    }
-
-    // Adding derived class to be able to test the protected constructors
-    private class TestExecutionException extends ExecutionException {
-        public TestExecutionException() {
-            super();
-        }
-        public TestExecutionException(String message) {
-            super(message);
-        }
-    }
-
-    /**
-     * constructor creates exception without any details
-     */
-    public void testConstructNoMessage() {
-        ExecutionException exception = new TestExecutionException();
-        assertNull(exception.getMessage());
-        assertNull(exception.getCause());
-    }
-
-    /**
-     * constructor creates exception with detail message
-     */
-    public void testConstructWithMessage() {
-        ExecutionException exception = new TestExecutionException("test");
-        assertEquals("test", exception.getMessage());
-        assertNull(exception.getCause());
-    }
-
-    /**
-     * constructor creates exception with detail message and cause
-     */
-    public void testConstructWithMessageAndCause() {
-        Throwable cause = new Exception();
-        ExecutionException exception = new ExecutionException("test", cause);
-        assertEquals("test", exception.getMessage());
-        assertEquals(cause, exception.getCause());
-    }
-
-}
diff --git a/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java b/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java
index 73625db..575a8f3 100644
--- a/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java
+++ b/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java
@@ -511,8 +511,6 @@
             AtomicReferenceFieldUpdaterTest.suite(),
             AtomicReferenceTest.suite(),
             AtomicStampedReferenceTest.suite(),
-            BrokenBarrierExceptionTest.suite(),
-            CompletionExceptionTest.suite(),
             ConcurrentHashMapTest.suite(),
             ConcurrentLinkedDequeTest.suite(),
             ConcurrentLinkedQueueTest.suite(),
@@ -528,9 +526,8 @@
             DelayQueueTest.suite(),
             EntryTest.suite(),
             ExchangerTest.suite(),
-            ExecutionExceptionTest.suite(),
-            ExecutorCompletionServiceTest.suite(),
             ExecutorsTest.suite(),
+            ExecutorCompletionServiceTest.suite(),
             FutureTaskTest.suite(),
             LinkedBlockingDequeTest.suite(),
             LinkedBlockingQueueTest.suite(),
@@ -540,9 +537,8 @@
             PriorityQueueTest.suite(),
             ReentrantLockTest.suite(),
             ReentrantReadWriteLockTest.suite(),
-            RejectedExecutionExceptionTest.suite(),
-            ScheduledExecutorSubclassTest.suite(),
             ScheduledExecutorTest.suite(),
+            ScheduledExecutorSubclassTest.suite(),
             SemaphoreTest.suite(),
             SynchronousQueueTest.suite(),
             SystemTest.suite(),
diff --git a/ojluni/src/test/java/util/concurrent/tck/RejectedExecutionExceptionTest.java b/ojluni/src/test/java/util/concurrent/tck/RejectedExecutionExceptionTest.java
deleted file mode 100644
index 4c6e239..0000000
--- a/ojluni/src/test/java/util/concurrent/tck/RejectedExecutionExceptionTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/publicdomain/zero/1.0/
- * Other contributors include Andrew Wright, Jeffrey Hayes,
- * Pat Fisher, Mike Judd.
- */
-
-package test.java.util.concurrent.tck;
-
-import java.util.concurrent.RejectedExecutionException;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class RejectedExecutionExceptionTest extends JSR166TestCase {
-    public static void main(String[] args) {
-        main(suite(), args);
-    }
-    public static Test suite() {
-        return new TestSuite(RejectedExecutionExceptionTest.class);
-    }
-
-    // Adding derived class to be able to test the protected constructors
-    private class TestExecutionException extends RejectedExecutionException {
-        public TestExecutionException() {
-            super();
-        }
-        public TestExecutionException(String message) {
-            super(message);
-        }
-    }
-
-    /**
-     * constructor creates exception without any details
-     */
-    public void testConstructDefault() {
-        RejectedExecutionException exception = new TestExecutionException();
-        assertNull(exception.getMessage());
-        assertNull(exception.getCause());
-    }
-
-    /**
-     * constructor creates exception with detail message and cause
-     */
-    public void testConstructWithMessageAndCause() {
-        Throwable cause = new Exception();
-        RejectedExecutionException exception = new RejectedExecutionException("test", cause);
-        assertEquals("test", exception.getMessage());
-        assertEquals(cause, exception.getCause());
-    }
-
-    /**
-     * constructor creates exception with cause
-     */
-    public void testConstructWithCause() {
-        Throwable cause = new Exception("root");
-        RejectedExecutionException exception = new RejectedExecutionException(cause);
-        assertEquals(cause.toString(), exception.getMessage());
-        assertEquals(cause, exception.getCause());
-    }
-
-}
diff --git a/test-rules/src/platform_compat/java/libcore/junit/util/CoreCompatChangeRule.java b/test-rules/src/platform_compat/java/libcore/junit/util/CoreCompatChangeRule.java
index b526707..4fd3208 100644
--- a/test-rules/src/platform_compat/java/libcore/junit/util/CoreCompatChangeRule.java
+++ b/test-rules/src/platform_compat/java/libcore/junit/util/CoreCompatChangeRule.java
@@ -17,7 +17,6 @@
 package libcore.junit.util.compat;
 
 import android.compat.Compatibility;
-import android.compat.Compatibility.Callbacks;
 import android.compat.Compatibility.ChangeConfig;
 
 import org.junit.rules.TestRule;