Merge "Revert^2 "Remove hidden System.arraycopy(byte[]....""
diff --git a/Android.mk b/Android.mk
index d68f654..465c964 100644
--- a/Android.mk
+++ b/Android.mk
@@ -23,12 +23,6 @@
 subdir_makefiles := $(call all-named-subdir-makefiles,$(subdirs))
 
 #
-# Include the definitions to build the Java code.
-#
-
-include $(LOCAL_PATH)/JavaLibrary.mk
-
-#
 # Disable test modules if LIBCORE_SKIP_TESTS environment variable is set.
 #
 
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index 066a0ac..53d0a10 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -658,6 +658,13 @@
     },
     no_standard_libs: true,
     system_modules: "none",
+
+    dist: {
+        targets: [
+            "sdk",
+            "win_sdk",
+        ],
+    },
 }
 
 // Target for validating nullability annotations for correctness and
@@ -695,3 +702,14 @@
     name: "timezone-host",
     srcs: [":timezone_host_files"],
 }
+
+// The source files that contain the UnsupportedAppUsage annotation and its dependencies.
+filegroup {
+    name: "unsupportedappusage_annotation_files",
+    srcs: [
+        "dalvik/src/main/java/dalvik/annotation/compat/UnsupportedAppUsage.java",
+        "dalvik/src/main/java/dalvik/system/VersionCodes.java",
+        "luni/src/main/java/libcore/api/CorePlatformApi.java",
+        "luni/src/main/java/libcore/api/IntraCoreApi.java",
+    ],
+}
\ No newline at end of file
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
deleted file mode 100644
index f5f9f70..0000000
--- a/JavaLibrary.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- mode: makefile -*-
-# Copyright (C) 2007 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.
-
-# Archive a copy of the classes.jar in SDK build.
-full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,core.current.stubs,,COMMON)/classes.jar
-$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):core.current.stubs.jar)
diff --git a/NativeCode.bp b/NativeCode.bp
index c5341e0..38f57b3 100644
--- a/NativeCode.bp
+++ b/NativeCode.bp
@@ -143,6 +143,9 @@
                 // for more information.
                 "-DANDROID_LINK_SHARED_ICU4C",
             ],
+            shared_libs: [
+                "libdl_android",
+            ],
         },
     },
 
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
index 2a81be1..486ee90 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -110,8 +110,9 @@
         //System.out.println("DEX FILE cookie is " + mCookie + " fileName=" + fileName);
     }
 
-    DexFile(ByteBuffer[] bufs) throws IOException {
-        mCookie = openInMemoryDexFiles(bufs);
+    DexFile(ByteBuffer[] bufs, ClassLoader loader, DexPathList.Element[] elements)
+            throws IOException {
+        mCookie = openInMemoryDexFiles(bufs, loader, elements);
         mInternalCookie = mCookie;
         mFileName = null;
     }
@@ -370,7 +371,8 @@
                                  elements);
     }
 
-    private static Object openInMemoryDexFiles(ByteBuffer[] bufs) throws IOException {
+    private static Object openInMemoryDexFiles(ByteBuffer[] bufs, ClassLoader loader,
+            DexPathList.Element[] elements) throws IOException {
         // Preprocess the ByteBuffers for openInMemoryDexFilesNative. We extract
         // the backing array (non-direct buffers only) and start/end positions
         // so that the native method does not have to call Java methods anymore.
@@ -382,11 +384,11 @@
             starts[i] = bufs[i].position();
             ends[i] = bufs[i].limit();
         }
-        return openInMemoryDexFilesNative(bufs, arrays, starts, ends);
+        return openInMemoryDexFilesNative(bufs, arrays, starts, ends, loader, elements);
     }
 
     private static native Object openInMemoryDexFilesNative(ByteBuffer[] bufs, byte[][] arrays,
-            int[] starts, int[] ends);
+            int[] starts, int[] ends, ClassLoader loader, DexPathList.Element[] elements);
 
     /*
      * Initiates background verification of this DexFile. This is a sepearate down-call
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java
index 227231a..c63bb13 100644
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ b/dalvik/src/main/java/dalvik/system/DexPathList.java
@@ -266,10 +266,10 @@
 
         try {
             Element[] null_elements = null;
-            DexFile dex = new DexFile(dexFiles);
+            DexFile dex = new DexFile(dexFiles, definingContext, null_elements);
             // Capture class loader context from *before* `dexElements` is set (see comment below).
-            String classLoaderContext = DexFile.getClassLoaderContext(definingContext,
-                    null_elements);
+            String classLoaderContext = dex.isBackedByOatFile()
+                    ? null : DexFile.getClassLoaderContext(definingContext, null_elements);
             dexElements = new Element[] { new Element(dex) };
             // Spawn background thread to verify all classes and cache verification results.
             // Must be called *after* `dexElements` has been initialized for ART to find
@@ -277,7 +277,13 @@
             // the order of the array), but with class loader context from *before*
             // `dexElements` was set because that is what it will be compared against next
             // time the same bytecode is loaded.
-            dex.verifyInBackground(definingContext, classLoaderContext);
+            // We only spawn the background thread if the bytecode is not backed by an oat
+            // file, i.e. this is the first time this bytecode is being loaded and/or
+            // verification results have not been cached yet. Skip spawning the thread on
+            // all subsequent loads of the same bytecode in the same class loader context.
+            if (classLoaderContext != null) {
+                dex.verifyInBackground(definingContext, classLoaderContext);
+            }
         } catch (IOException suppressed) {
             System.logE("Unable to load dex files", suppressed);
             suppressedExceptions.add(suppressed);
@@ -340,7 +346,8 @@
         int elementPos = 0;
         for (ByteBuffer buf : dexFiles) {
             try {
-                DexFile dex = new DexFile(new ByteBuffer[] { buf });
+                DexFile dex = new DexFile(new ByteBuffer[] { buf }, /* classLoader */ null,
+                        /* dexElements */ null);
                 elements[elementPos++] = new Element(dex);
             } catch (IOException suppressed) {
                 System.logE("Unable to load dex file: " + buf, suppressed);
diff --git a/expectations/Android.bp b/expectations/Android.bp
new file mode 100644
index 0000000..bf4a993
--- /dev/null
+++ b/expectations/Android.bp
@@ -0,0 +1,9 @@
+filegroup {
+    name: "libcore-expectations-knownfailures",
+    srcs: ["knownfailures.txt"],
+}
+
+filegroup {
+    name: "libcore-expectations-virtualdeviceknownfailures",
+    srcs: ["virtualdeviceknownfailures.txt"],
+}
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 0260e68..7d70680 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -696,4 +696,10 @@
      */
     @libcore.api.CorePlatformApi
     public static native void setProcessPackageName(String packageName);
+
+    /**
+     * Sets the full path to data directory of the app running in this process.
+     */
+    @libcore.api.CorePlatformApi
+    public static native void setProcessDataDirectory(String dataDir);
 }
diff --git a/luni/src/main/java/android/system/ErrnoException.java b/luni/src/main/java/android/system/ErrnoException.java
index 02a529f..a5edf47 100644
--- a/luni/src/main/java/android/system/ErrnoException.java
+++ b/luni/src/main/java/android/system/ErrnoException.java
@@ -19,6 +19,7 @@
 import java.io.IOException;
 import java.net.SocketException;
 import libcore.io.Libcore;
+import libcore.util.NonNull;
 
 /**
  * A checked exception thrown when {@link Os} methods fail. This exception contains the native
@@ -65,21 +66,26 @@
     }
 
     /**
-     * @hide - internal use only.
+     * Throws an {@link IOException} with a message based on {@link #getMessage()} and with this
+     * instance as the cause.
+     *
+     * <p>This method always terminates by throwing the exception. Callers can write
+     * {@code throw e.rethrowAsIOException()} to make that clear to the compiler.
      */
-    @libcore.api.CorePlatformApi
-    public IOException rethrowAsIOException() throws IOException {
+    public @NonNull IOException rethrowAsIOException() throws IOException {
         IOException newException = new IOException(getMessage());
         newException.initCause(this);
         throw newException;
     }
 
     /**
-     * @hide - internal use only.
+     * Throws a {@link SocketException} with a message based on {@link #getMessage()} and with this
+     * instance as the cause.
+     *
+     * <p>This method always terminates by throwing the exception. Callers can write
+     * {@code throw e.rethrowAsIOException()} to make that clear to the compiler.
      */
-    @libcore.api.CorePlatformApi
-    @libcore.api.IntraCoreApi
-    public SocketException rethrowAsSocketException() throws SocketException {
+    public @NonNull SocketException rethrowAsSocketException() throws SocketException {
         throw new SocketException(getMessage(), this);
     }
 }
diff --git a/luni/src/main/java/libcore/io/BlockGuardOs.java b/luni/src/main/java/libcore/io/BlockGuardOs.java
index d56e182..bd95a93 100644
--- a/luni/src/main/java/libcore/io/BlockGuardOs.java
+++ b/luni/src/main/java/libcore/io/BlockGuardOs.java
@@ -121,14 +121,29 @@
         return linger.isOn() && linger.l_linger > 0;
     }
 
