[automerger skipped] Make ArrayDeque clear old array when resizing
am: d3a99bc146 -s ours
am skip reason: change_id I614a514180e04440e1d59d69a9b249e5c3db485e with SHA1 7e1393d156 is in history

Change-Id: Ie292f2adc0470463fe2d5f82641820f3689ab33d
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index 2066c42..317ef4b 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -255,14 +255,20 @@
         // Device files put in /system.
         "tzdata",
         "tz_version",
-        // Files used to simulate the /system and runtime APEX dir
-        // structure on host.
-        "tzdata_host",
-        "tzdata_host_runtime_apex",
-        "tzlookup.xml_host_runtime_apex",
-        "tz_version_host",
-        "tz_version_host_runtime_apex",
     ],
+    target: {
+        hostdex: {
+            required: [
+                // Files used to simulate the /system and runtime APEX dir
+                // structure on host.
+                "tzdata_host",
+                "tzdata_host_runtime_apex",
+                "tzlookup.xml_host_runtime_apex",
+                "tz_version_host",
+                "tz_version_host_runtime_apex",
+            ],
+        },
+    },
 }
 
 // Provided solely to contribute information about which hidden parts of the
@@ -702,3 +708,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/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/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/BufferIterator.java b/luni/src/main/java/libcore/io/BufferIterator.java
index b7c5b38..97890c3 100644
--- a/luni/src/main/java/libcore/io/BufferIterator.java
+++ b/luni/src/main/java/libcore/io/BufferIterator.java
@@ -44,13 +44,13 @@
     public abstract int pos();
 
     /**
-     * Copies {@code byteCount} bytes from the current position into {@code dst}, starting at
-     * {@code dstOffset}, and advances the current position {@code byteCount} bytes.
+     * Copies {@code byteCount} bytes from the current position into {@code bytes}, starting at
+     * {@code arrayOffset}, and advances the current position {@code byteCount} bytes.
      *
      * @throws IndexOutOfBoundsException if the read / write would be outside of the buffer / array
      */
     @UnsupportedAppUsage
-    public abstract void readByteArray(byte[] dst, int dstOffset, int byteCount);
+    public abstract void readByteArray(byte[] bytes, int arrayOffset, int byteCount);
 
     /**
      * Returns the byte at the current position, and advances the current position one byte.
@@ -69,13 +69,21 @@
     public abstract int readInt();
 
     /**
-     * Copies {@code intCount} 32-bit ints from the current position into {@code dst}, starting at
-     * {@code dstOffset}, and advances the current position {@code 4 * intCount} bytes.
+     * Copies {@code intCount} 32-bit ints from the current position into {@code ints}, starting at
+     * {@code arrayOffset}, and advances the current position {@code 4 * intCount} bytes.
      *
      * @throws IndexOutOfBoundsException if the read / write would be outside of the buffer / array
      */
     @UnsupportedAppUsage
-    public abstract void readIntArray(int[] dst, int dstOffset, int intCount);
+    public abstract void readIntArray(int[] ints, int arrayOffset, int intCount);
+
+    /**
+     * Copies {@code longCount} 64-bit ints from the current position into {@code longs}, starting
+     * at {@code arrayOffset}, and advances the current position {@code 8 * longCount} bytes.
+     *
+     * @throws IndexOutOfBoundsException if the read / write would be outside of the buffer / array
+     */
+    public abstract void readLongArray(long[] longs, int arrayOffset, int longCount);
 
     /**
      * Returns the 16-bit short at the current position, and advances the current position two bytes.
diff --git a/luni/src/main/java/libcore/io/NioBufferIterator.java b/luni/src/main/java/libcore/io/NioBufferIterator.java
index 263666d..1554519 100644
--- a/luni/src/main/java/libcore/io/NioBufferIterator.java
+++ b/luni/src/main/java/libcore/io/NioBufferIterator.java
@@ -50,10 +50,12 @@
         this.swap = swap;
     }
 
+    @Override
     public void seek(int offset) {
         position = offset;
     }
 
+    @Override
     public void skip(int byteCount) {
         position += byteCount;
     }
@@ -63,14 +65,16 @@
         return position;
     }
 
-    public void readByteArray(byte[] dst, int dstOffset, int byteCount) {
-        checkDstBounds(dstOffset, dst.length, byteCount);
+    @Override
+    public void readByteArray(byte[] bytes, int arrayOffset, int byteCount) {
+        checkArrayBounds(arrayOffset, bytes.length, byteCount);
         file.checkNotClosed();
         checkReadBounds(position, length, byteCount);
-        Memory.peekByteArray(address + position, dst, dstOffset, byteCount);
+        Memory.peekByteArray(address + position, bytes, arrayOffset, byteCount);
         position += byteCount;
     }
 
+    @Override
     public byte readByte() {
         file.checkNotClosed();
         checkReadBounds(position, length, 1);
@@ -79,6 +83,7 @@
         return result;
     }
 
+    @Override
     public int readInt() {
         file.checkNotClosed();
         checkReadBounds(position, length, Integer.BYTES);
@@ -87,15 +92,27 @@
         return result;
     }
 
-    public void readIntArray(int[] dst, int dstOffset, int intCount) {
-        checkDstBounds(dstOffset, dst.length, intCount);
+    @Override
+    public void readIntArray(int[] ints, int arrayOffset, int intCount) {
+        checkArrayBounds(arrayOffset, ints.length, intCount);
         file.checkNotClosed();
         final int byteCount = Integer.BYTES * intCount;
         checkReadBounds(position, length, byteCount);
-        Memory.peekIntArray(address + position, dst, dstOffset, intCount, swap);
+        Memory.peekIntArray(address + position, ints, arrayOffset, intCount, swap);
         position += byteCount;
     }
 
+    @Override
+    public void readLongArray(long[] longs, int arrayOffset, int longCount) {
+        checkArrayBounds(arrayOffset, longs.length, longCount);
+        file.checkNotClosed();
+        final int byteCount = Long.BYTES * longCount;
+        checkReadBounds(position, length, byteCount);
+        Memory.peekLongArray(address + position, longs, arrayOffset, longCount, swap);
+        position += byteCount;
+    }
+
+    @Override
     public short readShort() {
         file.checkNotClosed();
         checkReadBounds(position, length, Short.BYTES);
@@ -118,18 +135,18 @@
         }
     }
 
-    private static void checkDstBounds(int dstOffset, int dstLength, int count) {
-        if (dstOffset < 0 || count < 0) {
+    private static void checkArrayBounds(int arrayOffset, int arrayLength, int count) {
+        if (arrayOffset < 0 || count < 0) {
             throw new IndexOutOfBoundsException(
-                    "Invalid dst args: offset=" + dstLength + ", count=" + count);
+                    "Invalid args: arrayOffset=" + arrayOffset + ", count=" + count);
         }
-        // Use of int here relies on dstLength being an int <= Integer.MAX_VALUE, which it has to
+        // Use of int here relies on arrayLength being an int <= Integer.MAX_VALUE, which it has to
         // be because it's an array length.
-        final int targetPos = dstOffset + count;
-        if (targetPos < 0 || targetPos > dstLength) {
+        final int targetPos = arrayOffset + count;
+        if (targetPos < 0 || targetPos > arrayLength) {
             throw new IndexOutOfBoundsException(
-                    "Write outside range: dst.length=" + dstLength + ", offset="
-                            + dstOffset + ", count=" + count);
+                    "Write outside range: arrayLength=" + arrayLength + ", arrayOffset="
+                            + arrayOffset + ", count=" + count);
         }
     }
 }
diff --git a/luni/src/main/java/libcore/net/android.mime.types b/luni/src/main/java/libcore/net/android.mime.types
index dd3b21a..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
diff --git a/luni/src/main/java/libcore/timezone/TzDataSetVersion.java b/luni/src/main/java/libcore/timezone/TzDataSetVersion.java
index 2ba64a0..c2e7d7b 100644
--- a/luni/src/main/java/libcore/timezone/TzDataSetVersion.java
+++ b/luni/src/main/java/libcore/timezone/TzDataSetVersion.java
@@ -45,7 +45,7 @@
      * version to 1 when doing so.
      */
     // @VisibleForTesting : Keep this inline-able: it is used from CTS tests.
