Merge "Remove unused methods in InetAddress"
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index 813b6db..f185573 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -275,6 +275,21 @@
     ],
 }
 
+//
+// Local droiddoc for faster libcore testing
+//
+// Run with:
+//     mm -j32 core-docs
+//
+// Main output:
+//     ../out/soong/.intermediates/libcore/core-docs/android_common/docs/out/reference/packages.html
+//
+// All text for proofreading (or running tools over):
+//     ../out/soong/.intermediates/libcore/core-docs/android_common/core-docs-proofread.txt
+//
+// TODO list of missing javadoc, etc:
+//     ../out/soong/.intermediates/libcore/core-docs/android_common/docs/out/core-docs-todo.html
+//
 droiddoc {
     name: "core-docs",
     srcs: [
@@ -304,3 +319,34 @@
         "known_oj_tags.txt",
     ],
 }
+
+droiddoc {
+    name: "core-current-stubs-gen-docs",
+    srcs: [
+        ":openjdk_javadoc_files",
+        ":non_openjdk_javadoc_files",
+        ":android_icu4j_src_files_for_docs",
+        ":gen-ojluni-jaif-annotated-srcs",
+    ],
+    exclude_srcs: [
+        ":annotated_ojluni_files",
+    ],
+    custom_template: "droiddoc-templates-sdk",
+    installable: false,
+    no_framework_libs: true,
+    args: "-nodocs",
+}
+
+java_library_static {
+    name: "core.current.stubs",
+    srcs: [
+        ":core-current-stubs-gen-docs",
+    ],
+    errorprone: {
+        javacflags: [
+            "-Xep:MissingOverride:OFF",
+        ],
+    },
+    no_standard_libs: true,
+    system_modules: "none",
+}
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 81fb460..1a79aa7 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -205,8 +205,6 @@
     LOCAL_DX_FLAGS := --core-library
     LOCAL_MODULE_TAGS := optional
     LOCAL_MODULE := core-ojtests
-    # jack bug workaround: int[] java.util.stream.StatefulTestOp.-getjava-util-stream-StreamShapeSwitchesValues() is a private synthetic method in an interface which causes a hard verifier error
-    LOCAL_DEX_PREOPT := false # disable AOT preverification which breaks the build. it will still throw VerifyError at runtime.
     LOCAL_ERROR_PRONE_FLAGS := -Xep:MissingOverride:OFF
     include $(BUILD_JAVA_LIBRARY)
 endif
@@ -234,8 +232,6 @@
     LOCAL_DX_FLAGS := --core-library
     LOCAL_MODULE_TAGS := optional
     LOCAL_MODULE := core-ojtests-public
-    # jack bug workaround: int[] java.util.stream.StatefulTestOp.-getjava-util-stream-StreamShapeSwitchesValues() is a private synthetic method in an interface which causes a hard verifier error
-    LOCAL_DEX_PREOPT := false # disable AOT preverification which breaks the build. it will still throw VerifyError at runtime.
     LOCAL_ERROR_PRONE_FLAGS := -Xep:MissingOverride:OFF
     include $(BUILD_JAVA_LIBRARY)
 endif
@@ -313,99 +309,6 @@
 
 endif # HOST_OS == linux
 
-#
-# Local droiddoc for faster libcore testing
-#
-#
-# Run with:
-#     mm -j32 libcore-docs
-#
-# Main output:
-#     ../out/target/common/docs/libcore/reference/packages.html
-#
-# All text for proofreading (or running tools over):
-#     ../out/target/common/docs/libcore-proofread.txt
-#
-# TODO list of missing javadoc, etc:
-#     ../out/target/common/docs/libcore-docs-todo.html
-#
-# Rerun:
-#     rm -rf ../out/target/common/docs/libcore-timestamp && mm -j32 libcore-docs
-#
-include $(CLEAR_VARS)
-
-# for shared defintion of libcore_to_document
-include $(LOCAL_PATH)/Docs.mk
-
-# The libcore_to_document paths are relative to $(TOPDIR). We are in libcore so we must prepend
-# ../ to make LOCAL_SRC_FILES relative to $(LOCAL_PATH).
-LOCAL_SRC_FILES := $(addprefix ../, $(libcore_to_document))
-LOCAL_INTERMEDIATE_SOURCES := \
-    $(patsubst $(TARGET_OUT_COMMON_INTERMEDIATES)/%,%,$(libcore_to_document_generated))
-LOCAL_ADDITIONAL_DEPENDENCIES := $(libcore_to_document_generated)
-# rerun doc generation without recompiling the java
-LOCAL_JAVACFLAGS := $(local_javac_flags)
-LOCAL_MODULE_CLASS:=JAVA_LIBRARIES
-
-LOCAL_MODULE := libcore
-
-LOCAL_DROIDDOC_OPTIONS := \
- -offlinemode \
- -title "libcore" \
- -proofread $(OUT_DOCS)/$(LOCAL_MODULE)-proofread.txt \
- -todo ../$(LOCAL_MODULE)-docs-todo.html \
- -knowntags ./libcore/known_oj_tags.txt \
- -hdf android.whichdoc offline
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-include $(BUILD_DROIDDOC)
-
-# For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
-ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
-
-# Generate the stub source files for core.current.stubs
-# =====================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(addprefix ../, $(libcore_to_document))
-LOCAL_GENERATED_SOURCES := $(libcore_to_document_generated)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-LOCAL_DROIDDOC_OPTIONS:= \
-    -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/core.current.stubs_intermediates/src \
-    -nodocs \
-
-LOCAL_UNINSTALLABLE_MODULE := true
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_MODULE := core-current-stubs-gen
-
-include $(BUILD_DROIDDOC)
-
-# Remember the target that will trigger the code generation.
-core_current_gen_stamp := $(full_target)
-
-# Build the core.current.stubs library
-# ====================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := core.current.stubs
-
-LOCAL_SOURCE_FILES_ALL_GENERATED := true
-
-# Make sure to run droiddoc first to generate the stub source files.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(core_current_gen_stamp)
-core_current_gen_stamp :=
-
-# Because javac refuses to compile these stubs with --system=none, ( http://b/72206056#comment31 ),
-# just patch them into java.base at compile time.
-LOCAL_PATCH_MODULE := java.base
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_ERROR_PRONE_FLAGS := -Xep:MissingOverride:OFF
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # Archive a copy of the classes.jar in SDK build.
+full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,core.current.stubs,,COMMON)/classes.jar
 $(call dist-for-goals,sdk win_sdk,$(full_classes_jar):core.current.stubs.jar)
-
-endif  # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicIntegerFieldUpdaterTest.java b/jsr166-tests/src/test/java/jsr166/AtomicIntegerFieldUpdaterTest.java
index c8d3856..818a3b2 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicIntegerFieldUpdaterTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicIntegerFieldUpdaterTest.java
@@ -30,56 +30,55 @@
     // }
 
     // for testing subclass access
-    // android-note: Removed because android doesn't restrict reflection access
-    // static class AtomicIntegerFieldUpdaterTestSubclass extends AtomicIntegerFieldUpdaterTest {
-    //     public void checkPrivateAccess() {
-    //         try {
-    //             AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
-    //                 AtomicIntegerFieldUpdater.newUpdater
-    //                 (AtomicIntegerFieldUpdaterTest.class, "privateField");
-    //             shouldThrow();
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
+    static class AtomicIntegerFieldUpdaterTestSubclass extends AtomicIntegerFieldUpdaterTest {
+        public void checkPrivateAccess() {
+            try {
+                AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
+                    AtomicIntegerFieldUpdater.newUpdater
+                    (AtomicIntegerFieldUpdaterTest.class, "privateField");
+                shouldThrow();
+            } catch (RuntimeException success) {
+                assertNotNull(success.getCause());
+            }
+        }
 
-    //     public void checkCompareAndSetProtectedSub() {
-    //         AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
-    //             AtomicIntegerFieldUpdater.newUpdater
-    //             (AtomicIntegerFieldUpdaterTest.class, "protectedField");
-    //         this.protectedField = 1;
-    //         assertTrue(a.compareAndSet(this, 1, 2));
-    //         assertTrue(a.compareAndSet(this, 2, -4));
-    //         assertEquals(-4, a.get(this));
-    //         assertFalse(a.compareAndSet(this, -5, 7));
-    //         assertEquals(-4, a.get(this));
-    //         assertTrue(a.compareAndSet(this, -4, 7));
-    //         assertEquals(7, a.get(this));
-    //     }
-    // }
+        public void checkCompareAndSetProtectedSub() {
+            AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
+                AtomicIntegerFieldUpdater.newUpdater
+                (AtomicIntegerFieldUpdaterTest.class, "protectedField");
+            this.protectedField = 1;
+            assertTrue(a.compareAndSet(this, 1, 2));
+            assertTrue(a.compareAndSet(this, 2, -4));
+            assertEquals(-4, a.get(this));
+            assertFalse(a.compareAndSet(this, -5, 7));
+            assertEquals(-4, a.get(this));
+            assertTrue(a.compareAndSet(this, -4, 7));
+            assertEquals(7, a.get(this));
+        }
+    }
 
-    // static class UnrelatedClass {
-    //     public void checkPackageAccess(AtomicIntegerFieldUpdaterTest obj) {
-    //         obj.x = 72;
-    //         AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
-    //             AtomicIntegerFieldUpdater.newUpdater
-    //             (AtomicIntegerFieldUpdaterTest.class, "x");
-    //         assertEquals(72, a.get(obj));
-    //         assertTrue(a.compareAndSet(obj, 72, 73));
-    //         assertEquals(73, a.get(obj));
-    //     }
+    static class UnrelatedClass {
+        public void checkPackageAccess(AtomicIntegerFieldUpdaterTest obj) {
+            obj.x = 72;
+            AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
+                AtomicIntegerFieldUpdater.newUpdater
+                (AtomicIntegerFieldUpdaterTest.class, "x");
+            assertEquals(72, a.get(obj));
+            assertTrue(a.compareAndSet(obj, 72, 73));
+            assertEquals(73, a.get(obj));
+        }
 
-    //     public void checkPrivateAccess(AtomicIntegerFieldUpdaterTest obj) {
-    //         try {
-    //             AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
-    //                 AtomicIntegerFieldUpdater.newUpdater
-    //                 (AtomicIntegerFieldUpdaterTest.class, "privateField");
-    //             throw new AssertionError("should throw");
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
-    // }
+        public void checkPrivateAccess(AtomicIntegerFieldUpdaterTest obj) {
+            try {
+                AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
+                    AtomicIntegerFieldUpdater.newUpdater
+                    (AtomicIntegerFieldUpdaterTest.class, "privateField");
+                throw new AssertionError("should throw");
+            } catch (RuntimeException success) {
+                assertNotNull(success.getCause());
+            }
+        }
+    }
 
     AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> updaterFor(String fieldName) {
         return AtomicIntegerFieldUpdater.newUpdater
@@ -121,22 +120,20 @@
     /**
      * construction using private field from subclass throws RuntimeException
      */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testPrivateFieldInSubclass() {
-    //     AtomicIntegerFieldUpdaterTestSubclass s =
-    //         new AtomicIntegerFieldUpdaterTestSubclass();
-    //     s.checkPrivateAccess();
-    // }
+    public void testPrivateFieldInSubclass() {
+        AtomicIntegerFieldUpdaterTestSubclass s =
+            new AtomicIntegerFieldUpdaterTestSubclass();
+        s.checkPrivateAccess();
+    }
 
     /**
      * construction from unrelated class; package access is allowed,
      * private access is not
      */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testUnrelatedClassAccess() {
-    //     new UnrelatedClass().checkPackageAccess(this);
-    //     new UnrelatedClass().checkPrivateAccess(this);
-    // }
+    public void testUnrelatedClassAccess() {
+        new UnrelatedClass().checkPackageAccess(this);
+        new UnrelatedClass().checkPrivateAccess(this);
+    }
 
     /**
      * get returns the last value set or assigned
@@ -203,12 +200,11 @@
      * compareAndSet succeeds in changing protected field value if
      * equal to expected else fails
      */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testCompareAndSetProtectedInSubclass() {
-    //     AtomicIntegerFieldUpdaterTestSubclass s =
-    //         new AtomicIntegerFieldUpdaterTestSubclass();
-    //     s.checkCompareAndSetProtectedSub();
-    // }
+    public void testCompareAndSetProtectedInSubclass() {
+        AtomicIntegerFieldUpdaterTestSubclass s =
+            new AtomicIntegerFieldUpdaterTestSubclass();
+        s.checkCompareAndSetProtectedSub();
+    }
 
     /**
      * compareAndSet in one thread enables another waiting for value
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicLongFieldUpdaterTest.java b/jsr166-tests/src/test/java/jsr166/AtomicLongFieldUpdaterTest.java
index d46280b..69b97bc 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicLongFieldUpdaterTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicLongFieldUpdaterTest.java
@@ -30,56 +30,55 @@
     // }
 
     // for testing subclass access
-    // android-note: Removed because android doesn't restrict reflection access
-    // static class AtomicLongFieldUpdaterTestSubclass extends AtomicLongFieldUpdaterTest {
-    //     public void checkPrivateAccess() {
-    //         try {
-    //             AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
-    //                 AtomicLongFieldUpdater.newUpdater
-    //                 (AtomicLongFieldUpdaterTest.class, "privateField");
-    //             shouldThrow();
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
+    static class AtomicLongFieldUpdaterTestSubclass extends AtomicLongFieldUpdaterTest {
+        public void checkPrivateAccess() {
+            try {
+                AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
+                    AtomicLongFieldUpdater.newUpdater
+                    (AtomicLongFieldUpdaterTest.class, "privateField");
+                shouldThrow();
+            } catch (RuntimeException success) {
+                assertNotNull(success.getCause());
+            }
+        }
 
-    //     public void checkCompareAndSetProtectedSub() {
-    //         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
-    //             AtomicLongFieldUpdater.newUpdater
-    //             (AtomicLongFieldUpdaterTest.class, "protectedField");
-    //         this.protectedField = 1;
-    //         assertTrue(a.compareAndSet(this, 1, 2));
-    //         assertTrue(a.compareAndSet(this, 2, -4));
-    //         assertEquals(-4, a.get(this));
-    //         assertFalse(a.compareAndSet(this, -5, 7));
-    //         assertEquals(-4, a.get(this));
-    //         assertTrue(a.compareAndSet(this, -4, 7));
-    //         assertEquals(7, a.get(this));
-    //     }
-    // }
+        public void checkCompareAndSetProtectedSub() {
+            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
+                AtomicLongFieldUpdater.newUpdater
+                (AtomicLongFieldUpdaterTest.class, "protectedField");
+            this.protectedField = 1;
+            assertTrue(a.compareAndSet(this, 1, 2));
+            assertTrue(a.compareAndSet(this, 2, -4));
+            assertEquals(-4, a.get(this));
+            assertFalse(a.compareAndSet(this, -5, 7));
+            assertEquals(-4, a.get(this));
+            assertTrue(a.compareAndSet(this, -4, 7));
+            assertEquals(7, a.get(this));
+        }
+    }
 
-    // static class UnrelatedClass {
-    //     public void checkPackageAccess(AtomicLongFieldUpdaterTest obj) {
-    //         obj.x = 72L;
-    //         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
-    //             AtomicLongFieldUpdater.newUpdater
-    //             (AtomicLongFieldUpdaterTest.class, "x");
-    //         assertEquals(72L, a.get(obj));
-    //         assertTrue(a.compareAndSet(obj, 72L, 73L));
-    //         assertEquals(73L, a.get(obj));
-    //     }
+    static class UnrelatedClass {
+        public void checkPackageAccess(AtomicLongFieldUpdaterTest obj) {
+            obj.x = 72L;
+            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
+                AtomicLongFieldUpdater.newUpdater
+                (AtomicLongFieldUpdaterTest.class, "x");
+            assertEquals(72L, a.get(obj));
+            assertTrue(a.compareAndSet(obj, 72L, 73L));
+            assertEquals(73L, a.get(obj));
+        }
 
-    //     public void checkPrivateAccess(AtomicLongFieldUpdaterTest obj) {
-    //         try {
-    //             AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
-    //                 AtomicLongFieldUpdater.newUpdater
-    //                 (AtomicLongFieldUpdaterTest.class, "privateField");
-    //             throw new AssertionError("should throw");
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
-    // }
+        public void checkPrivateAccess(AtomicLongFieldUpdaterTest obj) {
+            try {
+                AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
+                    AtomicLongFieldUpdater.newUpdater
+                    (AtomicLongFieldUpdaterTest.class, "privateField");
+                throw new AssertionError("should throw");
+            } catch (RuntimeException success) {
+                assertNotNull(success.getCause());
+            }
+        }
+    }
 
     AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> updaterFor(String fieldName) {
         return AtomicLongFieldUpdater.newUpdater
@@ -121,22 +120,20 @@
     /**
      * construction using private field from subclass throws RuntimeException
      */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testPrivateFieldInSubclass() {
-    //     AtomicLongFieldUpdaterTestSubclass s =
-    //         new AtomicLongFieldUpdaterTestSubclass();
-    //     s.checkPrivateAccess();
-    // }
+    public void testPrivateFieldInSubclass() {
+        AtomicLongFieldUpdaterTestSubclass s =
+            new AtomicLongFieldUpdaterTestSubclass();
+        s.checkPrivateAccess();
+    }
 
     /**
      * construction from unrelated class; package access is allowed,
      * private access is not
      */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testUnrelatedClassAccess() {
-    //     new UnrelatedClass().checkPackageAccess(this);
-    //     new UnrelatedClass().checkPrivateAccess(this);
-    // }
+    public void testUnrelatedClassAccess() {
+        new UnrelatedClass().checkPackageAccess(this);
+        new UnrelatedClass().checkPrivateAccess(this);
+    }
 
     /**
      * get returns the last value set or assigned
@@ -203,12 +200,11 @@
      * compareAndSet succeeds in changing protected field value if
      * equal to expected else fails
      */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testCompareAndSetProtectedInSubclass() {
-    //     AtomicLongFieldUpdaterTestSubclass s =
-    //         new AtomicLongFieldUpdaterTestSubclass();
-    //     s.checkCompareAndSetProtectedSub();
-    // }
+    public void testCompareAndSetProtectedInSubclass() {
+        AtomicLongFieldUpdaterTestSubclass s =
+            new AtomicLongFieldUpdaterTestSubclass();
+        s.checkCompareAndSetProtectedSub();
+    }
 
     /**
      * compareAndSet in one thread enables another waiting for value
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicReferenceFieldUpdaterTest.java b/jsr166-tests/src/test/java/jsr166/AtomicReferenceFieldUpdaterTest.java
index 9b2e9a9..a662e11 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicReferenceFieldUpdaterTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicReferenceFieldUpdaterTest.java
@@ -32,56 +32,55 @@
     // }
 
     // for testing subclass access
-    // android-note: Removed because android doesn't restrict reflection access
-    // static class AtomicReferenceFieldUpdaterTestSubclass extends AtomicReferenceFieldUpdaterTest {
-    //     public void checkPrivateAccess() {
-    //         try {
-    //             AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
-    //                 AtomicReferenceFieldUpdater.newUpdater
-    //                 (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField");
-    //             shouldThrow();
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
+    static class AtomicReferenceFieldUpdaterTestSubclass extends AtomicReferenceFieldUpdaterTest {
+        public void checkPrivateAccess() {
+            try {
+                AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
+                    AtomicReferenceFieldUpdater.newUpdater
+                    (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField");
+                shouldThrow();
+            } catch (RuntimeException success) {
+                assertNotNull(success.getCause());
+            }
+        }
 
-    //     public void checkCompareAndSetProtectedSub() {
-    //         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
-    //             AtomicReferenceFieldUpdater.newUpdater
-    //             (AtomicReferenceFieldUpdaterTest.class, Integer.class, "protectedField");
-    //         this.protectedField = one;
-    //         assertTrue(a.compareAndSet(this, one, two));
-    //         assertTrue(a.compareAndSet(this, two, m4));
-    //         assertSame(m4, a.get(this));
-    //         assertFalse(a.compareAndSet(this, m5, seven));
-    //         assertFalse(seven == a.get(this));
-    //         assertTrue(a.compareAndSet(this, m4, seven));
-    //         assertSame(seven, a.get(this));
-    //     }
-    // }
+        public void checkCompareAndSetProtectedSub() {
+            AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
+                AtomicReferenceFieldUpdater.newUpdater
+                (AtomicReferenceFieldUpdaterTest.class, Integer.class, "protectedField");
+            this.protectedField = one;
+            assertTrue(a.compareAndSet(this, one, two));
+            assertTrue(a.compareAndSet(this, two, m4));
+            assertSame(m4, a.get(this));
+            assertFalse(a.compareAndSet(this, m5, seven));
+            assertFalse(seven == a.get(this));
+            assertTrue(a.compareAndSet(this, m4, seven));
+            assertSame(seven, a.get(this));
+        }
+    }
 
-    // static class UnrelatedClass {
-    //     public void checkPackageAccess(AtomicReferenceFieldUpdaterTest obj) {
-    //         obj.x = one;
-    //         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
-    //             AtomicReferenceFieldUpdater.newUpdater
-    //             (AtomicReferenceFieldUpdaterTest.class, Integer.class, "x");
-    //         assertSame(one, a.get(obj));
-    //         assertTrue(a.compareAndSet(obj, one, two));
-    //         assertSame(two, a.get(obj));
-    //     }
+    static class UnrelatedClass {
+        public void checkPackageAccess(AtomicReferenceFieldUpdaterTest obj) {
+            obj.x = one;
+            AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
+                AtomicReferenceFieldUpdater.newUpdater
+                (AtomicReferenceFieldUpdaterTest.class, Integer.class, "x");
+            assertSame(one, a.get(obj));
+            assertTrue(a.compareAndSet(obj, one, two));
+            assertSame(two, a.get(obj));
+        }
 
-    //     public void checkPrivateAccess(AtomicReferenceFieldUpdaterTest obj) {
-    //         try {
-    //             AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
-    //                 AtomicReferenceFieldUpdater.newUpdater
-    //                 (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField");
-    //             throw new AssertionError("should throw");
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
-    // }
+        public void checkPrivateAccess(AtomicReferenceFieldUpdaterTest obj) {
+            try {
+                AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
+                    AtomicReferenceFieldUpdater.newUpdater
+                    (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField");
+                throw new AssertionError("should throw");
+            } catch (RuntimeException success) {
+                assertNotNull(success.getCause());
+            }
+        }
+    }
 
     static AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> updaterFor(String fieldName) {
         return AtomicReferenceFieldUpdater.newUpdater
@@ -133,22 +132,20 @@
     /**
      * construction using private field from subclass throws RuntimeException
      */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testPrivateFieldInSubclass() {
-    //     AtomicReferenceFieldUpdaterTestSubclass s =
-    //         new AtomicReferenceFieldUpdaterTestSubclass();
-    //     s.checkPrivateAccess();
-    // }
+    public void testPrivateFieldInSubclass() {
+        AtomicReferenceFieldUpdaterTestSubclass s =
+            new AtomicReferenceFieldUpdaterTestSubclass();
+        s.checkPrivateAccess();
+    }
 
     /**
      * construction from unrelated class; package access is allowed,
      * private access is not
      */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testUnrelatedClassAccess() {
-    //     new UnrelatedClass().checkPackageAccess(this);
-    //     new UnrelatedClass().checkPrivateAccess(this);
-    // }
+    public void testUnrelatedClassAccess() {
+        new UnrelatedClass().checkPackageAccess(this);
+        new UnrelatedClass().checkPrivateAccess(this);
+    }
 
     /**
      * get returns the last value set or assigned
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 737de65..8c80346 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -20,6 +20,7 @@
 import java.lang.ref.FinalizerReference;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.Consumer;
 
 /**
  * Provides an interface to VM-global, Dalvik-specific features.
@@ -59,6 +60,8 @@
      */
     public static final int SDK_VERSION_CUR_DEVELOPMENT = 10000;
 
+    private static Consumer<String> nonSdkApiUsageConsumer = null;
+
     private int targetSdkVersion = SDK_VERSION_CUR_DEVELOPMENT;
 
     /**
@@ -265,6 +268,15 @@
     public native boolean hasUsedHiddenApi();
 
     /**
+     * Sets the list of exemptions from hidden API access enforcement.
+     *
+     * @param signaturePrefixes
+     *         A list of signature prefixes. Each item in the list is a prefix match on the type
+     *         signature of a blacklisted API. Access is permitted to any matching API.
+     */
+    public native void setHiddenApiExemptions(String[] signaturePrefixes);
+
+    /**
      * Returns an array allocated in an area of the Java heap where it will never be moved.
      * This is used to implement native allocations on the Java heap, such as DirectByteBuffers
      * and Bitmaps.
@@ -432,4 +444,11 @@
      * Sets up the priority of the system daemon thread (caller).
      */
     public static native void setSystemDaemonThreadPriority();
+
+    /**
+     * Sets a callback that the runtime can call whenever a usage of a non SDK API is detected.
+     */
+    public static void setNonSdkApiUsageConsumer(Consumer<String> consumer) {
+        nonSdkApiUsageConsumer = consumer;
+    }
 }
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java
index 404b822..6301ff9 100644
--- a/luni/src/main/java/android/system/Os.java
+++ b/luni/src/main/java/android/system/Os.java
@@ -186,17 +186,6 @@
     public static int getgid() { return Libcore.os.getgid(); }
 
     /**
-     * See <a href="http://man7.org/linux/man-pages/man2/getgroups.2.html">getgroups(2)</a>.
-     *
-     * <p>Should the number of groups change during the execution of this call, the call may
-     *    return an arbitrary subset. This may be worth reconsidering should this be exposed
-     *    as public API.
-     *
-     * @hide
-     */
-    public static int[] getgroups() throws ErrnoException { return Libcore.os.getgroups(); }
-
-    /**
      * See <a href="http://man7.org/linux/man-pages/man3/getenv.3.html">getenv(3)</a>.
      */
     public static String getenv(String name) { return Libcore.os.getenv(name); }
@@ -507,13 +496,6 @@
     public static void setgid(int gid) throws ErrnoException { Libcore.os.setgid(gid); }
 
     /**
-     * See <a href="http://man7.org/linux/man-pages/man2/setgroups.2.html">setgroups(2)</a>.
-     *
-     * @hide
-     */
-    public static void setgroups(int[] gids) throws ErrnoException { Libcore.os.setgroups(gids); }
-
-    /**
      * See <a href="http://man7.org/linux/man-pages/man2/setpgid.2.html">setpgid(2)</a>.
      */
     /** @hide */ public static void setpgid(int pid, int pgid) throws ErrnoException { Libcore.os.setpgid(pid, pgid); }
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index ce88a3b..f141694 100644
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -91,7 +91,6 @@
     public int getegid() { return os.getegid(); }
     public int geteuid() { return os.geteuid(); }
     public int getgid() { return os.getgid(); }
-    public int[] getgroups() throws ErrnoException { return os.getgroups(); }
     public String getenv(String name) { return os.getenv(name); }
     public String getnameinfo(InetAddress address, int flags) throws GaiException { return os.getnameinfo(address, flags); }
     public SocketAddress getpeername(FileDescriptor fd) throws ErrnoException { return os.getpeername(fd); }
@@ -162,7 +161,6 @@
     public void setenv(String name, String value, boolean overwrite) throws ErrnoException { os.setenv(name, value, overwrite); }
     public void seteuid(int euid) throws ErrnoException { os.seteuid(euid); }
     public void setgid(int gid) throws ErrnoException { os.setgid(gid); }
-    public void setgroups(int[] gids) throws ErrnoException { os.setgroups(gids); }
     public void setpgid(int pid, int pgid) throws ErrnoException { os.setpgid(pid, pgid); }
     public void setregid(int rgid, int egid) throws ErrnoException { os.setregid(rgid, egid); }
     public void setreuid(int ruid, int euid) throws ErrnoException { os.setreuid(ruid, euid); }
diff --git a/luni/src/main/java/libcore/io/Linux.java b/luni/src/main/java/libcore/io/Linux.java
index de3b103..807e5a2 100644
--- a/luni/src/main/java/libcore/io/Linux.java
+++ b/luni/src/main/java/libcore/io/Linux.java
@@ -82,7 +82,6 @@
     public native int getegid();
     public native int geteuid();
     public native int getgid();
-    public native int[] getgroups() throws ErrnoException;
     public native String getenv(String name);
     public native String getnameinfo(InetAddress address, int flags) throws GaiException;
     public native SocketAddress getpeername(FileDescriptor fd) throws ErrnoException;
@@ -236,7 +235,6 @@
     public native void setenv(String name, String value, boolean overwrite) throws ErrnoException;
     public native void seteuid(int euid) throws ErrnoException;
     public native void setgid(int gid) throws ErrnoException;
-    public native void setgroups(int[] gids) throws ErrnoException;
     public native void setpgid(int pid, int pgid) throws ErrnoException;
     public native void setregid(int rgid, int egid) throws ErrnoException;
     public native void setreuid(int ruid, int euid) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index 194851f..61584b4 100644
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -76,10 +76,6 @@
     public int getegid();
     public int geteuid();
     public int getgid();
-    /* Should the number of groups change during the execution of this call, the call may
-       return an arbitrary subset. This may be worth reconsidering should this be exposed
-       as public API. */
-    public int[] getgroups() throws ErrnoException;
     public String getenv(String name);
     /* TODO: break into getnameinfoHost and getnameinfoService? */
     public String getnameinfo(InetAddress address, int flags) throws GaiException;
@@ -152,7 +148,6 @@
     public void setenv(String name, String value, boolean overwrite) throws ErrnoException;
     public void seteuid(int euid) throws ErrnoException;
     public void setgid(int gid) throws ErrnoException;
-    public void setgroups(int[] gids) throws ErrnoException;
     public void setpgid(int pid, int pgid) throws ErrnoException;
     public void setregid(int rgid, int egid) throws ErrnoException;
     public void setreuid(int ruid, int euid) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/util/CountryTimeZones.java b/luni/src/main/java/libcore/util/CountryTimeZones.java
index 048e551..f05bf28 100644
--- a/luni/src/main/java/libcore/util/CountryTimeZones.java
+++ b/luni/src/main/java/libcore/util/CountryTimeZones.java
@@ -62,16 +62,18 @@
     public final static class TimeZoneMapping {
         public final String timeZoneId;
         public final boolean showInPicker;
+        public final Long notUsedAfter;
 
-        TimeZoneMapping(String timeZoneId, boolean showInPicker) {
+        TimeZoneMapping(String timeZoneId, boolean showInPicker, Long notUsedAfter) {
             this.timeZoneId = timeZoneId;
             this.showInPicker = showInPicker;
+            this.notUsedAfter = notUsedAfter;
         }
 
         // VisibleForTesting
-        public static TimeZoneMapping createForTests(String timeZoneId,
-                boolean showInPicker) {
-            return new TimeZoneMapping(timeZoneId, showInPicker);
+        public static TimeZoneMapping createForTests(
+                String timeZoneId, boolean showInPicker, Long notUsedAfter) {
+            return new TimeZoneMapping(timeZoneId, showInPicker, notUsedAfter);
         }
 
         @Override
@@ -84,12 +86,13 @@
             }
             TimeZoneMapping that = (TimeZoneMapping) o;
             return showInPicker == that.showInPicker &&
-                    Objects.equals(timeZoneId, that.timeZoneId);
+                    Objects.equals(timeZoneId, that.timeZoneId) &&
+                    Objects.equals(notUsedAfter, that.notUsedAfter);
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(timeZoneId, showInPicker);
+            return Objects.hash(timeZoneId, showInPicker, notUsedAfter);
         }
 
         @Override
@@ -97,6 +100,7 @@
             return "TimeZoneMapping{"
                     + "timeZoneId='" + timeZoneId + '\''
                     + ", showInPicker=" + showInPicker
+                    + ", notUsedAfter=" + notUsedAfter
                     + '}';
         }
 
diff --git a/luni/src/main/java/libcore/util/TimeZoneFinder.java b/luni/src/main/java/libcore/util/TimeZoneFinder.java
index 55e25c7..7c682d0 100644
--- a/luni/src/main/java/libcore/util/TimeZoneFinder.java
+++ b/luni/src/main/java/libcore/util/TimeZoneFinder.java
@@ -60,10 +60,15 @@
     private static final String DEFAULT_TIME_ZONE_ID_ATTRIBUTE = "default";
     private static final String EVER_USES_UTC_ATTRIBUTE = "everutc";
 
-    // Country -> Time zone mapping. e.g. <id picker="n">
+    // Country -> Time zone mapping. e.g. <id>ZoneId</id>, <id picker="n">ZoneId</id>,
+    // <id notafter={timestamp}>ZoneId</id>
     // The default for the picker attribute when unspecified is "y".
+    // The notafter attribute is optional. It specifies a timestamp (time in milliseconds from Unix
+    // epoch start) after which the zone is not (effectively) in use. If unspecified the zone is in
+    // use forever.
     private static final String ZONE_ID_ELEMENT = "id";
     private static final String ZONE_SHOW_IN_PICKER_ATTRIBUTE = "picker";
+    private static final String ZONE_NOT_USED_AFTER_ATTRIBUTE = "notafter";
 
     private static final String TRUE_ATTRIBUTE_VALUE = "y";
     private static final String FALSE_ATTRIBUTE_VALUE = "n";
@@ -395,6 +400,8 @@
             // The picker attribute is optional and defaulted to true.
             boolean showInPicker = parseBooleanAttribute(
                     parser, ZONE_SHOW_IN_PICKER_ATTRIBUTE, true /* defaultValue */);
+            Long notUsedAfter = parseLongAttribute(
+                    parser, ZONE_NOT_USED_AFTER_ATTRIBUTE, null /* defaultValue */);
             String zoneIdString = consumeText(parser);
 
             // Make sure we are on the </id> element.
@@ -406,7 +413,8 @@
                         + parser.getPositionDescription());
             }
 
-            TimeZoneMapping timeZoneMapping = new TimeZoneMapping(zoneIdString, showInPicker);
+            TimeZoneMapping timeZoneMapping =
+                    new TimeZoneMapping(zoneIdString, showInPicker, notUsedAfter);
             timeZoneMappings.add(timeZoneMapping);
         }
 
@@ -415,6 +423,25 @@
     }
 
     /**
+     * Parses an attribute value, which must be either {@code null} or a valid signed long value.
+     * If the attribute value is {@code null} then {@code defaultValue} is returned. If the
+     * attribute is present but not a valid long value then an XmlPullParserException is thrown.
+     */
+    private static Long parseLongAttribute(XmlPullParser parser, String attributeName,
+            Long defaultValue) throws XmlPullParserException {
+        String attributeValueString = parser.getAttributeValue(null /* namespace */, attributeName);
+        if (attributeValueString == null) {
+            return defaultValue;
+        }
+        try {
+            return Long.parseLong(attributeValueString);
+        } catch (NumberFormatException e) {
+            throw new XmlPullParserException("Attribute \"" + attributeName
+                    + "\" is not a long value: " + parser.getPositionDescription());
+        }
+    }
+
+    /**
      * Parses an attribute value, which must be either {@code null}, {@code "y"} or {@code "n"}.
      * If the attribute value is {@code null} then {@code defaultValue} is returned. If the
      * attribute is present but not "y" or "n" then an XmlPullParserException is thrown.
diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp
index 04954b9..30da35c 100644
--- a/luni/src/main/native/libcore_io_Linux.cpp
+++ b/luni/src/main/native/libcore_io_Linux.cpp
@@ -19,7 +19,6 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <grp.h>
 #include <ifaddrs.h>
 #include <linux/rtnetlink.h>
 #include <net/if.h>
@@ -1322,24 +1321,6 @@
     return getgid();
 }
 
-static jintArray Linux_getgroups(JNIEnv* env, jobject) {
-    int ngrps = throwIfMinusOne(env, "getgroups", getgroups(0, nullptr));
-    if (ngrps == -1) {
-        return NULL;
-    }
-    std::vector<gid_t> groups(ngrps, 0);
-    ngrps = throwIfMinusOne(env, "getgroups", getgroups(ngrps, &groups[0]));
-    if (ngrps == -1) {
-        return NULL;
-    }
-    jintArray out = env->NewIntArray(ngrps);
-    if ((out != NULL) && (ngrps > 0)) {
-      env->SetIntArrayRegion(out, 0, ngrps, reinterpret_cast<int*>(&groups[0]));
-    }
-
-    return out;
-}
-
 static jstring Linux_getenv(JNIEnv* env, jobject, jstring javaName) {
     ScopedUtfChars name(env, javaName);
     if (name.c_str() == NULL) {
@@ -2179,13 +2160,6 @@
     throwIfMinusOne(env, "setgid", TEMP_FAILURE_RETRY(setgid(gid)));
 }
 
-static void Linux_setgroups(JNIEnv* env, jobject, jintArray gids) {
-    size_t ngrps = gids == NULL ? 0 : env->GetArrayLength(gids);
-    std::vector<gid_t> groups(ngrps, 0);
-    env->GetIntArrayRegion(gids, 0, ngrps, reinterpret_cast<int*>(&groups[0]));
-    throwIfMinusOne(env, "setgroups", setgroups(ngrps, &groups[0]));
-}
-
 static void Linux_setpgid(JNIEnv* env, jobject, jint pid, int pgid) {
     throwIfMinusOne(env, "setpgid", TEMP_FAILURE_RETRY(setpgid(pid, pgid)));
 }
@@ -2524,7 +2498,6 @@
     NATIVE_METHOD(Linux, getegid, "()I"),
     NATIVE_METHOD(Linux, geteuid, "()I"),
     NATIVE_METHOD(Linux, getgid, "()I"),
-    NATIVE_METHOD(Linux, getgroups, "()[I"),
     NATIVE_METHOD(Linux, getenv, "(Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(Linux, getnameinfo, "(Ljava/net/InetAddress;I)Ljava/lang/String;"),
     NATIVE_METHOD(Linux, getpeername, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
@@ -2590,7 +2563,6 @@
     NATIVE_METHOD(Linux, setenv, "(Ljava/lang/String;Ljava/lang/String;Z)V"),
     NATIVE_METHOD(Linux, seteuid, "(I)V"),
     NATIVE_METHOD(Linux, setgid, "(I)V"),
-    NATIVE_METHOD(Linux, setgroups, "([I)V"),
     NATIVE_METHOD(Linux, setpgid, "(II)V"),
     NATIVE_METHOD(Linux, setregid, "(II)V"),
     NATIVE_METHOD(Linux, setreuid, "(II)V"),
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 93f5aed..7320d9a 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -614,6 +614,15 @@
         assertEquals("", splits[7]);
     }
 
+    // http://b/63745717
+    // A buffer overflow bug was found in ICU4C. A native crash occurs only when ASAN is enabled.
+    public void testSplit_lookBehind() {
+        String string = "a";
+        String[] words = string.split("(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])| |_|-");
+        assertEquals(1, words.length);
+        assertEquals(string, words[0]);
+    }
+
     // http://b/26126818
     public void testCodePointCount() {
         String hello = "Hello, fools";
diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
index 9b3850c..fc18ab8 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
@@ -697,7 +697,7 @@
     }
 
     public void testUnreflectSpecial_superCalls() throws Throwable {
-        Method overridenMethod = UnreflectTester.class.getMethod("overridenMethod");
+        Method overridenMethod = UnreflectTesterBase.class.getMethod("overridenMethod");
         UnreflectTester instance = new UnreflectTester("unused");
         MethodHandle mh = UnreflectTester.lookup.unreflectSpecial(overridenMethod,
                 UnreflectTester.class);
diff --git a/luni/src/test/java/libcore/java/security/spec/AlgorithmParametersPSSTest.java b/luni/src/test/java/libcore/java/security/spec/AlgorithmParametersPSSTest.java
index 7c60b87..7b725bb 100644
--- a/luni/src/test/java/libcore/java/security/spec/AlgorithmParametersPSSTest.java
+++ b/luni/src/test/java/libcore/java/security/spec/AlgorithmParametersPSSTest.java
@@ -40,15 +40,8 @@
     private static final byte[] DEFAULT_SPEC_DER_ENCODED = HexEncoding.decode("3000");
 
     private static final PSSParameterSpec WEIRD_SPEC =
-            new PSSParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA384, 27, 3);
-    private static final byte[] WEIRD_SPEC_DER_ENCODED =
-            HexEncoding.decode(
-                    "3039a00f300d06096086480165030402030500a11c301a06092a864886f70d010108300d060960"
-                    + "86480165030402020500a20302011ba303020103");
-
-    private static final PSSParameterSpec WEIRD2_SPEC =
             new PSSParameterSpec("SHA-224", "MGF1", MGF1ParameterSpec.SHA256, 32, 1);
-    private static final byte[] WEIRD2_SPEC_DER_ENCODED =
+    private static final byte[] WEIRD_SPEC_DER_ENCODED =
             HexEncoding.decode(
                     "3034a00f300d06096086480165030402040500a11c301a06092a864886f70d010108300d060960"
                     + "86480165030402010500a203020120");
@@ -107,7 +100,6 @@
     public void testInitWithDerEncoded() throws Exception {
         assertInitWithDerEncoded(WEIRD_SPEC_DER_ENCODED, WEIRD_SPEC);
         assertInitWithDerEncoded(DEFAULT_SPEC_DER_ENCODED, DEFAULT_SPEC);
-        assertInitWithDerEncoded(WEIRD2_SPEC_DER_ENCODED, WEIRD2_SPEC);
     }
 
     private void assertInitWithDerEncoded(
@@ -136,7 +128,6 @@
     public void testGetEncoded() throws Exception {
         assertGetEncoded(WEIRD_SPEC, WEIRD_SPEC_DER_ENCODED);
         assertGetEncoded(DEFAULT_SPEC, DEFAULT_SPEC_DER_ENCODED);
-        assertGetEncoded(WEIRD2_SPEC, WEIRD2_SPEC_DER_ENCODED);
     }
 
     private void assertGetEncoded(PSSParameterSpec spec, byte[] expectedEncoded) throws Exception {
diff --git a/luni/src/test/java/libcore/libcore/io/OsTest.java b/luni/src/test/java/libcore/libcore/io/OsTest.java
index f169a2c..ab8f16e 100644
--- a/luni/src/test/java/libcore/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/libcore/io/OsTest.java
@@ -926,23 +926,6 @@
     return f;
   }
 
-  public void test_getgroups() throws Exception {
-    int[] gids = Libcore.os.getgroups();
-    assertNotNull(gids);
-  }
-
-  public void test_setgroups() throws Exception {
-    final long ngroupsMax = Libcore.os.sysconf(_SC_NGROUPS_MAX);
-    final int expectedError = ngroupsMax == 0 ? EINVAL : EPERM;
-
-    try {
-      Libcore.os.setgroups(new int[] {-1});
-      fail();
-    } catch (ErrnoException expected) {
-      assertEquals(expectedError, expected.errno);
-    }
-  }
-
   public void test_odirect() throws Exception {
     File testFile = createTempFile("test_odirect", "");
     try {
diff --git a/luni/src/test/java/libcore/libcore/util/CountryTimeZonesTest.java b/luni/src/test/java/libcore/libcore/util/CountryTimeZonesTest.java
index aeb9c00..3466e7b 100644
--- a/luni/src/test/java/libcore/libcore/util/CountryTimeZonesTest.java
+++ b/luni/src/test/java/libcore/libcore/util/CountryTimeZonesTest.java
@@ -722,7 +722,8 @@
      */
     private static List<TimeZoneMapping> timeZoneMappings(String... timeZoneIds) {
         return Arrays.stream(timeZoneIds)
-                .map(x -> TimeZoneMapping.createForTests(x, true))
+                .map(x -> TimeZoneMapping.createForTests(
+                        x, true /* picker */, null /* notUsedAfter */))
                 .collect(Collectors.toList());
     }
 
diff --git a/luni/src/test/java/libcore/libcore/util/CountryZonesFinderTest.java b/luni/src/test/java/libcore/libcore/util/CountryZonesFinderTest.java
index d9e2287..eca59a0 100644
--- a/luni/src/test/java/libcore/libcore/util/CountryZonesFinderTest.java
+++ b/luni/src/test/java/libcore/libcore/util/CountryZonesFinderTest.java
@@ -107,7 +107,8 @@
      */
     private static List<TimeZoneMapping> timeZoneMappings(String... timeZoneIds) {
         return Arrays.stream(timeZoneIds)
-                .map(x -> TimeZoneMapping.createForTests(x, true))
+                .map(x -> TimeZoneMapping.createForTests(
+                        x, true /* picker */, null /* notUsedAfter */))
                 .collect(Collectors.toList());
     }
 }
diff --git a/luni/src/test/java/libcore/libcore/util/TimeZoneFinderTest.java b/luni/src/test/java/libcore/libcore/util/TimeZoneFinderTest.java
index d4663b5..d3a0e03 100644
--- a/luni/src/test/java/libcore/libcore/util/TimeZoneFinderTest.java
+++ b/luni/src/test/java/libcore/libcore/util/TimeZoneFinderTest.java
@@ -462,10 +462,48 @@
         CountryTimeZones usTimeZones = finder.lookupCountryTimeZones("us");
         List<TimeZoneMapping> actualTimeZoneMappings = usTimeZones.getTimeZoneMappings();
         List<TimeZoneMapping> expectedTimeZoneMappings = list(
-                TimeZoneMapping.createForTests("America/New_York", true /* shownInPicker */),
-                TimeZoneMapping.createForTests("America/Los_Angeles", true /* shownInPicker */),
                 TimeZoneMapping.createForTests(
-                        "America/Indiana/Vincennes", false /* shownInPicker */)
+                        "America/New_York", true /* shownInPicker */, null /* notUsedAfter */),
+                TimeZoneMapping.createForTests(
+                        "America/Los_Angeles", true /* shownInPicker */, null /* notUsedAfter */),
+                TimeZoneMapping.createForTests(
+                        "America/Indiana/Vincennes", false /* shownInPicker */,
+                        null /* notUsedAfter */)
+        );
+        assertEquals(expectedTimeZoneMappings, actualTimeZoneMappings);
+    }
+
+    @Test
+    public void xmlParsing_badTimeZoneMappingNotAfter() throws Exception {
+        checkValidateThrowsParserException("<timezones ianaversion=\"2017b\">\n"
+                + "  <countryzones>\n"
+                + "    <country code=\"gb\" default=\"Europe/London\" everutc=\"y\">\n"
+                + "      <id notafter=\"sometimes\">Europe/London</id>\n"
+                + "    </country>\n"
+                + "  </countryzones>\n"
+                + "</timezones>\n");
+    }
+
+    @Test
+    public void xmlParsing_timeZoneMappingNotAfter() throws Exception {
+        TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n"
+                + "  <countryzones>\n"
+                + "    <country code=\"us\" default=\"America/New_York\" everutc=\"n\">\n"
+                + "      <!-- Explicit notafter -->\n"
+                + "      <id notafter=\"1234\">America/New_York</id>\n"
+                + "      <!-- Missing notafter -->\n"
+                + "      <id>America/Indiana/Vincennes</id>\n"
+                + "    </country>\n"
+                + "  </countryzones>\n"
+                + "</timezones>\n");
+        CountryTimeZones usTimeZones = finder.lookupCountryTimeZones("us");
+        List<TimeZoneMapping> actualTimeZoneMappings = usTimeZones.getTimeZoneMappings();
+        List<TimeZoneMapping> expectedTimeZoneMappings = list(
+                TimeZoneMapping.createForTests(
+                        "America/New_York", true /* shownInPicker */, 1234L /* notUsedAfter */),
+                TimeZoneMapping.createForTests(
+                        "America/Indiana/Vincennes", true /* shownInPicker */,
+                        null /* notUsedAfter */)
         );
         assertEquals(expectedTimeZoneMappings, actualTimeZoneMappings);
     }