-    @Override public void connect(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException {
-        BlockGuard.getThreadPolicy().onNetwork();
+    private static boolean isUdpSocket(FileDescriptor fd) throws ErrnoException {
+        return Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) == IPPROTO_UDP;
+    }
+
+    @Override public void connect(FileDescriptor fd, InetAddress address, int port)
+            throws ErrnoException, SocketException {
+        boolean skipGuard = false;
+        try {
+            skipGuard = isUdpSocket(fd);
+        } catch (ErrnoException ignored) {
+        }
+        if (!skipGuard) BlockGuard.getThreadPolicy().onNetwork();
         super.connect(fd, address, port);
     }
 
     @Override public void connect(FileDescriptor fd, SocketAddress address) throws ErrnoException,
             SocketException {
-        BlockGuard.getThreadPolicy().onNetwork();
+        boolean skipGuard = false;
+        try {
+            skipGuard = isUdpSocket(fd);
+        } catch (ErrnoException ignored) {
+        }
+        if (!skipGuard) BlockGuard.getThreadPolicy().onNetwork();
         super.connect(fd, address);
     }
 
diff --git a/luni/src/main/java/libcore/net/android.mime.types b/luni/src/main/java/libcore/net/android.mime.types
index 8a090fc..dff930a 100644
--- a/luni/src/main/java/libcore/net/android.mime.types
+++ b/luni/src/main/java/libcore/net/android.mime.types
@@ -69,6 +69,7 @@
 video/m4v m4v
 video/mp2p mpeg
 video/mp2ts ts
+video/MP2T m2ts MTS
 video/x-webex wrf
 
 # Special cases where Android has a strong opinion about mappings, so we
@@ -90,4 +91,5 @@
 video/3gpp 3gpp!
 video/mpeg mpeg!
 video/quicktime mov!
+video/vnd.youtube.yt yt
 video/x-matroska mkv!
diff --git a/luni/src/main/java/libcore/util/HexEncoding.java b/luni/src/main/java/libcore/util/HexEncoding.java
index eceec6b..6d00074 100644
--- a/luni/src/main/java/libcore/util/HexEncoding.java
+++ b/luni/src/main/java/libcore/util/HexEncoding.java
@@ -23,17 +23,43 @@
 @libcore.api.CorePlatformApi
 public class HexEncoding {
 
+    private static final char[] LOWER_CASE_DIGITS = {
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+    };
+
+    private static final char[] UPPER_CASE_DIGITS = {
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+    };
+
     /** Hidden constructor to prevent instantiation. */
     private HexEncoding() {}
 
-    private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
+    /**
+     * Encodes the provided byte as a two-digit hexadecimal String value.
+     */
+    @libcore.api.CorePlatformApi
+    public static String encodeToString(byte b, boolean upperCase) {
+        char[] digits = upperCase ? UPPER_CASE_DIGITS : LOWER_CASE_DIGITS;
+        char[] buf = new char[2]; // We always want two digits.
+        buf[0] = digits[(b >> 4) & 0xf];
+        buf[1] = digits[b & 0xf];
+        return new String(buf, 0, 2);
+    }
 
     /**
      * Encodes the provided data as a sequence of hexadecimal characters.
      */
     @libcore.api.CorePlatformApi
     public static char[] encode(byte[] data) {
-        return encode(data, 0, data.length);
+        return encode(data, 0, data.length, true /* upperCase */);
+    }
+
+    /**
+     * Encodes the provided data as a sequence of hexadecimal characters.
+     */
+    @libcore.api.CorePlatformApi
+    public static char[] encode(byte[] data, boolean upperCase) {
+        return encode(data, 0, data.length, upperCase);
     }
 
     /**
@@ -41,12 +67,20 @@
      */
     @libcore.api.CorePlatformApi
     public static char[] encode(byte[] data, int offset, int len) {
+        return encode(data, offset, len, true /* upperCase */);
+    }
+
+    /**
+     * Encodes the provided data as a sequence of hexadecimal characters.
+     */
+    private static char[] encode(byte[] data, int offset, int len, boolean upperCase) {
+        char[] digits = upperCase ? UPPER_CASE_DIGITS : LOWER_CASE_DIGITS;
         char[] result = new char[len * 2];
         for (int i = 0; i < len; i++) {
             byte b = data[offset + i];
             int resultIndex = 2 * i;
-            result[resultIndex] = (HEX_DIGITS[(b >>> 4) & 0x0f]);
-            result[resultIndex + 1] = (HEX_DIGITS[b & 0x0f]);
+            result[resultIndex] = (digits[(b >> 4) & 0x0f]);
+            result[resultIndex + 1] = (digits[b & 0x0f]);
         }
 
         return result;
@@ -57,7 +91,15 @@
      */
     @libcore.api.CorePlatformApi
     public static String encodeToString(byte[] data) {
-        return new String(encode(data));
+        return encodeToString(data, true /* upperCase */);
+    }
+
+    /**
+     * Encodes the provided data as a sequence of hexadecimal characters.
+     */
+    @libcore.api.CorePlatformApi
+    public static String encodeToString(byte[] data, boolean upperCase) {
+        return new String(encode(data, upperCase));
     }
 
     /**
@@ -78,7 +120,9 @@
      *
      * Throws an {@code IllegalArgumentException} if the input is malformed.
      */
-    public static byte[] decode(String encoded, boolean allowSingleChar) throws IllegalArgumentException {
+    @libcore.api.CorePlatformApi
+    public static byte[] decode(String encoded, boolean allowSingleChar)
+            throws IllegalArgumentException {
         return decode(encoded.toCharArray(), allowSingleChar);
     }
 
@@ -101,25 +145,28 @@
      * Throws an {@code IllegalArgumentException} if the input is malformed.
      */
     @libcore.api.CorePlatformApi
-    public static byte[] decode(char[] encoded, boolean allowSingleChar) throws IllegalArgumentException {
-        int resultLengthBytes = (encoded.length + 1) / 2;
+    public static byte[] decode(char[] encoded, boolean allowSingleChar)
+            throws IllegalArgumentException {
+        int encodedLength = encoded.length;
+        int resultLengthBytes = (encodedLength + 1) / 2;
         byte[] result = new byte[resultLengthBytes];
 
         int resultOffset = 0;
         int i = 0;
         if (allowSingleChar) {
-            if ((encoded.length % 2) != 0) {
-                // Odd number of digits -- the first digit is the lower 4 bits of the first result byte.
+            if ((encodedLength % 2) != 0) {
+                // Odd number of digits -- the first digit is the lower 4 bits of the first result
+                // byte.
                 result[resultOffset++] = (byte) toDigit(encoded, i);
                 i++;
             }
         } else {
-            if ((encoded.length % 2) != 0) {
-                throw new IllegalArgumentException("Invalid input length: " + encoded.length);
+            if ((encodedLength % 2) != 0) {
+                throw new IllegalArgumentException("Invalid input length: " + encodedLength);
             }
         }
 
-        for (int len = encoded.length; i < len; i += 2) {
+        for (; i < encodedLength; i += 2) {
             result[resultOffset++] = (byte) ((toDigit(encoded, i) << 4) | toDigit(encoded, i + 1));
         }
 
@@ -139,7 +186,6 @@
             return 10 + (pseudoCodePoint - 'A');
         }
 
-        throw new IllegalArgumentException("Illegal char: " + str[offset] +
-                " at offset " + offset);
+        throw new IllegalArgumentException("Illegal char: " + str[offset] + " at offset " + offset);
     }
 }
diff --git a/luni/src/main/java/libcore/util/ZoneInfo.java b/luni/src/main/java/libcore/util/ZoneInfo.java
index 65df611..abd98b1 100644
--- a/luni/src/main/java/libcore/util/ZoneInfo.java
+++ b/luni/src/main/java/libcore/util/ZoneInfo.java
@@ -37,8 +37,9 @@
  * Our concrete TimeZone implementation, backed by zoneinfo data.
  *
  * <p>This reads time zone information from a binary file stored on the platform. The binary file
- * is essentially a single file containing compacted versions of all the tzfile (see
- * {@code man 5 tzfile} for details of the source) and an index by long name, e.g. Europe/London.
+ * is essentially a single file containing compacted versions of all the tzfiles produced by the
+ * zone info compiler (zic) tool (see {@code man 5 tzfile} for details of the format and
+ * {@code man 8 zic}) and an index by long name, e.g. Europe/London.
  *
  * <p>The compacted form is created by {@code external/icu/tools/ZoneCompactor.java} and is used
  * by both this and Bionic. {@link ZoneInfoDB} is responsible for mapping the binary file, and
@@ -307,6 +308,8 @@
 
         // Use the latest non-daylight offset (if any) as the raw offset.
         if (mTransitions.length == 0) {
+            // This case is no longer expected to occur in the data used on Android after changes
+            // made in zic version 2014c. It is kept as a fallback.
             // If there are no transitions then use the first GMT offset.
             mRawOffset = gmtOffsets[0];
         } else {
diff --git a/luni/src/test/java/libcore/android/system/OsTest.java b/luni/src/test/java/libcore/android/system/OsTest.java
index 7536885..dd5e698 100644
--- a/luni/src/test/java/libcore/android/system/OsTest.java
+++ b/luni/src/test/java/libcore/android/system/OsTest.java
@@ -56,6 +56,7 @@
 import junit.framework.TestCase;
 
 import libcore.io.IoUtils;
+import libcore.testing.io.TestIoUtils;
 
 import static android.system.OsConstants.*;
 
@@ -81,7 +82,7 @@
             int flags = Os.fcntlVoid(fis.getFD(), F_GETFD);
             assertTrue((flags & FD_CLOEXEC) != 0);
         } finally {
-            IoUtils.closeQuietly(fis);
+            TestIoUtils.closeQuietly(fis);
             f.delete();
         }
     }
@@ -1133,7 +1134,7 @@
     }
 
     public void test_readlink() throws Exception {
-        File path = new File(IoUtils.createTemporaryDirectory("test_readlink"), "symlink");
+        File path = new File(TestIoUtils.createTemporaryDirectory("test_readlink"), "symlink");
 
         // ext2 and ext4 have PAGE_SIZE limits on symlink targets.
         // If file encryption is enabled, there's extra overhead to store the
@@ -1251,7 +1252,7 @@
                 android.system.Os.sendfile(outFd, inFd, offset, maxBytes);
                 assertEquals(expectedEndOffset, offset == null ? null : offset.value);
             }
-            return IoUtils.readFileAsString(out.getPath());
+            return TestIoUtils.readFileAsString(out.getPath());
         } finally {
             out.delete();
         }
@@ -1307,7 +1308,7 @@
             assertEquals(5, offOut.value);
         }
 
-        assertEquals("oobar", IoUtils.readFileAsString(out.getPath()));
+        assertEquals("oobar", TestIoUtils.readFileAsString(out.getPath()));
 
         Os.close(pipe[0]);
         Os.close(pipe[1]);
diff --git a/luni/src/test/java/libcore/java/io/ObjectStreamClassTest.java b/luni/src/test/java/libcore/java/io/ObjectStreamClassTest.java
index 612b7d8..8bee284 100644
--- a/luni/src/test/java/libcore/java/io/ObjectStreamClassTest.java
+++ b/luni/src/test/java/libcore/java/io/ObjectStreamClassTest.java
@@ -16,6 +16,7 @@
 package libcore.java.io;
 
 import java.io.ObjectStreamClass;
+import java.io.ObjectStreamClass.DefaultSUIDCompatibilityListener;
 import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -31,6 +32,7 @@
 import org.junit.runners.MethodSorters;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 @RunWith(JUnitParamsRunner.class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -99,8 +101,6 @@
         // The default SUID for the InheritStaticInitializer should be affected by the b/29064453
         // patch and so should differ between version <= 23 and version > 23.
         { InheritStaticInitializer.class, 4188245044387716731L, 992629205079295334L },
-
-
     };
   }
 
@@ -108,27 +108,46 @@
   @Test
   public void computeDefaultSUID_current(Class<?> clazz, long suid,
       @SuppressWarnings("unused") long suid23) {
-    checkSerialVersionUID(suid, clazz);
+    checkSerialVersionUID(suid, clazz, false);
   }
 
   @Parameters(method = "defaultSUIDs")
   @Test
   @TargetSdkVersion(23)
-  public void computeDefaultSUID_targetSdkVersion_23(Class<?> clazz,
-      @SuppressWarnings("unused") long suid, long suid23) {
-    checkSerialVersionUID(suid23, clazz);
+  public void computeDefaultSUID_targetSdkVersion_23(Class<?> clazz, long suid, long suid23) {
+    // If the suid and suid23 hashes are different then a warning is expected to be logged.
+    boolean expectedWarning = suid23 != suid;
+    checkSerialVersionUID(suid23, clazz, expectedWarning);
   }
 
-  private static void checkSerialVersionUID(long expectedSUID, Class<?> clazz) {
-    // Use reflection to access the private static computeDefaultSUID method.
+  private static void checkSerialVersionUID(
+      long expectedSUID, Class<?> clazz, boolean expectedWarning) {
+    // Use reflection to call the private static computeDefaultSUID method directly to avoid the
+    // caching performed by ObjectStreamClass.lookup(Class).
     long defaultSUID;
+    DefaultSUIDCompatibilityListener savedListener
+        = ObjectStreamClass.suidCompatibilityListener;
     try {
+      ObjectStreamClass.suidCompatibilityListener = (c, hash) -> {
+        // Delegate to the existing listener so that the warning is logged.
+        savedListener.warnDefaultSUIDTargetVersionDependent(clazz, hash);
+        if (expectedWarning) {
+          assertEquals(clazz, c);
+          assertEquals(expectedSUID, hash);
+        } else {
+          fail("Unexpected warning for " + c + " with defaultSUID " + hash);
+        }
+      };
+
       Method computeDefaultSUIDMethod =
           ObjectStreamClass.class.getDeclaredMethod("computeDefaultSUID", Class.class);
       computeDefaultSUIDMethod.setAccessible(true);
+
       defaultSUID = (Long) computeDefaultSUIDMethod.invoke(null, clazz);
     } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
       throw new IllegalStateException(e);
+    } finally {
+      ObjectStreamClass.suidCompatibilityListener = savedListener;
     }
     assertEquals(expectedSUID, defaultSUID);
   }
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 7320d9a..c440ebe 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -781,4 +781,18 @@
             fail();
         } catch (NullPointerException expected) {}
     }
