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 =