@@ -908,7 +946,7 @@
         assertEquals(expected, actual);
     }
 
-    private static void checkValidateThrowsParserException(String xml) throws Exception {
+    private static void checkValidateThrowsParserException(String xml) {
         try {
             validate(xml);
             fail();
@@ -927,7 +965,8 @@
      */
     private static List<TimeZoneMapping> timeZoneMappings(String... timeZoneIds) {
         return Arrays.stream(timeZoneIds)
-                .map(x -> TimeZoneMapping.createForTests(x, true))
+                .map(x -> TimeZoneMapping.createForTests(
+                        x, true /* showInPicker */, null /* notUsedAfter */))
                 .collect(Collectors.toList());
     }
 
diff --git a/ojluni/src/main/java/java/io/ObjectStreamField.java b/ojluni/src/main/java/java/io/ObjectStreamField.java
index 957972e..ff485d8 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamField.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamField.java
@@ -162,14 +162,16 @@
      */
     @CallerSensitive
     public Class<?> getType() {
-        /* BEGIN Android-removed: Security manager is always null on Android.
+        // BEGIN Android-removed: Security manager is always null on Android.
+        /*
         if (System.getSecurityManager() != null) {
              Class<?> caller = Reflection.getCallerClass();
             if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), type.getClassLoader())) {
                 ReflectUtil.checkPackageAccess(type);
             }
         }
-        END Android-removed: Security manager is always null on Android. */
+        */
+        // END Android-removed: Security manager is always null on Android.
         return type;
     }
 
diff --git a/ojluni/src/main/java/java/lang/Class.java b/ojluni/src/main/java/java/lang/Class.java
index f31a42c..bc87850 100644
--- a/ojluni/src/main/java/java/lang/Class.java
+++ b/ojluni/src/main/java/java/lang/Class.java
@@ -2065,7 +2065,8 @@
         // Fail if we didn't find the method or it was expected to be public.
         if (result == null ||
             (recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
-            throw new NoSuchMethodException(name + " " + Arrays.toString(parameterTypes));
+            throw new NoSuchMethodException(getName() + "." + name + " "
+                    + Arrays.toString(parameterTypes));
         }
         return result;
     }
@@ -2324,7 +2325,8 @@
         }
         Constructor<T> result = getDeclaredConstructorInternal(parameterTypes);
         if (result == null || which == Member.PUBLIC && !Modifier.isPublic(result.getAccessFlags())) {
-            throw new NoSuchMethodException("<init> " + Arrays.toString(parameterTypes));
+            throw new NoSuchMethodException(getName() + ".<init> "
+                    + Arrays.toString(parameterTypes));
         }
         return result;
     }
diff --git a/ojluni/src/main/java/java/lang/String.java b/ojluni/src/main/java/java/lang/String.java
index 7e82347..de54882 100644
--- a/ojluni/src/main/java/java/lang/String.java
+++ b/ojluni/src/main/java/java/lang/String.java
@@ -144,7 +144,7 @@
      * Class String is special cased within the Serialization Stream Protocol.
      *
      * A String instance is written into an ObjectOutputStream according to
-     * <a href="{@docRoot}/../platform/serialization/spec/output.html">
+     * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/platform/serialization/spec/output.html">
      * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
      */
     private static final ObjectStreamField[] serialPersistentFields =
diff --git a/ojluni/src/main/java/java/lang/ref/Reference.java b/ojluni/src/main/java/java/lang/ref/Reference.java
index 06b517e..4d51b18 100644
--- a/ojluni/src/main/java/java/lang/ref/Reference.java
+++ b/ojluni/src/main/java/java/lang/ref/Reference.java
@@ -282,16 +282,26 @@
 
     // Android-changed: reachabilityFence implementation differs from OpenJDK9.
     public static void reachabilityFence(Object ref) {
+        // This code is usually replaced by much faster intrinsic implementations.
+        // It will be executed for tests run with the access checks interpreter in
+        // ART, e.g. with --verify-soft-fail.  Since this is a volatile store, it
+        // cannot easily be moved up past prior accesses, even if this method is
+        // inlined.
         SinkHolder.sink = ref;
-        // TODO: This is a horrible implementation. Fix it. Remove SinkHolder.
-        // b/72698200 .
+        // Leaving SinkHolder set to ref is unpleasant, since it keeps ref live
+        // until the next reachabilityFence call. This causes e.g. 036-finalizer
+        // to fail. Clear it again in a way that's unlikely to be optimizable.
+        // The fact that finalize_count is volatile makes it hard to move the test up.
+        if (SinkHolder.finalize_count == 0) {
+            SinkHolder.sink = null;
+        }
     }
 
     private static class SinkHolder {
         static volatile Object sink;
 
         // Ensure that sink looks live to even a reasonably clever compiler.
-        private static int finalize_count = 0;
+        private static volatile int finalize_count = 0;
 
         private static Object sinkUser = new Object() {
             protected void finalize() {
diff --git a/ojluni/src/main/java/java/net/Inet6AddressImpl.java b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
index cfc2d13..1edfe34 100644
--- a/ojluni/src/main/java/java/net/Inet6AddressImpl.java
+++ b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
@@ -290,9 +290,11 @@
         } catch (IOException e) {
             // Silently ignore and fall back.
         } finally {
-            try {
-                Libcore.os.close(fd);
-            } catch (ErrnoException e) { }
+            if (fd != null) {
+                try {
+                    Libcore.os.close(fd);
+                } catch (ErrnoException e) { }
+            }
         }
 
         return false;
diff --git a/ojluni/src/main/java/java/security/KeyStore.java b/ojluni/src/main/java/java/security/KeyStore.java
index d091781..8fe46b8 100644
--- a/ojluni/src/main/java/java/security/KeyStore.java
+++ b/ojluni/src/main/java/java/security/KeyStore.java
@@ -311,7 +311,7 @@
          * @param protectionAlgorithm the encryption algorithm name, for
          *     example, {@code PBEWithHmacSHA256AndAES_256}.
          *     See the Cipher section in the <a href=
-         * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
+         * "{@docRoot}/openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#Cipher">
          * Java Cryptography Architecture Standard Algorithm Name
          * Documentation</a>
          *     for information about standard encryption algorithm names.
diff --git a/ojluni/src/main/java/java/security/cert/X509CRL.java b/ojluni/src/main/java/java/security/cert/X509CRL.java
index a233b44..927852b 100644
--- a/ojluni/src/main/java/java/security/cert/X509CRL.java
+++ b/ojluni/src/main/java/java/security/cert/X509CRL.java
@@ -241,16 +241,17 @@
     public void verify(PublicKey key, Provider sigProvider)
         throws CRLException, NoSuchAlgorithmException,
         InvalidKeyException, SignatureException {
-        // BEGIN Android-changed
-        // TODO(31294527): was X509CRLImpl.verify(this, key, sigProvider);
+        // Android-changed: Eliminate infinite recursion in default implementation.
         // As the javadoc says, this "default implementation" was introduced as to avoid breaking
         // providers that generate concrete subclasses of this class.
         // The method X509Impl in the original definition calls this method, thus entering an
-        // infinite loop. This strange behaviour was checked to be not specific to libcore by
-        // running a test with vogar --mode=jvm .
+        // infinite recursive loop. This strange behaviour was checked to be not specific to
+        // libcore by running a test with vogar --mode=jvm .  See b/31294527.
+        // This is fixed upstream in OpenJDK 10.
+        //
+        // X509CRLImpl.verify(this, key, sigProvider);
         throw new UnsupportedOperationException(
                 "X509CRL instance doesn't not support X509CRL#verify(PublicKey, Provider)");
-        // END Android-changed
     }
 
     /**
diff --git a/ojluni/src/main/java/java/security/cert/X509Certificate.java b/ojluni/src/main/java/java/security/cert/X509Certificate.java
index 042eefd..f7cb9ef 100644
--- a/ojluni/src/main/java/java/security/cert/X509Certificate.java
+++ b/ojluni/src/main/java/java/security/cert/X509Certificate.java
@@ -673,11 +673,11 @@
     public void verify(PublicKey key, Provider sigProvider)
         throws CertificateException, NoSuchAlgorithmException,
         InvalidKeyException, SignatureException {
-        // Android-changed: Use Certificate default implementation that
-        // throws UnsupportedOperationException.
+        // Android-changed: Eliminate infinite recursion in default implementation.
         // The method X509CertImpl calls this method, thus entering an
-        // infinite loop. This strange behaviour was checked to be not
-        // specific to libcore by running a test with vogar --mode=jvm
+        // infinite recursive loop. This strange behaviour was checked to be not
+        // specific to libcore by running a test with vogar --mode=jvm.
+        // This is fixed upstream in OpenJDK 10.
         //
         // X509CertImpl.verify(this, key, sigProvider);
         super.verify(key, sigProvider);
diff --git a/ojluni/src/main/java/java/security/cert/package-info.java b/ojluni/src/main/java/java/security/cert/package-info.java
index 0ef896b..0c1cb1f 100644
--- a/ojluni/src/main/java/java/security/cert/package-info.java
+++ b/ojluni/src/main/java/java/security/cert/package-info.java
@@ -52,7 +52,7 @@
  *   <li><a href="http://www.ietf.org/rfc/rfc5280.txt">
  *     http://www.ietf.org/rfc/rfc5280.txt</a>
  *   <li><a href=
- *     "{@docRoot}/../technotes/guides/security/certpath/CertPathProgGuide.html">
+ *     "{@docRoot}/openjdk-redirect.html?v=8&path=/technotes/guides/security/certpath/CertPathProgGuide.html">
  *     <b>Java&trade;
  *     PKI Programmer's Guide</b></a>
  *   <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/cert3.html">
diff --git a/ojluni/src/main/java/java/security/package-info.java b/ojluni/src/main/java/java/security/package-info.java
index 376aa9d..50a1527 100644
--- a/ojluni/src/main/java/java/security/package-info.java
+++ b/ojluni/src/main/java/java/security/package-info.java
@@ -46,14 +46,14 @@
  * <h2>Package Specification</h2>
  *
  * <ul>
- *   <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/crypto/CryptoSpec.html">
+ *   <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html">
  *     <b>Java&trade;
  *     Cryptography Architecture (JCA) Reference Guide</b></a></li>
  *
  *   <li>PKCS #8: Private-Key Information Syntax Standard, Version 1.2,
  *     November 1993</li>
  *
- *   <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/StandardNames.html">
+ *   <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html">
  *     <b>Java&trade;
  *     Cryptography Architecture Standard Algorithm Name
  *     Documentation</b></a></li>
@@ -64,44 +64,44 @@
  * For further documentation, please see:
  * <ul>
  *   <li><a href=
- *     "{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/spec/security-spec.doc.html">
+ *     "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/spec/security-spec.doc.html">
  *     <b>Java&trade;
  *     SE Platform Security Architecture</b></a></li>
  *
  *   <li><a href=
- *     "{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/crypto/HowToImplAProvider.html">
+ *     "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/HowToImplAProvider.html">
  *     <b>How to Implement a Provider in the
  *     Java&trade; Cryptography Architecture
  *     </b></a></li>
  *
  *   <li><a href=
- *     "{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/PolicyFiles.html"><b>
+ *     "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/PolicyFiles.html"><b>
  *     Default Policy Implementation and Policy File Syntax
  *     </b></a></li>
  *
  *   <li><a href=
- *     "{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/permissions.html"><b>
+ *     "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/permissions.html"><b>
  *     Permissions in the
  *     Java&trade; SE Development Kit (JDK)
  *     </b></a></li>
  *
  *   <li><a href=
- *     "{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/SecurityToolsSummary.html"><b>
+ *     "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/SecurityToolsSummary.html"><b>
  *     Summary of Tools for
  *     Java&trade; Platform Security
  *     </b></a></li>
  *
  *   <li><b>keytool</b>
- *     (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/tools/unix/keytool.html">
+ *     (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/tools/unix/keytool.html">
  *       for Solaris/Linux</a>)
- *     (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/tools/windows/keytool.html">
+ *     (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/tools/windows/keytool.html">
  *       for Windows</a>)
  *     </li>
  *
  *   <li><b>jarsigner</b>
- *     (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/tools/unix/jarsigner.html">
+ *     (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/tools/unix/jarsigner.html">
  *       for Solaris/Linux</a>)
- *     (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/tools/windows/jarsigner.html">
+ *     (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/tools/windows/jarsigner.html">
  *       for Windows</a>)
  *     </li>
  *
diff --git a/ojluni/src/main/java/java/sql/CallableStatement.java b/ojluni/src/main/java/java/sql/CallableStatement.java
index b4769e3..d58c88b 100644
--- a/ojluni/src/main/java/java/sql/CallableStatement.java
+++ b/ojluni/src/main/java/java/sql/CallableStatement.java
@@ -296,6 +296,7 @@
      *             or <code>getBigDecimal(String parameterName)</code>
      * @see #setBigDecimal
      */
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
     @Deprecated
     BigDecimal getBigDecimal(int parameterIndex, int scale)
         throws SQLException;
@@ -2438,4 +2439,6 @@
      */
      void setNClob(String parameterName, Reader reader)
        throws SQLException;
+
+    // Android-removed: JDBC 4.1 methods were removed immediately after the initial import.
 }
diff --git a/ojluni/src/main/java/java/sql/Connection.java b/ojluni/src/main/java/java/sql/Connection.java
index 3acfd12..b742388 100644
--- a/ojluni/src/main/java/java/sql/Connection.java
+++ b/ojluni/src/main/java/java/sql/Connection.java
@@ -1303,4 +1303,5 @@
  Struct createStruct(String typeName, Object[] attributes)
 throws SQLException;
 
+    // Android-removed: JDBC 4.1 methods were removed immediately after the initial import.
 }
diff --git a/ojluni/src/main/java/java/sql/DatabaseMetaData.java b/ojluni/src/main/java/java/sql/DatabaseMetaData.java
index 98101ce..8e7441c 100644
--- a/ojluni/src/main/java/java/sql/DatabaseMetaData.java
+++ b/ojluni/src/main/java/java/sql/DatabaseMetaData.java
@@ -3574,4 +3574,5 @@
      */
     int functionReturnsTable    = 2;
 
+    // Android-removed: JDBC 4.1 methods were removed immediately after the initial import.
 }