-    public static final int CURRENT_FORMAT_MAJOR_VERSION = 3; // Android Q
+    public static final int CURRENT_FORMAT_MAJOR_VERSION = 4; // Android R
 
     /**
      * Returns the major tz data format version supported by this device.
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 abd98b1..48665ca 100644
--- a/luni/src/main/java/libcore/util/ZoneInfo.java
+++ b/luni/src/main/java/libcore/util/ZoneInfo.java
@@ -48,20 +48,9 @@
  * and storing it a representation to support the {@link TimeZone} and {@link GregorianCalendar}
  * implementations. See {@link ZoneInfo#readTimeZone(String, BufferIterator, long)}.
  *
- * <p>The main difference between {@code tzfile} and the compacted form is that the
- * {@code struct ttinfo} only uses a single byte for {@code tt_isdst} and {@code tt_abbrind}.
- *
  * <p>This class does not use all the information from the {@code tzfile}; it uses:
  * {@code tzh_timecnt} and the associated transition times and type information. For each type
- * (described by {@code struct ttinfo}) it uses {@code tt_gmtoff} and {@code tt_isdst}. Note, that
- * the definition of {@code struct ttinfo} uses {@code long}, and {@code int} but they do not have
- * the same meaning as Java. The prose following the definition makes it clear that the {@code long}
- * is 4 bytes and the {@code int} fields are 1 byte.
- *
- * <p>As the data uses 32 bits to store the time in seconds the time range is limited to roughly
- * 69 years either side of the epoch (1st Jan 1970 00:00:00) that means that it cannot handle any
- * dates before 1900 and after 2038. There is an extended version of the table that uses 64 bits
- * to store the data but that information is not used by this.
+ * (described by {@code struct ttinfo}) it uses {@code tt_gmtoff} and {@code tt_isdst}.
  *
  * <p>This class should be in libcore.timezone but this class is Serializable so cannot
  * be moved there without breaking apps that have (for some reason) serialized TimeZone objects.
@@ -197,6 +186,19 @@
 
     public static ZoneInfo readTimeZone(String id, BufferIterator it, long currentTimeMillis)
             throws IOException {
+
+        // Skip over the superseded 32-bit header and data.
+        skipOver32BitData(id, it);
+
+        // Read the v2+ 64-bit header and data.
+        return read64BitData(id, it, currentTimeMillis);
+    }
+
+    /**
+     * Skip over the 32-bit data with some minimal validation to make sure sure we reading a valid
+     * and supported file.
+     */
+    private static void skipOver32BitData(String id, BufferIterator it) throws IOException {
         // Variable names beginning tzh_ correspond to those in "tzfile.h".
 
         // Check tzh_magic.
@@ -205,24 +207,82 @@
             throw new IOException("Timezone id=" + id + " has an invalid header=" + tzh_magic);
         }
 
