Merge "Avoid additional Object allocations that are immediately unboxed"
diff --git a/benchmarks/src/benchmarks/regression/StringBuilderBenchmark.java b/benchmarks/src/benchmarks/regression/StringBuilderBenchmark.java
index 07a2305..ef54432 100644
--- a/benchmarks/src/benchmarks/regression/StringBuilderBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/StringBuilderBenchmark.java
@@ -63,6 +63,16 @@
         }
     }
 
+    public void timeAppendSubCharSequence(int reps) {
+        CharSequence cs = "chars";
+        for (int i = 0; i < reps; ++i) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < length; ++j) {
+                sb.append(cs);
+            }
+        }
+    }
+
     public void timeAppendDouble(int reps) {
         double d = 1.2;
         for (int i = 0; i < reps; ++i) {
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/FileChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/FileChannelTest.java
index f3b5f8b..d6dacb4 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/FileChannelTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/FileChannelTest.java
@@ -46,6 +46,8 @@
 
 import junit.framework.TestCase;
 
+import libcore.io.IoUtils;
+
 public class FileChannelTest extends TestCase {
 
     private static final int CAPACITY = 100;
@@ -76,8 +78,12 @@
 
     private FileChannel readOnlyFileChannel;
 
+    private FileChannel readOnlyFileChannel2;
+
     private FileChannel writeOnlyFileChannel;
 
+    private FileChannel writeOnlyFileChannel2;
+
     private FileChannel readWriteFileChannel;
 
     private File fileOfReadOnlyFileChannel;
@@ -121,41 +127,23 @@
         fileLock = null;
         readOnlyFileChannel = new FileInputStream(fileOfReadOnlyFileChannel)
                 .getChannel();
+        readOnlyFileChannel2 = new FileInputStream(fileOfReadOnlyFileChannel)
+                .getChannel();
         writeOnlyFileChannel = new FileOutputStream(fileOfWriteOnlyFileChannel)
                 .getChannel();
+        writeOnlyFileChannel2 = new FileOutputStream(fileOfWriteOnlyFileChannel)
+                .getChannel();
         readWriteFileChannel = new RandomAccessFile(fileOfReadWriteFileChannel,
                 "rw").getChannel();
     }
 
     protected void tearDown() {
-        if (null != readOnlyFileChannel) {
-            try {
-                readOnlyFileChannel.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != writeOnlyFileChannel) {
-            try {
-                writeOnlyFileChannel.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != readWriteFileChannel) {
-            try {
-                readWriteFileChannel.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != fis) {
-            try {
-                fis.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
+        IoUtils.closeQuietly(readOnlyFileChannel);
+        IoUtils.closeQuietly(readOnlyFileChannel2);
+        IoUtils.closeQuietly(writeOnlyFileChannel);
+        IoUtils.closeQuietly(writeOnlyFileChannel2);
+        IoUtils.closeQuietly(readWriteFileChannel);
+        IoUtils.closeQuietly(fis);
 
         if (null != fileLock) {
             try {
@@ -174,56 +162,15 @@
         if (null != fileOfReadWriteFileChannel) {
             fileOfReadWriteFileChannel.delete();
         }
-        if (null != datagramChannelSender) {
-            try {
-                datagramChannelSender.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != datagramChannelReceiver) {
-            try {
-                datagramChannelReceiver.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != serverSocketChannel) {
-            try {
-                serverSocketChannel.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != socketChannelSender) {
-            try {
-                socketChannelSender.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
-        if (null != socketChannelReceiver) {
-            try {
-                socketChannelReceiver.close();
-            } catch (IOException e) {
-                // do nothing
-            }
-        }
+
+        IoUtils.closeQuietly(datagramChannelSender);
+        IoUtils.closeQuietly(datagramChannelReceiver);
+        IoUtils.closeQuietly(serverSocketChannel);
+        IoUtils.closeQuietly(socketChannelSender);
+        IoUtils.closeQuietly(socketChannelReceiver);
         if (null != pipe) {
-            if (null != pipe.source()) {
-                try {
-                    pipe.source().close();
-                } catch (IOException e) {
-                    // do nothing
-                }
-            }
-            if (null != pipe.sink()) {
-                try {
-                    pipe.sink().close();
-                } catch (IOException e) {
-                    // do nothing
-                }
-            }
+            IoUtils.closeQuietly(pipe.source());
+            IoUtils.closeQuietly(pipe.sink());
         }
     }
 
@@ -653,14 +600,81 @@
     /**
      * @tests java.nio.channels.FileChannel#lock()
      */
+    public void test_lock_Closed() throws Exception {
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.lock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.lock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.lock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock()
+     */
+    public void test_lock_NonWritable() throws Exception {
+        try {
+            readOnlyFileChannel.lock();
+            fail("should throw NonWritableChannelException");
+        } catch (NonWritableChannelException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock()
+     */
     public void test_lock() throws Exception {
-        MockFileChannel mockFileChannel = new MockFileChannel();
-        // Verify that calling lock() leads to the method
-        // lock(long, long, boolean) being called with a 0 for the
-        // first parameter, Long.MAX_VALUE as the second parameter and false
-        // as the third parameter.
-        mockFileChannel.lock();
-        assertTrue(mockFileChannel.isLockCalled);
+        fileLock = writeOnlyFileChannel.lock();
+        assertTrue(fileLock.isValid());
+        assertFalse(fileLock.isShared());
+        assertSame(writeOnlyFileChannel, fileLock.channel());
+        assertEquals(Long.MAX_VALUE, fileLock.size());
+        assertEquals(0, fileLock.position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock()
+     */
+    public void test_lock_OverlappingException() throws Exception {
+        fileLock = writeOnlyFileChannel.lock();
+        assertTrue(fileLock.isValid());
+
+        // Test the same channel cannot be locked twice.
+        try {
+            writeOnlyFileChannel.lock();
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
+
+        // Test that a different channel on the same file also cannot be locked.
+        try {
+            writeOnlyFileChannel2.lock();
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock()
+     */
+    public void test_lock_After_Release() throws Exception {
+        fileLock = writeOnlyFileChannel.lock();
+        fileLock.release();
+        // After release file lock can be obtained again.
+        fileLock = writeOnlyFileChannel.lock();
+        assertTrue(fileLock.isValid());
+
+        // A different channel should be able to obtain a lock after it has been released
+        fileLock.release();
+        assertTrue(writeOnlyFileChannel2.lock().isValid());
     }
 
     /**
@@ -826,12 +840,17 @@
         fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
         assertTrue(fileLock.isValid());
 
+        // Test the same channel cannot be locked twice.
         try {
             writeOnlyFileChannel.lock(POSITION + 1, SIZE, false);
             fail("should throw OverlappingFileLockException");
-        } catch (OverlappingFileLockException e) {
-            // expected
-        }
+        } catch (OverlappingFileLockException expected) {}
+
+        // Test that a different channel on the same file also cannot be locked.
+        try {
+            writeOnlyFileChannel2.lock(POSITION + 1, SIZE, false);
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
     }
 
     /**
@@ -861,14 +880,88 @@
     /**
      * @tests java.nio.channels.FileChannel#tryLock()
      */
+    public void test_tryLock_Closed() throws Exception {
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.tryLock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.tryLock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.tryLock();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock()
+     */
+    public void test_tryLock_NonWritable() throws Exception {
+        try {
+            readOnlyFileChannel.tryLock();
+            fail("should throw NonWritableChannelException");
+        } catch (NonWritableChannelException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock()
+     */
     public void test_tryLock() throws Exception {
-        MockFileChannel mockFileChannel = new MockFileChannel();
-        // Verify that calling tryLock() leads to the method
-        // tryLock(long, long, boolean) being called with a 0 for the
-        // first parameter, Long.MAX_VALUE as the second parameter and false
-        // as the third parameter.
-        mockFileChannel.tryLock();
-        assertTrue(mockFileChannel.isTryLockCalled);
+        fileLock = writeOnlyFileChannel.tryLock();
+        assertTrue(fileLock.isValid());
+        assertFalse(fileLock.isShared());
+        assertSame(writeOnlyFileChannel, fileLock.channel());
+        assertEquals(0, fileLock.position());
+        assertEquals(Long.MAX_VALUE, fileLock.size());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock()
+     */
+    public void test_tryLock_Overlapping() throws Exception {
+        fileLock = writeOnlyFileChannel.tryLock();
+        assertTrue(fileLock.isValid());
+
+        // Test the same channel cannot be locked twice.
+        try {
+            writeOnlyFileChannel.tryLock();
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
+
+        // Test that a different channel on the same file also cannot be locked.
+        try {
+            writeOnlyFileChannel2.tryLock();
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock()
+     */
+    public void test_tryLock_After_Release() throws Exception {
+        fileLock = writeOnlyFileChannel.tryLock();
+        fileLock.release();
+
+        // After release file lock can be obtained again.
+        fileLock = writeOnlyFileChannel.tryLock();
+        assertTrue(fileLock.isValid());
+
+        // Test that the same channel can acquire the lock after it has been released
+        fileLock.release();
+        fileLock = writeOnlyFileChannel.tryLock();
+        assertTrue(fileLock.isValid());
+
+        // Test that a different channel can acquire the lock after it has been released
+        fileLock.release();
+        fileLock = writeOnlyFileChannel2.tryLock();
+        assertTrue(fileLock.isValid());
     }
 
     /**
@@ -1034,12 +1127,17 @@
         fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
         assertTrue(fileLock.isValid());
 
+        // Test the same channel cannot be locked twice.
         try {
-            writeOnlyFileChannel.lock(POSITION + 1, SIZE, false);
+            writeOnlyFileChannel.tryLock(POSITION + 1, SIZE, false);
             fail("should throw OverlappingFileLockException");
-        } catch (OverlappingFileLockException e) {
-            // expected
-        }
+        } catch (OverlappingFileLockException expected) {}
+
+        // Test that a different channel on the same file also cannot be locked.
+        try {
+            writeOnlyFileChannel2.tryLock(POSITION + 1, SIZE, false);
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException expected) {}
     }
 
     /**
diff --git a/json/src/main/java/org/json/JSONObject.java b/json/src/main/java/org/json/JSONObject.java
index 9ea91a6..7902389 100644
--- a/json/src/main/java/org/json/JSONObject.java
+++ b/json/src/main/java/org/json/JSONObject.java
@@ -21,6 +21,7 @@
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 // Note: this class was written without inspecting the non-free org.json sourcecode.
@@ -100,6 +101,8 @@
         @Override public boolean equals(Object o) {
             return o == this || o == null; // API specifies this broken equals implementation
         }
+        // at least make the broken equals(null) consistent with Objects.hashCode(null).
+        @Override public int hashCode() { return Objects.hashCode(null); }
         @Override public String toString() {
             return "null";
         }
diff --git a/json/src/test/java/org/json/JSONObjectTest.java b/json/src/test/java/org/json/JSONObjectTest.java
index 9029ec6..07d1cf6 100644
--- a/json/src/test/java/org/json/JSONObjectTest.java
+++ b/json/src/test/java/org/json/JSONObjectTest.java
@@ -27,6 +27,7 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Set;
 import java.util.TreeMap;
 import junit.framework.TestCase;
@@ -825,6 +826,12 @@
         assertTrue(object.isNull("bar"));
     }
 
+    public void testNullValue_equalsAndHashCode() {
+        assertTrue(JSONObject.NULL.equals(null)); // guaranteed by javadoc
+        // not guaranteed by javadoc, but seems like a good idea
+        assertEquals(Objects.hashCode(null), JSONObject.NULL.hashCode());
+    }
+
     public void testHas() throws JSONException {
         JSONObject object = new JSONObject();
         object.put("foo", 5);
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 74aedd4..8b27ca2 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -396,4 +396,10 @@
      * set.
      */
     public static native boolean didPruneDalvikCache();
+
+    /**
+     * Register the current execution thread to the runtime as sensitive thread.
+     * Should be called just once. Subsequent calls are ignored.
+     */
+    public static native void registerSensitiveThread();
 }
diff --git a/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java b/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
index 38be0c2..0a73c9f 100644
--- a/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
+++ b/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
@@ -68,6 +68,7 @@
     private CharsetDecoderICU(Charset cs, float averageCharsPerByte, long address) {
         super(cs, averageCharsPerByte, MAX_CHARS_PER_BYTE);
         this.converterHandle = address;
+        NativeConverter.registerConverter(this, converterHandle);
     }
 
     @Override protected void implReplaceWith(String newReplacement) {
@@ -155,14 +156,6 @@
         }
     }
 
-    @Override protected void finalize() throws Throwable {
-        try {
-            NativeConverter.closeConverter(converterHandle);
-            converterHandle = 0;
-        } finally {
-            super.finalize();
-        }
-    }
 
     private int getArray(CharBuffer out) {
         if (out.hasArray()) {
diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
index 3583e19..a981c18 100644
--- a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
+++ b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
@@ -21,6 +21,7 @@
 import libcore.icu.ICU;
 import libcore.icu.NativeConverter;
 import libcore.util.EmptyArray;
+import libcore.util.NativeAllocationRegistry;
 
 final class CharsetEncoderICU extends CharsetEncoder {
     private static final Map<String, byte[]> DEFAULT_REPLACEMENTS = new HashMap<String, byte[]>();
@@ -49,7 +50,7 @@
     private int[] data = new int[3];
 
     /* handle to the ICU converter that is opened */
-    private long converterHandle=0;
+    private final long converterHandle;
 
     private char[] input = null;
     private byte[] output = null;
@@ -95,6 +96,7 @@
         super(cs, averageBytesPerChar, maxBytesPerChar, replacement, true);
         // Our native peer needs to know what just happened...
         this.converterHandle = address;
+        NativeConverter.registerConverter(this, converterHandle);
         updateCallback();
     }
 
@@ -184,15 +186,6 @@
         }
     }
 
-    @Override protected void finalize() throws Throwable {
-        try {
-            NativeConverter.closeConverter(converterHandle);
-            converterHandle=0;
-        } finally {
-            super.finalize();
-        }
-    }
-
     private int getArray(ByteBuffer out) {
         if (out.hasArray()) {
             output = out.array();
diff --git a/luni/src/main/java/libcore/icu/NativeConverter.java b/luni/src/main/java/libcore/icu/NativeConverter.java
index 17be458..a2b5798 100644
--- a/luni/src/main/java/libcore/icu/NativeConverter.java
+++ b/luni/src/main/java/libcore/icu/NativeConverter.java
@@ -9,12 +9,17 @@
 
 package libcore.icu;
 
+import libcore.util.NativeAllocationRegistry;
+
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CodingErrorAction;
 
 public final class NativeConverter {
+    private static final NativeAllocationRegistry registry = new NativeAllocationRegistry(
+            getNativeFinalizer(), getNativeSize());
+
     public static native int decode(long converterHandle, byte[] input, int inEnd,
             char[] output, int outEnd, int[] data, boolean flush);
 
@@ -24,6 +29,10 @@
     public static native long openConverter(String charsetName);
     public static native void closeConverter(long converterHandle);
 
+    public static void registerConverter(Object referrent, long converterHandle) {
+        registry.registerNativeAllocation(referrent, converterHandle);
+    }
+
     public static native void resetByteToChar(long converterHandle);
     public static native void resetCharToByte(long converterHandle);
 
@@ -67,4 +76,7 @@
                           encoder.replacement());
     }
     private static native void setCallbackEncode(long converterHandle, int onMalformedInput, int onUnmappableInput, byte[] subBytes);
+
+    public static native long getNativeFinalizer();
+    public static native long getNativeSize();
 }
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index 334f4c9..bf938d1 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -611,6 +611,20 @@
             javaCanonicalName, icuCanonicalNameStr, javaAliases);
 }
 
+static void FreeNativeConverter(void *converter) {
+    ucnv_close(reinterpret_cast<UConverter*>(converter));
+}
+
+static jlong NativeConverter_getNativeFinalizer(JNIEnv*, jclass) {
+    return reinterpret_cast<jlong>(&FreeNativeConverter);
+}
+
+
+static jlong NativeConverter_getNativeSize(JNIEnv*, jclass, jstring) {
+    // TODO: Improve estimate.
+    return 200;
+}
+
 static JNINativeMethod gMethods[] = {
     NATIVE_METHOD(NativeConverter, charsetForName, "(Ljava/lang/String;)Ljava/nio/charset/Charset;"),
     NATIVE_METHOD(NativeConverter, closeConverter, "(J)V"),
@@ -628,6 +642,8 @@
     NATIVE_METHOD(NativeConverter, resetCharToByte, "(J)V"),
     NATIVE_METHOD(NativeConverter, setCallbackDecode, "(JIILjava/lang/String;)V"),
     NATIVE_METHOD(NativeConverter, setCallbackEncode, "(JII[B)V"),
+    NATIVE_METHOD(NativeConverter, getNativeFinalizer, "()J"),
+    NATIVE_METHOD(NativeConverter, getNativeSize, "()J")
 };
 void register_libcore_icu_NativeConverter(JNIEnv* env) {
     jniRegisterNativeMethods(env, "libcore/icu/NativeConverter", gMethods, NELEM(gMethods));
diff --git a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
index 0eae20a..2b8b566 100644
--- a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
@@ -283,6 +283,13 @@
         assertEquals(expected, numberFormat.format(2.01));
     }
 
+    // http://b/27855939
+    public void testBug27855939() {
+        DecimalFormat df = new DecimalFormat("00");
+        assertEquals("01", df.format(BigDecimal.ONE));
+        assertEquals("00", df.format(BigDecimal.ZERO));
+    }
+
     // Confirm the currency symbol used by a format is determined by the locale of the format
     // not the current default Locale.
     public void testSetCurrency_symbolOrigin() {
diff --git a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
index e11ae3c..dfc2c6b 100755
--- a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -478,8 +478,16 @@
                 + s.length());
         int len = end - start;
         ensureCapacityInternal(count + len);
-        for (int i = start, j = count; i < end; i++, j++)
-            value[j] = s.charAt(i);
+        if (s instanceof String) {
+            ((String) s).getCharsNoCheck(start, end, value, count);
+        } else if (s instanceof AbstractStringBuilder) {
+            AbstractStringBuilder other = (AbstractStringBuilder) s;
+            System.arraycopy(other.value, start, value, count, len);
+        } else {
+            for (int i = start, j = count; i < end; i++, j++) {
+                value[j] = s.charAt(i);
+            }
+        }
         count += len;
         return this;
     }
diff --git a/ojluni/src/main/java/java/text/DecimalFormat.java b/ojluni/src/main/java/java/text/DecimalFormat.java
index b8eade3..bcc9e8b 100755
--- a/ojluni/src/main/java/java/text/DecimalFormat.java
+++ b/ojluni/src/main/java/java/text/DecimalFormat.java
@@ -465,10 +465,7 @@
     private void init(String pattern) {
         this.icuDecimalFormat =  new android.icu.text.DecimalFormat(pattern,
                 symbols.getIcuDecimalFormatSymbols());
-        maximumIntegerDigits = icuDecimalFormat.getMaximumIntegerDigits();
-        minimumIntegerDigits = icuDecimalFormat.getMinimumIntegerDigits();
-        maximumFractionDigits = icuDecimalFormat.getMaximumFractionDigits();
-        minimumFractionDigits = icuDecimalFormat.getMinimumFractionDigits();
+        updateFieldsFromIcu();
     }
 
     /**
@@ -1169,6 +1166,12 @@
     }
 
     private void updateFieldsFromIcu() {
+        // Imitate behaviour of ICU4C NumberFormat that Android used up to M.
+        // If the pattern doesn't enforce a different value (some exponential
+        // patterns do), then set the maximum integer digits to 2 billion.
+        if (icuDecimalFormat.getMaximumIntegerDigits() == DOUBLE_INTEGER_DIGITS) {
+            icuDecimalFormat.setMaximumIntegerDigits(2000000000);
+        }
         maximumIntegerDigits = icuDecimalFormat.getMaximumIntegerDigits();
         minimumIntegerDigits = icuDecimalFormat.getMinimumIntegerDigits();
         maximumFractionDigits = icuDecimalFormat.getMaximumFractionDigits();
diff --git a/ojluni/src/main/java/java/util/Collections.java b/ojluni/src/main/java/java/util/Collections.java
index 2dff95d..1a9f83a 100644
--- a/ojluni/src/main/java/java/util/Collections.java
+++ b/ojluni/src/main/java/java/util/Collections.java
@@ -2883,14 +2883,6 @@
         public boolean addAll(int index, Collection<? extends E> c) {
             return list.addAll(index, checkedCopyOf(c));
         }
-        @Override
-        public void replaceAll(UnaryOperator<E> operator) {
-            list.replaceAll(operator);
-        }
-        @Override
-        public void sort(Comparator<? super E> c) {
-            list.sort(c);
-        }
         public ListIterator<E> listIterator()   { return listIterator(0); }
 
         public ListIterator<E> listIterator(final int index) {
@@ -2925,6 +2917,32 @@
         public List<E> subList(int fromIndex, int toIndex) {
             return new CheckedList<>(list.subList(fromIndex, toIndex), type);
         }
+
+        /**
+         * {@inheritDoc}
+         *
+         * @throws ClassCastException if the class of an element returned by the
+         *         operator prevents it from being added to this collection. The
+         *         exception may be thrown after some elements of the list have
+         *         already been replaced.
+         */
+        @Override
+        public void replaceAll(UnaryOperator<E> operator) {
+            Objects.requireNonNull(operator);
+
+            // Android-changed: Modified from OpenJDK 8 code because typeCheck returns void in
+            // OpenJDK 7.
+            list.replaceAll(e -> {
+                    E newValue = operator.apply(e);
+                    typeCheck(newValue);
+                    return newValue;
+            });
+        }
+
+        @Override
+        public void sort(Comparator<? super E> c) {
+            list.sort(c);
+        }
     }
 
     /**
diff --git a/ojluni/src/main/java/java/util/Spliterators.java b/ojluni/src/main/java/java/util/Spliterators.java
index 3f97a83..79c0ef3 100644
--- a/ojluni/src/main/java/java/util/Spliterators.java
+++ b/ojluni/src/main/java/java/util/Spliterators.java
@@ -384,7 +384,7 @@
      */
     private static void checkFromToBounds(int arrayLength, int origin, int fence) {
         if (origin > fence) {
-            throw new IllegalArgumentException(
+            throw new ArrayIndexOutOfBoundsException(
                     "origin(" + origin + ") > fence(" + fence + ")");
         }
         if (origin < 0) {
diff --git a/support/src/test/java/libcore/java/security/CpuFeatures.java b/support/src/test/java/libcore/java/security/CpuFeatures.java
index 30ca868..319056a 100644
--- a/support/src/test/java/libcore/java/security/CpuFeatures.java
+++ b/support/src/test/java/libcore/java/security/CpuFeatures.java
@@ -19,6 +19,8 @@
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.List;
 import java.util.regex.Matcher;
@@ -39,6 +41,19 @@
             return true;
         }
 
+        // If we're in an emulated ABI, Conscrypt's NativeCrypto might bridge to
+        // a library that has accelerated AES instructions. See if Conscrypt
+        // detects that condition.
+        try {
+            Class<?> nativeCrypto = Class.forName("com.android.org.conscrypt.NativeCrypto");
+            Method EVP_has_aes_hardware = nativeCrypto.getDeclaredMethod("EVP_has_aes_hardware");
+            return ((Integer) EVP_has_aes_hardware.invoke(null)) == 1;
+        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException
+                | IllegalAccessException | IllegalArgumentException ignored) {
+        } catch (InvocationTargetException e) {
+            throw new IllegalArgumentException(e);
+        }
+
         return false;
     }