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;
}