-        // Skip the uninteresting part of the header.
-        it.skip(28);
+        byte tzh_version = it.readByte();
+        checkTzifVersionAcceptable(id, tzh_version);
+
+        // Skip the unused bytes.
+        it.skip(15);
+
+        // Read the header values necessary to read through all the 32-bit data.
+        int tzh_ttisgmtcnt = it.readInt();
+        int tzh_ttisstdcnt = it.readInt();
+        int tzh_leapcnt = it.readInt();
+        int tzh_timecnt = it.readInt();
+        int tzh_typecnt = it.readInt();
+        int tzh_charcnt = it.readInt();
+
+        // Skip transitions data, 4 bytes for each 32-bit time + 1 byte for isDst.
+        final int transitionInfoSize = 4 + 1;
+        it.skip(tzh_timecnt * transitionInfoSize);
+
+        // Skip ttinfos.
+        // struct ttinfo {
+        //     int32_t       tt_gmtoff;
+        //     unsigned char tt_isdst;
+        //     unsigned char tt_abbrind;
+        // };
+        final int ttinfoSize = 4 + 1 + 1;
+        it.skip(tzh_typecnt * ttinfoSize);
+
+        // Skip tzh_charcnt time zone abbreviations.
+        it.skip(tzh_charcnt);
+
+        // Skip tzh_leapcnt repetitions of a 32-bit time + a 32-bit correction.
+        int leapInfoSize = 4 + 4;
+        it.skip(tzh_leapcnt * leapInfoSize);
+
+        // Skip ttisstds and ttisgmts information. These can be ignored for our usecases as per
+        // https://mm.icann.org/pipermail/tz/2006-February/013359.html
+        it.skip(tzh_ttisstdcnt + tzh_ttisgmtcnt);
+    }
+
+    /**
+     * Read the 64-bit header and data for {@code id} from the current position of {@code it} and
+     * return a ZoneInfo.
+     */
+    private static ZoneInfo read64BitData(String id, BufferIterator it, long currentTimeMillis)
+            throws IOException {
+        // Variable names beginning tzh_ correspond to those in "tzfile.h".
+
+        // Check tzh_magic.
+        int tzh_magic = it.readInt();
+        if (tzh_magic != 0x545a6966) { // "TZif"
+            throw new IOException("Timezone id=" + id + " has an invalid header=" + tzh_magic);
+        }
+
+        byte tzh_version = it.readByte();
+        checkTzifVersionAcceptable(id, tzh_version);
+
+        // Skip the uninteresting parts of the header.
+        it.skip(27);
 
         // Read the sizes of the arrays we're about to read.
         int tzh_timecnt = it.readInt();
+
         // Arbitrary ceiling to prevent allocating memory for corrupt data.
-        // 2 per year with 2^32 seconds would give ~272 transitions.
         final int MAX_TRANSITIONS = 2000;
         if (tzh_timecnt < 0 || tzh_timecnt > MAX_TRANSITIONS) {
             throw new IOException(
-                    "Timezone id=" + id + " has an invalid number of transitions=" + tzh_timecnt);
+                    "Timezone id=" + id + " has an invalid number of transitions="
+                            + tzh_timecnt);
         }
 
         int tzh_typecnt = it.readInt();
         final int MAX_TYPES = 256;
         if (tzh_typecnt < 1) {
             throw new IOException("ZoneInfo requires at least one type "
-                    + "to be provided for each timezone but could not find one for '" + id + "'");
+                    + "to be provided for each timezone but could not find one for '" + id
+                    + "'");
         } else if (tzh_typecnt > MAX_TYPES) {
             throw new IOException(
                     "Timezone with id " + id + " has too many types=" + tzh_typecnt);
@@ -230,18 +290,9 @@
 
         it.skip(4); // Skip tzh_charcnt.
 
-        // Transitions are signed 32 bit integers, but we store them as signed 64 bit
-        // integers since it's easier to compare them against 64 bit inputs (see getOffset
-        // and isDaylightTime) with much less risk of an overflow in our calculations.
-        //
-        // The alternative of checking the input against the first and last transition in
-        // the array is far more awkward and error prone.
-        int[] transitions32 = new int[tzh_timecnt];
-        it.readIntArray(transitions32, 0, transitions32.length);
-
         long[] transitions64 = new long[tzh_timecnt];
+        it.readLongArray(transitions64, 0, transitions64.length);
         for (int i = 0; i < tzh_timecnt; ++i) {
-            transitions64[i] = transitions32[i];
             if (i > 0 && transitions64[i] <= transitions64[i - 1]) {
                 throw new IOException(
                         id + " transition at " + i + " is not sorted correctly, is "
@@ -249,13 +300,14 @@
             }
         }
 
-        byte[] type = new byte[tzh_timecnt];
-        it.readByteArray(type, 0, type.length);
-        for (int i = 0; i < type.length; i++) {
-            int typeIndex = type[i] & 0xff;
+        byte[] types = new byte[tzh_timecnt];
+        it.readByteArray(types, 0, types.length);
+        for (int i = 0; i < types.length; i++) {
+            int typeIndex = types[i] & 0xff;
             if (typeIndex >= tzh_typecnt) {
                 throw new IOException(
-                        id + " type at " + i + " is not < " + tzh_typecnt + ", is " + typeIndex);
+                        id + " type at " + i + " is not < " + tzh_typecnt + ", is "
+                                + typeIndex);
             }
         }
 
@@ -277,8 +329,19 @@
             // for any locale. (The RI doesn't do any better than us here either.)
             it.skip(1);
         }
+        return new ZoneInfo(id, transitions64, types, gmtOffsets, isDsts, currentTimeMillis);
+    }
 
-        return new ZoneInfo(id, transitions64, type, gmtOffsets, isDsts, currentTimeMillis);
+    private static void checkTzifVersionAcceptable(String id, byte tzh_version) throws IOException {
+        char tzh_version_char = (char) tzh_version;
+        // Version >= 2 is required because the 64-bit time section is required. v3 is the latest
+        // version known at the time of writing and is identical to v2 in the parts used by this
+        // class.
+        if (tzh_version_char != '2' && tzh_version_char != '3') {
+            throw new IOException(
+                    "Timezone id=" + id + " has an invalid format version=\'" + tzh_version_char
+                            + "\' (" + tzh_version + ")");
+        }
     }
 
     private ZoneInfo(String name, long[] transitions, byte[] types, int[] gmtOffsets, byte[] isDsts,
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/lang/invoke/MethodHandleCombinersTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java
index 5866ae4..a8cfa24 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java
@@ -1214,7 +1214,7 @@
 
         Object ret = handle.invokeWithArguments(new Object[]{"a", "b", "c"});
         assertEquals(42, (int) ret);
-        ret = handle.invokeWithArguments(new String[]{"a", "b", "c"});
+        ret = handle.invokeWithArguments((Object[]) new String[]{"a", "b", "c"});
         assertEquals(42, (int) ret);
 
         // Also test the versions that take a List<?> instead of an array.
diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodTypeTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodTypeTest.java
index f833840..0c4d18b 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/MethodTypeTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/MethodTypeTest.java
@@ -96,7 +96,7 @@
         }
 
         try {
-            MethodType.methodType(int.class, String.class, null);
+            MethodType.methodType(int.class, String.class, (Class<?>) null);
             fail();
         } catch (NullPointerException expected) {
         }