diff --git a/ojluni/src/main/java/java/sql/Date.java b/ojluni/src/main/java/java/sql/Date.java
index a64a42f..b96828a 100644
--- a/ojluni/src/main/java/java/sql/Date.java
+++ b/ojluni/src/main/java/java/sql/Date.java
@@ -52,7 +52,8 @@
      * @param day 1 to 31
      * @deprecated instead use the constructor <code>Date(long date)</code>
      */
-    @Deprecated // Android-added
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
+    @Deprecated
     public Date(int year, int month, int day) {
         super(year, month, day);
     }
@@ -172,6 +173,7 @@
 
     // Override all the time operations inherited from java.util.Date;
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL Date
     * values do not have a time component.
@@ -179,11 +181,13 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #setHours
     */
-    @Deprecated // Android-added: changed javadoc to include deprecation note.
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
+    @Deprecated
     public int getHours() {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL Date
     * values do not have a time component.
@@ -191,11 +195,13 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #setMinutes
     */
-    @Deprecated // Android-added: changed javadoc to include deprecation note.
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
+    @Deprecated
     public int getMinutes() {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL Date
     * values do not have a time component.
@@ -203,11 +209,13 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #setSeconds
     */
-    @Deprecated // Android-added: changed javadoc to include deprecation note.
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
+    @Deprecated
     public int getSeconds() {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL Date
     * values do not have a time component.
@@ -215,11 +223,13 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #getHours
     */
-    @Deprecated // Android-added: changed javadoc to include deprecation note.
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
+    @Deprecated
     public void setHours(int i) {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL Date
     * values do not have a time component.
@@ -227,11 +237,13 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #getMinutes
     */
-    @Deprecated // Android-added: changed javadoc to include deprecation note.
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
+    @Deprecated
     public void setMinutes(int i) {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL Date
     * values do not have a time component.
@@ -239,7 +251,8 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #getSeconds
     */
-    @Deprecated // Android-added: changed javadoc to include deprecation note.
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
+    @Deprecated
     public void setSeconds(int i) {
         throw new java.lang.IllegalArgumentException();
     }
diff --git a/ojluni/src/main/java/java/sql/Driver.java b/ojluni/src/main/java/java/sql/Driver.java
index a9bdc7d..3970b1c 100644
--- a/ojluni/src/main/java/java/sql/Driver.java
+++ b/ojluni/src/main/java/java/sql/Driver.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2014 The Android Open Source Project
  * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -153,4 +154,5 @@
      */
     boolean jdbcCompliant();
 
+    // Android-removed: JDBC 4.1 methods were removed immediately after the initial import.
 }
diff --git a/ojluni/src/main/java/java/sql/DriverManager.java b/ojluni/src/main/java/java/sql/DriverManager.java
index e7d9c94..b4ccb22 100644
--- a/ojluni/src/main/java/java/sql/DriverManager.java
+++ b/ojluni/src/main/java/java/sql/DriverManager.java
@@ -36,6 +36,7 @@
 
 import sun.reflect.CallerSensitive;
 
+// Android-changed line 2 of the javadoc to "{@code DataSource}".
 /**
  * <P>The basic service for managing a set of JDBC drivers.<br>
  * <B>NOTE:</B> The {@code DataSource} interface, new in the
@@ -80,7 +81,6 @@
  * @see Driver
  * @see Connection
  */
-// Android-changed line 2 of the javadoc to "{@code DataSource}"
 public class DriverManager {
 
 
@@ -188,6 +188,7 @@
     @CallerSensitive
     public static Connection getConnection(String url,
         java.util.Properties info) throws SQLException {
+        // Android-changed: Used VMStack to get the caller's ClassLoader rather than Class.
         return (getConnection(url, info, VMStack.getCallingClassLoader()));
     }
 
@@ -216,6 +217,7 @@
             info.put("password", password);
         }
 
+        // Android-changed: Used VMStack to get the caller's ClassLoader rather than Class.
         return (getConnection(url, info, VMStack.getCallingClassLoader()));
     }
 
@@ -234,6 +236,7 @@
         throws SQLException {
 
         java.util.Properties info = new java.util.Properties();
+        // Android-changed: Used VMStack to get the caller's ClassLoader rather than Class.
         return (getConnection(url, info, VMStack.getCallingClassLoader()));
     }
 
@@ -254,6 +257,7 @@
 
         println("DriverManager.getDriver(\"" + url + "\")");
 
+        // Android-changed: Used VMStack to get the caller's ClassLoader rather than Class.
         ClassLoader callerClassLoader = VMStack.getCallingClassLoader();
 
         // Walk through the loaded registeredDrivers attempting to locate someone
@@ -261,6 +265,7 @@
         for (DriverInfo aDriver : registeredDrivers) {
             // If the caller does not have permission to load the driver then
             // skip it.
+            // Android-changed: Pass caller's ClassLoader rather than Class.
             if(isDriverAllowed(aDriver.driver, callerClassLoader)) {
                 try {
                     if(aDriver.driver.acceptsURL(url)) {
@@ -326,6 +331,7 @@
 
         DriverInfo aDriver = new DriverInfo(driver);
         if(registeredDrivers.contains(aDriver)) {
+            // Android-changed: Pass caller's ClassLoader rather than Class.
             if (isDriverAllowed(driver, VMStack.getCallingClassLoader())) {
                  registeredDrivers.remove(aDriver);
             } else {
@@ -351,12 +357,14 @@
     public static java.util.Enumeration<Driver> getDrivers() {
         java.util.Vector<Driver> result = new java.util.Vector<Driver>();
 
+        // Android-changed: Used VMStack to get the caller's ClassLoader rather than Class.
         ClassLoader callerClassLoader = VMStack.getCallingClassLoader();
 
         // Walk through the loaded registeredDrivers.
         for(DriverInfo aDriver : registeredDrivers) {
             // If the caller does not have permission to load the driver then
             // skip it.
+            // Android-changed: Pass caller's ClassLoader rather than Class.
             if(isDriverAllowed(aDriver.driver, callerClassLoader)) {
                 result.addElement(aDriver.driver);
             } else {
@@ -389,6 +397,7 @@
         return (loginTimeout);
     }
 
+    // Android-changed: Added reason to @deprecated to improve the documentation.
     /**
      * Sets the logging/tracing PrintStream that is used
      * by the <code>DriverManager</code>
@@ -408,7 +417,8 @@
      * @see SecurityManager#checkPermission
      * @see #getLogStream
      */
-    @Deprecated // Android-added, also changed deprecation comment to include a reason.
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
+    @Deprecated
     public static void setLogStream(java.io.PrintStream out) {
 
         SecurityManager sec = System.getSecurityManager();
@@ -423,6 +433,7 @@
             logWriter = null;
     }
 
+    // Android-changed: Added reason to @deprecated to improve the documentation.
     /**
      * Retrieves the logging/tracing PrintStream that is used by the <code>DriverManager</code>
      * and all drivers.
@@ -431,7 +442,8 @@
      * @deprecated Use {@code getLogWriter} instead.
      * @see #setLogStream
      */
-    @Deprecated // Android-added, also changed deprecation comment to include a reason.
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
+    @Deprecated
     public static java.io.PrintStream getLogStream() {
         return logStream;
     }
@@ -454,6 +466,17 @@
 
     //------------------------------------------------------------------------
 
+    // BEGIN Android-removed: Unused method
+/*
+    // Indicates whether the class object that would be created if the code calling
+    // DriverManager is accessible.
+    private static boolean isDriverAllowed(Driver driver, Class<?> caller) {
+        ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
+        return isDriverAllowed(driver, callerCL);
+    }
+*/
+    // END Android-removed: Unused method
+
     private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
         boolean result = false;
         if(driver != null) {
@@ -535,6 +558,7 @@
 
 
     //  Worker method called by the public getConnection() methods.
+    // Android-changed: Use ClassLoader instead of Class.
     private static Connection getConnection(
         String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
         /*
@@ -543,6 +567,8 @@
          * classloader, so that the JDBC driver class outside rt.jar
          * can be loaded from here.
          */
+        // Android-removed: ClassLoader already provided by the caller.
+        // ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
         synchronized (DriverManager.class) {
             // synchronize loading of the correct classloader.
             if (callerCL == null) {
diff --git a/ojluni/src/main/java/java/sql/PreparedStatement.java b/ojluni/src/main/java/java/sql/PreparedStatement.java
index 0763390..ef57f69 100644
--- a/ojluni/src/main/java/java/sql/PreparedStatement.java
+++ b/ojluni/src/main/java/java/sql/PreparedStatement.java
@@ -317,6 +317,7 @@
     void setAsciiStream(int parameterIndex, java.io.InputStream x, int length)
             throws SQLException;
 
+    // Android-changed: Added reason to @deprecated to improve the documentation.
     /**
      * Sets the designated parameter to the given input stream, which
      * will have the specified number of bytes.
@@ -343,8 +344,9 @@
      * this method is called on a closed <code>PreparedStatement</code>
      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
      * this method
-     * @deprecated Deprecated.
+     * @deprecated Use setCharacterStream
      */
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
     @Deprecated
     void setUnicodeStream(int parameterIndex, java.io.InputStream x,
                           int length) throws SQLException;
diff --git a/ojluni/src/main/java/java/sql/ResultSet.java b/ojluni/src/main/java/java/sql/ResultSet.java
index 0b1f6a0..f9ca407 100644
--- a/ojluni/src/main/java/java/sql/ResultSet.java
+++ b/ojluni/src/main/java/java/sql/ResultSet.java
@@ -343,6 +343,7 @@
      */
     double getDouble(int columnIndex) throws SQLException;
 
+    // Android-changed: Added reason to @deprecated to improve the documentation.
     /**
      * Retrieves the value of the designated column in the current row
      * of this <code>ResultSet</code> object as
@@ -360,6 +361,7 @@
      * @deprecated Use {@code getBigDecimal(int columnIndex)}
      *             or {@code getBigDecimal(String columnLabel)}
      */
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
     @Deprecated
     BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException;
 
@@ -480,6 +482,7 @@
      * @deprecated use <code>getCharacterStream</code> in place of
      *              <code>getUnicodeStream</code>
      */
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
     @Deprecated
     java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException;
 
@@ -631,6 +634,7 @@
      */
     double getDouble(String columnLabel) throws SQLException;
 
+    // Android-changed: Added reason to @deprecated to improve the documentation.
     /**
      * Retrieves the value of the designated column in the current row
      * of this <code>ResultSet</code> object as
@@ -648,6 +652,7 @@
      * @deprecated Use {@code getBigDecimal(int columnIndex)}
      *             or {@code getBigDecimal(String columnLabel)}
      */
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
     @Deprecated
     BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException;
 
@@ -766,6 +771,7 @@
      * this method
      * @deprecated use <code>getCharacterStream</code> instead
      */
+    // Android-added: @Deprecated annotation from OpenJDK8u121-b13 to fix build warnings.
     @Deprecated
     java.io.InputStream getUnicodeStream(String columnLabel) throws SQLException;
 
@@ -4083,4 +4089,5 @@
      */
     void updateNClob(String columnLabel,  Reader reader) throws SQLException;
 
+    // Android-removed: JDBC 4.1 methods were removed immediately after the initial import.
 }
diff --git a/ojluni/src/main/java/java/sql/SQLPermission.java b/ojluni/src/main/java/java/sql/SQLPermission.java
index 505202c..d90cf64 100644
--- a/ojluni/src/main/java/java/sql/SQLPermission.java
+++ b/ojluni/src/main/java/java/sql/SQLPermission.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2014 The Android Open Source Project
  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -23,6 +24,7 @@
  * questions.
  */
 
+
 package java.sql;
 
 import java.security.*;
diff --git a/ojluni/src/main/java/java/sql/Statement.java b/ojluni/src/main/java/java/sql/Statement.java
index 40cd97c..5915114 100644
--- a/ojluni/src/main/java/java/sql/Statement.java
+++ b/ojluni/src/main/java/java/sql/Statement.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2014 The Android Open Source Project
  * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -1030,4 +1031,5 @@
         boolean isPoolable()
                 throws SQLException;
 
+    // Android-removed: JDBC 4.1 methods were removed immediately after the initial import.
 }
diff --git a/ojluni/src/main/java/java/sql/Time.java b/ojluni/src/main/java/java/sql/Time.java
index 4960ce5..1300003 100644
--- a/ojluni/src/main/java/java/sql/Time.java
+++ b/ojluni/src/main/java/java/sql/Time.java
@@ -144,6 +144,7 @@
 
     // Override all the date operations inherited from java.util.Date;
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL <code>TIME</code>
     * values do not have a year component.
@@ -152,12 +153,12 @@
     *           method is invoked
     * @see #setYear
     */
-    // Android-changed javadoc, @deprecated tag now has a reason.
     @Deprecated
     public int getYear() {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL <code>TIME</code>
     * values do not have a month component.
@@ -166,12 +167,12 @@
     *           method is invoked
     * @see #setMonth
     */
-    // Android-changed javadoc, @deprecated tag now has a reason.
     @Deprecated
     public int getMonth() {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL <code>TIME</code>
     * values do not have a day component.
@@ -179,12 +180,12 @@
     * @exception java.lang.IllegalArgumentException if this
     *           method is invoked
     */
-    // Android-changed javadoc, @deprecated tag now has a reason.
     @Deprecated
     public int getDay() {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL <code>TIME</code>
     * values do not have a date component.
@@ -193,12 +194,12 @@
     *           method is invoked
     * @see #setDate
     */
-    // Android-changed javadoc, @deprecated tag now has a reason.
     @Deprecated
     public int getDate() {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL <code>TIME</code>
     * values do not have a year component.
@@ -207,12 +208,12 @@
     *           method is invoked
     * @see #getYear
     */
-    // Android-changed javadoc, @deprecated tag now has a reason.
     @Deprecated
     public void setYear(int i) {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL <code>TIME</code>
     * values do not have a month component.
@@ -221,12 +222,12 @@
     *           method is invoked
     * @see #getMonth
     */
-    // Android-changed javadoc, @deprecated tag now has a reason.
     @Deprecated
     public void setMonth(int i) {
         throw new java.lang.IllegalArgumentException();
     }
 
+   // Android-changed: Moved @deprecated to include a deprecation reason in the documentation.
    /**
     * @deprecated This method is deprecated and should not be used because SQL <code>TIME</code>
     * values do not have a date component.
diff --git a/ojluni/src/main/java/java/util/LinkedHashMap.java b/ojluni/src/main/java/java/util/LinkedHashMap.java
index aec40bc..7c8cad0 100644
--- a/ojluni/src/main/java/java/util/LinkedHashMap.java
+++ b/ojluni/src/main/java/java/util/LinkedHashMap.java
@@ -158,7 +158,7 @@
  * {@code LinkedHashMap}.
  *
  * <p>This class is a member of the
- * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/openjdk-redirect.html?v=8&path=/technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @implNote
diff --git a/ojluni/src/main/java/java/util/Locale.java b/ojluni/src/main/java/java/util/Locale.java
index 9d9f3e4..c96bb13 100644
--- a/ojluni/src/main/java/java/util/Locale.java
+++ b/ojluni/src/main/java/java/util/Locale.java
@@ -520,6 +520,10 @@
  *     <td><a href="http://site.icu-project.org/download/58">ICU 58.2</a></td>
  *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-30">CLDR 30.0.3</a></td>
  *     <td><a href="http://www.unicode.org/versions/Unicode9.0.0/">Unicode 9.0</a></td></tr>
+ * <tr><td>Android 9.0 (TBD)</td>
+ *     <td><a href="http://site.icu-project.org/download/60">ICU 60.2</a></td>
+ *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-32">CLDR 32.0.1</a></td>
+ *     <td><a href="http://www.unicode.org/versions/Unicode10.0.0/">Unicode 10.0</a></td></tr>
  * </table>
  *
  * <a name="default_locale"></a><h4>Be wary of the default locale</h3>
diff --git a/ojluni/src/main/java/java/util/concurrent/CompletableFuture.java b/ojluni/src/main/java/java/util/concurrent/CompletableFuture.java
index b1de4f6..976bfe4 100644
--- a/ojluni/src/main/java/java/util/concurrent/CompletableFuture.java
+++ b/ojluni/src/main/java/java/util/concurrent/CompletableFuture.java
@@ -42,6 +42,8 @@
 import java.util.function.Function;
 import java.util.function.Supplier;
 
+// Android-note: Class javadoc changed to remove references to hidden OpenJDK 9 methods.
+
 /**
  * A {@link Future} that may be explicitly completed (setting its
  * value and status), and may be used as a {@link CompletionStage},
@@ -2405,9 +2407,8 @@
      * @param <U> the type of the value
      * @return a new CompletableFuture
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public <U> CompletableFuture<U> newIncompleteFuture() {
         return new CompletableFuture<U>();
     }
@@ -2422,9 +2423,8 @@
      *
      * @return the executor
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public Executor defaultExecutor() {
         return ASYNC_POOL;
     }
@@ -2442,9 +2442,8 @@
      *
      * @return the new CompletableFuture
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public CompletableFuture<T> copy() {
         return uniCopyStage();
     }
@@ -2461,9 +2460,8 @@
      *
      * @return the new CompletionStage
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public CompletionStage<T> minimalCompletionStage() {
         return uniAsMinimalStage();
     }
@@ -2478,9 +2476,8 @@
      * @param executor the executor to use for asynchronous execution
      * @return this CompletableFuture
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier,
                                               Executor executor) {
         if (supplier == null || executor == null)
@@ -2498,9 +2495,8 @@
      * to complete this CompletableFuture
      * @return this CompletableFuture
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier) {
         return completeAsync(supplier, defaultExecutor());
     }
@@ -2516,9 +2512,8 @@
      *        {@code timeout} parameter
      * @return this CompletableFuture
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public CompletableFuture<T> orTimeout(long timeout, TimeUnit unit) {
         if (unit == null)
             throw new NullPointerException();
@@ -2539,9 +2534,8 @@
      *        {@code timeout} parameter
      * @return this CompletableFuture
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public CompletableFuture<T> completeOnTimeout(T value, long timeout,
                                                   TimeUnit unit) {
         if (unit == null)
@@ -2565,9 +2559,8 @@
      * @param executor the base executor
      * @return the new delayed executor
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public static Executor delayedExecutor(long delay, TimeUnit unit,
                                            Executor executor) {
         if (unit == null || executor == null)
@@ -2586,9 +2579,8 @@
      *        {@code delay} parameter
      * @return the new delayed executor
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public static Executor delayedExecutor(long delay, TimeUnit unit) {
         if (unit == null)
             throw new NullPointerException();
@@ -2604,9 +2596,8 @@
      * @param <U> the type of the value
      * @return the completed CompletionStage
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public static <U> CompletionStage<U> completedStage(U value) {
         return new MinimalStage<U>((value == null) ? NIL : value);
     }
@@ -2619,9 +2610,8 @@
      * @param <U> the type of the value
      * @return the exceptionally completed CompletableFuture
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public static <U> CompletableFuture<U> failedFuture(Throwable ex) {
         if (ex == null) throw new NullPointerException();
         return new CompletableFuture<U>(new AltResult(ex));
@@ -2636,9 +2626,8 @@
      * @param <U> the type of the value
      * @return the exceptionally completed CompletionStage
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     public static <U> CompletionStage<U> failedStage(Throwable ex) {
         if (ex == null) throw new NullPointerException();
         return new MinimalStage<U>(new AltResult(ex));
diff --git a/ojluni/src/main/java/java/util/concurrent/ConcurrentHashMap.java b/ojluni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
index 2b51d91..67c8622 100644
--- a/ojluni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
+++ b/ojluni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
@@ -2562,7 +2562,8 @@
      * A padded cell for distributing counts.  Adapted from LongAdder
      * and Striped64.  See their internal docs for explanation.
      */
-    //@jdk.internal.vm.annotation.Contended // Android-removed
+    // Android-removed: @Contended, this hint is not used by the Android runtime.
+    //@jdk.internal.vm.annotation.Contended
     static final class CounterCell {
         volatile long value;
         CounterCell(long x) { value = x; }
diff --git a/ojluni/src/main/java/java/util/concurrent/CountedCompleter.java b/ojluni/src/main/java/java/util/concurrent/CountedCompleter.java
index f65371aa..a29208e 100644
--- a/ojluni/src/main/java/java/util/concurrent/CountedCompleter.java
+++ b/ojluni/src/main/java/java/util/concurrent/CountedCompleter.java
@@ -42,7 +42,7 @@
  * presence of subtask stalls and blockage than are other forms of
  * ForkJoinTasks, but are less intuitive to program.  Uses of
  * CountedCompleter are similar to those of other completion based
- * components
+ * components (such as {@link java.nio.channels.CompletionHandler})
  * except that multiple <em>pending</em> completions may be necessary
  * to trigger the completion action {@link #onCompletion(CountedCompleter)},
  * not just one.
diff --git a/ojluni/src/main/java/java/util/concurrent/Exchanger.java b/ojluni/src/main/java/java/util/concurrent/Exchanger.java
index b1e9324..f01a705 100644
--- a/ojluni/src/main/java/java/util/concurrent/Exchanger.java
+++ b/ojluni/src/main/java/java/util/concurrent/Exchanger.java
@@ -306,7 +306,8 @@
      * Nodes hold partially exchanged data, plus other per-thread
      * bookkeeping. Padded via @Contended to reduce memory contention.
      */
-    //@jdk.internal.vm.annotation.Contended // Android-removed
+    // Android-removed: @Contended, this hint is not used by the Android runtime.
+    //@jdk.internal.vm.annotation.Contended
     static final class Node {
         int index;              // Arena index
         int bound;              // Last recorded value of Exchanger.bound
diff --git a/ojluni/src/main/java/java/util/concurrent/Executors.java b/ojluni/src/main/java/java/util/concurrent/Executors.java
index 9244136..565fdeb 100644
--- a/ojluni/src/main/java/java/util/concurrent/Executors.java
+++ b/ojluni/src/main/java/java/util/concurrent/Executors.java
@@ -341,6 +341,7 @@
         return new DelegatedScheduledExecutorService(executor);
     }
 
+    // Android-changed: Removed references to SecurityManager from javadoc.
     /**
      * Returns a default thread factory used to create new threads.
      * This factory creates all new threads used by an Executor in the
@@ -358,6 +359,7 @@
         return new DefaultThreadFactory();
     }
 
+    // Android-changed: Dropped documentation for legacy security code.
     /**
      * Legacy security code; do not use.
      */
@@ -424,6 +426,7 @@
             public Object call() throws Exception { return action.run(); }};
     }
 
+    // Android-changed: Dropped documentation for legacy security code.
     /**
      * Legacy security code; do not use.
      */
@@ -433,6 +436,7 @@
         return new PrivilegedCallable<T>(callable);
     }
 
+    // Android-changed: Dropped documentation for legacy security code.
     /**
      * Legacy security code; do not use.
      */
@@ -497,19 +501,20 @@
         final ClassLoader ccl;
 
         PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
-            // BEGIN Android-removed
-            // SecurityManager sm = System.getSecurityManager();
-            // if (sm != null) {
-            //     // Calls to getContextClassLoader from this class
-            //     // never trigger a security check, but we check
-            //     // whether our callers have this permission anyways.
-            //     sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
+            // Android-removed: System.getSecurityManager always returns null.
+            /*
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                // Calls to getContextClassLoader from this class
+                // never trigger a security check, but we check
+                // whether our callers have this permission anyways.
+                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
 
-            //     // Whether setContextClassLoader turns out to be necessary
-            //     // or not, we fail fast if permission is not available.
-            //     sm.checkPermission(new RuntimePermission("setContextClassLoader"));
-            // }
-            // END Android-removed
+                // Whether setContextClassLoader turns out to be necessary
+                // or not, we fail fast if permission is not available.
+                sm.checkPermission(new RuntimePermission("setContextClassLoader"));
+            }
+            */
             this.task = task;
             this.acc = AccessController.getContext();
             this.ccl = Thread.currentThread().getContextClassLoader();
@@ -579,18 +584,19 @@
 
         PrivilegedThreadFactory() {
             super();
-            // BEGIN Android-removed
-            // SecurityManager sm = System.getSecurityManager();
-            // if (sm != null) {
-            //     // Calls to getContextClassLoader from this class
-            //     // never trigger a security check, but we check
-            //     // whether our callers have this permission anyways.
-            //     sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
+            // Android-removed: System.getSecurityManager always returns null.
+            /*
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                // Calls to getContextClassLoader from this class
+                // never trigger a security check, but we check
+                // whether our callers have this permission anyways.
+                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
 
-            //     // Fail fast
-            //     sm.checkPermission(new RuntimePermission("setContextClassLoader"));
-            // }
-            // END Android-removed
+                // Fail fast
+                sm.checkPermission(new RuntimePermission("setContextClassLoader"));
+            }
+            */
             this.acc = AccessController.getContext();
             this.ccl = Thread.currentThread().getContextClassLoader();
         }
diff --git a/ojluni/src/main/java/java/util/concurrent/ForkJoinPool.java b/ojluni/src/main/java/java/util/concurrent/ForkJoinPool.java
index 9cf9b2d..04ad7d7 100644
--- a/ojluni/src/main/java/java/util/concurrent/ForkJoinPool.java
+++ b/ojluni/src/main/java/java/util/concurrent/ForkJoinPool.java
@@ -162,7 +162,8 @@
  * @since 1.7
  * @author Doug Lea
  */
-//@jdk.internal.vm.annotation.Contended   // Android-removed
+// Android-removed: @Contended, this hint is not used by the Android runtime.
+//@jdk.internal.vm.annotation.Contended
 public class ForkJoinPool extends AbstractExecutorService {
 
     /*
@@ -781,7 +782,8 @@
      * arrays sharing cache lines. The @Contended annotation alerts
      * JVMs to try to keep instances apart.
      */
-    //@jdk.internal.vm.annotation.Contended   // Android-removed
+    // Android-removed: @Contended, this hint is not used by the Android runtime.
+    //@jdk.internal.vm.annotation.Contended
     static final class WorkQueue {
 
         /**
@@ -820,7 +822,8 @@
         volatile Thread parker;    // == owner during call to park; else null
         volatile ForkJoinTask<?> currentJoin; // task being joined in awaitJoin
 
-      // @jdk.internal.vm.annotation.Contended("group2") // segregate // Android-removed
+      // Android-removed: @Contended, this hint is not used by the Android runtime.
+      // @jdk.internal.vm.annotation.Contended("group2") // segregate
         volatile ForkJoinTask<?> currentSteal; // nonnull when running some task
 
         WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) {
diff --git a/ojluni/src/main/java/java/util/concurrent/ForkJoinTask.java b/ojluni/src/main/java/java/util/concurrent/ForkJoinTask.java
index 1f25549..efccfa5 100644
--- a/ojluni/src/main/java/java/util/concurrent/ForkJoinTask.java
+++ b/ojluni/src/main/java/java/util/concurrent/ForkJoinTask.java
@@ -1300,9 +1300,8 @@
      *
      * @return a task, or {@code null} if none are available
      * @since 9
-     * @hide
+     * @hide API from OpenJDK 9, not yet exposed on Android.
      */
-    // Android-changed: hidden
     protected static ForkJoinTask<?> pollSubmission() {
         Thread t;
         return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
diff --git a/ojluni/src/main/java/java/util/concurrent/ThreadLocalRandom.java b/ojluni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
index 03fa594..195f8ac 100644
--- a/ojluni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
+++ b/ojluni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
@@ -461,6 +461,7 @@
 
     // stream methods, coded in a way intended to better isolate for
     // maintenance purposes the small differences across forms.
+
     /**
      * Returns a stream producing the given {@code streamSize} number of
      * pseudorandom {@code int} values.
diff --git a/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java b/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
index b7d2246..b0096a4 100644
--- a/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
+++ b/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
@@ -1545,6 +1545,7 @@
         return handler;
     }
 
+    // Android-changed: Tolerate maximumPoolSize >= corePoolSize during setCorePoolSize().
     /**
      * Sets the core number of threads.  This overrides any value set
      * in the constructor.  If the new value is smaller than the
@@ -1556,15 +1557,15 @@
      * @throws IllegalArgumentException if {@code corePoolSize < 0}
      * @see #getCorePoolSize
      */
-     // Android-changed: Reverted code that threw an IAE when
-     // {@code corePoolSize} is greater than the {@linkplain #getMaximumPoolSize()
-     // maximum pool size}. This is due to defective code in a commonly used third
-     // party library that does something like :
-     //
-     // exec.setCorePoolSize(N);
-     // exec.setMaxPoolSize(N);
     public void setCorePoolSize(int corePoolSize) {
+        // BEGIN Android-changed: Tolerate maximumPoolSize >= corePoolSize during setCorePoolSize().
+        // This reverts a change that threw an IAE on that condition. This is due to defective code
+        // in a commonly used third party library that does something like exec.setCorePoolSize(N)
+        // before doing exec.setMaxPoolSize(N).
+        //
+        // if (corePoolSize < 0 || maximumPoolSize < corePoolSize)
         if (corePoolSize < 0)
+        // END Android-changed: Tolerate maximumPoolSize >= corePoolSize during setCorePoolSize().
             throw new IllegalArgumentException();
         int delta = corePoolSize - this.corePoolSize;
         this.corePoolSize = corePoolSize;
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index 8812a8c..4fc576f 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -35,7 +35,7 @@
 
 package java.util.concurrent.atomic;
 
-import dalvik.system.VMStack; // Android-added
+import dalvik.system.VMStack;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
@@ -85,7 +85,9 @@
     public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
                                                               String fieldName) {
         return new AtomicIntegerFieldUpdaterImpl<U>
-            (tclass, fieldName, VMStack.getStackClass1()); // Android-changed
+            // Android-changed: Use VMStack.getStackClass1.
+            // (tclass, fieldName, Reflection.getCallerClass());
+            (tclass, fieldName, VMStack.getStackClass1());
     }
 
     /**
@@ -384,27 +386,33 @@
             final Field field;
             final int modifiers;
             try {
+                // Android-changed: Skip privilege escalation which is a noop on Android.
+                /*
                 field = AccessController.doPrivileged(
                     new PrivilegedExceptionAction<Field>() {
                         public Field run() throws NoSuchFieldException {
                             return tclass.getDeclaredField(fieldName);
                         }
                     });
+                */
+                field = tclass.getDeclaredField(fieldName);
                 modifiers = field.getModifiers();
-                // BEGIN Android-removed
-                // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
-                //     caller, tclass, null, modifiers);
-                // ClassLoader cl = tclass.getClassLoader();
-                // ClassLoader ccl = caller.getClassLoader();
-                // if ((ccl != null) && (ccl != cl) &&
-                //     ((cl == null) || !isAncestor(cl, ccl))) {
-                //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
-                // }
-                // END Android-removed
-            // BEGIN Android-removed
-            // } catch (PrivilegedActionException pae) {
-            //     throw new RuntimeException(pae.getException());
-            // END Android-removed
+                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+                    caller, tclass, null, modifiers);
+                // BEGIN Android-removed: Skip checkPackageAccess which is a noop on Android.
+                /*
+                ClassLoader cl = tclass.getClassLoader();
+                ClassLoader ccl = caller.getClassLoader();
+                if ((ccl != null) && (ccl != cl) &&
+                    ((cl == null) || !isAncestor(cl, ccl))) {
+                    sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                }
+                */
+            // BEGIN Android-removed: Skip privilege escalation which is a noop on Android.
+            /*
+            } catch (PrivilegedActionException pae) {
+                throw new RuntimeException(pae.getException());
+            */
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -420,23 +428,24 @@
             this.offset = U.objectFieldOffset(field);
         }
 
-        // BEGIN Android-removed
-        // /**
-        //  * Returns true if the second classloader can be found in the first
-        //  * classloader's delegation chain.
-        //  * Equivalent to the inaccessible: first.isAncestor(second).
-        //  */
-        // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
-        //     ClassLoader acl = first;
-        //     do {
-        //         acl = acl.getParent();
-        //         if (second == acl) {
-        //             return true;
-        //         }
-        //     } while (acl != null);
-        //     return false;
-        // }
-        // END Android-removed
+        // Android-removed: isAncestor's only usage was removed above.
+        /*
+        /**
+         * Returns true if the second classloader can be found in the first
+         * classloader's delegation chain.
+         * Equivalent to the inaccessible: first.isAncestor(second).
+         *
+        private static boolean isAncestor(ClassLoader first, ClassLoader second) {
+            ClassLoader acl = first;
+            do {
+                acl = acl.getParent();
+                if (second == acl) {
+                    return true;
+                }
+            } while (acl != null);
+            return false;
+        }
+        */
 
         /**
          * Checks that target argument is instance of cclass.  On
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index 73c4e3e..721f58a 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -35,7 +35,7 @@
 
 package java.util.concurrent.atomic;
 
-import dalvik.system.VMStack; // Android-added
+import dalvik.system.VMStack;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
@@ -84,7 +84,9 @@
     @CallerSensitive
     public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
                                                            String fieldName) {
-      Class<?> caller = VMStack.getStackClass1(); // Android-changed
+        // Android-changed: Use VMStack.getStackClass1.
+        // Class<?> caller = Reflection.getCallerClass();
+        Class<?> caller = VMStack.getStackClass1();
         if (AtomicLong.VM_SUPPORTS_LONG_CAS)
             return new CASUpdater<U>(tclass, fieldName, caller);
         else
@@ -382,22 +384,33 @@
             final Field field;
             final int modifiers;
             try {
-                field = tclass.getDeclaredField(fieldName); // Android-changed
+                // Android-changed: Skip privilege escalation which is a noop on Android.
+                /*
+                field = AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<Field>() {
+                        public Field run() throws NoSuchFieldException {
+                            return tclass.getDeclaredField(fieldName);
+                        }
+                    });
+                */
+                field = tclass.getDeclaredField(fieldName);
                 modifiers = field.getModifiers();
-                // BEGIN Android-removed
-                // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
-                //     caller, tclass, null, modifiers);
-                // ClassLoader cl = tclass.getClassLoader();
-                // ClassLoader ccl = caller.getClassLoader();
-                // if ((ccl != null) && (ccl != cl) &&
-                //     ((cl == null) || !isAncestor(cl, ccl))) {
-                //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
-                // }
-                // END Android-removed
-            // BEGIN Android-removed
-            // } catch (PrivilegedActionException pae) {
-            //     throw new RuntimeException(pae.getException());
-            // END Android-removed
+                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+                    caller, tclass, null, modifiers);
+                // Android-removed: Skip checkPackageAccess which is a noop on Android.
+                /*
+                ClassLoader cl = tclass.getClassLoader();
+                ClassLoader ccl = caller.getClassLoader();
+                if ((ccl != null) && (ccl != cl) &&
+                    ((cl == null) || !isAncestor(cl, ccl))) {
+                    sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                }
+                */
+            // Android-removed: Skip privilege escalation which is a noop on Android.
+            /*
+            } catch (PrivilegedActionException pae) {
+                throw new RuntimeException(pae.getException());
+            */
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -512,22 +525,33 @@
             Field field = null;
             int modifiers = 0;
             try {
-                field = tclass.getDeclaredField(fieldName); // Android-changed
+                // Android-changed: Skip privilege escalation which is a noop on Android.
+                /*
+                field = AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<Field>() {
+                        public Field run() throws NoSuchFieldException {
+                            return tclass.getDeclaredField(fieldName);
+                        }
+                    });
+                */
+                field = tclass.getDeclaredField(fieldName);
                 modifiers = field.getModifiers();
-                // BEGIN Android-removed
-                // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
-                //     caller, tclass, null, modifiers);
-                // ClassLoader cl = tclass.getClassLoader();
-                // ClassLoader ccl = caller.getClassLoader();
-                // if ((ccl != null) && (ccl != cl) &&
-                //     ((cl == null) || !isAncestor(cl, ccl))) {
-                //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
-                // }
-                // END Android-removed
-            // BEGIN Android-removed
-            // } catch (PrivilegedActionException pae) {
-            //     throw new RuntimeException(pae.getException());
-            // END Android-removed
+                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+                    caller, tclass, null, modifiers);
+                // Android-removed: Skip checkPackageAccess which is a noop on Android.
+                /*
+                ClassLoader cl = tclass.getClassLoader();
+                ClassLoader ccl = caller.getClassLoader();
+                if ((ccl != null) && (ccl != cl) &&
+                    ((cl == null) || !isAncestor(cl, ccl))) {
+                    sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                }
+                */
+            // Android-removed: Skip privilege escalation which is a noop on Android.
+            /*
+            } catch (PrivilegedActionException pae) {
+                throw new RuntimeException(pae.getException());
+            */
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -604,21 +628,22 @@
         }
     }
 
-    // BEGIN Android-removed
-    // /**
-    //  * Returns true if the second classloader can be found in the first
-    //  * classloader's delegation chain.
-    //  * Equivalent to the inaccessible: first.isAncestor(second).
-    //  */
-    // static boolean isAncestor(ClassLoader first, ClassLoader second) {
-    //     ClassLoader acl = first;
-    //     do {
-    //         acl = acl.getParent();
-    //         if (second == acl) {
-    //             return true;
-    //         }
-    //     } while (acl != null);
-    //     return false;
-    // }
-    // END Android-removed
+    // Android-removed: isAncestor's only usage was removed above.
+    /*
+    /**
+     * Returns true if the second classloader can be found in the first
+     * classloader's delegation chain.
+     * Equivalent to the inaccessible: first.isAncestor(second).
+     *
+    static boolean isAncestor(ClassLoader first, ClassLoader second) {
+        ClassLoader acl = first;
+        do {
+            acl = acl.getParent();
+            if (second == acl) {
+                return true;
+            }
+        } while (acl != null);
+        return false;
+    }
+    */
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index 5164f36..2eef7e0 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -35,7 +35,7 @@
 
 package java.util.concurrent.atomic;
 
-import dalvik.system.VMStack; // Android-added
+import dalvik.system.VMStack;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
@@ -107,7 +107,9 @@
                                                                     Class<W> vclass,
                                                                     String fieldName) {
         return new AtomicReferenceFieldUpdaterImpl<U,W>
-            (tclass, vclass, fieldName, VMStack.getStackClass1()); // Android-changed
+            // Android-changed: Use VMStack.getStackClass1.
+            // (tclass, vclass, fieldName, Reflection.getCallerClass());
+            (tclass, vclass, fieldName, VMStack.getStackClass1());
     }
 
     /**
@@ -317,23 +319,34 @@
             final Class<?> fieldClass;
             final int modifiers;
             try {
-                field = tclass.getDeclaredField(fieldName); // Android-changed
+                // Android-changed: Skip privilege escalation which is a noop on Android.
+                /*
+                field = AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<Field>() {
+                        public Field run() throws NoSuchFieldException {
+                            return tclass.getDeclaredField(fieldName);
+                        }
+                    });
+                */
+                field = tclass.getDeclaredField(fieldName);
                 modifiers = field.getModifiers();
-                // BEGIN Android-removed
-                // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
-                //     caller, tclass, null, modifiers);
-                // ClassLoader cl = tclass.getClassLoader();
-                // ClassLoader ccl = caller.getClassLoader();
-                // if ((ccl != null) && (ccl != cl) &&
-                //     ((cl == null) || !isAncestor(cl, ccl))) {
-                //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
-                // }
-                // END Android-removed
+                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+                    caller, tclass, null, modifiers);
+                // Android-removed: Skip checkPackageAccess which is a noop on Android.
+                /*
+                ClassLoader cl = tclass.getClassLoader();
+                ClassLoader ccl = caller.getClassLoader();
+                if ((ccl != null) && (ccl != cl) &&
+                    ((cl == null) || !isAncestor(cl, ccl))) {
+                    sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                }
+                */
                 fieldClass = field.getType();
-            // BEGIN Android-removed
-            // } catch (PrivilegedActionException pae) {
-            //     throw new RuntimeException(pae.getException());
-            // END Android-removed
+            // Android-removed: Skip privilege escalation which is a noop on Android.
+            /*
+            } catch (PrivilegedActionException pae) {
+                throw new RuntimeException(pae.getException());
+            */
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -352,23 +365,24 @@
             this.offset = U.objectFieldOffset(field);
         }
 
-        // BEGIN Android-removed
-        // /**
-        //  * Returns true if the second classloader can be found in the first
-        //  * classloader's delegation chain.
-        //  * Equivalent to the inaccessible: first.isAncestor(second).
-        //  */
-        // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
-        //     ClassLoader acl = first;
-        //     do {
-        //         acl = acl.getParent();
-        //         if (second == acl) {
-        //             return true;
-        //         }
-        //     } while (acl != null);
-        //     return false;
-        // }
-        // END Android-removed
+        // Android-removed: isAncestor's only usage was removed above.
+        /*
+        /**
+         * Returns true if the second classloader can be found in the first
+         * classloader's delegation chain.
+         * Equivalent to the inaccessible: first.isAncestor(second).
+         *
+        private static boolean isAncestor(ClassLoader first, ClassLoader second) {
+            ClassLoader acl = first;
+            do {
+                acl = acl.getParent();
+                if (second == acl) {
+                    return true;
+                }
+            } while (acl != null);
+            return false;
+        }
+        */
 
         /**
          * Checks that target argument is instance of cclass.  On
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/Striped64.java b/ojluni/src/main/java/java/util/concurrent/atomic/Striped64.java
index e52729a..2a8f327 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/Striped64.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/Striped64.java
@@ -119,7 +119,8 @@
      * JVM intrinsics note: It would be possible to use a release-only
      * form of CAS here, if it were provided.
      */
-    // @jdk.internal.vm.annotation.Contended // Android-removed
+    // Android-removed: @Contended, this hint is not used by the Android runtime.
+    // @jdk.internal.vm.annotation.Contended
     static final class Cell {
         volatile long value;
         Cell(long x) { value = x; }
diff --git a/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
index 894de90..602b5ce 100644
--- a/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+++ b/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -886,6 +886,8 @@
      * @param arg the acquire argument
      * @return {@code true} if interrupted while waiting
      */
+    // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
+    // @ReservedStackAccess
     final boolean acquireQueued(final Node node, int arg) {
         try {
             boolean interrupted = false;
@@ -1218,6 +1220,8 @@
      *        {@link #tryAcquire} but is otherwise uninterpreted and
      *        can represent anything you like.
      */
+    // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
+    // @ReservedStackAccess
     public final void acquire(int arg) {
         if (!tryAcquire(arg) &&
             acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
@@ -1281,6 +1285,8 @@
      *        can represent anything you like.
      * @return the value returned from {@link #tryRelease}
      */
+    // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
+    // @ReservedStackAccess
     public final boolean release(int arg) {
         if (tryRelease(arg)) {
             Node h = head;
@@ -1361,6 +1367,8 @@
      *        and can represent anything you like.
      * @return the value returned from {@link #tryReleaseShared}
      */
+    // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
+    // @ReservedStackAccess
     public final boolean releaseShared(int arg) {
         if (tryReleaseShared(arg)) {
             doReleaseShared();
diff --git a/ojluni/src/main/java/java/util/concurrent/locks/ReentrantLock.java b/ojluni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
index 9df2505..3c1c492 100644
--- a/ojluni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
+++ b/ojluni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
@@ -127,6 +127,8 @@
          * Performs non-fair tryLock.  tryAcquire is implemented in
          * subclasses, but both need nonfair try for trylock method.
          */
+        // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
+        // @ReservedStackAccess
         final boolean nonfairTryAcquire(int acquires) {
             final Thread current = Thread.currentThread();
             int c = getState();
@@ -146,6 +148,8 @@
             return false;
         }
 
+        // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
+        // @ReservedStackAccess
         protected final boolean tryRelease(int releases) {
             int c = getState() - releases;
             if (Thread.currentThread() != getExclusiveOwnerThread())
@@ -203,6 +207,8 @@
          * Performs lock.  Try immediate barge, backing up to normal
          * acquire on failure.
          */
+        // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
+        // @ReservedStackAccess
         final void lock() {
             if (compareAndSetState(0, 1))
                 setExclusiveOwnerThread(Thread.currentThread());
@@ -229,6 +235,8 @@
          * Fair version of tryAcquire.  Don't grant access unless
          * recursive call or no waiters or is first.
          */
+        // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
+        // @ReservedStackAccess
         protected final boolean tryAcquire(int acquires) {
             final Thread current = Thread.currentThread();
             int c = getState();
diff --git a/ojluni/src/main/java/java/util/logging/FileHandler.java b/ojluni/src/main/java/java/util/logging/FileHandler.java
index 9cae655..24a7c75 100644
--- a/ojluni/src/main/java/java/util/logging/FileHandler.java
+++ b/ojluni/src/main/java/java/util/logging/FileHandler.java
@@ -598,13 +598,14 @@
                     continue;
                 } else if (ch2 == 'h') {
                     file = new File(System.getProperty("user.home"));
-                    // Android-changed: Don't make a special exemption for setuid programs.
-                    //
-                    // if (isSetUID()) {
-                    //     // Ok, we are in a set UID program.  For safety's sake
-                    //     // we disallow attempts to open files relative to %h.
-                    //     throw new IOException("can't use %h in set UID program");
-                    // }
+                    // Android-removed: Don't prohibit using user.home property in setuid programs.
+                    /*
+                    if (isSetUID()) {
+                        // Ok, we are in a set UID program.  For safety's sake
+                        // we disallow attempts to open files relative to %h.
+                        throw new IOException("can't use %h in set UID program");
+                    }
+                    */
                     ix++;
                     word = "";
                     continue;
@@ -735,9 +736,11 @@
         }
     }
 
-    // Android-changed: Not required.
+    // Android-removed: isSetUID's only caller is removed.
+    /*
     /**
      * check if we are in a set UID program.
-     */
-    // private static native boolean isSetUID();
+     *
+    private static native boolean isSetUID();
+    */
 }
diff --git a/ojluni/src/main/java/java/util/logging/Level.java b/ojluni/src/main/java/java/util/logging/Level.java
index c03b171..17b585b 100644
--- a/ojluni/src/main/java/java/util/logging/Level.java
+++ b/ojluni/src/main/java/java/util/logging/Level.java
@@ -262,8 +262,9 @@
     }
 
     private String computeLocalizedLevelName(Locale newLocale) {
-        // Android-changed: Use Thread.currentThread().getContextClassLoader(),
-        // otherwise we might get a BootClassLoader.
+        // Android-changed: Use Thread.currentThread().getContextClassLoader().
+        // Otherwise, we might get a BootClassLoader.
+        // ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName, newLocale);
         ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName, newLocale,
                                                      Thread.currentThread().getContextClassLoader());
         final String localizedName = rb.getString(name);
diff --git a/ojluni/src/main/java/java/util/logging/LogManager.java b/ojluni/src/main/java/java/util/logging/LogManager.java
index 7a08510..0d51b0f 100644
--- a/ojluni/src/main/java/java/util/logging/LogManager.java
+++ b/ojluni/src/main/java/java/util/logging/LogManager.java
@@ -185,6 +185,7 @@
                 try {
                     cname = System.getProperty("java.util.logging.manager");
                     if (cname != null) {
+                        // Android-changed: Extract logic into the getClassInstance() helper.
                         mgr = (LogManager) getClassInstance(cname).newInstance();
                     }
                 } catch (Exception ex) {
@@ -198,7 +199,7 @@
 
             }
         });
-     }
+    }
 
 
     // This private class is used as a shutdown hook.
@@ -487,7 +488,7 @@
     // Returns the LoggerContext for the user code (i.e. application or AppContext).
     // Loggers are isolated from each AppContext.
     private LoggerContext getUserContext() {
-        // Android-changed: No AWT specific hooks.
+        // Android-changed: Remove AWT specific hooks.
         return userContext;
     }
 
@@ -582,20 +583,13 @@
         return sysLogger;
     }
 
-    private static Class getClassInstance(String cname) {
-        Class clz = null;
-        if (cname != null) {
-            try {
-                clz = ClassLoader.getSystemClassLoader().loadClass(cname);
-            } catch (ClassNotFoundException ex) {
-                try {
-                    clz = Thread.currentThread().getContextClassLoader().loadClass(cname);
-                } catch (ClassNotFoundException innerEx) {
-                    clz = null;
-                }
-            }
+    // Android-added: getClassInstance helper method, used in several places in this class.
+    private static Class getClassInstance(String cname) throws ClassNotFoundException {
+        try {
+            return ClassLoader.getSystemClassLoader().loadClass(cname);
+        } catch (ClassNotFoundException ex) {
+            return Thread.currentThread().getContextClassLoader().loadClass(cname);
         }
-        return clz;
     }
 
     // LoggerContext maintains the logger namespace per context.
@@ -641,7 +635,7 @@
         // the context requires default loggers, will be added to the context
         // logger's tree.
         final Logger getGlobalLogger() {
-            // Android-changed: s/deprecated/deprecation
+            // Android-changed: Fix SuppressWarnings from "deprecated" to "deprecation".
             @SuppressWarnings("deprecation") // avoids initialization cycles.
             final Logger global = Logger.global;
             return global;
@@ -743,19 +737,9 @@
             return addLocalLogger(logger, requiresDefaultLoggers());
         }
 
-        boolean addLocalLogger(Logger logger, LogManager manager) {
-            // no need to add default loggers if it's not required
-            return addLocalLogger(logger, requiresDefaultLoggers(), manager);
-        }
-
-        boolean addLocalLogger(Logger logger, boolean addDefaultLoggersIfNeeded) {
-            return addLocalLogger(logger, addDefaultLoggersIfNeeded, manager);
-        }
-
         // Add a logger to this context.  This method will only set its level
         // and process parent loggers.  It doesn't set its handlers.
-        synchronized boolean addLocalLogger(Logger logger, boolean addDefaultLoggersIfNeeded,
-                                            LogManager manager) {
+        synchronized boolean addLocalLogger(Logger logger, boolean addDefaultLoggersIfNeeded) {
             // addDefaultLoggersIfNeeded serves to break recursion when adding
             // default loggers. If we're adding one of the default loggers
             // (we're being called from ensureDefaultLogger()) then
@@ -957,7 +941,8 @@
                 for (int i = 0; i < names.length; i++) {
                     String word = names[i];
                     try {
-                        // Android-changed:
+                        // Android-changed: Fall back from the system to the context classloader.
+                        // Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
                         Class<?> clz = getClassInstance(word);
                         Handler hdl = (Handler) clz.newInstance();
                         // Check if there is a property defining the
@@ -1155,7 +1140,7 @@
         }
         drainLoggerRefQueueBounded();
         LoggerContext cx = getUserContext();
-        if (cx.addLocalLogger(logger, this)) {
+        if (cx.addLocalLogger(logger)) {
             // Do we have a per logger handler too?
             // Note: this will add a 200ms penalty
             loadLoggerHandlers(logger, name, name + ".handlers");
@@ -1268,6 +1253,7 @@
                 // Instantiate the named class.  It is its constructor's
                 // responsibility to initialize the logging configuration, by
                 // calling readConfiguration(InputStream) with a suitable stream.
+                // Android-changed: Extract logic into the getClassInstance() helper.
                 getClassInstance(cname).newInstance();
                 return;
             } catch (Exception ex) {
@@ -1288,8 +1274,14 @@
             fname = f.getCanonicalPath();
         }
 
-        // Android-changed: Look in the boot class-path jar files for the logging.properties.
-        // It will not be present in the file system.
+        // BEGIN Android-changed: Look in the boot class-path jar files for the logging.properties.
+        // It may not be present in the file system.
+        /*
+        try (final InputStream in = new FileInputStream(fname)) {
+            final BufferedInputStream bin = new BufferedInputStream(in);
+            readConfiguration(bin);
+        }
+        */
         InputStream in;
         try {
             in = new FileInputStream(fname);
@@ -1308,6 +1300,7 @@
                 in.close();
             }
         }
+        // END Android-changed: Look in the boot class-path jar files for the logging.properties.
     }
 
     /**
@@ -1419,6 +1412,9 @@
         for (int i = 0; i < names.length; i++) {
             String word = names[i];
             try {
+                // Android-changed: Fall back from the system to the context classloader.
+                // Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
+                // clz.newInstance();
                 getClassInstance(word).newInstance();
             } catch (Exception ex) {
                 System.err.println("Can't load config class \"" + word + "\"");
@@ -1531,6 +1527,9 @@
         String val = getProperty(name);
         try {
             if (val != null) {
+                // Android-changed: Fall back from the system to the context classloader.
+                // Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(val);
+                // return (Filter) clz.newInstance();
                 return (Filter) getClassInstance(val).newInstance();
             }
         } catch (Exception ex) {
@@ -1551,6 +1550,9 @@
         String val = getProperty(name);
         try {
             if (val != null) {
+                // Android-changed: Fall back from the system to the context classloader.
+                // Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(val);
+                // return (Formatter) clz.newInstance();
                 return (Formatter) getClassInstance(val).newInstance();
             }
         } catch (Exception ex) {
@@ -1702,6 +1704,7 @@
 
     // Management Support
     private static LoggingMXBean loggingMXBean = null;
+    // Android-removed: References to java.lang.management in javadoc.
     /**
      * String representation of the {@code ObjectName} for the management interface
      * for the logging facility.
@@ -1710,12 +1713,10 @@
      *
      * @since 1.5
      */
-    // Android-changed: Remove reference to java.lang.management.ObjectName.
-    //
-    //@see java.lang.management.PlatformLoggingMXBean
     public final static String LOGGING_MXBEAN_NAME
         = "java.util.logging:type=Logging";
 
+    // Android-removed: References to java.lang.management in javadoc.
     /**
      * Returns <tt>LoggingMXBean</tt> for managing loggers.
      *
@@ -1723,17 +1724,6 @@
      *
      * @since 1.5
      */
-    // Android-removed docs areferring to java.lang.management.
-    //
-    // An alternative way to manage loggers is through the
-    // {@link java.lang.management.PlatformLoggingMXBean} interface
-    // that can be obtained by calling:
-    // <pre>
-    //     PlatformLoggingMXBean logging = {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
-    //        ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class);
-    // </pre>
-    //
-    // @see java.lang.management.PlatformLoggingMXBean
     public static synchronized LoggingMXBean getLoggingMXBean() {
         if (loggingMXBean == null) {
             loggingMXBean =  new Logging();
diff --git a/ojluni/src/main/java/java/util/logging/LogRecord.java b/ojluni/src/main/java/java/util/logging/LogRecord.java
index e5ead8b..3b0e518 100644
--- a/ojluni/src/main/java/java/util/logging/LogRecord.java
+++ b/ojluni/src/main/java/java/util/logging/LogRecord.java
@@ -528,6 +528,12 @@
                                 ClassLoader.getSystemClassLoader());
                 resourceBundle = bundle;
             } catch (MissingResourceException ex) {
+                // Android-changed: Fall back to context classloader before giving up.
+                /*
+                // This is not a good place to throw an exception,
+                // so we simply leave the resourceBundle null.
+                resourceBundle = null;
+                */
                 try {
                     resourceBundle = ResourceBundle.getBundle(resourceBundleName, Locale.getDefault(),
                             Thread.currentThread().getContextClassLoader());
@@ -545,16 +551,24 @@
     // Private method to infer the caller's class and method names
     private void inferCaller() {
         needToInferCaller = false;
-        // Android-changed: Use VMStack.getThreadStackTrace.
+        // BEGIN Android-changed: Use VMStack.getThreadStackTrace.
+        /*
+        JavaLangAccess access = SharedSecrets.getJavaLangAccess();
+        Throwable throwable = new Throwable();
+        int depth = access.getStackTraceDepth(throwable);
+        */
         StackTraceElement[] stack = VMStack.getThreadStackTrace(Thread.currentThread());
         int depth = stack.length;
+        // END Android-changed: Use VMStack.getThreadStackTrace.
 
         boolean lookingForLogger = true;
         for (int ix = 0; ix < depth; ix++) {
             // Calling getStackTraceElement directly prevents the VM
             // from paying the cost of building the entire stack frame.
             //
-            // Android-changed: Use value from getThreadStackTrace.
+            // Android-changed: Use value from previous getThreadStackTrace call.
+            // StackTraceElement frame =
+            //     access.getStackTraceElement(throwable, ix);
             StackTraceElement frame = stack[ix];
             String cname = frame.getClassName();
             boolean isLoggerImpl = isLoggerImplFrame(cname);
diff --git a/ojluni/src/main/java/java/util/logging/Logger.java b/ojluni/src/main/java/java/util/logging/Logger.java
index 8cf98fe..d7de5d8 100644
--- a/ojluni/src/main/java/java/util/logging/Logger.java
+++ b/ojluni/src/main/java/java/util/logging/Logger.java
@@ -441,7 +441,7 @@
                     return System.getProperty(key);
                 }
             });
-            return Boolean.parseBoolean(s);
+            return Boolean.valueOf(s);
         }
     }
 
@@ -502,6 +502,7 @@
         // the existing "resourceBundleForFoo" with null.
         //
         // Android-changed: Use VMStack.getStackClass1.
+        // return demandLogger(name, null, Reflection.getCallerClass());
         return demandLogger(name, null, VMStack.getStackClass1());
     }
 
@@ -553,6 +554,7 @@
     @CallerSensitive
     public static Logger getLogger(String name, String resourceBundleName) {
         // Android-changed: Use VMStack.getStackClass1.
+        // Class<?> callerClass = Reflection.getCallerClass();
         Class<?> callerClass = VMStack.getStackClass1();
         Logger result = demandLogger(name, resourceBundleName, callerClass);
 
@@ -642,6 +644,8 @@
         // cleanup some Loggers that have been GC'ed
         manager.drainLoggerRefQueueBounded();
         // Android-changed: Use VMStack.getStackClass1.
+        // Logger result = new Logger(null, resourceBundleName,
+        //                            Reflection.getCallerClass(), manager, false);
         Logger result = new Logger(null, resourceBundleName,
                                    VMStack.getStackClass1(), manager, false);
         result.anonymous = true;
@@ -1894,6 +1898,7 @@
         if (useCallersClassLoader) {
             // Try with the caller's ClassLoader
             ClassLoader callersClassLoader = getCallersClassLoader();
+
             if (callersClassLoader == null || callersClassLoader == cl) {
                 return null;
             }
diff --git a/ojluni/src/main/java/java/util/logging/LoggingMXBean.java b/ojluni/src/main/java/java/util/logging/LoggingMXBean.java
index 0c67cc5..14777c0 100644
--- a/ojluni/src/main/java/java/util/logging/LoggingMXBean.java
+++ b/ojluni/src/main/java/java/util/logging/LoggingMXBean.java
@@ -26,6 +26,7 @@
 
 package java.util.logging;
 
+// Android-removed: References to java.lang.management in javadoc.
 
 /**
  * The management interface for the logging facility.
@@ -44,28 +45,6 @@
  * @since   1.5
  *
  */
-
-// Android-removed: References to java.lang.management.
-//
-// It is recommended
-// to use the {@link java.lang.management.PlatformLoggingMXBean} management
-// interface that implements all attributes defined in this
-// {@code LoggingMXBean}.  The
-// {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
-// ManagementFactory.getPlatformMXBean} method can be used to obtain
-// the {@code PlatformLoggingMXBean} object representing the management
-// interface for logging.
-//
-// This instance is an {@link javax.management.MXBean MXBean} that
-// can be obtained by calling the {@link LogManager#getLoggingMXBean}
-// method or from the
-// {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer
-// platform <tt>MBeanServer</tt>}.
-//
-// The instance registered in the platform {@code MBeanServer}
-// is also a {@link java.lang.management.PlatformLoggingMXBean}.
-//
-// @see java.lang.management.PlatformLoggingMXBean
 public interface LoggingMXBean {
 
     /**
diff --git a/ojluni/src/main/java/java/util/logging/MemoryHandler.java b/ojluni/src/main/java/java/util/logging/MemoryHandler.java
index 94153dc..704c155 100644
--- a/ojluni/src/main/java/java/util/logging/MemoryHandler.java
+++ b/ojluni/src/main/java/java/util/logging/MemoryHandler.java
@@ -129,12 +129,13 @@
                     + " does not specify a target");
         }
         Class<?> clz;
-
         try {
             clz = ClassLoader.getSystemClassLoader().loadClass(targetName);
             target = (Handler) clz.newInstance();
-        } catch (Exception ex) {
-            // Android-changed: Try to load the class from the context class loader.
+        // Android-changed: Fall back to the context classloader before giving up.
+        // } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
+        //     throw new RuntimeException("MemoryHandler can't load handler target \"" + targetName + "\"" , e);
+        } catch (Exception e) {
             try {
                 clz = Thread.currentThread().getContextClassLoader()
                         .loadClass(targetName);
diff --git a/ojluni/src/main/java/java/util/logging/SimpleFormatter.java b/ojluni/src/main/java/java/util/logging/SimpleFormatter.java
index 6433365..12412f1 100644
--- a/ojluni/src/main/java/java/util/logging/SimpleFormatter.java
+++ b/ojluni/src/main/java/java/util/logging/SimpleFormatter.java
@@ -1,4 +1,4 @@
-/*g
+/*
  * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
diff --git a/ojluni/src/main/java/java/util/logging/SocketHandler.java b/ojluni/src/main/java/java/util/logging/SocketHandler.java
index e571d68..2561e90 100644
--- a/ojluni/src/main/java/java/util/logging/SocketHandler.java
+++ b/ojluni/src/main/java/java/util/logging/SocketHandler.java
@@ -165,6 +165,7 @@
             throw new IllegalArgumentException("Null host name: " + host);
         }
 
+        // Android-added: Enforce cleartext policy.
         if (!NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted()) {
             throw new IOException("Cleartext traffic not permitted");
         }
diff --git a/ojluni/src/main/java/java/util/logging/XMLFormatter.java b/ojluni/src/main/java/java/util/logging/XMLFormatter.java
index f3bb335..ab95f58 100644
--- a/ojluni/src/main/java/java/util/logging/XMLFormatter.java
+++ b/ojluni/src/main/java/java/util/logging/XMLFormatter.java
@@ -152,6 +152,7 @@
             escape(sb, message);
             sb.append("</message>");
             sb.append("\n");
+        // Android-added: Include empty <message/> tag. http://b/25861348#comment17
         } else {
             sb.append("<message/>");
             sb.append("\n");
diff --git a/ojluni/src/main/java/java/util/stream/AbstractPipeline.java b/ojluni/src/main/java/java/util/stream/AbstractPipeline.java
index 9bdea9c..627bb32 100644
--- a/ojluni/src/main/java/java/util/stream/AbstractPipeline.java
+++ b/ojluni/src/main/java/java/util/stream/AbstractPipeline.java
@@ -68,8 +68,9 @@
  * @param <E_OUT> type of output elements
  * @param <S> type of the subclass implementing {@code BaseStream}
  * @since 1.8
- * @hide Visibility for CTS only (OpenJDK 8 streams tests).
+ * @hide Made public for CTS tests only (OpenJDK 8 streams tests).
  */
+// Android-changed: Made public for CTS tests only.
 public abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
         extends PipelineHelper<E_OUT> implements BaseStream<E_OUT, S> {
     private static final String MSG_STREAM_LINKED = "stream has already been operated upon or closed";
@@ -242,6 +243,7 @@
      * @return a flat array-backed Node that holds the collected output elements
      */
     @SuppressWarnings("unchecked")
+    // Android-changed: Made public for CTS tests only.
     public final Node<E_OUT> evaluateToArrayNode(IntFunction<E_OUT[]> generator) {
         if (linkedOrConsumed)
             throw new IllegalStateException(MSG_STREAM_LINKED);
@@ -380,6 +382,7 @@
      *         intermediate operations
      * @see StreamOpFlag
      */
+    // Android-changed: Made public for CTS tests only.
     public final int getStreamFlags() {
         return StreamOpFlag.toStreamFlags(combinedFlags);
     }
@@ -501,6 +504,7 @@
     }
 
     @Override
+    // Android-changed: Made public for CTS tests only.
     public final int getStreamAndOpFlags() {
         return combinedFlags;
     }
@@ -511,6 +515,7 @@
 
     @Override
     @SuppressWarnings("unchecked")
+    // Android-changed: Made public for CTS tests only.
     public final <P_IN> Sink<P_IN> wrapSink(Sink<E_OUT> sink) {
         Objects.requireNonNull(sink);
 
@@ -533,6 +538,7 @@
 
     @Override
     @SuppressWarnings("unchecked")
+    // Android-changed: Made public for CTS tests only.
     public final <P_IN> Node<E_OUT> evaluate(Spliterator<P_IN> spliterator,
                                       boolean flatten,
                                       IntFunction<E_OUT[]> generator) {
@@ -558,6 +564,7 @@
      *
      * @return the output shape
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract StreamShape getOutputShape();
 
     /**
@@ -570,6 +577,7 @@
      * @param generator the array generator
      * @return a Node holding the output of the pipeline
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract <P_IN> Node<E_OUT> evaluateToNode(PipelineHelper<E_OUT> helper,
                                                       Spliterator<P_IN> spliterator,
                                                       boolean flattenTree,
@@ -584,6 +592,7 @@
      * @param supplier the supplier of a spliterator
      * @return a wrapping spliterator compatible with this shape
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract <P_IN> Spliterator<E_OUT> wrap(PipelineHelper<E_OUT> ph,
                                                    Supplier<Spliterator<P_IN>> supplier,
                                                    boolean isParallel);
@@ -593,6 +602,7 @@
      * spliterator when a method is invoked on the lazy spliterator.
      * @param supplier the supplier of a spliterator
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract Spliterator<E_OUT> lazySpliterator(Supplier<? extends Spliterator<E_OUT>> supplier);
 
     /**
@@ -603,6 +613,7 @@
      * @param spliterator the spliterator to pull elements from
      * @param sink the sink to push elements to
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract void forEachWithCancel(Spliterator<E_OUT> spliterator, Sink<E_OUT> sink);
 
     /**
@@ -621,6 +632,7 @@
      * @return a node builder
      */
     @Override
+    // Android-changed: Made public for CTS tests only.
     public abstract Node.Builder<E_OUT> makeNodeBuilder(long exactSizeIfKnown,
                                                         IntFunction<E_OUT[]> generator);
 
@@ -635,6 +647,7 @@
      *
      * @return {@code true} if this operation is stateful
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract boolean opIsStateful();
 
     /**
@@ -656,6 +669,7 @@
      *         each element, and passes the results (if any) to the provided
      *         {@code Sink}.
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract Sink<E_IN> opWrapSink(int flags, Sink<E_OUT> sink);
 
     /**
@@ -673,6 +687,7 @@
      * @param generator the array generator
      * @return a {@code Node} describing the result of the evaluation
      */
+    // Android-changed: Made public for CTS tests only.
     public <P_IN> Node<E_OUT> opEvaluateParallel(PipelineHelper<E_OUT> helper,
                                           Spliterator<P_IN> spliterator,
                                           IntFunction<E_OUT[]> generator) {
@@ -700,6 +715,7 @@
      * @return a {@code Spliterator} describing the result of the evaluation
      */
     @SuppressWarnings("unchecked")
+    // Android-changed: Made public for CTS tests only.
     public <P_IN> Spliterator<E_OUT> opEvaluateParallelLazy(PipelineHelper<E_OUT> helper,
                                                      Spliterator<P_IN> spliterator) {
         return opEvaluateParallel(helper, spliterator, i -> (E_OUT[]) new Object[i]).spliterator();
diff --git a/ojluni/src/main/java/java/util/stream/BaseStream.java b/ojluni/src/main/java/java/util/stream/BaseStream.java
index b0be000..35d46e0 100644
--- a/ojluni/src/main/java/java/util/stream/BaseStream.java
+++ b/ojluni/src/main/java/java/util/stream/BaseStream.java
@@ -25,6 +25,8 @@
 package java.util.stream;
 
 import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Spliterator;
diff --git a/ojluni/src/main/java/java/util/stream/DistinctOps.java b/ojluni/src/main/java/java/util/stream/DistinctOps.java
index 0b7713e..22fbe05 100644
--- a/ojluni/src/main/java/java/util/stream/DistinctOps.java
+++ b/ojluni/src/main/java/java/util/stream/DistinctOps.java
@@ -65,6 +65,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public <P_IN> Node<T> opEvaluateParallel(PipelineHelper<T> helper,
                                               Spliterator<P_IN> spliterator,
                                               IntFunction<T[]> generator) {
@@ -100,6 +101,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public <P_IN> Spliterator<T> opEvaluateParallelLazy(PipelineHelper<T> helper, Spliterator<P_IN> spliterator) {
                 if (StreamOpFlag.DISTINCT.isKnown(helper.getStreamAndOpFlags())) {
                     // No-op
@@ -116,6 +118,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<T> opWrapSink(int flags, Sink<T> sink) {
                 Objects.requireNonNull(sink);
 
diff --git a/ojluni/src/main/java/java/util/stream/DoublePipeline.java b/ojluni/src/main/java/java/util/stream/DoublePipeline.java
index 25c19c6..e61e5de 100644
--- a/ojluni/src/main/java/java/util/stream/DoublePipeline.java
+++ b/ojluni/src/main/java/java/util/stream/DoublePipeline.java
@@ -52,6 +52,7 @@
  * @since 1.8
  * @hide Visible for CTS testing only (OpenJDK8 tests).
  */
+// Android-changed: Made public for CTS tests only.
 public abstract class DoublePipeline<E_IN>
         extends AbstractPipeline<E_IN, Double, DoubleStream>
         implements DoubleStream {
@@ -128,11 +129,13 @@
     // Shape-specific methods
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final StreamShape getOutputShape() {
         return StreamShape.DOUBLE_VALUE;
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final <P_IN> Node<Double> evaluateToNode(PipelineHelper<Double> helper,
                                              Spliterator<P_IN> spliterator,
                                              boolean flattenTree,
@@ -141,6 +144,7 @@
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final <P_IN> Spliterator<Double> wrap(PipelineHelper<Double> ph,
                                           Supplier<Spliterator<P_IN>> supplier,
                                           boolean isParallel) {
@@ -149,11 +153,13 @@
 
     @Override
     @SuppressWarnings("unchecked")
+    // Android-changed: Make public, to match the method it's overriding.
     public final Spliterator.OfDouble lazySpliterator(Supplier<? extends Spliterator<Double>> supplier) {
         return new StreamSpliterators.DelegatingSpliterator.OfDouble((Supplier<Spliterator.OfDouble>) supplier);
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final void forEachWithCancel(Spliterator<Double> spliterator, Sink<Double> sink) {
         Spliterator.OfDouble spl = adapt(spliterator);
         DoubleConsumer adaptedSink = adapt(sink);
@@ -161,6 +167,7 @@
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final Node.Builder<Double> makeNodeBuilder(long exactSizeIfKnown, IntFunction<Double[]> generator) {
         return Nodes.doubleBuilder(exactSizeIfKnown);
     }
@@ -191,6 +198,7 @@
         return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
                                        StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedDouble<Double>(sink) {
                     @Override
@@ -208,6 +216,7 @@
         return new ReferencePipeline.StatelessOp<Double, U>(this, StreamShape.DOUBLE_VALUE,
                                                             StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Double> opWrapSink(int flags, Sink<U> sink) {
                 return new Sink.ChainedDouble<U>(sink) {
                     @Override
@@ -225,6 +234,7 @@
         return new IntPipeline.StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
                                                    StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Double> opWrapSink(int flags, Sink<Integer> sink) {
                 return new Sink.ChainedDouble<Integer>(sink) {
                     @Override
@@ -242,6 +252,7 @@
         return new LongPipeline.StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
                                                     StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Double> opWrapSink(int flags, Sink<Long> sink) {
                 return new Sink.ChainedDouble<Long>(sink) {
                     @Override
@@ -258,6 +269,7 @@
         return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
                                         StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedDouble<Double>(sink) {
                     @Override
@@ -284,6 +296,7 @@
             return this;
         return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE, StreamOpFlag.NOT_ORDERED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
                 return sink;
             }
@@ -296,6 +309,7 @@
         return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
                                        StreamOpFlag.NOT_SIZED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedDouble<Double>(sink) {
                     @Override
@@ -319,6 +333,7 @@
         return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
                                        0) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedDouble<Double>(sink) {
                     @Override
@@ -514,8 +529,9 @@
      * Source stage of a DoubleStream
      *
      * @param <E_IN> type of elements in the upstream source
-     * @hide Visibility for CTS only (OpenJDK 8 streams tests).
+     * @hide Made public for CTS tests only (OpenJDK 8 streams tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public static class Head<E_IN> extends DoublePipeline<E_IN> {
         /**
          * Constructor for the source stage of a DoubleStream.
@@ -526,6 +542,7 @@
          *                    in {@link StreamOpFlag}
          * @param parallel {@code true} if the pipeline is parallel
          */
+        // Android-changed: Made public for CTS tests only.
         public Head(Supplier<? extends Spliterator<Double>> source,
              int sourceFlags, boolean parallel) {
             super(source, sourceFlags, parallel);
@@ -539,17 +556,20 @@
          *                    in {@link StreamOpFlag}
          * @param parallel {@code true} if the pipeline is parallel
          */
+        // Android-changed: Made public for CTS tests only.
         public Head(Spliterator<Double> source,
              int sourceFlags, boolean parallel) {
             super(source, sourceFlags, parallel);
         }
 
         @Override
+        // Android-changed: Made public for CTS tests only.
         public final boolean opIsStateful() {
             throw new UnsupportedOperationException();
         }
 
         @Override
+        // Android-changed: Made public for CTS tests only.
         public final Sink<E_IN> opWrapSink(int flags, Sink<Double> sink) {
             throw new UnsupportedOperationException();
         }
@@ -585,6 +605,7 @@
      * @since 1.8
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract static class StatelessOp<E_IN> extends DoublePipeline<E_IN> {
         /**
          * Construct a new DoubleStream by appending a stateless intermediate
@@ -594,6 +615,7 @@
          * @param inputShape the stream shape for the upstream pipeline stage
          * @param opFlags operation flags for the new stage
          */
+        // Android-changed: Made public for CTS tests only.
         public StatelessOp(AbstractPipeline<?, E_IN, ?> upstream,
                     StreamShape inputShape,
                     int opFlags) {
@@ -602,6 +624,7 @@
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             return false;
         }
@@ -614,6 +637,7 @@
      * @since 1.8
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract static class StatefulOp<E_IN> extends DoublePipeline<E_IN> {
         /**
          * Construct a new DoubleStream by appending a stateful intermediate
@@ -623,6 +647,7 @@
          * @param inputShape the stream shape for the upstream pipeline stage
          * @param opFlags operation flags for the new stage
          */
+        // Android-changed: Made public for CTS tests only.
         public StatefulOp(AbstractPipeline<?, E_IN, ?> upstream,
                    StreamShape inputShape,
                    int opFlags) {
@@ -631,11 +656,13 @@
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             return true;
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public abstract <P_IN> Node<Double> opEvaluateParallel(PipelineHelper<Double> helper,
                                                         Spliterator<P_IN> spliterator,
                                                         IntFunction<Double[]> generator);
diff --git a/ojluni/src/main/java/java/util/stream/DoubleStream.java b/ojluni/src/main/java/java/util/stream/DoubleStream.java
index 347587e..4d5d23d 100644
--- a/ojluni/src/main/java/java/util/stream/DoubleStream.java
+++ b/ojluni/src/main/java/java/util/stream/DoubleStream.java
@@ -25,6 +25,8 @@
 package java.util.stream;
 
 import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.DoubleSummaryStatistics;
diff --git a/ojluni/src/main/java/java/util/stream/IntPipeline.java b/ojluni/src/main/java/java/util/stream/IntPipeline.java
index 60ab3b3..11f0bb7 100644
--- a/ojluni/src/main/java/java/util/stream/IntPipeline.java
+++ b/ojluni/src/main/java/java/util/stream/IntPipeline.java
@@ -51,6 +51,7 @@
  * @since 1.8
  * @hide Visible for CTS testing only (OpenJDK8 tests).
  */
+// Android-changed: Made public for CTS tests only.
 public abstract class IntPipeline<E_IN>
         extends AbstractPipeline<E_IN, Integer, IntStream>
         implements IntStream {
@@ -131,11 +132,13 @@
     // Shape-specific methods
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final StreamShape getOutputShape() {
         return StreamShape.INT_VALUE;
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final <P_IN> Node<Integer> evaluateToNode(PipelineHelper<Integer> helper,
                                                      Spliterator<P_IN> spliterator,
                                                      boolean flattenTree,
@@ -144,6 +147,7 @@
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final <P_IN> Spliterator<Integer> wrap(PipelineHelper<Integer> ph,
                                                   Supplier<Spliterator<P_IN>> supplier,
                                                   boolean isParallel) {
@@ -152,11 +156,13 @@
 
     @Override
     @SuppressWarnings("unchecked")
+    // Android-changed: Make public, to match the method it's overriding.
     public final Spliterator.OfInt lazySpliterator(Supplier<? extends Spliterator<Integer>> supplier) {
         return new StreamSpliterators.DelegatingSpliterator.OfInt((Supplier<Spliterator.OfInt>) supplier);
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final void forEachWithCancel(Spliterator<Integer> spliterator, Sink<Integer> sink) {
         Spliterator.OfInt spl = adapt(spliterator);
         IntConsumer adaptedSink = adapt(sink);
@@ -164,6 +170,7 @@
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final Node.Builder<Integer> makeNodeBuilder(long exactSizeIfKnown,
                                                        IntFunction<Integer[]> generator) {
         return Nodes.intBuilder(exactSizeIfKnown);
@@ -205,6 +212,7 @@
         return new DoublePipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE,
                                                        StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Integer> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedInt<Double>(sink) {
                     @Override
@@ -227,6 +235,7 @@
         return new StatelessOp<Integer>(this, StreamShape.INT_VALUE,
                                         StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
                 return new Sink.ChainedInt<Integer>(sink) {
                     @Override
@@ -244,6 +253,7 @@
         return new ReferencePipeline.StatelessOp<Integer, U>(this, StreamShape.INT_VALUE,
                                                              StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Integer> opWrapSink(int flags, Sink<U> sink) {
                 return new Sink.ChainedInt<U>(sink) {
                     @Override
@@ -261,6 +271,7 @@
         return new LongPipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE,
                                                      StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Integer> opWrapSink(int flags, Sink<Long> sink) {
                 return new Sink.ChainedInt<Long>(sink) {
                     @Override
@@ -278,6 +289,7 @@
         return new DoublePipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE,
                                                        StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Integer> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedInt<Double>(sink) {
                     @Override
@@ -294,6 +306,7 @@
         return new StatelessOp<Integer>(this, StreamShape.INT_VALUE,
                                         StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
                 return new Sink.ChainedInt<Integer>(sink) {
                     @Override
@@ -320,6 +333,7 @@
             return this;
         return new StatelessOp<Integer>(this, StreamShape.INT_VALUE, StreamOpFlag.NOT_ORDERED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
                 return sink;
             }
@@ -332,6 +346,7 @@
         return new StatelessOp<Integer>(this, StreamShape.INT_VALUE,
                                         StreamOpFlag.NOT_SIZED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
                 return new Sink.ChainedInt<Integer>(sink) {
                     @Override
@@ -355,6 +370,7 @@
         return new StatelessOp<Integer>(this, StreamShape.INT_VALUE,
                                         0) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
                 return new Sink.ChainedInt<Integer>(sink) {
                     @Override
@@ -513,6 +529,7 @@
      * @since 1.8
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public static class Head<E_IN> extends IntPipeline<E_IN> {
         /**
          * Constructor for the source stage of an IntStream.
@@ -523,6 +540,7 @@
          *                    in {@link StreamOpFlag}
          * @param parallel {@code true} if the pipeline is parallel
          */
+        // Android-changed: Made public for CTS tests only.
         public Head(Supplier<? extends Spliterator<Integer>> source,
              int sourceFlags, boolean parallel) {
             super(source, sourceFlags, parallel);
@@ -536,17 +554,20 @@
          *                    in {@link StreamOpFlag}
          * @param parallel {@code true} if the pipeline is parallel
          */
+        // Android-changed: Made public for CTS tests only.
         public Head(Spliterator<Integer> source,
              int sourceFlags, boolean parallel) {
             super(source, sourceFlags, parallel);
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             throw new UnsupportedOperationException();
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final Sink<E_IN> opWrapSink(int flags, Sink<Integer> sink) {
             throw new UnsupportedOperationException();
         }
@@ -581,6 +602,7 @@
      * @since 1.8
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract static class StatelessOp<E_IN> extends IntPipeline<E_IN> {
         /**
          * Construct a new IntStream by appending a stateless intermediate
@@ -589,6 +611,7 @@
          * @param inputShape The stream shape for the upstream pipeline stage
          * @param opFlags Operation flags for the new stage
          */
+        // Android-changed: Made public for CTS tests only.
         public StatelessOp(AbstractPipeline<?, E_IN, ?> upstream,
                     StreamShape inputShape,
                     int opFlags) {
@@ -597,6 +620,7 @@
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             return false;
         }
@@ -609,6 +633,7 @@
      * @since 1.8
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract static class StatefulOp<E_IN> extends IntPipeline<E_IN> {
         /**
          * Construct a new IntStream by appending a stateful intermediate
@@ -617,6 +642,7 @@
          * @param inputShape The stream shape for the upstream pipeline stage
          * @param opFlags Operation flags for the new stage
          */
+        // Android-changed: Made public for CTS tests only.
         public StatefulOp(AbstractPipeline<?, E_IN, ?> upstream,
                    StreamShape inputShape,
                    int opFlags) {
@@ -625,11 +651,13 @@
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             return true;
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public abstract <P_IN> Node<Integer> opEvaluateParallel(PipelineHelper<Integer> helper,
                                                          Spliterator<P_IN> spliterator,
                                                          IntFunction<Integer[]> generator);
diff --git a/ojluni/src/main/java/java/util/stream/LongPipeline.java b/ojluni/src/main/java/java/util/stream/LongPipeline.java
index e7f6a5ad..768a378 100644
--- a/ojluni/src/main/java/java/util/stream/LongPipeline.java
+++ b/ojluni/src/main/java/java/util/stream/LongPipeline.java
@@ -52,6 +52,7 @@
  * @since 1.8
  * @hide Visible for CTS testing only (OpenJDK8 tests).
  */
+// Android-changed: Made public for CTS tests only.
 public abstract class LongPipeline<E_IN>
         extends AbstractPipeline<E_IN, Long, LongStream>
         implements LongStream {
@@ -129,11 +130,13 @@
     // Shape-specific methods
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final StreamShape getOutputShape() {
         return StreamShape.LONG_VALUE;
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final <P_IN> Node<Long> evaluateToNode(PipelineHelper<Long> helper,
                                            Spliterator<P_IN> spliterator,
                                            boolean flattenTree,
@@ -142,6 +145,7 @@
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final <P_IN> Spliterator<Long> wrap(PipelineHelper<Long> ph,
                                         Supplier<Spliterator<P_IN>> supplier,
                                         boolean isParallel) {
@@ -150,11 +154,13 @@
 
     @Override
     @SuppressWarnings("unchecked")
+    // Android-changed: Make public, to match the method it's overriding.
     public final Spliterator.OfLong lazySpliterator(Supplier<? extends Spliterator<Long>> supplier) {
         return new StreamSpliterators.DelegatingSpliterator.OfLong((Supplier<Spliterator.OfLong>) supplier);
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final void forEachWithCancel(Spliterator<Long> spliterator, Sink<Long> sink) {
         Spliterator.OfLong spl = adapt(spliterator);
         LongConsumer adaptedSink =  adapt(sink);
@@ -162,6 +168,7 @@
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final Node.Builder<Long> makeNodeBuilder(long exactSizeIfKnown, IntFunction<Long[]> generator) {
         return Nodes.longBuilder(exactSizeIfKnown);
     }
@@ -186,6 +193,7 @@
         return new DoublePipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE,
                                                     StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Long> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedLong<Double>(sink) {
                     @Override
@@ -208,6 +216,7 @@
         return new StatelessOp<Long>(this, StreamShape.LONG_VALUE,
                                      StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
                 return new Sink.ChainedLong<Long>(sink) {
                     @Override
@@ -225,6 +234,7 @@
         return new ReferencePipeline.StatelessOp<Long, U>(this, StreamShape.LONG_VALUE,
                                                           StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Long> opWrapSink(int flags, Sink<U> sink) {
                 return new Sink.ChainedLong<U>(sink) {
                     @Override
@@ -242,6 +252,7 @@
         return new IntPipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE,
                                                  StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Long> opWrapSink(int flags, Sink<Integer> sink) {
                 return new Sink.ChainedLong<Integer>(sink) {
                     @Override
@@ -259,6 +270,7 @@
         return new DoublePipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE,
                                                     StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Long> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedLong<Double>(sink) {
                     @Override
@@ -275,6 +287,7 @@
         return new StatelessOp<Long>(this, StreamShape.LONG_VALUE,
                                      StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
                 return new Sink.ChainedLong<Long>(sink) {
                     @Override
@@ -301,6 +314,7 @@
             return this;
         return new StatelessOp<Long>(this, StreamShape.LONG_VALUE, StreamOpFlag.NOT_ORDERED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
                 return sink;
             }
@@ -313,6 +327,7 @@
         return new StatelessOp<Long>(this, StreamShape.LONG_VALUE,
                                      StreamOpFlag.NOT_SIZED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
                 return new Sink.ChainedLong<Long>(sink) {
                     @Override
@@ -336,6 +351,7 @@
         return new StatelessOp<Long>(this, StreamShape.LONG_VALUE,
                                      0) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
                 return new Sink.ChainedLong<Long>(sink) {
                     @Override
@@ -494,8 +510,9 @@
      *
      * @param <E_IN> type of elements in the upstream source
      * @since 1.8
-     * @hide Visibility for CTS only (OpenJDK 8 streams tests).
+     * @hide Made public for CTS tests only (OpenJDK 8 streams tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public static class Head<E_IN> extends LongPipeline<E_IN> {
         /**
          * Constructor for the source stage of a LongStream.
@@ -506,6 +523,7 @@
          *                    in {@link StreamOpFlag}
          * @param parallel {@code true} if the pipeline is parallel
          */
+        // Android-changed: Made public for CTS tests only.
         public Head(Supplier<? extends Spliterator<Long>> source,
              int sourceFlags, boolean parallel) {
             super(source, sourceFlags, parallel);
@@ -519,17 +537,20 @@
          *                    in {@link StreamOpFlag}
          * @param parallel {@code true} if the pipeline is parallel
          */
+        // Android-changed: Made public for CTS tests only.
         public Head(Spliterator<Long> source,
              int sourceFlags, boolean parallel) {
             super(source, sourceFlags, parallel);
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             throw new UnsupportedOperationException();
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final Sink<E_IN> opWrapSink(int flags, Sink<Long> sink) {
             throw new UnsupportedOperationException();
         }
@@ -561,6 +582,7 @@
      * @since 1.8
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract static class StatelessOp<E_IN> extends LongPipeline<E_IN> {
         /**
          * Construct a new LongStream by appending a stateless intermediate
@@ -569,6 +591,7 @@
          * @param inputShape The stream shape for the upstream pipeline stage
          * @param opFlags Operation flags for the new stage
          */
+        // Android-changed: Made public for CTS tests only.
         public StatelessOp(AbstractPipeline<?, E_IN, ?> upstream,
                     StreamShape inputShape,
                     int opFlags) {
@@ -577,6 +600,7 @@
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             return false;
         }
@@ -589,6 +613,7 @@
      * @since 1.8
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract static class StatefulOp<E_IN> extends LongPipeline<E_IN> {
         /**
          * Construct a new LongStream by appending a stateful intermediate
@@ -598,6 +623,7 @@
          * @param opFlags Operation flags for the new stage
          * @hide Visible for CTS testing only (OpenJDK8 tests).
          */
+        // Android-changed: Made public for CTS tests only.
         public StatefulOp(AbstractPipeline<?, E_IN, ?> upstream,
                    StreamShape inputShape,
                    int opFlags) {
@@ -606,11 +632,13 @@
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             return true;
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public abstract <P_IN> Node<Long> opEvaluateParallel(PipelineHelper<Long> helper,
                                                       Spliterator<P_IN> spliterator,
                                                       IntFunction<Long[]> generator);
diff --git a/ojluni/src/main/java/java/util/stream/LongStream.java b/ojluni/src/main/java/java/util/stream/LongStream.java
index 84189ef..a2d429e 100644
--- a/ojluni/src/main/java/java/util/stream/LongStream.java
+++ b/ojluni/src/main/java/java/util/stream/LongStream.java
@@ -24,8 +24,9 @@
  */
 package java.util.stream;
 
-import java.math.BigInteger;
 import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.LongSummaryStatistics;
@@ -791,11 +792,7 @@
             // Split the range in two and concatenate
             // Note: if the range is [Long.MIN_VALUE, Long.MAX_VALUE) then
             // the lower range, [Long.MIN_VALUE, 0) will be further split in two
-            // Android-changed: no divideUnsigned support yet, use BigInteger instead.
-            long m = startInclusive +
-                BigInteger.valueOf(endExclusive).subtract(BigInteger.valueOf(startInclusive))
-                     .divide(BigInteger.valueOf(2)).longValue() + 1;
-
+            long m = startInclusive + Long.divideUnsigned(endExclusive - startInclusive, 2) + 1;
             return concat(range(startInclusive, m), range(m, endExclusive));
         } else {
             return StreamSupport.longStream(
@@ -829,11 +826,7 @@
             // Note: if the range is [Long.MIN_VALUE, Long.MAX_VALUE] then
             // the lower range, [Long.MIN_VALUE, 0), and upper range,
             // [0, Long.MAX_VALUE], will both be further split in two
-            // Android-changed: no divideUnsigned support yet, use BigInteger instead.
-            long m = startInclusive +
-                BigInteger.valueOf(endInclusive).subtract(BigInteger.valueOf(startInclusive))
-                     .divide(BigInteger.valueOf(2)).longValue() + 1;
-
+            long m = startInclusive + Long.divideUnsigned(endInclusive - startInclusive, 2) + 1;
             return concat(range(startInclusive, m), rangeClosed(m, endInclusive));
         } else {
             return StreamSupport.longStream(
diff --git a/ojluni/src/main/java/java/util/stream/Node.java b/ojluni/src/main/java/java/util/stream/Node.java
index 4a72ca4..e20de78 100644
--- a/ojluni/src/main/java/java/util/stream/Node.java
+++ b/ojluni/src/main/java/java/util/stream/Node.java
@@ -58,6 +58,7 @@
  * @since 1.8
  * @hide Visible for CTS testing only (OpenJDK8 tests).
  */
+// Android-changed: Made public for CTS tests only.
 public interface Node<T> {
 
     /**
diff --git a/ojluni/src/main/java/java/util/stream/PipelineHelper.java b/ojluni/src/main/java/java/util/stream/PipelineHelper.java
index 06a4f92..832d68a 100644
--- a/ojluni/src/main/java/java/util/stream/PipelineHelper.java
+++ b/ojluni/src/main/java/java/util/stream/PipelineHelper.java
@@ -53,6 +53,7 @@
  * @since 1.8
  * @hide Visible for CTS testing only (OpenJDK8 tests).
  */
+// Android-changed: Made public for CTS tests only.
 public abstract class PipelineHelper<P_OUT> {
 
     /**
@@ -70,6 +71,7 @@
      * @return the combined stream and operation flags
      * @see StreamOpFlag
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract int getStreamAndOpFlags();
 
     /**
@@ -151,6 +153,7 @@
      * @return a {@code Sink} that implements the pipeline stages and sends
      *         results to the provided {@code Sink}
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract<P_IN> Sink<P_IN> wrapSink(Sink<P_OUT> sink);
 
     /**
@@ -198,6 +201,7 @@
      * @param generator a factory function for array instances
      * @return the {@code Node} containing all output elements
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract<P_IN> Node<P_OUT> evaluate(Spliterator<P_IN> spliterator,
                                         boolean flatten,
                                         IntFunction<P_OUT[]> generator);
diff --git a/ojluni/src/main/java/java/util/stream/ReferencePipeline.java b/ojluni/src/main/java/java/util/stream/ReferencePipeline.java
index ddec43e..84ec8c5 100644
--- a/ojluni/src/main/java/java/util/stream/ReferencePipeline.java
+++ b/ojluni/src/main/java/java/util/stream/ReferencePipeline.java
@@ -55,6 +55,7 @@
  * @since 1.8
  * @hide Visible for CTS testing only (OpenJDK8 tests).
  */
+// Android-changed: Made public for CTS tests only.
 public abstract class ReferencePipeline<P_IN, P_OUT>
         extends AbstractPipeline<P_IN, P_OUT, Stream<P_OUT>>
         implements Stream<P_OUT>  {
@@ -98,11 +99,13 @@
     // Shape-specific methods
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final StreamShape getOutputShape() {
         return StreamShape.REFERENCE;
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final <P_IN> Node<P_OUT> evaluateToNode(PipelineHelper<P_OUT> helper,
                                         Spliterator<P_IN> spliterator,
                                         boolean flattenTree,
@@ -111,6 +114,7 @@
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final <P_IN> Spliterator<P_OUT> wrap(PipelineHelper<P_OUT> ph,
                                      Supplier<Spliterator<P_IN>> supplier,
                                      boolean isParallel) {
@@ -118,16 +122,19 @@
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final Spliterator<P_OUT> lazySpliterator(Supplier<? extends Spliterator<P_OUT>> supplier) {
         return new StreamSpliterators.DelegatingSpliterator<>(supplier);
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final void forEachWithCancel(Spliterator<P_OUT> spliterator, Sink<P_OUT> sink) {
         do { } while (!sink.cancellationRequested() && spliterator.tryAdvance(sink));
     }
 
     @Override
+    // Android-changed: Make public, to match the method it's overriding.
     public final Node.Builder<P_OUT> makeNodeBuilder(long exactSizeIfKnown, IntFunction<P_OUT[]> generator) {
         return Nodes.builder(exactSizeIfKnown, generator);
     }
@@ -151,6 +158,7 @@
             return this;
         return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE, StreamOpFlag.NOT_ORDERED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
                 return sink;
             }
@@ -163,6 +171,7 @@
         return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
                                      StreamOpFlag.NOT_SIZED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
                 return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
                     @Override
@@ -204,6 +213,7 @@
         return new IntPipeline.StatelessOp<P_OUT>(this, StreamShape.REFERENCE,
                                               StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<P_OUT> opWrapSink(int flags, Sink<Integer> sink) {
                 return new Sink.ChainedReference<P_OUT, Integer>(sink) {
                     @Override
@@ -221,6 +231,7 @@
         return new LongPipeline.StatelessOp<P_OUT>(this, StreamShape.REFERENCE,
                                       StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<P_OUT> opWrapSink(int flags, Sink<Long> sink) {
                 return new Sink.ChainedReference<P_OUT, Long>(sink) {
                     @Override
@@ -238,6 +249,7 @@
         return new DoublePipeline.StatelessOp<P_OUT>(this, StreamShape.REFERENCE,
                                         StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<P_OUT> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedReference<P_OUT, Double>(sink) {
                     @Override
@@ -283,6 +295,7 @@
         return new IntPipeline.StatelessOp<P_OUT>(this, StreamShape.REFERENCE,
                                               StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<P_OUT> opWrapSink(int flags, Sink<Integer> sink) {
                 return new Sink.ChainedReference<P_OUT, Integer>(sink) {
                     IntConsumer downstreamAsInt = downstream::accept;
@@ -311,6 +324,7 @@
         return new DoublePipeline.StatelessOp<P_OUT>(this, StreamShape.REFERENCE,
                                                      StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<P_OUT> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedReference<P_OUT, Double>(sink) {
                     DoubleConsumer downstreamAsDouble = downstream::accept;
@@ -339,6 +353,7 @@
         return new LongPipeline.StatelessOp<P_OUT>(this, StreamShape.REFERENCE,
                                                    StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<P_OUT> opWrapSink(int flags, Sink<Long> sink) {
                 return new Sink.ChainedReference<P_OUT, Long>(sink) {
                     LongConsumer downstreamAsLong = downstream::accept;
@@ -366,6 +381,7 @@
         return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
                                      0) {
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
                 return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
                     @Override
@@ -436,7 +452,7 @@
         // super type of U an ArrayStoreException will be thrown.
         @SuppressWarnings("rawtypes")
         IntFunction rawGenerator = (IntFunction) generator;
-        // TODO(b/29399275): Eclipse compiler requires explicit (Node<A[]>) cast below.
+        // Android-changed: Eclipse compiler requires explicit (Node<A[]>) cast (b/29399275).
         return (A[]) Nodes.flatten((Node<A[]>) evaluateToArrayNode(rawGenerator), rawGenerator)
                 .asArray(rawGenerator);
     }
@@ -539,6 +555,7 @@
      * @since 1.8
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public static class Head<E_IN, E_OUT> extends ReferencePipeline<E_IN, E_OUT> {
         /**
          * Constructor for the source stage of a Stream.
@@ -548,6 +565,7 @@
          * @param sourceFlags the source flags for the stream source, described
          *                    in {@link StreamOpFlag}
          */
+        // Android-changed: Made public for CTS tests only.
         public Head(Supplier<? extends Spliterator<?>> source,
              int sourceFlags, boolean parallel) {
             super(source, sourceFlags, parallel);
@@ -560,17 +578,20 @@
          * @param sourceFlags the source flags for the stream source, described
          *                    in {@link StreamOpFlag}
          */
+        // Android-changed: Made public for CTS tests only.
         public Head(Spliterator<?> source,
              int sourceFlags, boolean parallel) {
             super(source, sourceFlags, parallel);
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             throw new UnsupportedOperationException();
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final Sink<E_IN> opWrapSink(int flags, Sink<E_OUT> sink) {
             throw new UnsupportedOperationException();
         }
@@ -606,6 +627,7 @@
      * @since 1.8
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract static class StatelessOp<E_IN, E_OUT>
             extends ReferencePipeline<E_IN, E_OUT> {
         /**
@@ -616,6 +638,7 @@
          * @param inputShape The stream shape for the upstream pipeline stage
          * @param opFlags Operation flags for the new stage
          */
+        // Android-changed: Made public for CTS tests only.
         public StatelessOp(AbstractPipeline<?, E_IN, ?> upstream,
                     StreamShape inputShape,
                     int opFlags) {
@@ -624,6 +647,7 @@
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             return false;
         }
@@ -637,6 +661,7 @@
      * @since 1.8
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public abstract static class StatefulOp<E_IN, E_OUT>
             extends ReferencePipeline<E_IN, E_OUT> {
         /**
@@ -646,6 +671,7 @@
          * @param inputShape The stream shape for the upstream pipeline stage
          * @param opFlags Operation flags for the new stage
          */
+        // Android-changed: Made public for CTS tests only.
         public StatefulOp(AbstractPipeline<?, E_IN, ?> upstream,
                    StreamShape inputShape,
                    int opFlags) {
@@ -654,11 +680,13 @@
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public final boolean opIsStateful() {
             return true;
         }
 
         @Override
+        // Android-changed: Make public, to match the method it's overriding.
         public abstract <P_IN> Node<E_OUT> opEvaluateParallel(PipelineHelper<E_OUT> helper,
                                                        Spliterator<P_IN> spliterator,
                                                        IntFunction<E_OUT[]> generator);
diff --git a/ojluni/src/main/java/java/util/stream/Sink.java b/ojluni/src/main/java/java/util/stream/Sink.java
index 032fd45..2c5609c 100644
--- a/ojluni/src/main/java/java/util/stream/Sink.java
+++ b/ojluni/src/main/java/java/util/stream/Sink.java
@@ -115,6 +115,7 @@
  * @since 1.8
  * @hide Visible for CTS testing only (OpenJDK8 tests).
  */
+// Android-changed: Made public for CTS tests only.
 public interface Sink<T> extends Consumer<T> {
     /**
      * Resets the sink state to receive a fresh data set.  This must be called
diff --git a/ojluni/src/main/java/java/util/stream/SliceOps.java b/ojluni/src/main/java/java/util/stream/SliceOps.java
index 3042197..6a6f85e 100644
--- a/ojluni/src/main/java/java/util/stream/SliceOps.java
+++ b/ojluni/src/main/java/java/util/stream/SliceOps.java
@@ -130,6 +130,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public <P_IN> Spliterator<T> opEvaluateParallelLazy(PipelineHelper<T> helper, Spliterator<P_IN> spliterator) {
                 long size = helper.exactOutputSizeIfKnown(spliterator);
                 if (size > 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
@@ -157,6 +158,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public <P_IN> Node<T> opEvaluateParallel(PipelineHelper<T> helper,
                                               Spliterator<P_IN> spliterator,
                                               IntFunction<T[]> generator) {
@@ -186,6 +188,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<T> opWrapSink(int flags, Sink<T> sink) {
                 return new Sink.ChainedReference<T, T>(sink) {
                     long n = skip;
@@ -246,6 +249,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public <P_IN> Spliterator<Integer> opEvaluateParallelLazy(PipelineHelper<Integer> helper,
                                                                Spliterator<P_IN> spliterator) {
                 long size = helper.exactOutputSizeIfKnown(spliterator);
@@ -266,6 +270,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public <P_IN> Node<Integer> opEvaluateParallel(PipelineHelper<Integer> helper,
                                                     Spliterator<P_IN> spliterator,
                                                     IntFunction<Integer[]> generator) {
@@ -295,6 +300,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
                 return new Sink.ChainedInt<Integer>(sink) {
                     long n = skip;
@@ -355,6 +361,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public <P_IN> Spliterator<Long> opEvaluateParallelLazy(PipelineHelper<Long> helper,
                                                             Spliterator<P_IN> spliterator) {
                 long size = helper.exactOutputSizeIfKnown(spliterator);
@@ -375,6 +382,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public <P_IN> Node<Long> opEvaluateParallel(PipelineHelper<Long> helper,
                                                  Spliterator<P_IN> spliterator,
                                                  IntFunction<Long[]> generator) {
@@ -404,6 +412,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
                 return new Sink.ChainedLong<Long>(sink) {
                     long n = skip;
@@ -464,6 +473,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public <P_IN> Spliterator<Double> opEvaluateParallelLazy(PipelineHelper<Double> helper,
                                                               Spliterator<P_IN> spliterator) {
                 long size = helper.exactOutputSizeIfKnown(spliterator);
@@ -484,6 +494,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public <P_IN> Node<Double> opEvaluateParallel(PipelineHelper<Double> helper,
                                                    Spliterator<P_IN> spliterator,
                                                    IntFunction<Double[]> generator) {
@@ -513,6 +524,7 @@
             }
 
             @Override
+            // Android-changed: Make public, to match the method it's overriding.
             public Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedDouble<Double>(sink) {
                     long n = skip;
diff --git a/ojluni/src/main/java/java/util/stream/SpinedBuffer.java b/ojluni/src/main/java/java/util/stream/SpinedBuffer.java
index c91c4ff..d21518a 100644
--- a/ojluni/src/main/java/java/util/stream/SpinedBuffer.java
+++ b/ojluni/src/main/java/java/util/stream/SpinedBuffer.java
@@ -54,6 +54,7 @@
  * @since 1.8
  * @hide Visible for CTS testing only (OpenJDK8 tests).
  */
+// Android-changed: Made public for CTS tests only.
 public class SpinedBuffer<E>
         extends AbstractSpinedBuffer
         implements Consumer<E>, Iterable<E> {
@@ -94,6 +95,7 @@
      *         is negative
      */
     @SuppressWarnings("unchecked")
+    // Android-changed: Made public for CTS tests only.
     public SpinedBuffer(int initialCapacity) {
         super(initialCapacity);
         curChunk = (E[]) new Object[1 << initialChunkPower];
@@ -103,6 +105,7 @@
      * Constructs an empty list with an initial capacity of sixteen.
      */
     @SuppressWarnings("unchecked")
+    // Android-changed: Made public for CTS tests only.
     public SpinedBuffer() {
         super();
         curChunk = (E[]) new Object[1 << initialChunkPower];
@@ -415,9 +418,8 @@
      * @param <E> the wrapper type for this primitive type
      * @param <T_ARR> the array type for this primitive type
      * @param <T_CONS> the Consumer type for this primitive type
-     * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
-    public abstract static class OfPrimitive<E, T_ARR, T_CONS>
+    abstract static class OfPrimitive<E, T_ARR, T_CONS>
             extends AbstractSpinedBuffer implements Iterable<E> {
 
         /*
@@ -723,10 +725,13 @@
      * An ordered collection of {@code int} values.
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public static class OfInt extends SpinedBuffer.OfPrimitive<Integer, int[], IntConsumer>
             implements IntConsumer {
+        // Android-changed: Made public for CTS tests only.
         public OfInt() { }
 
+        // Android-changed: Made public for CTS tests only.
         public OfInt(int initialCapacity) {
             super(initialCapacity);
         }
@@ -837,10 +842,13 @@
      * An ordered collection of {@code long} values.
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public static class OfLong extends SpinedBuffer.OfPrimitive<Long, long[], LongConsumer>
             implements LongConsumer {
+        // Android-changed: Made public for CTS tests only.
         public OfLong() { }
 
+        // Android-changed: Made public for CTS tests only.
         public OfLong(int initialCapacity) {
             super(initialCapacity);
         }
@@ -952,11 +960,14 @@
      * An ordered collection of {@code double} values.
      * @hide Visible for CTS testing only (OpenJDK8 tests).
      */
+    // Android-changed: Made public for CTS tests only.
     public static class OfDouble
             extends SpinedBuffer.OfPrimitive<Double, double[], DoubleConsumer>
             implements DoubleConsumer {
+        // Android-changed: Made public for CTS tests only.
         public OfDouble() { }
 
+        // Android-changed: Made public for CTS tests only.
         public OfDouble(int initialCapacity) {
             super(initialCapacity);
         }
diff --git a/ojluni/src/main/java/java/util/stream/Stream.java b/ojluni/src/main/java/java/util/stream/Stream.java
index d4cb9ff..c35fc05 100644
--- a/ojluni/src/main/java/java/util/stream/Stream.java
+++ b/ojluni/src/main/java/java/util/stream/Stream.java
@@ -25,6 +25,8 @@
 package java.util.stream;
 
 import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Comparator;
@@ -126,7 +128,8 @@
  *
  * <p>Streams have a {@link #close()} method and implement {@link AutoCloseable},
  * but nearly all stream instances do not actually need to be closed after use.
- * Generally, only streams whose source is an IO channel will require closing.  Most streams
+ * Generally, only streams whose source is an IO channel (such as those returned
+ * by {@link Files#lines(Path, Charset)}) will require closing.  Most streams
  * are backed by collections, arrays, or generating functions, which require no
  * special resource management.  (If a stream does require closing, it can be
  * declared as a resource in a {@code try}-with-resources statement.)
diff --git a/ojluni/src/main/java/java/util/stream/StreamOpFlag.java b/ojluni/src/main/java/java/util/stream/StreamOpFlag.java
index 3477a33..83a3660 100644
--- a/ojluni/src/main/java/java/util/stream/StreamOpFlag.java
+++ b/ojluni/src/main/java/java/util/stream/StreamOpFlag.java
@@ -202,6 +202,7 @@
  * @since 1.8
  * @hide Visible for CTS testing only (OpenJDK8 tests).
  */
+// Android-changed: Made public for CTS tests only.
 public enum StreamOpFlag {
 
     /*
@@ -458,6 +459,7 @@
      *
      * @return the bitmap for setting this characteristic
      */
+    // Android-changed: Made public for CTS tests only.
     public int set() {
         return set;
     }
@@ -467,6 +469,7 @@
      *
      * @return the bitmap for clearing this characteristic
      */
+    // Android-changed: Made public for CTS tests only.
     public int clear() {
         return clear;
     }
@@ -476,6 +479,7 @@
      *
      * @return true if a stream-based flag, otherwise false.
      */
+    // Android-changed: Made public for CTS tests only.
     public boolean isStreamFlag() {
         return maskTable.get(Type.STREAM) > 0;
     }
@@ -488,6 +492,7 @@
      *        operation flags
      * @return true if this flag is known, otherwise false.
      */
+    // Android-changed: Made public for CTS tests only.
     public boolean isKnown(int flags) {
         return (flags & preserve) == set;
     }
@@ -499,6 +504,7 @@
      * @param flags the operation flags or combined stream and operations flags.
      * @return true if this flag is preserved, otherwise false.
      */
+    // Android-changed: Made public for CTS tests only.
     public boolean isCleared(int flags) {
         return (flags & preserve) == clear;
     }
@@ -509,6 +515,7 @@
      * @param flags the combined stream and operations flags.
      * @return true if this flag is preserved, otherwise false.
      */
+    // Android-changed: Made public for CTS tests only.
     public boolean isPreserved(int flags) {
         return (flags & preserve) == preserve;
     }
@@ -519,6 +526,7 @@
      * @param t the flag type.
      * @return true if this flag can be set for the flag type, otherwise false.
      */
+    // Android-changed: Made public for CTS tests only.
     public boolean canSet(Type t) {
         return (maskTable.get(t) & SET_BITS) > 0;
     }
@@ -526,26 +534,31 @@
     /**
      * The bit mask for spliterator characteristics
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int SPLITERATOR_CHARACTERISTICS_MASK = createMask(Type.SPLITERATOR);
 
     /**
      * The bit mask for source stream flags.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int STREAM_MASK = createMask(Type.STREAM);
 
     /**
      * The bit mask for intermediate operation flags.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int OP_MASK = createMask(Type.OP);
 
     /**
      * The bit mask for terminal operation flags.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int TERMINAL_OP_MASK = createMask(Type.TERMINAL_OP);
 
     /**
      * The bit mask for upstream terminal operation flags.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int UPSTREAM_TERMINAL_OP_MASK = createMask(Type.UPSTREAM_TERMINAL_OP);
 
     private static int createMask(Type t) {
@@ -583,51 +596,61 @@
      * The initial value to be combined with the stream flags of the first
      * stream in the pipeline.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int INITIAL_OPS_VALUE = FLAG_MASK_IS | FLAG_MASK_NOT;
 
     /**
      * The bit value to set or inject {@link #DISTINCT}.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int IS_DISTINCT = DISTINCT.set;
 
     /**
      * The bit value to clear {@link #DISTINCT}.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int NOT_DISTINCT = DISTINCT.clear;
 
     /**
      * The bit value to set or inject {@link #SORTED}.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int IS_SORTED = SORTED.set;
 
     /**
      * The bit value to clear {@link #SORTED}.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int NOT_SORTED = SORTED.clear;
 
     /**
      * The bit value to set or inject {@link #ORDERED}.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int IS_ORDERED = ORDERED.set;
 
     /**
      * The bit value to clear {@link #ORDERED}.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int NOT_ORDERED = ORDERED.clear;
 
     /**
      * The bit value to set {@link #SIZED}.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int IS_SIZED = SIZED.set;
 
     /**
      * The bit value to clear {@link #SIZED}.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int NOT_SIZED = SIZED.clear;
 
     /**
      * The bit value to inject {@link #SHORT_CIRCUIT}.
      */
+    // Android-changed: Made public for CTS tests only.
     public static final int IS_SHORT_CIRCUIT = SHORT_CIRCUIT.set;
 
     private static int getMask(int flags) {
@@ -684,6 +707,7 @@
      *        The value {#link INITIAL_OPS_VALUE} must be used as the seed value.
      * @return the updated combined stream and operation flags.
      */
+    // Android-changed: Made public for CTS tests only.
     public static int combineOpFlags(int newStreamOrOpFlags, int prevCombOpFlags) {
         // 0x01 or 0x10 nibbles are transformed to 0x11
         // 0x00 nibbles remain unchanged
@@ -701,6 +725,7 @@
      * @param combOpFlags the combined stream and operation flags.
      * @return the stream flags.
      */
+    // Android-changed: Made public for CTS tests only.
     public static int toStreamFlags(int combOpFlags) {
         // By flipping the nibbles 0x11 become 0x00 and 0x01 become 0x10
         // Shift left 1 to restore set flags and mask off anything other than the set flags
@@ -713,6 +738,7 @@
      * @param streamFlags the stream flags.
      * @return the spliterator characteristic bit set.
      */
+    // Android-changed: Made public for CTS tests only.
     public static int toCharacteristics(int streamFlags) {
         return streamFlags & SPLITERATOR_CHARACTERISTICS_MASK;
     }
@@ -730,6 +756,7 @@
      *        bit set.
      * @return the stream flags.
      */
+    // Android-changed: Made public for CTS tests only.
     public static int fromCharacteristics(Spliterator<?> spliterator) {
         int characteristics = spliterator.characteristics();
         if ((characteristics & Spliterator.SORTED) != 0 && spliterator.getComparator() != null) {
@@ -748,6 +775,7 @@
      * @param characteristics the spliterator characteristic bit set.
      * @return the stream flags.
      */
+    // Android-changed: Made public for CTS tests only.
     public static int fromCharacteristics(int characteristics) {
         return characteristics & SPLITERATOR_CHARACTERISTICS_MASK;
     }
diff --git a/ojluni/src/main/java/java/util/stream/StreamShape.java b/ojluni/src/main/java/java/util/stream/StreamShape.java
index 2c5f83b..5bcae4a 100644
--- a/ojluni/src/main/java/java/util/stream/StreamShape.java
+++ b/ojluni/src/main/java/java/util/stream/StreamShape.java
@@ -47,6 +47,7 @@
  * @since 1.8
  * @hide Visible for CTS testing only (OpenJDK8 tests).
  */
+// Android-changed: Made public for CTS tests only.
 public enum StreamShape {
     /**
      * The shape specialization corresponding to {@code Stream} and elements
diff --git a/ojluni/src/main/java/java/util/stream/package-info.java b/ojluni/src/main/java/java/util/stream/package-info.java
index 17b070a..016c86d 100644
--- a/ojluni/src/main/java/java/util/stream/package-info.java
+++ b/ojluni/src/main/java/java/util/stream/package-info.java
@@ -82,7 +82,13 @@
  *     {@link java.util.stream.Stream#of(Object[])},
  *     {@link java.util.stream.IntStream#range(int, int)}
  *     or {@link java.util.stream.Stream#iterate(Object, UnaryOperator)};</li>
- *     </li>
+ *     <li>The lines of a file can be obtained from {@link java.io.BufferedReader#lines()};</li>
+ *     <li>Streams of file paths can be obtained from methods in {@link java.nio.file.Files};</li>
+ *     <li>Streams of random numbers can be obtained from {@link java.util.Random#ints()};</li>
+ *     <li>Numerous other stream-bearing methods in the JDK, including
+ *     {@link java.util.BitSet#stream()},
+ *     {@link java.util.regex.Pattern#splitAsStream(java.lang.CharSequence)},
+ *     and {@link java.util.jar.JarFile#stream()}.</li>
  * </ul>
  *
  * <p>Additional stream sources can be provided by third-party libraries using
diff --git a/ojluni/src/main/java/javax/security/auth/login/package-info.java b/ojluni/src/main/java/javax/security/auth/login/package-info.java
index a0f7f68..301ac21 100644
--- a/ojluni/src/main/java/javax/security/auth/login/package-info.java
+++ b/ojluni/src/main/java/javax/security/auth/login/package-info.java
@@ -28,7 +28,7 @@
  * <h2>Package Specification</h2>
  *
  * <ul>
- *   <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/StandardNames.html">
+ *   <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html">
  *     <b>Java&trade;
  *     Cryptography Architecture Standard Algorithm Name
  *     Documentation</b></a></li>
diff --git a/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java
index d752d1a..ef4bda2 100644
--- a/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java
@@ -105,10 +105,11 @@
         this.parent = parent;
         this.path = path;
         this.nd = new FileDispatcherImpl(append);
-        // Android-added: CloseGuard support.
+        // BEGIN Android-added: CloseGuard support.
         if (fd != null && fd.valid()) {
             guard.open("close");
         }
+        // END Android-added: CloseGuard support.
     }
 
     // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel()
@@ -167,6 +168,7 @@
 
     }
 
+    // BEGIN Android-added: CloseGuard support.
     protected void finalize() throws Throwable {
         try {
             if (guard != null) {
@@ -177,6 +179,7 @@
             super.finalize();
         }
     }
+    // END Android-added: CloseGuard support.
 
     public int read(ByteBuffer dst) throws IOException {
         ensureOpen();
@@ -294,9 +297,13 @@
                 ti = threads.add();
                 if (!isOpen())
                     return 0;
+                // BEGIN Android-added: BlockGuard support.
+                // Note: position() itself doesn't seem to block, so this may be overzealous
+                // when position() is not followed by a read/write operation. http://b/77263638
                 if (append) {
                     BlockGuard.getThreadPolicy().onWriteToDisk();
                 }
+                // END Android-added: BlockGuard support.
                 do {
                     // in append-mode then position is advanced to end before writing
                     p = (append) ? nd.size(fd) : position0(fd, -1);
@@ -322,6 +329,9 @@
                 ti = threads.add();
                 if (!isOpen())
                     return null;
+                // Android-added: BlockGuard support.
+                // Note: position() itself doesn't seem to block, so this may be overzealous
+                // when position() is not followed by a read/write operation. http://b/77263638
                 BlockGuard.getThreadPolicy().onReadFromDisk();
                 do {
                     p  = position0(fd, newPosition);
@@ -367,6 +377,7 @@
             int rv = -1;
             long p = -1;
             int ti = -1;
+            long rp = -1;
             try {
                 begin();
                 ti = threads.add();
@@ -402,8 +413,8 @@
                 if (p > newSize)
                     p = newSize;
                 do {
-                    rv = (int)position0(fd, p);
-                } while ((rv == IOStatus.INTERRUPTED) && isOpen());
+                    rp = position0(fd, p);
+                } while ((rp == IOStatus.INTERRUPTED) && isOpen());
                 return this;
             } finally {
                 threads.remove(ti);
@@ -462,6 +473,7 @@
             ti = threads.add();
             if (!isOpen())
                 return -1;
+            // Android-added: BlockGuard support.
             BlockGuard.getThreadPolicy().onWriteToDisk();
             do {
                 n = transferTo0(fd, position, icount, targetFD);
@@ -936,26 +948,25 @@
                 return null;
 
             if (filesize < position + size) { // Extend file size
-                // BEGIN Android-changed
+                // BEGIN Android-changed: Unexplained, needs investigation. http://b/77513071
                 /*
                 if (!writable) {
                     throw new IOException("Channel not open for writing " +
                         "- cannot extend file to required size");
                 }
                 */
-                // END Android-changed
-                int rv = 0;
+                // END Android-changed: Unexplained, needs investigation. http://b/77513071
+                int rv;
                 do {
-                    // BEGIN Android-changed
-                    //int rv = nd.truncate(fd, position + size);
+                    // BEGIN Android-changed: Ignore failed truncation for non-regular files.
+                    // For character devices such as /dev/zero, it's expected that truncation
+                    // will fail. For all non-regular files, we thus ignore the failed truncation
+                    // and continue on.
+                    // rv = nd.truncate(fd, position + size);
                     try {
                         rv = nd.truncate(fd, position + size);
                     } catch (IOException r) {
                         try {
-                            // If we're dealing with non-regular files, for example,
-                            // character devices such as /dev/zero. In those
-                            // cases, we ignore the failed truncation and continue
-                            // on.
                             if (android.system.OsConstants.S_ISREG(Libcore.os.fstat(fd).st_mode)) {
                                 throw r;
                             }
@@ -964,7 +975,7 @@
                         }
                         break;
                     }
-                    // END Android-changed
+                    // END Android-changed: Ignore failed truncation for non-regular files.
                 } while ((rv == IOStatus.INTERRUPTED) && isOpen());
                 if (!isOpen())
                     return null;
@@ -973,6 +984,13 @@
                 addr = 0;
                 // a valid file descriptor is not required
                 FileDescriptor dummy = new FileDescriptor();
+                // Android-changed: Allocate a DirectByteBuffer directly.
+                /*
+                if ((!writable) || (imode == MAP_RO))
+                    return Util.newMappedByteBufferR(0, 0, dummy, null);
+                else
+                    return Util.newMappedByteBuffer(0, 0, dummy, null);
+                */
                 return new DirectByteBuffer(0, 0, dummy, null,
                         (!writable) || (imode == MAP_RO) /* readOnly */);
             }
@@ -981,8 +999,9 @@
             long mapPosition = position - pagePosition;
             long mapSize = size + pagePosition;
             try {
-                // If no exception was thrown from map0, the address is valid
+                // Android-added: BlockGuard support.
                 BlockGuard.getThreadPolicy().onReadFromDisk();
+                // If no exception was thrown from map0, the address is valid
                 addr = map0(imode, mapPosition, mapSize);
             } catch (OutOfMemoryError x) {
                 // An OutOfMemoryError may indicate that we've exhausted memory
@@ -1015,6 +1034,20 @@
             assert (addr % allocationGranularity == 0);
             int isize = (int)size;
             Unmapper um = new Unmapper(addr, mapSize, isize, mfd);
+            // Android-changed: Allocate a DirectByteBuffer directly.
+            /*
+            if ((!writable) || (imode == MAP_RO)) {
+                return Util.newMappedByteBufferR(isize,
+                                                 addr + pagePosition,
+                                                 mfd,
+                                                 um);
+            } else {
+                return Util.newMappedByteBuffer(isize,
+                                                addr + pagePosition,
+                                                mfd,
+                                                um);
+            }
+            */
             return new DirectByteBuffer(isize, addr + pagePosition, mfd, um,
                     (!writable) || (imode == MAP_RO));
         } finally {
@@ -1023,8 +1056,38 @@
         }
     }
 
+    // Android-removed: Unused method getMappedBufferPool().
+    /*
+    /**
+     * Invoked by sun.management.ManagementFactoryHelper to create the management
+     * interface for mapped buffers.
+     *
+    public static sun.misc.JavaNioAccess.BufferPool getMappedBufferPool() {
+        return new sun.misc.JavaNioAccess.BufferPool() {
+            @Override
+            public String getName() {
+                return "mapped";
+            }
+            @Override
+            public long getCount() {
+                return Unmapper.count;
+            }
+            @Override
+            public long getTotalCapacity() {
+                return Unmapper.totalCapacity;
+            }
+            @Override
+            public long getMemoryUsed() {
+                return Unmapper.totalSize;
+            }
+        };
+    }
+    */
+
     // -- Locks --
 
+
+
     // keeps track of locks on this file
     private volatile FileLockTable fileLockTable;
 
@@ -1245,6 +1308,8 @@
     private static native long initIDs();
 
     static {
+        // Android-removed: Move clinit code to JNI registration functions.
+        // IOUtil.load();
         allocationGranularity = initIDs();
     }
 
diff --git a/ojluni/src/main/java/sun/nio/ch/PollSelectorImpl.java b/ojluni/src/main/java/sun/nio/ch/PollSelectorImpl.java
index 17c9f03..1911c35 100644
--- a/ojluni/src/main/java/sun/nio/ch/PollSelectorImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/PollSelectorImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, 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
@@ -57,9 +57,23 @@
         long pipeFds = IOUtil.makePipe(false);
         fd0 = (int) (pipeFds >>> 32);
         fd1 = (int) pipeFds;
-        pollWrapper = new PollArrayWrapper(INIT_CAP);
-        pollWrapper.initInterrupt(fd0, fd1);
-        channelArray = new SelectionKeyImpl[INIT_CAP];
+        try {
+            pollWrapper = new PollArrayWrapper(INIT_CAP);
+            pollWrapper.initInterrupt(fd0, fd1);
+            channelArray = new SelectionKeyImpl[INIT_CAP];
+        } catch (Throwable t) {
+            try {
+                FileDispatcherImpl.closeIntFD(fd0);
+            } catch (IOException ioe0) {
+                t.addSuppressed(ioe0);
+            }
+            try {
+                FileDispatcherImpl.closeIntFD(fd1);
+            } catch (IOException ioe1) {
+                t.addSuppressed(ioe1);
+            }
+            throw t;
+        }
     }
 
     protected int doSelect(long timeout)
diff --git a/ojluni/src/main/java/sun/nio/ch/PollSelectorProvider.java b/ojluni/src/main/java/sun/nio/ch/PollSelectorProvider.java
index 9ea18c9..d4ce6a1 100644
--- a/ojluni/src/main/java/sun/nio/ch/PollSelectorProvider.java
+++ b/ojluni/src/main/java/sun/nio/ch/PollSelectorProvider.java
@@ -36,8 +36,9 @@
         return new PollSelectorImpl(this);
     }
 
-    // Android-changed: Android never has stdin/stdout connected to a socket.
-    // public Channel inheritedChannel() throws IOException {
-    //     return InheritedChannel.getChannel();
-    // }
+    public Channel inheritedChannel() throws IOException {
+        // Android-changed: Android never has stdin/stdout connected to a socket.
+        // return InheritedChannel.getChannel();
+        return null;
+    }
 }
diff --git a/ojluni/src/main/java/sun/nio/fs/UnixFileStore.java b/ojluni/src/main/java/sun/nio/fs/UnixFileStore.java
index 98fc9ab..0532e4d 100644
--- a/ojluni/src/main/java/sun/nio/fs/UnixFileStore.java
+++ b/ojluni/src/main/java/sun/nio/fs/UnixFileStore.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -186,7 +186,8 @@
             return false;
         UnixFileStore other = (UnixFileStore)ob;
         return (this.dev == other.dev) &&
-               Arrays.equals(this.entry.dir(), other.entry.dir());
+               Arrays.equals(this.entry.dir(), other.entry.dir()) &&
+               this.entry.name().equals(other.entry.name());
     }
 
     @Override
diff --git a/ojluni/src/main/java/sun/nio/fs/Util.java b/ojluni/src/main/java/sun/nio/fs/Util.java
index fdd6ccc..08a3025 100644
--- a/ojluni/src/main/java/sun/nio/fs/Util.java
+++ b/ojluni/src/main/java/sun/nio/fs/Util.java
@@ -38,6 +38,8 @@
 class Util {
     private Util() { }
 
+    // Android-changed: Hard-code UTF-8 for jnuEncoding rather than requiring a system property.
+    // The system property sun.jnu.encoding is not set on Android; we just hard-code "UTF-8" here.
     // private static final Charset jnuEncoding = Charset.forName(
     //    AccessController.doPrivileged(new GetPropertyAction("sun.jnu.encoding")));
     private static final Charset jnuEncoding = Charset.forName("UTF-8");
diff --git a/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java b/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java
index 5896f15..b4fdf70 100644
--- a/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java
+++ b/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java
@@ -26,7 +26,10 @@
 
 
 package sun.reflect.misc;
+
+import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
+import sun.reflect.Reflection;
 
 public final class ReflectUtil {
 
@@ -45,7 +48,61 @@
         return cls.newInstance();
     }
 
-    // Android-removed: Dead code: Unused method ensureMemberAccess()
+    /*
+     * Reflection.ensureMemberAccess is overly-restrictive
+     * due to a bug. We awkwardly work around it for now.
+     */
+    public static void ensureMemberAccess(Class<?> currentClass,
+                                          Class<?> memberClass,
+                                          Object target,
+                                          int modifiers)
+        throws IllegalAccessException
+    {
+        if (target == null && Modifier.isProtected(modifiers)) {
+            int mods = modifiers;
+            mods = mods & (~Modifier.PROTECTED);
+            mods = mods | Modifier.PUBLIC;
+
+            /*
+             * See if we fail because of class modifiers
+             */
+            Reflection.ensureMemberAccess(currentClass,
+                                          memberClass,
+                                          target,
+                                          mods);
+            try {
+                /*
+                 * We're still here so class access was ok.
+                 * Now try with default field access.
+                 */
+                mods = mods & (~Modifier.PUBLIC);
+                Reflection.ensureMemberAccess(currentClass,
+                                              memberClass,
+                                              target,
+                                              mods);
+                /*
+                 * We're still here so access is ok without
+                 * checking for protected.
+                 */
+                return;
+            } catch (IllegalAccessException e) {
+                /*
+                 * Access failed but we're 'protected' so
+                 * if the test below succeeds then we're ok.
+                 */
+                if (isSubclassOf(currentClass, memberClass)) {
+                    return;
+                } else {
+                    throw e;
+                }
+            }
+        } else {
+            Reflection.ensureMemberAccess(currentClass,
+                                          memberClass,
+                                          target,
+                                          modifiers);
+        }
+    }
 
     private static boolean isSubclassOf(Class<?> queryClass,
                                         Class<?> ofClass)
diff --git a/ojluni/src/main/native/Android.bp b/ojluni/src/main/native/Android.bp
index 71546ca..14dde81 100644
--- a/ojluni/src/main/native/Android.bp
+++ b/ojluni/src/main/native/Android.bp
@@ -1,10 +1,10 @@
 filegroup {
     name: "libopenjdk_native_srcs",
     srcs: [
-        "java_util_zip_ZipFile.c",
-        "java_util_zip_Inflater.c",
-        "java_util_zip_Deflater.c",
-        "java_util_zip_CRC32.c",
+        "ZipFile.c",
+        "Inflater.c",
+        "Deflater.c",
+        "CRC32.c",
         "Adler32.c",
         "zip_util.c",
         "jni_util.c",
diff --git a/ojluni/src/main/native/java_util_zip_CRC32.c b/ojluni/src/main/native/CRC32.c
similarity index 100%
rename from ojluni/src/main/native/java_util_zip_CRC32.c
rename to ojluni/src/main/native/CRC32.c
diff --git a/ojluni/src/main/native/java_util_zip_Deflater.c b/ojluni/src/main/native/Deflater.c
similarity index 100%
rename from ojluni/src/main/native/java_util_zip_Deflater.c
rename to ojluni/src/main/native/Deflater.c
diff --git a/ojluni/src/main/native/java_util_zip_Inflater.c b/ojluni/src/main/native/Inflater.c
similarity index 100%
rename from ojluni/src/main/native/java_util_zip_Inflater.c
rename to ojluni/src/main/native/Inflater.c
diff --git a/ojluni/src/main/native/String.c b/ojluni/src/main/native/String.c
deleted file mode 100644
index 011089d..0000000
--- a/ojluni/src/main/native/String.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 1997, 1998, 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.
- */
-
-#include "jvm.h"
-#include <nativehelper/JNIHelp.h>
-
-#define NATIVE_METHOD(className, functionName, signature) \
-{ #functionName, signature, (void*)(className ## _ ## functionName) }
-
-
-JNIEXPORT jobject JNICALL
-String_intern(JNIEnv *env, jobject this)
-{
-    return JVM_InternString(env, this);
-}
-static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(String, intern, "()Ljava/lang/String;"),
-};
-
-void register_java_lang_String(JNIEnv* env) {
-  jniRegisterNativeMethods(env, "java/lang/String", gMethods, NELEM(gMethods));
-}
diff --git a/ojluni/src/main/native/Thread.c b/ojluni/src/main/native/Thread.c
deleted file mode 100644
index 83b448f..0000000
--- a/ojluni/src/main/native/Thread.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 1994, 2003, 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.
- */
-
-/*-
- *      Stuff for dealing with threads.
- *      originally in threadruntime.c, Sun Sep 22 12:09:39 1991
- */
-
-#include "jni.h"
-#include "jvm.h"
-
-
-#define THD "Ljava/lang/Thread;"
-#define OBJ "Ljava/lang/Object;"
-#define STE "Ljava/lang/StackTraceElement;"
-#define STR "Ljava/lang/String;"
-#include <nativehelper/JNIHelp.h>
-
-#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))
-
-static JNINativeMethod methods[] = {
-    {"start0",           "(JZ)V",        (void *)&JVM_StartThread},
-    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
-    {"yield",            "()V",        (void *)&JVM_Yield},
-    {"sleep",            "(Ljava/lang/Object;J)V",       (void *)&JVM_Sleep},
-    {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},
-    {"interrupt0",       "()V",        (void *)&JVM_Interrupt},
-    {"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},
-    {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},
-    {"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},
-};
-
-#undef THD
-#undef OBJ
-#undef STE
-#undef STR
-
-void register_java_lang_Thread(JNIEnv* env) {
-  jclass cls = (*env)->FindClass(env, "java/lang/Thread");
-  (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
-}
diff --git a/ojluni/src/main/native/Throwable.c b/ojluni/src/main/native/Throwable.c
deleted file mode 100644
index 805c80a..0000000
--- a/ojluni/src/main/native/Throwable.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 1994, 2011, 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.
- */
-
-/*
- *      Implementation of class Throwable
- *
- *      former classruntime.c, Wed Jun 26 18:43:20 1991
- */
-
-#include <stdio.h>
-#include <signal.h>
-
-#include "jni.h"
-#include "jvm.h"
-
-#include <nativehelper/JNIHelp.h>
-
-#define NATIVE_METHOD(className, functionName, signature) \
-{ #functionName, signature, (void*)(className ## _ ## functionName) }
-
-/*
- * Fill in the current stack trace in this exception.  This is
- * usually called automatically when the exception is created but it
- * may also be called explicitly by the user.  This routine returns
- * `this' so you can write 'throw e.fillInStackTrace();'
- */
-JNIEXPORT jobject JNICALL
-Throwable_fillInStackTrace(JNIEnv *env, jobject throwable, int dummy)
-{
-    JVM_FillInStackTrace(env, throwable);
-    return throwable;
-}
-
-JNIEXPORT jint JNICALL
-Throwable_getStackTraceDepth(JNIEnv *env, jobject throwable)
-{
-    return JVM_GetStackTraceDepth(env, throwable);
-}
-
-JNIEXPORT jobject JNICALL
-Throwable_getStackTraceElement(JNIEnv *env,
-                                              jobject throwable, jint index)
-{
-    return JVM_GetStackTraceElement(env, throwable, index);
-}
-static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Throwable, fillInStackTrace, "(I)Ljava/lang/Throwable;"),
-  NATIVE_METHOD(Throwable, getStackTraceDepth, "()I"),
-  NATIVE_METHOD(Throwable, getStackTraceElement, "(I)Ljava/lang/StackTraceElement;"),
-};
-
-void register_java_lang_Throwable(JNIEnv* env) {
-  jniRegisterNativeMethods(env, "java/lang/Throwable", gMethods, NELEM(gMethods));
-}
diff --git a/ojluni/src/main/native/UNIXProcess_md.c b/ojluni/src/main/native/UNIXProcess_md.c
index f944c31..550a5c5 100644
--- a/ojluni/src/main/native/UNIXProcess_md.c
+++ b/ojluni/src/main/native/UNIXProcess_md.c
@@ -115,7 +115,9 @@
 
 /* By default, use vfork() on Linux. */
 #ifndef START_CHILD_USE_VFORK
-  #ifdef __linux__
+// Android-changed: disable vfork under AddressSanitizer.
+//  #ifdef __linux__
+  #if defined(__linux__) && !__has_feature(address_sanitizer)
     #define START_CHILD_USE_VFORK 1
   #else
     #define START_CHILD_USE_VFORK 0
@@ -526,6 +528,8 @@
  * misfeature, but compatibility wins over sanity.  The original support for
  * this was imported accidentally from execvp().
  */
+// Android-added: #if START_CHILD_USE_CLONE || START_CHILD_USE_VFORK
+#if START_CHILD_USE_CLONE || START_CHILD_USE_VFORK
 static void
 execve_as_traditional_shell_script(const char *file,
                                    const char *argv[],
@@ -544,6 +548,7 @@
     memmove(argv+1, argv+2, (end-argv) * sizeof (*end));
     argv[0] = argv0;
 }
+#endif
 
 /**
  * Like execve(2), except that in case of ENOEXEC, FILE is assumed to
diff --git a/ojluni/src/main/native/java_util_zip_ZipFile.c b/ojluni/src/main/native/ZipFile.c
similarity index 100%
rename from ojluni/src/main/native/java_util_zip_ZipFile.c
rename to ojluni/src/main/native/ZipFile.c
diff --git a/ojluni/src/main/native/java_props_md.c b/ojluni/src/main/native/java_props_md.c
deleted file mode 100644
index a9fe5ba..0000000
--- a/ojluni/src/main/native/java_props_md.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, 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.
- */
-
-#if defined(__linux__) || defined(_ALLBSD_SOURCE)
-#include <stdio.h>
-#include <ctype.h>
-#endif
-#include <pwd.h>
-#include <locale.h>
-#ifndef ARCHPROPNAME
-#error "The macro ARCHPROPNAME has not been defined"
-#endif
-#include <sys/utsname.h>        /* For os_name and os_version */
-#include <langinfo.h>           /* For nl_langinfo */
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <time.h>
-#include <errno.h>
-
-#ifdef MACOSX
-#endif
-
-#if defined(_ALLBSD_SOURCE)
-#if !defined(P_tmpdir)
-#include <paths.h>
-#define P_tmpdir _PATH_VARTMP
-#endif
-#endif
-
-#include "locale_str.h"
-
-#if !defined(_ALLBSD_SOURCE)
-#ifdef __linux__
-  #ifndef CODESET
-  #define CODESET _NL_CTYPE_CODESET_NAME
-  #endif
-#else
-#ifdef ALT_CODESET_KEY
-#define CODESET ALT_CODESET_KEY
-#endif
-#endif
-#endif /* !_ALLBSD_SOURCE */
-
-#ifdef JAVASE_EMBEDDED
-#include <dlfcn.h>
-#include <sys/stat.h>
-#endif
-
-/* Take an array of string pairs (map of key->value) and a string (key).
- * Examine each pair in the map to see if the first string (key) matches the
- * string.  If so, store the second string of the pair (value) in the value and
- * return 1.  Otherwise do nothing and return 0.  The end of the map is
- * indicated by an empty string at the start of a pair (key of "").
- */
-static int
-mapLookup(char* map[], const char* key, char** value) {
-    int i;
-    for (i = 0; strcmp(map[i], ""); i += 2){
-        if (!strcmp(key, map[i])){
-            *value = map[i + 1];
-            return 1;
-        }
-    }
-    return 0;
-}
-
-/* This function sets an environment variable using envstring.
- * The format of envstring is "name=value".
- * If the name has already existed, it will append value to the name.
- */
-static void
-setPathEnvironment(char *envstring)
-{
-    char name[20], *value, *current;
-
-    value = strchr(envstring, '='); /* locate name and value separator */
-
-    if (! value)
-        return; /* not a valid environment setting */
-
-    /* copy first part as environment name */
-    strncpy(name, envstring, value - envstring);
-    name[value-envstring] = '\0';
-
-    value++; /* set value point to value of the envstring */
-
-    current = getenv(name);
-    if (current) {
-        if (! strstr(current, value)) {
-            /* value is not found in current environment, append it */
-            char *temp = malloc(strlen(envstring) + strlen(current) + 2);
-        strcpy(temp, name);
-        strcat(temp, "=");
-        strcat(temp, current);
-        strcat(temp, ":");
-        strcat(temp, value);
-        putenv(temp);
-        }
-        /* else the value has already been set, do nothing */
-    }
-    else {
-        /* environment variable is not found */
-        putenv(envstring);
-    }
-}
-
-#ifndef P_tmpdir
-#define P_tmpdir "/var/tmp"
-#endif
-
-static int ParseLocale(int cat, char ** std_language, char ** std_script,
-                       char ** std_country, char ** std_variant, char ** std_encoding) {
-    char temp[64];
-    char *language = NULL, *country = NULL, *variant = NULL,
-         *encoding = NULL;
-    char *p, encoding_variant[64];
-    char *lc;
-
-    /* Query the locale set for the category */
-
-#ifdef MACOSX
-    lc = setupMacOSXLocale(cat); // malloc'd memory, need to free
-#else
-    lc = setlocale(cat, NULL);
-#endif
-
-#ifndef __linux__
-    if (lc == NULL) {
-        return 0;
-    }
-
-    if (cat == LC_CTYPE) {
-        /*
-         * Workaround for Solaris bug 4201684: Xlib doesn't like @euro
-         * locales. Since we don't depend on the libc @euro behavior,
-         * we just remove the qualifier.
-         * On Linux, the bug doesn't occur; on the other hand, @euro
-         * is needed there because it's a shortcut that also determines
-         * the encoding - without it, we wouldn't get ISO-8859-15.
-         * Therefore, this code section is Solaris-specific.
-         */
-        lc = strdup(lc);    /* keep a copy, setlocale trashes original. */
-        strcpy(temp, lc);
-        p = strstr(temp, "@euro");
-        if (p != NULL) {
-            *p = '\0';
-            setlocale(LC_ALL, temp);
-        }
-    }
-#else
-    if (lc == NULL || !strcmp(lc, "C") || !strcmp(lc, "POSIX")) {
-        lc = "en_US";
-    }
-#endif
-
-    /*
-     * locale string format in Solaris is
-     * <language name>_<country name>.<encoding name>@<variant name>
-     * <country name>, <encoding name>, and <variant name> are optional.
-     */
-
-    strcpy(temp, lc);
-#ifdef MACOSX
-    free(lc); // malloced memory
-#endif
-    /* Parse the language, country, encoding, and variant from the
-     * locale.  Any of the elements may be missing, but they must occur
-     * in the order language_country.encoding@variant, and must be
-     * preceded by their delimiter (except for language).
-     *
-     * If the locale name (without .encoding@variant, if any) matches
-     * any of the names in the locale_aliases list, map it to the
-     * corresponding full locale name.  Most of the entries in the
-     * locale_aliases list are locales that include a language name but
-     * no country name, and this facility is used to map each language
-     * to a default country if that's possible.  It's also used to map
-     * the Solaris locale aliases to their proper Java locale IDs.
-     */
-    if ((p = strchr(temp, '.')) != NULL) {
-        strcpy(encoding_variant, p); /* Copy the leading '.' */
-        *p = '\0';
-    } else if ((p = strchr(temp, '@')) != NULL) {
-        strcpy(encoding_variant, p); /* Copy the leading '@' */
-        *p = '\0';
-    } else {
-        *encoding_variant = '\0';
-    }
-
-    if (mapLookup(locale_aliases, temp, &p)) {
-        strcpy(temp, p);
-        // check the "encoding_variant" again, if any.
-        if ((p = strchr(temp, '.')) != NULL) {
-            strcpy(encoding_variant, p); /* Copy the leading '.' */
-            *p = '\0';
-        } else if ((p = strchr(temp, '@')) != NULL) {
-            strcpy(encoding_variant, p); /* Copy the leading '@' */
-            *p = '\0';
-        }
-    }
-
-    language = temp;
-    if ((country = strchr(temp, '_')) != NULL) {
-        *country++ = '\0';
-    }
-
-    p = encoding_variant;
-    if ((encoding = strchr(p, '.')) != NULL) {
-        p[encoding++ - p] = '\0';
-        p = encoding;
-    }
-    if ((variant = strchr(p, '@')) != NULL) {
-        p[variant++ - p] = '\0';
-    }
-
-    /* Normalize the language name */
-    if (std_language != NULL) {
-        *std_language = "en";
-        if (language != NULL && mapLookup(language_names, language, std_language) == 0) {
-            *std_language = malloc(strlen(language)+1);
-            strcpy(*std_language, language);
-        }
-    }
-
-    /* Normalize the country name */
-    if (std_country != NULL && country != NULL) {
-        if (mapLookup(country_names, country, std_country) == 0) {
-            *std_country = malloc(strlen(country)+1);
-            strcpy(*std_country, country);
-        }
-    }
-
-    /* Normalize the script and variant name.  Note that we only use
-     * variants listed in the mapping array; others are ignored.
-     */
-    if (variant != NULL) {
-        if (std_script != NULL) {
-            mapLookup(script_names, variant, std_script);
-        }
-
-        if (std_variant != NULL) {
-            mapLookup(variant_names, variant, std_variant);
-        }
-    }
-
-    /* Normalize the encoding name.  Note that we IGNORE the string
-     * 'encoding' extracted from the locale name above.  Instead, we use the
-     * more reliable method of calling nl_langinfo(CODESET).  This function
-     * returns an empty string if no encoding is set for the given locale
-     * (e.g., the C or POSIX locales); we use the default ISO 8859-1
-     * converter for such locales.
-     */
-    if (std_encoding != NULL) {
-        /* OK, not so reliable - nl_langinfo() gives wrong answers on
-         * Euro locales, in particular. */
-        if (strcmp(p, "ISO8859-15") == 0)
-            p = "ISO8859-15";
-        else
-            p = nl_langinfo(CODESET);
-
-        /* Convert the bare "646" used on Solaris to a proper IANA name */
-        if (strcmp(p, "646") == 0)
-            p = "ISO646-US";
-
-        /* return same result nl_langinfo would return for en_UK,
-         * in order to use optimizations. */
-        *std_encoding = (*p != '\0') ? p : "ISO8859-1";
-
-#ifdef __linux__
-        /*
-         * Remap the encoding string to a different value for japanese
-         * locales on linux so that customized converters are used instead
-         * of the default converter for "EUC-JP". The customized converters
-         * omit support for the JIS0212 encoding which is not supported by
-         * the variant of "EUC-JP" encoding used on linux
-         */
-        if (strcmp(p, "EUC-JP") == 0) {
-            *std_encoding = "EUC-JP-LINUX";
-        }
-#else
-        if (strcmp(p,"eucJP") == 0) {
-            /* For Solaris use customized vendor defined character
-             * customized EUC-JP converter
-             */
-            *std_encoding = "eucJP-open";
-        } else if (strcmp(p, "Big5") == 0 || strcmp(p, "BIG5") == 0) {
-            /*
-             * Remap the encoding string to Big5_Solaris which augments
-             * the default converter for Solaris Big5 locales to include
-             * seven additional ideographic characters beyond those included
-             * in the Java "Big5" converter.
-             */
-            *std_encoding = "Big5_Solaris";
-        } else if (strcmp(p, "Big5-HKSCS") == 0) {
-            /*
-             * Solaris uses HKSCS2001
-             */
-            *std_encoding = "Big5-HKSCS-2001";
-        }
-#endif
-    }
-
-    return 1;
-}
-
-#ifdef JAVASE_EMBEDDED
-/* Determine the default embedded toolkit based on whether lib/xawt/
- * exists in the JRE. This can still be overridden by -Dawt.toolkit=XXX
- */
-static char* getEmbeddedToolkit() {
-    Dl_info dlinfo;
-    char buf[MAXPATHLEN];
-    int32_t len;
-    char *p;
-    struct stat statbuf;
-
-    /* Get address of this library and the directory containing it. */
-    dladdr((void *)getEmbeddedToolkit, &dlinfo);
-    realpath((char *)dlinfo.dli_fname, buf);
-    len = strlen(buf);
-    p = strrchr(buf, '/');
-    /* Default AWT Toolkit on Linux and Solaris is XAWT. */
-    strncpy(p, "/xawt/", MAXPATHLEN-len-1);
-    /* Check if it exists */
-    if (stat(buf, &statbuf) == -1 && errno == ENOENT) {
-        /* No - this is a reduced-headless-jre so use special HToolkit */
-        return "sun.awt.HToolkit";
-    }
-    else {
-        /* Yes - this is a headful JRE so fallback to SE defaults */
-        return NULL;
-    }
-}
-#endif
-
-/* This function gets called very early, before VM_CALLS are setup.
- * Do not use any of the VM_CALLS entries!!!
- */
-java_props_t *
-GetJavaProperties(JNIEnv *env)
-{
-    static java_props_t sprops;
-    char *v; /* tmp var */
-
-    if (sprops.user_dir) {
-        return &sprops;
-    }
-
-    /* tmp dir */
-    sprops.tmp_dir = P_tmpdir;
-#ifdef MACOSX
-    /* darwin has a per-user temp dir */
-    static char tmp_path[PATH_MAX];
-    int pathSize = confstr(_CS_DARWIN_USER_TEMP_DIR, tmp_path, PATH_MAX);
-    if (pathSize > 0 && pathSize <= PATH_MAX) {
-        sprops.tmp_dir = tmp_path;
-    }
-#endif /* MACOSX */
-
-    /* Printing properties */
-#ifdef MACOSX
-    sprops.printerJob = "sun.lwawt.macosx.CPrinterJob";
-#else
-    sprops.printerJob = "sun.print.PSPrinterJob";
-#endif
-
-    /* patches/service packs installed */
-    sprops.patch_level = "unknown";
-
-    /* Java 2D properties */
-#ifdef MACOSX
-    PreferredToolkit prefToolkit = getPreferredToolkit();
-    switch (prefToolkit) {
-        case CToolkit:
-        case HToolkit:
-            sprops.graphics_env = "sun.awt.CGraphicsEnvironment";
-            break;
-        case XToolkit:
-#endif
-    sprops.graphics_env = "sun.awt.X11GraphicsEnvironment";
-#ifdef MACOSX
-            break;
-    }
-#endif
-    /* AWT properties */
-#ifdef JAVASE_EMBEDDED
-    sprops.awt_toolkit = getEmbeddedToolkit();
-    if (sprops.awt_toolkit == NULL) // default as below
-#endif
-#ifdef MACOSX
-        switch (prefToolkit) {
-            case CToolkit:
-                sprops.awt_toolkit = "sun.lwawt.macosx.LWCToolkit";
-                break;
-            case XToolkit:
-#endif
-    sprops.awt_toolkit = "sun.awt.X11.XToolkit";
-#ifdef MACOSX
-                break;
-            default:
-                sprops.awt_toolkit = "sun.awt.HToolkit";
-                break;
-        }
-#endif
-
-    /* This is used only for debugging of font problems. */
-    v = getenv("JAVA2D_FONTPATH");
-    sprops.font_dir = v ? v : NULL;
-
-#ifdef SI_ISALIST
-    /* supported instruction sets */
-    {
-        char list[258];
-        sysinfo(SI_ISALIST, list, sizeof(list));
-        sprops.cpu_isalist = strdup(list);
-    }
-#else
-    sprops.cpu_isalist = NULL;
-#endif
-
-    /* endianness of platform */
-    {
-        unsigned int endianTest = 0xff000000;
-        if (((char*)(&endianTest))[0] != 0)
-            sprops.cpu_endian = "big";
-        else
-            sprops.cpu_endian = "little";
-    }
-
-    /* os properties */
-    {
-#ifdef MACOSX
-        setOSNameAndVersion(&sprops);
-#else
-        struct utsname name;
-        uname(&name);
-        sprops.os_name = strdup(name.sysname);
-        sprops.os_version = strdup(name.release);
-#endif
-
-        sprops.os_arch = ARCHPROPNAME;
-
-        if (getenv("GNOME_DESKTOP_SESSION_ID") != NULL) {
-            sprops.desktop = "gnome";
-        }
-        else {
-            sprops.desktop = NULL;
-        }
-    }
-
-    /* Determine the language, country, variant, and encoding from the host,
-     * and store these in the user.language, user.country, user.variant and
-     * file.encoding system properties. */
-    setlocale(LC_ALL, "");
-    if (ParseLocale(LC_CTYPE,
-                    &(sprops.format_language),
-                    &(sprops.format_script),
-                    &(sprops.format_country),
-                    &(sprops.format_variant),
-                    &(sprops.encoding))) {
-        ParseLocale(LC_MESSAGES,
-                    &(sprops.language),
-                    &(sprops.script),
-                    &(sprops.country),
-                    &(sprops.variant),
-                    NULL);
-    } else {
-        sprops.language = "en";
-        sprops.encoding = "ISO8859-1";
-    }
-    sprops.display_language = sprops.language;
-    sprops.display_script = sprops.script;
-    sprops.display_country = sprops.country;
-    sprops.display_variant = sprops.variant;
-
-#ifdef MACOSX
-    sprops.sun_jnu_encoding = "UTF-8";
-#else
-    sprops.sun_jnu_encoding = sprops.encoding;
-#endif
-
-#ifdef _ALLBSD_SOURCE
-#if BYTE_ORDER == _LITTLE_ENDIAN
-     sprops.unicode_encoding = "UnicodeLittle";
- #else
-     sprops.unicode_encoding = "UnicodeBig";
- #endif
-#else /* !_ALLBSD_SOURCE */
-#ifdef __linux__
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-    sprops.unicode_encoding = "UnicodeLittle";
-#else
-    sprops.unicode_encoding = "UnicodeBig";
-#endif
-#else
-    sprops.unicode_encoding = "UnicodeBig";
-#endif
-#endif /* _ALLBSD_SOURCE */
-
-    /* user properties */
-    {
-        struct passwd *pwent = getpwuid(getuid());
-        sprops.user_name = pwent ? strdup(pwent->pw_name) : "?";
-        sprops.user_home = pwent ? strdup(pwent->pw_dir) : "?";
-    }
-
-    /* User TIMEZONE */
-    {
-        /*
-         * We defer setting up timezone until it's actually necessary.
-         * Refer to TimeZone.getDefault(). However, the system
-         * property is necessary to be able to be set by the command
-         * line interface -D. Here temporarily set a null string to
-         * timezone.
-         */
-        tzset();        /* for compatibility */
-        sprops.timezone = "";
-    }
-
-    /* Current directory */
-    {
-        char buf[MAXPATHLEN];
-        errno = 0;
-        if (getcwd(buf, sizeof(buf))  == NULL)
-            JNU_ThrowByName(env, "java/lang/Error",
-             "Properties init: Could not determine current working directory.");
-        else
-            sprops.user_dir = strdup(buf);
-    }
-
-    sprops.file_separator = "/";
-    sprops.path_separator = ":";
-    sprops.line_separator = "\n";
-
-#if !defined(_ALLBSD_SOURCE)
-    /* Append CDE message and resource search path to NLSPATH and
-     * XFILESEARCHPATH, in order to pick localized message for
-     * FileSelectionDialog window (Bug 4173641).
-     */
-    setPathEnvironment("NLSPATH=/usr/dt/lib/nls/msg/%L/%N.cat");
-    setPathEnvironment("XFILESEARCHPATH=/usr/dt/app-defaults/%L/Dt");
-#endif
-
-
-#ifdef MACOSX
-    setProxyProperties(&sprops);
-#endif
-
-    return &sprops;
-}
-
-jstring
-GetStringPlatform(JNIEnv *env, nchar* cstr)
-{
-    return JNU_NewStringPlatform(env, cstr);
-}
diff --git a/tools/upstream/src/main/java/libcore/CompareUpstreams.java b/tools/upstream/src/main/java/libcore/CompareUpstreams.java
index fa6bd4f..348ec62 100644
--- a/tools/upstream/src/main/java/libcore/CompareUpstreams.java
+++ b/tools/upstream/src/main/java/libcore/CompareUpstreams.java
@@ -16,7 +16,8 @@
 
 package libcore;
 
-import java.io.*;
+import java.io.IOException;
+import java.io.PrintStream;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -119,45 +120,6 @@
         return escapeTsv(String.join("\n", result));
     }
 
-    /**
-     * Computes the edit distance of two lists, i.e. the smallest number of list items to delete,
-     * insert or replace that would transform the content of one list into the other.
-     */
-    private <T> int editDistance(List<T> a, List<T> b) {
-        int numB = b.size();
-        int[] prevCost = new int[numB + 1];
-        for (int i = 0; i <= numB; i++) {
-            prevCost[i] = i;
-        }
-        int[] curCost = new int[numB + 1];
-        for (int endA = 1; endA <= a.size(); endA++) {
-            // For each valid index i, prevCost[i] is the edit distance between
-            // a.subList(0, endA-1) and b.sublist(0, i).
-            // We now calculate curCost[end_b] as the edit distance between
-            // a.subList(0, endA) and b.subList(0, endB)
-            curCost[0] = endA;
-            for (int endB = 1; endB <= numB; endB++) {
-                boolean endsMatch = a.get(endA - 1).equals(b.get(endB - 1));
-                curCost[endB] = min(
-                        curCost[endB - 1] + 1, // append item from b
-                        prevCost[endB] + 1, // append item from a
-                        prevCost[endB - 1] + (endsMatch ? 0 : 1)); // match or replace item
-            }
-            int[] tmp = curCost;
-            curCost = prevCost;
-            prevCost = tmp;
-        }
-        return prevCost[numB];
-    }
-
-    private static int min(int a, int b, int c) {
-        if (a < b) {
-            return a < c ? a : c;
-        } else {
-            return b < c ? b : c;
-        }
-    }
-
     private static String escapeTsv(String value) {
         if (value.contains("\t")) {
             throw new IllegalArgumentException(value); // tsv doesn't support escaping tabs
@@ -207,7 +169,7 @@
                     comparison = "missing";
                 } else {
                     List<String> linesA = Util.readLines(upstreamFile);
-                    int distance = editDistance(linesA, linesB);
+                    int distance = Util.editDistance(linesA, linesB);
                     if (distance == 0) {
                         comparison = "identical";
                     } else {
@@ -246,7 +208,7 @@
     }
 
     public void run() throws IOException {
-        List<Path> relPaths = standardRepositories.ojluni().loadRelPathsFromMakefile();
+        List<Path> relPaths = standardRepositories.ojluni().loadRelPathsFromBlueprint();
         run(System.out, relPaths);
     }
 
diff --git a/tools/upstream/src/main/java/libcore/CopyUpstreamFiles.java b/tools/upstream/src/main/java/libcore/CopyUpstreamFiles.java
index 007914f..6bd758e 100644
--- a/tools/upstream/src/main/java/libcore/CopyUpstreamFiles.java
+++ b/tools/upstream/src/main/java/libcore/CopyUpstreamFiles.java
@@ -20,7 +20,6 @@
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
@@ -36,7 +35,7 @@
     }
 
     public void run() throws IOException {
-        List<Path> relPaths = standardRepositories.ojluni().loadRelPathsFromMakefile();
+        List<Path> relPaths = standardRepositories.ojluni().loadRelPathsFromBlueprint();
         if (outputDir.toFile().exists()) {
             throw new IOException(outputDir + " already exists");
         } else {
diff --git a/tools/upstream/src/main/java/libcore/Lines.java b/tools/upstream/src/main/java/libcore/Lines.java
new file mode 100644
index 0000000..c60fd0b
--- /dev/null
+++ b/tools/upstream/src/main/java/libcore/Lines.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 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;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * A List of lines (eg. from a text file or a command's output).
+ */
+public class Lines extends AbstractList<String> implements RandomAccess {
+    public static Lines EMPTY = new Lines(Collections.emptyList());
+
+    private final List<String> delegate;
+    private volatile int hashCode = 0;
+
+    public Lines(Collection<String> collection) {
+        this.delegate = new ArrayList<>(collection);
+    }
+
+    @Override
+    public int hashCode() {
+        if (hashCode == 0) {
+            hashCode = super.hashCode();
+        }
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o.hashCode() != this.hashCode()) {
+            return false;
+        }
+        return super.equals(o);
+    }
+
+    @Override
+    public Iterator<String> iterator() {
+        return Collections.unmodifiableList(delegate).iterator();
+    }
+
+    @Override
+    public String get(int index) {
+        return delegate.get(index);
+    }
+
+    @Override
+    public int size() {
+        return delegate.size();
+    }
+}
diff --git a/tools/upstream/src/main/java/libcore/Repository.java b/tools/upstream/src/main/java/libcore/Repository.java
index 9a4eee6..ed92a24 100644
--- a/tools/upstream/src/main/java/libcore/Repository.java
+++ b/tools/upstream/src/main/java/libcore/Repository.java
@@ -23,8 +23,11 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -33,12 +36,22 @@
  */
 abstract class Repository {
 
+    /**
+     * Maps from a file's (current) relPath to the corresponding OpenJDK relPath from
+     * which it has been, and still remains, renamed.
+     */
+    static final Map<Path, Path> OPENJDK_REL_PATH = Collections.singletonMap(
+        // renamed in libcore commit 583eb0e4738456f0547014a4857a14456be267ee
+        Paths.get("native/linux_close.cpp"), Paths.get("native/linux_close.c"));
+
     protected final Path rootPath;
     protected final String name;
+    protected final List<String> sourceDirs;
 
-    protected Repository(Path rootPath, String name) {
+    protected Repository(Path rootPath, String name, List<String> sourceDirs) {
         this.rootPath = Objects.requireNonNull(rootPath);
         this.name = Objects.requireNonNull(name);
+        this.sourceDirs = Objects.requireNonNull(sourceDirs);
         if (!rootPath.toFile().isDirectory()) {
             throw new IllegalArgumentException("Missing or not a directory: " + rootPath);
         }
@@ -55,7 +68,21 @@
         return p == null ? null : rootPath.resolve(p).toAbsolutePath();
     }
 
-    public abstract Path pathFromRepository(Path relPath);
+    public Path pathFromRepository(Path relPath) {
+        // Search across all sourceDirs for the indicated file.
+        for (String sourceDir : sourceDirs) {
+            Path repositoryRelativePath = Paths.get(sourceDir).resolve(relPath);
+            File file = rootPath.resolve(repositoryRelativePath).toFile();
+            if (file.exists()) {
+                return repositoryRelativePath;
+            }
+        }
+        return null;
+    }
+
+    public final Path rootPath() {
+        return rootPath;
+    }
 
     /**
      * @return A human readable name to identify this repository, suitable for use as a
@@ -76,18 +103,22 @@
      */
     public static Repository openJdk9(Path upstreamRoot, String upstreamName) {
         List<String> sourceDirs = Arrays.asList(
-                "jdk/src/java.base/share/classes",
-                "jdk/src/java.logging/share/classes",
-                "jdk/src/java.prefs/share/classes",
-                "jdk/src/java.sql/share/classes",
-                "jdk/src/java.desktop/share/classes",
-                "jdk/src/java.base/solaris/classes",
-                "jdk/src/java.base/unix/classes",
-                "jdk/src/java.prefs/unix/classes",
-                "jdk/src/jdk.unsupported/share/classes",
-                "jdk/src/jdk.net/share/classes",
-                "jdk/src/java.base/linux/classes",
-                "build/linux-x86_64-normal-server-release/support/gensrc/java.base"
+            "jdk/src/java.base/share/classes",
+            "jdk/src/java.logging/share/classes",
+            "jdk/src/java.prefs/share/classes",
+            "jdk/src/java.sql/share/classes",
+            "jdk/src/java.desktop/share/classes",
+            "jdk/src/java.base/solaris/classes",
+            "jdk/src/java.base/unix/classes",
+            "jdk/src/java.prefs/unix/classes",
+            "jdk/src/jdk.unsupported/share/classes",
+            "jdk/src/jdk.net/share/classes",
+            "jdk/src/java.base/linux/classes",
+            "build/linux-x86_64-normal-server-release/support/gensrc/java.base",
+
+            // Native (.c) files
+            "jdk/src/java.base/unix/native/libjava",
+            "jdk/src/java.base/share/native/libjava"
         );
         return new OpenJdkRepository(upstreamRoot, upstreamName, sourceDirs);
     }
@@ -97,11 +128,27 @@
      * subdirectory {@code upstreamName} under the directory {@code upstreamRoot}.
      */
     public static Repository openJdkLegacy(Path upstreamRoot, String upstreamName) {
-        List<String> sourceDirs = Arrays.asList(
-                "jdk/src/share/classes",
-                "jdk/src/solaris/classes",
-                "build/linux-x86_64-normal-server-release/jdk/gensrc"
-                );
+        List<String> sourceDirs = new ArrayList<>();
+        sourceDirs.addAll(Arrays.asList(
+            "jdk/src/share/classes",
+            "jdk/src/solaris/classes",
+            "build/linux-x86_64-normal-server-release/jdk/gensrc"
+        ));
+
+        // In legacy OpenJDK versions, the source files are organized into a subfolder
+        // hierarchy based on package name, whereas in Android and OpenJDK 9+ they're in
+        // a flat folder. We work around this by just searching through all of the
+        // applicable folders (from which we have sources) in legacy OpenJDK versions.
+        List<String> nativeSourceDirs = new ArrayList<>();
+        List<String> pkgPaths = Arrays.asList("", "java/io", "java/lang", "java/net", "java/nio",
+            "java/util", "java/util/zip", "sun/nio/ch", "sun/nio/fs");
+        for (String pkgPath : pkgPaths) {
+            nativeSourceDirs.add("jdk/src/solaris/native/" + pkgPath);
+            nativeSourceDirs.add("jdk/src/share/native/" + pkgPath);
+            nativeSourceDirs.add("jdk/src/solaris/native/common/" + pkgPath);
+            nativeSourceDirs.add("jdk/src/share/native/common/" + pkgPath);
+        }
+        sourceDirs.addAll(nativeSourceDirs);
 
         return new OpenJdkRepository(upstreamRoot, upstreamName, sourceDirs);
     }
@@ -120,7 +167,6 @@
     }
 
     static class OjluniRepository extends Repository {
-
         /**
          * The repository of ojluni java files belonging to the Android sources under
          * {@code buildTop}.
@@ -129,29 +175,42 @@
          *        {@quote ANDROID_BUILD_TOP} environment variable.
          */
         public OjluniRepository(Path buildTop) {
-            super(buildTop.resolve("libcore"), "ojluni");
+            super(buildTop.resolve("libcore"), "ojluni",
+                /* sourceDirs */ Arrays.asList("ojluni/src/main/java", "ojluni/src/main/native"));
         }
 
 
         @Override
         public Path pathFromRepository(Path relPath) {
-            return Paths.get("ojluni/src/main/java").resolve(relPath);
+            // Enforce that the file exists in ojluni
+            return Objects.requireNonNull(super.pathFromRepository(relPath));
         }
 
         /**
-         * Returns the list of relative paths to .java files parsed from openjdk_java_files.mk
+         * Returns the list of relative paths to files parsed from blueprint files.
          */
-        public List<Path> loadRelPathsFromMakefile() throws IOException {
+        public List<Path> loadRelPathsFromBlueprint() throws IOException {
             List<Path> result = new ArrayList<>();
-            Path makefile = rootPath.resolve("openjdk_java_files.bp");
-            Pattern pattern = Pattern.compile("\"ojluni/src/main/java/(.+\\.java)\"");
-            for (String line : Util.readLines(makefile)) {
+            result.addAll(loadRelPathsFromBlueprint(
+                "openjdk_java_files.bp", "\"ojluni/src/main/java/(.+\\.java)\""));
+            result.addAll(loadRelPathsFromBlueprint(
+                "ojluni/src/main/native/Android.bp", "\\s+\"(.+\\.(?:c|cpp))\","));
+            return result;
+        }
+
+        private List<Path> loadRelPathsFromBlueprint(
+            String blueprintPathString, String patternString) throws IOException {
+            Path blueprintPath = rootPath.resolve(blueprintPathString);
+            Pattern pattern = Pattern.compile(patternString);
+            List<Path> result = new ArrayList<>();
+            for (String line : Util.readLines(blueprintPath)) {
                 Matcher matcher = pattern.matcher(line);
                 while (matcher.find()) {
-                    Path path = new File(matcher.group(1)).toPath();
-                    result.add(path);
+                    Path relPath = Paths.get(matcher.group(1));
+                    result.add(relPath);
                 }
             }
+            Collections.sort(result);
             return result;
         }
 
@@ -162,23 +221,17 @@
     }
 
     static class OpenJdkRepository extends Repository {
-        private final List<String> sourceDirs;
 
         public OpenJdkRepository(Path upstreamRoot, String name, List<String> sourceDirs) {
-            super(upstreamRoot.resolve(name), name);
-            this.sourceDirs = Objects.requireNonNull(sourceDirs);
+            super(upstreamRoot.resolve(name), name, sourceDirs);
         }
 
         @Override
         public Path pathFromRepository(Path relPath) {
-            for (String sourceDir : sourceDirs) {
-                Path repositoryRelativePath = Paths.get(sourceDir).resolve(relPath);
-                Path file = rootPath.resolve(repositoryRelativePath);
-                if (file.toFile().exists()) {
-                    return repositoryRelativePath;
-                }
+            if (OPENJDK_REL_PATH.containsKey(relPath)) {
+                relPath = OPENJDK_REL_PATH.get(relPath);
             }
-            return null;
+            return super.pathFromRepository(relPath);
         }
 
         @Override
@@ -187,5 +240,4 @@
         }
     }
 
-
 }
diff --git a/tools/upstream/src/main/java/libcore/StandardRepositories.java b/tools/upstream/src/main/java/libcore/StandardRepositories.java
index 36478dd..a79e905 100644
--- a/tools/upstream/src/main/java/libcore/StandardRepositories.java
+++ b/tools/upstream/src/main/java/libcore/StandardRepositories.java
@@ -34,12 +34,14 @@
     private final List<Repository> historicUpstreams;
     private final Repository defaultUpstream;
     private final Repository jsr166Upstream;
+    private final Repository javaSqlUpstream;
     private final OjluniRepository ojluni;
 
     private StandardRepositories(Path buildTop, Path upstreamRoot) {
         this.historicUpstreams = openJdkLegacy(upstreamRoot, Arrays.asList("8u60", "7u40"));
         this.defaultUpstream = openJdkLegacy(upstreamRoot, "8u121-b13");
         this.jsr166Upstream = openJdk9(upstreamRoot, "9b113+");
+        this.javaSqlUpstream = openJdkLegacy(upstreamRoot, "7u40");
         this.ojluni = new OjluniRepository(buildTop);
     }
 
@@ -89,18 +91,29 @@
                     "SplittableRandom"
             )));
 
-    public Repository currentUpstream(Path relPath) {
-        boolean isJsr166 = relPath.toString().startsWith("java/util/concurrent");
+    public boolean isJsr166(Path relPath) {
+        boolean result = relPath.startsWith("java/util/concurrent/");
         String ju = "java/util/";
         String suffix = ".java";
-        if (!isJsr166 && relPath.startsWith(ju)) {
+        if (!result && relPath.startsWith(ju)) {
             String name = relPath.toString().substring(ju.length());
             if (name.endsWith(suffix)) {
                 name = name.substring(0, name.length() - suffix.length());
-                isJsr166 = juFilesFromJsr166.contains(name);
+                result = juFilesFromJsr166.contains(name);
             }
         }
-        return isJsr166 ? jsr166Upstream : defaultUpstream;
+        return result;
+    }
+
+    public Repository currentUpstream(Path relPath) {
+        boolean isJsr166 = isJsr166(relPath);
+        if (isJsr166) {
+            return jsr166Upstream;
+        } else if (relPath.startsWith("java/sql/") || relPath.startsWith("javax/sql/")) {
+            return javaSqlUpstream;
+        } else {
+            return defaultUpstream;
+        }
     }
 
 }
diff --git a/tools/upstream/src/main/java/libcore/Util.java b/tools/upstream/src/main/java/libcore/Util.java
index d213080..c50e990 100644
--- a/tools/upstream/src/main/java/libcore/Util.java
+++ b/tools/upstream/src/main/java/libcore/Util.java
@@ -17,25 +17,90 @@
 package libcore;
 
 import java.io.BufferedReader;
+import java.io.BufferedWriter;
 import java.io.FileReader;
+import java.io.FileWriter;
 import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * Utilities for dealing with text file contents.
+ */
 class Util {
     private Util() {
     }
 
-    public static List<String> readLines(Path path) throws IOException {
+    public static Lines readLines(Reader reader) throws IOException {
         List<String> result = new ArrayList<>();
-        try (BufferedReader reader = new BufferedReader(new FileReader(path.toFile()))) {
-            String line;
-            while ((line = reader.readLine()) != null) {
-                result.add(line);
+        BufferedReader br = (reader instanceof BufferedReader)
+                ? (BufferedReader) reader : new BufferedReader(reader);
+        String line;
+        while ((line = br.readLine()) != null) {
+            result.add(line);
+        }
+        return new Lines(result);
+    }
+
+    public static Lines readLines(Path path) throws IOException {
+        try (Reader reader = new FileReader(path.toFile())) {
+            return readLines(reader);
+        }
+    }
+
+    public static void writeLines(Path path, Lines lines) throws IOException {
+        try (PrintStream printStream = new PrintStream(path.toFile())) {
+            for (String line : lines) {
+                printStream.println(line);
             }
         }
-        return result;
+    }
+
+    /**
+     * Computes the edit distance of two lists, i.e. the smallest number of list items to delete,
+     * insert or replace that would transform the content of one list into the other.
+     */
+    public static <T> int editDistance(List<T> a, List<T> b) {
+        if (a.equals(b)) {
+            return 0;
+        }
+        int numB = b.size();
+        int[] prevCost = new int[numB + 1];
+        for (int i = 0; i <= numB; i++) {
+            prevCost[i] = i;
+        }
+        int[] curCost = new int[numB + 1];
+        for (int endA = 1; endA <= a.size(); endA++) {
+            // For each valid index i, prevCost[i] is the edit distance between
+            // a.subList(0, endA-1) and b.sublist(0, i).
+            // We now calculate curCost[end_b] as the edit distance between
+            // a.subList(0, endA) and b.subList(0, endB)
+            curCost[0] = endA;
+            for (int endB = 1; endB <= numB; endB++) {
+                boolean endsMatch = a.get(endA - 1).equals(b.get(endB - 1));
+                curCost[endB] = min(
+                        curCost[endB - 1] + 1, // append item from b
+                        prevCost[endB] + 1, // append item from a
+                        prevCost[endB - 1] + (endsMatch ? 0 : 1)); // match or replace item
+            }
+            int[] tmp = curCost;
+            curCost = prevCost;
+            prevCost = tmp;
+        }
+        return prevCost[numB];
+    }
+
+    private static int min(int a, int b, int c) {
+        if (a < b) {
+            return a < c ? a : c;
+        } else {
+            return b < c ? b : c;
+        }
     }
 
 }
diff --git a/tools/upstream/upstream-diff b/tools/upstream/upstream-diff
index 359ffee..b689b33 100755
--- a/tools/upstream/upstream-diff
+++ b/tools/upstream/upstream-diff
@@ -52,6 +52,7 @@
 import argparse
 import os
 import os.path
+import re
 import subprocess
 import sys
 
@@ -61,13 +62,17 @@
     # Root of repository snapshots. See go/libcore-o-verify for how you'd want to set this.
     ojluni_upstreams = os.environ['OJLUNI_UPSTREAMS']
     for rel_path in rel_paths:
-        if not rel_path.endswith('.java'):
-            # Might be a fully qualified class name
+        # Paths end with a dot and lowercase file extension (.c, .java, ...) but
+        # fully qualified class names do not.
+        if ('/' not in rel_path) and (not re.match('.+\\.[a-z]{1,4}$', rel_path)):
+            # Assume a fully qualified class name
             rel_path = rel_path.replace('.', '/') + '.java'
         paths = []
         for repository in repositories:
-            if repository == "ojluni":
-                paths.append('%s/libcore/ojluni/src/main/java/%s' % (android_build_top, rel_path))
+            if repository == 'ojluni':
+                file_group = 'java/' if rel_path.endswith('.java') else 'native/'
+                paths.append('%s/libcore/ojluni/src/main/%s/%s'
+                             % (android_build_top, file_group, rel_path))
             else:
                 paths.append('%s/%s/%s' % (ojluni_upstreams, repository, rel_path))
         subprocess.call([diff] + paths)
@@ -88,8 +93,8 @@
     parser.add_argument('-d', '--diff', default='meld',
                         help='Application to use for diffing.')
     parser.add_argument('rel_path', nargs="+",
-                        help='File to compare: either a relative path below '
-                             'libcore/ojluni/src/main/java, or a fully qualified class name.')
+                        help='File to compare: either a relative path below libcore/ojluni/'
+                             'src/main/{java,native}, or a fully qualified class name.')
     args = parser.parse_args()
     repositories = args.repositories.split(',')
     if (len(repositories) < 2):