+
+    /**
+     * Check that String.format() does not throw when the default locale is invalid.
+     * http://b/129070579
+     */
+    public void testFormat_invalidLocale() {
+        Locale defaultLocale = Locale.getDefault();
+        try {
+            Locale.setDefault(new Locale("invalidLocale"));
+            String.format("%s", "");
+        } finally {
+            Locale.setDefault(defaultLocale);
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/ThrowableTest.java b/luni/src/test/java/libcore/java/lang/ThrowableTest.java
index 3479a22..74b1956 100644
--- a/luni/src/test/java/libcore/java/lang/ThrowableTest.java
+++ b/luni/src/test/java/libcore/java/lang/ThrowableTest.java
@@ -16,13 +16,22 @@
 
 package libcore.java.lang;
 
+import java.io.ObjectStreamClass;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.Arrays;
-import junit.framework.TestCase;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.SwitchTargetSdkVersionRule;
+import libcore.junit.util.SwitchTargetSdkVersionRule.TargetSdkVersion;
 import libcore.libcore.util.SerializationTester;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
-public class ThrowableTest extends TestCase {
+public class ThrowableTest extends TestCaseWithRules {
+
+    @Rule
+    public TestRule switchTargetSdkVersionRule = SwitchTargetSdkVersionRule.getInstance();
+
     private static class NoStackTraceException extends Exception {
         @Override
         public synchronized Throwable fillInStackTrace() {
@@ -315,6 +324,32 @@
         }.test();
     }
 
+    /**
+     * Detect issue that caused b/109930347
+     *
+     * <p>Due to a bug in the default serialVersionUID calculation that is used for apps with
+     * targetSdkVersion <= 23 changes in {@link Throwable} can affect the default SUID for
+     * subclasses of {@link Throwable}.
+     *
+     * <p>This test protects against changes in Throwable (e.g. removing Android specific patches)
+     * that would cause a change in the default SUID of Throwable subclasses in apps with
+     * targetSdkVersion <= 23. It does so by checking the default SUID for a Throwable subclass,
+     * computed as by an app with targetSdkVersion <= 23, against a known good value.
+     */
+    @TargetSdkVersion(23)
+    public void testThrowableSubclassSerialVersionUIDComputation_target23() {
+        ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(ThrowableSubclass.class);
+        assertEquals(
+            "SerialVersionUID computation for Throwable subclass is broken for targetSdkVersion 23",
+            -1036450421582688704L, objectStreamClass.getSerialVersionUID());
+    }
+
+    public static class ThrowableSubclass extends Throwable {
+        public ThrowableSubclass(String message) {
+            super(message);
+        }
+    }
+
     private void assertSerialized(final Throwable throwable, String golden) {
         new SerializationTester<Throwable>(throwable, golden) {
             @Override protected boolean equals(Throwable a, Throwable b) {
diff --git a/luni/src/test/java/libcore/java/net/AuditInputStream.java b/luni/src/test/java/libcore/java/net/AuditInputStream.java
new file mode 100644
index 0000000..2a76cac
--- /dev/null
+++ b/luni/src/test/java/libcore/java/net/AuditInputStream.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 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.net;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Objects;
+
+/**
+ * An {@link InputStream} that reads from a delegate and also writes an audit log of all data
+ * that was read to the given {@code audit} {@link OutputStream}.
+ */
+class AuditInputStream extends FilterInputStream {
+    private final OutputStream audit;
+
+    protected AuditInputStream(InputStream in, OutputStream audit) {
+        super(in);
+        this.audit = Objects.requireNonNull(audit);
+    }
+
+    @Override
+    public int read() throws IOException {
+        int result = super.read();
+        audit.write(result);
+        return result;
+    }
+
+    @Override
+    public int read(byte[] b) throws IOException {
+        int result = super.read(b);
+        if (result > 0) {
+            audit.write(b, 0, result);
+        }
+        return result;
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        int result = super.read(b, off, len);
+        if (result > 0) {
+            audit.write(b, off, result);
+        }
+        return result;
+    }
+}
diff --git a/luni/src/test/java/libcore/java/net/InetAddressTest.java b/luni/src/test/java/libcore/java/net/InetAddressTest.java
index 307cd1d..88f03d4 100644
--- a/luni/src/test/java/libcore/java/net/InetAddressTest.java
+++ b/luni/src/test/java/libcore/java/net/InetAddressTest.java
@@ -36,6 +36,7 @@
 import junitparams.JUnitParamsRunner;
 import junitparams.Parameters;
 import libcore.libcore.util.SerializationTester;
+import libcore.net.InetAddressUtils;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -312,8 +313,12 @@
     public void test_getByName_invalid(String invalid) throws Exception {
         try {
             InetAddress.getByName(invalid);
-            fail("Invalid IP address incorrectly recognized as valid: "
-                + invalid);
+            String msg = "Invalid IP address incorrectly recognized as valid: \"" + invalid + "\"";
+            if (InetAddressUtils.parseNumericAddressNoThrowStripOptionalBrackets(invalid) == null) {
+                msg += " (it was probably unexpectedly resolved by this network's DNS)";
+            }
+            msg += ".";
+            fail(msg);
         } catch (UnknownHostException expected) {
         }
 
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 1574caf..c29ba09 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -19,6 +19,7 @@
 import com.google.mockwebserver.Dispatcher;
 import com.google.mockwebserver.MockResponse;
 import com.google.mockwebserver.MockWebServer;
+import com.google.mockwebserver.QueueDispatcher;
 import com.google.mockwebserver.RecordedRequest;
 import com.google.mockwebserver.SocketPolicy;
 
@@ -57,6 +58,7 @@
 import java.net.URLConnection;
 import java.net.UnknownHostException;
 import java.nio.channels.SocketChannel;
+import java.nio.charset.StandardCharsets;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
@@ -88,6 +90,7 @@
 import javax.net.ssl.X509TrustManager;
 import libcore.java.security.TestKeyStore;
 import libcore.javax.net.ssl.TestSSLContext;
+import libcore.testing.io.TestIoUtils;
 
 import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END;
 import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_START;
@@ -342,7 +345,7 @@
         server.enqueue(new MockResponse().setResponseCode(404).setBody("A"));
         server.play();
         HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection.getErrorStream(), Integer.MAX_VALUE));
+        assertEquals("A", readAscii(connection.getErrorStream()));
     }
 
     // Check that if we don't read to the end of a response, the next request on the
@@ -408,10 +411,10 @@
         server.play();
 
         URLConnection connection1 = server.getUrl("/").openConnection();
-        assertEquals("ABC", readAscii(connection1.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("ABC", readAscii(connection1.getInputStream()));
         assertEquals(0, server.takeRequest().getSequenceNumber());
         URLConnection connection2 = server.getUrl("/").openConnection();
-        assertEquals("DEF", readAscii(connection2.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("DEF", readAscii(connection2.getInputStream()));
         assertEquals(1, server.takeRequest().getSequenceNumber());
     }
 
@@ -593,7 +596,7 @@
 
         connection = (HttpsURLConnection) server.getUrl("/").openConnection();
         try {
-            readAscii(connection.getInputStream(), Integer.MAX_VALUE);
+            readAscii(connection.getInputStream());
             fail("without an SSL socket factory, the connection should fail");
         } catch (SSLException expected) {
         }
@@ -1127,6 +1130,105 @@
         }
     }
 
+    public void testDisconnectFromBackgroundThread_blockedRead_beforeHeader()
+            throws IOException {
+        QueueDispatcher dispatcher = new QueueDispatcher() {
+            @Override
+            public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
+                Thread.sleep(6000);
+                return super.dispatch(request);
+            }
+        };
+        server.setDispatcher(dispatcher);
+        server.enqueue(new MockResponse().setHeader("Key", "Value").setBody("Response body"));
+        checkDisconnectFromBackgroundThread_blockedRead(2000, null /* disconnectMillis */);
+    }
+
+    public void testDisconnectFromBackgroundThread_blockedRead_beforeBody()
+            throws IOException {
+        server.enqueue(new MockResponse().setHeader("Key", "Value")
+                .setBody("Response body").setBodyDelayTimeMs(6000));
+        checkDisconnectFromBackgroundThread_blockedRead(2000, "" /* disconnectMillis */);
+    }
+
+    /**
+     *
+     * @throws IOException
+     */
+    public void testDisconnectFromBackgroundThread_blockedRead_duringBody()
+            throws IOException {
+        server.enqueue(new MockResponse().setHeader("Key", "Value")
+                .setBody("Response body").throttleBody(3, 1333, TimeUnit.MILLISECONDS));
+        // After 2 sec, we should have read about 6 bytes (we sleep 1333msec after every 3 bytes).
+        checkDisconnectFromBackgroundThread_blockedRead(2000, "Respon");
+    }
+
+    /**
+     * Checks that {@link HttpURLConnection#disconnect() disconnecting} a blocked read
+     * from a background thread unblocks the reading thread quickly and that the headers/body
+     * read so far are as given.
+     *
+     * The disconnect happens after approximately {@code disconnectMillis} msec (between half
+     * and double that is tolerated), so the server must already be set up such that reading
+     * the headers and the entire request takes comfortably more than that, eg.
+     * {@code 3 * disconnectMillis}.
+     *
+     * @param disconnectMillis number of milliseconds until the connection should be
+     *        {@link HttpURLConnection#disconnect() disconnected} by a background thread.
+     * @param expectedResponseContent The part of the body that is expected to have been read by
+     *        the time the connection is disconnected, or null if not even the headers
+     *        are expected to have been read at the time.
+     * @throws IOException if one occurs unexpectedly while establishing the connection.
+     */
+    private void checkDisconnectFromBackgroundThread_blockedRead(
+            long disconnectMillis, String expectedResponseContent) throws IOException {
+        server.play();
+        HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
+
+        Thread disconnectThread = new Thread("Disconnect after " + disconnectMillis + "msec") {
+            @Override
+            public void run() {
+                try {
+                    Thread.sleep(disconnectMillis);
+                } catch (InterruptedException e) {
+                    // Even if an AssertionFailedError on this background thread doesn't
+                    // cause the test to fail directly, we'd still prematurely disconnect()
+                    // and that would (if significant) be detected further down by the
+                    // assertion on the number of elapsed milliseconds observed by the
+                    // main thread.
+                    fail("Unexpectedly interrupted: " + e);
+                }
+                connection.disconnect();
+            }
+        };
+
+        ByteArrayOutputStream auditStream = new ByteArrayOutputStream();
+        AuditInputStream inputStream = null;
+        boolean headerRead = false;
+        long start = System.currentTimeMillis();
+        disconnectThread.start();
+        try {
+            inputStream = new AuditInputStream(connection.getInputStream(), auditStream);
+            connection.getHeaderFields();
+            headerRead = true;
+            readAscii(inputStream);
+            fail("Didn't expect to successfully read all of the data");
+        } catch (IOException expected) {
+        } finally {
+            TestIoUtils.closeQuietly(inputStream);
+        }
+        long elapsed = System.currentTimeMillis() - start;
+
+        assertTrue("Expected approx. " + disconnectMillis + " msec elapsed, got " + elapsed,
+                disconnectMillis / 2 <= elapsed && elapsed <= 2 * disconnectMillis);
+        String readBody = new String(auditStream.toByteArray(), StandardCharsets.UTF_8);
+
+        String actualResponse = headerRead ? readBody : null;
+        assertEquals("Headers read: " + headerRead + "; read response body: " +  readBody,
+                expectedResponseContent, actualResponse);
+    }
+
+
     // http://b/33763156
     public void testDisconnectDuringConnect_getInputStream() throws IOException {
         checkDisconnectDuringConnect(HttpURLConnection::getInputStream);
@@ -1223,7 +1325,7 @@
      * exhausted before {@code count} characters can be read, the remaining
      * characters are returned and the stream is closed.
      */
-    private String readAscii(InputStream in, int count) throws IOException {
+    private static String readAscii(InputStream in, int count) throws IOException {
         StringBuilder result = new StringBuilder();
         for (int i = 0; i < count; i++) {
             int value = in.read();
@@ -1236,6 +1338,10 @@
         return result.toString();
     }
 
+    private static String readAscii(InputStream in) throws IOException {
+        return readAscii(in, Integer.MAX_VALUE);
+    }
+
     public void testMarkAndResetWithContentLengthHeader() throws IOException {
         testMarkAndReset(TransferKind.FIXED_LENGTH);
     }
@@ -1264,7 +1370,7 @@
             fail();
         } catch (IOException expected) {
         }
-        assertEquals("FGHIJKLMNOPQRSTUVWXYZ", readAscii(in, Integer.MAX_VALUE));
+        assertEquals("FGHIJKLMNOPQRSTUVWXYZ", readAscii(in));
         assertContent("ABCDEFGHIJKLMNOPQRSTUVWXYZ", server.getUrl("/").openConnection());
     }
 
@@ -1301,7 +1407,7 @@
 
         URLConnection connection = server.getUrl("/").openConnection();
         try {
-            readAscii(connection.getInputStream(), Integer.MAX_VALUE);
+            readAscii(connection.getInputStream());
             fail();
         } catch (IOException e) {
         }
@@ -1317,7 +1423,7 @@
 
         URLConnection connection = server.getUrl("/").openConnection();
         try {
-            readAscii(connection.getInputStream(), Integer.MAX_VALUE);
+            readAscii(connection.getInputStream());
             fail();
         } catch (IOException e) {
         }
@@ -1335,7 +1441,7 @@
         server.play();
 
         URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("ABCABCABC", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("ABCABCABC", readAscii(connection.getInputStream()));
         assertNull(connection.getContentEncoding());
         assertEquals(-1, connection.getContentLength());
 
@@ -1354,7 +1460,7 @@
         URLConnection connection = server.getUrl("/").openConnection();
         connection.addRequestProperty("Accept-Encoding", "gzip");
         InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream());
-        assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", readAscii(gunzippedIn, Integer.MAX_VALUE));
+        assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", readAscii(gunzippedIn));
         assertEquals(bodyBytes.length, connection.getContentLength());
 
         RecordedRequest request = server.takeRequest();
@@ -1378,7 +1484,7 @@
 
         URLConnection connection = server.getUrl("/").openConnection();
         connection.addRequestProperty("Accept-Encoding", "custom");
-        assertEquals("ABCDE", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("ABCDE", readAscii(connection.getInputStream()));
 
         RecordedRequest request = server.takeRequest();
         assertContains(request.getHeaders(), "Accept-Encoding: custom");
@@ -1403,11 +1509,11 @@
         URLConnection connection = server.getUrl("/").openConnection();
         connection.addRequestProperty("Accept-Encoding", "gzip");
         InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream());
-        assertEquals("one (gzipped)", readAscii(gunzippedIn, Integer.MAX_VALUE));
+        assertEquals("one (gzipped)", readAscii(gunzippedIn));
         assertEquals(0, server.takeRequest().getSequenceNumber());
 
         connection = server.getUrl("/").openConnection();
-        assertEquals("two (identity)", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("two (identity)", readAscii(connection.getInputStream()));
         assertEquals(1, server.takeRequest().getSequenceNumber());
     }
 
@@ -1428,7 +1534,7 @@
         assertContent("", connection1);
 
         HttpURLConnection connection2 = (HttpURLConnection) server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection2.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("A", readAscii(connection2.getInputStream()));
 
         assertEquals(0, server.takeRequest().getSequenceNumber());
         assertEquals(1, server.takeRequest().getSequenceNumber());
@@ -1564,7 +1670,7 @@
         server.enqueue(new MockResponse().setBody("A"));
         server.play();
         HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("A", readAscii(connection.getInputStream()));
         try {
             connection.setFixedLengthStreamingMode(1);
             fail();
@@ -1576,7 +1682,7 @@
         server.enqueue(new MockResponse().setBody("A"));
         server.play();
         HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("A", readAscii(connection.getInputStream()));
         try {
             connection.setChunkedStreamingMode(1);
             fail();
@@ -1636,7 +1742,7 @@
         OutputStream outputStream = connection.getOutputStream();
         outputStream.write(requestBody);
         outputStream.close();
-        assertEquals("Success!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("Success!", readAscii(connection.getInputStream()));
 
         RecordedRequest request = server.takeRequest();
         assertEquals("POST / HTTP/1.1", request.getRequestLine());
@@ -1672,7 +1778,7 @@
         OutputStream outputStream = connection.getOutputStream();
         outputStream.write(requestBody);
         outputStream.close();
-        assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("Successful auth!", readAscii(connection.getInputStream()));
 
         // no authorization header for the first request...
         RecordedRequest request = server.takeRequest();
@@ -1704,7 +1810,7 @@
         SimpleAuthenticator authenticator = new SimpleAuthenticator();
         Authenticator.setDefault(authenticator);
         HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("Successful auth!", readAscii(connection.getInputStream()));
         assertEquals(Authenticator.RequestorType.SERVER, authenticator.requestorType);
         assertEquals(server.getPort(), authenticator.requestingPort);
         assertEquals(InetAddress.getByName(server.getHostName()), authenticator.requestingSite);
@@ -1742,7 +1848,7 @@
         SimpleAuthenticator authenticator = new SimpleAuthenticator();
         Authenticator.setDefault(authenticator);
         HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("Successful auth!", readAscii(connection.getInputStream()));
         assertEquals(Authenticator.RequestorType.SERVER, authenticator.requestorType);
         assertEquals(server.getPort(), authenticator.requestingPort);
         assertEquals(InetAddress.getByName(server.getHostName()), authenticator.requestingSite);
@@ -1765,7 +1871,7 @@
         authenticator.expectedPrompt = "b";
         Authenticator.setDefault(authenticator);
         HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("Successful auth!", readAscii(connection.getInputStream()));
 
         assertContainsNoneMatching(server.takeRequest().getHeaders(), "Authorization: .*");
         assertContains(server.takeRequest().getHeaders(),
@@ -1787,7 +1893,7 @@
         authenticator.expectedPrompt = "b";
         Authenticator.setDefault(authenticator);
         HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("Successful auth!", readAscii(connection.getInputStream()));
 
         assertContainsNoneMatching(server.takeRequest().getHeaders(), "Authorization: .*");
         assertContains(server.takeRequest().getHeaders(),
@@ -1817,8 +1923,7 @@
         server.play();
 
         URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("This is the new location!",
-                readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("This is the new location!", readAscii(connection.getInputStream()));
 
         RecordedRequest first = server.takeRequest();
         assertEquals("GET / HTTP/1.1", first.getRequestLine());
@@ -1841,8 +1946,7 @@
 
         HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
         connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("This is the new location!",
-                readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("This is the new location!", readAscii(connection.getInputStream()));
 
         RecordedRequest first = server.takeRequest();
         assertEquals("GET / HTTP/1.1", first.getRequestLine());
@@ -1862,8 +1966,7 @@
 
         HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
         connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("This page has moved!",
-                readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("This page has moved!", readAscii(connection.getInputStream()));
     }
 
     public void testNotRedirectedFromHttpToHttps() throws IOException, InterruptedException {
@@ -1874,8 +1977,7 @@
         server.play();
 
         HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        assertEquals("This page has moved!",
-                readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("This page has moved!", readAscii(connection.getInputStream()));
     }
 
     public void testRedirectToAnotherOriginServer() throws Exception {
@@ -1891,13 +1993,11 @@
         server.play();
 
         URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("This is the 2nd server!",
-                readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("This is the 2nd server!", readAscii(connection.getInputStream()));
         assertEquals(server2.getUrl("/"), connection.getURL());
 
         // make sure the first server was careful to recycle the connection
-        assertEquals("This is the first server again!",
-                readAscii(server.getUrl("/").openStream(), Integer.MAX_VALUE));
+        assertEquals("This is the first server again!", readAscii(server.getUrl("/").openStream()));
 
         RecordedRequest first = server.takeRequest();
         assertContains(first.getHeaders(), "Host: " + hostName + ":" + server.getPort());
@@ -1963,7 +2063,7 @@
 
         try {
             HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-            assertEquals("Target", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+            assertEquals("Target", readAscii(connection.getInputStream()));
 
             // Inspect the redirect request to see what request was actually made.
             RecordedRequest actualRequest = server2.takeRequest();
@@ -2051,7 +2151,7 @@
         OutputStream outputStream = connection.getOutputStream();
         outputStream.write(requestBody);
         outputStream.close();
-        assertEquals("Page 2", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("Page 2", readAscii(connection.getInputStream()));
         assertTrue(connection.getDoOutput());
 
         RecordedRequest page1 = server.takeRequest();
@@ -2072,8 +2172,7 @@
 
         HttpURLConnection connection = (HttpURLConnection) server.getUrl("/foo").openConnection();
         // Fails on the RI, which gets "Proxy Response"
-        assertEquals("This page has moved!",
-                readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("This page has moved!", readAscii(connection.getInputStream()));
 
         RecordedRequest page1 = server.takeRequest();
         assertEquals("GET /foo HTTP/1.1", page1.getRequestLine());
@@ -2099,9 +2198,9 @@
             server.play();
 
             URL url = server.getUrl("/");
-            assertEquals("ABC", readAscii(url.openStream(), Integer.MAX_VALUE));
-            assertEquals("DEF", readAscii(url.openStream(), Integer.MAX_VALUE));
-            assertEquals("GHI", readAscii(url.openStream(), Integer.MAX_VALUE));
+            assertEquals("ABC", readAscii(url.openStream()));
+            assertEquals("DEF", readAscii(url.openStream()));
+            assertEquals("GHI", readAscii(url.openStream()));
 
             assertEquals(Arrays.asList("verify " + hostName), hostnameVerifier.calls);
             assertEquals(Arrays.asList("checkServerTrusted ["
@@ -2270,8 +2369,7 @@
         server.play();
 
         URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("This is the new location!",
-                readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("This is the new location!", readAscii(connection.getInputStream()));
 
         assertEquals(0, server.takeRequest().getSequenceNumber());
         assertEquals("When connection: close is used, each request should get its own connection",
@@ -2285,8 +2383,7 @@
         server.play();
 
         URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("This body is not allowed!",
-                readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("This body is not allowed!", readAscii(connection.getInputStream()));
     }
 
     public void testSingleByteReadIsSigned() throws IOException {
@@ -2333,7 +2430,7 @@
 
         OutputStream out = connection.getOutputStream();
         out.write(upload);
-        assertEquals("abc", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("abc", readAscii(connection.getInputStream()));
 
         out.flush(); // dubious but permitted
         try {
@@ -2370,7 +2467,7 @@
         // Read timeout of a day, sure to cause the test to timeout and fail.
         connection.setReadTimeout(24 * 3600 * 1000);
         InputStream input = connection.getInputStream();
-        assertEquals("ABC", readAscii(input, Integer.MAX_VALUE));
+        assertEquals("ABC", readAscii(input));
         input.close();
         try {
             connection = server.getUrl("").openConnection();
@@ -2677,7 +2774,7 @@
         server.play();
         HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
         InputStream in = (InputStream) connection.getContent();
-        assertEquals("A", readAscii(in, Integer.MAX_VALUE));
+        assertEquals("A", readAscii(in));
     }
 
     public void testGetContentOfType() throws Exception {
@@ -2761,7 +2858,7 @@
         OutputStream out = connection.getOutputStream();
         out.write(new byte[] { 'A', 'B', 'C' });
         out.close();
-        assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+        assertEquals("A", readAscii(connection.getInputStream()));
         RecordedRequest request = server.takeRequest();
         assertContains(request.getHeaders(), "Content-Length: 3");
     }
@@ -2799,7 +2896,7 @@
         server.enqueue(new MockResponse().setBody("A"));
         server.play();
         URL url = new URL("http", server.getHostName(), server.getPort(), "?query");
-        assertEquals("A", readAscii(url.openConnection().getInputStream(), Integer.MAX_VALUE));
+        assertEquals("A", readAscii(url.openConnection().getInputStream()));
         RecordedRequest request = server.takeRequest();
         assertEquals("GET /?query HTTP/1.1", request.getRequestLine());
     }
diff --git a/luni/src/test/java/libcore/java/util/DateTest.java b/luni/src/test/java/libcore/java/util/DateTest.java
index df86a38..9cd9868 100644
--- a/luni/src/test/java/libcore/java/util/DateTest.java
+++ b/luni/src/test/java/libcore/java/util/DateTest.java
@@ -50,10 +50,15 @@
         c.clear();
         c.set(Calendar.YEAR, 21);
         assertEquals("Wed Jan 01 00:00:00 PST 21", c.getTime().toString());
-        assertEquals("1 Jan 21 08:00:00 GMT", c.getTime().toGMTString());
+        String actual21GmtString = c.getTime().toGMTString();
+        // zic <= 2014b data produces -08:00:00, later ones produce -07:52:58 instead.
+        assertEquals("1 Jan 21 07:52:58 GMT", actual21GmtString);
+
         c.set(Calendar.YEAR, 321);
         assertEquals("Sun Jan 01 00:00:00 PST 321", c.getTime().toString());
-        assertEquals("1 Jan 321 08:00:00 GMT", c.getTime().toGMTString());
+        String actual321GmtString = c.getTime().toGMTString();
+        // zic <= 2014b data produces -08:00:00, later ones produce -07:52:58 instead.
+        assertEquals("1 Jan 321 07:52:58 GMT", actual321GmtString);
     }
 
     public void test_toGMTString_nonUs() throws Exception {
@@ -64,10 +69,15 @@
         c.clear();
         c.set(Calendar.YEAR, 21);
         assertEquals("Wed Jan 01 00:00:00 PST 21", c.getTime().toString());
-        assertEquals("1 Jan 21 08:00:00 GMT", c.getTime().toGMTString());
+        String actual21GmtString = c.getTime().toGMTString();
+        // zic <= 2014b data produces -08:00:00, later ones produce -07:52:58 instead.
+        assertEquals("1 Jan 21 07:52:58 GMT", actual21GmtString);
+
         c.set(Calendar.YEAR, 321);
         assertEquals("Sun Jan 01 00:00:00 PST 321", c.getTime().toString());
-        assertEquals("1 Jan 321 08:00:00 GMT", c.getTime().toGMTString());
+        String actual321GmtString = c.getTime().toGMTString();
+        // zic <= 2014b data produces -08:00:00, later ones produce -07:52:58 instead.
+        assertEquals("1 Jan 321 07:52:58 GMT", actual321GmtString);
     }
 
     public void test_parse_timezones() {
diff --git a/luni/src/test/java/libcore/java/util/TimeZoneTest.java b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
index 68b6a54..481766c 100644
--- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
@@ -58,7 +58,30 @@
     }
 
     // http://code.google.com/p/android/issues/detail?id=14395
-    public void testPreHistoricInDaylightTime() throws Exception {
+    public void testPreHistoricInDaylightTime() {
+        // A replacement for testPreHistoricInDaylightTime_old() using a zone that still lacks an
+        // explicit transition at Integer.MIN_VALUE with zic 2019a and 2019a data.
+        TimeZone tz = TimeZone.getTimeZone("CET");
+
+        long firstTransitionTimeMillis = -1693706400000L; // Apr 30, 1916 22:00:00 GMT
+        assertEquals(7200000L, tz.getOffset(firstTransitionTimeMillis));
+        assertTrue(tz.inDaylightTime(new Date(firstTransitionTimeMillis)));
+
+        long beforeFirstTransitionTimeMillis = firstTransitionTimeMillis - 1;
+        assertEquals(3600000L, tz.getOffset(beforeFirstTransitionTimeMillis));
+        assertFalse(tz.inDaylightTime(new Date(beforeFirstTransitionTimeMillis)));
+    }
+
+    // http://code.google.com/p/android/issues/detail?id=14395
+    public void testPreHistoricInDaylightTime_old() throws Exception {
+        // Originally this test was intended to assert what happens when the first transition for a
+        // time zone was a "to DST" transition. i.e. that the (implicit) offset / DST state before
+        // the first was treated as a non-DST state. Since zic version 2014c some zones have an
+        // explicit non-DST transition at time -2^31 seconds so it is no longer possible to test
+        // this with America/Los_Angeles.
+        // This regression test has been kept in case that changes again in future and to prove the
+        // behavior has remained consistent.
+
         Locale.setDefault(Locale.US);
         TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
         TimeZone.setDefault(tz);
@@ -69,7 +92,7 @@
         assertFalse(tz.inDaylightTime(date));
         assertEquals("Fri Oct 31 08:00:00 PST 1902", date.toString());
         assertEquals("31 Oct 1902 16:00:00 GMT", date.toGMTString());
-        // Any time before we have transition data is considered non-daylight, even in summer.
+        // For zic versions <= 2014b, this would be before the first transition.
         date = sdf.parse("1902-06-01T00:00:00.000+0800");
         assertEquals(-28800000, tz.getOffset(date.getTime()));
         assertFalse(tz.inDaylightTime(date));
@@ -84,17 +107,20 @@
     public void testPreHistoricOffsets() throws Exception {
         // Note: This test changed after P to account for previously incorrect handling of
         // prehistoric offsets. http://b/118835133
-        // "Africa/Bissau" has just a few transitions:
-        // Date, Offset, IsDst
-        // 1901-12-13 20:45:52,-3740,0 (Integer.MIN_VALUE, implicit with zic <= 2014b)
-        // 1912-01-01 01:00:00,-3600,0
-        // 1975-01-01 01:00:00,0,0
+        // "Africa/Bissau" has just a few known transitions:
+        // Transition time             : Offset    : DST / non-DST
+        // <Integer.MIN_VALUE secs>[1] : -01:02:20 : non-DST
+        // 1912-01-01 01:00:00 GMT     : -01:00:00 : non-DST
+        // 1975-01-01 01:00:00 GMT     :  00:00:00 : non-DST
+        //
+        // [1] This transition can be implicit or explicit depending on the version of zic used to
+        // generate the data. When implicit, the first non-DST type defn should be used.
         TimeZone tz = TimeZone.getTimeZone("Africa/Bissau");
 
-        // Before Integer.MIN_VALUE.
+        // Times before Integer.MIN_VALUE should assume we're using the first non-DST type.
         assertNonDaylightOffset(-3740, parseIsoTime("1900-01-01T00:00:00.0+0000"), tz);
 
-        // Times before 1912-01-01 01:00:00
+        // Time before 1912-01-01 01:00:00 but after Integer.MIN_VALUE.
         assertNonDaylightOffset(-3740, parseIsoTime("1911-01-01T00:00:00.0+0000"), tz);
 
         // Times after 1912-01-01 01:00:00 should use that transition.
@@ -104,19 +130,22 @@
         assertNonDaylightOffset(0, parseIsoTime("1980-01-01T00:00:00.0+0000"), tz);
     }
 
-    private static void assertNonDaylightOffset(int expectedOffsetSeconds, long epochSeconds, TimeZone tz) {
-        assertEquals(expectedOffsetSeconds, tz.getOffset(epochSeconds * 1000) / 1000);
-        assertFalse(tz.inDaylightTime(new Date(epochSeconds * 1000)));
+    private static void assertNonDaylightOffset(
+            int expectedOffsetSeconds, long epochMillis, TimeZone tz) {
+        assertEquals(expectedOffsetSeconds, tz.getOffset(epochMillis) / 1000);
+        assertFalse(tz.inDaylightTime(new Date(epochMillis)));
     }
 
+    /** Returns the millis elapsed since the beginning of the Unix epoch. */
     private static long parseIsoTime(String isoTime) throws Exception {
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
         Date date = sdf.parse(isoTime);
-        return date.getTime() / 1000;
+        return date.getTime();
     }
 
-    public void testZeroTransitionZones() throws Exception {
-        // Zones with no transitions historical or future seem ideal for testing.
+    public void testMinimalTransitionZones() throws Exception {
+        // Zones with minimal transitions, historical or future, seem ideal for testing.
+        // UTC is also included, although it may be implemented differently from the others.
         String[] ids = new String[] { "Africa/Bujumbura", "Indian/Cocos", "Pacific/Wake", "UTC" };
         for (String id : ids) {
             TimeZone tz = TimeZone.getTimeZone(id);
@@ -338,18 +367,16 @@
         final long lowerTimeMillis = beforeInt32Seconds * 1000L;
         final long upperTimeMillis = afterInt32Seconds * 1000L;
 
-        // This timezone didn't have any daylight savings prior to 1917 and this
-        // date is in 1900.
+        // This timezone didn't have any daylight savings prior to 1917 and this date is in 1900.
         assertFalse(tz.inDaylightTime(new Date(lowerTimeMillis)));
 
         // http://b/118835133:
         // zic <= 2014b produces data that suggests before -1633280400 seconds (Sun, 31 Mar 1918
         // 07:00:00 GMT) the offset was -18000000.
         // zic > 2014b produces data that suggests before Integer.MIN_VALUE seconds the offset was
-        // -17762000 and between Integer.MIN_VALUE and -1633280400 it was -18000000. Once Android
-        // moves to zic > 2014b the -18000000 can be removed.
+        // -17762000 and between Integer.MIN_VALUE and -1633280400 it was -18000000.
         int actualOffset = tz.getOffset(lowerTimeMillis);
-        assertTrue(-18000000 == actualOffset || -17762000 == actualOffset);
+        assertEquals(-17762000, actualOffset);
 
         // Nov 30th 2039, no daylight savings as per current rules.
         assertFalse(tz.inDaylightTime(new Date(upperTimeMillis)));
diff --git a/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java b/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
index f5be28b..607397d 100644
--- a/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
+++ b/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
@@ -138,4 +138,12 @@
     LocaleData haw = LocaleData.get(new Locale("haw"));
     assertFalse(haw.shortDateFormat.isEmpty());
   }
+
+  /**
+   * Check that LocaleData.get() does not throw when the input locale is invalid.
+   * http://b/129070579
+   */
+  public void testInvalidLocale() {
+    LocaleData.get(new Locale("invalidLocale"));
+  }
 }
diff --git a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
index 91d7c3a..0e2c6b5 100644
--- a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
+++ b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
@@ -16,6 +16,12 @@
 
 package libcore.libcore.io;
 
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.IPPROTO_TCP;
+import static android.system.OsConstants.IPPROTO_UDP;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_STREAM;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -24,9 +30,12 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import android.system.ErrnoException;
 import android.system.OsConstants;
 import android.system.StructAddrinfo;
 
+import java.io.FileDescriptor;
+import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.net.InetAddress;
@@ -38,6 +47,8 @@
 import java.util.regex.Pattern;
 
 import libcore.io.BlockGuardOs;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
 import libcore.io.Os;
 
 import dalvik.system.BlockGuard;
@@ -47,6 +58,8 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -58,22 +71,42 @@
 
     @Mock private Os mockOsDelegate;
     @Mock private BlockGuard.Policy mockThreadPolicy;
+    @Mock private BlockGuard.VmPolicy mockVmPolicy;
 
     private BlockGuard.Policy savedThreadPolicy;
+    private BlockGuard.VmPolicy savedVmPolicy;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         savedThreadPolicy = BlockGuard.getThreadPolicy();
+        savedVmPolicy = BlockGuard.getVmPolicy();
         BlockGuard.setThreadPolicy(mockThreadPolicy);
+        BlockGuard.setVmPolicy(mockVmPolicy);
     }
 
     @After
     public void tearDown() {
+        BlockGuard.setVmPolicy(savedVmPolicy);
         BlockGuard.setThreadPolicy(savedThreadPolicy);
     }
 
     @Test
+    public void test_blockguardOsIsNotifiedByDefault_rename() {
+        String oldPath = "BlockGuardOsTest/missing/old/path";
+        String newPath = "BlockGuardOsTest/missing/new/path";
+        try {
+            // We try not to be prescriptive about the exact default Os implementation.
+            // Whatever default Os is installed, we do expect BlockGuard to be called.
+            Os.getDefault().rename(oldPath, newPath);
+        } catch (ErrnoException ignored) {
+        }
+        verify(mockThreadPolicy).onWriteToDisk();
+        verify(mockVmPolicy).onPathAccess(oldPath);
+        verify(mockVmPolicy).onPathAccess(newPath);
+    }
+
+    @Test
     public void test_android_getaddrinfo_networkPolicy() {
         InetAddress[] addresses = new InetAddress[] { InetAddress.getLoopbackAddress() };
         when(mockOsDelegate.android_getaddrinfo(anyString(), any(), anyInt()))
@@ -109,6 +142,31 @@
         }
     }
 
+    @Test
+    public void test_connect_networkPolicy() throws ErrnoException, IOException {
+        BlockGuardOs blockGuardOs = new BlockGuardOs(mockOsDelegate);
+
+        // Test connect with a UDP socket that will not trigger a network policy check.
+        FileDescriptor udpSocket = Libcore.os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+        try {
+            blockGuardOs.connect(udpSocket, InetAddress.getLoopbackAddress(), 0);
+            verify(mockThreadPolicy, never()).onNetwork();
+            verify(mockOsDelegate, times(1)).connect(eq(udpSocket), any(), anyInt());
+        } finally {
+            IoUtils.closeQuietly(udpSocket);
+        }
+
+        // Test connect with a TCP socket that will trigger a network policy check.
+        FileDescriptor tcpSocket = Libcore.os.socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+        try {
+            blockGuardOs.connect(tcpSocket, InetAddress.getLoopbackAddress(), 0);
+            verify(mockThreadPolicy, times(1)).onNetwork();
+            verify(mockOsDelegate, times(1)).connect(eq(tcpSocket), any(), anyInt());
+        } finally {
+            IoUtils.closeQuietly(tcpSocket);
+        }
+    }
+
     /**
      * Checks that BlockGuardOs is updated when the Os interface changes. BlockGuardOs extends
      * ForwardingOs so doing so isn't an obvious step and it can be missed. When adding methods to
diff --git a/luni/src/test/java/libcore/libcore/io/OsTest.java b/luni/src/test/java/libcore/libcore/io/OsTest.java
index 0b66d96..6359f87 100644
--- a/luni/src/test/java/libcore/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/libcore/io/OsTest.java
@@ -18,7 +18,6 @@
 
 import junit.framework.TestCase;
 
-import libcore.io.BlockGuardOs;
 import libcore.io.ForwardingOs;
 import libcore.io.Os;
 
@@ -26,11 +25,6 @@
 
 public class OsTest extends TestCase {
 
-    public void testGetDefault_instanceofBlockguardOs() {
-        Os os = Os.getDefault();
-        assertTrue(os.getClass().toString(), os instanceof BlockGuardOs);
-    }
-
     public void testCompareAndSetDefault_success() throws Exception {
         Os defaultOs = Os.getDefault();
         Os mockOs = Mockito.mock(Os.class);
diff --git a/luni/src/test/java/libcore/libcore/net/MimeUtilsTest.java b/luni/src/test/java/libcore/libcore/net/MimeUtilsTest.java
index cf1e233..26be32b 100644
--- a/luni/src/test/java/libcore/libcore/net/MimeUtilsTest.java
+++ b/luni/src/test/java/libcore/libcore/net/MimeUtilsTest.java
@@ -90,8 +90,13 @@
         assertEquals("video/ogg", MimeUtils.guessMimeTypeFromExtension("ogv"));
     }
 
-    public void test_70851634() {
-        assertEquals("application/vnd.youtube.yt", MimeUtils.guessMimeTypeFromExtension("yt"));
+    public void test_70851634_mimeTypeFromExtension() {
+        assertEquals("video/vnd.youtube.yt", MimeUtils.guessMimeTypeFromExtension("yt"));
+    }
+
+    public void test_70851634_extensionFromMimeType() {
+        assertEquals("yt", MimeUtils.guessExtensionFromMimeType("video/vnd.youtube.yt"));
+        assertEquals("yt", MimeUtils.guessExtensionFromMimeType("application/vnd.youtube.yt"));
     }
 
     public void test_112162449_audio() {
diff --git a/luni/src/test/java/libcore/libcore/timezone/ZoneInfoDBTest.java b/luni/src/test/java/libcore/libcore/timezone/ZoneInfoDBTest.java
index 3f4791c..ef70236 100644
--- a/luni/src/test/java/libcore/libcore/timezone/ZoneInfoDBTest.java
+++ b/luni/src/test/java/libcore/libcore/timezone/ZoneInfoDBTest.java
@@ -18,7 +18,6 @@
 
 import java.io.File;
 import java.io.FileOutputStream;
-import java.io.IOException;
 import java.io.RandomAccessFile;
 
 import libcore.timezone.TimeZoneDataFiles;
diff --git a/luni/src/test/java/libcore/libcore/util/HexEncodingTest.java b/luni/src/test/java/libcore/libcore/util/HexEncodingTest.java
index 4de1a01..800928f 100644
--- a/luni/src/test/java/libcore/libcore/util/HexEncodingTest.java
+++ b/luni/src/test/java/libcore/libcore/util/HexEncodingTest.java
@@ -18,28 +18,69 @@
 
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Locale;
+
 import junit.framework.TestCase;
 import static libcore.util.HexEncoding.decode;
 import static libcore.util.HexEncoding.encode;
+import static libcore.util.HexEncoding.encodeToString;
 
 public class HexEncodingTest extends TestCase {
-  public void testEncode() {
-    final byte[] avocados = "avocados".getBytes(StandardCharsets.UTF_8);
 
-    assertArraysEqual("61766F6361646F73".toCharArray(), encode(avocados));
-    assertArraysEqual(avocados, decode(encode(avocados), false));
-    // Make sure we can handle lower case hex encodings as well.
-    assertArraysEqual(avocados, decode("61766f6361646f73".toCharArray(), false));
+  public void testEncodeByte() {
+    Object[][] testCases = new Object[][] {
+        { 0x01, "01" },
+        { 0x09, "09" },
+        { 0x0A, "0A" },
+        { 0x0F, "0F" },
+        { 0x10, "10" },
+        { 0x1F, "1F" },
+        { 0x20, "20" },
+        { 0x7F, "7F" },
+        { 0x80, "80" },
+        { 0xFF, "FF" },
+    };
+    for (Object[] testCase : testCases) {
+      Number toEncode = (Number) testCase[0];
+      String expected = (String) testCase[1];
+
+      String actualUpper = encodeToString(toEncode.byteValue(), true /* upperCase */);
+      assertEquals(upper(expected), actualUpper);
+
+      String actualLower = encodeToString(toEncode.byteValue(), false /* upperCase */);
+      assertEquals(lower(expected), actualLower);
+    }
+  }
+
+  public void testEncodeBytes() {
+    Object[][] testCases = new Object[][] {
+        { "avocados".getBytes(StandardCharsets.UTF_8), "61766F6361646F73" },
+    };
+
+    for (Object[] testCase : testCases) {
+      byte[] bytes = (byte[]) testCase[0];
+      String encodedLower = lower((String) testCase[1]);
+      String encodedUpper = upper((String) testCase[1]);
+
+      assertArraysEqual(encodedUpper.toCharArray(), encode(bytes));
+      assertArraysEqual(encodedUpper.toCharArray(), encode(bytes, true /* upperCase */));
+      assertArraysEqual(encodedLower.toCharArray(), encode(bytes, false /* upperCase */));
+
+      assertArraysEqual(bytes, decode(encode(bytes), false /* allowSingleChar */));
+
+      // Make sure we can handle lower case hex encodings as well.
+      assertArraysEqual(bytes, decode(encodedLower.toCharArray(), false /* allowSingleChar */));
+    }
   }
 
   public void testDecode_allow4Bit() {
     assertArraysEqual(new byte[] { 6 }, decode("6".toCharArray(), true));
-    assertArraysEqual(new byte[] { 6, 'v' }, decode("676".toCharArray(), true));
+    assertArraysEqual(new byte[] { 6, 0x76 }, decode("676".toCharArray(), true));
   }
 
   public void testDecode_disallow4Bit() {
     try {
-      decode("676".toCharArray(), false);
+      decode("676".toCharArray(), false /* allowSingleChar */);
       fail();
     } catch (IllegalArgumentException expected) {
     }
@@ -47,7 +88,7 @@
 
   public void testDecode_invalid() {
     try {
-      decode("DEADBARD".toCharArray(), false);
+      decode("DEADBARD".toCharArray(), false /* allowSingleChar */);
       fail();
     } catch (IllegalArgumentException expected) {
     }
@@ -56,13 +97,13 @@
     // commons uses Character.isDigit and would successfully decode a string with
     // arabic and devanagari characters.
     try {
-      decode("६१٧٥٥F6361646F73".toCharArray(), false);
+      decode("६१٧٥٥F6361646F73".toCharArray(), false /* allowSingleChar */);
       fail();
     } catch (IllegalArgumentException expected) {
     }
 
     try {
-      decode("#%6361646F73".toCharArray(), false);
+      decode("#%6361646F73".toCharArray(), false /* allowSingleChar */);
       fail();
     } catch (IllegalArgumentException expected) {
     }
@@ -75,4 +116,12 @@
   private static void assertArraysEqual(byte[] lhs, byte[] rhs) {
     assertEquals(Arrays.toString(lhs), Arrays.toString(rhs));
   }
+
+  private static String lower(String string) {
+    return string.toLowerCase(Locale.ROOT);
+  }
+
+  private static String upper(String string) {
+    return string.toUpperCase(Locale.ROOT);
+  }
 }
diff --git a/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java b/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java
index a151ee4..cddf41b 100644
--- a/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java
+++ b/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java
@@ -322,6 +322,7 @@
    * <p>Newer versions of zic after 2014b introduce an explicit transition at the earliest
    * representable time, which is Integer.MIN_VALUE for TZif version 1 files. Previously the type
    * used was left implicit and readers were expected to use the first non-DST type in the file.
+   * This extra transition mostly went away again with zic 2018f.
    *
    * <p>Testing newer zic versions demonstrated that Android had been mishandling the lookup of
    * offset for times before the first transition. The logic has been corrected. This test would
@@ -357,8 +358,8 @@
             { offsetToSeconds(type2Offset), 0 },
     };
 
-    // Creates a simulation of zic version <= 2014b where there is usually no explicit transition at
-    // Integer.MIN_VALUE seconds in TZif version 1 data.
+    // Creates a simulation of zic version <= 2014b or zic version >= 2018f where there is often
+    // no explicit transition at Integer.MIN_VALUE seconds in TZif version 1 data.
     {
       int[][] transitions = {
               { timeToSeconds(firstRealTransitionTime), 2 /* type 2 */ },
@@ -374,8 +375,8 @@
       assertOffsetAt(oldZoneInfo, type2Offset, afterFirstRealTransitionTimes);
     }
 
-    // Creates a simulation of zic version > 2014b where there is usually an explicit transition at
-    // Integer.MIN_VALUE seconds for TZif version 1 data.
+    // Creates a simulation of zic version > 2014b and zic version < 2018f where there is usually an
+    // explicit transition at Integer.MIN_VALUE seconds for TZif version 1 data.
     {
       int[][] transitions = {
               { Integer.MIN_VALUE, 1 /* type 1 */ }, // The extra transition added by zic.
diff --git a/mmodules/core_platform_api/api/platform/current-api.txt b/mmodules/core_platform_api/api/platform/current-api.txt
index 9e3515a..da717bd 100644
--- a/mmodules/core_platform_api/api/platform/current-api.txt
+++ b/mmodules/core_platform_api/api/platform/current-api.txt
@@ -71,11 +71,6 @@
 
 package android.system {
 
-  public final class ErrnoException extends java.lang.Exception {
-    method public java.io.IOException rethrowAsIOException() throws java.io.IOException;
-    method public java.net.SocketException rethrowAsSocketException() throws java.net.SocketException;
-  }
-
   public class Int32Ref {
     ctor public Int32Ref(int);
     field @dalvik.annotation.compat.UnsupportedAppUsage public int value;
@@ -748,6 +743,7 @@
     method public void setHiddenApiExemptions(String[]);
     method public static void setHiddenApiUsageLogger(dalvik.system.VMRuntime.HiddenApiUsageLogger);
     method public static void setNonSdkApiUsageConsumer(java.util.function.Consumer<java.lang.String>);
+    method public static void setProcessDataDirectory(String);
     method public static void setProcessPackageName(String);
     method @dalvik.annotation.compat.UnsupportedAppUsage public float setTargetHeapUtilization(float);
     method public void setTargetSdkVersion(int);
@@ -804,10 +800,6 @@
 
 package java.lang {
 
-  public final class Byte extends java.lang.Number implements java.lang.Comparable<java.lang.Byte> {
-    method public static String toHexString(byte, boolean);
-  }
-
   public final class Class<T> implements java.lang.reflect.AnnotatedElement java.lang.reflect.GenericDeclaration java.io.Serializable java.lang.reflect.Type {
     method @dalvik.annotation.optimization.FastNative public java.lang.reflect.Field[] getDeclaredFieldsUnchecked(boolean);
     method @dalvik.annotation.optimization.FastNative public java.lang.reflect.Method[] getDeclaredMethodsUnchecked(boolean);
@@ -1227,11 +1219,15 @@
 
   public class HexEncoding {
     method public static byte[] decode(String) throws java.lang.IllegalArgumentException;
+    method public static byte[] decode(String, boolean) throws java.lang.IllegalArgumentException;
     method public static byte[] decode(char[]) throws java.lang.IllegalArgumentException;
     method public static byte[] decode(char[], boolean) throws java.lang.IllegalArgumentException;
     method public static char[] encode(byte[]);
+    method public static char[] encode(byte[], boolean);
     method public static char[] encode(byte[], int, int);
+    method public static String encodeToString(byte, boolean);
     method public static String encodeToString(byte[]);
+    method public static String encodeToString(byte[], boolean);
   }
 
   public class NativeAllocationRegistry {
@@ -1366,6 +1362,18 @@
     method public static sun.misc.Cleaner create(Object, Runnable);
   }
 
+  public final class Unsafe {
+    method public int arrayBaseOffset(Class);
+    method @dalvik.annotation.optimization.FastNative public byte getByte(Object, long);
+    method @dalvik.annotation.optimization.FastNative public byte getByte(long);
+    method @dalvik.annotation.optimization.FastNative public long getLong(Object, long);
+    method @dalvik.annotation.optimization.FastNative public long getLong(long);
+    method public static sun.misc.Unsafe getUnsafe();
+    method public long objectFieldOffset(java.lang.reflect.Field);
+    method @dalvik.annotation.optimization.FastNative public void putByte(Object, long, byte);
+    method @dalvik.annotation.optimization.FastNative public void putByte(long, byte);
+  }
+
 }
 
 package sun.security.jca {
diff --git a/mmodules/intracoreapi/api/intra/current-api.txt b/mmodules/intracoreapi/api/intra/current-api.txt
index a7a2fdc..9780457 100644
--- a/mmodules/intracoreapi/api/intra/current-api.txt
+++ b/mmodules/intracoreapi/api/intra/current-api.txt
@@ -1,12 +1,4 @@
 // Signature format: 2.0
-package android.system {
-
-  public final class ErrnoException extends java.lang.Exception {
-    method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public java.net.SocketException rethrowAsSocketException() throws java.net.SocketException;
-  }
-
-}
-
 package com.android.org.conscrypt {
 
   @libcore.api.IntraCoreApi public class DESEDESecretKeyFactory extends javax.crypto.SecretKeyFactorySpi {
diff --git a/ojluni/Android.bp b/ojluni/Android.bp
new file mode 100644
index 0000000..20a5a5a
--- /dev/null
+++ b/ojluni/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2019 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.
+
+// 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: [
+        "core-oj",
+    ],
+}
diff --git a/ojluni/Android.mk b/ojluni/Android.mk
deleted file mode 100644
index 8eef8b5..0000000
--- a/ojluni/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- mode: makefile -*-
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ojluni-phony
-include $(BUILD_PHONY_PACKAGE)
-
diff --git a/ojluni/annotations/mmodule/java/lang/Byte.annotated.java b/ojluni/annotations/mmodule/java/lang/Byte.annotated.java
deleted file mode 100644
index 2d61598..0000000
--- a/ojluni/annotations/mmodule/java/lang/Byte.annotated.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-
-package java.lang;
-
-
-@SuppressWarnings({"unchecked", "deprecation", "all"})
-public final class Byte extends java.lang.Number implements java.lang.Comparable<java.lang.Byte> {
-
-public Byte(byte value) { throw new RuntimeException("Stub!"); }
-
-public Byte(java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public static java.lang.String toString(byte b) { throw new RuntimeException("Stub!"); }
-
-public static java.lang.Byte valueOf(byte b) { throw new RuntimeException("Stub!"); }
-
-public static byte parseByte(java.lang.String s, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public static byte parseByte(java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public static java.lang.Byte valueOf(java.lang.String s, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public static java.lang.Byte valueOf(java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public static java.lang.Byte decode(java.lang.String nm) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public byte byteValue() { throw new RuntimeException("Stub!"); }
-
-public short shortValue() { throw new RuntimeException("Stub!"); }
-
-public int intValue() { throw new RuntimeException("Stub!"); }
-
-public long longValue() { throw new RuntimeException("Stub!"); }
-
-public float floatValue() { throw new RuntimeException("Stub!"); }
-
-public double doubleValue() { throw new RuntimeException("Stub!"); }
-
-public java.lang.String toString() { throw new RuntimeException("Stub!"); }
-
-public int hashCode() { throw new RuntimeException("Stub!"); }
-
-public static int hashCode(byte value) { throw new RuntimeException("Stub!"); }
-
-public boolean equals(java.lang.Object obj) { throw new RuntimeException("Stub!"); }
-
-public int compareTo(java.lang.Byte anotherByte) { throw new RuntimeException("Stub!"); }
-
-public static int compare(byte x, byte y) { throw new RuntimeException("Stub!"); }
-
-public static int toUnsignedInt(byte x) { throw new RuntimeException("Stub!"); }
-
-public static long toUnsignedLong(byte x) { throw new RuntimeException("Stub!"); }
-
-@libcore.api.CorePlatformApi
-public static java.lang.String toHexString(byte b, boolean upperCase) { throw new RuntimeException("Stub!"); }
-
-public static final int BYTES = 1; // 0x1
-
-public static final byte MAX_VALUE = 127; // 0x7f
-
-public static final byte MIN_VALUE = -128; // 0xffffff80
-
-public static final int SIZE = 8; // 0x8
-
-public static final java.lang.Class<java.lang.Byte> TYPE;
-static { TYPE = null; }
-}
-
diff --git a/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java b/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java
new file mode 100644
index 0000000..f272a9a
--- /dev/null
+++ b/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.misc;
+
+@libcore.api.CorePlatformApi
+@libcore.api.Hide
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public final class Unsafe {
+
+    private Unsafe() {
+        throw new RuntimeException("Stub!");
+    }
+
+    @libcore.api.CorePlatformApi
+    public static sun.misc.Unsafe getUnsafe() {
+        throw new RuntimeException("Stub!");
+    }
+
+    @libcore.api.CorePlatformApi
+    public long objectFieldOffset(java.lang.reflect.Field field) {
+        throw new RuntimeException("Stub!");
+    }
+
+    @libcore.api.CorePlatformApi
+    public int arrayBaseOffset(java.lang.Class clazz) {
+        throw new RuntimeException("Stub!");
+    }
+
+    @libcore.api.CorePlatformApi
+    public native byte getByte(java.lang.Object obj, long offset);
+
+    @libcore.api.CorePlatformApi
+    public native byte getByte(long address);
+
+    @libcore.api.CorePlatformApi
+    public native long getLong(java.lang.Object obj, long offset);
+
+    @libcore.api.CorePlatformApi
+    public native long getLong(long address);
+
+    @libcore.api.CorePlatformApi
+    public native void putByte(java.lang.Object obj, long offset, byte newValue);
+
+    @libcore.api.CorePlatformApi
+    public native void putByte(long address, byte x);
+}
diff --git a/ojluni/src/main/java/java/io/ObjectStreamClass.java b/ojluni/src/main/java/java/io/ObjectStreamClass.java
index 7561aa8..10babed 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamClass.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamClass.java
@@ -1797,15 +1797,27 @@
                 }
             }
 
-            // Android-changed: Clinit serialization workaround b/29064453
+            // BEGIN Android-changed: Fix/log clinit serialization workaround b/29064453
             // Prior to SDK 24 hasStaticInitializer() would return true if the superclass had a
             // static initializer, that was contrary to the specification. In SDK 24 the default
             // behavior was corrected but the old behavior was preserved for apps that targeted 23
             // or below in order to maintain backwards compatibility.
+            //
+            // if (hasStaticInitializer(cl)) {
             boolean inheritStaticInitializer =
                 (VMRuntime.getRuntime().getTargetSdkVersion()
                 <= MAX_SDK_TARGET_FOR_CLINIT_UIDGEN_WORKAROUND);
+            boolean warnIncompatibleSUIDChange = false;
             if (hasStaticInitializer(cl, inheritStaticInitializer)) {
+                // If a static initializer was found but the current class does not have one then
+                // the class's default SUID will change if the app targets SDK > 24 so send a
+                // warning.
+                if (inheritStaticInitializer && !hasStaticInitializer(cl, false)) {
+                    // Defer until hash has been calculated so the warning message can give precise
+                    // instructions to the developer on how to fix the problems.
+                    warnIncompatibleSUIDChange = true;
+                }
+                // END Android-changed: Fix/log clinit serialization workaround b/29064453
                 dout.writeUTF("<clinit>");
                 dout.writeInt(Modifier.STATIC);
                 dout.writeUTF("()V");
@@ -1870,6 +1882,14 @@
             for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
                 hash = (hash << 8) | (hashBytes[i] & 0xFF);
             }
+            // BEGIN Android-added: Fix/log clinit serialization workaround b/29064453
+            // ObjectStreamClass instances are cached per Class and caches its default
+            // serialVersionUID so it will only log one message per class per app process
+            // irrespective of the number of times the class is serialized.
+            if (warnIncompatibleSUIDChange) {
+                suidCompatibilityListener.warnDefaultSUIDTargetVersionDependent(cl, hash);
+            }
+            // END Android-added: Fix/log clinit serialization workaround b/29064453
             return hash;
         } catch (IOException ex) {
             throw new InternalError(ex);
@@ -1878,8 +1898,38 @@
         }
     }
 
-    // BEGIN Android-changed: Clinit serialization workaround b/29064453
-    /** Max SDK target version for which we use buggy hasStaticIntializier implementation. */
+    // BEGIN Android-changed: Fix/log clinit serialization workaround b/29064453
+    /**
+     * Created for testing as there is no nice way to detect when a message is logged.
+     *
+     * @hide
+     */
+    public interface DefaultSUIDCompatibilityListener {
+        /**
+         * Called when a class being serialized/deserialized relies on the default SUID computation
+         * (because it has no explicit {@code serialVersionUID} field) where that computation is
+         * dependent on the app's targetSdkVersion.
+         *
+         * @param clazz the clazz for which the default SUID is being computed.
+         * @param hash the computed value.
+         */
+        void warnDefaultSUIDTargetVersionDependent(Class<?> clazz, long hash);
+    }
+
+    /**
+     * Public and mutable for testing purposes.
+     *
+     * @hide
+     */
+    public static DefaultSUIDCompatibilityListener suidCompatibilityListener =
+        (clazz, hash) -> {
+            System.logW("Class " + clazz.getCanonicalName() + " relies on its default SUID which"
+                + " is dependent on the app's targetSdkVersion. To avoid problems during upgrade"
+                + " add the following to class " + clazz.getCanonicalName() + "\n"
+                + "    private static final long serialVersionUID = " + hash + "L;");
+        };
+
+    /** Max SDK target version for which we use buggy hasStaticInitializer implementation. */
     static final int MAX_SDK_TARGET_FOR_CLINIT_UIDGEN_WORKAROUND = 23;
 
     /**
@@ -1893,7 +1943,7 @@
      */
     private native static boolean hasStaticInitializer(
         Class<?> cl, boolean inheritStaticInitializer);
-    // END Android-changed: Clinit serialization workaround b/29064453
+    // END Android-changed: Fix/log clinit serialization workaround b/29064453
 
     /**
      * Class for computing and caching field/constructor/method signatures
diff --git a/ojluni/src/main/java/java/lang/Byte.java b/ojluni/src/main/java/java/lang/Byte.java
index e53899c..deb4ecb 100644
--- a/ojluni/src/main/java/java/lang/Byte.java
+++ b/ojluni/src/main/java/java/lang/Byte.java
@@ -25,6 +25,8 @@
 
 package java.lang;
 
+import libcore.util.HexEncoding;
+
 /**
  *
  * The {@code Byte} class wraps a value of primitive type {@code byte}
@@ -523,24 +525,8 @@
      * @hide
      */
     public static String toHexString(byte b, boolean upperCase) {
-        char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
-        char[] buf = new char[2]; // We always want two digits.
-        buf[0] = digits[(b >> 4) & 0xf];
-        buf[1] = digits[b & 0xf];
-        return new String(0, 2, buf);
+        // This method currently retained because it is marked @UnsupportedAppUsage.
+        return HexEncoding.encodeToString(b, upperCase);
     }
-    private static final char[] DIGITS = {
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
-        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
-        'u', 'v', 'w', 'x', 'y', 'z'
-    };
-
-    private static final char[] UPPER_CASE_DIGITS = {
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
-        'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
-        'U', 'V', 'W', 'X', 'Y', 'Z'
-    };
     // END Android-added: toHexString() for internal use.
 }
diff --git a/ojluni/src/main/java/java/net/Inet6AddressImpl.java b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
index 6b22f8c..bb722f3 100644
--- a/ojluni/src/main/java/java/net/Inet6AddressImpl.java
+++ b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
@@ -44,6 +44,7 @@
 import static android.system.OsConstants.AI_ADDRCONFIG;
 import static android.system.OsConstants.EACCES;
 import static android.system.OsConstants.ECONNREFUSED;
+import static android.system.OsConstants.EPERM;
 import static android.system.OsConstants.NI_NAMEREQD;
 import static android.system.OsConstants.ICMP6_ECHO_REPLY;
 import static android.system.OsConstants.ICMP_ECHOREPLY;
@@ -144,7 +145,8 @@
             // SecurityException to aid in debugging this common mistake.
             // http://code.google.com/p/android/issues/detail?id=15722
             if (gaiException.getCause() instanceof ErrnoException) {
-                if (((ErrnoException) gaiException.getCause()).errno == EACCES) {
+                int errno = ((ErrnoException) gaiException.getCause()).errno;
+                if (errno == EACCES || errno == EPERM) {
                     throw new SecurityException("Permission denied (missing INTERNET permission?)", gaiException);
                 }
             }
diff --git a/ojluni/src/main/java/java/time/chrono/JapaneseEra.java b/ojluni/src/main/java/java/time/chrono/JapaneseEra.java
index 0c9e3e8..d52f3c1 100644
--- a/ojluni/src/main/java/java/time/chrono/JapaneseEra.java
+++ b/ojluni/src/main/java/java/time/chrono/JapaneseEra.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,11 +73,14 @@
 import java.io.Serializable;
 import java.time.DateTimeException;
 import java.time.LocalDate;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.TextStyle;
 import java.time.temporal.ChronoField;
 import java.time.temporal.TemporalField;
 import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.util.Arrays;
+import java.util.Locale;
 import java.util.Objects;
 
 import sun.util.calendar.CalendarDate;
@@ -85,10 +88,33 @@
 /**
  * An era in the Japanese Imperial calendar system.
  * <p>
- * This class defines the valid eras for the Japanese chronology.
- * Japan introduced the Gregorian calendar starting with Meiji 6.
- * Only Meiji and later eras are supported;
- * dates before Meiji 6, January 1 are not supported.
+ * The Japanese government defines the official name and start date of
+ * each era. Eras are consecutive and their date ranges do not overlap,
+ * so the end date of one era is always the day before the start date
+ * of the next era.
+ * <p>
+ * The Java SE Platform supports all eras defined by the Japanese government,
+ * beginning with the Meiji era. Each era is identified in the Platform by an
+ * integer value and a name. The {@link #of(int)} and {@link #valueOf(String)}
+ * methods may be used to obtain a singleton instance of JapaneseEra for each
+ * era. The {@link #values()} method returns the singleton instances of all
+ * supported eras.
+ * <p>
+ * For convenience, this class declares a number of public static final fields
+ * that refer to singleton instances returned by the values() method.
+ *
+ * @apiNote
+ * The fields declared in this class may evolve over time, in line with the
+ * results of the {@link #values()} method. However, there is not necessarily
+ * a 1:1 correspondence between the fields and the singleton instances.
+ *
+ * @apiNote
+ * The Japanese government may announce a new era and define its start
+ * date but not its official name. In this scenario, the singleton instance
+ * that represents the new era may return a name that is not stable until
+ * the official name is defined. Developers should exercise caution when
+ * relying on the name returned by any singleton instance that does not
+ * correspond to a public static final field.
  *
  * @implSpec
  * This class is immutable and thread-safe.
@@ -120,14 +146,20 @@
      */
     public static final JapaneseEra SHOWA = new JapaneseEra(1, LocalDate.of(1926, 12, 25));
     /**
-     * The singleton instance for the 'Heisei' era (1989-01-08 - current)
+     * The singleton instance for the 'Heisei' era (1989-01-08 - 2019-04-30)
      * which has the value 2.
      */
     public static final JapaneseEra HEISEI = new JapaneseEra(2, LocalDate.of(1989, 1, 8));
+    /**
+     * The singleton instance for the 'Reiwa' era (2019-05-01 - current)
+     * which has the value 3. The end date of this era is not specified, unless
+     * the Japanese Government defines it.
+     */
+    private static final JapaneseEra REIWA = new JapaneseEra(3, LocalDate.of(2019, 5, 1));
 
-    // the number of defined JapaneseEra constants.
-    // There could be an extra era defined in its configuration.
-    private static final int N_ERA_CONSTANTS = HEISEI.getValue() + ERA_OFFSET;
+    // The number of predefined JapaneseEra constants.
+    // There may be a supplemental era defined by the property.
+    private static final int N_ERA_CONSTANTS = REIWA.getValue() + ERA_OFFSET;
 
     /**
      * Serialization version.
@@ -145,6 +177,7 @@
         KNOWN_ERAS[1] = TAISHO;
         KNOWN_ERAS[2] = SHOWA;
         KNOWN_ERAS[3] = HEISEI;
+        KNOWN_ERAS[4] = REIWA;
         for (int i = N_ERA_CONSTANTS; i < ERA_CONFIG.length; i++) {
             CalendarDate date = ERA_CONFIG[i].getSinceDate();
             LocalDate isoDate = LocalDate.of(date.getYear(), date.getMonth(), date.getDayOfMonth());
@@ -185,10 +218,18 @@
     //-----------------------------------------------------------------------
     /**
      * Obtains an instance of {@code JapaneseEra} from an {@code int} value.
+      * <ul>
+      * <li>The value {@code 1} is associated with the 'Showa' era, because
+      * it contains 1970-01-01 (ISO calendar system).</li>
+      * <li>The values {@code -1} and {@code 0} are associated with two earlier
+      * eras, Meiji and Taisho, respectively.</li>
+      * <li>A value greater than {@code 1} is associated with a later era,
+      * beginning with Heisei ({@code 2}).</li>
+      * </ul>
      * <p>
-     * The {@link #SHOWA} era that contains 1970-01-01 (ISO calendar system) has the value 1
-     * Later era is numbered 2 ({@link #HEISEI}). Earlier eras are numbered 0 ({@link #TAISHO}),
-     * -1 ({@link #MEIJI}), only Meiji and later eras are supported.
+      * Every instance of {@code JapaneseEra} that is returned from the {@link #values()}
+      * method has an int value (available via {@link Era#getValue()} which is
+      * accepted by this method.
      *
      * @param japaneseEra  the era to represent
      * @return the {@code JapaneseEra} singleton, not null
@@ -236,6 +277,28 @@
         return Arrays.copyOf(KNOWN_ERAS, KNOWN_ERAS.length);
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * @param style {@inheritDoc}
+     * @param locale {@inheritDoc}
+     */
+    @Override
+    public String getDisplayName(TextStyle style, Locale locale) {
+        // If this JapaneseEra is a supplemental one, obtain the name from
+        // the era definition.
+        if (getValue() > N_ERA_CONSTANTS - ERA_OFFSET) {
+            Objects.requireNonNull(locale, "locale");
+            return style.asNormal() == TextStyle.NARROW ? getAbbreviation() : getName();
+        }
+
+        return new DateTimeFormatterBuilder()
+            .appendText(ERA, style)
+            .toFormatter(locale)
+            .withChronology(JapaneseChronology.INSTANCE)
+            .format(this == MEIJI ? MEIJI_6_ISODATE : since);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Obtains an instance of {@code JapaneseEra} from a date.
@@ -337,11 +400,7 @@
 
     //-----------------------------------------------------------------------
     String getAbbreviation() {
-        int index = ordinal(getValue());
-        if (index == 0) {
-            return "";
-        }
-        return ERA_CONFIG[index].getAbbreviation();
+        return ERA_CONFIG[ordinal(getValue())].getAbbreviation();
     }
 
     String getName() {
diff --git a/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java b/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
index c569981..a0ee15e 100644
--- a/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
+++ b/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@
  *     2       Taisho      1912-07-30 midnight local time
  *     3       Showa       1926-12-25 midnight local time
  *     4       Heisei      1989-01-08 midnight local time
+ *     5       Reiwa       2019-05-01 midnight local time
  * ------------------------------------------------------
  * </tt></pre>
  *
@@ -100,6 +101,11 @@
      */
     public static final int HEISEI = 4;
 
+    /**
+     * The ERA constant designating the Reiwa era.
+     */
+    private static final int REIWA = 5;
+
     private static final int EPOCH_OFFSET   = 719163; // Fixed date of January 1, 1970 (Gregorian)
     private static final int EPOCH_YEAR     = 1970;
 
@@ -132,6 +138,9 @@
     // Fixed date of the first date of each era.
     private static final long[] sinceFixedDates;
 
+    // The current era
+    private static final int currentEra;
+
     /*
      * <pre>
      *                                 Greatest       Least
@@ -227,13 +236,25 @@
         // eras[BEFORE_MEIJI] and sinceFixedDate[BEFORE_MEIJI] are the
         // same as Gregorian.
         int index = BEFORE_MEIJI;
+        // Android-removed: Zygote could initialize this class when system has outdated time.
+        // int current = index;
         sinceFixedDates[index] = gcal.getFixedDate(BEFORE_MEIJI_ERA.getSinceDate());
         eras[index++] = BEFORE_MEIJI_ERA;
         for (Era e : es) {
+            // Android-removed: Zygote could initialize this class when system has outdated time.
+            // Android hard-code the current era. Unlike upstream, Android does not add the new era
+            // in the code until the new era arrives. Thus, Android can't have newer era than the
+            // real world. currentEra is the latest Era that Android knows about.
+            // if(e.getSince(TimeZone.NO_TIMEZONE) < System.currentTimeMillis()) {
+            //     current = index;
+            // }
             CalendarDate d = e.getSinceDate();
             sinceFixedDates[index] = gcal.getFixedDate(d);
             eras[index++] = e;
         }
+        // Android-changed: Zygote could initialize this class when system has outdated time.
+        // currentEra = current;
+        currentEra = REIWA;
 
         LEAST_MAX_VALUES[ERA] = MAX_VALUES[ERA] = eras.length - 1;
 
@@ -1574,14 +1595,17 @@
             zoneOffsets = new int[2];
         }
         if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) {
-            // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+            // BEGIN Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
             // if (tz instanceof ZoneInfo) {
             //     zoneOffset = ((ZoneInfo)tz).getOffsets(time, zoneOffsets);
-            // } else {
+            if (tz instanceof libcore.util.ZoneInfo) {
+                zoneOffset = ((libcore.util.ZoneInfo)tz).getOffsetsByUtcTime(time, zoneOffsets);
+            // END Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+            } else {
                 zoneOffset = tz.getOffset(time);
                 zoneOffsets[0] = tz.getRawOffset();
                 zoneOffsets[1] = zoneOffset - zoneOffsets[0];
-            // }
+            }
         }
         if (tzMask != 0) {
             if (isFieldSet(tzMask, ZONE_OFFSET)) {
@@ -1713,12 +1737,12 @@
                     }
                 } else if (transitionYear) {
                     if (jdate.getYear() == 1) {
-                        // As of Heisei (since Meiji) there's no case
+                        // As of Reiwa (since Meiji) there's no case
                         // that there are multiple transitions in a
                         // year.  Historically there was such
                         // case. There might be such case again in the
                         // future.
-                        if (era > HEISEI) {
+                        if (era > REIWA) {
                             CalendarDate pd = eras[era - 1].getSinceDate();
                             if (normalizedYear == pd.getYear()) {
                                 d.setMonth(pd.getMonth()).setDayOfMonth(pd.getDayOfMonth());
@@ -1853,7 +1877,7 @@
             year = isSet(YEAR) ? internalGet(YEAR) : 1;
         } else {
             if (isSet(YEAR)) {
-                era = eras.length - 1;
+                era = currentEra;
                 year = internalGet(YEAR);
             } else {
                 // Equivalent to 1970 (Gregorian)
@@ -2338,7 +2362,7 @@
      * default ERA is the current era, but a zero (unset) ERA means before Meiji.
      */
     private int internalGetEra() {
-        return isSet(ERA) ? internalGet(ERA) : eras.length - 1;
+        return isSet(ERA) ? internalGet(ERA) : currentEra;
     }
 
     /**
diff --git a/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java b/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java
index 143fa5e..b71d11a 100644
--- a/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java
+++ b/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java
@@ -188,7 +188,6 @@
      */
     private static class NoPreloadHolder {
         public static HostnameVerifier defaultHostnameVerifier;
-        public static final Class<? extends HostnameVerifier> originalDefaultHostnameVerifierClass;
         static {
             try {
                 /**
@@ -200,7 +199,6 @@
                 defaultHostnameVerifier = (HostnameVerifier)
                         Class.forName("com.android.okhttp.internal.tls.OkHostnameVerifier")
                         .getField("INSTANCE").get(null);
-                originalDefaultHostnameVerifierClass = defaultHostnameVerifier.getClass();
             } catch (Exception e) {
                 throw new AssertionError("Failed to obtain okhttp HostnameVerifier", e);
             }
@@ -210,7 +208,7 @@
     /**
      * The <code>hostnameVerifier</code> for this object.
      */
-    protected HostnameVerifier hostnameVerifier;
+    protected HostnameVerifier hostnameVerifier = NoPreloadHolder.defaultHostnameVerifier;
     // END Android-changed: Use holder class idiom for a lazily-created OkHttp hostname verifier.
 
     // Android-changed: Modified the documentation to explain side effects / discourage method use.
@@ -329,15 +327,6 @@
      * @see #setDefaultHostnameVerifier(HostnameVerifier)
      */
     public HostnameVerifier getHostnameVerifier() {
-        // Android-added: Use the default verifier if none is set.
-        // Note that this also has the side effect of *setting* (if unset)
-        // hostnameVerifier to be the default one. It's not clear why this
-        // was done (commit abd00f0eaa46f71f98e75a631c268c812d1ec7c1) but
-        // we're keeping this behavior for lack of a strong reason to do
-        // otherwise.
-        if (hostnameVerifier == null) {
-            hostnameVerifier = NoPreloadHolder.defaultHostnameVerifier;
-        }
         return hostnameVerifier;
     }
 
diff --git a/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java b/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java
index ead18de..28b10c8 100644
--- a/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java
+++ b/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java
@@ -126,12 +126,14 @@
             // BEGIN Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
             // if (zi instanceof ZoneInfo) {
             //    zoneOffset = ((ZoneInfo)zi).getOffsets(millis, offsets);
-            // } else {
+            if (zi instanceof libcore.util.ZoneInfo) {
+                zoneOffset = ((libcore.util.ZoneInfo) zi).getOffsetsByUtcTime(millis, offsets);
+            // END Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+            } else {
                 zoneOffset = zi.getOffset(millis);
                 offsets[0] = zi.getRawOffset();
                 offsets[1] = zoneOffset - offsets[0];
-            // }
-            // END Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+            }
 
             // We need to calculate the given millis and time zone
             // offset separately for java.util.GregorianCalendar
diff --git a/ojluni/src/main/java/sun/util/calendar/Era.java b/ojluni/src/main/java/sun/util/calendar/Era.java
index a013c57..7c02cce 100644
--- a/ojluni/src/main/java/sun/util/calendar/Era.java
+++ b/ojluni/src/main/java/sun/util/calendar/Era.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@
  *                           Taisho           1912-07-30 midnight local time
  *                           Showa            1926-12-26 midnight local time
  *                           Heisei           1989-01-08 midnight local time
+ *                           Reiwa            2019-05-01 midnight local time
  *   Julian calendar         BeforeCommonEra  -292275055-05-16T16:47:04.192Z
  *                           CommonEra        0000-12-30 midnight local time
  *   Taiwanese calendar      MinGuo           1911-01-01 midnight local time
diff --git a/ojluni/src/main/resources/calendars.properties b/ojluni/src/main/resources/calendars.properties
index 49f68ac..6007d7a 100644
--- a/ojluni/src/main/resources/calendars.properties
+++ b/ojluni/src/main/resources/calendars.properties
@@ -29,12 +29,14 @@
 #   Taisho since 1912-07-30 00:00:00 local time (Gregorian)
 #   Showa  since 1926-12-25 00:00:00 local time (Gregorian)
 #   Heisei since 1989-01-08 00:00:00 local time (Gregorian)
+#   Reiwa  since 2019-05-01 00:00:00 local time (Gregorian)
 calendar.japanese.type: LocalGregorianCalendar
 calendar.japanese.eras: \
 	name=Meiji,abbr=M,since=-3218832000000;  \
 	name=Taisho,abbr=T,since=-1812153600000; \
 	name=Showa,abbr=S,since=-1357603200000;  \
-	name=Heisei,abbr=H,since=600220800000
+	name=Heisei,abbr=H,since=600220800000;   \
+	name=Reiwa,abbr=R,since=1556668800000
 
 #
 # Taiwanese calendar
diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
index 2bc1f4c..091b385 100644
--- a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
+++ b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -111,6 +111,9 @@
  */
 @Test
 public class TCKJapaneseChronology {
+
+    // Year differences from Gregorian years.
+    private static final int YDIFF_REIWA = 2018;
     private static final int YDIFF_HEISEI = 1988;
     private static final int YDIFF_MEIJI = 1867;
     private static final int YDIFF_SHOWA = 1925;
@@ -173,6 +176,7 @@
     @DataProvider(name="createByEra")
     Object[][] data_createByEra() {
         return new Object[][] {
+                {JapaneseEra.of(3), 2020 - YDIFF_REIWA, 2, 29, 60, LocalDate.of(2020, 2, 29)}, // NEWERA
                 {JapaneseEra.HEISEI, 1996 - YDIFF_HEISEI, 2, 29, 60, LocalDate.of(1996, 2, 29)},
                 {JapaneseEra.HEISEI, 2000 - YDIFF_HEISEI, 2, 29, 60, LocalDate.of(2000, 2, 29)},
                 {JapaneseEra.MEIJI, 1874 - YDIFF_MEIJI, 2, 28, 59, LocalDate.of(1874, 2, 28)},
@@ -365,8 +369,11 @@
     @DataProvider(name="prolepticYear")
     Object[][] data_prolepticYear() {
         return new Object[][] {
+                {3, JapaneseEra.of(3), 1, 1 + YDIFF_REIWA, false},
+                {3, JapaneseEra.of(3), 102, 102 + YDIFF_REIWA, true},
+
                 {2, JapaneseEra.HEISEI, 1, 1 + YDIFF_HEISEI, false},
-                {2, JapaneseEra.HEISEI, 100, 100 + YDIFF_HEISEI, true},
+                {2, JapaneseEra.HEISEI, 4, 4 + YDIFF_HEISEI, true},
 
                 {-1, JapaneseEra.MEIJI, 9, 9 + YDIFF_MEIJI, true},
                 {-1, JapaneseEra.MEIJI, 10, 10 + YDIFF_MEIJI, false},
@@ -548,6 +555,7 @@
             { JapaneseEra.TAISHO, 0, "Taisho"},
             { JapaneseEra.SHOWA, 1, "Showa"},
             { JapaneseEra.HEISEI, 2, "Heisei"},
+            { JapaneseEra.of(3), 3, "Reiwa"},
         };
     }
 
@@ -562,7 +570,7 @@
 
     @Test
     public void test_Japanese_badEras() {
-        int badEras[] = {-1000, -998, -997, -2, 3, 4, 1000};
+        int badEras[] = {-1000, -998, -997, -2, 4, 5, 1000};
         for (int badEra : badEras) {
             try {
                 Era era = JapaneseChronology.INSTANCE.eraOf(badEra);
@@ -683,6 +691,7 @@
             {JapaneseChronology.INSTANCE.date(1989,  1,  7), "Japanese Showa 64-01-07"},
             {JapaneseChronology.INSTANCE.date(1989,  1,  8), "Japanese Heisei 1-01-08"},
             {JapaneseChronology.INSTANCE.date(2012, 12,  6), "Japanese Heisei 24-12-06"},
+            {JapaneseChronology.INSTANCE.date(2020,  1,  6), "Japanese Reiwa 2-01-06"},
         };
     }
 
diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java
index de83e1d..e37a6a5 100644
--- a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java
+++ b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,6 +77,7 @@
     @DataProvider(name = "JapaneseEras")
     Object[][] data_of_eras() {
         return new Object[][] {
+                    {JapaneseEra.of(3), "Reiwa", 3},
                     {JapaneseEra.HEISEI, "Heisei", 2},
                     {JapaneseEra.SHOWA, "Showa", 1},
                     {JapaneseEra.TAISHO, "Taisho", 0},
diff --git a/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java b/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java
index 3fbf853..03443d9 100644
--- a/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java
+++ b/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
 
 /**
  * Tests for the Japanese chronology
@@ -58,6 +59,8 @@
             { JapaneseEra.SHOWA,      1, 12, 25, 1926 },
             { JapaneseEra.SHOWA,     64,  1,  7, 1989 },
             { JapaneseEra.HEISEI,     1,  1,  8, 1989 },
+            { JapaneseEra.HEISEI,    31,  4, 30, 2019 },
+            { JapaneseEra.of(3),      1,  5,  1, 2019 },
         };
     }
 
@@ -74,6 +77,8 @@
             { JapaneseEra.SHOWA,  64,    7,  1,  7 },
             { JapaneseEra.HEISEI,  1,    1,  1,  8 },
             { JapaneseEra.HEISEI,  2,    8,  1,  8 },
+            { JapaneseEra.HEISEI, 31,  120,  4, 30 },
+            { JapaneseEra.of(3),   1,    1,  5,  1 },
         };
     }
 
@@ -81,8 +86,8 @@
     Object[][] rangeData() {
         return new Object[][] {
             // field, minSmallest, minLargest, maxSmallest, maxLargest
-            { ChronoField.ERA,         -1, -1, 2, 2},
-            { ChronoField.YEAR_OF_ERA, 1, 1, 15, 999999999-1989 }, // depends on the current era
+            { ChronoField.ERA,         -1, -1, 3, 3},
+            { ChronoField.YEAR_OF_ERA, 1, 1, 15, 999999999-2019}, // depends on the current era
             { ChronoField.DAY_OF_YEAR, 1, 1, 7, 366},
             { ChronoField.YEAR, 1873, 1873, 999999999, 999999999},
         };
@@ -105,7 +110,9 @@
             { JapaneseEra.SHOWA,     65,  1,  1 },
             { JapaneseEra.HEISEI,     1,  1,  7 },
             { JapaneseEra.HEISEI,     1,  2, 29 },
-            { JapaneseEra.HEISEI, Year.MAX_VALUE,  12, 31 },
+            { JapaneseEra.HEISEI,    31,  5,  1 },
+            { JapaneseEra.of(3),      1,  4, 30 },
+            { JapaneseEra.of(3), Year.MAX_VALUE,  12, 31 },
         };
     }
 
@@ -124,7 +131,10 @@
             { JapaneseEra.SHOWA,     65 },
             { JapaneseEra.HEISEI,    -1 },
             { JapaneseEra.HEISEI,     0 },
-            { JapaneseEra.HEISEI, Year.MAX_VALUE },
+            { JapaneseEra.HEISEI,    32 },
+            { JapaneseEra.of(3),     -1 },
+            { JapaneseEra.of(3),      0 },
+            { JapaneseEra.of(3), Year.MAX_VALUE },
         };
     }
 
@@ -141,6 +151,22 @@
             { JapaneseEra.SHOWA,  64,   8 },
             { JapaneseEra.HEISEI,  1, 360 },
             { JapaneseEra.HEISEI,  2, 366 },
+            { JapaneseEra.HEISEI, 31, 121 },
+            { JapaneseEra.of(3),   1, 246 },
+            { JapaneseEra.of(3),   2, 367 },
+        };
+    }
+
+    @DataProvider
+    Object[][] eraNameData() {
+        return new Object[][] {
+            // Japanese era, name, exception
+            { "Meiji",  JapaneseEra.MEIJI,      null },
+            { "Taisho", JapaneseEra.TAISHO,     null },
+            { "Showa",  JapaneseEra.SHOWA,      null },
+            { "Heisei", JapaneseEra.HEISEI,     null },
+            { "Reiwa", JapaneseEra.of(3),       null },
+            { "NewEra", null,                   IllegalArgumentException.class},
         };
     }
 
@@ -192,4 +218,13 @@
         JapaneseDate date = JAPANESE.dateYearDay(era, yearOfEra, dayOfYear);
         System.out.printf("No DateTimeException with era=%s, year=%d, dayOfYear=%d%n", era, yearOfEra, dayOfYear);
     }
+
+    @Test(dataProvider="eraNameData")
+    public void test_eraName(String eraName, JapaneseEra era, Class expectedEx) {
+        try {
+            assertEquals(JapaneseEra.valueOf(eraName), era);
+        } catch (Exception ex) {
+            assertTrue(expectedEx.isInstance(ex));
+        }
+    }
 }
diff --git a/ojluni/src/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java b/ojluni/src/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java
index ab61c71..f86f144 100644
--- a/ojluni/src/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java
+++ b/ojluni/src/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -72,6 +72,7 @@
 /**
  * Tests for the Umm alQura chronology and data.
  * Note: The dates used for testing are just a sample of calendar data.
+ * @bug 8067800
  */
 @Test
 public class TestUmmAlQuraChronology {
@@ -548,6 +549,7 @@
         assertFalse(HijrahChronology.INSTANCE.isLeapYear(y), "Out of range leap year");
     }
 
+
     // Date samples to convert HijrahDate to LocalDate and vice versa
     @DataProvider(name="samples")
     Object[][] data_samples() {
@@ -773,8 +775,10 @@
             {HijrahDate.of(1350,5,15), "Japanese Showa 6-09-28"},
             {HijrahDate.of(1434,5,1), "Japanese Heisei 25-03-13"},
             {HijrahDate.of(1436,1,1), "Japanese Heisei 26-10-25"},
-            {HijrahDate.of(1500,6,12), "Japanese Heisei 89-05-05"},
-            {HijrahDate.of(1550,3,11), "Japanese Heisei 137-08-11"},
+            {HijrahDate.of(1440,8,25), "Japanese Heisei 31-04-30"},
+            {HijrahDate.of(1440,8,26), "Japanese Reiwa 1-05-01"},
+            {HijrahDate.of(1500,6,12), "Japanese Reiwa 59-05-05"},
+            {HijrahDate.of(1550,3,11), "Japanese Reiwa 107-08-11"},
         };
     }
 
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java b/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java
index 1edaba6..e2c2b4a 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,6 +20,13 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
+/*
+ *
+ * @test
+ * @bug 8206120
+ */
+
 package test.java.time.format;
 
 import static org.testng.Assert.assertEquals;
@@ -37,6 +44,7 @@
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.DateTimeParseException;
 import java.time.format.FormatStyle;
+import java.time.format.ResolverStyle;
 import java.time.format.TextStyle;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalQueries;
@@ -134,6 +142,19 @@
         };
     }
 
+    @DataProvider(name="lenient_eraYear")
+    Object[][] lenientEraYear() {
+        return new Object[][] {
+            // Chronology, lenient era/year, strict era/year
+            { JAPANESE, "Meiji 123", "Heisei 2" },
+            // Android-changed: Eras names have been changed in CLDR data.
+            // { JAPANESE, "Showa 65", "Heisei 2" }
+            // { JAPANESE, "Heisei 32", "NewEra 2" }, // NewEra
+            { JAPANESE, "Shōwa 65", "Heisei 2" },
+            { JAPANESE, "Heisei 32", "Qqqq 2" }, // NewEra
+        };
+    }
+
     @Test(dataProvider="format_data")
     public void test_formatLocalizedDate(Chronology chrono, Locale formatLocale, Locale numberingLocale,
                                          ChronoLocalDate date, String expected) {
@@ -172,4 +193,15 @@
         Chronology cal = ta.query(TemporalQueries.chronology());
         assertEquals(cal, chrono);
     }
+
+    @Test(dataProvider="lenient_eraYear")
+    public void test_lenientEraYear(Chronology chrono, String lenient, String strict) {
+        String mdStr = "-01-01";
+        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
+            .appendPattern("GGGG y-M-d")
+            .toFormatter()
+            .withChronology(chrono);
+        DateTimeFormatter dtfLenient = dtf.withResolverStyle(ResolverStyle.LENIENT);
+        assertEquals(LocalDate.parse(lenient+mdStr, dtfLenient), LocalDate.parse(strict+mdStr, dtf));
+    }
 }
diff --git a/openjdk_java_files.bp b/openjdk_java_files.bp
index 5c27228..c1f29ea 100644
--- a/openjdk_java_files.bp
+++ b/openjdk_java_files.bp
@@ -1387,6 +1387,7 @@
     srcs: [
         "ojluni/src/main/java/java/nio/DirectByteBuffer.java",
         "ojluni/src/main/java/sun/misc/Cleaner.java",
+        "ojluni/src/main/java/sun/misc/Unsafe.java",
         "ojluni/src/main/java/sun/nio/ch/DirectBuffer.java",
         "ojluni/src/main/java/sun/security/jca/Providers.java",
         "ojluni/src/main/java/sun/security/pkcs/ContentInfo.java",
@@ -1451,7 +1452,6 @@
         "ojluni/src/main/java/sun/misc/Resource.java",
         "ojluni/src/main/java/sun/misc/SharedSecrets.java",
         "ojluni/src/main/java/sun/misc/URLClassPath.java",
-        "ojluni/src/main/java/sun/misc/Unsafe.java",
         "ojluni/src/main/java/sun/misc/Version.java",
         "ojluni/src/main/java/sun/misc/VM.java",
         "ojluni/src/main/java/sun/net/ApplicationProxy.java",
diff --git a/support/src/test/java/libcore/testing/io/TestIoUtils.java b/support/src/test/java/libcore/testing/io/TestIoUtils.java
index 8e241df..34a2cf7 100644
--- a/support/src/test/java/libcore/testing/io/TestIoUtils.java
+++ b/support/src/test/java/libcore/testing/io/TestIoUtils.java
@@ -17,6 +17,10 @@
 package libcore.testing.io;
 
 import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.Random;
 
 public class TestIoUtils {
@@ -25,6 +29,13 @@
     private TestIoUtils() {}
 
     /**
+     * Returns the contents of 'path' as a string. The contents are assumed to be UTF-8.
+     */
+    public static String readFileAsString(String absolutePath) throws IOException {
+        return new String(Files.readAllBytes(Paths.get(absolutePath)), StandardCharsets.UTF_8);
+    }
+
+    /**
      * Creates a unique new temporary directory under "java.io.tmpdir".
      */
     public static File createTemporaryDirectory(String prefix) {