@@ -334,7 +334,7 @@
         }
 
         try {
-            mt.insertParameterTypes(1, Arrays.asList(null));
+            mt.insertParameterTypes(1, Arrays.asList((Class<?>) null));
             fail();
         } catch (NullPointerException expected) {
         }
@@ -404,7 +404,7 @@
         }
 
         try {
-            mt.appendParameterTypes(Arrays.asList(null));
+            mt.appendParameterTypes(Arrays.asList((Class<?>) null));
             fail();
         } catch (NullPointerException expected) {
         }
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/nio/file/DefaultFileSystemProvider2Test.java b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
index 2916b03..42d0f05 100644
--- a/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
+++ b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
@@ -600,7 +600,8 @@
         } catch (NullPointerException expected) {}
 
         try {
-            provider.newByteChannel(filesSetup.getTestPath(), new HashSet<>(), null);
+            provider.newByteChannel(filesSetup.getTestPath(), new HashSet<>(),
+                (FileAttribute<?>) null);
             fail();
         } catch (NullPointerException expected) {}
     }
diff --git a/luni/src/test/java/libcore/java/nio/file/DefaultSecureDirectoryStreamTest.java b/luni/src/test/java/libcore/java/nio/file/DefaultSecureDirectoryStreamTest.java
index 2c9c2cd..273ff8f 100644
--- a/luni/src/test/java/libcore/java/nio/file/DefaultSecureDirectoryStreamTest.java
+++ b/luni/src/test/java/libcore/java/nio/file/DefaultSecureDirectoryStreamTest.java
@@ -185,7 +185,7 @@
 
             // NPE
             try (DirectoryStream<Path> ds_path_dir1 =  ds_path_root.newDirectoryStream(path_root.
-                    relativize(path_f1), null)) {
+                    relativize(path_f1), (LinkOption) null)) {
                 fail();
             } catch (NullPointerException expected) {}
 
@@ -380,7 +380,7 @@
 
         try {
             ds_path_dir1.move(path_dir1, ds_path_dir1,
-                    Paths.get(path_root.getParent().toString(), null));
+                    Paths.get(path_root.getParent().toString(), (String) null));
             fail();
         } catch (NullPointerException expected) {}
 
@@ -498,7 +498,7 @@
         try (SecureDirectoryStream<Path> ds_path_root = (SecureDirectoryStream<Path>)
                 Files.newDirectoryStream(path_root)) {
             ds_path_root.getFileAttributeView(path_root.relativize(path_f1),
-                    BasicFileAttributeView.class, null);
+                    BasicFileAttributeView.class, (LinkOption) null);
             fail();
         } catch (NullPointerException expected) {}
     }
diff --git a/luni/src/test/java/libcore/java/nio/file/Files2Test.java b/luni/src/test/java/libcore/java/nio/file/Files2Test.java
index 436d3e3..a3357e3 100644
--- a/luni/src/test/java/libcore/java/nio/file/Files2Test.java
+++ b/luni/src/test/java/libcore/java/nio/file/Files2Test.java
@@ -1683,7 +1683,7 @@
         } catch (NullPointerException expected) {}
 
         try {
-            Files.createTempDirectory(filesSetup.getTestDirPath(), tmpDir, null);
+            Files.createTempDirectory(filesSetup.getTestDirPath(), tmpDir, (FileAttribute<?>) null);
             fail();
         } catch (NullPointerException expected) {}
     }
@@ -1710,7 +1710,7 @@
         assertEquals(attr.value(), Files.getAttribute(tmpDirPath, attr.name()));
 
         try {
-            Files.createTempDirectory(tmpDir, null);
+            Files.createTempDirectory(tmpDir, (FileAttribute<?>) null);
             fail();
         } catch (NullPointerException expected) {}
     }
@@ -1757,7 +1757,7 @@
 
         try {
             Files.createTempFile(filesSetup.getTestDirPath(), tmpFilePrefix, tmpFileSuffix,
-                    null);
+                (FileAttribute<?>) null);
             fail();
         } catch (NullPointerException expected) {}
     }
@@ -1796,7 +1796,7 @@
         assertEquals(attr.value(), Files.getAttribute(tmpFilePath, attr.name()));
 
         try {
-            Files.createTempFile(tmpFilePrefix, tmpFileSuffix, null);
+            Files.createTempFile(tmpFilePrefix, tmpFileSuffix, (FileAttribute<?>) null);
             fail();
         } catch (NullPointerException expected) {}
     }
diff --git a/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java b/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java
index e95f5bc..458804c 100644
--- a/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java
+++ b/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java
@@ -18,6 +18,7 @@
 
 import com.sun.nio.file.ExtendedWatchEventModifier;
 
+import java.nio.file.WatchEvent.Kind;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -454,7 +455,7 @@
         } catch (NullPointerException expected) {}
 
         try {
-            directory.register(watchService, null);
+            directory.register(watchService, (Kind<?>) null);
             fail();
         } catch (NullPointerException expected) {}
     }
