Merge "Removing 1.9 as fixed target for libcore libraries"
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index a2c7387..e5aa957 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -702,9 +702,6 @@
"ojluni/src/test/java/**/*.java",
"ojluni/src/test/javax/**/*.java",
],
- exclude_srcs: [
- "ojluni/src/test/java/lang/invoke/VarHandles/**/*ByteArray*.java",
- ],
java_resource_dirs: [
"ojluni/src/test/java",
"ojluni/src/test/resources",
@@ -768,12 +765,10 @@
// and won't actually run, and
// 2.) util/stream/boot*. Those directories contain classes in the package java.util.stream;
// excluding them means we don't need patch_module: "java.base"
- // 3.) java.lang.invoke.VarHandles. A few issues to clear out then address b/203822478.
exclude_srcs: [
"**/DeserializeMethodTest.java",
"**/SerializedLambdaTest.java",
"ojluni/src/test/java/util/stream/boot*/**/*",
- "ojluni/src/test/java/lang/invoke/VarHandles/**/*ByteArray*.java",
],
java_resource_dirs: [
"ojluni/src/test/java",
diff --git a/api/current.txt b/api/current.txt
index 7034335..237d049c 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -5864,6 +5864,8 @@
}
public abstract class ByteBuffer extends java.nio.Buffer implements java.lang.Comparable<java.nio.ByteBuffer> {
+ method @NonNull public final java.nio.ByteBuffer alignedSlice(int);
+ method public final int alignmentOffset(int, int);
method @NonNull public static java.nio.ByteBuffer allocate(int);
method @NonNull public static java.nio.ByteBuffer allocateDirect(int);
method @NonNull public final byte[] array();
diff --git a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
index 555654e..69621cb 100644
--- a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
+++ b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
@@ -41,6 +41,7 @@
import libcore.io.IoUtils;
import libcore.io.Libcore;
import libcore.io.Os;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.IFF_LOOPBACK;
@@ -114,6 +115,7 @@
}
}
+ @EnableCompatChanges({NetworkInterface.RETURN_NULL_HARDWARE_ADDRESS})
public void testGetHardwareAddress_returnsNull() throws Exception {
// Hardware addresses should be unavailable to non-system apps.
for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
diff --git a/luni/src/test/java/libcore/java/nio/BufferTest.java b/luni/src/test/java/libcore/java/nio/BufferTest.java
index f808092..e826967 100644
--- a/luni/src/test/java/libcore/java/nio/BufferTest.java
+++ b/luni/src/test/java/libcore/java/nio/BufferTest.java
@@ -251,6 +251,14 @@
b.order(ByteOrder.LITTLE_ENDIAN);
assertEquals(ByteOrder.BIG_ENDIAN, b.slice().order());
+ // alignedSlice always returns a big-endian buffer.
+ b.order(ByteOrder.BIG_ENDIAN);
+ assertEquals(ByteOrder.BIG_ENDIAN, b.alignedSlice(4).order());
+ assertEquals(0, b.alignedSlice(4).alignmentOffset(0, 4));
+ b.order(ByteOrder.LITTLE_ENDIAN);
+ assertEquals(ByteOrder.BIG_ENDIAN, b.alignedSlice(4).order());
+ assertEquals(0, b.alignedSlice(2).alignmentOffset(0, 2));
+
// asXBuffer always returns a current-endian buffer.
b.order(ByteOrder.BIG_ENDIAN);
assertEquals(ByteOrder.BIG_ENDIAN, b.asCharBuffer().order());
@@ -639,6 +647,27 @@
assertEquals(directBuffer.arrayOffset() + 1, directSlice.arrayOffset());
}
+ public void testAlignedSliceOffset() throws Exception {
+ final ByteBuffer [] buffers = {
+ ByteBuffer.allocate(10),
+ ByteBuffer.allocateDirect(10),
+ ByteBuffer.wrap(new byte[10]),
+ ByteBuffer.wrap(new byte[10], 1, 8),
+ };
+
+ for (ByteBuffer buffer: buffers) {
+ for (int i = 0; i < 4; ++i) {
+ // Slicing changes the array offset.
+ ByteBuffer slice = ((ByteBuffer) buffer.duplicate().position(i)).alignedSlice(4);
+ for (int j = 0; j < 4; ++j) {
+ assertEquals(j, slice.alignmentOffset(j, 4));
+ }
+ assertEquals(0, slice.limit() % 4);
+ assertTrue(buffer.limit() > 0);
+ }
+ }
+ }
+
// http://code.google.com/p/android/issues/detail?id=16184
public void testPutByteBuffer() throws Exception {
ByteBuffer dst = ByteBuffer.allocate(10).asReadOnlyBuffer();
@@ -1441,4 +1470,41 @@
FinalizationTester.induceFinalization();
assertTrue(pr.isEnqueued());
}
+
+ private void alignmentOffsetChecks(final ByteBuffer buffer) {
+
+ for (int start = 0; start < buffer.limit(); ++start) {
+ buffer.position(start);
+ final ByteBuffer bb = buffer.slice();
+ for (int unitSize = 1; unitSize <= 8; unitSize *= 2) {
+ try {
+ bb.alignmentOffset(-1 - start, unitSize);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ if (unitSize > 2) {
+ try {
+ bb.alignmentOffset(0, unitSize - 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ int alignmentAtZero = bb.alignmentOffset(0, unitSize);
+ for (int i = 0; i < bb.limit(); ++i) {
+ assertEquals((alignmentAtZero + i) % unitSize, bb.alignmentOffset(i, unitSize));
+ }
+ }
+ }
+ }
+
+ public void test_alignmentOffset() throws Exception {
+ alignmentOffsetChecks(ByteBuffer.allocateDirect(32));
+ alignmentOffsetChecks(ByteBuffer.allocate(32));
+
+ byte[] array = new byte[32];
+ alignmentOffsetChecks(ByteBuffer.wrap(array));
+ alignmentOffsetChecks(ByteBuffer.wrap(array, 1, 31));
+ }
}
diff --git a/ojluni/annotations/sdk/nullability/java/nio/ByteBuffer.annotated.java b/ojluni/annotations/sdk/nullability/java/nio/ByteBuffer.annotated.java
index 30c82ec..adea368 100644
--- a/ojluni/annotations/sdk/nullability/java/nio/ByteBuffer.annotated.java
+++ b/ojluni/annotations/sdk/nullability/java/nio/ByteBuffer.annotated.java
@@ -100,6 +100,8 @@
@libcore.util.NonNull public final java.nio.ByteBuffer order(@libcore.util.NonNull java.nio.ByteOrder bo) { throw new RuntimeException("Stub!"); }
+@libcore.util.NonNull public final java.nio.ByteBuffer alignedSlice(int unitSize) { throw new RuntimeException("Stub!"); }
+
public abstract char getChar();
@libcore.util.NonNull public abstract java.nio.ByteBuffer putChar(char value);
diff --git a/ojluni/src/main/java/java/net/NetworkInterface.java b/ojluni/src/main/java/java/net/NetworkInterface.java
index d38d2ba..f09c48b 100644
--- a/ojluni/src/main/java/java/net/NetworkInterface.java
+++ b/ojluni/src/main/java/java/net/NetworkInterface.java
@@ -73,10 +73,12 @@
* If this change is enabled, {@link #getHardwareAddress()} returns null when the hardware
* address is <a href="#access-restrictions">inaccessible</a>. If the change is disabled, the
* default MAC address (02:00:00:00:00:00) is returned instead.
+ *
+ * @hide
*/
@ChangeId
@EnabledSince(targetSdkVersion=VersionCodes.R)
- static final long RETURN_NULL_HARDWARE_ADDRESS = 170188668L;
+ public static final long RETURN_NULL_HARDWARE_ADDRESS = 170188668L;
// The default hardware address is a zeroed-out MAC address with only its
// locally-administered bit set, returned to apps targeting older API versions if they would
// otherwise see a null MAC address.
diff --git a/ojluni/src/main/java/java/nio/ByteBuffer.java b/ojluni/src/main/java/java/nio/ByteBuffer.java
index b286cbd..bec1079 100644
--- a/ojluni/src/main/java/java/nio/ByteBuffer.java
+++ b/ojluni/src/main/java/java/nio/ByteBuffer.java
@@ -28,6 +28,8 @@
package java.nio;
+import jdk.internal.misc.Unsafe;
+
import libcore.io.Memory;
import dalvik.annotation.codegen.CovariantReturnType;
@@ -1069,6 +1071,150 @@
return this;
}
+ /**
+ * Returns the memory address, pointing to the byte at the given index,
+ * modulus the given unit size.
+ *
+ * <p> A return value greater than zero indicates the address of the byte at
+ * the index is misaligned for the unit size, and the value's quantity
+ * indicates how much the index should be rounded up or down to locate a
+ * byte at an aligned address. Otherwise, a value of {@code 0} indicates
+ * that the address of the byte at the index is aligned for the unit size.
+ *
+ * @apiNote
+ * This method may be utilized to determine if unit size bytes from an
+ * index can be accessed atomically, if supported by the native platform.
+ *
+ * @implNote
+ * This implementation throws {@code UnsupportedOperationException} for
+ * non-direct buffers when the given unit size is greater than {@code 8}.
+ *
+ * @param index
+ * The index to query for alignment offset, must be non-negative, no
+ * upper bounds check is performed
+ *
+ * @param unitSize
+ * The unit size in bytes, must be a power of {@code 2}
+ *
+ * @return The indexed byte's memory address modulus the unit size
+ *
+ * @throws IllegalArgumentException
+ * If the index is negative or the unit size is not a power of
+ * {@code 2}
+ *
+ * @throws UnsupportedOperationException
+ * If the native platform does not guarantee stable alignment offset
+ * values for the given unit size when managing the memory regions
+ * of buffers of the same kind as this buffer (direct or
+ * non-direct). For example, if garbage collection would result
+ * in the moving of a memory region covered by a non-direct buffer
+ * from one location to another and both locations have different
+ * alignment characteristics.
+ *
+ * @see #alignedSlice(int)
+ * @since 9
+ */
+ public final int alignmentOffset(int index, int unitSize) {
+ if (index < 0)
+ throw new IllegalArgumentException("Index less than zero: " + index);
+ if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
+ throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
+ if (unitSize > 8 && !isDirect())
+ throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
+
+ // BEGIN Android-changed: Android specific alignment calculation.
+ // return (int) ((address + index) % unitSize);
+ final long baseAddress =
+ isDirect() ? address : (Unsafe.getUnsafe().arrayBaseOffset(byte[].class) + offset);
+
+ final long elementAddress = baseAddress + index;
+ return (int) (elementAddress & (unitSize - 1));
+ // END Android-changed: Android specific alignment calculation.
+ }
+
+ /**
+ * Creates a new byte buffer whose content is a shared and aligned
+ * subsequence of this buffer's content.
+ *
+ * <p> The content of the new buffer will start at this buffer's current
+ * position rounded up to the index of the nearest aligned byte for the
+ * given unit size, and end at this buffer's limit rounded down to the index
+ * of the nearest aligned byte for the given unit size.
+ * If rounding results in out-of-bound values then the new buffer's capacity
+ * and limit will be zero. If rounding is within bounds the following
+ * expressions will be true for a new buffer {@code nb} and unit size
+ * {@code unitSize}:
+ * <pre>{@code
+ * nb.alignmentOffset(0, unitSize) == 0
+ * nb.alignmentOffset(nb.limit(), unitSize) == 0
+ * }</pre>
+ *
+ * <p> Changes to this buffer's content will be visible in the new
+ * buffer, and vice versa; the two buffers' position, limit, and mark
+ * values will be independent.
+ *
+ * <p> The new buffer's position will be zero, its capacity and its limit
+ * will be the number of bytes remaining in this buffer or fewer subject to
+ * alignment, its mark will be undefined, and its byte order will be
+ * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+ *
+ * The new buffer will be direct if, and only if, this buffer is direct, and
+ * it will be read-only if, and only if, this buffer is read-only. </p>
+ *
+ * @apiNote
+ * This method may be utilized to create a new buffer where unit size bytes
+ * from index, that is a multiple of the unit size, may be accessed
+ * atomically, if supported by the native platform.
+ *
+ * @implNote
+ * This implementation throws {@code UnsupportedOperationException} for
+ * non-direct buffers when the given unit size is greater than {@code 8}.
+ *
+ * @param unitSize
+ * The unit size in bytes, must be a power of {@code 2}
+ *
+ * @return The new byte buffer
+ *
+ * @throws IllegalArgumentException
+ * If the unit size not a power of {@code 2}
+ *
+ * @throws UnsupportedOperationException
+ * If the native platform does not guarantee stable aligned slices
+ * for the given unit size when managing the memory regions
+ * of buffers of the same kind as this buffer (direct or
+ * non-direct). For example, if garbage collection would result
+ * in the moving of a memory region covered by a non-direct buffer
+ * from one location to another and both locations have different
+ * alignment characteristics.
+ *
+ * @see #alignmentOffset(int, int)
+ * @see #slice()
+ * @since 9
+ */
+ public final ByteBuffer alignedSlice(int unitSize) {
+ int pos = position();
+ int lim = limit();
+
+ int pos_mod = alignmentOffset(pos, unitSize);
+ int lim_mod = alignmentOffset(lim, unitSize);
+
+ // Round up the position to align with unit size
+ int aligned_pos = (pos_mod > 0)
+ ? pos + (unitSize - pos_mod)
+ : pos;
+
+ // Round down the limit to align with unit size
+ int aligned_lim = lim - lim_mod;
+
+ if (aligned_pos > lim || aligned_lim < pos) {
+ aligned_pos = aligned_lim = pos;
+ }
+
+ return slice(aligned_pos, aligned_lim);
+ }
+
+ abstract ByteBuffer slice(int pos, int lim);
+
// Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
//
abstract byte _get(int i); // package-private
diff --git a/ojluni/src/main/java/java/nio/DirectByteBuffer.java b/ojluni/src/main/java/java/nio/DirectByteBuffer.java
index 3e06011..7d883a3 100644
--- a/ojluni/src/main/java/java/nio/DirectByteBuffer.java
+++ b/ojluni/src/main/java/java/nio/DirectByteBuffer.java
@@ -167,6 +167,18 @@
return new DirectByteBuffer(memoryRef, -1, 0, rem, rem, off, isReadOnly);
}
+ ByteBuffer slice(int pos, int lim) {
+ if (!memoryRef.isAccessible) {
+ throw new IllegalStateException("buffer is inaccessible");
+ }
+ assert (pos >= 0);
+ assert (pos <= lim);
+ int rem = (pos <= lim ? lim - pos : 0);
+ int off = pos + offset;
+ assert (off >= 0);
+ return new DirectByteBuffer(memoryRef, -1, 0, rem, rem, off, isReadOnly);
+ }
+
@Override
public final ByteBuffer duplicate() {
if (memoryRef.isFreed) {
diff --git a/ojluni/src/main/java/java/nio/HeapByteBuffer.java b/ojluni/src/main/java/java/nio/HeapByteBuffer.java
index 4666638..b9d332b 100644
--- a/ojluni/src/main/java/java/nio/HeapByteBuffer.java
+++ b/ojluni/src/main/java/java/nio/HeapByteBuffer.java
@@ -81,6 +81,19 @@
isReadOnly);
}
+ ByteBuffer slice(int pos, int lim) {
+ assert (pos >= 0);
+ assert (pos <= lim);
+ int rem = lim - pos;
+ return new HeapByteBuffer(hb,
+ -1,
+ 0,
+ rem,
+ rem,
+ pos + offset,
+ isReadOnly);
+ }
+
@Override
public ByteBuffer duplicate() {
return new HeapByteBuffer(hb,
diff --git a/ojluni/src/main/native/net_util_md.c b/ojluni/src/main/native/net_util_md.c
index 3fb3eb6..23c4d24 100644
--- a/ojluni/src/main/native/net_util_md.c
+++ b/ojluni/src/main/native/net_util_md.c
@@ -1097,6 +1097,7 @@
// Android-changed: This is out-dated RFC 1349 scheme. Modern Linux uses
// Diffsev/ECN, and this mask is no longer relavant.
// *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
+ (void) iptos;
}
/*
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java
index 93afaad..9679883 100644
--- a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java
@@ -319,8 +319,9 @@
MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
bavss.add(dbb_ro);
+ // Android-changed: Use ByteBuffer.slice() rather than Buffer.slice().
ByteBufferSource dbb_offset_aligned =
- new ByteBufferSource(dbb.s.slice().position(array.length / 4).limit(array.length / 4 + array.length / 2).slice(),
+ new ByteBufferSource(((ByteBuffer) dbb.s.slice().position(array.length / 4).limit(array.length / 4 + array.length / 2)).slice(),
MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
bavss.add(dbb_offset_aligned);
ByteBufferReadOnlySource dbb_offset_aligned_ro =
@@ -328,8 +329,9 @@
MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
bavss.add(dbb_offset_aligned_ro);
+ // Android-changed: Use ByteBuffer.slice() rather than Buffer.slice().
ByteBufferSource dbb_offset_unaligned =
- new ByteBufferSource(dbb.s.slice().position(array.length / 4 - 1).limit(array.length / 4 - 1 + array.length / 2).slice(),
+ new ByteBufferSource(((ByteBuffer) dbb.s.slice().position(array.length / 4 - 1).limit(array.length / 4 - 1 + array.length / 2)).slice(),
MemoryMode.UNALIGNED, ne, MemoryMode.READ_WRITE);
bavss.add(dbb_offset_unaligned);
ByteBufferReadOnlySource dbb_offset_unaligned_ro =