diff --git a/luni/src/test/java/libcore/java/util/DateTest.java b/luni/src/test/java/libcore/java/util/DateTest.java
index 1fd8193..9cd9868 100644
--- a/luni/src/test/java/libcore/java/util/DateTest.java
+++ b/luni/src/test/java/libcore/java/util/DateTest.java
@@ -51,18 +51,14 @@
         c.set(Calendar.YEAR, 21);
         assertEquals("Wed Jan 01 00:00:00 PST 21", c.getTime().toString());
         String actual21GmtString = c.getTime().toGMTString();
-        // zic <= 2014b data gives -08:00:00, later ones gives -07:52:58 instead. http://b/73719425
-        assertTrue("Actual: " + actual21GmtString,
-                "1 Jan 21 07:52:58 GMT".equals(actual21GmtString)
-                        || "1 Jan 21 08:00:00 GMT".equals(actual21GmtString));
+        // 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());
         String actual321GmtString = c.getTime().toGMTString();
-        // zic <= 2014b data gives -08:00:00, later ones gives -07:52:58 instead. http://b/73719425
-        assertTrue("Actual: " + actual321GmtString,
-                "1 Jan 321 07:52:58 GMT".equals(actual321GmtString)
-                        || "1 Jan 321 08:00:00 GMT".equals(actual321GmtString));
+        // 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 {
@@ -74,18 +70,14 @@
         c.set(Calendar.YEAR, 21);
         assertEquals("Wed Jan 01 00:00:00 PST 21", c.getTime().toString());
         String actual21GmtString = c.getTime().toGMTString();
-        // zic <= 2014b data gives -08:00:00, later ones gives -07:52:58 instead. http://b/73719425
-        assertTrue("Actual: " + actual21GmtString,
-                "1 Jan 21 07:52:58 GMT".equals(actual21GmtString)
-                        || "1 Jan 21 08:00:00 GMT".equals(actual21GmtString));
+        // 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());
         String actual321GmtString = c.getTime().toGMTString();
-        // zic <= 2014b data gives -08:00:00, later ones gives -07:52:58 instead. http://b/73719425
-        assertTrue("Actual: " + actual321GmtString,
-                "1 Jan 321 07:52:58 GMT".equals(actual321GmtString)
-                        || "1 Jan 321 08:00:00 GMT".equals(actual321GmtString));
+        // 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 6297080..da4a04f 100644
--- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
@@ -59,7 +59,7 @@
 
     // http://code.google.com/p/android/issues/detail?id=14395
     public void testPreHistoricInDaylightTime() {
-        // A replacement for testPreHistoricInDaylightTime_old() using a zone that still lacks an
+        // A replacement for testPreHistoricInDaylightTime_old() using a zone that lacks an
         // explicit transition at Integer.MIN_VALUE with zic 2019a and 2019a data.
         TimeZone tz = TimeZone.getTimeZone("CET");
 
@@ -76,9 +76,7 @@
     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.
+        // the first was treated as a non-DST state. With the latest data this is no longer true.
         // This regression test has been kept in case that changes again in future and to prove the
         // behavior has remained consistent.
 
@@ -92,7 +90,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());
-        // For zic versions <= 2014b, this would be before the first transition.
+        // For zic versions <= 2014b with 32-bit data, 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));
@@ -109,7 +107,7 @@
         // prehistoric offsets. http://b/118835133
         // "Africa/Bissau" has just a few known transitions:
         // Transition time             : Offset    : DST / non-DST
-        // <Integer.MIN_VALUE secs>[1] : -01:02:20 : non-DST
+        // <Before first transition>[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
         //
@@ -117,7 +115,8 @@
         // generate the data. When implicit, the first non-DST type defn should be used.
         TimeZone tz = TimeZone.getTimeZone("Africa/Bissau");
 
-        // Times before Integer.MIN_VALUE should assume we're using the first non-DST type.
+        // Integer.MIN_VALUE seconds should not be significant for TimeZone on Android since it
+        // switched to using 64-bit data but we try a time before to make sure that is true.
         assertNonDaylightOffset(-3740, parseIsoTime("1900-01-01T00:00:00.0+0000"), tz);
 
         // Time before 1912-01-01 01:00:00 but after Integer.MIN_VALUE.
@@ -351,11 +350,6 @@
      * calculations. A bug (http://b/18839557) was reported when someone noticed that Android's
      * TimeZone didn't produce the same answers as other libraries at times just outside the range
      * of Integer seconds. The reason was because of int overflow / underflow which has been fixed.
-     * At the time of writing, Android's java.util.TimeZone implementation only supports reading
-     * TZif version 1 data (32-bit times) and provides one additional "before first transition"
-     * type. This makes Android's time zone information outside of the Integer range unreliable and
-     * unlikely to match libraries that use 64-bit times for transitions and/or calculate times
-     * outside of the range using rules (e.g. like ICU4J does).
      */
     public void testOverflowing32BitUnixDates() {
         final TimeZone tz = TimeZone.getTimeZone("America/New_York");
@@ -370,14 +364,8 @@
         // 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. http://b/73719425
         int actualOffset = tz.getOffset(lowerTimeMillis);
-        assertTrue(-18000000 == actualOffset || -17762000 == actualOffset);
+        assertEquals(-18000000, 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/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 cddf41b..fba0b47 100644
--- a/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java
+++ b/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java
@@ -39,7 +39,7 @@
    * Checks that a {@link ZoneInfo} cannot be created without any types.
    */
   public void testMakeTimeZone_NoTypes() throws Exception {
-    int[][] transitions = {};
+    long[][] transitions = {};
     int[][] types = {};
     try {
       createZoneInfo(transitions, types);
@@ -52,7 +52,7 @@
    * Checks that a {@link ZoneInfo} can be created with one type and no transitions.
    */
   public void testMakeTimeZone_OneType_NoTransitions() throws Exception {
-    int[][] transitions = {};
+    long[][] transitions = {};
     int[][] types = {
         { 4800, 0 }
     };
@@ -78,7 +78,7 @@
    * Checks that a {@link ZoneInfo} can be created with one non-DST transition.
    */
   public void testReadTimeZone_OneNonDstTransition() throws Exception {
-    int[][] transitions = {
+    long[][] transitions = {
         { 0, 0 }
     };
     int[][] types = {
@@ -102,7 +102,7 @@
    * Checks that a {@link ZoneInfo} cannot be created with one DST but no non-DSTs transitions.
    */
   public void testReadTimeZone_OneDstTransition() throws Exception {
-    int[][] transitions = {
+    long[][] transitions = {
         { 0, 0 }
     };
     int[][] types = {
@@ -120,7 +120,7 @@
    * around the boundary of negative transitions.
    */
   public void testReadTimeZone_NegativeTransition() throws Exception {
-    int[][] transitions = {
+    long[][] transitions = {
         { -2000, 0 },
         { -5, 1 },
         { 0, 2 },
@@ -157,7 +157,7 @@
    * around the boundary of positive transitions.
    */
   public void testReadTimeZone_PositiveTransition() throws Exception {
-    int[][] transitions = {
+    long[][] transitions = {
         { 0, 0 },
         { 5, 1 },
         { 2000, 2 },
@@ -195,7 +195,7 @@
    * transitions where the transition times are negative is not affected by rounding issues.
    */
   public void testReadTimeZone_HasFutureDST_NoPastDST_NegativeTransitions() throws Exception {
-    int[][] transitions = {
+    long[][] transitions = {
         { -2000, 0 },
         { -500, 1 },
         { -100, 2 },
@@ -228,7 +228,7 @@
    * transitions where the transition times are positive is not affected by rounding issues.
    */
   public void testReadTimeZone_HasFutureDST_NoPastDST_PositiveTransitions() throws Exception {
-    int[][] transitions = {
+    long[][] transitions = {
         { 4000, 0 },
         { 5500, 1 },
         { 6000, 2 },
@@ -261,7 +261,7 @@
    * transitions where the transition times are negative is not affected by rounding issues.
    */
   public void testReadTimeZone_HasPastDST_NoFutureDST_NegativeTransitions() throws Exception {
-    int[][] transitions = {
+    long[][] transitions = {
         { -5000, 0 },
         { -2000, 1 },
         { -500, 0 },
@@ -290,7 +290,7 @@
    * transitions where the transition times are positive is not affected by rounding issues.
    */
   public void testReadTimeZone_HasPastDST_NoFutureDST_PositiveTransitions() throws Exception {
-    int[][] transitions = {
+    long[][] transitions = {
         { 1000, 0 },
         { 4000, 1 },
         { 5500, 0 },
@@ -315,24 +315,17 @@
   }
 
   /**
-   * TimeZone APIs use long times in millis. Android uses TZif version 1 format data which
-   * uses 32-bit time values for transitions so it only gives accurate results for times in that
-   * range.
+   * TimeZone APIs use Java long times in millis.
    *
-   * <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
-   * fail on versions of Android <= P.
+   * <p>Android has historically mishandled the lookup of offset for times before Integer.MIN_VALUE
+   * seconds for various reasons. The logic has been corrected. This test would fail on versions of
+   * Android <= P.
    */
   public void testReadTimeZone_Bug118835133_extraFirstTransition() throws Exception {
-    // A time before the first representable time in a TZif version 1 file.
+    // A time before the first representable time in seconds with a java int.
     Instant before32BitTime = timeFromSeconds(Integer.MIN_VALUE).minusMillis(1);
 
-    // Times between the start of the 32-bit time range and the first "official" transition.
+    // Times around the 32-bit seconds minimum.
     Instant[] earlyTimes = {
             timeFromSeconds(Integer.MIN_VALUE),
             timeFromSeconds(Integer.MIN_VALUE).plusMillis(1),
@@ -358,10 +351,9 @@
             { offsetToSeconds(type2Offset), 0 },
     };
 
-    // 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.
+    // Simulates a zone with a single transition.
     {
-      int[][] transitions = {
+      long[][] transitions = {
               { timeToSeconds(firstRealTransitionTime), 2 /* type 2 */ },
       };
       ZoneInfo oldZoneInfo = createZoneInfo(transitions, types, currentTime);
@@ -375,11 +367,11 @@
       assertOffsetAt(oldZoneInfo, type2Offset, afterFirstRealTransitionTimes);
     }
 
-    // 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.
+    // Simulation a zone where there is an explicit transition at Integer.MIN_VALUE seconds. This
+    // used to be common when Android used 32-bit data from the TZif file.
     {
-      int[][] transitions = {
-              { Integer.MIN_VALUE, 1 /* type 1 */ }, // The extra transition added by zic.
+      long[][] transitions = {
+              { Integer.MIN_VALUE, 1 /* type 1 */ },
               { timeToSeconds(firstRealTransitionTime), 2 /* type 2 */ },
       };
       ZoneInfo newZoneInfo = createZoneInfo(transitions, types, currentTime);
@@ -398,7 +390,7 @@
 
   /**
    * Newer versions of zic after 2014b sometime introduce an explicit transition at
-   * Integer.MAX_VALUE.
+   * Integer.MAX_VALUE seconds.
    */
   public void testReadTimeZone_Bug118835133_extraLastTransition() throws Exception {
     // An arbitrary time to use as currentTime. Not important for this test.
@@ -419,10 +411,10 @@
     };
     Duration expectedLateOffset = offsetFromSeconds(latestOffsetSeconds);
 
-    // Create a simulation of zic version <= 2014b where there is usually no explicit transition at
-    // Integer.MAX_VALUE seconds.
+    // Create a simulation of a zone where there is no explicit transition at Integer.MAX_VALUE
+    // seconds.
     {
-      int[][] transitions = {
+      long[][] transitions = {
               { 1000, 0 },
               { 2000, 1 },
       };
@@ -430,10 +422,10 @@
       assertOffsetAt(oldZoneInfo, expectedLateOffset, timesToCheck);
     }
 
-    // Create a simulation of zic version > 2014b where there is sometimes an explicit transition at
-    // Integer.MAX_VALUE seconds.
+    // Create a simulation of a zone where there is an explicit transition at Integer.MAX_VALUE
+    // seconds.
     {
-      int[][] transitions = {
+      long[][] transitions = {
               { 1000, 0 },
               { 2000, 1 },
               { Integer.MAX_VALUE, 1}, // The extra transition.
@@ -444,12 +436,14 @@
   }
 
   /**
-   * Checks to make sure that it can handle up to 256 types.
+   * Checks to make sure that ZoneInfo can handle up to 256 types.
    */
-  public void testReadTimeZone_LotsOfTypes() throws Exception {
-    int[][] transitions = {
+  public void testReadTimeZone_MaxTypeCount() throws Exception {
+    long[][] transitions = {
         { -2000, 255 },
     };
+    // Create 256 types, each with zero offset and without DST except the last, which is offset by
+    // one hour but also without DST.
     int[][] types = new int[256][];
     Arrays.fill(types, new int[2]);
     types[255] = new int[] { 3600, 0 };
@@ -491,14 +485,14 @@
     }
   }
 
-  public void testReadTimeZone_valid() throws Exception {
+  public void testReadTimeZone_Valid() throws Exception {
     ZoneInfoTestHelper.ZicDataBuilder builder =
             new ZoneInfoTestHelper.ZicDataBuilder()
                     .initializeToValid();
     assertNotNull(createZoneInfo(getName(), Instant.now(), builder.build()));
   }
 
-  public void testReadTimeZone_badMagic() throws Exception {
+  public void testReadTimeZone_BadMagic() {
     ZoneInfoTestHelper.ZicDataBuilder builder =
             new ZoneInfoTestHelper.ZicDataBuilder()
                     .initializeToValid()
@@ -512,11 +506,15 @@
   /**
    * Checks to make sure that ZoneInfo rejects more than 256 types.
    */
-  public void testReadTimeZone_TooManyTypes() throws Exception {
+  public void testReadTimeZone_TooManyTypes() {
+    int typeCount = 257; // Max types allowed is 256
+    int transitionCount = 5;
+    long[][] transitions = createTransitions(transitionCount, typeCount);
+    int[][] types = createTypes(typeCount);
     ZoneInfoTestHelper.ZicDataBuilder builder =
             new ZoneInfoTestHelper.ZicDataBuilder()
                     .initializeToValid()
-                    .setTypeCountOverride(257);
+                    .setTransitionsAndTypes(transitions, types);
     byte[] bytes = builder.build();
     try {
       createZoneInfo(getName(), Instant.now(), bytes);
@@ -528,11 +526,15 @@
   /**
    * Checks to make sure that ZoneInfo rejects more than 2000 transitions.
    */
-  public void testReadTimeZone_TooManyTransitions() throws Exception {
+  public void testReadTimeZone_TooManyTransitions() {
+    int typeCount = 5;
+    int transitionCount = 2001; // Max transitions allowed is 2000.
+    long[][] transitions = createTransitions(transitionCount, typeCount);
+    int[][] types = createTypes(typeCount);
     ZoneInfoTestHelper.ZicDataBuilder builder =
             new ZoneInfoTestHelper.ZicDataBuilder()
                     .initializeToValid()
-                    .setTransitionCountOverride(2001);
+                    .setTransitionsAndTypes(transitions, types);
     byte[] bytes = builder.build();
     try {
       createZoneInfo(getName(), Instant.now(), bytes);
@@ -541,40 +543,8 @@
     }
   }
 
-  /**
-   * Checks to make sure that ZoneInfo rejects a negative type count.
-   */
-  public void testReadTimeZone_NegativeTypes() throws Exception {
-    ZoneInfoTestHelper.ZicDataBuilder builder =
-            new ZoneInfoTestHelper.ZicDataBuilder()
-                    .initializeToValid()
-                    .setTypeCountOverride(-1);
-    byte[] bytes = builder.build();
-    try {
-      createZoneInfo(getName(), Instant.now(), bytes);
-      fail();
-    } catch (IOException expected) {
-    }
-  }
-
-  /**
-   * Checks to make sure that ZoneInfo rejects a negative transition count.
-   */
-  public void testReadTimeZone_NegativeTransitions() throws Exception {
-    ZoneInfoTestHelper.ZicDataBuilder builder =
-            new ZoneInfoTestHelper.ZicDataBuilder()
-                    .initializeToValid()
-                    .setTransitionCountOverride(-1);
-    byte[] bytes = builder.build();
-    try {
-      createZoneInfo(getName(), Instant.now(), bytes);
-      fail();
-    } catch (IOException expected) {
-    }
-  }
-
-  public void testReadTimeZone_TransitionsNotSorted() throws Exception {
-    int[][] transitions = {
+  public void testReadTimeZone_TransitionsNotSorted() {
+    long[][] transitions = {
             { 1000, 0 },
             { 3000, 1 }, // Out of transition order.
             { 2000, 0 },
@@ -597,8 +567,8 @@
     }
   }
 
-  public void testReadTimeZone_InvalidTypeIndex() throws Exception {
-    int[][] transitions = {
+  public void testReadTimeZone_InvalidTypeIndex() {
+    long[][] transitions = {
             { 1000, 0 },
             { 2000, 2 }, // Invalid type index - only 0 and 1 defined below.
             { 3000, 0 },
@@ -621,8 +591,8 @@
     }
   }
 
-  public void testReadTimeZone_InvalidIsDst() throws Exception {
-    int[][] transitions = {
+  public void testReadTimeZone_InvalidIsDst() {
+    long[][] transitions = {
             { 1000, 0 },
             { 2000, 1 },
             { 3000, 0 },
@@ -664,7 +634,7 @@
       zoneInfoRead = (ZoneInfo) object;
     }
 
-    int[][] transitions = {
+    long[][] transitions = {
         { -5000, 0 },
         { -2000, 1 },
         { -500, 0 },
@@ -705,16 +675,12 @@
     }
   }
 
-  private static Instant timeFromSeconds(int timeInSeconds) {
+  private static Instant timeFromSeconds(long timeInSeconds) {
     return Instant.ofEpochSecond(timeInSeconds);
   }
 
-  private static int timeToSeconds(Instant time) {
-    long seconds = time.getEpochSecond();
-    if (seconds < Integer.MIN_VALUE || seconds > Integer.MAX_VALUE) {
-      fail("Time out of seconds range: " + time);
-    }
-    return (int) seconds;
+  private static long timeToSeconds(Instant time) {
+    return time.getEpochSecond();
   }
 
   private static Duration offsetFromSeconds(int offsetSeconds) {
@@ -729,17 +695,17 @@
     return (int) seconds;
   }
 
-  private ZoneInfo createZoneInfo(int[][] transitions, int[][] types)
+  private ZoneInfo createZoneInfo(long[][] transitions, int[][] types)
       throws Exception {
     return createZoneInfo(getName(), transitions, types, Instant.now());
   }
 
-  private ZoneInfo createZoneInfo(int[][] transitions, int[][] types, Instant currentTime)
+  private ZoneInfo createZoneInfo(long[][] transitions, int[][] types, Instant currentTime)
           throws Exception {
     return createZoneInfo(getName(), transitions, types, currentTime);
   }
 
-  private ZoneInfo createZoneInfo(String name, int[][] transitions, int[][] types,
+  private ZoneInfo createZoneInfo(String name, long[][] transitions, int[][] types,
           Instant currentTime) throws Exception {
 
     ZoneInfoTestHelper.ZicDataBuilder builder =
@@ -748,7 +714,7 @@
     return createZoneInfo(name, currentTime, builder.build());
   }
 
-  private ZoneInfo createZoneInfo(String name, Instant currentTime, byte[] bytes)
+  private static ZoneInfo createZoneInfo(String name, Instant currentTime, byte[] bytes)
           throws IOException {
     ByteBufferIterator bufferIterator = new ByteBufferIterator(ByteBuffer.wrap(bytes));
     return ZoneInfo.readTimeZone(
@@ -756,6 +722,38 @@
   }
 
   /**
+   * Creates {@code typeCount} "types" for use with
+   * {@link ZoneInfoTestHelper.ZicDataBuilder#setTypes(int[][])} and related methods. Each type is
+   * given an arbitrary offset and "isDst" value.
+   */
+  private static int[][] createTypes(int typeCount) {
+    int[][] types = new int[typeCount][2];
+    for (int i = 0; i < typeCount; i++) {
+      // [0] holds the offset from UTC in seconds.
+      types[i][0] = typeCount;
+      // [1] holds isDst: 0 == STD, 1 == DST
+      types[i][1] = typeCount % 2;
+    }
+    return types;
+  }
+
+  /**
+   * Creates {@code transitionCount} "transition pairs" for use with
+   * {@link ZoneInfoTestHelper.ZicDataBuilder#setTransitions(long[][])} and related methods. Each
+   * transition is given an arbitrary (but increasing) time referencing an arbitrary type.
+   */
+  private static long[][] createTransitions(int transitionCount, int typeCount) {
+    long[][] transitions = new long[transitionCount][2];
+    for (int i = 0; i < transitionCount; i++) {
+      // [0] holds the transition time.
+      transitions[i][0] = (i * 3600) + 100;
+      // [1] holds the type index to use. Must be > 0 and < typeCount to be valid.
+      transitions[i][1] = i % typeCount;
+    }
+    return transitions;
+  }
+
+  /**
    * A {@link BufferIterator} that wraps a {@link ByteBuffer}.
    */
   private static class ByteBufferIterator extends BufferIterator {
@@ -782,8 +780,8 @@
     }
 
     @Override
-    public void readByteArray(byte[] dst, int dstOffset, int byteCount) {
-      buffer.get(dst, dstOffset, byteCount);
+    public void readByteArray(byte[] bytes, int arrayOffset, int byteCount) {
+      buffer.get(bytes, arrayOffset, byteCount);
     }
 
     @Override
@@ -796,16 +794,24 @@
       int value = buffer.asIntBuffer().get();
       // Using a separate view does not update the position of this buffer so do it
       // explicitly.
-      skip(4);
+      skip(Integer.BYTES);
       return value;
     }
 
     @Override
-    public void readIntArray(int[] dst, int dstOffset, int intCount) {
-      buffer.asIntBuffer().get(dst, dstOffset, intCount);
+    public void readIntArray(int[] ints, int arrayOffset, int intCount) {
+      buffer.asIntBuffer().get(ints, arrayOffset, intCount);
       // Using a separate view does not update the position of this buffer so do it
       // explicitly.
-      skip(4 * intCount);
+      skip(Integer.BYTES * intCount);
+    }
+
+    @Override
+    public void readLongArray(long[] longs, int arrayOffset, int longCount) {
+      buffer.asLongBuffer().get(longs, arrayOffset, longCount);
+      // Using a separate view does not update the position of this buffer so do it
+      // explicitly.
+      skip(Long.BYTES * longCount);
     }
 
     @Override
@@ -813,7 +819,7 @@
       short value = buffer.asShortBuffer().get();
       // Using a separate view does not update the position of this buffer so do it
       // explicitly.
-      skip(2);
+      skip(Short.BYTES);
       return value;
     }
   }
diff --git a/mmodules/core_platform_api/api/platform/current-api.txt b/mmodules/core_platform_api/api/platform/current-api.txt
index dbc0201..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;
@@ -805,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);
@@ -1228,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 {
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/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/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/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
index 091b385..951b30c 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
@@ -176,7 +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.of(3), 2020 - YDIFF_REIWA, 2, 29, 60, LocalDate.of(2020, 2, 29)},
                 {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)},
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) {