Merge "Use System.nanoTime() for timeouts and durations"
diff --git a/Docs.mk b/Docs.mk
index 0c52bf5..a163d1f 100644
--- a/Docs.mk
+++ b/Docs.mk
@@ -20,20 +20,11 @@
    libart/src/main/java/dalvik \
    libart/src/main/java/java \
    luni/src/main/java/android \
+   luni/src/main/java/java \
    luni/src/main/java/javax \
    luni/src/main/java/org/xml/sax \
    luni/src/main/java/org/w3c \
    xml/src/main/java/org/xmlpull/v1)
 
-# IcuIteratorWrapper.java references com.ibm.icu.text.BreakIterator,
-# which is renamed by our jarjar rule, and so unrecognizable by javadoc,
-# with annoying error: error: package com.ibm.icu.text does not exist.
-# We don't want to generate doc for this file anyway.
-libcore_to_document += \
-  $(filter-out luni/src/main/java/java/text/IcuIteratorWrapper.java,\
-    $(call find-files-in-subdirs, libcore, \
-      "*.java", \
-      luni/src/main/java/java))
-
 libcore_docs_include_once := 1
 endif # libcore_docs_include_once
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index fb0b207..8720170 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -77,10 +77,9 @@
 icu4j_src_files := $(call all-java-files-under,$(icu4j_root)/main/classes)
 
 # Filter out bits of ICU4J we don't use yet : the SPIs (which we have limited support for),
-# the charset encoders and the transliterators.
+# and the charset encoders
 icu4j_src_files := $(filter-out $(icu4j_root)/main/classes/localespi/%, $(icu4j_src_files))
 icu4j_src_files := $(filter-out $(icu4j_root)/main/classes/charset/%, $(icu4j_src_files))
-icu4j_src_files := $(filter-out $(icu4j_root)/main/classes/translit/%, $(icu4j_src_files))
 
 # Not all src dirs contain resources, some instead contain other random files
 # that should not be included as resources. The ones that should be included
@@ -93,7 +92,6 @@
 icu4j_resource_dirs := $(call all-icu-subdir-with-subdir,$(icu4j_root)/main/classes/*/src,com/ibm/icu)
 icu4j_resource_dirs := $(filter-out $(icu4j_root)/main/classes/localespi/%, $(icu4j_resource_dirs))
 icu4j_resource_dirs := $(filter-out $(icu4j_root)/main/classes/charset/%, $(icu4j_resource_dirs))
-icu4j_resource_dirs := $(filter-out $(icu4j_root)/main/classes/translit/%, $(icu4j_resource_dirs))
 
 
 
@@ -122,7 +120,7 @@
 LOCAL_SRC_FILES := $(test_src_files)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-libart okhttp core-junit bouncycastle
+LOCAL_JAVA_LIBRARIES := core-libart okhttp core-junit bouncycastle mockito-target
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support sqlite-jdbc mockwebserver nist-pkix-tests
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_MODULE := core-tests
@@ -162,12 +160,6 @@
 
 ifeq ($(HOST_OS),linux)
 
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-main-java-files-under, dex)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := dex-host
-include $(BUILD_HOST_JAVA_LIBRARY)
-
 # Definitions to make the core library.
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(libart_core_src_files) $(icu4j_src_files)
@@ -188,7 +180,7 @@
     LOCAL_SRC_FILES := $(test_src_files)
     LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
     LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_JAVA_LIBRARIES := core-libart-hostdex okhttp-hostdex bouncycastle-hostdex core-junit-hostdex core-tests-support-hostdex
+    LOCAL_JAVA_LIBRARIES := core-libart-hostdex okhttp-hostdex bouncycastle-hostdex core-junit-hostdex core-tests-support-hostdex mockito-api-hostdex
     LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
diff --git a/benchmarks/src/benchmarks/regression/BidiBenchmark.java b/benchmarks/src/benchmarks/regression/BidiBenchmark.java
new file mode 100644
index 0000000..bb5087e
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/BidiBenchmark.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 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 benchmarks.regression;
+
+import com.google.caliper.SimpleBenchmark;
+
+import java.math.BigDecimal;
+import java.text.AttributedCharacterIterator;
+import java.text.Bidi;
+import java.text.DecimalFormat;
+
+public class BidiBenchmark extends SimpleBenchmark {
+
+    private static final AttributedCharacterIterator charIter =
+            DecimalFormat.getInstance().formatToCharacterIterator(new BigDecimal(Math.PI));
+
+    public void time_createBidiFromIter(int reps) {
+        for (int i = 0; i < reps; i++) {
+            Bidi bidi = new Bidi(charIter);
+        }
+    }
+
+    public void time_createBidiFromCharArray(int reps) {
+        for (int i = 0; i < reps; i++) {
+            Bidi bd = new Bidi(new char[]{'s', 's', 's'}, 0, new byte[]{(byte) 1,
+                    (byte) 2, (byte) 3}, 0, 3, Bidi.DIRECTION_RIGHT_TO_LEFT);
+        }
+    }
+
+    public void time_createBidiFromString(int reps) {
+        for (int i = 0; i < reps; i++) {
+            Bidi bidi = new Bidi("Hello", Bidi.DIRECTION_LEFT_TO_RIGHT);
+        }
+    }
+
+    public void time_reorderVisually(int reps) {
+        for (int i = 0; i < reps; i++) {
+            Bidi.reorderVisually(new byte[]{2, 1, 3, 0, 4}, 0,
+                    new String[]{"H", "e", "l", "l", "o"}, 0, 5);
+        }
+    }
+
+    public void time_hebrewBidi(int reps) {
+        for (int i = 0; i < reps; i++) {
+            Bidi bd = new Bidi(new char[]{'\u05D0', '\u05D0', '\u05D0'}, 0,
+                    new byte[]{(byte) -1, (byte) -2, (byte) -3}, 0, 3,
+                    Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
+            bd = new Bidi(new char[]{'\u05D0', '\u05D0', '\u05D0'}, 0,
+                    new byte[]{(byte) -1, (byte) -2, (byte) -3}, 0, 3,
+                    Bidi.DIRECTION_LEFT_TO_RIGHT);
+        }
+    }
+
+    public void time_complicatedOverrideBidi(int reps) {
+        for (int i = 0; i < reps; i++) {
+            Bidi bd = new Bidi("a\u05D0a\"a\u05D0\"\u05D0a".toCharArray(), 0,
+                    new byte[]{0, 0, 0, -3, -3, 2, 2, 0, 3}, 0, 9,
+                    Bidi.DIRECTION_RIGHT_TO_LEFT);
+        }
+    }
+
+    public void time_requiresBidi(int reps) {
+        for (int i = 0; i < reps; i++) {
+            Bidi.requiresBidi("\u05D0".toCharArray(), 1, 1);  // false.
+            Bidi.requiresBidi("\u05D0".toCharArray(), 0, 1);  // true.
+        }
+    }
+
+}
diff --git a/benchmarks/src/benchmarks/regression/IdnBenchmark.java b/benchmarks/src/benchmarks/regression/IdnBenchmark.java
new file mode 100644
index 0000000..9de5261
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/IdnBenchmark.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 Google Inc.
+ *
+ * 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 benchmarks.regression;
+
+import com.google.caliper.SimpleBenchmark;
+
+import java.net.IDN;
+
+public class IdnBenchmark extends SimpleBenchmark {
+
+    public void timeToUnicode(int reps) {
+        for (int i = 0; i < reps; i++) {
+            IDN.toASCII("fass.de");
+            IDN.toASCII("faß.de");
+            IDN.toASCII("fäß.de");
+            IDN.toASCII("a\u200Cb");
+            IDN.toASCII("öbb.at");
+            IDN.toASCII("abc・日本.co.jp");
+            IDN.toASCII("日本.co.jp");
+            IDN.toASCII("x\u0327\u0301.de");
+            IDN.toASCII("σόλοσ.gr");
+        }
+    }
+
+    public void timeToAscii(int reps) {
+        for (int i = 0; i < reps; i++) {
+            IDN.toUnicode("xn--fss-qla.de");
+            IDN.toUnicode("xn--n00d.com");
+            IDN.toUnicode("xn--bb-eka.at");
+            IDN.toUnicode("xn--og-09a.de");
+            IDN.toUnicode("xn--53h.de");
+            IDN.toUnicode("xn--iny-zx5a.de");
+            IDN.toUnicode("xn--abc-rs4b422ycvb.co.jp");
+            IDN.toUnicode("xn--wgv71a.co.jp");
+            IDN.toUnicode("xn--x-xbb7i.de");
+            IDN.toUnicode("xn--wxaikc6b.gr");
+            IDN.toUnicode("xn--wxaikc6b.xn--gr-gtd9a1b0g.de");
+        }
+    }
+
+}
diff --git a/benchmarks/src/benchmarks/regression/ReflectionBenchmark.java b/benchmarks/src/benchmarks/regression/ReflectionBenchmark.java
index fcb2636..b1926f2 100644
--- a/benchmarks/src/benchmarks/regression/ReflectionBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/ReflectionBenchmark.java
@@ -163,6 +163,14 @@
         }
     }
 
+    public void timeClass_isInstance(int reps) throws Exception {
+        D d = new D();
+        Class<?> klass = IC.class;
+        for (int rep = 0; rep < reps; ++rep) {
+            klass.isInstance(d);
+        }
+    }
+
     public void timeGetInstanceField(int reps) throws Exception {
         for (int rep = 0; rep < reps; ++rep) {
             // The field here (and in timeGetStaticField) were chosen to be
@@ -182,7 +190,6 @@
         }
     }
 
-
     public static class C {
         public static int sf = 0;
         public int f = 0;
@@ -206,4 +213,16 @@
             sf = value;
         }
     }
+
+    interface IA {
+    }
+
+    interface IB extends IA {
+    }
+
+    interface IC extends IB {
+    }
+
+    class D implements IC {
+    }
 }
diff --git a/dalvik/src/main/java/dalvik/annotation/AndroidOnly.java b/dalvik/src/main/java/dalvik/annotation/AndroidOnly.java
deleted file mode 100644
index da3c1c5..0000000
--- a/dalvik/src/main/java/dalvik/annotation/AndroidOnly.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2008 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 dalvik.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marks a test-case as Android-only, that is, it should not be executed on
- * other systems.
- *
- * @hide
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.METHOD, ElementType.TYPE })
-public @interface AndroidOnly {
-
-    /**
-     * Plain text reason for adding this annotation.
-     */
-    String value();
-
-}
diff --git a/dalvik/src/main/java/dalvik/annotation/BrokenTest.java b/dalvik/src/main/java/dalvik/annotation/BrokenTest.java
deleted file mode 100644
index 16788d0..0000000
--- a/dalvik/src/main/java/dalvik/annotation/BrokenTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2008 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 dalvik.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marks a test case as broken. This means the test case should be fixed.
- *
- * @hide
- *
- * @deprecated - use expectations/brokentests.txt instead
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.METHOD })
-public @interface BrokenTest {
-
-    /**
-     * Plain text reason for adding this annotation.
-     */
-    String value();
-
-}
diff --git a/dalvik/src/main/java/dalvik/annotation/SideEffect.java b/dalvik/src/main/java/dalvik/annotation/SideEffect.java
deleted file mode 100644
index 2d691e3..0000000
--- a/dalvik/src/main/java/dalvik/annotation/SideEffect.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 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 dalvik.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marks a test-case as either having a side-effect that other tests might
- * notice or suffering from such a side effect. Such tests should be run in an
- * isolated manner.
- *
- * @hide
- *
- * @deprecated - use expectations/brokentests.txt instead
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.METHOD, ElementType.TYPE })
-public @interface SideEffect {
-
-    /**
-     * Plain text reason for adding this annotation.
-     */
-    String value();
-
-}
diff --git a/dalvik/src/main/java/dalvik/annotation/TestLevel.java b/dalvik/src/main/java/dalvik/annotation/TestLevel.java
deleted file mode 100644
index f62ea2f..0000000
--- a/dalvik/src/main/java/dalvik/annotation/TestLevel.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2008 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 dalvik.annotation;
-
-/**
- * Defines an enumeration of possible states a test case can be in.
- *
- * @hide
- */
-public enum TestLevel {
-
-    /**
-     * Indicates that a test method completely tests its target API method.
-     */
-    COMPLETE,
-
-    /**
-     * Indicates that a test method partially tests its target API method and
-     * that together with all other {@code PARTIAL_COMPLETE} tests for the same
-     * method it is sufficient.
-     */
-    PARTIAL_COMPLETE,
-
-    /**
-     * Just for compatibility purposes, will be removed later.
-     */
-    PARTIAL_OK,
-
-    /**
-     * Indicates that a test method partially tests its target API method. It
-     * needs a second review phase to find out if the sum of all partial tests
-     * is sufficient for completely testing the target API method. If yes, the
-     * level has to be changed to {@code PARTIAL_COMPLETE}.
-     */
-    PARTIAL,
-
-    /**
-     * Indicates that a test method is known to not completely test an API
-     * method but the missing test steps are too complex and costly to
-     * implement. This level is positioned somewhere between {@code PARTIAL}
-     * and {@code COMPLETE}.
-     */
-    SUFFICIENT,
-
-    /**
-     * Indicates that a test method provides additional testing for an API
-     * method for which there already exists one {@code COMPLETE} or a set of
-     * {@code PARTIAL_COMPLETE} tests. This level may also be used for test
-     * methods that test a concept which can not be directly attributed to
-     * the specification of an API method or class.
-     */
-    ADDITIONAL,
-
-    /**
-     * Indicates that there is nothing to test in an API method, for example if
-     * the specification states that a method does nothing.
-     */
-    NOT_NECESSARY,
-
-    /**
-     * Indicates that it is very hard or impossible to test an API method.
-     */
-    NOT_FEASIBLE,
-
-    /**
-     * Indicates that the tests is either insufficient or wrong. Something needs
-     * to be done about it.
-     */
-    TODO,
-
-}
diff --git a/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java b/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java
index 1e16d0c..89116ba 100644
--- a/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java
+++ b/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java
@@ -38,10 +38,4 @@
      * Specifies the class being tested.
      */
     Class<?> value();
-
-    /**
-     * Option to specify untested methods for the class.
-     * @hide
-     */
-    TestTargetNew[] untestedMethods() default {};
 }
diff --git a/dalvik/src/main/java/dalvik/annotation/TestTargetNew.java b/dalvik/src/main/java/dalvik/annotation/TestTargetNew.java
deleted file mode 100644
index 80aebee..0000000
--- a/dalvik/src/main/java/dalvik/annotation/TestTargetNew.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 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 dalvik.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Defines an annotation used be used within the TestInfo annotation. It
- * specifies a single method target for the test (but can be used multiple
- * times).
- * @hide
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
-public @interface TestTargetNew {
-
-    /**
-     * Specifies the name of the API method that is being tested. This field
-     * may be left empty if the test target is a concept implemented in a
-     * class rather than a concrete API method.
-     */
-    String method() default "";
-
-    /**
-     * Specifies the signature of the API method that is being tested, in terms
-     * of Java classes.
-     */
-    Class<?>[] args() default {};
-
-    /**
-     * Specifies the class to which the tested method belongs. If this value is
-     * not provided, the class identified in @TestTargetClass is used by the
-     * test progress doclet.
-     */
-    Class<?> clazz() default void.class;
-
-    /**
-     * Specifies the level of coverage the tested API method has.
-     */
-    TestLevel level();
-
-    /**
-     * Specifies noteworthy plain-text information about the test, for example
-     * if something is NOT covered by the test method.
-     */
-    String notes() default "";
-}
diff --git a/dalvik/src/main/java/dalvik/annotation/TestTargets.java b/dalvik/src/main/java/dalvik/annotation/TestTargets.java
deleted file mode 100644
index 207572c..0000000
--- a/dalvik/src/main/java/dalvik/annotation/TestTargets.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2008 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 dalvik.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Defines an annotation for test classes that allows to link them to the class
- * that is being tested. The current assumption is that the test are somewhat
- * organized according to the API classes they test. Might be too strict for
- * some cases.
- * @hide
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.METHOD })
-public @interface TestTargets {
-
-    /**
-     * Specifies the API methods that are tested by the annotated test method.
-     */
-    TestTargetNew[] value();
-}
diff --git a/dalvik/src/main/java/dalvik/annotation/ToBeFixed.java b/dalvik/src/main/java/dalvik/annotation/ToBeFixed.java
deleted file mode 100644
index 751a038..0000000
--- a/dalvik/src/main/java/dalvik/annotation/ToBeFixed.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2008 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 dalvik.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Defines an annotation for test methods that indicate the test method
- * need to be fixed in future.
- * {@hide pending API Council approval}
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.METHOD })
-public @interface ToBeFixed {
-
-    /**
-     * Specifies the related bug number on CTS bug tracking system.
-     */
-    String bug() default "";
-
-    /**
-     * Specifies why this method need to be fixed. If we think it's a bug, explain
-     * the expectation and the actual result.
-     */
-    String explanation() default "";
-}
diff --git a/dalvik/src/main/java/dalvik/system/VMDebug.java b/dalvik/src/main/java/dalvik/system/VMDebug.java
index 59e28e2..23d7407 100644
--- a/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -361,6 +361,8 @@
 
     /**
      * Counts the instances of a class.
+     * It is the caller's responsibility to do GC if they don't want unreachable
+     * objects to get counted.
      *
      * @param klass the class to be counted.
      * @param assignable if false, direct instances of klass are
@@ -372,6 +374,21 @@
     public static native long countInstancesOfClass(Class klass, boolean assignable);
 
     /**
+     * Counts the instances of classes.
+     * It is the caller's responsibility to do GC if they don't want unreachable
+     * objects to get counted.
+     *
+     * @param classes the classes to be counted.
+     * @param assignable if false, direct instances of klass are
+     *                   counted.  If true, instances that are
+     *                   assignable to klass, as defined by
+     *                   {@link Class#isAssignableFrom} are counted.
+     * @return an array containing the number of matching instances. The value for
+     * an index is the number of instances of the class at that index in number classes.
+     */
+    public static native long[] countInstancesOfClasses(Class[] classes, boolean assignable);
+
+    /**
      * Export the heap per-space stats for dumpsys meminfo.
      *
      * The content of the array is:
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index f5a13c6..e903cbb 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -1526,5 +1526,14 @@
     "com.android.org.conscrypt.NativeCryptoTest#test_SSL_renegotiate",
     "com.android.org.conscrypt.NativeCryptoTest#test_SSL_do_handshake_clientCertificateRequested_throws_after_renegotiate"
   ]
+},
+{
+  description: "Failures in OldSHA1PRNGSecureRandomTest",
+  result: EXEC_FAILED,
+  names: [
+    "org.apache.harmony.tests.javax.security.OldSHA1PRNGSecureRandomTest#testNextBytesbyteArray02",
+    "org.apache.harmony.tests.javax.security.OldSHA1PRNGSecureRandomTest#testNextBytesbyteArray04",
+    "org.apache.harmony.tests.javax.security.OldSHA1PRNGSecureRandomTest#testSetSeedbyteArray03"
+  ]
 }
 ]
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/Process2Test.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/Process2Test.java
index 649488c..7294bdd 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/Process2Test.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/Process2Test.java
@@ -17,8 +17,6 @@
 
 package org.apache.harmony.tests.java.lang;
 
-import dalvik.annotation.AndroidOnly;
-
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.IOException;
@@ -35,7 +33,6 @@
      *        java.lang.Process#getOutputStream()
      * Tests if these methods return buffered streams.
      */
-    @AndroidOnly("dalvikvm specific")
     public void test_streams()
             throws IOException, InterruptedException {
         Process p = javaProcessBuilder().start();
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/GenericSignatureFormatErrorTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/GenericSignatureFormatErrorTest.java
index 0cad681..20b9ab0 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/GenericSignatureFormatErrorTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/GenericSignatureFormatErrorTest.java
@@ -1,6 +1,5 @@
 package org.apache.harmony.tests.java.lang.reflect;
 
-import dalvik.annotation.AndroidOnly;
 import dalvik.system.DexFile;
 
 import junit.framework.TestCase;
@@ -31,8 +30,6 @@
     }
 
 
-    @AndroidOnly("Uses Android specific class dalvik.system.DexFile " +
-            "for loading classes.")
     // SideEffect: strange issue (exception: 'could not open dex file', 
     //  dalvikvm: 'waitpid failed' log msg  - only occurs when @SideEffect is removed 
     // and this test is run via running tests.luni.AllTestsLang TestSuite
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/SinkChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/SinkChannelTest.java
index 32f59c5..55a8fc3 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/SinkChannelTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/SinkChannelTest.java
@@ -463,7 +463,8 @@
 
     public void test_socketChannel_read_close() throws Exception {
         ServerSocketChannel ssc = ServerSocketChannel.open();
-        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0 /* any free port */));
+        int localPort = ssc.socket().getLocalPort();
         SocketChannel sc = SocketChannel.open();
         ByteBuffer buf = null;
         try{
@@ -472,7 +473,7 @@
         }catch (NullPointerException e){
             // expected
         }
-        sc.connect(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+        sc.connect(new InetSocketAddress(InetAddress.getLocalHost(), localPort));
         SocketChannel sock = ssc.accept();
         ssc.close();
         sc.close();
@@ -487,9 +488,10 @@
 
     public void test_socketChannel_read_write() throws Exception {
         ServerSocketChannel ssc = ServerSocketChannel.open();
-        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0 /* any free port */));
+        int localPort = ssc.socket().getLocalPort();
         SocketChannel sc = SocketChannel.open();
-        sc.connect(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+        sc.connect(new InetSocketAddress(InetAddress.getLocalHost(), localPort));
         SocketChannel sock = ssc.accept();
         ByteBuffer[] buf = {ByteBuffer.allocate(10),null};
         try {
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java
index 676e373..b201468 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java
@@ -16,8 +16,6 @@
 
 package org.apache.harmony.tests.java.util;
 
-import dalvik.annotation.AndroidOnly;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.EnumMap;
@@ -333,7 +331,7 @@
     /**
      * java.util.EnumMap#entrySet()
      */
-    @AndroidOnly("Map.Entry is indirectly modified on RI when Iterator.next() is invoked")
+    // AndroidOnly("Map.Entry is indirectly modified on RI when Iterator.next() is invoked")
     @SuppressWarnings({ "unchecked", "boxing" })
     public void test_entrySet() {
         EnumMap enumSizeMap = new EnumMap(Size.class);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/FormatterTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/FormatterTest.java
index c0e814e..87e177f 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/FormatterTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/FormatterTest.java
@@ -152,6 +152,8 @@
 
     private TimeZone defaultTimeZone;
 
+    private Locale defaultLocale;
+
     /**
      * java.util.Formatter#Formatter()
      */
@@ -4164,6 +4166,7 @@
      * test the short name for timezone whether uses DaylightTime or not
      */
     public void test_DaylightTime() {
+        Locale.setDefault(Locale.US);
         Calendar c1 = new GregorianCalendar(2007, 0, 1);
         Calendar c2 = new GregorianCalendar(2007, 7, 1);
 
@@ -4216,6 +4219,8 @@
 
         secret = File.createTempFile("secret", null);
 
+        defaultLocale = Locale.getDefault();
+
         defaultTimeZone = TimeZone.getDefault();
         TimeZone cst = TimeZone.getTimeZone("Asia/Shanghai");
         TimeZone.setDefault(cst);
@@ -4239,6 +4244,7 @@
             secret.delete();
         }
 
+        Locale.setDefault(defaultLocale);
         TimeZone.setDefault(defaultTimeZone);
     }
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/GregorianCalendarTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/GregorianCalendarTest.java
index f35be4b..6f25495 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/GregorianCalendarTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/GregorianCalendarTest.java
@@ -31,6 +31,20 @@
     private static final TimeZone AMERICA_CHICAGO = TimeZone.getTimeZone("America/Chicago");
     private static final TimeZone AMERICA_NEW_YORK = TimeZone.getTimeZone("America/New_York");
 
+    private Locale defaultLocale;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        defaultLocale = Locale.getDefault();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        Locale.setDefault(defaultLocale);
+        super.tearDown();
+    }
+
     /**
      * java.util.GregorianCalendar#GregorianCalendar()
      */
@@ -531,6 +545,8 @@
      * java.util.GregorianCalendar#roll(int, boolean)
      */
     public void test_rollIZ() {
+        Locale.setDefault(Locale.US);
+
         // Test for method void java.util.GregorianCalendar.roll(int, boolean)
         GregorianCalendar gc = new GregorianCalendar(1972, Calendar.OCTOBER,
                 13, 19, 9, 59);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/RandomTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/RandomTest.java
index d51d8abf..f790a31 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/RandomTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/RandomTest.java
@@ -18,12 +18,13 @@
 package org.apache.harmony.tests.java.util;
 
 import java.io.Serializable;
+import java.util.Arrays;
 import java.util.Random;
 import org.apache.harmony.testframework.serialization.SerializationTest;
 
 public class RandomTest extends junit.framework.TestCase {
 
-    Random r;
+    private Random r;
 
     /**
      * java.util.Random#Random()
@@ -44,6 +45,17 @@
                     .nextInt() == r2.nextInt());
     }
 
+    public void test_setSeed() {
+        Random r = new Random();
+        r.setSeed(1337);
+        Random r2 = new Random();
+        r2.setSeed(1337);
+        for (int i = 0; i < 100; i++)
+            assertTrue("Values from randoms with same seed don't match", r
+                    .nextInt() == r2.nextInt());
+    }
+
+
     /**
      * java.util.Random#nextBoolean()
      */
@@ -216,38 +228,39 @@
      */
     public void test_setSeedJ() {
         // Test for method void java.util.Random.setSeed(long)
-        long[] randomArray = new long[100];
-        boolean someDifferent = false;
-        final long firstSeed = 1000;
-        long aLong, anotherLong, yetAnotherLong;
-        Random aRandom = new Random();
-        Random anotherRandom = new Random();
-        Random yetAnotherRandom = new Random();
-        aRandom.setSeed(firstSeed);
-        anotherRandom.setSeed(firstSeed);
-        for (int counter = 0; counter < randomArray.length; counter++) {
-            aLong = aRandom.nextLong();
-            anotherLong = anotherRandom.nextLong();
-            assertTrue(
-                    "Two randoms with same seeds gave differing nextLong values",
-                    aLong == anotherLong);
-            yetAnotherLong = yetAnotherRandom.nextLong();
-            randomArray[counter] = aLong;
-            if (aLong != yetAnotherLong)
-                someDifferent = true;
+        long[] random1Values = new long[100];
+        long[] random2Values = new long[100];
+        long[] random3Values = new long[100];
+
+        Random random1 = new Random();
+        Random random2 = new Random();
+        Random random3 = new Random();
+
+        random1.setSeed(1337);
+        random2.setSeed(1337);
+        random3.setSeed(5000);
+
+        for (int i = 0; i < 100; ++i) {
+            random1Values[i] = random1.nextLong();
+            random2Values[i] = random2.nextLong();
+            random3Values[i] = random3.nextLong();
         }
-        assertTrue(
-                "Two randoms with the different seeds gave the same chain of values",
-                someDifferent);
-        aRandom.setSeed(firstSeed);
-        for (int counter = 0; counter < randomArray.length; counter++)
-            assertTrue(
-                    "Reseting a random to its old seed did not result in the same chain of values as it gave before",
-                    aRandom.nextLong() == randomArray[counter]);
+
+        assertTrue(Arrays.equals(random1Values, random2Values));
+        assertFalse(Arrays.equals(random2Values, random3Values));
+
+        // Set random3's seed to 1337 and assert it results in the same sequence of
+        // values as the first two randoms.
+        random3.setSeed(1337);
+        for (int i = 0; i < 100; ++i) {
+            random3Values[i] = random3.nextLong();
+        }
+
+        assertTrue(Arrays.equals(random1Values, random3Values));
     }
 
-    class Mock_Random extends Random {
-        boolean nextCalled = false;
+    static final class Mock_Random extends Random {
+        private boolean nextCalled = false;
 
         public boolean getFlag () {
             boolean retVal = nextCalled;
@@ -283,18 +296,12 @@
         assertTrue(mr.getFlag());
     }
 
-    /**
-     * Sets up the fixture, for example, open a network connection. This method
-     * is called before a test is executed.
-     */
+    @Override
     protected void setUp() {
         r = new Random();
     }
 
-    /**
-     * Tears down the fixture, for example, close a network connection. This
-     * method is called after a test is executed.
-     */
+    @Override
     protected void tearDown() {
     }
 
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarEntryTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarEntryTest.java
index a48bd60..3f4ed3b 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarEntryTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarEntryTest.java
@@ -26,6 +26,7 @@
 import java.util.jar.JarFile;
 import java.util.zip.ZipEntry;
 import junit.framework.TestCase;
+import libcore.io.Streams;
 import tests.support.resource.Support_Resources;
 
 public class JarEntryTest extends TestCase {
@@ -80,9 +81,6 @@
         }
     }
 
-    /**
-     * java.util.jar.JarEntry#JarEntry(java.util.zip.ZipEntry)
-     */
     public void test_ConstructorLjava_util_zip_ZipEntry() {
         assertNotNull("Jar file is null", jarFile);
         zipEntry = jarFile.getEntry(entryName);
@@ -116,38 +114,46 @@
         attrJar.close();
     }
 
-    /**
-     * java.util.jar.JarEntry#getCertificates()
-     */
-    public void test_getCertificates() throws Exception {
+    // http://b/1864326
+    public void testCertificatesAndCodesigners() throws Exception {
         zipEntry = jarFile.getEntry(entryName2);
         jarEntry = new JarEntry(zipEntry);
         assertNull(jarEntry.getCertificates());
 
-        // Regression Test for HARMONY-3424
+        // Regression Test for HARMONY-3424, b/1864326
         String jarFileName = "TestCodeSigners.jar";
         Support_Resources.copyFile(resources, null, jarFileName);
         File file = new File(resources, jarFileName);
         JarFile jarFile = new JarFile(file);
         JarEntry jarEntry1 = jarFile.getJarEntry("Test.class");
         JarEntry jarEntry2 = jarFile.getJarEntry("Test.class");
-        InputStream in = jarFile.getInputStream(jarEntry1);
-        byte[] buffer = new byte[1024];
-        while (in.available() > 0) {
-            assertNull("getCertificates() should be null until the entry is read",
-                    jarEntry1.getCertificates());
+
+        try (InputStream in = jarFile.getInputStream(jarEntry1)) {
+            // Code signers and certs must be {@code null} until the entry is completely
+            // read.
+            assertNull(jarEntry1.getCertificates());
             assertNull(jarEntry2.getCertificates());
-            in.read(buffer);
+            assertNull(jarEntry1.getCodeSigners());
+            assertNull(jarEntry2.getCodeSigners());
+
+            // Read a few bytes from the stream.
+            in.read(new byte[64]);
+            assertNull(jarEntry1.getCertificates());
+            assertNull(jarEntry2.getCertificates());
+            assertNull(jarEntry1.getCodeSigners());
+            assertNull(jarEntry2.getCodeSigners());
+
+            // Read the rest of the stream.
+            Streams.skipByReading(in, Long.MAX_VALUE);
+
+            assertEquals(-1, in.read());
+            assertNotNull(jarEntry1.getCodeSigners());
+            assertNotNull(jarEntry2.getCodeSigners());
+            assertNotNull(jarEntry1.getCertificates());
+            assertNotNull(jarEntry2.getCertificates());
         }
-        assertEquals("the file is fully read", -1, in.read());
-        assertNotNull(jarEntry1.getCertificates());
-        assertNotNull(jarEntry2.getCertificates());
-        in.close();
     }
 
-    /**
-     * java.util.jar.JarEntry#getCodeSigners()
-     */
     public void test_getCodeSigners() throws IOException {
         String jarFileName = "TestCodeSigners.jar";
         Support_Resources.copyFile(resources, null, jarFileName);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HandshakeCompletedEventTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HandshakeCompletedEventTest.java
index ec2f4f31..bb2265f 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HandshakeCompletedEventTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/HandshakeCompletedEventTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.harmony.tests.javax.net.ssl;
 
-import dalvik.annotation.AndroidOnly;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -334,7 +333,6 @@
      * because our self-signed test certificates are not valid.)
      */
 
-    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
     public void testClientAuth() throws Exception {
 
         boolean useBKS = true;
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLSocketTest.java
index 11e3142..861f4a8 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/ssl/SSLSocketTest.java
@@ -15,7 +15,6 @@
  */
 package org.apache.harmony.tests.javax.net.ssl;
 
-import dalvik.annotation.AndroidOnly;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -223,7 +222,7 @@
     /**
      * javax.net.ssl.SSLSocket#addHandshakeCompletedListener(HandshakeCompletedListener listener)
      */
-    @AndroidOnly("RI doesn't throw the specified IAE")
+    // AndroidOnly("RI doesn't throw the specified IAE")
     public void test_addHandshakeCompletedListener() throws IOException {
         SSLSocket ssl = getSSLSocket();
         HandshakeCompletedListener ls = new HandshakeCL();
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/provider/crypto/SHA1PRNG_SecureRandomTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/OldSHA1PRNGSecureRandomTest.java
similarity index 87%
rename from luni/src/test/java/org/apache/harmony/security/tests/provider/crypto/SHA1PRNG_SecureRandomTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/OldSHA1PRNGSecureRandomTest.java
index 0db5ee1..b213b47 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/provider/crypto/SHA1PRNG_SecureRandomTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/OldSHA1PRNGSecureRandomTest.java
@@ -15,10 +15,8 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.security.tests.provider.crypto;
+package org.apache.harmony.tests.javax.security;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.SecureRandom;
@@ -29,7 +27,7 @@
  * Tests against methods in SecureRandom class object using
  * SHA1PRNG_SecureRandomImpl.
  */
-public class SHA1PRNG_SecureRandomTest extends TestCase {
+public class OldSHA1PRNGSecureRandomTest extends TestCase {
 
     private static final int LENGTH = 20; // constant defining loop limit
 
@@ -37,8 +35,6 @@
 
     private static final String algorithm = "SHA1PRNG"; // algorithm's name
 
-    private static final String provider = "Crypto"; // provider's name
-
     private static SecureRandom sr; // fields used by tests
 
     private static SecureRandom sr2; //
@@ -48,8 +44,8 @@
      */
     protected void setUp() throws Exception {
         super.setUp();
-        sr = SecureRandom.getInstance(algorithm, provider);
-        sr2 = SecureRandom.getInstance(algorithm, provider);
+        sr = SecureRandom.getInstance(algorithm);
+        sr2 = SecureRandom.getInstance(algorithm);
     }
 
     /**
@@ -189,8 +185,8 @@
         byte[] myBytes2;
 
         for (int i = 1; i < LENGTH / 2; i += INCR) {
-            sr1 = SecureRandom.getInstance(algorithm, provider);
-            sr2 = SecureRandom.getInstance(algorithm, provider);
+            sr1 = SecureRandom.getInstance(algorithm);
+            sr2 = SecureRandom.getInstance(algorithm);
 
             boolean flag = true;
 
@@ -245,8 +241,8 @@
 
         // case 1:
         for (int i = 1; i < LENGTH / 2; i += INCR) {
-            sr1 = SecureRandom.getInstance(algorithm, provider);
-            sr2 = SecureRandom.getInstance(algorithm, provider);
+            sr1 = SecureRandom.getInstance(algorithm);
+            sr2 = SecureRandom.getInstance(algorithm);
 
             sr1.nextBytes(new byte[0]);
             sr2.nextBytes(new byte[0]);
@@ -286,8 +282,8 @@
             byte[][] bytes1 = new byte[2][n];
             byte[][] bytes2 = new byte[2][n];
 
-            sr1 = SecureRandom.getInstance(algorithm, provider);
-            sr2 = SecureRandom.getInstance(algorithm, provider);
+            sr1 = SecureRandom.getInstance(algorithm);
+            sr2 = SecureRandom.getInstance(algorithm);
 
             sr1.setSeed(myBytes);
             sr2.setSeed(myBytes);
@@ -402,31 +398,4 @@
             assertFalse("sequences are equal i=" + i, b);
         }
     }
-
-    public void testSeedIsFullLength() throws Exception {
-        Class<?> srClass = Class.forName(
-                "org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl");
-        Field seedField = srClass.getDeclaredField("seed");
-        seedField.setAccessible(true);
-
-        Method nextBytesMethod = srClass.getDeclaredMethod("engineNextBytes", byte[].class);
-        nextBytesMethod.setAccessible(true);
-
-        byte[] bytes = new byte[1];
-
-        // Iterate 8 times to make sure the probability of a false positive is
-        // extremely rare.
-        for (int i = 0; i < 8; i++) {
-            Object sr = srClass.newInstance();
-            nextBytesMethod.invoke(sr, bytes);
-            int[] seed = (int[]) seedField.get(sr);
-
-            // If the first integer is not zero, it is fixed.
-            if (seed[0] != 0) {
-                return; // Success
-            }
-        }
-
-        fail("Fallback SHA1PRNG_SecureRandomImpl should not clobber seed internally");
-    }
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/SAXParserFactoryTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/SAXParserFactoryTest.java
index 614b9d8..4e1ffdf 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/SAXParserFactoryTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/SAXParserFactoryTest.java
@@ -35,7 +35,6 @@
 import org.xml.sax.SAXNotSupportedException;
 import org.xml.sax.helpers.DefaultHandler;
 
-import dalvik.annotation.AndroidOnly;
 import dalvik.annotation.KnownFailure;
 
 public class SAXParserFactoryTest extends TestCase {
@@ -65,7 +64,7 @@
         super.tearDown();
     }
 
-    @AndroidOnly("Android SAX implementation is non-validating")
+    // AndroidOnly("Android SAX implementation is non-validating")
     public void test_Constructor() {
         MySAXParserFactory mpf = new MySAXParserFactory();
         assertTrue(mpf instanceof SAXParserFactory);
diff --git a/libart/src/main/java/java/lang/CaseMapper.java b/libart/src/main/java/java/lang/CaseMapper.java
index f23a4ef..5cf4ecf 100644
--- a/libart/src/main/java/java/lang/CaseMapper.java
+++ b/libart/src/main/java/java/lang/CaseMapper.java
@@ -18,7 +18,7 @@
 
 import java.util.Locale;
 import libcore.icu.ICU;
-import libcore.icu.Transliterator;
+import com.ibm.icu.text.Transliterator;
 
 /**
  * Performs case operations as described by http://unicode.org/reports/tr21/tr21-5.html.
@@ -138,7 +138,7 @@
 
     private static final ThreadLocal<Transliterator> EL_UPPER = new ThreadLocal<Transliterator>() {
         @Override protected Transliterator initialValue() {
-            return new Transliterator("el-Upper");
+            return Transliterator.getInstance("el-Upper");
         }
     };
 
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
index bc54f89..0d37cd6 100644
--- a/libart/src/main/java/java/lang/Class.java
+++ b/libart/src/main/java/java/lang/Class.java
@@ -227,24 +227,12 @@
      */
     private transient volatile int dexTypeIndex;
 
-    /** Number of direct methods. */
-    private transient int numDirectMethods;
-
-    /** Number of instance fields. */
-    private transient int numInstanceFields;
-
     /** Number of instance fields that are object references. */
     private transient int numReferenceInstanceFields;
 
     /** Number of static fields that are object references. */
     private transient int numReferenceStaticFields;
 
-    /** Number of static fields. */
-    private transient int numStaticFields;
-
-    /** Number of virtual methods. */
-    private transient int numVirtualMethods;
-
     /**
      * Total object size; used when allocating storage on GC heap. For interfaces and abstract
      * classes this will be zero. See also {@link Class#classSize}.
@@ -583,7 +571,7 @@
      *            {@code (Class[]) null} is equivalent to the empty array.
      * @return the method described by {@code name} and {@code parameterTypes}.
      * @throws NoSuchMethodException
-     *             if the requested constructor cannot be found.
+     *             if the requested method cannot be found.
      * @throws NullPointerException
      *             if {@code name} is {@code null}.
      * @see #getMethod(String, Class[])
@@ -1283,8 +1271,7 @@
             Object[] iftable = c.ifTable;
             if (iftable != null) {
                 for (int i = 0; i < iftable.length; i += 2) {
-                    Class<?> ifc = (Class<?>) iftable[i];
-                    if (ifc == this) {
+                    if (iftable[i] == this) {
                         return true;
                     }
                 }
diff --git a/libart/src/main/java/java/lang/ClassLoader.java b/libart/src/main/java/java/lang/ClassLoader.java
index dfbeeb5..860e4a1 100644
--- a/libart/src/main/java/java/lang/ClassLoader.java
+++ b/libart/src/main/java/java/lang/ClassLoader.java
@@ -92,6 +92,11 @@
     private Map<String, Package> packages = new HashMap<String, Package>();
 
     /**
+     * Pointer to the class table, only used from within the runtime.
+     */
+    private transient long classTable;
+
+    /**
      * To avoid unloading individual classes, {@link java.lang.reflect.Proxy}
      * only generates one class for each set of interfaces. This maps sets of
      * interfaces to the proxy class that implements all of them. It is declared
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java
index fcecf18..c43c1ba 100644
--- a/luni/src/main/java/android/system/Os.java
+++ b/luni/src/main/java/android/system/Os.java
@@ -43,6 +43,12 @@
   public static FileDescriptor accept(FileDescriptor fd, InetSocketAddress peerAddress) throws ErrnoException, SocketException { return Libcore.os.accept(fd, peerAddress); }
 
   /**
+   * TODO Change the public API by removing the overload above and unhiding this version.
+   * @hide
+   */
+  public static FileDescriptor accept(FileDescriptor fd, SocketAddress peerAddress) throws ErrnoException, SocketException { return Libcore.os.accept(fd, peerAddress); }
+
+  /**
    * See <a href="http://man7.org/linux/man-pages/man2/access.2.html">access(2)</a>.
    */
   public static boolean access(String path, int mode) throws ErrnoException { return Libcore.os.access(path, mode); }
@@ -215,6 +221,8 @@
    */
   public static int getuid() { return Libcore.os.getuid(); }
 
+  /** @hide */ public static int getxattr(String path, String name, byte[] outValue) throws ErrnoException { return Libcore.os.getxattr(path, name, outValue); }
+
   /**
    * See <a href="http://man7.org/linux/man-pages/man3/if_indextoname.3.html">if_indextoname(3)</a>.
    */
@@ -389,6 +397,8 @@
    */
   public static void remove(String path) throws ErrnoException { Libcore.os.remove(path); }
 
+  /** @hide */ public static void removexattr(String path, String name) throws ErrnoException { Libcore.os.removexattr(path, name); }
+
   /**
    * See <a href="http://man7.org/linux/man-pages/man2/rename.2.html">rename(2)</a>.
    */
@@ -468,6 +478,8 @@
    */
   public static void setuid(int uid) throws ErrnoException { Libcore.os.setuid(uid); }
 
+  /** @hide */ public static void setxattr(String path, String name, byte[] value, int flags) throws ErrnoException { Libcore.os.setxattr(path, name, value, flags); };
+
   /**
    * See <a href="http://man7.org/linux/man-pages/man2/shutdown.2.html">shutdown(2)</a>.
    */
@@ -534,6 +546,11 @@
   public static StructUtsname uname() { return Libcore.os.uname(); }
 
   /**
+   * @hide See <a href="http://man7.org/linux/man-pages/man2/unlink.2.html">unlink(2)</a>.
+   */
+  public static void unlink(String pathname) throws ErrnoException { Libcore.os.unlink(pathname); }
+
+  /**
    * See <a href="http://man7.org/linux/man-pages/man3/unsetenv.3.html">unsetenv(3)</a>.
    */
   public static void unsetenv(String name) throws ErrnoException { Libcore.os.unsetenv(name); }
diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java
index 6a99bb3..f0d77de 100644
--- a/luni/src/main/java/android/system/OsConstants.java
+++ b/luni/src/main/java/android/system/OsConstants.java
@@ -238,6 +238,7 @@
     public static final int ETIME = placeholder();
     public static final int ETIMEDOUT = placeholder();
     public static final int ETXTBSY = placeholder();
+    /** @hide */ public static final int EUSERS = placeholder();
     // On Linux, EWOULDBLOCK == EAGAIN. Use EAGAIN instead, to reduce confusion.
     public static final int EXDEV = placeholder();
     public static final int EXIT_FAILURE = placeholder();
@@ -349,6 +350,7 @@
     public static final int O_RDONLY = placeholder();
     public static final int O_RDWR = placeholder();
     public static final int O_SYNC = placeholder();
+    /** @hide */ public static final int O_DSYNC = placeholder();
     public static final int O_TRUNC = placeholder();
     public static final int O_WRONLY = placeholder();
     public static final int POLLERR = placeholder();
@@ -489,6 +491,8 @@
     public static final int S_IXOTH = placeholder();
     public static final int S_IXUSR = placeholder();
     public static final int TCP_NODELAY = placeholder();
+    /** @hide */ public static final int TIOCOUTQ = placeholder();
+    /** @hide */ public static final int UNIX_PATH_MAX = placeholder();
     public static final int WCONTINUED = placeholder();
     public static final int WEXITED = placeholder();
     public static final int WNOHANG = placeholder();
@@ -496,6 +500,8 @@
     public static final int WSTOPPED = placeholder();
     public static final int WUNTRACED = placeholder();
     public static final int W_OK = placeholder();
+    /** @hide */ public static final int XATTR_CREATE = placeholder();
+    /** @hide */ public static final int XATTR_REPLACE = placeholder();
     public static final int X_OK = placeholder();
     public static final int _SC_2_CHAR_TERM = placeholder();
     public static final int _SC_2_C_BIND = placeholder();
diff --git a/luni/src/main/java/android/system/UnixSocketAddress.java b/luni/src/main/java/android/system/UnixSocketAddress.java
new file mode 100644
index 0000000..e0ade78
--- /dev/null
+++ b/luni/src/main/java/android/system/UnixSocketAddress.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 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 android.system;
+
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+/**
+ * A UNIX-domain (AF_UNIX / AF_LOCAL) socket address.
+ *
+ * @hide
+ */
+public final class UnixSocketAddress extends SocketAddress {
+
+    private static final int NAMED_PATH_LENGTH = OsConstants.UNIX_PATH_MAX;
+    private static final byte[] UNNAMED_PATH = new byte[0];
+
+    // See unix(7): Three types of UnixSocketAddress:
+    // 1) pathname: 0 < sun_path.length <= NAMED_PATH_LENGTH, sun_path[0] != 0.
+    // 2) unnamed: sun_path = [].
+    // 3) abstract: 0 < sun_path.length <= NAMED_PATH_LENGTH, sun_path[0] == 0.
+    private byte[] sun_path;
+
+    /** This constructor is also used from JNI. */
+    private UnixSocketAddress(byte[] sun_path) {
+        if (sun_path == null) {
+            throw new IllegalArgumentException("sun_path must not be null");
+        }
+        if (sun_path.length > NAMED_PATH_LENGTH) {
+            throw new IllegalArgumentException("sun_path exceeds the maximum length");
+        }
+
+        if (sun_path.length == 0) {
+            this.sun_path = UNNAMED_PATH;
+        } else {
+            this.sun_path = new byte[sun_path.length];
+            System.arraycopy(sun_path, 0, this.sun_path, 0, sun_path.length);
+        }
+    }
+
+    /**
+     * Creates a named, abstract AF_UNIX socket address.
+     */
+    public static UnixSocketAddress createAbstract(String name) {
+        byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
+        // Abstract sockets have a path that starts with (byte) 0.
+        byte[] path = new byte[nameBytes.length + 1];
+        System.arraycopy(nameBytes, 0, path, 1, nameBytes.length);
+        return new UnixSocketAddress(path);
+    }
+
+    /**
+     * Creates a named, filesystem AF_UNIX socket address.
+     */
+    public static UnixSocketAddress createFileSystem(String pathName) {
+        byte[] pathNameBytes = pathName.getBytes(StandardCharsets.UTF_8);
+        // File system sockets have a path that ends with (byte) 0.
+        byte[] path = new byte[pathNameBytes.length + 1];
+        System.arraycopy(pathNameBytes, 0, path, 0, pathNameBytes.length);
+        return new UnixSocketAddress(path);
+    }
+
+    /**
+     * Creates an unnamed, filesystem AF_UNIX socket address.
+     */
+    public static UnixSocketAddress createUnnamed() {
+        return new UnixSocketAddress(UNNAMED_PATH);
+    }
+
+    /** Used for testing. */
+    public byte[] getSunPath() {
+        if (sun_path.length == 0) {
+            return sun_path;
+        }
+        byte[] sunPathCopy = new byte[sun_path.length];
+        System.arraycopy(sun_path, 0, sunPathCopy, 0, sun_path.length);
+        return sunPathCopy;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        UnixSocketAddress that = (UnixSocketAddress) o;
+        return Arrays.equals(sun_path, that.sun_path);
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(sun_path);
+    }
+
+    @Override
+    public String toString() {
+        return "UnixSocketAddress[" +
+                "sun_path=" + Arrays.toString(sun_path) +
+                ']';
+    }
+}
diff --git a/luni/src/main/java/java/io/RandomAccessFile.java b/luni/src/main/java/java/io/RandomAccessFile.java
index 0e4fa4f..42c30c4 100644
--- a/luni/src/main/java/java/io/RandomAccessFile.java
+++ b/luni/src/main/java/java/io/RandomAccessFile.java
@@ -44,8 +44,6 @@
      */
     private FileDescriptor fd;
 
-    private boolean syncMetadata = false;
-
     // The unique file channel associated with this FileInputStream (lazily
     // initialized).
     private FileChannel channel;
@@ -104,11 +102,11 @@
         } else if (mode.equals("rw") || mode.equals("rws") || mode.equals("rwd")) {
             flags = O_RDWR | O_CREAT;
             if (mode.equals("rws")) {
-                // Sync file and metadata with every write
-                syncMetadata = true;
-            } else if (mode.equals("rwd")) {
-                // Sync file, but not necessarily metadata
+                // Sync data and metadata with every write
                 flags |= O_SYNC;
+            } else if (mode.equals("rwd")) {
+                // Sync data, but not necessarily metadata
+                flags |= O_DSYNC;
             }
         } else {
             throw new IllegalArgumentException("Invalid mode: " + mode);
@@ -116,14 +114,6 @@
         this.mode = flags;
         this.fd = IoBridge.open(file.getPath(), flags);
 
-        // if we are in "rws" mode, attempt to sync file+metadata
-        if (syncMetadata) {
-            try {
-                fd.sync();
-            } catch (IOException e) {
-                // Ignored
-            }
-        }
         guard.open("close");
     }
 
@@ -635,10 +625,6 @@
             seek(newLength);
         }
 
-        // if we are in "rws" mode, attempt to sync file+metadata
-        if (syncMetadata) {
-            fd.sync();
-        }
     }
 
     /**
@@ -689,10 +675,6 @@
      */
     public void write(byte[] buffer, int byteOffset, int byteCount) throws IOException {
         IoBridge.write(fd, buffer, byteOffset, byteCount);
-        // if we are in "rws" mode, attempt to sync file+metadata
-        if (syncMetadata) {
-            fd.sync();
-        }
     }
 
     /**
diff --git a/luni/src/main/java/java/lang/reflect/Array.java b/luni/src/main/java/java/lang/reflect/Array.java
index a7dacfe..72e6717 100644
--- a/luni/src/main/java/java/lang/reflect/Array.java
+++ b/luni/src/main/java/java/lang/reflect/Array.java
@@ -371,7 +371,7 @@
         } else if (componentType == void.class) {
             throw new IllegalArgumentException("Can't allocate an array of void");
         }
-        throw new AssertionError();
+        throw new AssertionError(componentType.toString());
     }
 
     /*
diff --git a/luni/src/main/java/java/net/IDN.java b/luni/src/main/java/java/net/IDN.java
index 4e60209..dd256c2 100644
--- a/luni/src/main/java/java/net/IDN.java
+++ b/luni/src/main/java/java/net/IDN.java
@@ -16,7 +16,7 @@
 
 package java.net;
 
-import libcore.icu.NativeIDN;
+import com.ibm.icu.text.IDNA;
 
 /**
  * Converts internationalized domain names between Unicode and the ASCII Compatible Encoding
@@ -61,7 +61,11 @@
      * @throws IllegalArgumentException if {@code input} does not conform to <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a>
      */
     public static String toASCII(String input, int flags) {
-        return NativeIDN.toASCII(input, flags);
+        try {
+            return IDNA.convertIDNToASCII(input, flags).toString();
+        } catch (com.ibm.icu.text.StringPrepParseException e) {
+            throw new IllegalArgumentException("Invalid input to toASCII: " + input, e);
+        }
     }
 
     /**
@@ -91,7 +95,28 @@
      *         or {@code ALLOW_UNASSIGNED | USE_STD3_ASCII_RULES}
      */
     public static String toUnicode(String input, int flags) {
-        return NativeIDN.toUnicode(input, flags);
+        try {
+            // ICU only translates separators to ASCII for toASCII.
+            // Java expects the translation for toUnicode too.
+            return convertFullStop(IDNA.convertIDNToUnicode(input, flags)).toString();
+        } catch (com.ibm.icu.text.StringPrepParseException e) {
+            // The RI documentation explicitly states that if the conversion was unsuccessful
+            // the original string is returned.
+            return input;
+        }
+    }
+
+    private static boolean isLabelSeperator(char c) {
+        return (c == '\u3002' || c == '\uff0e' || c == '\uff61');
+    }
+
+    private static StringBuffer convertFullStop(StringBuffer input) {
+        for (int i = 0; i < input.length(); i++) {
+            if (isLabelSeperator(input.charAt(i))) {
+                input.setCharAt(i, '.');
+            }
+        }
+        return input;
     }
 
     /**
@@ -101,6 +126,6 @@
      * @return the Unicode name
      */
     public static String toUnicode(String input) {
-        return NativeIDN.toUnicode(input, 0);
+        return toUnicode(input, 0);
     }
 }
diff --git a/luni/src/main/java/java/net/InetUnixAddress.java b/luni/src/main/java/java/net/InetUnixAddress.java
deleted file mode 100644
index 51236e2..0000000
--- a/luni/src/main/java/java/net/InetUnixAddress.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2013 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 java.net;
-
-import java.nio.charset.StandardCharsets;
-
-import static android.system.OsConstants.*;
-
-/**
- * An AF_UNIX address. See {@link InetAddress}.
- * @hide
- */
-public final class InetUnixAddress extends InetAddress {
-  /**
-   * Constructs an AF_UNIX InetAddress for the given path.
-   */
-  public InetUnixAddress(String path) {
-    this(path.getBytes(StandardCharsets.UTF_8));
-  }
-
-  /**
-   * Constructs an AF_UNIX InetAddress for the given path.
-   */
-  public InetUnixAddress(byte[] path) {
-    super(AF_UNIX, path, null);
-  }
-
-  /**
-   * Returns a string form of this InetAddress.
-   */
-  @Override public String toString() {
-    return "InetUnixAddress[" + new String(ipaddress, StandardCharsets.UTF_8) + "]";
-  }
-}
diff --git a/luni/src/main/java/java/security/SecureRandom.java b/luni/src/main/java/java/security/SecureRandom.java
index 7a03801..8fbcc39 100644
--- a/luni/src/main/java/java/security/SecureRandom.java
+++ b/luni/src/main/java/java/security/SecureRandom.java
@@ -23,7 +23,6 @@
 import libcore.io.SizeOf;
 import org.apache.harmony.security.fortress.Engine;
 import org.apache.harmony.security.fortress.Services;
-import org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl;
 
 /**
  * This class generates cryptographically secure pseudo-random numbers.
@@ -86,12 +85,8 @@
      */
     public SecureRandom() {
         super(0);
-        Provider.Service service = Services.getSecureRandomService();
-        if (service == null) {
-            this.provider = null;
-            this.secureRandomSpi = new SHA1PRNG_SecureRandomImpl();
-            this.algorithm = "SHA1PRNG";
-        } else {
+        final Provider.Service service = Services.getSecureRandomService();
+        if (service != null) {
             try {
                 this.provider = service.getProvider();
                 this.secureRandomSpi = (SecureRandomSpi)service.newInstance(null);
@@ -99,6 +94,8 @@
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
+        } else {
+            throw new AssertionError("Services.getSecureRandomService() == null");
         }
     }
 
diff --git a/luni/src/main/java/java/security/Security.java b/luni/src/main/java/java/security/Security.java
index aeb189f..723b0eb 100644
--- a/luni/src/main/java/java/security/Security.java
+++ b/luni/src/main/java/java/security/Security.java
@@ -90,8 +90,7 @@
     private static void registerDefaultProviders() {
         secprops.put("security.provider.1", "com.android.org.conscrypt.OpenSSLProvider");
         secprops.put("security.provider.2", "com.android.org.bouncycastle.jce.provider.BouncyCastleProvider");
-        secprops.put("security.provider.3", "org.apache.harmony.security.provider.crypto.CryptoProvider");
-        secprops.put("security.provider.4", "com.android.org.conscrypt.JSSEProvider");
+        secprops.put("security.provider.3", "com.android.org.conscrypt.JSSEProvider");
     }
 
     /**
diff --git a/luni/src/main/java/java/security/Signature.java b/luni/src/main/java/java/security/Signature.java
index b11abaa..7a21a46 100644
--- a/luni/src/main/java/java/security/Signature.java
+++ b/luni/src/main/java/java/security/Signature.java
@@ -687,16 +687,32 @@
         }
 
         @Override
+        protected int engineSign(byte[] outbuf, int offset, int len) throws SignatureException {
+            return getSpi().engineSign(outbuf, offset, len);
+        }
+
+        @Override
         protected void engineUpdate(byte arg0) throws SignatureException {
             getSpi().engineUpdate(arg0);
         }
 
         @Override
+        protected void engineUpdate(ByteBuffer input) {
+            getSpi().engineUpdate(input);
+        }
+
+        @Override
         protected boolean engineVerify(byte[] arg0) throws SignatureException {
             return getSpi().engineVerify(arg0);
         }
 
         @Override
+        protected boolean engineVerify(byte[] sigBytes, int offset, int length)
+                throws SignatureException {
+            return getSpi().engineVerify(sigBytes, offset, length);
+        }
+
+        @Override
         protected void engineUpdate(byte[] arg0, int arg1, int arg2) throws SignatureException {
             getSpi().engineUpdate(arg0, arg1, arg2);
         }
@@ -707,6 +723,12 @@
         }
 
         @Override
+        protected void engineInitSign(PrivateKey arg0, SecureRandom arg1)
+                throws InvalidKeyException {
+            getSpi(arg0).engineInitSign(arg0, arg1);
+        }
+
+        @Override
         protected void engineInitVerify(PublicKey arg0) throws InvalidKeyException {
             getSpi(arg0).engineInitVerify(arg0);
         }
@@ -717,6 +739,11 @@
         }
 
         @Override
+        protected AlgorithmParameters engineGetParameters() {
+            return getSpi().engineGetParameters();
+        }
+
+        @Override
         protected void engineSetParameter(String arg0, Object arg1)
                 throws InvalidParameterException {
             getSpi().engineSetParameter(arg0, arg1);
diff --git a/luni/src/main/java/java/security/security.properties b/luni/src/main/java/java/security/security.properties
index a06283b..289efa9 100644
--- a/luni/src/main/java/java/security/security.properties
+++ b/luni/src/main/java/java/security/security.properties
@@ -22,9 +22,8 @@
 security.provider.1=com.android.org.conscrypt.OpenSSLProvider
 # Android's stripped down BouncyCastle provider
 security.provider.2=com.android.org.bouncycastle.jce.provider.BouncyCastleProvider
-# Remaining Harmony providers
-security.provider.3=org.apache.harmony.security.provider.crypto.CryptoProvider
-security.provider.4=com.android.org.conscrypt.JSSEProvider
+# Android's provider of OpenSSL backed implementations
+security.provider.3=com.android.org.conscrypt.JSSEProvider
 
 
 
diff --git a/luni/src/main/java/java/text/Bidi.java b/luni/src/main/java/java/text/Bidi.java
index d73ea4a..65861a7 100644
--- a/luni/src/main/java/java/text/Bidi.java
+++ b/luni/src/main/java/java/text/Bidi.java
@@ -17,11 +17,6 @@
 
 package java.text;
 
-import java.awt.font.NumericShaper;
-import java.awt.font.TextAttribute;
-import java.util.ArrayList;
-import java.util.Arrays;
-
 /**
  * Implements the <a href="http://unicode.org/reports/tr9/">Unicode Bidirectional Algorithm</a>.
  *
@@ -58,33 +53,28 @@
      */
     public static final int DIRECTION_RIGHT_TO_LEFT = 1;
 
-    /**
-     * TODO: if we care about performance, we might just want to use an int[] instead of a Run[].
-     */
-    static class Run {
-        private final int start;
-        private final int limit;
-        private final int level;
-
-        public Run(int start, int limit, int level) {
-            this.start = start;
-            this.limit = limit;
-            this.level = level;
-        }
-
-        public int getLevel() {
-            return level;
-        }
-
-        public int getLimit() {
-            return limit;
-        }
-
-        public int getStart() {
-            return start;
+    private static int translateConstToIcu(int javaInt) {
+        switch (javaInt) {
+            case DIRECTION_DEFAULT_LEFT_TO_RIGHT:
+                return com.ibm.icu.text.Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
+            case DIRECTION_DEFAULT_RIGHT_TO_LEFT:
+                return com.ibm.icu.text.Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT;
+            case DIRECTION_LEFT_TO_RIGHT:
+                return com.ibm.icu.text.Bidi.DIRECTION_LEFT_TO_RIGHT;
+            case DIRECTION_RIGHT_TO_LEFT:
+                return com.ibm.icu.text.Bidi.DIRECTION_RIGHT_TO_LEFT;
+            // If the parameter was unrecognized use LEFT_TO_RIGHT.
+            default:
+                return com.ibm.icu.text.Bidi.DIRECTION_LEFT_TO_RIGHT;
         }
     }
 
+    private boolean isUnidirectional() {
+        return icuBidi.getRunCount() == 0;
+    }
+
+    private final com.ibm.icu.text.Bidi icuBidi;
+
     /**
      * Creates a {@code Bidi} object from the {@code
      * AttributedCharacterIterator} of a paragraph text. The RUN_DIRECTION
@@ -114,65 +104,7 @@
             throw new IllegalArgumentException("paragraph is null");
         }
 
-        int begin = paragraph.getBeginIndex();
-        int end = paragraph.getEndIndex();
-        int length = end - begin;
-        char[] text = new char[length + 1]; // One more char for AttributedCharacterIterator.DONE
-
-        if (length != 0) {
-            text[0] = paragraph.first();
-        } else {
-            paragraph.first();
-        }
-
-        // First check the RUN_DIRECTION attribute.
-        int flags = DIRECTION_DEFAULT_LEFT_TO_RIGHT;
-        Object direction = paragraph.getAttribute(TextAttribute.RUN_DIRECTION);
-        if (direction != null && direction instanceof Boolean) {
-            if (direction.equals(TextAttribute.RUN_DIRECTION_LTR)) {
-                flags = DIRECTION_LEFT_TO_RIGHT;
-            } else {
-                flags = DIRECTION_RIGHT_TO_LEFT;
-            }
-        }
-
-        // Retrieve the text and gather BIDI_EMBEDDINGS
-        byte[] embeddings = null;
-        for (int textLimit = 1, i = 1; i < length; textLimit = paragraph
-                .getRunLimit(TextAttribute.BIDI_EMBEDDING)
-                - begin + 1) {
-            Object embedding = paragraph.getAttribute(TextAttribute.BIDI_EMBEDDING);
-            if (embedding != null && embedding instanceof Integer) {
-                int embLevel = ((Integer) embedding).intValue();
-
-                if (embeddings == null) {
-                    embeddings = new byte[length];
-                }
-
-                for (; i < textLimit; i++) {
-                    text[i] = paragraph.next();
-                    embeddings[i - 1] = (byte) embLevel;
-                }
-            } else {
-                for (; i < textLimit; i++) {
-                    text[i] = paragraph.next();
-                }
-            }
-        }
-
-        // Apply NumericShaper to the text
-        Object numericShaper = paragraph.getAttribute(TextAttribute.NUMERIC_SHAPING);
-        if (numericShaper != null && numericShaper instanceof NumericShaper) {
-            ((NumericShaper) numericShaper).shape(text, 0, length);
-        }
-
-        long bidi = 0;
-        try {
-            bidi = createUBiDi(text, 0, embeddings, 0, length, flags);
-            readBidiInfo(bidi);
-        } finally {
-            ubidi_close(bidi);
-        }
+        this.icuBidi = new com.ibm.icu.text.Bidi(paragraph);
     }
 
     /**
@@ -214,13 +146,11 @@
         if (text == null || text.length - textStart < paragraphLength) {
             throw new IllegalArgumentException();
         }
-
         if (embeddings != null) {
             if (embeddings.length - embStart < paragraphLength) {
                 throw new IllegalArgumentException();
             }
         }
-
         if (textStart < 0) {
             throw new IllegalArgumentException("Negative textStart value " + textStart);
         }
@@ -231,13 +161,9 @@
             throw new IllegalArgumentException("Negative paragraph length " + paragraphLength);
         }
 
-        long bidi = 0;
-        try {
-            bidi = createUBiDi(text, textStart, embeddings, embStart, paragraphLength, flags);
-            readBidiInfo(bidi);
-        } finally {
-            ubidi_close(bidi);
-        }
+        this.icuBidi = new com.ibm.icu.text.Bidi(text, textStart, embeddings, embStart,
+                paragraphLength, translateConstToIcu(flags));
+
     }
 
     /**
@@ -261,109 +187,18 @@
                 (paragraph == null ? 0 : paragraph.length()), flags);
     }
 
-    // create the native UBiDi struct, need to be closed with ubidi_close().
-    private static long createUBiDi(char[] text, int textStart,
-            byte[] embeddings, int embStart, int paragraphLength, int flags) {
-        char[] realText = null;
 
-        byte[] realEmbeddings = null;
-
-        if (text == null || text.length - textStart < paragraphLength) {
-            throw new IllegalArgumentException();
-        }
-        realText = new char[paragraphLength];
-        System.arraycopy(text, textStart, realText, 0, paragraphLength);
-
-        if (embeddings != null) {
-            if (embeddings.length - embStart < paragraphLength) {
-                throw new IllegalArgumentException();
-            }
-            if (paragraphLength > 0) {
-                Bidi temp = new Bidi(text, textStart, null, 0, paragraphLength, flags);
-                realEmbeddings = new byte[paragraphLength];
-                System.arraycopy(temp.offsetLevel, 0, realEmbeddings, 0, paragraphLength);
-                for (int i = 0; i < paragraphLength; i++) {
-                    byte e = embeddings[i];
-                    if (e < 0) {
-                        realEmbeddings[i] = (byte) (UBIDI_LEVEL_OVERRIDE - e);
-                    } else if (e > 0) {
-                        realEmbeddings[i] = e;
-                    } else {
-                        realEmbeddings[i] |= (byte) UBIDI_LEVEL_OVERRIDE;
-                    }
-                }
-            }
-        }
-
-        if (flags > 1 || flags < -2) {
-            flags = 0;
-        }
-
-        long bidi = 0;
-        boolean needsDeletion = true;
-        try {
-            bidi = ubidi_open();
-            ubidi_setPara(bidi, realText, paragraphLength, flags, realEmbeddings);
-            needsDeletion = false;
-        } finally {
-            if (needsDeletion) {
-                ubidi_close(bidi);
-            }
-        }
-        return bidi;
+    private Bidi(com.ibm.icu.text.Bidi icuBidi) {
+        this.icuBidi = icuBidi;
     }
 
-    /* private constructor used by createLineBidi() */
-    private Bidi(long pBidi) {
-        readBidiInfo(pBidi);
-    }
-
-    // read info from the native UBiDi struct
-    private void readBidiInfo(long pBidi) {
-        length = ubidi_getLength(pBidi);
-
-        offsetLevel = (length == 0) ? null : ubidi_getLevels(pBidi);
-
-        baseLevel = ubidi_getParaLevel(pBidi);
-
-        int runCount = ubidi_countRuns(pBidi);
-        if (runCount == 0) {
-            unidirectional = true;
-            runs = null;
-        } else if (runCount < 0) {
-            runs = null;
-        } else {
-            runs = ubidi_getRuns(pBidi);
-
-            // Simplified case for one run which has the base level
-            if (runCount == 1 && runs[0].getLevel() == baseLevel) {
-                unidirectional = true;
-                runs = null;
-            }
-        }
-
-        direction = ubidi_getDirection(pBidi);
-    }
-
-    private int baseLevel;
-
-    private int length;
-
-    private byte[] offsetLevel;
-
-    private Run[] runs;
-
-    private int direction;
-
-    private boolean unidirectional;
-
     /**
      * Returns whether the base level is from left to right.
      *
      * @return true if the base level is from left to right.
      */
     public boolean baseIsLeftToRight() {
-        return baseLevel % 2 == 0 ? true : false;
+        return icuBidi.baseIsLeftToRight();
     }
 
     /**
@@ -382,55 +217,36 @@
      *             than the length of this object's paragraph text.
      */
     public Bidi createLineBidi(int lineStart, int lineLimit) {
-        if (lineStart < 0 || lineLimit < 0 || lineLimit > length || lineStart > lineLimit) {
+        if (lineStart < 0 || lineLimit < 0 || lineLimit > getLength() || lineStart > lineLimit) {
             throw new IllegalArgumentException("Invalid ranges (start=" + lineStart + ", " +
-                    "limit=" + lineLimit + ", length=" + length + ")");
+                    "limit=" + lineLimit + ", length=" + getLength() + ")");
         }
 
-        char[] text = new char[this.length];
-        Arrays.fill(text, 'a');
-        byte[] embeddings = new byte[this.length];
-        for (int i = 0; i < embeddings.length; i++) {
-            embeddings[i] = (byte) -this.offsetLevel[i];
+        // In the special case where the start and end positions are the same, we return a new bidi
+        // instance which is empty. Note that the default constructor for an empty ICU4J bidi
+        // instance is not the same as passing in empty values. This way allows one to call
+        // .getLength() for example and return a correct value instead of an IllegalStateException
+        // being thrown, which happens in the case of using the empty constructor.
+        if (lineStart == lineLimit) {
+            return new Bidi(new com.ibm.icu.text.Bidi(new char[] {}, 0, new byte[] {}, 0, 0,
+                    translateConstToIcu(DIRECTION_LEFT_TO_RIGHT)));
         }
 
-        int dir = this.baseIsLeftToRight()
-                ? Bidi.DIRECTION_LEFT_TO_RIGHT
-                : Bidi.DIRECTION_RIGHT_TO_LEFT;
-        long parent = 0;
-        try {
-            parent = createUBiDi(text, 0, embeddings, 0, this.length, dir);
-            if (lineStart == lineLimit) {
-                return createEmptyLineBidi(parent);
-            }
-            return new Bidi(ubidi_setLine(parent, lineStart, lineLimit));
-        } finally {
-            ubidi_close(parent);
-        }
-    }
-
-    private Bidi createEmptyLineBidi(long parent) {
-        // ICU4C doesn't allow this case, but the RI does.
-        Bidi result = new Bidi(parent);
-        result.length = 0;
-        result.offsetLevel = null;
-        result.runs = null;
-        result.unidirectional = true;
-        return result;
+        return new Bidi(icuBidi.createLineBidi(lineStart, lineLimit));
     }
 
     /**
      * Returns the base level.
      */
     public int getBaseLevel() {
-        return baseLevel;
+        return icuBidi.getBaseLevel();
     }
 
     /**
      * Returns the length of the text.
      */
     public int getLength() {
-        return length;
+        return icuBidi.getLength();
     }
 
     /**
@@ -438,9 +254,9 @@
      */
     public int getLevelAt(int offset) {
         try {
-            return offsetLevel[offset] & ~UBIDI_LEVEL_OVERRIDE;
-        } catch (RuntimeException e) {
-            return baseLevel;
+            return icuBidi.getLevelAt(offset);
+        } catch (IllegalArgumentException e) {
+            return getBaseLevel();
         }
     }
 
@@ -448,28 +264,43 @@
      * Returns the number of runs in the text, at least 1.
      */
     public int getRunCount() {
-        return unidirectional ? 1 : runs.length;
+        return isUnidirectional() ? 1 : icuBidi.getRunCount();
     }
 
     /**
      * Returns the level of the given run.
      */
     public int getRunLevel(int run) {
-        return unidirectional ? baseLevel : runs[run].getLevel();
+        // Paper over a the ICU4J behaviour of strictly enforcing run must be strictly less than
+        // the number of runs. Done to maintain compatibility with previous C implementation.
+        if (run == getRunCount()) {
+            return getBaseLevel();
+        }
+        return isUnidirectional() ? icuBidi.getBaseLevel() : icuBidi.getRunLevel(run);
     }
 
     /**
      * Returns the limit offset of the given run.
      */
     public int getRunLimit(int run) {
-        return unidirectional ? length : runs[run].getLimit();
+        // Paper over a the ICU4J behaviour of strictly enforcing run must be strictly less than
+        // the number of runs. Done to maintain compatibility with previous C implementation.
+        if (run == getRunCount()) {
+            return getBaseLevel();
+        }
+        return isUnidirectional() ? icuBidi.getLength() : icuBidi.getRunLimit(run);
     }
 
     /**
      * Returns the start offset of the given run.
      */
     public int getRunStart(int run) {
-        return unidirectional ? 0 : runs[run].getStart();
+        // Paper over a the ICU4J behaviour of strictly enforcing run must be strictly less than
+        // the number of runs. Done to maintain compatibility with previous C implementation.
+        if (run == getRunCount()) {
+            return getBaseLevel();
+        }
+        return isUnidirectional() ? 0 : icuBidi.getRunStart(run);
     }
 
     /**
@@ -477,14 +308,14 @@
      * direction and the text direction is from left to right.
      */
     public boolean isLeftToRight() {
-        return direction == UBiDiDirection_UBIDI_LTR;
+        return icuBidi.isLeftToRight();
     }
 
     /**
      * Returns true if the text direction is mixed.
      */
     public boolean isMixed() {
-        return direction == UBiDiDirection_UBIDI_MIXED;
+        return icuBidi.isMixed();
     }
 
     /**
@@ -492,7 +323,7 @@
      * direction and the text direction is from right to left.
      */
     public boolean isRightToLeft() {
-        return direction == UBiDiDirection_UBIDI_RTL;
+        return icuBidi.isRightToLeft();
     }
 
     /**
@@ -519,6 +350,7 @@
      */
     public static void reorderVisually(byte[] levels, int levelStart,
             Object[] objects, int objectStart, int count) {
+
         if (count < 0 || levelStart < 0 || objectStart < 0
                 || count > levels.length - levelStart
                 || count > objects.length - objectStart) {
@@ -527,17 +359,7 @@
                     ", objectStart=" + objectStart + ", count=" + count + ")");
         }
 
-        byte[] realLevels = new byte[count];
-        System.arraycopy(levels, levelStart, realLevels, 0, count);
-
-        int[] indices = ubidi_reorderVisual(realLevels, count);
-
-        ArrayList<Object> result = new ArrayList<Object>(count);
-        for (int i = 0; i < count; i++) {
-            result.add(objects[objectStart + indices[i]]);
-        }
-
-        System.arraycopy(result.toArray(), 0, objects, objectStart, count);
+        com.ibm.icu.text.Bidi.reorderVisually(levels, levelStart, objects, objectStart, count);
     }
 
     /**
@@ -562,33 +384,13 @@
             throw new IllegalArgumentException();
         }
 
-        Bidi bidi = new Bidi(text, start, null, 0, limit - start, 0);
-        return !bidi.isLeftToRight();
+        return com.ibm.icu.text.Bidi.requiresBidi(text, start, limit);
     }
 
     @Override
     public String toString() {
         return getClass().getName()
-                + "[direction: " + direction + " baseLevel: " + baseLevel
-                + " length: " + length + " runs: " + Arrays.toString(runs) + "]";
+                + "[direction: " + icuBidi.getDirection() + " baseLevel: " + icuBidi.getBaseLevel()
+                + " length: " + icuBidi.getLength() + " runs: " + icuBidi.getRunCount() + "]";
     }
-
-    // ICU4C constants.
-    private static final int UBIDI_LEVEL_OVERRIDE = 0x80;
-    private static final int UBiDiDirection_UBIDI_LTR = 0;
-    private static final int UBiDiDirection_UBIDI_RTL = 1;
-    private static final int UBiDiDirection_UBIDI_MIXED = 2;
-
-    // ICU4C functions.
-    private static native long ubidi_open();
-    private static native void ubidi_close(long pBiDi);
-    private static native void ubidi_setPara(long pBiDi, char[] text, int length, int paraLevel, byte[] embeddingLevels);
-    private static native long ubidi_setLine(final long pParaBiDi, int start, int limit);
-    private static native int ubidi_getDirection(final long pBiDi);
-    private static native int ubidi_getLength(final long pBiDi);
-    private static native byte ubidi_getParaLevel(final long pBiDi);
-    private static native byte[] ubidi_getLevels(long pBiDi);
-    private static native int ubidi_countRuns(long pBiDi);
-    private static native Bidi.Run[] ubidi_getRuns(long pBidi);
-    private static native int[] ubidi_reorderVisual(byte[] levels, int length);
 }
diff --git a/luni/src/main/java/java/text/Normalizer.java b/luni/src/main/java/java/text/Normalizer.java
index 2e6647e..5355014 100644
--- a/luni/src/main/java/java/text/Normalizer.java
+++ b/luni/src/main/java/java/text/Normalizer.java
@@ -16,8 +16,6 @@
 
 package java.text;
 
-import libcore.icu.NativeNormalizer;
-
 /**
  * Provides normalization functions according to
  * <a href="http://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode Standard Annex #15:
@@ -36,22 +34,32 @@
         /**
          * Normalization Form D - Canonical Decomposition.
          */
-        NFD,
+        NFD(com.ibm.icu.text.Normalizer.NFD),
 
         /**
          * Normalization Form C - Canonical Decomposition, followed by Canonical Composition.
          */
-        NFC,
+        NFC(com.ibm.icu.text.Normalizer.NFC),
 
         /**
          * Normalization Form KD - Compatibility Decomposition.
          */
-        NFKD,
+        NFKD(com.ibm.icu.text.Normalizer.NFKD),
 
         /**
          * Normalization Form KC - Compatibility Decomposition, followed by Canonical Composition.
          */
-        NFKC;
+        NFKC(com.ibm.icu.text.Normalizer.NFKC);
+
+        private final com.ibm.icu.text.Normalizer.Mode icuForm;
+
+        Form(com.ibm.icu.text.Normalizer.Mode icuForm) {
+            this.icuForm = icuForm;
+        }
+
+        com.ibm.icu.text.Normalizer.Mode getIcuForm() {
+            return icuForm;
+        }
     }
 
     /**
@@ -63,7 +71,7 @@
      * @return true if normalized according to <code>form</code>
      */
     public static boolean isNormalized(CharSequence src, Form form) {
-        return NativeNormalizer.isNormalized(src, form);
+        return com.ibm.icu.text.Normalizer.isNormalized(src.toString(), form.getIcuForm(), 0);
     }
 
     /**
@@ -75,7 +83,7 @@
      * @return string normalized according to <code>form</code>
      */
     public static String normalize(CharSequence src, Form form) {
-        return NativeNormalizer.normalize(src, form);
+        return com.ibm.icu.text.Normalizer.normalize(src.toString(), form.getIcuForm());
     }
 
     private Normalizer() {}
diff --git a/luni/src/main/java/java/util/zip/InflaterInputStream.java b/luni/src/main/java/java/util/zip/InflaterInputStream.java
index e5ad3db..a558f34 100644
--- a/luni/src/main/java/java/util/zip/InflaterInputStream.java
+++ b/luni/src/main/java/java/util/zip/InflaterInputStream.java
@@ -193,6 +193,8 @@
         } else {
             if ((len = in.read(buf)) > 0) {
                 inf.setInput(buf, 0, len);
+            } else if (len == -1) {
+                throw new EOFException("Unexpected end of stream.");
             }
         }
     }
diff --git a/luni/src/main/java/java/util/zip/Zip64.java b/luni/src/main/java/java/util/zip/Zip64.java
index 9be3d1c..3060670 100644
--- a/luni/src/main/java/java/util/zip/Zip64.java
+++ b/luni/src/main/java/java/util/zip/Zip64.java
@@ -19,6 +19,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.RandomAccessFile;
+import java.nio.BufferOverflowException;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -37,8 +38,10 @@
 
     /**
      * The maximum supported entry / archive size for standard (non zip64) entries and archives.
+     *
+     * @hide
      */
-    static final long MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE = 0x00000000ffffffffL;
+    public static final long MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE = 0x00000000ffffffffL;
 
     /**
      * The header ID of the zip64 extended info header. This value is used to identify
@@ -46,11 +49,6 @@
      */
     private static final short ZIP64_EXTENDED_INFO_HEADER_ID = 0x0001;
 
-    /**
-     * The minimum size of the zip64 extended info header. This excludes the 2 byte header ID
-     * and the 2 byte size.
-     */
-    private static final int ZIP64_EXTENDED_INFO_MIN_SIZE = 28;
 
     /*
      * Size (in bytes) of the zip64 end of central directory locator. This will be located
@@ -191,35 +189,32 @@
             if (extendedInfoSize != -1) {
                 extendedInfoStart = buf.position();
                 try {
-                    if (extendedInfoSize < ZIP64_EXTENDED_INFO_MIN_SIZE) {
-                        throw new ZipException("Invalid zip64 extended info size: " + extendedInfoSize);
-                    }
-
                     // The size & compressed size only make sense in the central directory *or* if
                     // we know them beforehand. If we don't know them beforehand, they're stored in
                     // the data descriptor and should be read from there.
+                    //
+                    // Note that the spec says that the local file header "MUST" contain the
+                    // original and compressed size fields. We don't care too much about that.
+                    // The spec claims that the order of fields is fixed anyway.
                     if (fromCentralDirectory || (ze.getMethod() == ZipEntry.STORED)) {
-                        final long zip64Size = buf.getLong();
                         if (ze.size == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) {
-                            ze.size = zip64Size;
+                            ze.size = buf.getLong();
                         }
 
-                        final long zip64CompressedSize = buf.getLong();
                         if (ze.compressedSize == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) {
-                            ze.compressedSize = zip64CompressedSize;
+                            ze.compressedSize = buf.getLong();
                         }
                     }
 
                     // The local header offset is significant only in the central directory. It makes no
                     // sense within the local header itself.
                     if (fromCentralDirectory) {
-                        final long zip64LocalHeaderRelOffset = buf.getLong();
                         if (ze.localHeaderRelOffset == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) {
-                            ze.localHeaderRelOffset = zip64LocalHeaderRelOffset;
+                            ze.localHeaderRelOffset = buf.getLong();
                         }
                     }
                 } catch (BufferUnderflowException bue) {
-                    ZipException zipException = new ZipException("Error parsing extendend info ");
+                    ZipException zipException = new ZipException("Error parsing extended info");
                     zipException.initCause(bue);
                     throw zipException;
                 }
@@ -273,8 +268,20 @@
      */
     public static void insertZip64ExtendedInfoToExtras(ZipEntry ze) throws ZipException {
         final byte[] output;
-        // We add 4 to ZIP64_EXTENDED_INFO_MIN_SIZE to account for the 2 byte header and length.
-        final int extendedInfoSize = ZIP64_EXTENDED_INFO_MIN_SIZE + 4;
+        // We always write the size, uncompressed size and local rel header offset in all our
+        // Zip64 extended info headers (in both the local file header as well as the central
+        // directory). We always omit the disk number because we don't support spanned
+        // archives anyway.
+        //
+        //  2 bytes : Zip64 Extended Info Header ID
+        //  2 bytes : Zip64 Extended Info Field Size.
+        //  8 bytes : Uncompressed size
+        //  8 bytes : Compressed size
+        //  8 bytes : Local header rel offset.
+        // ----------
+        // 28 bytes : total
+        final int extendedInfoSize = 28;
+
         if (ze.extra == null) {
             output = new byte[extendedInfoSize];
         } else {
@@ -291,13 +298,15 @@
             // This means that people that for ZipOutputStream users, the value ZipEntry.getExtra
             // after an entry is written will be different from before. This shouldn't be an issue
             // in practice.
-            output = new byte[ze.extra.length + ZIP64_EXTENDED_INFO_MIN_SIZE + 4];
-            System.arraycopy(ze.extra, 0, output,  ZIP64_EXTENDED_INFO_MIN_SIZE + 4, ze.extra.length);
+            output = new byte[ze.extra.length + extendedInfoSize];
+            System.arraycopy(ze.extra, 0, output,  extendedInfoSize, ze.extra.length);
         }
 
         ByteBuffer bb = ByteBuffer.wrap(output).order(ByteOrder.LITTLE_ENDIAN);
         bb.putShort(ZIP64_EXTENDED_INFO_HEADER_ID);
-        bb.putShort((short) ZIP64_EXTENDED_INFO_MIN_SIZE);
+        // We subtract four because extendedInfoSize includes the ID and field
+        // size itself.
+        bb.putShort((short) (extendedInfoSize - 4));
 
         if (ze.getMethod() == ZipEntry.STORED) {
             bb.putLong(ze.size);
@@ -311,7 +320,6 @@
         // The offset is only relevant in the central directory entry, but we write it out here
         // anyway, since we know what it is.
         bb.putLong(ze.localHeaderRelOffset);
-        bb.putInt(0);  //  disk number
 
         ze.extra = output;
     }
@@ -354,23 +362,29 @@
      * we could calculate the correct sizes only after writing out the entry. In this case,
      * the local file header would not contain real sizes, and they would be present in the
      * data descriptor and the central directory only.
+     *
+     * We choose the simplest strategy of always writing out the size, compressedSize and
+     * local header offset in all our Zip64 Extended info records.
      */
     public static void refreshZip64ExtendedInfo(ZipEntry ze) {
-        if (ze.extra == null || ze.extra.length < ZIP64_EXTENDED_INFO_MIN_SIZE) {
+        if (ze.extra == null) {
             throw new IllegalStateException("Zip64 entry has no available extras: " + ze);
         }
 
-
         ByteBuffer buf = ByteBuffer.wrap(ze.extra).order(ByteOrder.LITTLE_ENDIAN);
-        if (getZip64ExtendedInfoSize(buf) == -1) {
+        final int extendedInfoSize = getZip64ExtendedInfoSize(buf);
+        if (extendedInfoSize == -1) {
             throw new IllegalStateException(
                     "Zip64 entry extras has no zip64 extended info record: " + ze);
         }
 
-        buf.putLong(ze.size);
-        buf.putLong(ze.compressedSize);
-        buf.putLong(ze.localHeaderRelOffset);
-        buf.putInt(0); // disk number.
+        try {
+            buf.putLong(ze.size);
+            buf.putLong(ze.compressedSize);
+            buf.putLong(ze.localHeaderRelOffset);
+        } catch (BufferOverflowException boe) {
+            throw new IllegalStateException("Invalid extended info extra", boe);
+        }
     }
 
     public static void writeZip64EocdRecordAndLocator(ByteArrayOutputStream baos,
diff --git a/luni/src/main/java/java/util/zip/ZipEntry.java b/luni/src/main/java/java/util/zip/ZipEntry.java
index 26f6863..a06f1b6 100644
--- a/luni/src/main/java/java/util/zip/ZipEntry.java
+++ b/luni/src/main/java/java/util/zip/ZipEntry.java
@@ -66,7 +66,8 @@
      */
     public static final int STORED = 0;
 
-    ZipEntry(String name, String comment, long crc, long compressedSize,
+    /** @hide - for testing only */
+    public ZipEntry(String name, String comment, long crc, long compressedSize,
             long size, int compressionMethod, int time, int modDate, byte[] extra,
             long localHeaderRelOffset, long dataOffset) {
         this.name = name;
diff --git a/luni/src/main/java/java/util/zip/ZipInputStream.java b/luni/src/main/java/java/util/zip/ZipInputStream.java
index f3ca74e..f254ba2 100644
--- a/luni/src/main/java/java/util/zip/ZipInputStream.java
+++ b/luni/src/main/java/java/util/zip/ZipInputStream.java
@@ -112,7 +112,11 @@
     @Override
     public void close() throws IOException {
         if (!closed) {
-            closeEntry(); // Close the current entry
+            try {
+                closeEntry(); // Close the current entry
+            } catch (IOException ignored) {
+            }
+
             super.close();
         }
     }
diff --git a/luni/src/main/java/java/util/zip/ZipOutputStream.java b/luni/src/main/java/java/util/zip/ZipOutputStream.java
index 7748cfd..dfd85b6 100644
--- a/luni/src/main/java/java/util/zip/ZipOutputStream.java
+++ b/luni/src/main/java/java/util/zip/ZipOutputStream.java
@@ -260,7 +260,11 @@
         writeIntAsUint16(cDir, 0); // Disk Start
         writeIntAsUint16(cDir, 0); // Internal File Attributes
         writeLongAsUint32(cDir, 0); // External File Attributes
-        writeLongAsUint32(cDir, offset);
+        if (currentEntryNeedsZip64) {
+            writeLongAsUint32(cDir, Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE);
+        } else {
+            writeLongAsUint32(cDir, currentEntry.localHeaderRelOffset);
+        }
         cDir.write(nameBytes);
         nameBytes = null;
         if (currentEntry.extra != null) {
diff --git a/luni/src/main/java/javax/crypto/Cipher.java b/luni/src/main/java/javax/crypto/Cipher.java
index 9d6bd22..b27ea88 100644
--- a/luni/src/main/java/javax/crypto/Cipher.java
+++ b/luni/src/main/java/javax/crypto/Cipher.java
@@ -108,6 +108,50 @@
     };
 
     /**
+     * Used to keep track of which underlying {@code CipherSpi#engineInit(...)}
+     * variant to call when testing suitability.
+     */
+    private static enum InitType {
+        KEY, ALGORITHM_PARAMS, ALGORITHM_PARAM_SPEC,
+    };
+
+    /**
+     * Keeps track of the possible arguments to {@code Cipher#init(...)}.
+     */
+    private static class InitParams {
+        private final InitType initType;
+        private final int opmode;
+        private final Key key;
+        private final SecureRandom random;
+        private final AlgorithmParameterSpec spec;
+        private final AlgorithmParameters params;
+
+        private InitParams(InitType initType, int opmode, Key key, SecureRandom random,
+                AlgorithmParameterSpec spec, AlgorithmParameters params) {
+            this.initType = initType;
+            this.opmode = opmode;
+            this.key = key;
+            this.random = random;
+            this.spec = spec;
+            this.params = params;
+        }
+    }
+
+    /**
+     * Expresses the various types of transforms that may be used during
+     * initialization.
+     */
+    private static class Transform {
+        private final String name;
+        private final NeedToSet needToSet;
+
+        public Transform(String name, NeedToSet needToSet) {
+            this.name = name;
+            this.needToSet = needToSet;
+        }
+    }
+
+    /**
      * The service name.
      */
     private static final String SERVICE = "Cipher";
@@ -298,14 +342,15 @@
 
         String[] transformParts = checkTransformation(transformation);
 
-        boolean providerSupportsAlgorithm;
+        Engine.SpiAndProvider sap;
         try {
-            providerSupportsAlgorithm =
-                    tryCombinations(null /* key */, provider, transformParts) != null;
-        } catch (InvalidKeyException e) {
-            throw new IllegalStateException("InvalidKeyException thrown when key == null", e);
+            sap = tryCombinations(null /* params */, provider, transformation, transformParts);
+        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
+            // should never happen since we passed in null params
+            throw new ProviderException(e);
         }
-        if (!providerSupportsAlgorithm) {
+
+        if (sap == null) {
             if (provider == null) {
                 throw new NoSuchAlgorithmException("No provider found for " + transformation);
             } else {
@@ -316,6 +361,25 @@
         return new Cipher(transformation, transformParts, provider);
     }
 
+    /**
+     * Checks that the provided algorithm {@code transformation} string is a
+     * valid input. The algorithm is the only mandatory field and input can be
+     * of the form:
+     * <ul>
+     * <li><code>"[cipher]"</code>
+     * <li><code>"[cipher]/[mode]/[padding]"</code>
+     * <li><code>"[cipher]//[padding]"</code>
+     * <li><code>"[cipher]/[mode]"</code>
+     * </ul>
+     * <p>
+     * Returns the specified transformation split up into three parts
+     * corresponding to their function:
+     * <p>
+     * <code>
+     * {&lt;algorithm&gt;, &lt;mode&gt;, &lt;padding&gt;}
+     * </code>
+     * <p>
+     */
     private static String[] checkTransformation(String transformation)
             throws NoSuchAlgorithmException {
         // ignore an extra prefix / characters such as in
@@ -347,25 +411,33 @@
     }
 
     /**
-     * Makes sure a CipherSpi that matches this type is selected.
+     * Makes sure a CipherSpi that matches this type is selected. If
+     * {@code key != null} then it assumes that a suitable provider exists for
+     * this instance (used by {@link #init}. If the {@code initParams} is passed
+     * in, then the {@code CipherSpi} returned will be initialized.
      *
      * @throws InvalidKeyException if the specified key cannot be used to
      *             initialize this cipher.
+     * @throws InvalidAlgorithmParameterException
      */
-    private CipherSpi getSpi(Key key) throws InvalidKeyException {
+    private CipherSpi getSpi(InitParams initParams) throws InvalidKeyException,
+            InvalidAlgorithmParameterException {
         if (specifiedSpi != null) {
             return specifiedSpi;
         }
 
         synchronized (initLock) {
-            if (spiImpl != null && key == null) {
+            // This is not only a matter of performance. Many methods like update, doFinal, etc.
+            // call {@code #getSpi()} (ie, {@code #getSpi(null /* params */)}) and without this
+            // shortcut they would override an spi that was chosen using the key.
+            if (spiImpl != null && initParams == null) {
                 return spiImpl;
             }
 
-            final Engine.SpiAndProvider sap = tryCombinations(
-                    key, specifiedProvider, transformParts);
+            final Engine.SpiAndProvider sap = tryCombinations(initParams, specifiedProvider,
+                    transformation, transformParts);
             if (sap == null) {
-                throw new ProviderException("No provider for " + transformation);
+                throw new ProviderException("No provider found for " + transformation);
             }
 
             spiImpl = (CipherSpi) sap.spi;
@@ -381,8 +453,8 @@
     private CipherSpi getSpi() {
         try {
             return getSpi(null);
-        } catch (InvalidKeyException e) {
-            throw new IllegalStateException("InvalidKeyException thrown when key == null", e);
+        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
+            throw new ProviderException("Exception thrown when params == null", e);
         }
     }
 
@@ -403,84 +475,105 @@
     }
 
     /**
-     * Try all combinations of mode strings:
-     *
-     * <pre>
-     *   [cipher]/[mode]/[padding]
-     *   [cipher]/[mode]
-     *   [cipher]//[padding]
-     *   [cipher]
-     * </pre>
-     *
-     * @throws InvalidKeyException if the specified key cannot be used to
-     *             initialize any provider.
+     * Tries to find the correct {@code Cipher} transform to use. Returns a
+     * {@link Engine.SpiAndProvider}, throws the first exception that was
+     * encountered during attempted initialization, or {@code null} if there are
+     * no providers that support the {@code initParams}.
+     * <p>
+     * {@code transformParts} must be in the format returned by
+     * {@link #checkTransformation(String)}. The combinations of mode strings
+     * tried are as follows:
+     * <ul>
+     * <li><code>[cipher]/[mode]/[padding]</code>
+     * <li><code>[cipher]/[mode]</code>
+     * <li><code>[cipher]//[padding]</code>
+     * <li><code>[cipher]</code>
+     * </ul>
      */
-    private static Engine.SpiAndProvider tryCombinations(Key key, Provider provider,
-            String[] transformParts) throws InvalidKeyException {
-        Engine.SpiAndProvider sap = null;
-
+    private static Engine.SpiAndProvider tryCombinations(InitParams initParams, Provider provider,
+            String transformation, String[] transformParts) throws InvalidKeyException,
+            InvalidAlgorithmParameterException {
+        // Enumerate all the transforms we need to try
+        ArrayList<Transform> transforms = new ArrayList<Transform>();
         if (transformParts[1] != null && transformParts[2] != null) {
-            sap = tryTransform(key, provider, transformParts[0] + "/" + transformParts[1] + "/"
-                    + transformParts[2], transformParts, NeedToSet.NONE);
-            if (sap != null) {
-                return sap;
-            }
+            transforms.add(new Transform(transformParts[0] + "/" + transformParts[1] + "/"
+                    + transformParts[2], NeedToSet.NONE));
         }
-
         if (transformParts[1] != null) {
-            sap = tryTransform(key, provider, transformParts[0] + "/" + transformParts[1],
-                    transformParts, NeedToSet.PADDING);
-            if (sap != null) {
-                return sap;
-            }
+            transforms.add(new Transform(transformParts[0] + "/" + transformParts[1],
+                    NeedToSet.PADDING));
         }
-
         if (transformParts[2] != null) {
-            sap = tryTransform(key, provider, transformParts[0] + "//" + transformParts[2],
-                    transformParts, NeedToSet.MODE);
-            if (sap != null) {
-                return sap;
-            }
+            transforms.add(new Transform(transformParts[0] + "//" + transformParts[2],
+                    NeedToSet.MODE));
         }
+        transforms.add(new Transform(transformParts[0], NeedToSet.BOTH));
 
-        return tryTransform(key, provider, transformParts[0], transformParts, NeedToSet.BOTH);
-    }
-
-    /**
-     * @throws InvalidKeyException if the specified key cannot be used to
-     *             initialize this cipher.
-     */
-    private static Engine.SpiAndProvider tryTransform(Key key, Provider provider, String transform,
-            String[] transformParts, NeedToSet type) throws InvalidKeyException {
-        if (provider != null) {
-            Provider.Service service = provider.getService(SERVICE, transform);
-            if (service == null) {
-                return null;
+        // Try each of the transforms and keep track of the first exception
+        // encountered.
+        Exception cause = null;
+        for (Transform transform : transforms) {
+            if (provider != null) {
+                Provider.Service service = provider.getService(SERVICE, transform.name);
+                if (service == null) {
+                    continue;
+                }
+                return tryTransformWithProvider(initParams, transformParts, transform.needToSet,
+                        service);
             }
-            return tryTransformWithProvider(transformParts, type, service);
-        }
-        ArrayList<Provider.Service> services = ENGINE.getServices(transform);
-        if (services == null || services.isEmpty()) {
-            return null;
-        }
-        boolean keySupported = false;
-        for (Provider.Service service : services) {
-            if (key == null || service.supportsParameter(key)) {
-                keySupported = true;
-                Engine.SpiAndProvider sap = tryTransformWithProvider(transformParts, type, service);
-                if (sap != null) {
-                    return sap;
+            ArrayList<Provider.Service> services = ENGINE.getServices(transform.name);
+            if (services == null || services.isEmpty()) {
+                continue;
+            }
+            for (Provider.Service service : services) {
+                if (initParams == null || initParams.key == null
+                        || service.supportsParameter(initParams.key)) {
+                    try {
+                        Engine.SpiAndProvider sap = tryTransformWithProvider(initParams,
+                                transformParts, transform.needToSet, service);
+                        if (sap != null) {
+                            return sap;
+                        }
+                    } catch (Exception e) {
+                        if (cause == null) {
+                            cause = e;
+                        }
+                    }
                 }
             }
         }
-        if (!keySupported) {
-            throw new InvalidKeyException("No provider supports the provided key");
+        if (cause instanceof InvalidKeyException) {
+            throw (InvalidKeyException) cause;
+        } else if (cause instanceof InvalidAlgorithmParameterException) {
+            throw (InvalidAlgorithmParameterException) cause;
+        } else if (cause instanceof RuntimeException) {
+            throw (RuntimeException) cause;
+        } else if (cause != null) {
+            throw new InvalidKeyException("No provider can be initialized with given key", cause);
+        } else if (initParams == null || initParams.key == null) {
+            return null;
+        } else {
+            // Since the key is not null, a suitable provider exists,
+            // and it is an InvalidKeyException.
+            throw new InvalidKeyException("No provider offers " + transformation + " for "
+                    + initParams.key.getAlgorithm() + " key of class "
+                    + initParams.key.getClass().getName() + " and export format "
+                    + initParams.key.getFormat());
         }
-        return null;
     }
 
-    private static Engine.SpiAndProvider tryTransformWithProvider(String[] transformParts,
-            NeedToSet type, Provider.Service service) {
+    /**
+     * Tries to initialize the {@code Cipher} from a given {@code service}. If
+     * initialization is successful, the initialized {@code spi} is returned. If
+     * the {@code service} cannot be initialized with the specified
+     * {@code initParams}, then it's expected to throw
+     * {@code InvalidKeyException} or {@code InvalidAlgorithmParameterException}
+     * as a hint to the caller that it should continue searching for a
+     * {@code Service} that will work.
+     */
+    private static Engine.SpiAndProvider tryTransformWithProvider(InitParams initParams,
+            String[] transformParts, NeedToSet type, Provider.Service service)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
         try {
             /*
              * Check to see if the Cipher even supports the attributes before
@@ -495,9 +588,6 @@
             if (sap.spi == null || sap.provider == null) {
                 return null;
             }
-            if (!(sap.spi instanceof CipherSpi)) {
-                return null;
-            }
             CipherSpi spi = (CipherSpi) sap.spi;
             if (((type == NeedToSet.MODE) || (type == NeedToSet.BOTH))
                     && (transformParts[1] != null)) {
@@ -507,6 +597,24 @@
                     && (transformParts[2] != null)) {
                 spi.engineSetPadding(transformParts[2]);
             }
+
+            if (initParams != null) {
+                switch (initParams.initType) {
+                    case ALGORITHM_PARAMS:
+                        spi.engineInit(initParams.opmode, initParams.key, initParams.params,
+                                initParams.random);
+                        break;
+                    case ALGORITHM_PARAM_SPEC:
+                        spi.engineInit(initParams.opmode, initParams.key, initParams.spec,
+                                initParams.random);
+                        break;
+                    case KEY:
+                        spi.engineInit(initParams.opmode, initParams.key, initParams.random);
+                        break;
+                    default:
+                        throw new AssertionError("This should never be reached");
+                }
+            }
             return sap;
         } catch (NoSuchAlgorithmException ignored) {
         } catch (NoSuchPaddingException ignored) {
@@ -618,6 +726,10 @@
 
     }
 
+    /**
+     * Checks that the provided {@code mode} is one that is valid for
+     * {@code Cipher}.
+     */
     private void checkMode(int mode) {
         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE && mode != UNWRAP_MODE
                 && mode != WRAP_MODE) {
@@ -699,7 +811,12 @@
         //        FIXME InvalidKeyException
         //        if keysize exceeds the maximum allowable keysize
         //        (jurisdiction policy files)
-        getSpi(key).engineInit(opmode, key, random);
+        try {
+            getSpi(new InitParams(InitType.KEY, opmode, key, random, null, null));
+        } catch (InvalidAlgorithmParameterException e) {
+            // Should never happen since we only specified the key.
+            throw new ProviderException("Invalid parameters when params == null", e);
+        }
         mode = opmode;
     }
 
@@ -789,7 +906,7 @@
         //        FIXME InvalidAlgorithmParameterException
         //        cryptographic strength exceed the legal limits
         //        (jurisdiction policy files)
-        getSpi(key).engineInit(opmode, key, params, random);
+        getSpi(new InitParams(InitType.ALGORITHM_PARAM_SPEC, opmode, key, random, params, null));
         mode = opmode;
     }
 
@@ -880,7 +997,7 @@
         //        FIXME InvalidAlgorithmParameterException
         //        cryptographic strength exceed the legal limits
         //        (jurisdiction policy files)
-        getSpi(key).engineInit(opmode, key, params, random);
+        getSpi(new InitParams(InitType.ALGORITHM_PARAMS, opmode, key, random, null, params));
         mode = opmode;
     }
 
@@ -1005,7 +1122,12 @@
         //        if keysize exceeds the maximum allowable keysize
         //        (jurisdiction policy files)
         final Key key = certificate.getPublicKey();
-        getSpi(key).engineInit(opmode, key, random);
+        try {
+            getSpi(new InitParams(InitType.KEY, opmode, key, random, null, null));
+        } catch (InvalidAlgorithmParameterException e) {
+            // Should never happen since we only specified the key.
+            throw new ProviderException("Invalid parameters when params == null", e);
+        }
         mode = opmode;
     }
 
diff --git a/luni/src/main/java/libcore/icu/AlphabeticIndex.java b/luni/src/main/java/libcore/icu/AlphabeticIndex.java
deleted file mode 100644
index 322384d..0000000
--- a/luni/src/main/java/libcore/icu/AlphabeticIndex.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2013 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.icu;
-
-import java.util.Locale;
-
-/**
- * Exposes icu4c's AlphabeticIndex.
- */
-public final class AlphabeticIndex {
-
-  /**
-   * Exposes icu4c's ImmutableIndex (new to icu 51). This exposes a read-only,
-   * thread safe snapshot view of an AlphabeticIndex at the moment it was
-   * created, and allows for random access to buckets by index.
-   */
-  public static final class ImmutableIndex {
-    private long peer;
-
-    private ImmutableIndex(long peer) {
-      this.peer = peer;
-    }
-
-    @Override protected synchronized void finalize() throws Throwable {
-      try {
-        destroy(peer);
-        peer = 0;
-      } finally {
-        super.finalize();
-      }
-    }
-
-    /**
-     * Returns the number of the label buckets in this index.
-     */
-    public int getBucketCount() {
-      return getBucketCount(peer);
-    }
-
-    /**
-     * Returns the index of the bucket in which 's' should appear.
-     * Function is synchronized because underlying routine walks an iterator
-     * whose state is maintained inside the index object.
-     */
-    public int getBucketIndex(String s) {
-      return getBucketIndex(peer, s);
-    }
-
-    /**
-     * Returns the label for the bucket at the given index (as returned by getBucketIndex).
-     */
-    public String getBucketLabel(int index) {
-      return getBucketLabel(peer, index);
-    }
-
-    private static native int getBucketCount(long peer);
-    private static native int getBucketIndex(long peer, String s);
-    private static native String getBucketLabel(long peer, int index);
-  }
-
-  private long peer;
-
-  /**
-   * Creates a new AlphabeticIndex for the given locale.
-   */
-  public AlphabeticIndex(Locale locale) {
-    peer = create(locale.toString());
-  }
-
-  @Override protected synchronized void finalize() throws Throwable {
-    try {
-      destroy(peer);
-      peer = 0;
-    } finally {
-      super.finalize();
-    }
-  }
-
-  /**
-   * Returns the max number of the label buckets allowed in this index.
-   */
-  public synchronized int getMaxLabelCount() {
-    return getMaxLabelCount(peer);
-  }
-
-  /**
-   * Sets the max number of the label buckets in this index.
-   * (ICU 51 default is 99)
-   */
-  public synchronized AlphabeticIndex setMaxLabelCount(int count) {
-    setMaxLabelCount(peer, count);
-    return this;
-  }
-
-  /**
-   * Adds the index characters from the given locale to the index.
-   * The labels are added to those that are already in the index;
-   * they do not replace the existing index characters.
-   * The collation order for this index is not changed;
-   * it remains that of the locale that was originally specified
-   * when creating this index.
-   */
-  public synchronized AlphabeticIndex addLabels(Locale locale) {
-    addLabels(peer, locale.toString());
-    return this;
-  }
-
-  /**
-   * Adds the index characters in the range between the specified start and
-   * end code points, inclusive.
-   */
-  public synchronized AlphabeticIndex addLabelRange(int codePointStart, int codePointEnd) {
-    addLabelRange(peer, codePointStart, codePointEnd);
-    return this;
-  }
-
-  /**
-   * Returns the number of the label buckets in this index.
-   */
-  public synchronized int getBucketCount() {
-    return getBucketCount(peer);
-  }
-
-  /**
-   * Returns the index of the bucket in which 's' should appear.
-   * Function is synchronized because underlying routine walks an iterator
-   * whose state is maintained inside the index object.
-   */
-  public synchronized int getBucketIndex(String s) {
-    return getBucketIndex(peer, s);
-  }
-
-  /**
-   * Returns the label for the bucket at the given index (as returned by getBucketIndex).
-   */
-  public synchronized String getBucketLabel(int index) {
-    return getBucketLabel(peer, index);
-  }
-
-  /**
-   * Returns an ImmutableIndex created from this AlphabeticIndex.
-   */
-  public synchronized ImmutableIndex getImmutableIndex() {
-    return new ImmutableIndex(buildImmutableIndex(peer));
-  }
-
-  private static native long create(String locale);
-  private static native void destroy(long peer);
-  private static native int getMaxLabelCount(long peer);
-  private static native void setMaxLabelCount(long peer, int count);
-  private static native void addLabels(long peer, String locale);
-  private static native void addLabelRange(long peer, int codePointStart, int codePointEnd);
-  private static native int getBucketCount(long peer);
-  private static native int getBucketIndex(long peer, String s);
-  private static native String getBucketLabel(long peer, int index);
-  private static native long buildImmutableIndex(long peer);
-}
diff --git a/luni/src/main/java/libcore/icu/NativeIDN.java b/luni/src/main/java/libcore/icu/NativeIDN.java
deleted file mode 100644
index db93379..0000000
--- a/luni/src/main/java/libcore/icu/NativeIDN.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2010 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.icu;
-
-public final class NativeIDN {
-    public static String toASCII(String s, int flags) {
-        return convert(s, flags, true);
-    }
-
-    public static String toUnicode(String s, int flags) {
-        try {
-            return convert(s, flags, false);
-        } catch (IllegalArgumentException ex) {
-            // The RI documentation explicitly states that this method can't fail.
-            // ICU4C disagrees, as does the RI in practice.
-            // The RI just returns the input string if it can't
-            return s;
-        }
-    }
-
-    private static String convert(String s, int flags, boolean toAscii) {
-        if (s == null) {
-            throw new NullPointerException("s == null");
-        }
-        return convertImpl(s, flags, toAscii);
-    }
-    private static native String convertImpl(String s, int flags, boolean toAscii);
-
-    private NativeIDN() {}
-}
diff --git a/luni/src/main/java/libcore/icu/NativeNormalizer.java b/luni/src/main/java/libcore/icu/NativeNormalizer.java
deleted file mode 100644
index a5d8da2..0000000
--- a/luni/src/main/java/libcore/icu/NativeNormalizer.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2010 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.icu;
-
-import java.text.Normalizer.Form;
-
-public final class NativeNormalizer {
-    public static boolean isNormalized(CharSequence src, Form form) {
-        return isNormalizedImpl(src.toString(), toUNormalizationMode(form));
-    }
-
-    public static String normalize(CharSequence src, Form form) {
-        return normalizeImpl(src.toString(), toUNormalizationMode(form));
-    }
-
-    private static int toUNormalizationMode(Form form) {
-        // Translates Java enum constants to ICU int constants.
-        // See UNormalizationMode in "unicode/unorm.h". Stable API since ICU 2.0.
-        switch (form) {
-        case NFC: return 4;
-        case NFD: return 2;
-        case NFKC: return 5;
-        case NFKD: return 3;
-        }
-        throw new AssertionError("unknown Normalizer.Form " + form);
-    }
-
-    private static native String normalizeImpl(String src, int form);
-
-    private static native boolean isNormalizedImpl(String src, int form);
-
-    private NativeNormalizer() {}
-}
diff --git a/luni/src/main/java/libcore/icu/NativePluralRules.java b/luni/src/main/java/libcore/icu/NativePluralRules.java
deleted file mode 100644
index f9fe74b..0000000
--- a/luni/src/main/java/libcore/icu/NativePluralRules.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2010 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.icu;
-
-import java.util.Locale;
-
-/**
- * Provides access to ICU's
- * <a href="http://icu-project.org/apiref/icu4c/classPluralRules.html">PluralRules</a> class.
- * This is not necessary for Java API, but is used by frameworks/base's resources system to
- * ease localization of strings to languages with complex grammatical rules regarding number.
- */
-public final class NativePluralRules {
-    public static final int ZERO  = 0;
-    public static final int ONE   = 1;
-    public static final int TWO   = 2;
-    public static final int FEW   = 3;
-    public static final int MANY  = 4;
-    public static final int OTHER = 5;
-
-    private final long address;
-
-    private NativePluralRules(long address) {
-        this.address = address;
-    }
-
-    @Override protected void finalize() throws Throwable {
-        try {
-            finalizeImpl(address);
-        } finally {
-            super.finalize();
-        }
-    }
-
-    public static NativePluralRules forLocale(Locale locale) {
-        return new NativePluralRules(forLocaleImpl(locale.toString()));
-    }
-
-    /**
-     * Returns the constant defined in this class corresponding
-     * to the first rule that matches the given value.
-     */
-    public int quantityForInt(int value) {
-        // Pre-L compatibility. http://b/18429565.
-        if (value < 0) {
-            return OTHER;
-        }
-        return quantityForIntImpl(address, value);
-    }
-
-    private static native void finalizeImpl(long address);
-    private static native long forLocaleImpl(String localeName);
-    private static native int quantityForIntImpl(long address, int value);
-}
diff --git a/luni/src/main/java/libcore/icu/Transliterator.java b/luni/src/main/java/libcore/icu/Transliterator.java
deleted file mode 100644
index 77b5ba7..0000000
--- a/luni/src/main/java/libcore/icu/Transliterator.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2013 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.icu;
-
-/**
- * Exposes icu4c's Transliterator.
- */
-public final class Transliterator {
-  private long peer;
-
-  /**
-   * Creates a new Transliterator for the given id.
-   */
-  public Transliterator(String id) {
-    peer = create(id);
-  }
-
-  @Override protected synchronized void finalize() throws Throwable {
-    try {
-      destroy(peer);
-      peer = 0;
-    } finally {
-      super.finalize();
-    }
-  }
-
-  /**
-   * Returns the ids of all known transliterators.
-   */
-  public static native String[] getAvailableIDs();
-
-  /**
-   * Transliterates the specified string.
-   */
-  public String transliterate(String s) {
-    return transliterate(peer, s);
-  }
-
-  private static native long create(String id);
-  private static native void destroy(long peer);
-  private static native String transliterate(long peer, String s);
-}
diff --git a/luni/src/main/java/libcore/io/BlockGuardOs.java b/luni/src/main/java/libcore/io/BlockGuardOs.java
index 532493a..0923c85 100644
--- a/luni/src/main/java/libcore/io/BlockGuardOs.java
+++ b/luni/src/main/java/libcore/io/BlockGuardOs.java
@@ -28,6 +28,7 @@
 import java.io.InterruptedIOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.SocketAddress;
 import java.net.SocketException;
 import java.nio.ByteBuffer;
 import static android.system.OsConstants.*;
@@ -58,7 +59,7 @@
         }
     }
 
-    @Override public FileDescriptor accept(FileDescriptor fd, InetSocketAddress peerAddress) throws ErrnoException, SocketException {
+    @Override public FileDescriptor accept(FileDescriptor fd, SocketAddress peerAddress) throws ErrnoException, SocketException {
         BlockGuard.getThreadPolicy().onNetwork();
         return tagSocket(os.accept(fd, peerAddress));
     }
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index 5c0c8fd..2dfb418 100644
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -50,7 +50,7 @@
         this.os = os;
     }
 
-    public FileDescriptor accept(FileDescriptor fd, InetSocketAddress peerAddress) throws ErrnoException, SocketException { return os.accept(fd, peerAddress); }
+    public FileDescriptor accept(FileDescriptor fd, SocketAddress peerAddress) throws ErrnoException, SocketException { return os.accept(fd, peerAddress); }
     public boolean access(String path, int mode) throws ErrnoException { return os.access(path, mode); }
     public InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException { return os.android_getaddrinfo(node, hints, netId); }
     public void bind(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException { os.bind(fd, address, port); }
@@ -96,6 +96,7 @@
     public StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptUcred(fd, level, option); }
     public int gettid() { return os.gettid(); }
     public int getuid() { return os.getuid(); }
+    public int getxattr(String path, String name, byte[] outValue) throws ErrnoException { return os.getxattr(path, name, outValue); }
     public String if_indextoname(int index) { return os.if_indextoname(index); }
     public InetAddress inet_pton(int family, String address) { return os.inet_pton(family, address); }
     public InetAddress ioctlInetAddress(FileDescriptor fd, int cmd, String interfaceName) throws ErrnoException { return os.ioctlInetAddress(fd, cmd, interfaceName); }
@@ -131,6 +132,7 @@
     public int recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException { return os.recvfrom(fd, buffer, flags, srcAddress); }
     public int recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException { return os.recvfrom(fd, bytes, byteOffset, byteCount, flags, srcAddress); }
     public void remove(String path) throws ErrnoException { os.remove(path); }
+    public void removexattr(String path, String name) throws ErrnoException { os.removexattr(path, name); }
     public void rename(String oldPath, String newPath) throws ErrnoException { os.rename(oldPath, newPath); }
     public long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset, long byteCount) throws ErrnoException { return os.sendfile(outFd, inFd, inOffset, byteCount); }
     public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException { return os.sendto(fd, buffer, flags, inetAddress, port); }
@@ -153,6 +155,7 @@
     public void setsockoptLinger(FileDescriptor fd, int level, int option, StructLinger value) throws ErrnoException { os.setsockoptLinger(fd, level, option, value); }
     public void setsockoptTimeval(FileDescriptor fd, int level, int option, StructTimeval value) throws ErrnoException { os.setsockoptTimeval(fd, level, option, value); }
     public void setuid(int uid) throws ErrnoException { os.setuid(uid); }
+    public void setxattr(String path, String name, byte[] value, int flags) throws ErrnoException { os.setxattr(path, name, value, flags); }
     public void shutdown(FileDescriptor fd, int how) throws ErrnoException { os.shutdown(fd, how); }
     public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException { return os.socket(domain, type, protocol); }
     public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException { os.socketpair(domain, type, protocol, fd1, fd2); }
@@ -166,6 +169,7 @@
     public void tcsendbreak(FileDescriptor fd, int duration) throws ErrnoException { os.tcsendbreak(fd, duration); }
     public int umask(int mask) { return os.umask(mask); }
     public StructUtsname uname() { return os.uname(); }
+    public void unlink(String pathname) throws ErrnoException { os.unlink(pathname); }
     public void unsetenv(String name) throws ErrnoException { os.unsetenv(name); }
     public int waitpid(int pid, MutableInt status, int options) throws ErrnoException { return os.waitpid(pid, status, options); }
     public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException { return os.write(fd, buffer); }
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index 987d331..3cae357 100644
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -41,7 +41,7 @@
 import java.nio.ByteBuffer;
 
 public interface Os {
-    public FileDescriptor accept(FileDescriptor fd, InetSocketAddress peerAddress) throws ErrnoException, SocketException;
+    public FileDescriptor accept(FileDescriptor fd, SocketAddress peerAddress) throws ErrnoException, SocketException;
     public boolean access(String path, int mode) throws ErrnoException;
     public InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException;
     public void bind(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException;
@@ -88,6 +88,7 @@
     public StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException;
     public int gettid();
     public int getuid();
+    public int getxattr(String path, String name, byte[] outValue) throws ErrnoException;
     public String if_indextoname(int index);
     public InetAddress inet_pton(int family, String address);
     public InetAddress ioctlInetAddress(FileDescriptor fd, int cmd, String interfaceName) throws ErrnoException;
@@ -124,6 +125,7 @@
     public int recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException;
     public int recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException;
     public void remove(String path) throws ErrnoException;
+    public void removexattr(String path, String name) throws ErrnoException;
     public void rename(String oldPath, String newPath) throws ErrnoException;
     public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException;
     public int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException;
@@ -146,6 +148,7 @@
     public void setsockoptLinger(FileDescriptor fd, int level, int option, StructLinger value) throws ErrnoException;
     public void setsockoptTimeval(FileDescriptor fd, int level, int option, StructTimeval value) throws ErrnoException;
     public void setuid(int uid) throws ErrnoException;
+    public void setxattr(String path, String name, byte[] value, int flags) throws ErrnoException;
     public void shutdown(FileDescriptor fd, int how) throws ErrnoException;
     public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException;
     public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException;
@@ -159,6 +162,7 @@
     public void tcsendbreak(FileDescriptor fd, int duration) throws ErrnoException;
     public int umask(int mask);
     public StructUtsname uname();
+    public void unlink(String pathname) throws ErrnoException;
     public void unsetenv(String name) throws ErrnoException;
     public int waitpid(int pid, MutableInt status, int options) throws ErrnoException;
     public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException;
diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java
index d680200..b8bbc85 100644
--- a/luni/src/main/java/libcore/io/Posix.java
+++ b/luni/src/main/java/libcore/io/Posix.java
@@ -44,7 +44,7 @@
 public final class Posix implements Os {
     Posix() { }
 
-    public native FileDescriptor accept(FileDescriptor fd, InetSocketAddress peerAddress) throws ErrnoException, SocketException;
+    public native FileDescriptor accept(FileDescriptor fd, SocketAddress peerAddress) throws ErrnoException, SocketException;
     public native boolean access(String path, int mode) throws ErrnoException;
     public native InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException;
     public native void bind(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException;
@@ -90,6 +90,7 @@
     public native StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException;
     public native int gettid();
     public native int getuid();
+    public native int getxattr(String path, String name, byte[] outValue) throws ErrnoException;
     public native String if_indextoname(int index);
     public native InetAddress inet_pton(int family, String address);
     public native InetAddress ioctlInetAddress(FileDescriptor fd, int cmd, String interfaceName) throws ErrnoException;
@@ -189,6 +190,7 @@
     }
     private native int recvfromBytes(FileDescriptor fd, Object buffer, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException;
     public native void remove(String path) throws ErrnoException;
+    public native void removexattr(String path, String name) throws ErrnoException;
     public native void rename(String oldPath, String newPath) throws ErrnoException;
     public native long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset, long byteCount) throws ErrnoException;
     public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException {
@@ -230,6 +232,7 @@
     public native void setsockoptLinger(FileDescriptor fd, int level, int option, StructLinger value) throws ErrnoException;
     public native void setsockoptTimeval(FileDescriptor fd, int level, int option, StructTimeval value) throws ErrnoException;
     public native void setuid(int uid) throws ErrnoException;
+    public native void setxattr(String path, String name, byte[] value, int flags) throws ErrnoException;
     public native void shutdown(FileDescriptor fd, int how) throws ErrnoException;
     public native FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException;
     public native void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException;
@@ -249,6 +252,7 @@
     }
     private native int umaskImpl(int mask);
     public native StructUtsname uname();
+    public native void unlink(String pathname) throws ErrnoException;
     public native void unsetenv(String name) throws ErrnoException;
     public native int waitpid(int pid, MutableInt status, int options) throws ErrnoException;
     public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException {
diff --git a/luni/src/main/java/org/apache/harmony/security/PrivateKeyImpl.java b/luni/src/main/java/org/apache/harmony/security/PrivateKeyImpl.java
deleted file mode 100644
index 47aceb3..0000000
--- a/luni/src/main/java/org/apache/harmony/security/PrivateKeyImpl.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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 org.apache.harmony.security;
-
-import java.security.PrivateKey;
-
-/**
- * PrivateKeyImpl
- */
-public class PrivateKeyImpl implements PrivateKey {
-
-    /*
-     * @serial
-     */
-    private static final long serialVersionUID = 7776497482533790279L;
-
-    private String algorithm;
-
-    private byte[] encoding;
-
-    public PrivateKeyImpl(String algorithm) {
-        this.algorithm = algorithm;
-    }
-
-    public String getAlgorithm() {
-        return algorithm;
-    }
-
-    public String getFormat() {
-        return "PKCS#8";
-    }
-
-    public byte[] getEncoded() {
-
-        byte[] toReturn = new byte[encoding.length];
-        System.arraycopy(encoding, 0, toReturn, 0, encoding.length);
-
-        return toReturn;
-    }
-
-    public void setAlgorithm(String algorithm) {
-        this.algorithm = algorithm;
-    }
-
-    public void setEncoding(byte[] encoding) {
-        this.encoding = new byte[encoding.length];
-        System.arraycopy(encoding, 0, this.encoding, 0, encoding.length);
-    }
-
-}
diff --git a/luni/src/main/java/org/apache/harmony/security/PublicKeyImpl.java b/luni/src/main/java/org/apache/harmony/security/PublicKeyImpl.java
deleted file mode 100644
index dccc72d..0000000
--- a/luni/src/main/java/org/apache/harmony/security/PublicKeyImpl.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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 org.apache.harmony.security;
-
-import java.security.PublicKey;
-
-
-/**
- * PublicKeyImpl
- */
-public class PublicKeyImpl implements PublicKey {
-
-    /**
-     * @serial
-     */
-    private static final long serialVersionUID = 7179022516819534075L;
-
-
-    private byte[] encoding;
-
-    private String algorithm;
-
-
-    public PublicKeyImpl(String algorithm) {
-        this.algorithm = algorithm;
-    }
-
-
-    public String getAlgorithm() {
-        return algorithm;
-    }
-
-
-    public String getFormat() {
-        return "X.509";
-    }
-
-
-    public byte[] getEncoded() {
-        byte[] result = new byte[encoding.length];
-        System.arraycopy(encoding, 0, result, 0, encoding.length);
-        return result;
-    }
-
-
-    public void setAlgorithm(String algorithm) {
-        this.algorithm = algorithm;
-    }
-
-
-    public void setEncoding(byte[] encoding) {
-        this.encoding = new byte[encoding.length];
-        System.arraycopy(encoding, 0, this.encoding, 0, encoding.length);
-    }
-}
-
diff --git a/luni/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequest.java b/luni/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequest.java
deleted file mode 100644
index 3d36d37..0000000
--- a/luni/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.pkcs10;
-
-import org.apache.harmony.security.asn1.ASN1BitString;
-import org.apache.harmony.security.asn1.ASN1Sequence;
-import org.apache.harmony.security.asn1.ASN1Type;
-import org.apache.harmony.security.asn1.BerInputStream;
-import org.apache.harmony.security.asn1.BitString;
-import org.apache.harmony.security.x509.AlgorithmIdentifier;
-
-/**
- * The class implements the ASN.1 DER encoding and decoding of the PKCS#10
- * Certificate Signing Request (CSR). Its ASN notation is as follows:
- *
- * CertificationRequest ::= SEQUENCE {
- *   certificationRequestInfo CertificationRequestInfo,
- *   signatureAlgorithm SignatureAlgorithmIdentifier,
- *   signature Signature
- * }
- *
- * SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
- *
- * Signature ::= BIT STRING
- */
-public final class CertificationRequest {
-
-    /** the value of certificationRequestInfo field of the structure */
-    private CertificationRequestInfo info;
-
-    /** the value of signatureAlgorithm field of the structure */
-    private AlgorithmIdentifier algId;
-
-    /** the value of signature field of the structure */
-    private byte[] signature;
-
-    /** the ASN.1 encoded form of CertificationRequest */
-    private byte[] encoding;
-
-    public CertificationRequest(CertificationRequestInfo info,
-            AlgorithmIdentifier algId, byte[] signature) {
-        this.info = info;
-        this.algId = algId;
-        this.signature = signature.clone();
-    }
-
-    private CertificationRequest(CertificationRequestInfo info,
-            AlgorithmIdentifier algId, byte[] signature, byte[] encoding) {
-        this(info, algId, signature);
-        this.encoding = encoding;
-    }
-
-    public CertificationRequestInfo getInfo() {
-        return info;
-    }
-
-    public byte[] getSignature() {
-        byte[] result = new byte[signature.length];
-        System.arraycopy(signature, 0, result, 0, signature.length);
-        return result;
-    }
-
-    /**
-     * Returns ASN.1 encoded form of this CertificationRequest value.
-     * @return a byte array containing ASN.1 encode form.
-     */
-    public byte[] getEncoded() {
-        if (encoding == null) {
-            encoding = CertificationRequest.ASN1.encode(this);
-        }
-        return encoding;
-    }
-
-    public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {
-            CertificationRequestInfo.ASN1,  // info
-            AlgorithmIdentifier.ASN1,       // signatureAlgorithm
-            ASN1BitString.getInstance() })  // signature
-    {
-
-        public Object getDecodedObject(BerInputStream in) {
-            Object[] values = (Object[]) in.content;
-            return new CertificationRequest(
-                    (CertificationRequestInfo) values[0],
-                    (AlgorithmIdentifier) values[1],
-                    ((BitString) values[2]).bytes,
-                    in.getEncoded());
-        }
-
-        protected void getValues(Object object, Object[] values) {
-            CertificationRequest certReq = (CertificationRequest) object;
-            values[0] = certReq.info;
-            values[1] = certReq.algId;
-            values[2] = new BitString(certReq.signature, 0);
-        }
-    };
-}
-
diff --git a/luni/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java b/luni/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java
deleted file mode 100644
index d13f952..0000000
--- a/luni/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.pkcs10;
-
-import java.util.List;
-import javax.security.auth.x500.X500Principal;
-import org.apache.harmony.security.asn1.ASN1Implicit;
-import org.apache.harmony.security.asn1.ASN1Integer;
-import org.apache.harmony.security.asn1.ASN1Sequence;
-import org.apache.harmony.security.asn1.ASN1SetOf;
-import org.apache.harmony.security.asn1.ASN1Type;
-import org.apache.harmony.security.asn1.BerInputStream;
-import org.apache.harmony.security.x501.AttributeTypeAndValue;
-import org.apache.harmony.security.x501.Name;
-import org.apache.harmony.security.x509.SubjectPublicKeyInfo;
-
-/**
- * CertificationRequestInfo ::= SEQUENCE {
- *   version Version,
- *   subject Name,
- *   subjectPublicKeyInfo SubjectPublicKeyInfo,
- *   attributes [0] IMPLICIT Attributes }
- *
- * Version ::= INTEGER
- *
- * Attributes ::= SET OF Attribute
- */
-public final class CertificationRequestInfo {
-    private final int version;
-
-    /** the value of subject field of the structure */
-    private final Name subject;
-
-    /** the value of subjectPublicKeyInfo field of the structure */
-    private final SubjectPublicKeyInfo subjectPublicKeyInfo;
-
-    /** the value of attributes field of the structure */
-    private final List<?> attributes;
-
-    /** the ASN.1 encoded form of CertificationRequestInfo */
-    private byte[] encoding;
-
-    private CertificationRequestInfo(int version, Name subject,
-            SubjectPublicKeyInfo subjectPublicKeyInfo, List<?> attributes, byte [] encoding) {
-        this.version = version;
-        this.subject = subject;
-        this.subjectPublicKeyInfo = subjectPublicKeyInfo;
-        this.attributes = attributes;
-        this.encoding = encoding;
-    }
-
-    public Name getSubject() {
-        return subject;
-    }
-
-    public int getVersion() {
-        return version;
-    }
-
-    /**
-     * Returns ASN.1 encoded form of this CertificationRequestInfo.
-     * @return a byte array containing ASN.1 encode form.
-     */
-    public byte[] getEncoded() {
-        if (encoding == null) {
-            encoding = ASN1.encode(this);
-        }
-        return encoding;
-    }
-
-    @Override public String toString() {
-        StringBuilder res = new StringBuilder();
-        res.append("-- CertificationRequestInfo:");
-        res.append("\n version: ");
-        res.append(version);
-        res.append("\n subject: ");
-        res.append(subject.getName(X500Principal.CANONICAL));
-        res.append("\n subjectPublicKeyInfo: ");
-        res.append("\n\t algorithm: ");
-        res.append(subjectPublicKeyInfo.getAlgorithmIdentifier().getAlgorithm());
-        res.append("\n\t public key: ").append(subjectPublicKeyInfo.getPublicKey());
-        res.append("\n attributes: ");
-        if (attributes != null) {
-            res.append(attributes.toString());
-        } else {
-            res.append("none");
-        }
-        res.append("\n-- CertificationRequestInfo End\n");
-        return res.toString();
-    }
-
-    public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {
-            ASN1Integer.getInstance(),              // version
-            Name.ASN1,                              // subject
-            SubjectPublicKeyInfo.ASN1,              // subjectPublicKeyInfo
-            new ASN1Implicit(0, new ASN1SetOf(
-                    AttributeTypeAndValue.ASN1))    // attributes
-            }) {
-
-        @Override protected Object getDecodedObject(BerInputStream in) {
-            Object[] values = (Object[]) in.content;
-            return new CertificationRequestInfo(
-                    ASN1Integer.toIntValue(values[0]),
-                    (Name) values[1],
-                    (SubjectPublicKeyInfo) values[2],
-                    (List<?>) values[3],
-                    in.getEncoded());
-        }
-
-        @Override protected void getValues(Object object, Object[] values) {
-            CertificationRequestInfo certReqInfo = (CertificationRequestInfo) object;
-            values[0] = ASN1Integer.fromIntValue(certReqInfo.version);
-            values[1] = certReqInfo.subject;
-            values[2] = certReqInfo.subjectPublicKeyInfo;
-            values[3] = certReqInfo.attributes;
-        }
-    };
-}
-
diff --git a/luni/src/main/java/org/apache/harmony/security/pkcs8/PrivateKeyInfo.java b/luni/src/main/java/org/apache/harmony/security/pkcs8/PrivateKeyInfo.java
deleted file mode 100644
index 400bf86..0000000
--- a/luni/src/main/java/org/apache/harmony/security/pkcs8/PrivateKeyInfo.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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 org.apache.harmony.security.pkcs8;
-
-import java.util.List;
-import org.apache.harmony.security.asn1.ASN1Implicit;
-import org.apache.harmony.security.asn1.ASN1Integer;
-import org.apache.harmony.security.asn1.ASN1OctetString;
-import org.apache.harmony.security.asn1.ASN1Sequence;
-import org.apache.harmony.security.asn1.ASN1SetOf;
-import org.apache.harmony.security.asn1.ASN1Type;
-import org.apache.harmony.security.asn1.BerInputStream;
-import org.apache.harmony.security.x501.AttributeTypeAndValue;
-import org.apache.harmony.security.x509.AlgorithmIdentifier;
-
-/**
- * The class implements the ASN.1 DER encoding and decoding of the PKCS#8
- * PrivateKeyInfo having the following ASN.1 notation:
- *
- *  PrivateKeyInfo ::= SEQUENCE {
- *      version Version,
- *      privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
- *      privateKey PrivateKey,
- *      attributes [0] IMPLICIT Attributes OPTIONAL }
- *
- *  Version ::= INTEGER
- *
- *  PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
- *
- *  PrivateKey ::= OCTET STRING
- *
- *  Attributes ::= SET OF Attribute
- */
-public final class PrivateKeyInfo {
-    private final int version;
-    private final AlgorithmIdentifier privateKeyAlgorithm;
-    private final byte[] privateKey;
-    private final List<?> attributes;
-    private byte[] encoding;
-
-    public PrivateKeyInfo(int version, AlgorithmIdentifier privateKeyAlgorithm,
-            byte[] privateKey, List attributes) {
-        this.version = version;
-        this.privateKeyAlgorithm = privateKeyAlgorithm;
-        this.privateKey = privateKey;
-        this.attributes = attributes;
-    }
-
-    private PrivateKeyInfo(int version,
-            AlgorithmIdentifier privateKeyAlgorithm, byte[] privateKey,
-            List attributes, byte[] encoding) {
-        this(version, privateKeyAlgorithm, privateKey, attributes);
-        this.encoding = encoding;
-    }
-
-    public int getVersion() {
-        return version;
-    }
-
-    public AlgorithmIdentifier getAlgorithmIdentifier() {
-        return privateKeyAlgorithm;
-    }
-
-    public List getAttributes() {
-        return attributes;
-    }
-
-    /**
-     * Returns the OCTET STRING.
-     */
-    public byte[] getPrivateKey() {
-        return privateKey;
-    }
-
-    /**
-     * Returns ASN.1 encoded form of this PrivateKeyInfo.
-     */
-    public byte[] getEncoded() {
-        if (encoding == null) {
-            encoding = ASN1.encode(this);
-        }
-        return encoding;
-    }
-
-    public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {
-
-    ASN1Integer.getInstance(), // version
-            AlgorithmIdentifier.ASN1, // AlgorithmIdentifier
-            ASN1OctetString.getInstance(), // privateKey
-
-            new ASN1Implicit(0, new ASN1SetOf(AttributeTypeAndValue.ASN1)) // attributes
-            }) {
-
-        {
-            setOptional(3); // attributes are OPTIONAL
-        }
-
-        protected Object getDecodedObject(BerInputStream in) {
-            Object[] values = (Object[]) in.content;
-            return new PrivateKeyInfo(ASN1Integer.toIntValue(values[0]),
-                    (AlgorithmIdentifier) values[1], (byte[]) values[2],
-                    (List) values[3], in.getEncoded());
-        }
-
-        protected void getValues(Object object, Object[] values) {
-            PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) object;
-            values[0] = ASN1Integer.fromIntValue(privateKeyInfo.version);
-            values[1] = privateKeyInfo.privateKeyAlgorithm;
-            values[2] = privateKeyInfo.privateKey;
-            values[3] = privateKeyInfo.attributes;
-        }
-    };
-}
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java
deleted file mode 100644
index ad5ac7d..0000000
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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 org.apache.harmony.security.provider.crypto;
-
-import java.security.Provider;
-
-/**
- * Implementation of Provider for SecureRandom. The implementation supports the
- * "SHA1PRNG" algorithm described in JavaTM Cryptography Architecture, API
- * Specification & Reference
- */
-
-public final class CryptoProvider extends Provider {
-
-    private static final long serialVersionUID = 7991202868423459598L;
-
-    /**
-     * Creates a Provider and puts parameters
-     */
-    public CryptoProvider() {
-        super("Crypto", 1.0, "HARMONY (SHA1 digest; SecureRandom; SHA1withDSA signature)");
-
-        put("SecureRandom.SHA1PRNG",
-                "org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl");
-        put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Constants.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Constants.java
deleted file mode 100644
index fc6a847..0000000
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Constants.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.
- */
-/**
-* @author Yuri A. Kropachev
-* @version $Revision$
-*/
-
-
-package org.apache.harmony.security.provider.crypto;
-
-
-/**
- * This interface contains : <BR>
- * - a set of constant values, H0-H4, defined in "SECURE HASH STANDARD", FIPS PUB 180-2 ;<BR>
- * - implementation constant values to use in classes using SHA-1 algorithm.    <BR>
- */
-public final class SHA1Constants {
-    private SHA1Constants() {
-    }
-
-    /**
-     *  constant defined in "SECURE HASH STANDARD"
-     */
-    public static final int H0 = 0x67452301;
-
-
-    /**
-     *  constant defined in "SECURE HASH STANDARD"
-     */
-    public static final int H1 = 0xEFCDAB89;
-
-
-    /**
-     *  constant defined in "SECURE HASH STANDARD"
-     */
-    public static final int H2 = 0x98BADCFE;
-
-
-    /**
-     *  constant defined in "SECURE HASH STANDARD"
-     */
-    public static final int H3 = 0x10325476;
-
-
-    /**
-     *  constant defined in "SECURE HASH STANDARD"
-     */
-    public static final int H4 = 0xC3D2E1F0;
-
-
-    /**
-     * offset in buffer to store number of bytes in 0-15 word frame
-     */
-    public static final int BYTES_OFFSET = 81;
-
-
-    /**
-     * offset in buffer to store current hash value
-     */
-    public static final int HASH_OFFSET = 82;
-
-
-    /**
-     * # of bytes in H0-H4 words; <BR>
-     * in this implementation # is set to 20 (in general # varies from 1 to 20)
-     */
-    public static final int DIGEST_LENGTH = 20;
-}
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java
deleted file mode 100644
index 57b9005..0000000
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.
- */
-/**
-* @author Yuri A. Kropachev
-* @version $Revision$
-*/
-
-
-package org.apache.harmony.security.provider.crypto;
-
-import static org.apache.harmony.security.provider.crypto.SHA1Constants.*;
-
-/**
- * This class contains methods providing SHA-1 functionality to use in classes. <BR>
- * The methods support the algorithm described in "SECURE HASH STANDARD", FIPS PUB 180-2, <BR>
- * "http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf"      <BR>
- * <BR>
- * The class contains two package level access methods, -
- * "void updateHash(int[], byte[], int, int)" and "void computeHash(int[])", -
- * performing the following operations. <BR>
- * <BR>
- * The "updateHash(..)" method appends new bytes to existing ones
- * within limit of a frame of 64 bytes (16 words).
- * Once a length of accumulated bytes reaches the limit
- * the "computeHash(int[])" method is invoked on the frame to compute updated hash,
- * and the number of bytes in the frame is set to 0.
- * Thus, after appending all bytes, the frame contain only those bytes
- * that were not used in computing final hash value yet. <BR>
- * <BR>
- * The "computeHash(..)" method generates a 160 bit hash value using
- * a 512 bit message stored in first 16 words of int[] array argument and
- * current hash value stored in five words, beginning HASH_OFFSET, of the array argument.
- * Computation is done according to SHA-1 algorithm. <BR>
- * <BR>
- * The resulting hash value replaces the previous hash value in the array;
- * original bits of the message are not preserved.
- */
-public class SHA1Impl {
-
-
-    /**
-     * The method generates a 160 bit hash value using
-     * a 512 bit message stored in first 16 words of int[] array argument and
-     * current hash value stored in five words, beginning OFFSET+1, of the array argument.
-     * Computation is done according to SHA-1 algorithm.
-     *
-     * The resulting hash value replaces the previous hash value in the array;
-     * original bits of the message are not preserved.
-     *
-     * No checks on argument supplied, that is,
-     * a calling method is responsible for such checks.
-     * In case of incorrect array passed to the method
-     * either NPE or IndexOutOfBoundException gets thrown by JVM.
-     *
-     * @params
-     *        arrW - integer array; arrW.length >= (BYTES_OFFSET+6); <BR>
-     *               only first (BYTES_OFFSET+6) words are used
-     */
-    static void computeHash(int[] arrW) {
-
-        int  a = arrW[HASH_OFFSET   ];
-        int  b = arrW[HASH_OFFSET +1];
-        int  c = arrW[HASH_OFFSET +2];
-        int  d = arrW[HASH_OFFSET +3];
-        int  e = arrW[HASH_OFFSET +4];
-
-        int temp;
-
-        // In this implementation the "d. For t = 0 to 79 do" loop
-        // is split into four loops. The following constants:
-        //     K = 5A827999   0 <= t <= 19
-        //     K = 6ED9EBA1  20 <= t <= 39
-        //     K = 8F1BBCDC  40 <= t <= 59
-        //     K = CA62C1D6  60 <= t <= 79
-        // are hex literals in the loops.
-
-        for ( int t = 16; t < 80 ; t++ ) {
-
-            temp  = arrW[t-3] ^ arrW[t-8] ^ arrW[t-14] ^ arrW[t-16];
-            arrW[t] = ( temp<<1 ) | ( temp>>>31 );
-        }
-
-        for ( int t = 0 ; t < 20 ; t++ ) {
-
-            temp = ( ( a<<5 ) | ( a>>>27 )   ) +
-                   ( ( b & c) | ((~b) & d)   ) +
-                   ( e + arrW[t] + 0x5A827999 ) ;
-            e = d;
-            d = c;
-            c = ( b<<30 ) | ( b>>>2 ) ;
-            b = a;
-            a = temp;
-        }
-        for ( int t = 20 ; t < 40 ; t++ ) {
-
-            temp = ((( a<<5 ) | ( a>>>27 ))) + (b ^ c ^ d) + (e + arrW[t] + 0x6ED9EBA1) ;
-            e = d;
-            d = c;
-            c = ( b<<30 ) | ( b>>>2 ) ;
-            b = a;
-            a = temp;
-        }
-        for ( int t = 40 ; t < 60 ; t++ ) {
-
-            temp = (( a<<5 ) | ( a>>>27 )) + ((b & c) | (b & d) | (c & d)) +
-                                                             (e + arrW[t] + 0x8F1BBCDC) ;
-            e = d;
-            d = c;
-            c = ( b<<30 ) | ( b>>>2 ) ;
-            b = a;
-            a = temp;
-        }
-        for ( int t = 60 ; t < 80 ; t++ ) {
-
-            temp = ((( a<<5 ) | ( a>>>27 ))) + (b ^ c ^ d) + (e + arrW[t] + 0xCA62C1D6) ;
-            e = d;
-            d = c;
-            c = ( b<<30 ) | ( b>>>2 ) ;
-            b = a;
-            a = temp;
-        }
-
-        arrW[HASH_OFFSET   ] += a;
-        arrW[HASH_OFFSET +1] += b;
-        arrW[HASH_OFFSET +2] += c;
-        arrW[HASH_OFFSET +3] += d;
-        arrW[HASH_OFFSET +4] += e;
-    }
-
-    /**
-     * The method appends new bytes to existing ones
-     * within limit of a frame of 64 bytes (16 words).
-     *
-     * Once a length of accumulated bytes reaches the limit
-     * the "computeHash(int[])" method is invoked on the array to compute updated hash,
-     * and the number of bytes in the frame is set to 0.
-     * Thus, after appending all bytes, the array contain only those bytes
-     * that were not used in computing final hash value yet.
-     *
-     * No checks on arguments passed to the method, that is,
-     * a calling method is responsible for such checks.
-     *
-     * @params
-     *        intArray  - int array containing bytes to which to append;
-     *                    intArray.length >= (BYTES_OFFSET+6)
-     * @params
-     *        byteInput - array of bytes to use for the update
-     * @params
-     *        from      - the offset to start in the "byteInput" array
-     * @params
-     *        to        - a number of the last byte in the input array to use,
-     *                that is, for first byte "to"==0, for last byte "to"==input.length-1
-     */
-    static void updateHash(int[] intArray, byte[] byteInput, int fromByte, int toByte) {
-
-        // As intArray contains a packed bytes
-        // the buffer's index is in the intArray[BYTES_OFFSET] element
-
-        int index = intArray[BYTES_OFFSET];
-        int i = fromByte;
-        int maxWord;
-        int nBytes;
-
-        int wordIndex = index >>2;
-        int byteIndex = index & 0x03;
-
-        intArray[BYTES_OFFSET] = ( index + toByte - fromByte + 1 ) & 077 ;
-
-        // In general case there are 3 stages :
-        // - appending bytes to non-full word,
-        // - writing 4 bytes into empty words,
-        // - writing less than 4 bytes in last word
-
-        if ( byteIndex != 0 ) {       // appending bytes in non-full word (as if)
-
-            for ( ; ( i <= toByte ) && ( byteIndex < 4 ) ; i++ ) {
-                intArray[wordIndex] |= ( byteInput[i] & 0xFF ) << ((3 - byteIndex)<<3) ;
-                byteIndex++;
-            }
-            if ( byteIndex == 4 ) {
-                wordIndex++;
-                if ( wordIndex == 16 ) {          // intArray is full, computing hash
-
-                    computeHash(intArray);
-                    wordIndex = 0;
-                }
-            }
-            if ( i > toByte ) {                 // all input bytes appended
-                return ;
-            }
-        }
-
-        // writing full words
-
-        maxWord = (toByte - i + 1) >> 2;           // # of remaining full words, may be "0"
-        for ( int k = 0; k < maxWord ; k++ ) {
-
-            intArray[wordIndex] = ( ((int) byteInput[i   ] & 0xFF) <<24 ) |
-                                  ( ((int) byteInput[i +1] & 0xFF) <<16 ) |
-                                  ( ((int) byteInput[i +2] & 0xFF) <<8  ) |
-                                  ( ((int) byteInput[i +3] & 0xFF)      )  ;
-            i += 4;
-            wordIndex++;
-
-            if ( wordIndex < 16 ) {     // buffer is not full yet
-                continue;
-            }
-            computeHash(intArray);      // buffer is full, computing hash
-            wordIndex = 0;
-        }
-
-        // writing last incomplete word
-        // after writing free byte positions are set to "0"s
-
-        nBytes = toByte - i +1;
-        if ( nBytes != 0 ) {
-
-            int w =  ((int) byteInput[i] & 0xFF) <<24 ;
-
-            if ( nBytes != 1 ) {
-                w |= ((int) byteInput[i +1] & 0xFF) <<16 ;
-                if ( nBytes != 2) {
-                    w |= ((int) byteInput[i +2] & 0xFF) <<8 ;
-                }
-            }
-            intArray[wordIndex] = w;
-        }
-
-        return ;
-    }
-
-}
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
deleted file mode 100644
index 5c0e328..0000000
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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 org.apache.harmony.security.provider.crypto;
-
-import dalvik.system.BlockGuard;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.security.InvalidParameterException;
-import java.security.ProviderException;
-import java.security.SecureRandomSpi;
-import libcore.io.Streams;
-import libcore.util.EmptyArray;
-
-import static org.apache.harmony.security.provider.crypto.SHA1Constants.*;
-
-/**
- * This class extends the SecureRandomSpi class implementing all its abstract methods.
- *
- * <p>To generate pseudo-random bits, the implementation uses technique described in
- * the "Random Number Generator (RNG) algorithms" section, Appendix A,
- * JavaTM Cryptography Architecture, API Specification & Reference.
- */
-public class SHA1PRNG_SecureRandomImpl extends SecureRandomSpi implements Serializable {
-
-    private static final long serialVersionUID = 283736797212159675L;
-
-    private static FileInputStream devURandom;
-    static {
-        try {
-            devURandom = new FileInputStream(new File("/dev/urandom"));
-        } catch (IOException ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    // constants to use in expressions operating on bytes in int and long variables:
-    // END_FLAGS - final bytes in words to append to message;
-    //             see "ch.5.1 Padding the Message, FIPS 180-2"
-    // RIGHT1    - shifts to right for left half of long
-    // RIGHT2    - shifts to right for right half of long
-    // LEFT      - shifts to left for bytes
-    // MASK      - mask to select counter's bytes after shift to right
-
-    private static final int[] END_FLAGS = { 0x80000000, 0x800000, 0x8000, 0x80 };
-
-    private static final int[] RIGHT1 = { 0, 40, 48, 56 };
-
-    private static final int[] RIGHT2 = { 0, 8, 16, 24 };
-
-    private static final int[] LEFT = { 0, 24, 16, 8 };
-
-    private static final int[] MASK = { 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF,
-            0x000000FF };
-
-    // HASHBYTES_TO_USE defines # of bytes returned by "computeHash(byte[])"
-    // to use to form byte array returning by the "nextBytes(byte[])" method
-    // Note, that this implementation uses more bytes than it is defined
-    // in the above specification.
-    private static final int HASHBYTES_TO_USE = 20;
-
-    // value of 16 defined in the "SECURE HASH STANDARD", FIPS PUB 180-2
-    private static final int FRAME_LENGTH = 16;
-
-    // miscellaneous constants defined in this implementation:
-    // COUNTER_BASE - initial value to set to "counter" before computing "nextBytes(..)";
-    //                note, that the exact value is not defined in STANDARD
-    // HASHCOPY_OFFSET   - offset for copy of current hash in "copies" array
-    // EXTRAFRAME_OFFSET - offset for extra frame in "copies" array;
-    //                     as the extra frame follows the current hash frame,
-    //                     EXTRAFRAME_OFFSET is equal to length of current hash frame
-    // FRAME_OFFSET      - offset for frame in "copies" array
-    // MAX_BYTES - maximum # of seed bytes processing which doesn't require extra frame
-    //             see (1) comments on usage of "seed" array below and
-    //             (2) comments in "engineNextBytes(byte[])" method
-    //
-    // UNDEFINED  - three states of engine; initially its state is "UNDEFINED"
-    // SET_SEED     call to "engineSetSeed"  sets up "SET_SEED" state,
-    // NEXT_BYTES   call to "engineNextByte" sets up "NEXT_BYTES" state
-
-    private static final int COUNTER_BASE = 0;
-
-    private static final int HASHCOPY_OFFSET = 0;
-
-    private static final int EXTRAFRAME_OFFSET = 5;
-
-    private static final int FRAME_OFFSET = 21;
-
-    private static final int MAX_BYTES = 48;
-
-    private static final int UNDEFINED = 0;
-
-    private static final int SET_SEED = 1;
-
-    private static final int NEXT_BYTES = 2;
-
-    private static SHA1PRNG_SecureRandomImpl myRandom;
-
-    // Structure of "seed" array:
-    // -  0-79 - words for computing hash
-    // - 80    - unused
-    // - 81    - # of seed bytes in current seed frame
-    // - 82-86 - 5 words, current seed hash
-    private transient int[] seed;
-
-    // total length of seed bytes, including all processed
-    private transient long seedLength;
-
-    // Structure of "copies" array
-    // -  0-4  - 5 words, copy of current seed hash
-    // -  5-20 - extra 16 words frame;
-    //           is used if final padding exceeds 512-bit length
-    // - 21-36 - 16 word frame to store a copy of remaining bytes
-    private transient int[] copies;
-
-    // ready "next" bytes; needed because words are returned
-    private transient byte[] nextBytes;
-
-    // index of used bytes in "nextBytes" array
-    private transient int nextBIndex;
-
-    // variable required according to "SECURE HASH STANDARD"
-    private transient long counter;
-
-    // contains int value corresponding to engine's current state
-    private transient int state;
-
-    // The "seed" array is used to compute both "current seed hash" and "next bytes".
-    //
-    // As the "SHA1" algorithm computes a hash of entire seed by splitting it into
-    // a number of the 512-bit length frames (512 bits = 64 bytes = 16 words),
-    // "current seed hash" is a hash (5 words, 20 bytes) for all previous full frames;
-    // remaining bytes are stored in the 0-15 word frame of the "seed" array.
-    //
-    // As for calculating "next bytes",
-    // both remaining bytes and "current seed hash" are used,
-    // to preserve the latter for following "setSeed(..)" commands,
-    // the following technique is used:
-    // - upon getting "nextBytes(byte[])" invoked, single or first in row,
-    //   which requires computing new hash, that is,
-    //   there is no more bytes remaining from previous "next bytes" computation,
-    //   remaining bytes are copied into the 21-36 word frame of the "copies" array;
-    // - upon getting "setSeed(byte[])" invoked, single or first in row,
-    //   remaining bytes are copied back.
-
-    /**
-     *  Creates object and sets implementation variables to their initial values
-     */
-    public SHA1PRNG_SecureRandomImpl() {
-
-        seed = new int[HASH_OFFSET + EXTRAFRAME_OFFSET];
-        seed[HASH_OFFSET] = H0;
-        seed[HASH_OFFSET + 1] = H1;
-        seed[HASH_OFFSET + 2] = H2;
-        seed[HASH_OFFSET + 3] = H3;
-        seed[HASH_OFFSET + 4] = H4;
-
-        seedLength = 0;
-        copies = new int[2 * FRAME_LENGTH + EXTRAFRAME_OFFSET];
-        nextBytes = new byte[DIGEST_LENGTH];
-        nextBIndex = HASHBYTES_TO_USE;
-        counter = COUNTER_BASE;
-        state = UNDEFINED;
-    }
-
-    /*
-     * The method invokes the SHA1Impl's "updateHash(..)" method
-     * to update current seed frame and
-     * to compute new intermediate hash value if the frame is full.
-     *
-     * After that it computes a length of whole seed.
-     */
-    private void updateSeed(byte[] bytes) {
-
-        // on call:   "seed" contains current bytes and current hash;
-        // on return: "seed" contains new current bytes and possibly new current hash
-        //            if after adding, seed bytes overfill its buffer
-        SHA1Impl.updateHash(seed, bytes, 0, bytes.length - 1);
-
-        seedLength += bytes.length;
-    }
-
-    /**
-     * Changes current seed by supplementing a seed argument to the current seed,
-     * if this already set;
-     * the argument is used as first seed otherwise. <BR>
-     *
-     * The method overrides "engineSetSeed(byte[])" in class SecureRandomSpi.
-     *
-     * @param
-     *       seed - byte array
-     * @throws
-     *       NullPointerException - if null is passed to the "seed" argument
-     */
-    protected synchronized void engineSetSeed(byte[] seed) {
-
-        if (seed == null) {
-            throw new NullPointerException("seed == null");
-        }
-
-        if (state == NEXT_BYTES) { // first setSeed after NextBytes; restoring hash
-            System.arraycopy(copies, HASHCOPY_OFFSET, this.seed, HASH_OFFSET,
-                    EXTRAFRAME_OFFSET);
-        }
-        state = SET_SEED;
-
-        if (seed.length != 0) {
-            updateSeed(seed);
-        }
-    }
-
-    /**
-     * Returns a required number of random bytes. <BR>
-     *
-     * The method overrides "engineGenerateSeed (int)" in class SecureRandomSpi. <BR>
-     *
-     * @param
-     *       numBytes - number of bytes to return; should be >= 0.
-     * @return
-     *       byte array containing bits in order from left to right
-     * @throws
-     *       InvalidParameterException - if numBytes < 0
-     */
-    protected synchronized byte[] engineGenerateSeed(int numBytes) {
-
-        byte[] myBytes; // byte[] for bytes returned by "nextBytes()"
-
-        if (numBytes < 0) {
-            throw new NegativeArraySizeException(Integer.toString(numBytes));
-        }
-        if (numBytes == 0) {
-            return EmptyArray.BYTE;
-        }
-
-        if (myRandom == null) {
-            myRandom = new SHA1PRNG_SecureRandomImpl();
-            myRandom.engineSetSeed(getRandomBytes(DIGEST_LENGTH));
-        }
-
-        myBytes = new byte[numBytes];
-        myRandom.engineNextBytes(myBytes);
-
-        return myBytes;
-    }
-
-    /**
-     * Writes random bytes into an array supplied.
-     * Bits in a byte are from left to right. <BR>
-     *
-     * To generate random bytes, the "expansion of source bits" method is used,
-     * that is,
-     * the current seed with a 64-bit counter appended is used to compute new bits.
-     * The counter is incremented by 1 for each 20-byte output. <BR>
-     *
-     * The method overrides engineNextBytes in class SecureRandomSpi.
-     *
-     * @param
-     *       bytes - byte array to be filled in with bytes
-     * @throws
-     *       NullPointerException - if null is passed to the "bytes" argument
-     */
-    protected synchronized void engineNextBytes(byte[] bytes) {
-
-        int i, n;
-
-        long bits; // number of bits required by Secure Hash Standard
-        int nextByteToReturn; // index of ready bytes in "bytes" array
-        int lastWord; // index of last word in frame containing bytes
-        final int extrabytes = 7;// # of bytes to add in order to computer # of 8 byte words
-
-        if (bytes == null) {
-            throw new NullPointerException("bytes == null");
-        }
-
-        lastWord = seed[BYTES_OFFSET] == 0 ? 0
-                : (seed[BYTES_OFFSET] + extrabytes) >> 3 - 1;
-
-        if (state == UNDEFINED) {
-
-            // no seed supplied by user, hence it is generated thus randomizing internal state
-            updateSeed(getRandomBytes(DIGEST_LENGTH));
-            nextBIndex = HASHBYTES_TO_USE;
-
-            // updateSeed(...) updates where the last word of the seed is, so we
-            // have to read it again.
-            lastWord = seed[BYTES_OFFSET] == 0 ? 0
-                    : (seed[BYTES_OFFSET] + extrabytes) >> 3 - 1;
-
-        } else if (state == SET_SEED) {
-
-            System.arraycopy(seed, HASH_OFFSET, copies, HASHCOPY_OFFSET,
-                    EXTRAFRAME_OFFSET);
-
-            // possible cases for 64-byte frame:
-            //
-            // seed bytes < 48      - remaining bytes are enough for all, 8 counter bytes,
-            //                        0x80, and 8 seedLength bytes; no extra frame required
-            // 48 < seed bytes < 56 - remaining 9 bytes are for 0x80 and 8 counter bytes
-            //                        extra frame contains only seedLength value at the end
-            // seed bytes > 55      - extra frame contains both counter's bytes
-            //                        at the beginning and seedLength value at the end;
-            //                        note, that beginning extra bytes are not more than 8,
-            //                        that is, only 2 extra words may be used
-
-            // no need to set to "0" 3 words after "lastWord" and
-            // more than two words behind frame
-            for (i = lastWord + 3; i < FRAME_LENGTH + 2; i++) {
-                seed[i] = 0;
-            }
-
-            bits = (seedLength << 3) + 64; // transforming # of bytes into # of bits
-
-            // putting # of bits into two last words (14,15) of 16 word frame in
-            // seed or copies array depending on total length after padding
-            if (seed[BYTES_OFFSET] < MAX_BYTES) {
-                seed[14] = (int) (bits >>> 32);
-                seed[15] = (int) (bits & 0xFFFFFFFF);
-            } else {
-                copies[EXTRAFRAME_OFFSET + 14] = (int) (bits >>> 32);
-                copies[EXTRAFRAME_OFFSET + 15] = (int) (bits & 0xFFFFFFFF);
-            }
-
-            nextBIndex = HASHBYTES_TO_USE; // skipping remaining random bits
-        }
-        state = NEXT_BYTES;
-
-        if (bytes.length == 0) {
-            return;
-        }
-
-        nextByteToReturn = 0;
-
-        // possibly not all of HASHBYTES_TO_USE bytes were used previous time
-        n = (HASHBYTES_TO_USE - nextBIndex) < (bytes.length - nextByteToReturn) ? HASHBYTES_TO_USE
-                - nextBIndex
-                : bytes.length - nextByteToReturn;
-        if (n > 0) {
-            System.arraycopy(nextBytes, nextBIndex, bytes, nextByteToReturn, n);
-            nextBIndex += n;
-            nextByteToReturn += n;
-        }
-
-        if (nextByteToReturn >= bytes.length) {
-            return; // return because "bytes[]" are filled in
-        }
-
-        n = seed[BYTES_OFFSET] & 0x03;
-        for (;;) {
-            if (n == 0) {
-
-                seed[lastWord] = (int) (counter >>> 32);
-                seed[lastWord + 1] = (int) (counter & 0xFFFFFFFF);
-                seed[lastWord + 2] = END_FLAGS[0];
-
-            } else {
-
-                seed[lastWord] |= (int) ((counter >>> RIGHT1[n]) & MASK[n]);
-                seed[lastWord + 1] = (int) ((counter >>> RIGHT2[n]) & 0xFFFFFFFF);
-                seed[lastWord + 2] = (int) ((counter << LEFT[n]) | END_FLAGS[n]);
-            }
-            if (seed[BYTES_OFFSET] > MAX_BYTES) {
-                copies[EXTRAFRAME_OFFSET] = seed[FRAME_LENGTH];
-                copies[EXTRAFRAME_OFFSET + 1] = seed[FRAME_LENGTH + 1];
-            }
-
-            SHA1Impl.computeHash(seed);
-
-            if (seed[BYTES_OFFSET] > MAX_BYTES) {
-
-                System.arraycopy(seed, 0, copies, FRAME_OFFSET, FRAME_LENGTH);
-                System.arraycopy(copies, EXTRAFRAME_OFFSET, seed, 0,
-                        FRAME_LENGTH);
-
-                SHA1Impl.computeHash(seed);
-                System.arraycopy(copies, FRAME_OFFSET, seed, 0, FRAME_LENGTH);
-            }
-            counter++;
-
-            int j = 0;
-            for (i = 0; i < EXTRAFRAME_OFFSET; i++) {
-                int k = seed[HASH_OFFSET + i];
-                nextBytes[j] = (byte) (k >>> 24); // getting first  byte from left
-                nextBytes[j + 1] = (byte) (k >>> 16); // getting second byte from left
-                nextBytes[j + 2] = (byte) (k >>> 8); // getting third  byte from left
-                nextBytes[j + 3] = (byte) (k); // getting fourth byte from left
-                j += 4;
-            }
-
-            nextBIndex = 0;
-            j = HASHBYTES_TO_USE < (bytes.length - nextByteToReturn) ? HASHBYTES_TO_USE
-                    : bytes.length - nextByteToReturn;
-
-            if (j > 0) {
-                System.arraycopy(nextBytes, 0, bytes, nextByteToReturn, j);
-                nextByteToReturn += j;
-                nextBIndex += j;
-            }
-
-            if (nextByteToReturn >= bytes.length) {
-                break;
-            }
-        }
-    }
-
-    private void writeObject(ObjectOutputStream oos) throws IOException {
-
-        int[] intData = null;
-
-        final int only_hash = EXTRAFRAME_OFFSET;
-        final int hashes_and_frame = EXTRAFRAME_OFFSET * 2 + FRAME_LENGTH;
-        final int hashes_and_frame_extra = EXTRAFRAME_OFFSET * 2 + FRAME_LENGTH
-                * 2;
-
-        oos.writeLong(seedLength);
-        oos.writeLong(counter);
-        oos.writeInt(state);
-        oos.writeInt(seed[BYTES_OFFSET]);
-
-        int nRemaining = (seed[BYTES_OFFSET] + 3) >> 2; // converting bytes in words
-        // result may be 0
-        if (state != NEXT_BYTES) {
-
-            // either the state is UNDEFINED or previous method was "setSeed(..)"
-            // so in "seed[]" to serialize are remaining bytes (seed[0-nRemaining]) and
-            // current hash (seed[82-86])
-
-            intData = new int[only_hash + nRemaining];
-
-            System.arraycopy(seed, 0, intData, 0, nRemaining);
-            System.arraycopy(seed, HASH_OFFSET, intData, nRemaining,
-                    EXTRAFRAME_OFFSET);
-
-        } else {
-            // previous method was "nextBytes(..)"
-            // so, data to serialize are all the above (two first are in "copies" array)
-            // and current words in both frame and extra frame (as if)
-
-            int offset = 0;
-            if (seed[BYTES_OFFSET] < MAX_BYTES) { // no extra frame
-
-                intData = new int[hashes_and_frame + nRemaining];
-
-            } else { // extra frame is used
-
-                intData = new int[hashes_and_frame_extra + nRemaining];
-
-                intData[offset] = seed[FRAME_LENGTH];
-                intData[offset + 1] = seed[FRAME_LENGTH + 1];
-                intData[offset + 2] = seed[FRAME_LENGTH + 14];
-                intData[offset + 3] = seed[FRAME_LENGTH + 15];
-                offset += 4;
-            }
-
-            System.arraycopy(seed, 0, intData, offset, FRAME_LENGTH);
-            offset += FRAME_LENGTH;
-
-            System.arraycopy(copies, FRAME_LENGTH + EXTRAFRAME_OFFSET, intData,
-                    offset, nRemaining);
-            offset += nRemaining;
-
-            System.arraycopy(copies, 0, intData, offset, EXTRAFRAME_OFFSET);
-            offset += EXTRAFRAME_OFFSET;
-
-            System.arraycopy(seed, HASH_OFFSET, intData, offset,
-                    EXTRAFRAME_OFFSET);
-        }
-        for (int i = 0; i < intData.length; i++) {
-            oos.writeInt(intData[i]);
-        }
-
-        oos.writeInt(nextBIndex);
-        oos.write(nextBytes, nextBIndex, HASHBYTES_TO_USE - nextBIndex);
-    }
-
-    private void readObject(ObjectInputStream ois) throws IOException,
-            ClassNotFoundException {
-
-        seed = new int[HASH_OFFSET + EXTRAFRAME_OFFSET];
-        copies = new int[2 * FRAME_LENGTH + EXTRAFRAME_OFFSET];
-        nextBytes = new byte[DIGEST_LENGTH];
-
-        seedLength = ois.readLong();
-        counter = ois.readLong();
-        state = ois.readInt();
-        seed[BYTES_OFFSET] = ois.readInt();
-
-        int nRemaining = (seed[BYTES_OFFSET] + 3) >> 2; // converting bytes in words
-
-        if (state != NEXT_BYTES) {
-
-            for (int i = 0; i < nRemaining; i++) {
-                seed[i] = ois.readInt();
-            }
-            for (int i = 0; i < EXTRAFRAME_OFFSET; i++) {
-                seed[HASH_OFFSET + i] = ois.readInt();
-            }
-        } else {
-            if (seed[BYTES_OFFSET] >= MAX_BYTES) {
-
-                // reading next bytes in seed extra frame
-                seed[FRAME_LENGTH] = ois.readInt();
-                seed[FRAME_LENGTH + 1] = ois.readInt();
-                seed[FRAME_LENGTH + 14] = ois.readInt();
-                seed[FRAME_LENGTH + 15] = ois.readInt();
-            }
-            // reading next bytes in seed frame
-            for (int i = 0; i < FRAME_LENGTH; i++) {
-                seed[i] = ois.readInt();
-            }
-            // reading remaining seed bytes
-            for (int i = 0; i < nRemaining; i++) {
-                copies[FRAME_LENGTH + EXTRAFRAME_OFFSET + i] = ois.readInt();
-            }
-            // reading copy of current hash
-            for (int i = 0; i < EXTRAFRAME_OFFSET; i++) {
-                copies[i] = ois.readInt();
-            }
-            // reading current hash
-            for (int i = 0; i < EXTRAFRAME_OFFSET; i++) {
-                seed[HASH_OFFSET + i] = ois.readInt();
-            }
-        }
-
-        nextBIndex = ois.readInt();
-        Streams.readFully(ois, nextBytes, nextBIndex, HASHBYTES_TO_USE - nextBIndex);
-    }
-
-    private static byte[] getRandomBytes(int byteCount) {
-        if (byteCount <= 0) {
-            throw new IllegalArgumentException("Too few bytes requested: " + byteCount);
-        }
-
-        BlockGuard.Policy originalPolicy = BlockGuard.getThreadPolicy();
-        try {
-            BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
-            byte[] result = new byte[byteCount];
-            Streams.readFully(devURandom, result, 0, byteCount);
-            return result;
-        } catch (Exception ex) {
-            throw new ProviderException("Couldn't read " + byteCount + " random bytes", ex);
-        } finally {
-            BlockGuard.setThreadPolicy(originalPolicy);
-        }
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java b/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
index c1d73df..8df02c9 100644
--- a/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
+++ b/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
@@ -87,14 +87,33 @@
 
     static {
         for (String[] element : knownAlgMappings) {
-            String algUC = element[1].toUpperCase(Locale.US);
-            alg2OidMap.put(algUC, element[0]);
-            oid2AlgMap.put(element[0], algUC);
-            // map upper case alg name to its original name
-            algAliasesMap.put(algUC, element[1]);
+            addMapping(element[0], element[1]);
         }
     }
 
+    /**
+     * Adds a mapping to the internal table. Will overwrite any entry already
+     * present. Visible for testing.
+     */
+    public static void addMapping(String oid, String name) {
+        String nameUC = name.toUpperCase(Locale.ROOT);
+        alg2OidMap.put(nameUC, oid);
+        oid2AlgMap.put(oid, nameUC);
+        // map upper case alg name to its original name
+        algAliasesMap.put(nameUC, name);
+    }
+
+    /**
+     * Removes a mapping from the internal table. Visible for testing.
+     */
+    public static void removeMapping(String oid, String name) {
+        String nameUC = name.toUpperCase(Locale.ROOT);
+        alg2OidMap.remove(nameUC);
+        oid2AlgMap.remove(oid);
+        // map upper case alg name to its original name
+        algAliasesMap.remove(nameUC);
+    }
+
     // No instances
     private AlgNameMapper() {
     }
@@ -126,7 +145,7 @@
         checkCacheVersion();
 
         // alg2OidMap map contains upper case keys
-        String result = alg2OidMap.get(algName.toUpperCase(Locale.US));
+        String result = alg2OidMap.get(algName.toUpperCase(Locale.ROOT));
         if (result != null) {
             return result;
         }
@@ -144,7 +163,7 @@
      * Returns algName for OID
      *
      * @param oid OID to be mapped
-     * @return algorithm name
+     * @return algorithm name or {@code null} if not found.
      */
     public static String map2AlgName(String oid) {
         checkCacheVersion();
@@ -172,7 +191,7 @@
      * @return algorithm name
      */
     public static String getStandardName(String algName) {
-        return algAliasesMap.get(algName.toUpperCase(Locale.US));
+        return algAliasesMap.get(algName.toUpperCase(Locale.ROOT));
     }
 
     // Searches given provider for mappings like
@@ -185,11 +204,11 @@
         for (String service : serviceName) {
             String keyPrfix2find = "Alg.Alias." + service + ".";
             for (Entry<Object, Object> me : entrySet) {
-                String key = (String)me.getKey();
+                String key = (String) me.getKey();
                 if (key.startsWith(keyPrfix2find)) {
                     String alias = key.substring(keyPrfix2find.length());
-                    String alg = (String)me.getValue();
-                    String algUC = alg.toUpperCase(Locale.US);
+                    String alg = (String) me.getValue();
+                    String algUC = alg.toUpperCase(Locale.ROOT);
                     if (isOID(alias)) {
                         if (alias.startsWith("OID.")) {
                             alias = alias.substring(4);
@@ -207,9 +226,9 @@
                             // map upper case alg name to its original name
                             algAliasesMap.put(algUC, alg);
                         }
-                           // Do not override known standard names
-                    } else if (!algAliasesMap.containsKey(alias.toUpperCase(Locale.US))) {
-                        algAliasesMap.put(alias.toUpperCase(Locale.US), alg);
+                    // Do not override known standard names
+                    } else if (!algAliasesMap.containsKey(alias.toUpperCase(Locale.ROOT))) {
+                        algAliasesMap.put(alias.toUpperCase(Locale.ROOT), alg);
                     }
                 }
             }
diff --git a/luni/src/main/native/AsynchronousCloseMonitor.cpp b/luni/src/main/native/AsynchronousCloseMonitor.cpp
index 31cde00..6c9b2e5 100644
--- a/luni/src/main/native/AsynchronousCloseMonitor.cpp
+++ b/luni/src/main/native/AsynchronousCloseMonitor.cpp
@@ -38,11 +38,7 @@
  * The specific signal chosen here is arbitrary, but bionic needs to know so that SIGRTMIN
  * starts at a higher value.
  */
-#if defined(__APPLE__)
-static const int BLOCKED_THREAD_SIGNAL = SIGUSR2;
-#else
 static const int BLOCKED_THREAD_SIGNAL = __SIGRTMIN + 2;
-#endif
 
 static void blockedThreadSignalHandler(int /*signal*/) {
     // Do nothing. We only sent this signal for its side-effect of interrupting syscalls.
diff --git a/luni/src/main/native/NetworkUtilities.cpp b/luni/src/main/native/NetworkUtilities.cpp
index 7215306..f2d0f8a 100644
--- a/luni/src/main/native/NetworkUtilities.cpp
+++ b/luni/src/main/native/NetworkUtilities.cpp
@@ -61,10 +61,6 @@
         addressLength = 16;
         sin_port = ntohs(sin6.sin6_port);
         scope_id = sin6.sin6_scope_id;
-    } else if (ss.ss_family == AF_UNIX) {
-        const sockaddr_un& sun = reinterpret_cast<const sockaddr_un&>(ss);
-        rawAddress = &sun.sun_path;
-        addressLength = strlen(sun.sun_path);
     } else {
         // We can't throw SocketException. We aren't meant to see bad addresses, so seeing one
         // really does imply an internal error.
@@ -83,14 +79,6 @@
     env->SetByteArrayRegion(byteArray.get(), 0, addressLength,
             reinterpret_cast<const jbyte*>(rawAddress));
 
-    if (ss.ss_family == AF_UNIX) {
-        // Note that we get here for AF_UNIX sockets on accept(2). The unix(7) man page claims
-        // that the peer's sun_path will contain the path, but in practice it doesn't, and the
-        // peer length is returned as 2 (meaning only the sun_family field was set).
-        static jmethodID ctor = env->GetMethodID(JniConstants::inetUnixAddressClass, "<init>", "([B)V");
-        return env->NewObject(JniConstants::inetUnixAddressClass, ctor, byteArray.get());
-    }
-
     static jmethodID getByAddressMethod = env->GetStaticMethodID(JniConstants::inetAddressClass,
             "getByAddress", "(Ljava/lang/String;[BI)Ljava/net/InetAddress;");
     if (getByAddressMethod == NULL) {
@@ -118,7 +106,7 @@
     }
 
     // Check this is an address family we support.
-    if (ss.ss_family != AF_INET && ss.ss_family != AF_INET6 && ss.ss_family != AF_UNIX) {
+    if (ss.ss_family != AF_INET && ss.ss_family != AF_INET6) {
         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                 "inetAddressToSockaddr bad family: %i", ss.ss_family);
         return false;
@@ -132,25 +120,6 @@
         return false;
     }
 
-    // Handle the AF_UNIX special case.
-    if (ss.ss_family == AF_UNIX) {
-        sockaddr_un& sun = reinterpret_cast<sockaddr_un&>(ss);
-
-        size_t path_length = env->GetArrayLength(addressBytes.get());
-        if (path_length >= sizeof(sun.sun_path)) {
-            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
-                                 "inetAddressToSockaddr path too long for AF_UNIX: %i", path_length);
-            return false;
-        }
-
-        // Copy the bytes...
-        jbyte* dst = reinterpret_cast<jbyte*>(&sun.sun_path);
-        memset(dst, 0, sizeof(sun.sun_path));
-        env->GetByteArrayRegion(addressBytes.get(), 0, path_length, dst);
-        sa_len = sizeof(sun.sun_path);
-        return true;
-    }
-
     // TODO: bionic's getnameinfo(3) seems to want its length parameter to be exactly
     // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
     // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
diff --git a/luni/src/main/native/NetworkUtilities.h b/luni/src/main/native/NetworkUtilities.h
index 6b720d4..db1ad1f 100644
--- a/luni/src/main/native/NetworkUtilities.h
+++ b/luni/src/main/native/NetworkUtilities.h
@@ -17,25 +17,24 @@
 #include "jni.h"
 #include <sys/socket.h>
 
-// Convert from sockaddr_storage to Inet4Address (AF_INET), Inet6Address (AF_INET6), or
-// InetUnixAddress (AF_UNIX). If 'port' is non-NULL and the address family includes a notion
+// Convert from sockaddr_storage to Inet4Address (AF_INET) or Inet6Address (AF_INET6).
+// If 'port' is non-NULL and the address family includes a notion
 // of port number, *port will be set to the port number.
 jobject sockaddrToInetAddress(JNIEnv* env, const sockaddr_storage& ss, int* port);
 
-// Convert from InetAddress to sockaddr_storage. An InetUnixAddress will be converted to
-// an AF_UNIX sockaddr_un. An Inet6Address will be converted to an AF_INET6 sockaddr_in6.
-// An Inet4Address will be converted to an IPv4-mapped AF_INET6 sockaddr_in6. This is what
-// you want if you're about to perform an operation on a socket, since all our sockets
-// are AF_INET6.
+// Convert from InetAddress to sockaddr_storage. An Inet6Address will be converted to an
+// AF_INET6 sockaddr_in6. An Inet4Address will be converted to an IPv4-mapped AF_INET6
+// sockaddr_in6. This is what you want if you're about to perform an operation on a socket,
+// since all our sockets are AF_INET6.
 bool inetAddressToSockaddr(JNIEnv* env, jobject inetAddress, int port,
                            sockaddr_storage& ss, socklen_t& sa_len);
 
-// Convert from InetAddress to sockaddr_storage. An InetUnixAddress will be converted to
-// an AF_UNIX sockaddr_un. An Inet6Address will be converted to an AF_INET6 sockaddr_in6.
-// An Inet4Address will be converted to a sockaddr_in. This is probably only useful for
-// getnameinfo(2), where we'll be presenting the result to the user and the user may actually
-// care whether the original address was pure IPv4 or an IPv4-mapped IPv6 address, and
-// for the MCAST_JOIN_GROUP, MCAST_LEAVE_GROUP, and other multicast socket options.
+// Convert from InetAddress to sockaddr_storage. An Inet6Address will be converted to an
+// AF_INET6 sockaddr_in6. An Inet4Address will be converted to a sockaddr_in. This is probably
+// only useful for getnameinfo(2), where we'll be presenting the result to the user and the
+// user may actually care whether the original address was pure IPv4 or an IPv4-mapped IPv6
+// address, and for the MCAST_JOIN_GROUP, MCAST_LEAVE_GROUP, and other multicast socket
+// options.
 bool inetAddressToSockaddrVerbatim(JNIEnv* env, jobject inetAddress, int port,
                                    sockaddr_storage& ss, socklen_t& sa_len);
 
diff --git a/luni/src/main/native/Portability.h b/luni/src/main/native/Portability.h
index 5900cb0..4df3353 100644
--- a/luni/src/main/native/Portability.h
+++ b/luni/src/main/native/Portability.h
@@ -17,64 +17,10 @@
 #ifndef PORTABILITY_H_included
 #define PORTABILITY_H_included
 
-#if defined(__APPLE__)
-
-// Mac OS.
-#include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_MAX_ALLOWED
-
-#include <libkern/OSByteOrder.h>
-#define bswap_16 OSSwapInt16
-#define bswap_32 OSSwapInt32
-#define bswap_64 OSSwapInt64
-
-#include <crt_externs.h>
-#define environ (*_NSGetEnviron())
-
-// Mac OS has a 64-bit off_t and no 32-bit compatibility cruft.
-#define flock64 flock
-#define ftruncate64 ftruncate
-#define isnanf __inline_isnanf
-#define lseek64 lseek
-#define pread64 pread
-#define pwrite64 pwrite
-
-// TODO: Darwin appears to have an fdatasync syscall.
-static inline int fdatasync(int fd) { return fsync(fd); }
-
-// For Linux-compatible sendfile(3).
-#include <sys/socket.h>
-#include <sys/types.h>
-static inline ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) {
-  off_t in_out_count = count;
-  int result = sendfile(in_fd, out_fd, *offset, &in_out_count, NULL, 0);
-  if (result == -1) {
-    return -1;
-  }
-  return in_out_count;
-}
-
-// For mincore(3).
-#define _DARWIN_C_SOURCE
-#include <sys/mman.h>
-#undef _DARWIN_C_SOURCE
-static inline int mincore(void* addr, size_t length, unsigned char* vec) {
-  return mincore(addr, length, reinterpret_cast<char*>(vec));
-}
-
-// For statfs(3).
-#include <sys/param.h>
-#include <sys/mount.h>
-
-#else
-
-// Bionic or glibc.
-
 #include <byteswap.h>
 #include <sys/sendfile.h>
 #include <sys/statvfs.h>
 
-#endif
-
 #include <netdb.h>
 #if defined(__BIONIC__)
 extern "C" int android_getaddrinfofornet(const char*, const char*, const struct addrinfo*, unsigned, unsigned, struct addrinfo**);
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index 787a149..c32e675 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -47,7 +47,6 @@
     REGISTER(register_java_lang_StringToReal);
     REGISTER(register_java_lang_System);
     REGISTER(register_java_math_NativeBN);
-    REGISTER(register_java_text_Bidi);
     REGISTER(register_java_util_jar_StrictJarFile);
     REGISTER(register_java_util_regex_Matcher);
     REGISTER(register_java_util_regex_Pattern);
@@ -55,16 +54,11 @@
     REGISTER(register_java_util_zip_CRC32);
     REGISTER(register_java_util_zip_Deflater);
     REGISTER(register_java_util_zip_Inflater);
-    REGISTER(register_libcore_icu_AlphabeticIndex);
     REGISTER(register_libcore_icu_ICU);
     REGISTER(register_libcore_icu_NativeCollation);
     REGISTER(register_libcore_icu_NativeConverter);
     REGISTER(register_libcore_icu_NativeDecimalFormat);
-    REGISTER(register_libcore_icu_NativeIDN);
-    REGISTER(register_libcore_icu_NativeNormalizer);
-    REGISTER(register_libcore_icu_NativePluralRules);
     REGISTER(register_libcore_icu_TimeZoneNames);
-    REGISTER(register_libcore_icu_Transliterator);
     REGISTER(register_libcore_io_AsynchronousCloseMonitor);
     REGISTER(register_libcore_io_Memory);
     REGISTER(register_libcore_io_Posix);
diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp
index a44d176..074bbef 100644
--- a/luni/src/main/native/android_system_OsConstants.cpp
+++ b/luni/src/main/native/android_system_OsConstants.cpp
@@ -30,22 +30,20 @@
 #include <stdlib.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
-#ifndef __APPLE__
 #include <sys/prctl.h>
-#endif
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/un.h>
 #include <sys/wait.h>
+#include <sys/xattr.h>
 #include <unistd.h>
 
 #include <net/if_arp.h>
 #include <linux/if_ether.h>
 
 // After the others because these are not necessarily self-contained in glibc.
-#ifndef __APPLE__
 #include <linux/if_addr.h>
 #include <linux/rtnetlink.h>
-#endif
 
 #include <net/if.h> // After <sys/socket.h> to work around a Mac header file bug.
 
@@ -210,6 +208,7 @@
     initConstant(env, c, "ETIME", ETIME);
     initConstant(env, c, "ETIMEDOUT", ETIMEDOUT);
     initConstant(env, c, "ETXTBSY", ETXTBSY);
+    initConstant(env, c, "EUSERS", EUSERS);
 #if EWOULDBLOCK != EAGAIN
 #error EWOULDBLOCK != EAGAIN
 #endif
@@ -383,6 +382,7 @@
     initConstant(env, c, "O_RDONLY", O_RDONLY);
     initConstant(env, c, "O_RDWR", O_RDWR);
     initConstant(env, c, "O_SYNC", O_SYNC);
+    initConstant(env, c, "O_DSYNC", O_DSYNC);
     initConstant(env, c, "O_TRUNC", O_TRUNC);
     initConstant(env, c, "O_WRONLY", O_WRONLY);
     initConstant(env, c, "POLLERR", POLLERR);
@@ -413,7 +413,6 @@
 // members. The best we can do (barring UAPI / kernel version checks) is
 // to hope they exist on all host linuxes we're building on. These
 // constants have been around since 2.6.35 at least, so we should be ok.
-#if !defined(__APPLE__)
     initConstant(env, c, "RT_SCOPE_HOST", RT_SCOPE_HOST);
     initConstant(env, c, "RT_SCOPE_LINK", RT_SCOPE_LINK);
     initConstant(env, c, "RT_SCOPE_NOWHERE", RT_SCOPE_NOWHERE);
@@ -432,7 +431,6 @@
     initConstant(env, c, "RTMGRP_NEIGH", RTMGRP_NEIGH);
     initConstant(env, c, "RTMGRP_NOTIFY", RTMGRP_NOTIFY);
     initConstant(env, c, "RTMGRP_TC", RTMGRP_TC);
-#endif
     initConstant(env, c, "SEEK_CUR", SEEK_CUR);
     initConstant(env, c, "SEEK_END", SEEK_END);
     initConstant(env, c, "SEEK_SET", SEEK_SET);
@@ -549,6 +547,9 @@
     initConstant(env, c, "S_IXOTH", S_IXOTH);
     initConstant(env, c, "S_IXUSR", S_IXUSR);
     initConstant(env, c, "TCP_NODELAY", TCP_NODELAY);
+    initConstant(env, c, "TIOCOUTQ", TIOCOUTQ);
+    // UNIX_PATH_MAX is mentioned in some versions of unix(7), but not actually declared.
+    initConstant(env, c, "UNIX_PATH_MAX", sizeof(sockaddr_un::sun_path));
     initConstant(env, c, "WCONTINUED", WCONTINUED);
     initConstant(env, c, "WEXITED", WEXITED);
     initConstant(env, c, "WNOHANG", WNOHANG);
@@ -556,6 +557,8 @@
     initConstant(env, c, "WSTOPPED", WSTOPPED);
     initConstant(env, c, "WUNTRACED", WUNTRACED);
     initConstant(env, c, "W_OK", W_OK);
+    initConstant(env, c, "XATTR_CREATE", XATTR_CREATE);
+    initConstant(env, c, "XATTR_REPLACE", XATTR_REPLACE);
     initConstant(env, c, "X_OK", X_OK);
     initConstant(env, c, "_SC_2_CHAR_TERM", _SC_2_CHAR_TERM);
     initConstant(env, c, "_SC_2_C_BIND", _SC_2_C_BIND);
diff --git a/luni/src/main/native/cbigint.cpp b/luni/src/main/native/cbigint.cpp
index 6943ca2..c202ed7 100644
--- a/luni/src/main/native/cbigint.cpp
+++ b/luni/src/main/native/cbigint.cpp
@@ -18,31 +18,9 @@
 #include <string.h>
 #include "cbigint.h"
 
-#if defined(__linux__) || defined(__APPLE__)
-#define USE_LL
-#endif
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define at(i) (i)
-#else
-#define at(i) ((i)^1)
-/* the sequence for halfAt is -1, 2, 1, 4, 3, 6, 5, 8... */
-/* and it should correspond to 0, 1, 2, 3, 4, 5, 6, 7... */
-#define halfAt(i) (-((-(i)) ^ 1))
-#endif
-
 #define HIGH_IN_U64(u64) ((u64) >> 32)
-#if defined(USE_LL)
 #define LOW_IN_U64(u64) ((u64) & 0x00000000FFFFFFFFLL)
-#else
-#if defined(USE_L)
-#define LOW_IN_U64(u64) ((u64) & 0x00000000FFFFFFFFL)
-#else
-#define LOW_IN_U64(u64) ((u64) & 0x00000000FFFFFFFF)
-#endif /* USE_L */
-#endif /* USE_LL */
 
-#if defined(USE_LL)
 #define TEN_E1 (0xALL)
 #define TEN_E2 (0x64LL)
 #define TEN_E3 (0x3E8LL)
@@ -53,54 +31,15 @@
 #define TEN_E8 (0x5F5E100LL)
 #define TEN_E9 (0x3B9ACA00LL)
 #define TEN_E19 (0x8AC7230489E80000LL)
-#else
-#if defined(USE_L)
-#define TEN_E1 (0xAL)
-#define TEN_E2 (0x64L)
-#define TEN_E3 (0x3E8L)
-#define TEN_E4 (0x2710L)
-#define TEN_E5 (0x186A0L)
-#define TEN_E6 (0xF4240L)
-#define TEN_E7 (0x989680L)
-#define TEN_E8 (0x5F5E100L)
-#define TEN_E9 (0x3B9ACA00L)
-#define TEN_E19 (0x8AC7230489E80000L)
-#else
-#define TEN_E1 (0xA)
-#define TEN_E2 (0x64)
-#define TEN_E3 (0x3E8)
-#define TEN_E4 (0x2710)
-#define TEN_E5 (0x186A0)
-#define TEN_E6 (0xF4240)
-#define TEN_E7 (0x989680)
-#define TEN_E8 (0x5F5E100)
-#define TEN_E9 (0x3B9ACA00)
-#define TEN_E19 (0x8AC7230489E80000)
-#endif /* USE_L */
-#endif /* USE_LL */
 
 #define TIMES_TEN(x) (((x) << 3) + ((x) << 1))
 #define bitSection(x, mask, shift) (((x) & (mask)) >> (shift))
 #define CREATE_DOUBLE_BITS(normalizedM, e) (((normalizedM) & MANTISSA_MASK) | ((static_cast<uint64_t>((e) + E_OFFSET)) << 52))
 
-#if defined(USE_LL)
 #define MANTISSA_MASK (0x000FFFFFFFFFFFFFLL)
 #define EXPONENT_MASK (0x7FF0000000000000LL)
 #define NORMAL_MASK (0x0010000000000000LL)
 #define SIGN_MASK (0x8000000000000000LL)
-#else
-#if defined(USE_L)
-#define MANTISSA_MASK (0x000FFFFFFFFFFFFFL)
-#define EXPONENT_MASK (0x7FF0000000000000L)
-#define NORMAL_MASK (0x0010000000000000L)
-#define SIGN_MASK (0x8000000000000000L)
-#else
-#define MANTISSA_MASK (0x000FFFFFFFFFFFFF)
-#define EXPONENT_MASK (0x7FF0000000000000)
-#define NORMAL_MASK (0x0010000000000000)
-#define SIGN_MASK (0x8000000000000000)
-#endif /* USE_L */
-#endif /* USE_LL */
 
 #define E_OFFSET (1075)
 
@@ -229,53 +168,28 @@
   do
     {
       product =
-        HIGH_IN_U64 (product) + result[at (resultIndex)] +
+        HIGH_IN_U64 (product) + result[resultIndex] +
         arg2 * LOW_U32_FROM_PTR (arg1 + index);
-      result[at (resultIndex)] = LOW_U32_FROM_VAR (product);
+      result[resultIndex] = LOW_U32_FROM_VAR (product);
       ++resultIndex;
       product =
-        HIGH_IN_U64 (product) + result[at (resultIndex)] +
+        HIGH_IN_U64 (product) + result[resultIndex] +
         arg2 * HIGH_U32_FROM_PTR (arg1 + index);
-      result[at (resultIndex)] = LOW_U32_FROM_VAR (product);
+      result[resultIndex] = LOW_U32_FROM_VAR (product);
       ++resultIndex;
     }
   while (++index < length);
 
-  result[at (resultIndex)] += HIGH_U32_FROM_VAR (product);
-  if (result[at (resultIndex)] < HIGH_U32_FROM_VAR (product))
+  result[resultIndex] += HIGH_U32_FROM_VAR (product);
+  if (result[resultIndex] < HIGH_U32_FROM_VAR (product))
     {
       /* must be careful with ++ operator and macro expansion */
       ++resultIndex;
-      while (++result[at (resultIndex)] == 0)
+      while (++result[resultIndex] == 0)
         ++resultIndex;
     }
 }
 
-#if __BYTE_ORDER != __LITTLE_ENDIAN
-void simpleMultiplyAddHighPrecisionBigEndianFix(uint64_t* arg1, int32_t length, uint64_t arg2, uint32_t* result) {
-    /* Assumes result can hold the product and arg2 only holds 32 bits of information */
-    int32_t index = 0;
-    int32_t resultIndex = 0;
-    uint64_t product = 0;
-
-    do {
-        product = HIGH_IN_U64(product) + result[halfAt(resultIndex)] + arg2 * LOW_U32_FROM_PTR(arg1 + index);
-        result[halfAt(resultIndex)] = LOW_U32_FROM_VAR(product);
-        ++resultIndex;
-        product = HIGH_IN_U64(product) + result[halfAt(resultIndex)] + arg2 * HIGH_U32_FROM_PTR(arg1 + index);
-        result[halfAt(resultIndex)] = LOW_U32_FROM_VAR(product);
-        ++resultIndex;
-    } while (++index < length);
-
-    result[halfAt(resultIndex)] += HIGH_U32_FROM_VAR(product);
-    if (result[halfAt(resultIndex)] < HIGH_U32_FROM_VAR(product)) {
-        /* must be careful with ++ operator and macro expansion */
-        ++resultIndex;
-        while (++result[halfAt(resultIndex)] == 0) ++resultIndex;
-    }
-}
-#endif
-
 void
 multiplyHighPrecision (uint64_t * arg1, int32_t length1, uint64_t * arg2, int32_t length2,
                        uint64_t * result, int32_t length)
@@ -304,11 +218,7 @@
     {
       simpleMultiplyAddHighPrecision (arg1, length1, LOW_IN_U64 (arg2[count]),
                                       resultIn32 + (++index));
-#if __BYTE_ORDER == __LITTLE_ENDIAN
       simpleMultiplyAddHighPrecision(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index));
-#else
-      simpleMultiplyAddHighPrecisionBigEndianFix(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index));
-#endif
     }
 }
 
@@ -374,7 +284,6 @@
   if (*y == 0)
     return 0;
 
-#if defined(USE_LL)
   if (*y & 0xFFFFFFFF00000000LL)
     {
       x = HIGH_U32_FROM_PTR (y);
@@ -385,31 +294,6 @@
       x = LOW_U32_FROM_PTR (y);
       result = 0;
     }
-#else
-#if defined(USE_L)
-  if (*y & 0xFFFFFFFF00000000L)
-    {
-      x = HIGH_U32_FROM_PTR (y);
-      result = 32;
-    }
-  else
-    {
-      x = LOW_U32_FROM_PTR (y);
-      result = 0;
-    }
-#else
-  if (*y & 0xFFFFFFFF00000000)
-    {
-      x = HIGH_U32_FROM_PTR (y);
-      result = 32;
-    }
-  else
-    {
-      x = LOW_U32_FROM_PTR (y);
-      result = 0;
-    }
-#endif /* USE_L */
-#endif /* USE_LL */
 
   if (x & 0xFFFF0000)
     {
@@ -445,7 +329,6 @@
   if (*y == 0)
     return 0;
 
-#if defined(USE_LL)
   if (*y & 0x00000000FFFFFFFFLL)
     {
       x = LOW_U32_FROM_PTR (y);
@@ -456,31 +339,6 @@
       x = HIGH_U32_FROM_PTR (y);
       result = 32;
     }
-#else
-#if defined(USE_L)
-  if (*y & 0x00000000FFFFFFFFL)
-    {
-      x = LOW_U32_FROM_PTR (y);
-      result = 0;
-    }
-  else
-    {
-      x = HIGH_U32_FROM_PTR (y);
-      result = 32;
-    }
-#else
-  if (*y & 0x00000000FFFFFFFF)
-    {
-      x = LOW_U32_FROM_PTR (y);
-      result = 0;
-    }
-  else
-    {
-      x = HIGH_U32_FROM_PTR (y);
-      result = 32;
-    }
-#endif /* USE_L */
-#endif /* USE_LL */
 
   if (!(x & 0xFFFF))
     {
diff --git a/luni/src/main/native/java_lang_ProcessManager.cpp b/luni/src/main/native/java_lang_ProcessManager.cpp
index 3a97ac6..efa5e77 100644
--- a/luni/src/main/native/java_lang_ProcessManager.cpp
+++ b/luni/src/main/native/java_lang_ProcessManager.cpp
@@ -38,11 +38,6 @@
 static void CloseNonStandardFds(int status_pipe_fd) {
   // On Cygwin, Linux, and Solaris, the best way to close iterates over "/proc/self/fd/".
   const char* fd_path = "/proc/self/fd";
-#if defined(__APPLE__)
-  // On Mac OS, there's "/dev/fd/" which Linux seems to link to "/proc/self/fd/",
-  // but which on Solaris appears to be something quite different.
-  fd_path = "/dev/fd";
-#endif
 
   // Keep track of the system properties fd so we don't close it.
   int properties_fd = -1;
diff --git a/luni/src/main/native/java_lang_System.cpp b/luni/src/main/native/java_lang_System.cpp
index 306adab..1ba230a 100644
--- a/luni/src/main/native/java_lang_System.cpp
+++ b/luni/src/main/native/java_lang_System.cpp
@@ -34,7 +34,7 @@
 #include <time.h>
 #include <unistd.h>
 
-#if defined(HAVE_ANDROID_OS)
+#if defined(__ANDROID__)
 extern "C" void android_get_LD_LIBRARY_PATH(char*, size_t);
 #endif
 
@@ -91,7 +91,7 @@
 #endif
 
     const char* library_path = getenv("LD_LIBRARY_PATH");
-#if defined(HAVE_ANDROID_OS)
+#if defined(__ANDROID__)
     if (library_path == NULL) {
         android_get_LD_LIBRARY_PATH(path, sizeof(path));
         library_path = path;
@@ -113,15 +113,9 @@
 }
 
 static jlong System_nanoTime(JNIEnv*, jclass) {
-#if defined(__linux__)
     timespec now;
     clock_gettime(CLOCK_MONOTONIC, &now);
     return now.tv_sec * 1000000000LL + now.tv_nsec;
-#else // __APPLE__
-    timeval now;
-    gettimeofday(&now, NULL);
-    return static_cast<jlong>(now.tv_sec) * 1000000000LL + now.tv_usec * 1000LL;
-#endif
 }
 
 static JNINativeMethod gMethods[] = {
diff --git a/luni/src/main/native/java_text_Bidi.cpp b/luni/src/main/native/java_text_Bidi.cpp
deleted file mode 100644
index 6a3e751..0000000
--- a/luni/src/main/native/java_text_Bidi.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-#define LOG_TAG "Bidi"
-
-#include "IcuUtilities.h"
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "JniException.h"
-#include "ScopedPrimitiveArray.h"
-#include "unicode/ubidi.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <memory>
-
-struct BiDiData {
-    BiDiData(UBiDi* biDi) : mBiDi(biDi) {
-    }
-
-    ~BiDiData() {
-        ubidi_close(mBiDi);
-    }
-
-    UBiDiLevel* embeddingLevels() {
-        return reinterpret_cast<UBiDiLevel*>(&mEmbeddingLevels[0]);
-    }
-
-    void setEmbeddingLevels(jbyte* newEmbeddingLevels) {
-        mEmbeddingLevels.reset(newEmbeddingLevels);
-    }
-
-    UBiDi* uBiDi() {
-        return mBiDi;
-    }
-
-private:
-    UBiDi* mBiDi;
-    std::unique_ptr<jbyte[]> mEmbeddingLevels;
-
-    // Disallow copy and assignment.
-    BiDiData(const BiDiData&);
-    void operator=(const BiDiData&);
-};
-
-static BiDiData* biDiData(jlong ptr) {
-    return reinterpret_cast<BiDiData*>(static_cast<uintptr_t>(ptr));
-}
-
-static UBiDi* uBiDi(jlong ptr) {
-    return reinterpret_cast<BiDiData*>(static_cast<uintptr_t>(ptr))->uBiDi();
-}
-
-static jlong Bidi_ubidi_open(JNIEnv*, jclass) {
-    return reinterpret_cast<uintptr_t>(new BiDiData(ubidi_open()));
-}
-
-static void Bidi_ubidi_close(JNIEnv*, jclass, jlong ptr) {
-    delete biDiData(ptr);
-}
-
-static void Bidi_ubidi_setPara(JNIEnv* env, jclass, jlong ptr, jcharArray text, jint length, jint paraLevel, jbyteArray newEmbeddingLevels) {
-    BiDiData* data = biDiData(ptr);
-    // Copy the new embedding levels from the Java heap to the native heap.
-    if (newEmbeddingLevels != NULL) {
-        jbyte* dst;
-        data->setEmbeddingLevels(dst = new jbyte[length]);
-        env->GetByteArrayRegion(newEmbeddingLevels, 0, length, dst);
-    } else {
-        data->setEmbeddingLevels(NULL);
-    }
-    ScopedCharArrayRO chars(env, text);
-    if (chars.get() == NULL) {
-        return;
-    }
-    UErrorCode err = U_ZERO_ERROR;
-    ubidi_setPara(data->uBiDi(), chars.get(), length, paraLevel, data->embeddingLevels(), &err);
-    maybeThrowIcuException(env, "ubidi_setPara", err);
-}
-
-static jlong Bidi_ubidi_setLine(JNIEnv* env, jclass, jlong ptr, jint start, jint limit) {
-    UErrorCode status = U_ZERO_ERROR;
-    UBiDi* sized = ubidi_openSized(limit - start, 0, &status);
-    if (maybeThrowIcuException(env, "ubidi_openSized", status)) {
-        return 0;
-    }
-    std::unique_ptr<BiDiData> lineData(new BiDiData(sized));
-    ubidi_setLine(uBiDi(ptr), start, limit, lineData->uBiDi(), &status);
-    maybeThrowIcuException(env, "ubidi_setLine", status);
-    return reinterpret_cast<uintptr_t>(lineData.release());
-}
-
-static jint Bidi_ubidi_getDirection(JNIEnv*, jclass, jlong ptr) {
-    return ubidi_getDirection(uBiDi(ptr));
-}
-
-static jint Bidi_ubidi_getLength(JNIEnv*, jclass, jlong ptr) {
-    return ubidi_getLength(uBiDi(ptr));
-}
-
-static jbyte Bidi_ubidi_getParaLevel(JNIEnv*, jclass, jlong ptr) {
-    return ubidi_getParaLevel(uBiDi(ptr));
-}
-
-static jbyteArray Bidi_ubidi_getLevels(JNIEnv* env, jclass, jlong ptr) {
-    UErrorCode status = U_ZERO_ERROR;
-    const UBiDiLevel* levels = ubidi_getLevels(uBiDi(ptr), &status);
-    if (maybeThrowIcuException(env, "ubidi_getLevels", status)) {
-        return NULL;
-    }
-    int len = ubidi_getLength(uBiDi(ptr));
-    jbyteArray result = env->NewByteArray(len);
-    env->SetByteArrayRegion(result, 0, len, reinterpret_cast<const jbyte*>(levels));
-    return result;
-}
-
-static jint Bidi_ubidi_countRuns(JNIEnv* env, jclass, jlong ptr) {
-    UErrorCode status = U_ZERO_ERROR;
-    int count = ubidi_countRuns(uBiDi(ptr), &status);
-    maybeThrowIcuException(env, "ubidi_countRuns", status);
-    return count;
-}
-
-/**
- * TODO: if we care about performance, we might just want to use an int[] instead of a Run[].
- */
-static jobjectArray Bidi_ubidi_getRuns(JNIEnv* env, jclass, jlong ptr) {
-    UBiDi* ubidi = uBiDi(ptr);
-    UErrorCode status = U_ZERO_ERROR;
-    int runCount = ubidi_countRuns(ubidi, &status);
-    if (maybeThrowIcuException(env, "ubidi_countRuns", status)) {
-        return NULL;
-    }
-    static jmethodID bidiRunConstructor =
-            env->GetMethodID(JniConstants::bidiRunClass, "<init>", "(III)V");
-    jobjectArray runs = env->NewObjectArray(runCount, JniConstants::bidiRunClass, NULL);
-    UBiDiLevel level = 0;
-    int start = 0;
-    int limit = 0;
-    for (int i = 0; i < runCount; ++i) {
-        ubidi_getLogicalRun(ubidi, start, &limit, &level);
-        jobject run = env->NewObject(JniConstants::bidiRunClass, bidiRunConstructor, start, limit, level);
-        env->SetObjectArrayElement(runs, i, run);
-        start = limit;
-    }
-    return runs;
-}
-
-static jintArray Bidi_ubidi_reorderVisual(JNIEnv* env, jclass, jbyteArray javaLevels, jint length) {
-    ScopedByteArrayRO levelBytes(env, javaLevels);
-    if (levelBytes.get() == NULL) {
-        return NULL;
-    }
-
-    const UBiDiLevel* levels = reinterpret_cast<const UBiDiLevel*>(levelBytes.get());
-
-    std::unique_ptr<int[]> indexMap(new int[length]);
-    ubidi_reorderVisual(levels, length, &indexMap[0]);
-
-    jintArray result = env->NewIntArray(length);
-    env->SetIntArrayRegion(result, 0, length, &indexMap[0]);
-    return result;
-}
-
-static JNINativeMethod gMethods[] = {
-    NATIVE_METHOD(Bidi, ubidi_close, "(J)V"),
-    NATIVE_METHOD(Bidi, ubidi_countRuns, "(J)I"),
-    NATIVE_METHOD(Bidi, ubidi_getDirection, "(J)I"),
-    NATIVE_METHOD(Bidi, ubidi_getLength, "(J)I"),
-    NATIVE_METHOD(Bidi, ubidi_getLevels, "(J)[B"),
-    NATIVE_METHOD(Bidi, ubidi_getParaLevel, "(J)B"),
-    NATIVE_METHOD(Bidi, ubidi_getRuns, "(J)[Ljava/text/Bidi$Run;"),
-    NATIVE_METHOD(Bidi, ubidi_open, "()J"),
-    NATIVE_METHOD(Bidi, ubidi_reorderVisual, "([BI)[I"),
-    NATIVE_METHOD(Bidi, ubidi_setLine, "(JII)J"),
-    NATIVE_METHOD(Bidi, ubidi_setPara, "(J[CII[B)V"),
-};
-void register_java_text_Bidi(JNIEnv* env) {
-    jniRegisterNativeMethods(env, "java/text/Bidi", gMethods, NELEM(gMethods));
-}
diff --git a/luni/src/main/native/java_util_jar_StrictJarFile.cpp b/luni/src/main/native/java_util_jar_StrictJarFile.cpp
index 82547bd..13a4db38 100644
--- a/luni/src/main/native/java_util_jar_StrictJarFile.cpp
+++ b/luni/src/main/native/java_util_jar_StrictJarFile.cpp
@@ -97,11 +97,11 @@
   int32_t error = 0;
   if (prefixChars.size() == 0) {
     error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
-                           handle->CookieAddress(), NULL);
+                           handle->CookieAddress(), NULL, NULL);
   } else {
-    ZipEntryName entry_name(prefixChars.c_str());
+    ZipString entry_name(prefixChars.c_str());
     error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
-                           handle->CookieAddress(), &entry_name);
+                           handle->CookieAddress(), &entry_name, NULL);
   }
 
   if (error) {
@@ -114,7 +114,7 @@
 
 static jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterationHandle) {
   ZipEntry data;
-  ZipEntryName entryName;
+  ZipString entryName;
 
   IterationHandle* handle = reinterpret_cast<IterationHandle*>(iterationHandle);
   const int32_t error = Next(*handle->CookieAddress(), &data, &entryName);
@@ -140,7 +140,7 @@
 
   ZipEntry data;
   const int32_t error = FindEntry(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
-                                  ZipEntryName(entryNameChars.c_str()), &data);
+                                  ZipString(entryNameChars.c_str()), &data);
   if (error) {
     return NULL;
   }
diff --git a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
deleted file mode 100644
index acc247b..0000000
--- a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#define LOG_TAG "AlphabeticIndex"
-
-#include "IcuUtilities.h"
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "JniException.h"
-#include "ScopedIcuLocale.h"
-#include "ScopedJavaUnicodeString.h"
-#include "unicode/alphaindex.h"
-#include "unicode/uniset.h"
-
-static icu::AlphabeticIndex* fromPeer(jlong peer) {
-  return reinterpret_cast<icu::AlphabeticIndex*>(static_cast<uintptr_t>(peer));
-}
-
-static jlong AlphabeticIndex_create(JNIEnv* env, jclass, jstring javaLocaleName) {
-  UErrorCode status = U_ZERO_ERROR;
-  ScopedIcuLocale icuLocale(env, javaLocaleName);
-  if (!icuLocale.valid()) {
-    return 0;
-  }
-  icu::AlphabeticIndex* ai = new icu::AlphabeticIndex(icuLocale.locale(), status);
-  if (maybeThrowIcuException(env, "AlphabeticIndex", status)) {
-    return 0;
-  }
-  return reinterpret_cast<uintptr_t>(ai);
-}
-
-static void AlphabeticIndex_destroy(JNIEnv*, jclass, jlong peer) {
-  delete fromPeer(peer);
-}
-
-static jint AlphabeticIndex_getMaxLabelCount(JNIEnv*, jclass, jlong peer) {
-  icu::AlphabeticIndex* ai = fromPeer(peer);
-  return ai->getMaxLabelCount();
-}
-
-static void AlphabeticIndex_setMaxLabelCount(JNIEnv* env, jclass, jlong peer, jint count) {
-  icu::AlphabeticIndex* ai = fromPeer(peer);
-  UErrorCode status = U_ZERO_ERROR;
-  ai->setMaxLabelCount(count, status);
-  maybeThrowIcuException(env, "AlphabeticIndex::setMaxLabelCount", status);
-}
-
-static void AlphabeticIndex_addLabels(JNIEnv* env, jclass, jlong peer, jstring javaLocaleName) {
-  icu::AlphabeticIndex* ai = fromPeer(peer);
-  ScopedIcuLocale icuLocale(env, javaLocaleName);
-  if (!icuLocale.valid()) {
-    return;
-  }
-  UErrorCode status = U_ZERO_ERROR;
-  ai->addLabels(icuLocale.locale(), status);
-  maybeThrowIcuException(env, "AlphabeticIndex::addLabels", status);
-}
-
-static void AlphabeticIndex_addLabelRange(JNIEnv* env, jclass, jlong peer,
-                                          jint codePointStart, jint codePointEnd) {
-  icu::AlphabeticIndex* ai = fromPeer(peer);
-  UErrorCode status = U_ZERO_ERROR;
-  ai->addLabels(icu::UnicodeSet(codePointStart, codePointEnd), status);
-  maybeThrowIcuException(env, "AlphabeticIndex::addLabels", status);
-}
-
-static jint AlphabeticIndex_getBucketCount(JNIEnv* env, jclass, jlong peer) {
-  icu::AlphabeticIndex* ai = fromPeer(peer);
-  UErrorCode status = U_ZERO_ERROR;
-  jint result = ai->getBucketCount(status);
-  if (maybeThrowIcuException(env, "AlphabeticIndex::getBucketCount", status)) {
-    return -1;
-  }
-  return result;
-}
-
-static jint AlphabeticIndex_getBucketIndex(JNIEnv* env, jclass, jlong peer, jstring javaString) {
-  icu::AlphabeticIndex* ai = fromPeer(peer);
-  ScopedJavaUnicodeString string(env, javaString);
-  if (!string.valid()) {
-    return -1;
-  }
-  UErrorCode status = U_ZERO_ERROR;
-  jint result = ai->getBucketIndex(string.unicodeString(), status);
-  if (maybeThrowIcuException(env, "AlphabeticIndex::getBucketIndex", status)) {
-    return -1;
-  }
-  return result;
-}
-
-static jstring AlphabeticIndex_getBucketLabel(JNIEnv* env, jclass, jlong peer, jint index) {
-  if (index < 0) {
-    jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "Invalid index: %d", index);
-    return NULL;
-  }
-
-  // Iterate to the nth bucket.
-  icu::AlphabeticIndex* ai = fromPeer(peer);
-  UErrorCode status = U_ZERO_ERROR;
-  ai->resetBucketIterator(status);
-  if (maybeThrowIcuException(env, "AlphabeticIndex::resetBucketIterator", status)) {
-    return NULL;
-  }
-  for (jint i = 0; i <= index; ++i) {
-    if (!ai->nextBucket(status)) {
-      jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "Invalid index: %d", index);
-      return NULL;
-    }
-    if (maybeThrowIcuException(env, "AlphabeticIndex::nextBucket", status)) {
-      return NULL;
-    }
-  }
-
-  // Return "" for the underflow/inflow/overflow buckets.
-  if (ai->getBucketLabelType() != U_ALPHAINDEX_NORMAL) {
-    return env->NewStringUTF("");
-  }
-
-  const icu::UnicodeString& label(ai->getBucketLabel());
-  return env->NewString(label.getBuffer(), label.length());
-}
-
-static jlong AlphabeticIndex_buildImmutableIndex(JNIEnv* env, jclass, jlong peer) {
-  icu::AlphabeticIndex* ai = fromPeer(peer);
-  UErrorCode status = U_ZERO_ERROR;
-  icu::AlphabeticIndex::ImmutableIndex* ii = ai->buildImmutableIndex(status);
-  if (maybeThrowIcuException(env, "AlphabeticIndex::buildImmutableIndex", status)) {
-    return 0;
-  }
-  return reinterpret_cast<uintptr_t>(ii);
-}
-
-static icu::AlphabeticIndex::ImmutableIndex* immutableIndexFromPeer(jlong peer) {
-  return reinterpret_cast<icu::AlphabeticIndex::ImmutableIndex*>(static_cast<uintptr_t>(peer));
-}
-
-static jint ImmutableIndex_getBucketCount(JNIEnv*, jclass, jlong peer) {
-  icu::AlphabeticIndex::ImmutableIndex* ii = immutableIndexFromPeer(peer);
-  return ii->getBucketCount();
-}
-
-static jint ImmutableIndex_getBucketIndex(JNIEnv* env, jclass, jlong peer, jstring javaString) {
-  icu::AlphabeticIndex::ImmutableIndex* ii = immutableIndexFromPeer(peer);
-  ScopedJavaUnicodeString string(env, javaString);
-  if (!string.valid()) {
-    return -1;
-  }
-  UErrorCode status = U_ZERO_ERROR;
-  jint result = ii->getBucketIndex(string.unicodeString(), status);
-  if (maybeThrowIcuException(env, "AlphabeticIndex::ImmutableIndex::getBucketIndex", status)) {
-    return -1;
-  }
-  return result;
-}
-
-static jstring ImmutableIndex_getBucketLabel(JNIEnv* env, jclass, jlong peer, jint index) {
-  icu::AlphabeticIndex::ImmutableIndex* ii = immutableIndexFromPeer(peer);
-  const icu::AlphabeticIndex::Bucket* bucket = ii->getBucket(index);
-  if (bucket == NULL) {
-    jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "Invalid index: %d", index);
-    return NULL;
-  }
-
-  // Return "" for the underflow/inflow/overflow buckets.
-  if (bucket->getLabelType() != U_ALPHAINDEX_NORMAL) {
-    return env->NewStringUTF("");
-  }
-
-  const icu::UnicodeString& label(bucket->getLabel());
-  return env->NewString(label.getBuffer(), label.length());
-}
-
-static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(AlphabeticIndex, create, "(Ljava/lang/String;)J"),
-  NATIVE_METHOD(AlphabeticIndex, destroy, "(J)V"),
-  NATIVE_METHOD(AlphabeticIndex, getMaxLabelCount, "(J)I"),
-  NATIVE_METHOD(AlphabeticIndex, setMaxLabelCount, "(JI)V"),
-  NATIVE_METHOD(AlphabeticIndex, addLabels, "(JLjava/lang/String;)V"),
-  NATIVE_METHOD(AlphabeticIndex, addLabelRange, "(JII)V"),
-  NATIVE_METHOD(AlphabeticIndex, getBucketCount, "(J)I"),
-  NATIVE_METHOD(AlphabeticIndex, getBucketIndex, "(JLjava/lang/String;)I"),
-  NATIVE_METHOD(AlphabeticIndex, getBucketLabel, "(JI)Ljava/lang/String;"),
-  NATIVE_METHOD(AlphabeticIndex, buildImmutableIndex, "(J)J"),
-};
-static JNINativeMethod gImmutableIndexMethods[] = {
-  NATIVE_METHOD(ImmutableIndex, getBucketCount, "(J)I"),
-  NATIVE_METHOD(ImmutableIndex, getBucketIndex, "(JLjava/lang/String;)I"),
-  NATIVE_METHOD(ImmutableIndex, getBucketLabel, "(JI)Ljava/lang/String;"),
-};
-void register_libcore_icu_AlphabeticIndex(JNIEnv* env) {
-  jniRegisterNativeMethods(env, "libcore/icu/AlphabeticIndex", gMethods, NELEM(gMethods));
-  jniRegisterNativeMethods(env, "libcore/icu/AlphabeticIndex$ImmutableIndex", gImmutableIndexMethods, NELEM(gImmutableIndexMethods));
-}
diff --git a/luni/src/main/native/libcore_icu_NativeIDN.cpp b/luni/src/main/native/libcore_icu_NativeIDN.cpp
deleted file mode 100644
index 43f3ce5..0000000
--- a/luni/src/main/native/libcore_icu_NativeIDN.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#define LOG_TAG "NativeIDN"
-
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "ScopedStringChars.h"
-#include "unicode/uidna.h"
-
-static bool isLabelSeparator(const UChar ch) {
-    switch (ch) {
-    case 0x3002: // ideographic full stop
-    case 0xff0e: // fullwidth full stop
-    case 0xff61: // halfwidth ideographic full stop
-        return true;
-    default:
-        return false;
-    }
-}
-
-static jstring NativeIDN_convertImpl(JNIEnv* env, jclass, jstring javaSrc, jint flags, jboolean toAscii) {
-    ScopedStringChars src(env, javaSrc);
-    if (src.get() == NULL) {
-        return NULL;
-    }
-    UChar dst[256];
-    UErrorCode status = U_ZERO_ERROR;
-
-    // We're stuck implementing IDNA-2003 for now since that's what we specify.
-    //
-    // TODO: Change our spec to IDNA-2008 + UTS-46 compatibility processing if
-    // it's safe enough.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-    size_t resultLength = toAscii
-        ? uidna_IDNToASCII(src.get(), src.size(), &dst[0], sizeof(dst), flags, NULL, &status)
-        : uidna_IDNToUnicode(src.get(), src.size(), &dst[0], sizeof(dst), flags, NULL, &status);
-#pragma GCC diagnostic pop
-
-    if (U_FAILURE(status)) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", u_errorName(status));
-        return NULL;
-    }
-    if (!toAscii) {
-        // ICU only translates separators to ASCII for toASCII.
-        // Java expects the translation for toUnicode too.
-        // We may as well do this here, while the string is still mutable.
-        for (size_t i = 0; i < resultLength; ++i) {
-            if (isLabelSeparator(dst[i])) {
-                dst[i] = '.';
-            }
-        }
-    }
-    return env->NewString(&dst[0], resultLength);
-}
-
-static JNINativeMethod gMethods[] = {
-    NATIVE_METHOD(NativeIDN, convertImpl, "(Ljava/lang/String;IZ)Ljava/lang/String;"),
-};
-void register_libcore_icu_NativeIDN(JNIEnv* env) {
-    jniRegisterNativeMethods(env, "libcore/icu/NativeIDN", gMethods, NELEM(gMethods));
-}
diff --git a/luni/src/main/native/libcore_icu_NativeNormalizer.cpp b/luni/src/main/native/libcore_icu_NativeNormalizer.cpp
deleted file mode 100644
index 2d5e282..0000000
--- a/luni/src/main/native/libcore_icu_NativeNormalizer.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#define LOG_TAG "NativeNormalizer"
-
-#include "IcuUtilities.h"
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "JniException.h"
-#include "ScopedJavaUnicodeString.h"
-#include "unicode/normlzr.h"
-
-static jstring NativeNormalizer_normalizeImpl(JNIEnv* env, jclass, jstring s, jint intMode) {
-  ScopedJavaUnicodeString src(env, s);
-  if (!src.valid()) {
-    return NULL;
-  }
-  UNormalizationMode mode = static_cast<UNormalizationMode>(intMode);
-  UErrorCode status = U_ZERO_ERROR;
-  icu::UnicodeString dst;
-  icu::Normalizer::normalize(src.unicodeString(), mode, 0, dst, status);
-  maybeThrowIcuException(env, "Normalizer::normalize", status);
-  return dst.isBogus() ? NULL : env->NewString(dst.getBuffer(), dst.length());
-}
-
-static jboolean NativeNormalizer_isNormalizedImpl(JNIEnv* env, jclass, jstring s, jint intMode) {
-  ScopedJavaUnicodeString src(env, s);
-  if (!src.valid()) {
-    return JNI_FALSE;
-  }
-  UNormalizationMode mode = static_cast<UNormalizationMode>(intMode);
-  UErrorCode status = U_ZERO_ERROR;
-  UBool result = icu::Normalizer::isNormalized(src.unicodeString(), mode, status);
-  maybeThrowIcuException(env, "Normalizer::isNormalized", status);
-  return result;
-}
-
-static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(NativeNormalizer, normalizeImpl, "(Ljava/lang/String;I)Ljava/lang/String;"),
-  NATIVE_METHOD(NativeNormalizer, isNormalizedImpl, "(Ljava/lang/String;I)Z"),
-};
-void register_libcore_icu_NativeNormalizer(JNIEnv* env) {
-  jniRegisterNativeMethods(env, "libcore/icu/NativeNormalizer", gMethods, NELEM(gMethods));
-}
diff --git a/luni/src/main/native/libcore_icu_NativePluralRules.cpp b/luni/src/main/native/libcore_icu_NativePluralRules.cpp
deleted file mode 100644
index f278485..0000000
--- a/luni/src/main/native/libcore_icu_NativePluralRules.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#define LOG_TAG "NativePluralRules"
-
-#include "IcuUtilities.h"
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "JniException.h"
-#include "ScopedUtfChars.h"
-#include "unicode/plurrule.h"
-
-#include <string>
-
-static icu::PluralRules* toPluralRules(jlong address) {
-    return reinterpret_cast<icu::PluralRules*>(static_cast<uintptr_t>(address));
-}
-
-static void NativePluralRules_finalizeImpl(JNIEnv*, jclass, jlong address) {
-    delete toPluralRules(address);
-}
-
-static jlong NativePluralRules_forLocaleImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
-    // The icu4c PluralRules returns a "other: n" default rule for the deprecated locales Java uses.
-    // Work around this by translating back to the current language codes.
-    std::string localeName(ScopedUtfChars(env, javaLocaleName).c_str());
-    if (localeName[0] == 'i' && localeName[1] == 'w') {
-        localeName[0] = 'h';
-        localeName[1] = 'e';
-    } else if (localeName[0] == 'i' && localeName[1] == 'n') {
-        localeName[0] = 'i';
-        localeName[1] = 'd';
-    } else if (localeName[0] == 'j' && localeName[1] == 'i') {
-        localeName[0] = 'y';
-        localeName[1] = 'i';
-    }
-
-    icu::Locale locale = icu::Locale::createFromName(localeName.c_str());
-    UErrorCode status = U_ZERO_ERROR;
-    icu::PluralRules* result = icu::PluralRules::forLocale(locale, status);
-    maybeThrowIcuException(env, "PluralRules::forLocale", status);
-    return reinterpret_cast<uintptr_t>(result);
-}
-
-static jint NativePluralRules_quantityForIntImpl(JNIEnv*, jclass, jlong address, jint value) {
-    icu::UnicodeString keyword = toPluralRules(address)->select(value);
-    if (keyword == "zero") {
-        return 0;
-    } else if (keyword == "one") {
-        return 1;
-    } else if (keyword == "two") {
-        return 2;
-    } else if (keyword == "few") {
-        return 3;
-    } else if (keyword == "many") {
-        return 4;
-    } else {
-        return 5;
-    }
-}
-
-static JNINativeMethod gMethods[] = {
-    NATIVE_METHOD(NativePluralRules, finalizeImpl, "(J)V"),
-    NATIVE_METHOD(NativePluralRules, forLocaleImpl, "(Ljava/lang/String;)J"),
-    NATIVE_METHOD(NativePluralRules, quantityForIntImpl, "(JI)I"),
-};
-void register_libcore_icu_NativePluralRules(JNIEnv* env) {
-    jniRegisterNativeMethods(env, "libcore/icu/NativePluralRules", gMethods, NELEM(gMethods));
-}
diff --git a/luni/src/main/native/libcore_icu_Transliterator.cpp b/luni/src/main/native/libcore_icu_Transliterator.cpp
deleted file mode 100644
index ae21565..0000000
--- a/luni/src/main/native/libcore_icu_Transliterator.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#define LOG_TAG "Transliterator"
-
-#include "IcuUtilities.h"
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "JniException.h"
-#include "ScopedJavaUnicodeString.h"
-#include "unicode/translit.h"
-
-static icu::Transliterator* fromPeer(jlong peer) {
-  return reinterpret_cast<icu::Transliterator*>(static_cast<uintptr_t>(peer));
-}
-
-static jlong Transliterator_create(JNIEnv* env, jclass, jstring javaId) {
-  ScopedJavaUnicodeString id(env, javaId);
-  if (!id.valid()) {
-    return 0;
-  }
-  UErrorCode status = U_ZERO_ERROR;
-  icu::Transliterator* t = icu::Transliterator::createInstance(id.unicodeString(), UTRANS_FORWARD, status);
-  if (maybeThrowIcuException(env, "Transliterator::createInstance", status)) {
-    return 0;
-  }
-  return reinterpret_cast<uintptr_t>(t);
-}
-
-static void Transliterator_destroy(JNIEnv*, jclass, jlong peer) {
-  delete fromPeer(peer);
-}
-
-static jobjectArray Transliterator_getAvailableIDs(JNIEnv* env, jclass) {
-  UErrorCode status = U_ZERO_ERROR;
-  icu::StringEnumeration* e = icu::Transliterator::getAvailableIDs(status);
-  return fromStringEnumeration(env, status, "Transliterator::getAvailableIDs", e);
-}
-
-static jstring Transliterator_transliterate(JNIEnv* env, jclass, jlong peer, jstring javaString) {
-  icu::Transliterator* t = fromPeer(peer);
-  ScopedJavaUnicodeString string(env, javaString);
-  if (!string.valid()) {
-    return NULL;
-  }
-
-  icu::UnicodeString& s(string.unicodeString());
-  t->transliterate(s);
-  return env->NewString(s.getBuffer(), s.length());
-}
-
-static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Transliterator, create, "(Ljava/lang/String;)J"),
-  NATIVE_METHOD(Transliterator, destroy, "(J)V"),
-  NATIVE_METHOD(Transliterator, getAvailableIDs, "()[Ljava/lang/String;"),
-  NATIVE_METHOD(Transliterator, transliterate, "(JLjava/lang/String;)Ljava/lang/String;"),
-};
-void register_libcore_icu_Transliterator(JNIEnv* env) {
-  jniRegisterNativeMethods(env, "libcore/icu/Transliterator", gMethods, NELEM(gMethods));
-}
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index f6af483..bfe2380 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -45,20 +45,17 @@
 #include <stdlib.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
-#ifndef __APPLE__
 #include <sys/prctl.h>
-#endif
 #include <sys/socket.h>
 #include <sys/stat.h>
-#ifdef __APPLE__
-#include <sys/statvfs.h>
-#endif
 #include <sys/syscall.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/uio.h>
+#include <sys/un.h>
 #include <sys/utsname.h>
 #include <sys/wait.h>
+#include <sys/xattr.h>
 #include <termios.h>
 #include <unistd.h>
 #include <memory>
@@ -138,9 +135,9 @@
  */
 #define NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
     return_type _rc = -1; \
+    int _syscallErrno; \
     do { \
         bool _wasSignaled; \
-        int _syscallErrno; \
         { \
             int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
             AsynchronousCloseMonitor _monitor(_fd); \
@@ -159,6 +156,10 @@
             break; \
         } \
     } while (_rc == -1); /* _syscallErrno == EINTR && !_wasSignaled */ \
+    if (_rc == -1) { \
+        /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ \
+        errno = _syscallErrno; \
+    } \
     _rc; })
 
 /**
@@ -173,9 +174,9 @@
  */
 #define IO_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
     return_type _rc = -1; \
+    int _syscallErrno; \
     do { \
         bool _wasSignaled; \
-        int _syscallErrno; \
         { \
             int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
             AsynchronousCloseMonitor _monitor(_fd); \
@@ -194,6 +195,10 @@
             break; \
         } \
     } while (_rc == -1); /* && _syscallErrno == EINTR && !_wasSignaled */ \
+    if (_rc == -1) { \
+        /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ \
+        errno = _syscallErrno; \
+    } \
     _rc; })
 
 #define NULL_ADDR_OK         true
@@ -316,8 +321,40 @@
     std::vector<ScopedT*> mScopedBuffers;
 };
 
-static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage& ss) {
-    if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6 || ss.ss_family == AF_UNIX) {
+/**
+ * Returns a jbyteArray containing the sockaddr_un.sun_path from ss. As per unix(7) sa_len should be
+ * the length of ss as returned by getsockname(2), getpeername(2), or accept(2).
+ * If the returned array is of length 0 the sockaddr_un refers to an unnamed socket.
+ * A null pointer is returned in the event of an error. See unix(7) for more information.
+ */
+static jbyteArray getUnixSocketPath(JNIEnv* env, const sockaddr_storage& ss,
+        const socklen_t& sa_len) {
+    if (ss.ss_family != AF_UNIX) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                "getUnixSocketPath unsupported ss_family: %i", ss.ss_family);
+        return NULL;
+    }
+
+    const struct sockaddr_un* un_addr = reinterpret_cast<const struct sockaddr_un*>(&ss);
+    // The length of sun_path is sa_len minus the length of the overhead (ss_family).
+    // See unix(7) for details. This calculation must match that of socket_make_sockaddr_un() in
+    // socket_local_client.c and javaUnixSocketAddressToSockaddr() to interoperate.
+    size_t pathLength = sa_len - offsetof(struct sockaddr_un, sun_path);
+
+    jbyteArray javaSunPath = env->NewByteArray(pathLength);
+    if (javaSunPath == NULL) {
+        return NULL;
+    }
+
+    if (pathLength > 0) {
+        env->SetByteArrayRegion(javaSunPath, 0, pathLength,
+                reinterpret_cast<const jbyte*>(&un_addr->sun_path));
+    }
+    return javaSunPath;
+}
+
+static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage& ss, const socklen_t sa_len) {
+    if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) {
         jint port;
         jobject inetAddress = sockaddrToInetAddress(env, ss, &port);
         if (inetAddress == NULL) {
@@ -326,6 +363,15 @@
         static jmethodID ctor = env->GetMethodID(JniConstants::inetSocketAddressClass,
                 "<init>", "(Ljava/net/InetAddress;I)V");
         return env->NewObject(JniConstants::inetSocketAddressClass, ctor, inetAddress, port);
+    } else if (ss.ss_family == AF_UNIX) {
+        static jmethodID ctor = env->GetMethodID(JniConstants::unixSocketAddressClass,
+                "<init>", "([B)V");
+
+        jbyteArray javaSunPath = getUnixSocketPath(env, ss, sa_len);
+        if (!javaSunPath) {
+            return NULL;
+        }
+        return env->NewObject(JniConstants::unixSocketAddressClass, ctor, javaSunPath);
     } else if (ss.ss_family == AF_NETLINK) {
         const struct sockaddr_nl* nl_addr = reinterpret_cast<const struct sockaddr_nl*>(&ss);
         static jmethodID ctor = env->GetMethodID(JniConstants::netlinkSocketAddressClass,
@@ -380,13 +426,6 @@
 }
 
 static jobject makeStructStatVfs(JNIEnv* env, const struct statvfs& sb) {
-#if defined(__APPLE__)
-    // Mac OS has no f_namelen field in struct statfs.
-    jlong max_name_length = 255; // __DARWIN_MAXNAMLEN
-#else
-    jlong max_name_length = static_cast<jlong>(sb.f_namemax);
-#endif
-
     static jmethodID ctor = env->GetMethodID(JniConstants::structStatVfsClass, "<init>",
             "(JJJJJJJJJJJ)V");
     return env->NewObject(JniConstants::structStatVfsClass, ctor,
@@ -400,7 +439,7 @@
                           static_cast<jlong>(sb.f_favail),
                           static_cast<jlong>(sb.f_fsid),
                           static_cast<jlong>(sb.f_flag),
-                          max_name_length);
+                          static_cast<jlong>(sb.f_namemax));
 }
 
 static jobject makeStructLinger(JNIEnv* env, const struct linger& l) {
@@ -415,13 +454,8 @@
 }
 
 static jobject makeStructUcred(JNIEnv* env, const struct ucred& u __unused) {
-#ifdef __APPLE__
-  jniThrowException(env, "java/lang/UnsupportedOperationException", "unimplemented support for ucred on a Mac");
-  return NULL;
-#else
   static jmethodID ctor = env->GetMethodID(JniConstants::structUcredClass, "<init>", "(III)V");
   return env->NewObject(JniConstants::structUcredClass, ctor, u.pid, u.uid, u.gid);
-#endif
 }
 
 static jobject makeStructUtsname(JNIEnv* env, const struct utsname& buf) {
@@ -447,8 +481,25 @@
     return true;
 }
 
-static bool fillInetSocketAddress(JNIEnv* env, jint rc, jobject javaInetSocketAddress, const sockaddr_storage& ss) {
-    if (rc == -1 || javaInetSocketAddress == NULL) {
+static bool fillUnixSocketAddress(JNIEnv* env, jobject javaUnixSocketAddress,
+        const sockaddr_storage& ss, const socklen_t& sa_len) {
+    if (javaUnixSocketAddress == NULL) {
+        return true;
+    }
+    jbyteArray javaSunPath = getUnixSocketPath(env, ss, sa_len);
+    if (!javaSunPath) {
+        return false;
+    }
+
+    static jfieldID sunPathFid =
+            env->GetFieldID(JniConstants::unixSocketAddressClass, "sun_path", "[B");
+    env->SetObjectField(javaUnixSocketAddress, sunPathFid, javaSunPath);
+    return true;
+}
+
+static bool fillInetSocketAddress(JNIEnv* env, jobject javaInetSocketAddress,
+        const sockaddr_storage& ss) {
+    if (javaInetSocketAddress == NULL) {
         return true;
     }
     // Fill out the passed-in InetSocketAddress with the sender's IP address and port number.
@@ -464,6 +515,23 @@
     return true;
 }
 
+static bool fillSocketAddress(JNIEnv* env, jobject javaSocketAddress, const sockaddr_storage& ss,
+        const socklen_t& sa_len) {
+    if (javaSocketAddress == NULL) {
+        return true;
+    }
+
+    if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) {
+        return fillInetSocketAddress(env, javaSocketAddress, ss);
+    } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::unixSocketAddressClass)) {
+        return fillUnixSocketAddress(env, javaSocketAddress, ss, sa_len);
+    }
+    jniThrowException(env, "java/lang/UnsupportedOperationException",
+            "unsupported SocketAddress subclass");
+    return false;
+
+}
+
 static void javaInetSocketAddressToInetAddressAndPort(
         JNIEnv* env, jobject javaInetSocketAddress, jobject& javaInetAddress, jint& port) {
     static jfieldID addressFid = env->GetFieldID(
@@ -496,6 +564,31 @@
     return true;
 }
 
+static bool javaUnixSocketAddressToSockaddr(
+        JNIEnv* env, jobject javaUnixSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
+    static jfieldID sunPathFid = env->GetFieldID(
+            JniConstants::unixSocketAddressClass, "sun_path", "[B");
+
+    struct sockaddr_un* un_addr = reinterpret_cast<struct sockaddr_un*>(&ss);
+    memset (un_addr, 0, sizeof(sockaddr_un));
+    un_addr->sun_family = AF_UNIX;
+
+    jbyteArray javaSunPath = (jbyteArray) env->GetObjectField(javaUnixSocketAddress, sunPathFid);
+    jsize pathLength = env->GetArrayLength(javaSunPath);
+    if ((size_t) pathLength > sizeof(sockaddr_un::sun_path)) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                "sun_path too long: max=%i, is=%i",
+                sizeof(sockaddr_un::sun_path), pathLength);
+        return false;
+    }
+    env->GetByteArrayRegion(javaSunPath, 0, pathLength, (jbyte*) un_addr->sun_path);
+    // sa_len is sun_path plus the length of the overhead (ss_family_t). See unix(7) for
+    // details. This calculation must match that of socket_make_sockaddr_un() in
+    // socket_local_client.c and getUnixSocketPath() to interoperate.
+    sa_len = offsetof(struct sockaddr_un, sun_path) + pathLength;
+    return true;
+}
+
 static bool javaPacketSocketAddressToSockaddr(
         JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
     static jfieldID protocolFid = env->GetFieldID(
@@ -545,6 +638,8 @@
         return javaInetSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
     } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::packetSocketAddressClass)) {
         return javaPacketSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
+    } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::unixSocketAddressClass)) {
+        return javaUnixSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
     }
     jniThrowException(env, "java/lang/UnsupportedOperationException",
             "unsupported SocketAddress subclass");
@@ -578,7 +673,7 @@
     throwErrnoException(env, is_sockname ? "getsockname" : "getpeername");
     return NULL;
   }
-  return makeSocketAddress(env, ss);
+  return makeSocketAddress(env, ss, byteCount);
 }
 
 class Passwd {
@@ -617,14 +712,14 @@
     struct passwd* mResult;
 };
 
-static jobject Posix_accept(JNIEnv* env, jobject, jobject javaFd, jobject javaInetSocketAddress) {
+static jobject Posix_accept(JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) {
     sockaddr_storage ss;
     socklen_t sl = sizeof(ss);
     memset(&ss, 0, sizeof(ss));
-    sockaddr* peer = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
-    socklen_t* peerLength = (javaInetSocketAddress != NULL) ? &sl : 0;
+    sockaddr* peer = (javaSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
+    socklen_t* peerLength = (javaSocketAddress != NULL) ? &sl : 0;
     jint clientFd = NET_FAILURE_RETRY(env, int, accept, javaFd, peer, peerLength);
-    if (clientFd == -1 || !fillInetSocketAddress(env, clientFd, javaInetSocketAddress, ss)) {
+    if (clientFd == -1 || !fillSocketAddress(env, javaSocketAddress, ss, *peerLength)) {
         close(clientFd);
         return NULL;
     }
@@ -1042,15 +1137,7 @@
 }
 
 static jint Posix_gettid(JNIEnv* env __unused, jobject) {
-#if defined(__APPLE__)
-  uint64_t owner;
-  int rc = pthread_threadid_np(NULL, &owner);  // Requires Mac OS 10.6
-  if (rc != 0) {
-    throwErrnoException(env, "gettid");
-    return 0;
-  }
-  return static_cast<jint>(owner);
-#elif defined(__BIONIC__)
+#if defined(__BIONIC__)
   return TEMP_FAILURE_RETRY(gettid());
 #else
   return syscall(__NR_gettid);
@@ -1061,6 +1148,28 @@
     return getuid();
 }
 
+static jint Posix_getxattr(JNIEnv* env, jobject, jstring javaPath,
+        jstring javaName, jbyteArray javaOutValue) {
+    ScopedUtfChars path(env, javaPath);
+    if (path.c_str() == NULL) {
+        return -1;
+    }
+    ScopedUtfChars name(env, javaName);
+    if (name.c_str() == NULL) {
+        return -1;
+    }
+    ScopedBytesRW outValue(env, javaOutValue);
+    if (outValue.get() == NULL) {
+        return -1;
+    }
+    size_t outValueLength = env->GetArrayLength(javaOutValue);
+    ssize_t size = getxattr(path.c_str(), name.c_str(), outValue.get(), outValueLength);
+    if (size < 0) {
+        throwErrnoException(env, "getxattr");
+    }
+    return size;
+}
+
 static jstring Posix_if_indextoname(JNIEnv* env, jobject, jint index) {
     char buf[IF_NAMESIZE];
     char* name = if_indextoname(index, buf);
@@ -1220,10 +1329,6 @@
 }
 
 static jobjectArray Posix_pipe2(JNIEnv* env, jobject, jint flags __unused) {
-#ifdef __APPLE__
-    jniThrowException(env, "java/lang/UnsupportedOperationException", "no pipe2 on Mac OS");
-    return NULL;
-#else
     int fds[2];
     throwIfMinusOne(env, "pipe2", TEMP_FAILURE_RETRY(pipe2(&fds[0], flags)));
     jobjectArray result = env->NewObjectArray(2, JniConstants::fileDescriptorClass, NULL);
@@ -1241,7 +1346,6 @@
         }
     }
     return result;
-#endif
 }
 
 static jint Posix_poll(JNIEnv* env, jobject, jobjectArray javaStructs, jint timeoutMs) {
@@ -1327,32 +1431,22 @@
 
 static void Posix_posix_fallocate(JNIEnv* env, jobject, jobject javaFd __unused,
                                   jlong offset __unused, jlong length __unused) {
-#ifdef __APPLE__
-    jniThrowException(env, "java/lang/UnsupportedOperationException",
-                      "fallocate doesn't exist on a Mac");
-#else
     int fd = jniGetFDFromFileDescriptor(env, javaFd);
     while ((errno = posix_fallocate64(fd, offset, length)) == EINTR) {
     }
     if (errno != 0) {
         throwErrnoException(env, "posix_fallocate");
     }
-#endif
 }
 
 static jint Posix_prctl(JNIEnv* env, jobject, jint option __unused, jlong arg2 __unused,
                         jlong arg3 __unused, jlong arg4 __unused, jlong arg5 __unused) {
-#ifdef __APPLE__
-    jniThrowException(env, "java/lang/UnsupportedOperationException", "prctl doesn't exist on a Mac");
-    return 0;
-#else
     int result = TEMP_FAILURE_RETRY(prctl(static_cast<int>(option),
                                           static_cast<unsigned long>(arg2),
                                           static_cast<unsigned long>(arg3),
                                           static_cast<unsigned long>(arg4),
                                           static_cast<unsigned long>(arg5)));
     return throwIfMinusOne(env, "prctl", result);
-#endif
 }
 
 static jint Posix_preadBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jlong offset) {
@@ -1412,7 +1506,10 @@
     sockaddr* from = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
     socklen_t* fromLength = (javaInetSocketAddress != NULL) ? &sl : 0;
     jint recvCount = NET_FAILURE_RETRY(env, ssize_t, recvfrom, javaFd, bytes.get() + byteOffset, byteCount, flags, from, fromLength);
-    fillInetSocketAddress(env, recvCount, javaInetSocketAddress, ss);
+    if (recvCount == -1) {
+        return recvCount;
+    }
+    fillInetSocketAddress(env, javaInetSocketAddress, ss);
     return recvCount;
 }
 
@@ -1424,6 +1521,22 @@
     throwIfMinusOne(env, "remove", TEMP_FAILURE_RETRY(remove(path.c_str())));
 }
 
+static void Posix_removexattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName) {
+    ScopedUtfChars path(env, javaPath);
+    if (path.c_str() == NULL) {
+        return;
+    }
+    ScopedUtfChars name(env, javaName);
+    if (name.c_str() == NULL) {
+        return;
+    }
+
+    int res = removexattr(path.c_str(), name.c_str());
+    if (res < 0) {
+        throwErrnoException(env, "removexattr");
+    }
+}
+
 static void Posix_rename(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
     ScopedUtfChars oldPath(env, javaOldPath);
     if (oldPath.c_str() == NULL) {
@@ -1550,12 +1663,6 @@
     throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
 }
 
-#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED < 1070
-// Mac OS didn't support modern multicast APIs until 10.7.
-static void Posix_setsockoptIpMreqn(JNIEnv*, jobject, jobject, jint, jint, jint) { abort(); }
-static void Posix_setsockoptGroupReq(JNIEnv*, jobject, jobject, jint, jint, jobject) { abort(); }
-static void Posix_setsockoptGroupSourceReq(JNIEnv*, jobject, jobject, jint, jint, jobject) { abort(); }
-#else
 static void Posix_setsockoptIpMreqn(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
     ip_mreqn req;
     memset(&req, 0, sizeof(req));
@@ -1638,7 +1745,6 @@
     }
     throwIfMinusOne(env, "setsockopt", rc);
 }
-#endif
 
 static void Posix_setsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaLinger) {
     static jfieldID lOnoffFid = env->GetFieldID(JniConstants::structLingerClass, "l_onoff", "I");
@@ -1664,6 +1770,27 @@
     throwIfMinusOne(env, "setuid", TEMP_FAILURE_RETRY(setuid(uid)));
 }
 
+static void Posix_setxattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName,
+        jbyteArray javaValue, jint flags) {
+    ScopedUtfChars path(env, javaPath);
+    if (path.c_str() == NULL) {
+        return;
+    }
+    ScopedUtfChars name(env, javaName);
+    if (name.c_str() == NULL) {
+        return;
+    }
+    ScopedBytesRO value(env, javaValue);
+    if (value.get() == NULL) {
+        return;
+    }
+    size_t valueLength = env->GetArrayLength(javaValue);
+    int res = setxattr(path.c_str(), name.c_str(), value.get(), valueLength, flags);
+    if (res < 0) {
+        throwErrnoException(env, "setxattr");
+    }
+}
+
 static void Posix_shutdown(JNIEnv* env, jobject, jobject javaFd, jint how) {
     int fd = jniGetFDFromFileDescriptor(env, javaFd);
     throwIfMinusOne(env, "shutdown", TEMP_FAILURE_RETRY(shutdown(fd, how)));
@@ -1758,6 +1885,14 @@
     return makeStructUtsname(env, buf);
 }
 
+static void Posix_unlink(JNIEnv* env, jobject, jstring javaPathname) {
+    ScopedUtfChars pathname(env, javaPathname);
+    if (pathname.c_str() == NULL) {
+        return;
+    }
+    throwIfMinusOne(env, "unlink", unlink(pathname.c_str()));
+}
+
 static void Posix_unsetenv(JNIEnv* env, jobject, jstring javaName) {
     ScopedUtfChars name(env, javaName);
     if (name.c_str() == NULL) {
@@ -1796,7 +1931,7 @@
     { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName ## variant) }
 
 static JNINativeMethod gMethods[] = {
-    NATIVE_METHOD(Posix, accept, "(Ljava/io/FileDescriptor;Ljava/net/InetSocketAddress;)Ljava/io/FileDescriptor;"),
+    NATIVE_METHOD(Posix, accept, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)Ljava/io/FileDescriptor;"),
     NATIVE_METHOD(Posix, access, "(Ljava/lang/String;I)Z"),
     NATIVE_METHOD(Posix, android_getaddrinfo, "(Ljava/lang/String;Landroid/system/StructAddrinfo;I)[Ljava/net/InetAddress;"),
     NATIVE_METHOD(Posix, bind, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"),
@@ -1842,6 +1977,7 @@
     NATIVE_METHOD(Posix, getsockoptUcred, "(Ljava/io/FileDescriptor;II)Landroid/system/StructUcred;"),
     NATIVE_METHOD(Posix, gettid, "()I"),
     NATIVE_METHOD(Posix, getuid, "()I"),
+    NATIVE_METHOD(Posix, getxattr, "(Ljava/lang/String;Ljava/lang/String;[B)I"),
     NATIVE_METHOD(Posix, if_indextoname, "(I)Ljava/lang/String;"),
     NATIVE_METHOD(Posix, inet_pton, "(ILjava/lang/String;)Ljava/net/InetAddress;"),
     NATIVE_METHOD(Posix, ioctlInetAddress, "(Ljava/io/FileDescriptor;ILjava/lang/String;)Ljava/net/InetAddress;"),
@@ -1873,6 +2009,7 @@
     NATIVE_METHOD(Posix, readv, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"),
     NATIVE_METHOD(Posix, recvfromBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetSocketAddress;)I"),
     NATIVE_METHOD(Posix, remove, "(Ljava/lang/String;)V"),
+    NATIVE_METHOD(Posix, removexattr, "(Ljava/lang/String;Ljava/lang/String;)V"),
     NATIVE_METHOD(Posix, rename, "(Ljava/lang/String;Ljava/lang/String;)V"),
     NATIVE_METHOD(Posix, sendfile, "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Landroid/util/MutableLong;J)J"),
     NATIVE_METHOD(Posix, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetAddress;I)I"),
@@ -1894,6 +2031,7 @@
     NATIVE_METHOD(Posix, setsockoptLinger, "(Ljava/io/FileDescriptor;IILandroid/system/StructLinger;)V"),
     NATIVE_METHOD(Posix, setsockoptTimeval, "(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V"),
     NATIVE_METHOD(Posix, setuid, "(I)V"),
+    NATIVE_METHOD(Posix, setxattr, "(Ljava/lang/String;Ljava/lang/String;[BI)V"),
     NATIVE_METHOD(Posix, shutdown, "(Ljava/io/FileDescriptor;I)V"),
     NATIVE_METHOD(Posix, socket, "(III)Ljava/io/FileDescriptor;"),
     NATIVE_METHOD(Posix, socketpair, "(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V"),
@@ -1907,6 +2045,7 @@
     NATIVE_METHOD(Posix, tcsendbreak, "(Ljava/io/FileDescriptor;I)V"),
     NATIVE_METHOD(Posix, umaskImpl, "(I)I"),
     NATIVE_METHOD(Posix, uname, "()Landroid/system/StructUtsname;"),
+    NATIVE_METHOD(Posix, unlink, "(Ljava/lang/String;)V"),
     NATIVE_METHOD(Posix, unsetenv, "(Ljava/lang/String;)V"),
     NATIVE_METHOD(Posix, waitpid, "(ILandroid/util/MutableInt;I)I"),
     NATIVE_METHOD(Posix, writeBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"),
diff --git a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index 48defc1..f6f812c 100644
--- a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -31,7 +31,7 @@
 #include <memory>
 
 #include <string.h>
-#include <libexpat/expat.h>
+#include <expat.h>
 
 #define BUCKET_COUNT 128
 
diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk
index 78ec37a..b227793 100644
--- a/luni/src/main/native/sub.mk
+++ b/luni/src/main/native/sub.mk
@@ -27,7 +27,6 @@
     java_lang_StringToReal.cpp \
     java_lang_System.cpp \
     java_math_NativeBN.cpp \
-    java_text_Bidi.cpp \
     java_util_jar_StrictJarFile.cpp \
     java_util_regex_Matcher.cpp \
     java_util_regex_Pattern.cpp \
@@ -35,16 +34,11 @@
     java_util_zip_CRC32.cpp \
     java_util_zip_Deflater.cpp \
     java_util_zip_Inflater.cpp \
-    libcore_icu_AlphabeticIndex.cpp \
     libcore_icu_ICU.cpp \
     libcore_icu_NativeCollation.cpp \
     libcore_icu_NativeConverter.cpp \
     libcore_icu_NativeDecimalFormat.cpp \
-    libcore_icu_NativeIDN.cpp \
-    libcore_icu_NativeNormalizer.cpp \
-    libcore_icu_NativePluralRules.cpp \
     libcore_icu_TimeZoneNames.cpp \
-    libcore_icu_Transliterator.cpp \
     libcore_io_AsynchronousCloseMonitor.cpp \
     libcore_io_Memory.cpp \
     libcore_io_Posix.cpp \
diff --git a/luni/src/test/java/android/system/UnixSocketAddressTest.java b/luni/src/test/java/android/system/UnixSocketAddressTest.java
new file mode 100644
index 0000000..f1b7fc2
--- /dev/null
+++ b/luni/src/test/java/android/system/UnixSocketAddressTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 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 android.system;
+
+import junit.framework.TestCase;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+public class UnixSocketAddressTest extends TestCase {
+
+    public void testFilesystemSunPath() throws Exception {
+        String path = "/foo/bar";
+        UnixSocketAddress sa = UnixSocketAddress.createFileSystem(path);
+
+        byte[] abstractNameBytes = path.getBytes(StandardCharsets.UTF_8);
+        byte[] expected = new byte[abstractNameBytes.length + 1];
+        // See unix(7)
+        System.arraycopy(abstractNameBytes, 0, expected, 0, abstractNameBytes.length);
+        assertTrue(Arrays.equals(expected, sa.getSunPath()));
+    }
+
+    public void testUnnamedSunPath() throws Exception {
+        UnixSocketAddress sa = UnixSocketAddress.createUnnamed();
+        assertEquals(0, sa.getSunPath().length);
+    }
+
+    public void testAbstractSunPath() throws Exception {
+        String abstractName = "abstract";
+        UnixSocketAddress sa = UnixSocketAddress.createAbstract(abstractName);
+        byte[] abstractNameBytes = abstractName.getBytes(StandardCharsets.UTF_8);
+        byte[] expected = new byte[abstractNameBytes.length + 1];
+        // See unix(7)
+        System.arraycopy(abstractNameBytes, 0, expected, 1, abstractNameBytes.length);
+        assertTrue(Arrays.equals(expected, sa.getSunPath()));
+    }
+}
diff --git a/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java b/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
deleted file mode 100644
index 6c7452d..0000000
--- a/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2013 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.icu;
-
-import java.util.Locale;
-
-public class AlphabeticIndexTest extends junit.framework.TestCase {
-  private static AlphabeticIndex.ImmutableIndex createIndex(Locale locale) {
-    return new AlphabeticIndex(locale).addLabels(Locale.US).getImmutableIndex();
-  }
-
-  private static void assertHasLabel(AlphabeticIndex.ImmutableIndex ii, String string, String expectedLabel) {
-    int index = ii.getBucketIndex(string);
-    String label = ii.getBucketLabel(index);
-    assertEquals(expectedLabel, label);
-  }
-
-  public void test_en() throws Exception {
-    // English [A-Z]
-    AlphabeticIndex.ImmutableIndex en = createIndex(Locale.ENGLISH);
-    assertHasLabel(en, "Allen", "A");
-    assertHasLabel(en, "allen", "A");
-  }
-
-  public void test_ja() throws Exception {
-    AlphabeticIndex.ImmutableIndex ja = createIndex(Locale.JAPANESE);
-
-    // Japanese
-    //   sorts hiragana/katakana, Kanji/Chinese, English, other
-    // …, あ, か, さ, た, な, は, ま, や, ら, わ, …
-    // hiragana "a"
-    assertHasLabel(ja, "Allen", "A");
-    assertHasLabel(ja, "\u3041", "\u3042");
-    // katakana "a"
-    assertHasLabel(ja, "\u30a1", "\u3042");
-
-    // Kanji (sorts to inflow section)
-    assertHasLabel(ja, "\u65e5", "");
-
-    // http://bugs.icu-project.org/trac/ticket/10423 / http://b/10809397
-    assertHasLabel(ja, "\u95c7", "");
-    assertHasLabel(ja, "\u308f", "わ");
-
-    // English
-    assertHasLabel(ja, "Smith", "S");
-
-    // Chinese (sorts to inflow section)
-    assertHasLabel(ja, "\u6c88" /* Shen/Chen */, "");
-
-    // Korean Hangul (sorts to overflow section)
-    assertHasLabel(ja, "\u1100", "");
-  }
-
-  public void test_ko() throws Exception {
-    // Korean (sorts Korean, then English)
-    // …, ᄀ, ᄂ, ᄃ, ᄅ, ᄆ, ᄇ, ᄉ, ᄋ, ᄌ, ᄎ, ᄏ, ᄐ, ᄑ, ᄒ, …
-    AlphabeticIndex.ImmutableIndex ko = createIndex(Locale.KOREAN);
-    assertHasLabel(ko, "\u1100", "\u3131");
-    assertHasLabel(ko, "\u3131", "\u3131");
-    assertHasLabel(ko, "\u1101", "\u3131");
-    assertHasLabel(ko, "\u1161", "\u314e");
-  }
-
-  public void test_cs() throws Exception {
-    // Czech
-    // …, [A-C], Č,[D-H], CH, [I-R], Ř, S, Š, [T-Z], Ž, …
-    AlphabeticIndex.ImmutableIndex cs = createIndex(new Locale("cs"));
-    assertHasLabel(cs, "Cena", "C");
-    assertHasLabel(cs, "Čáp", "\u010c");
-    assertHasLabel(cs, "Ruda", "R");
-    assertHasLabel(cs, "Řada", "\u0158");
-    assertHasLabel(cs, "Selka", "S");
-    assertHasLabel(cs, "Šála", "\u0160");
-    assertHasLabel(cs, "Zebra", "Z");
-    assertHasLabel(cs, "Žába", "\u017d");
-    assertHasLabel(cs, "Chata", "CH");
-  }
-
-  public void test_fr() throws Exception {
-    // French: [A-Z] (no accented chars)
-    AlphabeticIndex.ImmutableIndex fr = createIndex(Locale.FRENCH);
-    assertHasLabel(fr, "Øfer", "O");
-    assertHasLabel(fr, "Œster", "O");
-  }
-
-  public void test_da() throws Exception {
-    // Danish: [A-Z], Æ, Ø, Å
-    AlphabeticIndex.ImmutableIndex da = createIndex(new Locale("da"));
-    assertHasLabel(da, "Ænes", "\u00c6");
-    assertHasLabel(da, "Øfer", "\u00d8");
-    assertHasLabel(da, "Œster", "\u00d8");
-    assertHasLabel(da, "Ågård", "\u00c5");
-  }
-
-  public void test_de() throws Exception {
-    // German: [A-Z] (no ß or umlauted characters in standard alphabet)
-    AlphabeticIndex.ImmutableIndex de = createIndex(Locale.GERMAN);
-    assertHasLabel(de, "ßind", "S");
-    // We no longer split out "S", "Sch", and "St".
-    assertHasLabel(de, "Sacher", "S");
-    assertHasLabel(de, "Schiller", "S");
-    assertHasLabel(de, "Steiff", "S");
-  }
-
-  public void test_th() throws Exception {
-    // Thai (sorts English then Thai)
-    // …, ก, ข, ฃ, ค, ฅ, ฆ, ง, จ, ฉ, ช, ซ, ฌ, ญ, ฎ, ฏ, ฐ, ฑ, ฒ, ณ, ด, ต, ถ, ท, ธ, น, บ, ป, ผ, ฝ, พ, ฟ, ภ, ม, ย, ร, ฤ, ล, ฦ, ว, ศ, ษ, ส, ห, ฬ, อ, ฮ, …,
-    AlphabeticIndex.ImmutableIndex th = createIndex(new Locale("th"));
-    assertHasLabel(th, "\u0e2d\u0e07\u0e04\u0e4c\u0e40\u0e25\u0e47\u0e01", "\u0e2d");
-    assertHasLabel(th, "\u0e2a\u0e34\u0e07\u0e2b\u0e40\u0e2a\u0e19\u0e35", "\u0e2a");
-  }
-
-  public void test_ar() throws Exception {
-    // Arabic (sorts English then Arabic)
-    // …, ا, ب, ت, ث, ج, ح, خ, د, ذ, ر, ز, س, ش, ص, ض, ط, ظ, ع, غ, ف, ق, ك, ل, م, ن, ه, و, ي, …
-    AlphabeticIndex.ImmutableIndex ar = createIndex(new Locale("ar"));
-    assertHasLabel(ar, "\u0646\u0648\u0631", /* Noor */ "\u0646");
-  }
-
-  public void test_he() throws Exception {
-    // Hebrew (sorts English then Hebrew)
-    // …, א, ב, ג, ד, ה, ו, ז, ח, ט, י, כ, ל, מ, נ, ס, ע, פ, צ, ק, ר, ש, ת, …
-    AlphabeticIndex.ImmutableIndex he = createIndex(new Locale("he"));
-    assertHasLabel(he, "\u05e4\u05e8\u05d9\u05d3\u05de\u05df", "\u05e4");
-  }
-
-  public void test_zh_CN() throws Exception {
-    // Simplified Chinese (default collator Pinyin): [A-Z]
-    AlphabeticIndex.ImmutableIndex zh_CN = createIndex(new Locale("zh", "CN"));
-
-    // Jia/Gu: should be, usually, 'J' for name collator and 'G' for apps/other
-    assertHasLabel(zh_CN, "\u8d3e", "J");
-
-    // Shen/Chen (simplified): should usually be 'S' for names and 'C' for apps/other.
-    // icu4c does not specialize for names and defaults to 'C'.
-    // Some OEMs prefer to default to 'S'.
-    // We allow either to pass CTS since neither choice is right all the time.
-    // assertHasLabel(zh_CN, "\u6c88", "C");
-    String shenChenLabel = zh_CN.getBucketLabel(zh_CN.getBucketIndex("\u6c88"));
-    assertTrue(shenChenLabel.equals("C") || shenChenLabel.equals("S"));
-
-    // Shen/Chen (traditional)
-    assertHasLabel(zh_CN, "\u700b", "S");
-  }
-
-  public void test_zh_HK() throws Exception {
-    // Traditional Chinese (strokes).
-    // …, [1-33, 35, 36, 39, 48]劃, …
-    // Shen/Chen
-    AlphabeticIndex.ImmutableIndex zh_HK = createIndex(new Locale("zh", "HK"));
-    assertHasLabel(zh_HK, "\u6c88", "7\u5283");
-    assertHasLabel(zh_HK, "\u700b", "18\u5283");
-    // Jia/Gu
-    assertHasLabel(zh_HK, "\u8d3e", "10\u5283");
-  }
-
-  public void test_constructor_NPE() throws Exception {
-    try {
-      new AlphabeticIndex(null);
-      fail();
-    } catch (NullPointerException expected) {
-    }
-  }
-
-  public void test_addLabels_NPE() throws Exception {
-    AlphabeticIndex ai = new AlphabeticIndex(Locale.US);
-    try {
-      ai.addLabels(null);
-      fail();
-    } catch (NullPointerException expected) {
-    }
-  }
-
-  // ICU 51 default max label count is 99. Test to make sure can create an
-  // index with a larger number of labels.
-  public void test_setMaxLabelCount() throws Exception {
-    final int MAX_LABEL_COUNT = 500;
-    AlphabeticIndex ai = new AlphabeticIndex(Locale.US)
-      .setMaxLabelCount(MAX_LABEL_COUNT)
-      .addLabels(Locale.JAPANESE)
-      .addLabels(Locale.KOREAN)
-      .addLabels(new Locale("th"))
-      .addLabels(new Locale("ar"))
-      .addLabels(new Locale("he"))
-      .addLabels(new Locale("el"))
-      .addLabels(new Locale("ru"));
-    assertEquals(MAX_LABEL_COUNT, ai.getMaxLabelCount());
-    assertEquals(208, ai.getBucketCount());
-    AlphabeticIndex.ImmutableIndex ii = ai.getImmutableIndex();
-    assertEquals(ai.getBucketCount(), ii.getBucketCount());
-  }
-
-  public void test_getBucketIndex_NPE() throws Exception {
-    AlphabeticIndex.ImmutableIndex ii = createIndex(Locale.US);
-    try {
-      ii.getBucketIndex(null);
-      fail();
-    } catch (NullPointerException expected) {
-    }
-  }
-
-  public void test_getBucketLabel_invalid() throws Exception {
-    AlphabeticIndex.ImmutableIndex ii = createIndex(Locale.US);
-    try {
-      ii.getBucketLabel(-1);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-
-    try {
-      ii.getBucketLabel(123456);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-  }
-}
diff --git a/luni/src/test/java/libcore/icu/NativePluralRulesTest.java b/luni/src/test/java/libcore/icu/NativePluralRulesTest.java
deleted file mode 100644
index 76179b4..0000000
--- a/luni/src/test/java/libcore/icu/NativePluralRulesTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2009 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.icu;
-
-import java.util.Locale;
-
-public class NativePluralRulesTest extends junit.framework.TestCase {
-    public void testNegatives() throws Exception {
-        // icu4c's behavior changed, but we prefer to preserve compatibility.
-        NativePluralRules en_US = NativePluralRules.forLocale(new Locale("en", "US"));
-        assertEquals(NativePluralRules.OTHER, en_US.quantityForInt(2));
-        assertEquals(NativePluralRules.ONE, en_US.quantityForInt(1));
-        assertEquals(NativePluralRules.OTHER, en_US.quantityForInt(0));
-        assertEquals(NativePluralRules.OTHER, en_US.quantityForInt(-1));
-        assertEquals(NativePluralRules.OTHER, en_US.quantityForInt(-2));
-
-        NativePluralRules ar = NativePluralRules.forLocale(new Locale("ar"));
-        assertEquals(NativePluralRules.ZERO, ar.quantityForInt(0));
-        assertEquals(NativePluralRules.OTHER, ar.quantityForInt(-1)); // Not ONE.
-        assertEquals(NativePluralRules.OTHER, ar.quantityForInt(-2)); // Not TWO.
-        assertEquals(NativePluralRules.OTHER, ar.quantityForInt(-3)); // Not FEW.
-        assertEquals(NativePluralRules.OTHER, ar.quantityForInt(-11)); // Not MANY.
-        assertEquals(NativePluralRules.OTHER, ar.quantityForInt(-100));
-    }
-
-    public void testEnglish() throws Exception {
-        NativePluralRules npr = NativePluralRules.forLocale(new Locale("en", "US"));
-        assertEquals(NativePluralRules.OTHER, npr.quantityForInt(0));
-        assertEquals(NativePluralRules.ONE, npr.quantityForInt(1));
-        assertEquals(NativePluralRules.OTHER, npr.quantityForInt(2));
-    }
-
-    public void testCzech() throws Exception {
-        NativePluralRules npr = NativePluralRules.forLocale(new Locale("cs", "CZ"));
-        assertEquals(NativePluralRules.OTHER, npr.quantityForInt(0));
-        assertEquals(NativePluralRules.ONE, npr.quantityForInt(1));
-        assertEquals(NativePluralRules.FEW, npr.quantityForInt(2));
-        assertEquals(NativePluralRules.FEW, npr.quantityForInt(3));
-        assertEquals(NativePluralRules.FEW, npr.quantityForInt(4));
-        assertEquals(NativePluralRules.OTHER, npr.quantityForInt(5));
-    }
-
-    public void testArabic() throws Exception {
-        NativePluralRules npr = NativePluralRules.forLocale(new Locale("ar"));
-        assertEquals(NativePluralRules.ZERO, npr.quantityForInt(0));
-        assertEquals(NativePluralRules.ONE, npr.quantityForInt(1));
-        assertEquals(NativePluralRules.TWO, npr.quantityForInt(2));
-        for (int i = 3; i <= 10; ++i) {
-            assertEquals(NativePluralRules.FEW, npr.quantityForInt(i));
-        }
-        assertEquals(NativePluralRules.MANY, npr.quantityForInt(11));
-        assertEquals(NativePluralRules.MANY, npr.quantityForInt(99));
-        assertEquals(NativePluralRules.OTHER, npr.quantityForInt(100));
-        assertEquals(NativePluralRules.OTHER, npr.quantityForInt(101));
-        assertEquals(NativePluralRules.OTHER, npr.quantityForInt(102));
-        assertEquals(NativePluralRules.FEW, npr.quantityForInt(103));
-        assertEquals(NativePluralRules.MANY, npr.quantityForInt(111));
-    }
-
-    public void testHebrew() throws Exception {
-        // java.util.Locale will translate "he" to the deprecated "iw".
-        NativePluralRules he = NativePluralRules.forLocale(new Locale("he"));
-        assertEquals(NativePluralRules.ONE, he.quantityForInt(1));
-        assertEquals(NativePluralRules.TWO, he.quantityForInt(2));
-        assertEquals(NativePluralRules.OTHER, he.quantityForInt(3));
-        assertEquals(NativePluralRules.OTHER, he.quantityForInt(10));
-    }
-}
-
diff --git a/luni/src/test/java/libcore/icu/TransliteratorTest.java b/luni/src/test/java/libcore/icu/TransliteratorTest.java
index 9ced2de..626d951 100644
--- a/luni/src/test/java/libcore/icu/TransliteratorTest.java
+++ b/luni/src/test/java/libcore/icu/TransliteratorTest.java
@@ -16,18 +16,24 @@
 
 package libcore.icu;
 
+import android.icu.text.Transliterator;
+
+import java.util.Enumeration;
+
 public class TransliteratorTest extends junit.framework.TestCase {
   public void testAll() throws Exception {
-    for (String id : Transliterator.getAvailableIDs()) {
+    Enumeration<String> ids = Transliterator.getAvailableIDs();
+    while (ids.hasMoreElements()) {
+      String id = ids.nextElement();
       System.err.println(id);
-      Transliterator t = new Transliterator(id);
+      Transliterator t = Transliterator.getInstance(id);
       t.transliterate("hello");
     }
   }
 
   public void test_Unknown() throws Exception {
     try {
-      Transliterator t = new Transliterator("Unknown");
+      Transliterator t = Transliterator.getInstance("Unknown");
       fail();
     } catch (RuntimeException expected) {
     }
@@ -35,29 +41,20 @@
 
   public void test_null_id() throws Exception {
     try {
-      Transliterator t = new Transliterator(null);
-      fail();
-    } catch (NullPointerException expected) {
-    }
-  }
-
-  public void test_null_string() throws Exception {
-    try {
-      Transliterator t = new Transliterator("Any-Upper");
-      t.transliterate(null);
+      Transliterator t = Transliterator.getInstance(null);
       fail();
     } catch (NullPointerException expected) {
     }
   }
 
   public void test_Any_Upper() throws Exception {
-    Transliterator t = new Transliterator("Any-Upper");
+    Transliterator t = Transliterator.getInstance("Any-Upper");
     assertEquals("HELLO WORLD!", t.transliterate("HeLlO WoRlD!"));
     assertEquals("STRASSE", t.transliterate("Straße"));
   }
 
   public void test_Any_Lower() throws Exception {
-    Transliterator t = new Transliterator("Any-Lower");
+    Transliterator t = Transliterator.getInstance("Any-Lower");
     assertEquals("hello world!", t.transliterate("HeLlO WoRlD!"));
   }
 
@@ -65,34 +62,34 @@
     String greek = "Καλημέρα κόσμε!";
 
     // Transliterate Greek to Latin, then to plain ASCII.
-    Transliterator t = new Transliterator("Greek-Latin");
+    Transliterator t = Transliterator.getInstance("Greek-Latin");
     String latin = t.transliterate(greek);
-    t = new Transliterator("Latin-Ascii");
+    t = Transliterator.getInstance("Latin-Ascii");
     String ascii = t.transliterate(latin);
     assertEquals("Kalēméra kósme!", latin);
     assertEquals("Kalemera kosme!", ascii);
 
     // Use alternative transliteration variants.
-    t = new Transliterator("Greek-Latin/BGN");
+    t = Transliterator.getInstance("Greek-Latin/BGN");
     assertEquals("Kaliméra kósme!", t.transliterate(greek));
-    t = new Transliterator("Greek-Latin/UNGEGN");
+    t = Transliterator.getInstance("Greek-Latin/UNGEGN");
     assertEquals("Kali̱méra kósme!",t.transliterate(greek));
   }
 
   public void test_Han_Latin() throws Exception {
-    Transliterator t = new Transliterator("Han-Latin");
+    Transliterator t = Transliterator.getInstance("Han-Latin");
     assertEquals("hàn zì/hàn zì", t.transliterate("汉字/漢字"));
 
     assertEquals("chén", t.transliterate("\u6c88"));
     assertEquals("shěn", t.transliterate("\u700b"));
     assertEquals("jiǎ", t.transliterate("\u8d3e"));
 
-    t = new Transliterator("Han-Latin/Names");
+    t = Transliterator.getInstance("Han-Latin/Names");
     assertEquals("shěn", t.transliterate("\u6c88"));
     assertEquals("shěn", t.transliterate("\u700b"));
     assertEquals("jiǎ", t.transliterate("\u8d3e"));
 
-    t = new Transliterator("Han-Latin/Names; Latin-Ascii; Any-Upper");
+    t = Transliterator.getInstance("Han-Latin/Names; Latin-Ascii; Any-Upper");
     assertEquals("SHEN", t.transliterate("\u6c88"));
     assertEquals("SHEN", t.transliterate("\u700b"));
     assertEquals("JIA", t.transliterate("\u8d3e"));
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index e648e8a..1dcc3c6 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -18,9 +18,12 @@
 
 import android.system.ErrnoException;
 import android.system.NetlinkSocketAddress;
+import android.system.OsConstants;
 import android.system.PacketSocketAddress;
 import android.system.StructTimeval;
 import android.system.StructUcred;
+import android.system.UnixSocketAddress;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -29,10 +32,8 @@
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
-import java.net.InetUnixAddress;
 import java.net.NetworkInterface;
 import java.net.ServerSocket;
-import java.net.SocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
@@ -69,19 +70,25 @@
   public void testUnixDomainSockets_in_file_system() throws Exception {
     String path = System.getProperty("java.io.tmpdir") + "/test_unix_socket";
     new File(path).delete();
-    checkUnixDomainSocket(new InetUnixAddress(path), false);
+    checkUnixDomainSocket(UnixSocketAddress.createFileSystem(path), false);
   }
 
   public void testUnixDomainSocket_abstract_name() throws Exception {
     // Linux treats a sun_path starting with a NUL byte as an abstract name. See unix(7).
-    byte[] path = "/abstract_name_unix_socket".getBytes("UTF-8");
-    path[0] = 0;
-    checkUnixDomainSocket(new InetUnixAddress(path), true);
+    checkUnixDomainSocket(UnixSocketAddress.createAbstract("/abstract_name_unix_socket"), true);
   }
 
-  private void checkUnixDomainSocket(final InetUnixAddress address, final boolean isAbstract) throws Exception {
+  public void testUnixDomainSocket_unnamed() throws Exception {
+    final FileDescriptor fd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0);
+    // unix(7) says an unbound socket is unnamed.
+    checkNoSockName(fd);
+    Libcore.os.close(fd);
+  }
+
+  private void checkUnixDomainSocket(final UnixSocketAddress address, final boolean isAbstract)
+      throws Exception {
     final FileDescriptor serverFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0);
-    Libcore.os.bind(serverFd, address, 0);
+    Libcore.os.bind(serverFd, address);
     Libcore.os.listen(serverFd, 5);
 
     checkSockName(serverFd, isAbstract, address);
@@ -89,7 +96,7 @@
     Thread server = new Thread(new Runnable() {
       public void run() {
         try {
-          InetSocketAddress peerAddress = new InetSocketAddress();
+          UnixSocketAddress peerAddress = UnixSocketAddress.createUnnamed();
           FileDescriptor clientFd = Libcore.os.accept(serverFd, peerAddress);
           checkSockName(clientFd, isAbstract, address);
           checkNoName(peerAddress);
@@ -118,7 +125,7 @@
 
     FileDescriptor clientFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0);
 
-    Libcore.os.connect(clientFd, address, 0);
+    Libcore.os.connect(clientFd, address);
     checkNoSockName(clientFd);
 
     String string = "hello, world!";
@@ -134,26 +141,25 @@
     Libcore.os.close(clientFd);
   }
 
-  private void checkSockName(FileDescriptor fd, boolean isAbstract, InetAddress address) throws Exception {
-    InetSocketAddress isa = (InetSocketAddress) Libcore.os.getsockname(fd);
+  private static void checkSockName(FileDescriptor fd, boolean isAbstract,
+      UnixSocketAddress address) throws Exception {
+    UnixSocketAddress isa = (UnixSocketAddress) Libcore.os.getsockname(fd);
+    assertEquals(address, isa);
     if (isAbstract) {
-      checkNoName(isa);
-    } else {
-      assertEquals(address, isa.getAddress());
+      assertEquals(0, isa.getSunPath()[0]);
     }
   }
 
-  private void checkNoName(SocketAddress sa) {
-    InetSocketAddress isa = (InetSocketAddress) sa;
-    assertEquals(0, isa.getAddress().getAddress().length);
+  private void checkNoName(UnixSocketAddress usa) {
+    assertEquals(0, usa.getSunPath().length);
   }
 
   private void checkNoPeerName(FileDescriptor fd) throws Exception {
-    checkNoName(Libcore.os.getpeername(fd));
+    checkNoName((UnixSocketAddress) Libcore.os.getpeername(fd));
   }
 
   private void checkNoSockName(FileDescriptor fd) throws Exception {
-    checkNoName(Libcore.os.getsockname(fd));
+    checkNoName((UnixSocketAddress) Libcore.os.getsockname(fd));
   }
 
   public void test_strsignal() throws Exception {
@@ -219,7 +225,7 @@
   }
 
   static void checkByteBufferPositions_sendto_recvfrom(
-          int family, InetAddress loopback) throws Exception {
+      int family, InetAddress loopback) throws Exception {
     final FileDescriptor serverFd = Libcore.os.socket(family, SOCK_STREAM, 0);
     Libcore.os.bind(serverFd, loopback, 0);
     Libcore.os.listen(serverFd, 5);
@@ -252,13 +258,13 @@
       }
     });
 
-
     server.start();
 
     FileDescriptor clientFd = Libcore.os.socket(family, SOCK_STREAM, 0);
     Libcore.os.connect(clientFd, address.getAddress(), address.getPort());
 
-    final byte[] bytes = "good bye, cruel black hole with fancy distortion".getBytes(StandardCharsets.US_ASCII);
+    final byte[] bytes = "good bye, cruel black hole with fancy distortion"
+        .getBytes(StandardCharsets.US_ASCII);
     assertTrue(bytes.length > 24);
 
     ByteBuffer input = ByteBuffer.wrap(bytes);
@@ -340,11 +346,11 @@
   }
 
   public void test_sendtoSocketAddress_af_inet() throws Exception {
-      checkSendToSocketAddress(AF_INET, InetAddress.getByName("127.0.0.1"));
+    checkSendToSocketAddress(AF_INET, InetAddress.getByName("127.0.0.1"));
   }
 
   public void test_sendtoSocketAddress_af_inet6() throws Exception {
-      checkSendToSocketAddress(AF_INET6, InetAddress.getByName("::1"));
+    checkSendToSocketAddress(AF_INET6, InetAddress.getByName("::1"));
   }
 
   public void test_socketFamilies() throws Exception {
@@ -372,11 +378,11 @@
 
   private static void assertArrayEquals(byte[] expected, byte[] actual) {
     assertTrue("Expected=" + Arrays.toString(expected) + ", actual=" + Arrays.toString(actual),
-               Arrays.equals(expected, actual));
+        Arrays.equals(expected, actual));
   }
 
   private static void checkSocketPing(FileDescriptor fd, InetAddress to, byte[] packet,
-          byte type, byte responseType, boolean useSendto) throws Exception {
+      byte type, byte responseType, boolean useSendto) throws Exception {
     int len = packet.length;
     packet[0] = type;
     if (useSendto) {
@@ -406,8 +412,8 @@
     final byte ICMP_ECHO = 8, ICMP_ECHOREPLY = 0;
     final byte ICMPV6_ECHO_REQUEST = (byte) 128, ICMPV6_ECHO_REPLY = (byte) 129;
     final byte[] packet = ("\000\000\000\000" +  // ICMP type, code.
-                           "\000\000\000\003" +  // ICMP ID (== port), sequence number.
-                           "Hello myself").getBytes(StandardCharsets.US_ASCII);
+        "\000\000\000\003" +  // ICMP ID (== port), sequence number.
+        "Hello myself").getBytes(StandardCharsets.US_ASCII);
 
     FileDescriptor fd = Libcore.os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6);
     InetAddress ipv6Loopback = InetAddress.getByName("::1");
@@ -419,4 +425,90 @@
     checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, true);
     checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, false);
   }
+
+  public void test_Ipv4Fallback() throws Exception {
+    // This number of iterations gives a ~60% chance of creating the conditions that caused
+    // http://b/23088314 without making test times too long. On a hammerhead running MRZ37C using
+    // vogar, this test takes about 4s.
+    final int ITERATIONS = 10000;
+    for (int i = 0; i < ITERATIONS; i++) {
+      FileDescriptor mUdpSock = Libcore.os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+      try {
+          Libcore.os.bind(mUdpSock, Inet4Address.ANY, 0);
+      } catch(ErrnoException e) {
+          fail("ErrnoException after " + i + " iterations: " + e);
+      } finally {
+          Libcore.os.close(mUdpSock);
+      }
+    }
+  }
+
+  public void test_unlink() throws Exception {
+    File f = File.createTempFile("OsTest", "tst");
+    assertTrue(f.exists());
+    Libcore.os.unlink(f.getAbsolutePath());
+    assertFalse(f.exists());
+
+    try {
+      Libcore.os.unlink(f.getAbsolutePath());
+      fail();
+    } catch (ErrnoException e) {
+      assertEquals(OsConstants.ENOENT, e.errno);
+    }
+  }
+
+  public void test_xattr() throws Exception {
+    final String NAME_TEST = "user.meow";
+
+    final byte[] VALUE_CAKE = "cake cake cake".getBytes(StandardCharsets.UTF_8);
+    final byte[] VALUE_PIE = "pie".getBytes(StandardCharsets.UTF_8);
+
+    File file = File.createTempFile("xattr", "test");
+    String path = file.getAbsolutePath();
+
+    byte[] tmp = new byte[1024];
+    try {
+      try {
+        Libcore.os.getxattr(path, NAME_TEST, tmp);
+        fail("Expected ENODATA");
+      } catch (ErrnoException e) {
+        assertEquals(OsConstants.ENODATA, e.errno);
+      }
+
+      Libcore.os.setxattr(path, NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE);
+      assertEquals(VALUE_CAKE.length, Libcore.os.getxattr(path, NAME_TEST, tmp));
+      assertStartsWith(VALUE_CAKE, tmp);
+
+      try {
+        Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_CREATE);
+        fail("Expected EEXIST");
+      } catch (ErrnoException e) {
+        assertEquals(OsConstants.EEXIST, e.errno);
+      }
+
+      Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_REPLACE);
+      assertEquals(VALUE_PIE.length, Libcore.os.getxattr(path, NAME_TEST, tmp));
+      assertStartsWith(VALUE_PIE, tmp);
+
+      Libcore.os.removexattr(path, NAME_TEST);
+      try {
+        Libcore.os.getxattr(path, NAME_TEST, tmp);
+        fail("Expected ENODATA");
+      } catch (ErrnoException e) {
+        assertEquals(OsConstants.ENODATA, e.errno);
+      }
+
+    } finally {
+      file.delete();
+    }
+  }
+
+  private static void assertStartsWith(byte[] expectedContents, byte[] container) {
+    for (int i = 0; i < expectedContents.length; i++) {
+      if (expectedContents[i] != container[i]) {
+        fail("Expected " + Arrays.toString(expectedContents) + " but found "
+            + Arrays.toString(expectedContents));
+      }
+    }
+  }
 }
diff --git a/luni/src/test/java/libcore/java/io/SerializationTest.java b/luni/src/test/java/libcore/java/io/SerializationTest.java
index 32bc402..03e7d94 100644
--- a/luni/src/test/java/libcore/java/io/SerializationTest.java
+++ b/luni/src/test/java/libcore/java/io/SerializationTest.java
@@ -49,7 +49,9 @@
 
     static class FieldMadeTransient implements Serializable {
         private static final long serialVersionUID = 0L;
+        @SuppressWarnings("unused")
         private transient int transientInt;
+        @SuppressWarnings("unused")
         private int nonTransientInt;
     }
 
@@ -64,7 +66,7 @@
                 + "374244669656c644d6164655374617469630000000000000000020001490009737461746963496e7"
                 + "47870000022b8";
         FieldMadeStatic deserialized = (FieldMadeStatic) SerializationTester.deserializeHex(s);
-        // The field data is simply ignored if it is static.
+        // The field data must be ignored if it is static.
         assertEquals(9999, deserialized.staticInt);
     }
 
@@ -74,73 +76,101 @@
         private static int staticInt = 9999;
     }
 
+    public static boolean serializableContainer1InitializedFlag = false;
+    public static boolean unserializable1InitializedFlag = false;
+
+    public static class Unserializable1 {
+        static {
+            SerializationTest.unserializable1InitializedFlag = true;
+        }
+    }
+
+    static class SerializableContainer1 implements Serializable {
+        private static final long serialVersionUID = 0L;
+        private Unserializable1 unserializable = null;
+
+        static {
+            serializableContainer1InitializedFlag = true;
+        }
+    }
+
     // We can serialize an object that has an unserializable field providing it is null.
     public void testDeserializeNullUnserializableField() throws Exception {
         // This was created by creating a new SerializableContainer and not setting the
         // unserializable field. A canned serialized form is used so we can tell if the static
         // initializers were executed during deserialization.
-        // SerializationTester.serializeHex(new SerializableContainer());
-        String s = "aced0005737200376c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
-                + "3742453657269616c697a61626c65436f6e7461696e657200000000000000000200014c000e756e7"
-                + "3657269616c697a61626c657400334c6c6962636f72652f6a6176612f696f2f53657269616c697a6"
-                + "174696f6e546573742457617353657269616c697a61626c653b787070";
+        // SerializationTester.serializeHex(new SerializableContainer1());
+        String s = "aced0005737200386c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
+                  + "3742453657269616c697a61626c65436f6e7461696e65723100000000000000000200014c000e7"
+                  + "56e73657269616c697a61626c657400124c6a6176612f6c616e672f4f626a6563743b787070";
 
-        serializableContainerInitializedFlag = false;
-        wasSerializableInitializedFlag = false;
+        assertFalse(serializableContainer1InitializedFlag);
+        assertFalse(unserializable1InitializedFlag);
 
-        SerializableContainer sc = (SerializableContainer) SerializationTester.deserializeHex(s);
+        SerializableContainer1 sc = (SerializableContainer1) SerializationTester.deserializeHex(s);
         assertNull(sc.unserializable);
 
         // Confirm the container was initialized, but the class for the null field was not.
-        assertTrue(serializableContainerInitializedFlag);
-        assertFalse(wasSerializableInitializedFlag);
+        assertTrue(serializableContainer1InitializedFlag);
+        assertFalse(unserializable1InitializedFlag);
     }
 
-    public static boolean serializableContainerInitializedFlag = false;
+    static class Unserializable2 {
+    }
 
-    static class SerializableContainer implements Serializable {
+    static class HasUnserializableField implements Serializable {
         private static final long serialVersionUID = 0L;
-        private Object unserializable = null;
-
-        static {
-            serializableContainerInitializedFlag = true;
-        }
+        @SuppressWarnings("unused") // Required to make objects unserializable.
+        private Unserializable2 unserializable = new Unserializable2();
     }
 
     // We must not serialize an object that has a non-null unserializable field.
     public void testSerializeUnserializableField() throws Exception {
-        SerializableContainer sc = new SerializableContainer();
-        sc.unserializable = new WasSerializable();
+        HasUnserializableField uf = new HasUnserializableField();
         try {
-            SerializationTester.serializeHex(sc);
+            SerializationTester.serializeHex(uf);
             fail();
         } catch (NotSerializableException expected) {
         }
     }
 
+    public static boolean serializableContainer2InitializedFlag = false;
+
+    @SuppressWarnings("unused") // Required for deserialization test
+    static class SerializableContainer2 implements Serializable {
+        private static final long serialVersionUID = 0L;
+        private WasSerializable unserializable = null;
+
+        static {
+            serializableContainer2InitializedFlag = true;
+        }
+    }
+
     // It must not be possible to deserialize an object if a field is no longer serializable.
     public void testDeserializeUnserializableField() throws Exception {
-        // This was generated by creating a SerializableContainer and setting the unserializable
+        // This was generated by creating a SerializableContainer2 and setting the unserializable
         // field to a WasSerializable when it was still Serializable. A canned serialized form is
         // used so we can tell if the static initializers were executed during deserialization.
-        // SerializableContainer sc = new SerializableContainer();
+        // SerializableContainer2 sc = new SerializableContainer2();
         // sc.unserializable = new WasSerializable();
         // SerializationTester.serializeHex(sc);
-        String s = "aced0005737200376c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
-                + "3742453657269616c697a61626c65436f6e7461696e657200000000000000000200014c000e756e7"
-                + "3657269616c697a61626c657400124c6a6176612f6c616e672f4f626a6563743b7870737200316c6"
-                + "962636f72652e6a6176612e696f2e53657269616c697a6174696f6e5465737424576173536572696"
-                + "16c697a61626c65000000000000000002000149000169787000000000";
+        String s = "aced0005737200386c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
+                  + "3742453657269616c697a61626c65436f6e7461696e65723200000000000000000200014c000e7"
+                  + "56e73657269616c697a61626c657400334c6c6962636f72652f6a6176612f696f2f53657269616"
+                  + "c697a6174696f6e546573742457617353657269616c697a61626c653b7870737200316c6962636"
+                  + "f72652e6a6176612e696f2e53657269616c697a6174696f6e546573742457617353657269616c6"
+                  + "97a61626c65000000000000000002000149000169787000000000";
 
-        serializableContainerInitializedFlag = false;
-        wasSerializableInitializedFlag = false;
+        assertFalse(serializableContainer2InitializedFlag);
+        assertFalse(wasSerializableInitializedFlag);
         try {
             SerializationTester.deserializeHex(s);
             fail();
         } catch (InvalidClassException expected) {
         }
-        // Confirm neither the container nor the contained class was initialized.
-        assertFalse(serializableContainerInitializedFlag);
+        // The container class will be initialized to establish the serialVersionUID.
+        assertTrue(serializableContainer2InitializedFlag);
+        // Confirm the contained class was initialized.
         assertFalse(wasSerializableInitializedFlag);
     }
 
@@ -196,7 +226,7 @@
                 + "e546573742457617353657269616c697a61626c65000000000000000002000149000169787000000"
                 + "000";
 
-        wasSerializableInitializedFlag = false;
+        assertFalse(wasSerializableInitializedFlag);
         try {
             SerializationTester.deserializeHex(s);
             fail();
@@ -239,7 +269,7 @@
         final String s = "aced0005737200336c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6"
                 + "e546573742457617345787465726e616c697a61626c6500000000000000000c0000787078";
 
-        wasExternalizableInitializedFlag = false;
+        assertFalse(wasExternalizableInitializedFlag);
         try {
             SerializationTester.deserializeHex(s);
             fail();
@@ -275,7 +305,7 @@
                 + "e5465737424576173456e756d00000000000000001200007872000e6a6176612e6c616e672e456e7"
                 + "56d0000000000000000120000787074000556414c5545";
 
-        wasEnumInitializedFlag = false;
+        assertFalse(wasEnumInitializedFlag);
         try {
             SerializationTester.deserializeHex(s);
             fail();
@@ -309,7 +339,7 @@
         final String s = "aced00057372002b6c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6"
                 + "e54657374245761734f626a656374000000000000000002000149000169787000000000";
 
-        wasObjectInitializedFlag = false;
+        assertFalse(wasObjectInitializedFlag);
         try {
             SerializationTester.deserializeHex(s);
             fail();
diff --git a/luni/src/test/java/libcore/java/lang/OldAndroidMonitorTest.java b/luni/src/test/java/libcore/java/lang/OldAndroidMonitorTest.java
index 4760c6d..8ef507a 100755
--- a/luni/src/test/java/libcore/java/lang/OldAndroidMonitorTest.java
+++ b/luni/src/test/java/libcore/java/lang/OldAndroidMonitorTest.java
@@ -18,6 +18,8 @@
 
 import junit.framework.TestCase;
 
+import java.util.concurrent.CountDownLatch;
+
 public class OldAndroidMonitorTest extends TestCase {
 
     public void testWaitArgumentsTest() throws Exception {
@@ -102,363 +104,69 @@
             }
     }
 
-    private class Interrupter extends Thread {
-            private final Waiter waiter;
+    /**
+     * A thread that blocks forever on {@code wait()} until it's interrupted.
+     */
+    static class Waiter extends Thread {
+        private final Object lock;
+        private final CountDownLatch cdl;
+        private boolean wasInterrupted;
 
-            Interrupter(String name, Waiter waiter) {
-                super(name);
-                this.waiter = waiter;
-            }
-
-            public void run() {
-                try {
-                    run_inner();
-                } catch (Throwable t) {
-                    OldAndroidMonitorTest.errorException = t;
-                    OldAndroidMonitorTest.testThread.interrupt();
-                }
-            }
-
-            private void run_inner() {
-                // System.out.println("InterruptTest: starting waiter");
-                waiter.start();
-
-                try {
-                    Thread.currentThread().sleep(500);
-                } catch (InterruptedException ex) {
-                    throw new RuntimeException("Test sleep interrupted.", ex);
-                }
-
-                /* Waiter is spinning, and its monitor should still be thin.
-                 */
-                // System.out.println("Test interrupting waiter");
-                waiter.interrupt();
-                waiter.spin = false;
-
-                for (int i = 0; i < 3; i++) {
-                    /* Wait for the waiter to start waiting.
-                     */
-                    synchronized (waiter.interrupterLock) {
-                        try {
-                            waiter.interrupterLock.wait();
-                        } catch (InterruptedException ex) {
-                            throw new RuntimeException("Test wait interrupted.", ex);
-                        }
-                    }
-
-                    /* Before interrupting, grab the waiter lock, which
-                     * guarantees that the waiter is already sitting in wait().
-                     */
-                    synchronized (waiter) {
-                        //System.out.println("Test interrupting waiter (" + i + ")");
-                        waiter.interrupt();
-                    }
-                }
-
-                // System.out.println("Test waiting for waiter to die.");
-                try {
-                    waiter.join();
-                } catch (InterruptedException ex) {
-                    throw new RuntimeException("Test join interrupted.", ex);
-                }
-                // System.out.println("InterruptTest done.");
-            }
+        public Waiter(Object lock, CountDownLatch cdl) {
+            this.lock = lock;
+            this.cdl = cdl;
+            wasInterrupted = false;
         }
 
-    private class Waiter extends Thread {
-            Object interrupterLock = new Object();
-            volatile boolean spin = true;
-
-            Waiter(String name) {
-                super(name);
-            }
-
-            public void run() {
-                try {
-                    run_inner();
-                } catch (Throwable t) {
-                    OldAndroidMonitorTest.errorException = t;
-                    OldAndroidMonitorTest.testThread.interrupt();
-                }
-            }
-
-            void run_inner() {
-                // System.out.println("Waiter spinning");
-                while (spin) {
-                    // We're going to get interrupted while we spin.
-                }
-
-                if (interrupted()) {
-                    // System.out.println("Waiter done spinning; interrupted.");
-                } else {
-                    throw new RuntimeException("Thread not interrupted " +
-                                               "during spin");
-                }
-
-                synchronized (this) {
-                    boolean sawEx = false;
-
-                    try {
-                        synchronized (interrupterLock) {
-                            interrupterLock.notify();
-                        }
-                        // System.out.println("Waiter calling wait()");
-                        this.wait();
-                    } catch (InterruptedException ex) {
-                        sawEx = true;
-                        // System.out.println("wait(): Waiter caught " + ex);
-                    }
-                    // System.out.println("wait() finished");
-
-                    if (!sawEx) {
-                        throw new RuntimeException("Thread not interrupted " +
-                                                   "during wait()");
-                    }
-                }
-                synchronized (this) {
-                    boolean sawEx = false;
-
-                    try {
-                        synchronized (interrupterLock) {
-                            interrupterLock.notify();
-                        }
-                        // System.out.println("Waiter calling wait(1000)");
-                        this.wait(1000);
-                    } catch (InterruptedException ex) {
-                        sawEx = true;
-                        // System.out.println("wait(1000): Waiter caught " + ex);
-                    }
-                    // System.out.println("wait(1000) finished");
-
-                    if (!sawEx) {
-                        throw new RuntimeException("Thread not interrupted " +
-                                                   "during wait(1000)");
-                    }
-                }
-                synchronized (this) {
-                    boolean sawEx = false;
-
-                    try {
-                        synchronized (interrupterLock) {
-                            interrupterLock.notify();
-                        }
-                        // System.out.println("Waiter calling wait(1000, 5000)");
-                        this.wait(1000, 5000);
-                    } catch (InterruptedException ex) {
-                        sawEx = true;
-                        // System.out.println("wait(1000, 5000): Waiter caught " + ex);
-                    }
-                    // System.out.println("wait(1000, 5000) finished");
-
-                    if (!sawEx) {
-                        throw new RuntimeException("Thread not interrupted " +
-                                                   "during wait(1000, 5000)");
-                    }
-                }
-
-               //  System.out.println("Waiter returning");
-            }
-        }
-
-    private static Throwable errorException;
-    private static Thread testThread;
-
-    // TODO: Flaky test. Add back MediumTest annotation once fixed
-    public void testInterruptTest() throws Exception {
-
-
-            testThread = Thread.currentThread();
-            errorException = null;
-
-            Waiter waiter = new Waiter("InterruptTest Waiter");
-            Interrupter interrupter =
-                    new Interrupter("InterruptTest Interrupter", waiter);
-            interrupter.start();
-
-            try {
-                interrupter.join();
-                waiter.join();
-            } catch (InterruptedException ex) {
-                throw new RuntimeException("Test join interrupted.", ex);
-            }
-
-            if (errorException != null) {
-                throw new RuntimeException("InterruptTest failed",
-                                           errorException);
-            }
-
-
-
-
-    }
-
-     private static void deepWait(int depth, Object lock) {
-            synchronized (lock) {
-                if (depth > 0) {
-                    deepWait(depth - 1, lock);
-                } else {
-                    String threadName = Thread.currentThread().getName();
-                    try {
-                        // System.out.println(threadName + " waiting");
-                        lock.wait();
-                        // System.out.println(threadName + " done waiting");
-                    } catch (InterruptedException ex) {
-                        // System.out.println(threadName + " interrupted.");
-                    }
-                }
-            }
-        }
-
-        private class Worker extends Thread {
-            Object lock;
-            int id;
-
-            Worker(int id, Object lock) {
-                super("Worker(" + id + ")");
-                this.id = id;
-                this.lock = lock;
-            }
-
-            public void run() {
-                int iterations = 0;
-
-                while (OldAndroidMonitorTest.running) {
-                    OldAndroidMonitorTest.deepWait(id, lock);
-                    iterations++;
-                }
-                // System.out.println(getName() + " done after " + iterations + " iterations.");
-            }
-        }
-
-    private static Object commonLock = new Object();
-        private static Boolean running = false;
-
-
-    public void testNestedMonitors() throws Exception {
-        final int NUM_WORKERS = 5;
-
-            Worker w[] = new Worker[NUM_WORKERS];
-            int i;
-
-            for (i = 0; i < NUM_WORKERS; i++) {
-                w[i] = new Worker(i * 2 - 1, new Object());
-            }
-
-            running = true;
-
-            // System.out.println("NestedMonitors: starting workers");
-            for (i = 0; i < NUM_WORKERS; i++) {
-                w[i].start();
-            }
-
-            try {
-                Thread.currentThread().sleep(1000);
-            } catch (InterruptedException ex) {
-               // System.out.println("Test sleep interrupted.");
-            }
-
-            for (i = 0; i < 100; i++) {
-                for (int j = 0; j < NUM_WORKERS; j++) {
-                    synchronized (w[j].lock) {
-                        w[j].lock.notify();
-                    }
-                }
-            }
-
-            // System.out.println("NesterMonitors: stopping workers");
-            running = false;
-            for (i = 0; i < NUM_WORKERS; i++) {
-                synchronized (w[i].lock) {
-                    w[i].lock.notifyAll();
-                }
-            }
-    }
-
-    private static class CompareAndExchange extends Thread {
-        static Object toggleLock = null;
-        static int toggle = -1;
-        static Boolean running = false;
-
+        @Override
         public void run() {
-            toggleLock = new Object();
-            toggle = -1;
-
-            Worker w1 = new Worker(0, 1);
-            Worker w2 = new Worker(2, 3);
-            Worker w3 = new Worker(4, 5);
-            Worker w4 = new Worker(6, 7);
-
-            running = true;
-
-            // System.out.println("CompareAndExchange: starting workers");
-
-            w1.start();
-            w2.start();
-            w3.start();
-            w4.start();
-
-            try {
-                this.sleep(10000);
-            } catch (InterruptedException ex) {
-                // System.out.println(getName() + " interrupted.");
-            }
-
-            // System.out.println("MonitorTest: stopping workers");
-            running = false;
-
-            toggleLock = null;
-        }
-
-        class Worker extends Thread {
-            int i1;
-            int i2;
-
-            Worker(int i1, int i2) {
-                super("Worker(" + i1 + ", " + i2 + ")");
-                this.i1 = i1;
-                this.i2 = i2;
-            }
-
-            public void run() {
-                int iterations = 0;
-
-                /* Latch this because run() may set the static field to
-                 * null at some point.
-                 */
-                Object toggleLock = CompareAndExchange.toggleLock;
-
-                // System.out.println(getName() + " running");
+            synchronized (lock) {
                 try {
-                    while (CompareAndExchange.running) {
-                        synchronized (toggleLock) {
-                            int test;
-                            int check;
-
-                            if (CompareAndExchange.toggle == i1) {
-                                this.sleep(5 + i2);
-                                CompareAndExchange.toggle = test = i2;
-                            } else {
-                                this.sleep(5 + i1);
-                                CompareAndExchange.toggle = test = i1;
-                            }
-                            if ((check = CompareAndExchange.toggle) != test) {
-//                                System.out.println("Worker(" + i1 + ", " +
-//                                                   i2 + ") " + "test " + test +
-//                                                   " != toggle " + check);
-                                throw new RuntimeException(
-                                        "locked value changed");
-                            }
-                        }
-
-                        iterations++;
+                    cdl.countDown();
+                    while (true) {
+                        lock.wait();
                     }
                 } catch (InterruptedException ex) {
-                   // System.out.println(getName() + " interrupted.");
+                    wasInterrupted = true;
                 }
-
-//                System.out.println(getName() + " done after " +
-//                                   iterations + " iterations.");
             }
         }
+
+        public boolean wasInterrupted() {
+            synchronized (lock) {
+                return wasInterrupted;
+            }
+        }
+    }
+
+    public void testInterrupt() throws Exception {
+        final Object lock = new Object();
+        final CountDownLatch cdl = new CountDownLatch(1);
+        final Waiter waiter = new Waiter(lock, cdl);
+
+        waiter.start();
+
+        // Wait for the "waiter" to start and acquire |lock| for the first time.
+        try {
+            cdl.await();
+        } catch (InterruptedException ie) {
+            fail();
+        }
+
+        // Interrupt |waiter| after we acquire |lock|. This ensures that |waiter| is
+        // currently blocked on a call to "wait".
+        synchronized (lock) {
+            waiter.interrupt();
+        }
+
+        // Wait for the waiter to complete.
+        try {
+            waiter.join();
+        } catch (InterruptedException ie) {
+            fail();
+        }
+
+        // Assert than an InterruptedException was thrown.
+        assertTrue(waiter.wasInterrupted());
     }
 }
diff --git a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
index b7c4bc6..116eb3f 100644
--- a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
+++ b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
@@ -22,14 +22,18 @@
 import java.net.InetAddress;
 import java.net.InterfaceAddress;
 import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import libcore.io.IoUtils;
 
 public class NetworkInterfaceTest extends TestCase {
     // http://code.google.com/p/android/issues/detail?id=13784
+    private final static int ARPHRD_ETHER = 1; // from if_arp.h
     public void testIPv6() throws Exception {
         NetworkInterface lo = NetworkInterface.getByName("lo");
         Set<InetAddress> actual = new HashSet<InetAddress>(Collections.list(lo.getInetAddresses()));
@@ -70,24 +74,31 @@
         assertEquals(1, ifAddresses.size());
     }
 
+    public void testInterfaceProperties() throws Exception {
+        for (NetworkInterface nif : Collections.list(NetworkInterface.getNetworkInterfaces())) {
+            assertEquals(nif, NetworkInterface.getByName(nif.getName()));
+            // Skip interfaces that are inactive
+            if (nif.isUp() == false) {
+                continue;
+            }
+            // Ethernet
+            if (isEthernet(nif.getName())) {
+                assertEquals(6, nif.getHardwareAddress().length);
+                for (InterfaceAddress ia : nif.getInterfaceAddresses()) {
+                    if (ia.getAddress() instanceof Inet4Address) {
+                        assertNotNull(ia.getBroadcast());
+                    }
+                }
+            }
+        }
+    }
+
     public void testLoopback() throws Exception {
-        // We know lo shouldn't have a hardware address or an IPv4 broadcast address.
         NetworkInterface lo = NetworkInterface.getByName("lo");
         assertNull(lo.getHardwareAddress());
         for (InterfaceAddress ia : lo.getInterfaceAddresses()) {
             assertNull(ia.getBroadcast());
         }
-
-        // But eth0, if it exists, should...
-        NetworkInterface eth0 = NetworkInterface.getByName("eth0");
-        if (eth0 != null) {
-            assertEquals(6, eth0.getHardwareAddress().length);
-            for (InterfaceAddress ia : eth0.getInterfaceAddresses()) {
-                if (ia.getAddress() instanceof Inet4Address) {
-                    assertNotNull(ia.getBroadcast());
-                }
-            }
-        }
     }
 
     public void testDumpAll() throws Exception {
@@ -130,4 +141,14 @@
             allIndexes.add(nif.getIndex());
         }
     }
+
+    // Returns true if interface by name ifName is Ethernet
+    private boolean isEthernet(String ifName) throws Exception {
+        String s = IoUtils.readFileAsString("/sys/class/net/" + ifName + "/type").trim();
+        if (s.startsWith("0x")) {
+            return (Integer.parseInt(s.substring(2), 16) == ARPHRD_ETHER);
+        } else {
+            return (Integer.parseInt(s) == ARPHRD_ETHER);
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java b/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java
index 4fa6e0c..db2be53 100644
--- a/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java
+++ b/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java
@@ -85,7 +85,11 @@
 
     private static byte[] encode(String charsetName, String s) throws Exception {
         CharsetEncoder encoder = Charset.forName(charsetName).newEncoder();
-        return encoder.encode(CharBuffer.wrap(s)).array();
+        ByteBuffer buf = encoder.encode(CharBuffer.wrap(s));
+        byte[] out = new byte[buf.remaining()];
+        buf.get(out);
+        assertEquals(0, buf.remaining());
+        return out;
     }
 
     public void testUtf8BytesSplitAcrossMultipleWrites() throws Exception {
diff --git a/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java b/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java
index 1320a8a..10bb621 100644
--- a/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java
+++ b/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java
@@ -56,13 +56,32 @@
 
 public class KeyPairGeneratorTest extends TestCase {
 
-    public void test_providerCount() {
+    private List<Provider> providers = new ArrayList<Provider>();
+
+    @Override
+    public void setUp() {
         Provider[] providers = Security.getProviders();
+        for (Provider p : providers) {
+            // Do not test AndroidKeyStore Provider. It does not accept vanilla public keys for
+            // signature verification. It's OKish not to test here because it's tested by
+            // cts/tests/tests/keystore.
+            if (!p.getName().startsWith("AndroidKeyStore")) {
+                this.providers.add(p);
+            }
+        }
+    }
+
+    @Override
+    public void tearDown() {
+        providers.clear();
+    }
+
+    public void test_providerCount() {
         // We expect there to be at least one provider.
-        assertTrue(providers.length > 0);
+        assertTrue(providers.size() > 0);
         // If this fails remember to add _provider methods below. This test is sharded because it
         // takes a long time to execute.
-        assertTrue(providers.length < 10);
+        assertTrue(providers.size() < 10);
     }
 
     public void test_getInstance_provider0() throws Exception {
@@ -106,14 +125,14 @@
     }
 
     private void test_getInstance(int providerIndex) throws Exception {
-        Provider[] providers = Security.getProviders();
-        if (providerIndex >= providers.length) {
+        if (providerIndex >= providers.size()) {
             // Providers can be added by vendors and other tests. We do not
             // specify a fixed number and silenty pass if the provider at the
             // specified index does not exist.
             return;
         }
-        Provider provider = providers[providerIndex];
+
+        Provider provider = providers.get(providerIndex);
         Set<Provider.Service> services = provider.getServices();
         for (Provider.Service service : services) {
             String type = service.getType();
@@ -121,15 +140,6 @@
                 continue;
             }
             String algorithm = service.getAlgorithm();
-
-            // Do not test AndroidKeyStore's KeyPairGenerator. It cannot be initialized without
-            // providing AndroidKeyStore-specific algorithm parameters.
-            // It's OKish not to test AndroidKeyStore's KeyPairGenerator here because it's tested
-            // by cts/tests/test/keystore.
-            if ("AndroidKeyStore".equals(provider.getName())) {
-                continue;
-            }
-
             AlgorithmParameterSpec params = null;
 
             if ("DH".equals(algorithm)) {
@@ -306,8 +316,6 @@
         byte[] encoded = k.getEncoded();
 
         String keyAlgo = k.getAlgorithm();
-
-        Provider[] providers = Security.getProviders();
         for (Provider p : providers) {
             Set<Provider.Service> services = p.getServices();
             for (Provider.Service service : services) {
diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java
index f6e3a06..272dc21 100644
--- a/luni/src/test/java/libcore/java/security/SignatureTest.java
+++ b/luni/src/test/java/libcore/java/security/SignatureTest.java
@@ -16,7 +16,14 @@
 
 package libcore.java.security;
 
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import java.lang.reflect.Method;
 import java.math.BigInteger;
+import java.security.AlgorithmParameters;
 import java.security.InvalidKeyException;
 import java.security.InvalidParameterException;
 import java.security.KeyFactory;
@@ -29,6 +36,7 @@
 import java.security.Security;
 import java.security.Signature;
 import java.security.SignatureException;
+import java.security.SignatureSpi;
 import java.security.spec.DSAPrivateKeySpec;
 import java.security.spec.DSAPublicKeySpec;
 import java.security.spec.ECFieldFp;
@@ -41,8 +49,11 @@
 import java.security.spec.RSAPrivateKeySpec;
 import java.security.spec.RSAPublicKeySpec;
 import java.security.spec.X509EncodedKeySpec;
+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.Set;
 import java.util.concurrent.Callable;
@@ -1738,4 +1749,104 @@
         result = ecdsaVerify.verify(SIGNATURE);
         assertEquals(false, result);
     }
+
+    /**
+     * When an instance of a Signature is obtained, it's actually wrapped in an
+     * implementation that makes sure the correct SPI is selected and then calls
+     * through to the underlying SPI. We need to make sure that all methods on
+     * the delegate are wrapped and don't call directly into
+     * {@link SignatureSpi}.
+     */
+    public void testSignatureDelegateOverridesAllMethods() throws Exception {
+        Signature sig = Signature.getInstance("SHA1withRSA");
+
+        /*
+         * Make sure we're dealing with a delegate and not an actual instance of
+         * Signature.
+         */
+        Class<?> sigClass = sig.getClass();
+        assertFalse(sigClass.equals(SignatureSpi.class));
+        assertFalse(sigClass.equals(Signature.class));
+
+        List<String> methodsNotOverridden = new ArrayList<String>();
+
+        for (Method spiMethod : SignatureSpi.class.getDeclaredMethods()) {
+            try {
+                sigClass.getDeclaredMethod(spiMethod.getName(), spiMethod.getParameterTypes());
+            } catch (NoSuchMethodException e) {
+                methodsNotOverridden.add(spiMethod.toString());
+            }
+        }
+
+        assertEquals(Collections.EMPTY_LIST, methodsNotOverridden);
+    }
+
+    public void testGetParameters_IsCalled() throws Exception {
+        Provider provider = spy(new MockableProvider());
+        Provider.Service service = spy(new Provider.Service(provider, "Signature",
+                "FAKEFORGETPARAMETERS", "fake", null, null));
+        MockableSignatureSpi signatureSpi = mock(MockableSignatureSpi.class);
+
+        // Since these are spies, we want to use the doReturn(...) syntax to
+        // avoid calling the real methods.
+        doReturn(service).when(provider).getService(service.getType(), service.getAlgorithm());
+        doReturn(signatureSpi).when(service).newInstance(null);
+
+        Signature sig = Signature.getInstance(service.getAlgorithm(), provider);
+        sig.getParameters();
+        verify(signatureSpi).engineGetParameters();
+    }
+
+    public static class MockableProvider extends Provider {
+        protected MockableProvider() {
+            super("MockableProvider", 1.0, "Used by Mockito");
+        }
+    }
+
+    public static class MockableSignatureSpi extends SignatureSpi {
+        @Override
+        public void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void engineUpdate(byte b) throws SignatureException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public byte[] engineSign() throws SignatureException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean engineVerify(byte[] sigBytes) throws SignatureException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void engineSetParameter(String param, Object value) throws InvalidParameterException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Object engineGetParameter(String param) throws InvalidParameterException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public AlgorithmParameters engineGetParameters() {
+            throw new UnsupportedOperationException();
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/security/cert/FakeOidProvider.java b/luni/src/test/java/libcore/java/security/cert/FakeOidProvider.java
new file mode 100644
index 0000000..3e9183a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/cert/FakeOidProvider.java
@@ -0,0 +1,69 @@
+package libcore.java.security.cert;
+
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.SignatureSpi;
+
+public class FakeOidProvider extends Provider {
+    /**
+     * Used for testing some effects of algorithm OID mapping. We have to be
+     * slightly careful of the OID we pick here: the first number has to be 0,
+     * 1, or 2, and the second number has to be less than 39.
+     */
+    public static final String SIGALG_OID = "1.2.34359737229.1.1.5";
+
+    /**
+     * Used for testing some effects of algorithm OID mapping.
+     */
+    public static final String SIGALG_OID_NAME = "FAKEwithFAKE";
+
+    public static final String PROVIDER_NAME = "FakeOidProvider";
+
+    protected FakeOidProvider() {
+        super(PROVIDER_NAME, 1.0, "Fake OID Provider for Tests");
+
+        put("Signature." + SIGALG_OID, FakeOidSignature.class.getName());
+    }
+
+    public static class FakeOidSignature extends SignatureSpi {
+        @Override
+        protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
+        }
+
+        @Override
+        protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
+        }
+
+        @Override
+        protected void engineUpdate(byte b) throws SignatureException {
+        }
+
+        @Override
+        protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+        }
+
+        @Override
+        protected byte[] engineSign() throws SignatureException {
+            return null;
+        }
+
+        @Override
+        protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+            return true;
+        }
+
+        @Override
+        protected void engineSetParameter(String param, Object value)
+                throws InvalidParameterException {
+        }
+
+        @Override
+        protected Object engineGetParameter(String param) throws InvalidParameterException {
+            return null;
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
index c35f8e6..5ddbed3 100644
--- a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
@@ -16,6 +16,8 @@
 
 package libcore.java.security.cert;
 
+import org.apache.harmony.security.utils.AlgNameMapper;
+
 import tests.support.resource.Support_Resources;
 
 import java.io.BufferedInputStream;
@@ -294,6 +296,8 @@
                 generateCertificates_PKCS7_PEM_TrailingData(f);
                 generateCertificates_PKCS7_DER_TrailingData(f);
                 test_Serialization(f);
+                test_UnknownUnmappedKeyOID(f);
+                test_UnknownMappedKeyOID(f);
             } catch (Throwable e) {
                 out.append("Error encountered checking " + p.getName() + "\n");
                 e.printStackTrace(out);
@@ -1174,7 +1178,7 @@
             Collection<? extends X509Certificate> certs = (Collection<? extends X509Certificate>)
                     f.generateCertificates(bais);
             if (StandardNames.IS_RI) {
-                fail("RI fails on this test.");
+                return;
             }
         } catch (CertificateParsingException e) {
             if (StandardNames.IS_RI) {
@@ -1204,7 +1208,7 @@
             Collection<? extends X509Certificate> certs = (Collection<? extends X509Certificate>)
                     f.generateCertificates(bais);
             if (StandardNames.IS_RI) {
-                fail("RI fails on this test.");
+                return;
             }
         } catch (CertificateParsingException e) {
             if (StandardNames.IS_RI) {
@@ -1249,12 +1253,7 @@
         Collection<? extends X509Certificate> certs = (Collection<? extends X509Certificate>)
                 f.generateCertificates(bais);
 
-        // RI is broken
-        if (StandardNames.IS_RI) {
-            assertEquals(0, bais.available());
-        } else {
-            assertEquals(4096, bais.available());
-        }
+        assertEquals(4096, bais.available());
     }
 
     private void test_Serialization(CertificateFactory f) throws Exception {
@@ -1284,6 +1283,89 @@
         }
     }
 
+    private void test_UnknownUnmappedKeyOID(CertificateFactory f) throws Exception {
+        byte[] certBytes = generateFakeOidCertificate();
+
+        {
+            X509Certificate cert = (X509Certificate) f
+                    .generateCertificate(new ByteArrayInputStream(certBytes));
+            assertEquals(FakeOidProvider.SIGALG_OID, cert.getSigAlgOID());
+            assertEquals(FakeOidProvider.SIGALG_OID, cert.getSigAlgName());
+        }
+    }
+
+    private void test_UnknownMappedKeyOID(CertificateFactory f) throws Exception {
+        AlgNameMapper.addMapping(FakeOidProvider.SIGALG_OID, FakeOidProvider.SIGALG_OID_NAME);
+
+        Security.addProvider(new FakeOidProvider());
+        try {
+            byte[] certBytes = generateFakeOidCertificate();
+
+            // Make sure the certificate is outputting something.
+            X509Certificate cert = (X509Certificate) f
+                    .generateCertificate(new ByteArrayInputStream(certBytes));
+            assertEquals(FakeOidProvider.SIGALG_OID, cert.getSigAlgOID());
+            if ("AndroidOpenSSL".equals(f.getProvider().getName())) {
+                // AndroidOpenSSL provider has a connection to AlgNameMapper, so
+                // we expect it to get our special name.
+                assertEquals(FakeOidProvider.SIGALG_OID_NAME, cert.getSigAlgName());
+            } else {
+                assertNotNull(cert.getSigAlgName());
+            }
+
+            cert.verify(cert.getPublicKey());
+        } finally {
+            AlgNameMapper
+                    .removeMapping(FakeOidProvider.SIGALG_OID, FakeOidProvider.SIGALG_OID_NAME);
+            Security.removeProvider(FakeOidProvider.PROVIDER_NAME);
+        }
+    }
+
+    private byte[] generateFakeOidCertificate() throws IOException {
+        byte[] certBytes;
+
+        // Read in the original cert.
+        {
+            InputStream is = null;
+            try {
+                is = Support_Resources.getStream(CERT_RSA);
+
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                byte[] buffer = new byte[2048];
+                int numRead;
+                while ((numRead = is.read(buffer, 0, buffer.length)) != -1) {
+                    baos.write(buffer, 0, numRead);
+                }
+                certBytes = baos.toByteArray();
+            } finally {
+                if (is != null) {
+                    try {
+                        is.close();
+                    } catch (IOException ignored) {
+                    }
+                }
+            }
+        }
+
+        // Fix the OID for the certificate.
+        {
+            int numFixed = 0;
+            for (int i = 0; i < certBytes.length - 5; i++) {
+                if (certBytes[i] == (byte) 0x2A && certBytes[i + 1] == (byte) 0x86
+                        && certBytes[i + 2] == (byte) 0x48 && certBytes[i + 3] == (byte) 0x86
+                        && certBytes[i + 4] == (byte) 0xF7) {
+                    certBytes[i + 1] = (byte) 0xFF;
+                    certBytes[i + 2] = (byte) 0xFF;
+                    certBytes[i + 3] = (byte) 0xFF;
+                    i += 4;
+                    numFixed++;
+                }
+            }
+            assertEquals(3, numFixed);
+        }
+        return certBytes;
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
diff --git a/luni/src/test/java/libcore/java/text/OldBidiTest.java b/luni/src/test/java/libcore/java/text/OldBidiTest.java
index 45fe258..fbf68ea 100644
--- a/luni/src/test/java/libcore/java/text/OldBidiTest.java
+++ b/luni/src/test/java/libcore/java/text/OldBidiTest.java
@@ -70,4 +70,126 @@
         assertEquals(1, bd.getRunStart(1));
         assertEquals(2, bd.getRunStart(2));
     }
+
+    public void testReorderVisuallyIllegalArguments() {
+        // Negative index.
+        try {
+            Bidi.reorderVisually(new byte[] {}, -1, new Object[] {}, 0, 0);
+            fail();
+        } catch (IllegalArgumentException  expected) {
+            // Expected.
+        }
+
+        try {
+            Bidi.reorderVisually(new byte[] {}, 0, new Object[] {}, -1, 0);
+            fail();
+        } catch (IllegalArgumentException  expected) {
+            // Expected.
+        }
+
+        try {
+            Bidi.reorderVisually(new byte[] {}, 0, new Object[] {}, 0, -1);
+            fail();
+        } catch (IllegalArgumentException  expected) {
+            // Expected.
+        }
+
+        // Count > levels.length.
+        try {
+            Bidi.reorderVisually(new byte[] {}, 0, new Object[] {}, 0, 1);
+            fail();
+        } catch (IllegalArgumentException  expected) {
+            // Expected.
+        }
+
+        // Count > levels.length - levelStart.
+        try {
+            Bidi.reorderVisually(new byte[] {1, 2, 3}, 2, new Object[] {}, 0, 2);
+            fail();
+        } catch (IllegalArgumentException  expected) {
+            // Expected.
+        }
+    }
+
+    public void testRequiresBidiIllegalArguments() {
+        // Negative param.
+        try {
+            Bidi.requiresBidi(new char[] {}, 0, -1);
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+
+        try {
+            Bidi.requiresBidi(new char[] {}, -1, 0);
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+
+        // Limit > start.
+        try {
+            Bidi.requiresBidi(new char[] {}, 1, 0);
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+
+        // Limit > text.length.
+        try {
+            Bidi.requiresBidi(new char[] {'a', 'b', 'c'}, 0, 4);
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+    }
+
+    public void testCreateLineBidiIllegalArguments() {
+        Bidi bidi = new Bidi("test", Bidi.DIRECTION_LEFT_TO_RIGHT);
+
+        try {
+            bidi.createLineBidi(-1, 0);
+            fail();
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+
+        try {
+            bidi.createLineBidi(0, -1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+
+        // Linelimit > getLength().
+        try {
+            bidi.createLineBidi(0, 5);
+            fail();
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+
+        // lineStart > lineLimit.
+         try {
+            bidi.createLineBidi(2, 1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+    }
+
+    public void testConstructorIllegalArguments() {
+        try {
+            new Bidi(null, Bidi.DIRECTION_LEFT_TO_RIGHT);
+            fail();
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+
+        // text.length - textStart < paragraphLength.
+        try {
+            new Bidi(new char[] {'a', 'b', 'c', 'd', 'e'}, 1, new byte[] {}, 0, 5,
+                    Bidi.DIRECTION_LEFT_TO_RIGHT);
+            fail();
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+    }
+
 }
diff --git a/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java b/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java
index 7a5fc4a..04396f4 100644
--- a/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java
@@ -17,7 +17,6 @@
 
 package libcore.java.util;
 
-import dalvik.annotation.AndroidOnly;
 import java.util.Date;
 import java.util.Locale;
 import java.util.TimeZone;
@@ -103,7 +102,6 @@
         assertEquals("Pacific Standard Time", tz.getDisplayName(false, TimeZone.LONG));
     }
 
-    @AndroidOnly("fail on RI. See comment below")
     public void test_getDisplayNameZILjava_util_Locale() {
         TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
         assertEquals("Pacific Daylight Time", tz.getDisplayName(true,  TimeZone.LONG, Locale.US));
diff --git a/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java b/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java
index 2e32f7d..6b25f08 100644
--- a/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java
@@ -101,6 +101,13 @@
         }
     }
 
+    static class FlushingDeflater extends Deflater {
+        @Override
+        public int deflate(byte[] buf, int offset, int byteCount) {
+            return super.deflate(buf, offset, byteCount, Deflater.SYNC_FLUSH);
+        }
+    }
+
     /**
      * Confirm that a DeflaterOutputStream constructed with Deflater
      * with flushParm == SYNC_FLUSH does not need to to be flushed.
@@ -108,11 +115,7 @@
      * http://b/4005091
      */
     public void testSyncFlushDeflater() throws Exception {
-        Deflater def = new Deflater();
-        Field f = def.getClass().getDeclaredField("flushParm");
-        f.setAccessible(true);
-        f.setInt(def, Deflater.SYNC_FLUSH);
-
+        Deflater def = new FlushingDeflater();
         final int deflaterBufferSize = 512;
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         DeflaterOutputStream dos = new DeflaterOutputStream(baos, def, deflaterBufferSize);
diff --git a/luni/src/test/java/libcore/java/util/zip/Zip64Test.java b/luni/src/test/java/libcore/java/util/zip/Zip64Test.java
new file mode 100644
index 0000000..e4b5baf
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/zip/Zip64Test.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2015 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.java.util.zip;
+
+import junit.framework.TestCase;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.zip.Zip64;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+
+public class Zip64Test extends TestCase {
+
+    // We shouldn't attempt to look inside the extended info if we have valid fields
+    // in the regular file header / central directory entry.
+    public void testParseZip64ExtendedInfo_noFieldsPresent() throws Exception {
+        ZipEntry ze = createZipEntry(null, 100, 200, ZipEntry.STORED, 300);
+        Zip64.parseZip64ExtendedInfo(ze, false /* fromCentralDirectory */);
+        Zip64.parseZip64ExtendedInfo(ze, true /* fromCentralDirectory */);
+    }
+
+    // We *should* attempt to look in the extended info if the local file header / central
+    // directory entry don't have the correct values.
+    public void testParseZip64ExtendedInfo_missingExtendedInfo() throws Exception {
+        ZipEntry ze = createZipEntry(null, Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE,
+                Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE, ZipEntry.STORED, 300);
+        try {
+            Zip64.parseZip64ExtendedInfo(ze, false /* fromCentralDirectory */);
+            fail();
+        } catch (ZipException expected) {
+        }
+
+        try {
+            Zip64.parseZip64ExtendedInfo(ze, true /* fromCentralDirectory */);
+            fail();
+        } catch (ZipException expected) {
+        }
+    }
+
+    // Test the case where the compressed / uncompressed sizes are in the extended info
+    // but the header offset isn't.
+    public void testParseZip64ExtendedInfo_partialInfo() throws Exception {
+        byte[] extras = new byte[20];
+        ByteBuffer buf = ByteBuffer.wrap(extras);
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+        buf.putShort((short) 0x0001);
+        buf.putShort((short) 16);
+        buf.putLong(50);
+        buf.putLong(100);
+
+        ZipEntry ze = createZipEntry(extras, Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE,
+                Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE, ZipEntry.STORED, 300);
+
+        Zip64.parseZip64ExtendedInfo(ze, false /*fromCentralDirectory */);
+        assertEquals(50, ze.getSize());
+        assertEquals(100, ze.getCompressedSize());
+
+        ze = createZipEntry(extras, Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE,
+                Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE, ZipEntry.STORED, 300);
+        Zip64.parseZip64ExtendedInfo(ze, true /*fromCentralDirectory */);
+        assertEquals(50, ze.getSize());
+        assertEquals(100, ze.getCompressedSize());
+    }
+
+    public void testInsertZip64ExtendedInfo() throws Exception {
+        ZipEntry ze = createZipEntry(null, Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE + 300,
+                Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE + 500, ZipEntry.STORED, 300);
+        Zip64.insertZip64ExtendedInfoToExtras(ze);
+
+        assertNotNull(ze.getExtra());
+        ByteBuffer buf = ByteBuffer.wrap(ze.getExtra());
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+        assertEquals(0x0001, buf.getShort());
+        assertEquals(24, buf.getShort());
+        assertEquals(Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE + 300, buf.getLong());
+        assertEquals(Zip64.MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE + 500, buf.getLong());
+    }
+
+    private static ZipEntry createZipEntry(byte[] extras, long size, long compressedSize,
+                                           int compressionMethod, long headerOffset) {
+        return new ZipEntry("name", "comment", 42 /* crc */, compressedSize, size,
+                compressionMethod, 42 /* time */, 42 /* modDate */, extras, headerOffset,
+                42 /* data offset */);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java b/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java
index 49990a3..1dc22ca 100644
--- a/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/ZipInputStreamTest.java
@@ -18,6 +18,9 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.Charset;
@@ -29,6 +32,7 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
 
@@ -82,4 +86,33 @@
             in.close();
         }
     }
+
+    // NOTE: Using octal because it's easiest to use "hexdump -b" to dump file contents.
+    private static final byte[] INCOMPLETE_ZIP = new byte[] {
+            0120, 0113, 0003, 0004, 0024, 0000, 0010, 0010, 0010, 0000, 0002, 0035, (byte) 0330,
+            0106, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0013,
+            0000, 0000, 0000, 0146, 0157, 0157, 0057, 0142, 0141, 0162, 0056, 0160, 0156, 0147 };
+
+    // http://b//21846904
+    public void testReadOnIncompleteStream() throws Exception {
+        ZipInputStream zi = new ZipInputStream(new ByteArrayInputStream(INCOMPLETE_ZIP));
+        ZipEntry ze = zi.getNextEntry();
+
+        // read() and closeEntry() must throw IOExceptions to indicate that
+        // the stream is corrupt. The bug above reported that they would loop
+        // forever.
+        try {
+            zi.read(new byte[1024], 0, 1024);
+            fail();
+        } catch (IOException expected) {
+        }
+
+        try {
+            zi.closeEntry();
+            fail();
+        } catch (IOException expected) {
+        }
+
+        zi.close();
+    }
 }
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index afd2e59..13d54b4 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -27,6 +27,7 @@
 import java.security.InvalidKeyException;
 import java.security.Key;
 import java.security.KeyFactory;
+import java.security.KeyPairGenerator;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.Provider;
@@ -988,24 +989,129 @@
         Security.addProvider(mockProviderInvalid);
         try {
             Cipher c = Cipher.getInstance("FOO");
-            if (StandardNames.IS_RI) {
-                c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[16], "FOO"));
-            } else {
-                fail("Should not find any matching providers; found: " + c);
-            }
-        } catch (NoSuchAlgorithmException maybe) {
-            if (StandardNames.IS_RI) {
-                throw maybe;
-            }
-        } catch (ClassCastException maybe) {
-            if (!StandardNames.IS_RI) {
-                throw maybe;
-            }
+            c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[16], "FOO"));
+            fail("Should not find any matching providers; found: " + c);
+        } catch (ClassCastException expected) {
         } finally {
             Security.removeProvider(mockProviderInvalid.getName());
         }
     }
 
+    public void testCipher_init_CallsInitWithParams_AlgorithmParameterSpec() throws Exception {
+        Provider mockProviderRejects = new MockProvider("MockProviderRejects") {
+            public void setup() {
+                put("Cipher.FOO",
+                        MockCipherSpi.MustInitWithAlgorithmParameterSpec_RejectsAll.class.getName());
+                put("Cipher.FOO SupportedKeyClasses", MockKey.class.getName());
+            }
+        };
+        Provider mockProviderAccepts = new MockProvider("MockProviderAccepts") {
+            public void setup() {
+                put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
+                put("Cipher.FOO SupportedKeyClasses", MockKey.class.getName());
+            }
+        };
+
+        Security.addProvider(mockProviderRejects);
+        Security.addProvider(mockProviderAccepts);
+        try {
+            Cipher c = Cipher.getInstance("FOO");
+            c.init(Cipher.ENCRYPT_MODE, new MockKey(), new IvParameterSpec(new byte[12]));
+            assertEquals(mockProviderAccepts, c.getProvider());
+        } finally {
+            Security.removeProvider(mockProviderRejects.getName());
+            Security.removeProvider(mockProviderAccepts.getName());
+        }
+    }
+
+    public void testCipher_init_CallsInitWithParams_AlgorithmParameters() throws Exception {
+        Provider mockProviderRejects = new MockProvider("MockProviderRejects") {
+            public void setup() {
+                put("Cipher.FOO",
+                        MockCipherSpi.MustInitWithAlgorithmParameters_RejectsAll.class.getName());
+                put("Cipher.FOO SupportedKeyClasses", MockKey.class.getName());
+            }
+        };
+        Provider mockProviderAccepts = new MockProvider("MockProviderAccepts") {
+            public void setup() {
+                put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
+                put("Cipher.FOO SupportedKeyClasses", MockKey.class.getName());
+            }
+        };
+
+        Security.addProvider(mockProviderRejects);
+        Security.addProvider(mockProviderAccepts);
+        try {
+            Cipher c = Cipher.getInstance("FOO");
+            c.init(Cipher.ENCRYPT_MODE, new MockKey(), AlgorithmParameters.getInstance("AES"));
+            assertEquals(mockProviderAccepts, c.getProvider());
+        } finally {
+            Security.removeProvider(mockProviderRejects.getName());
+            Security.removeProvider(mockProviderAccepts.getName());
+        }
+    }
+
+    public void testCipher_init_CallsInitIgnoresRuntimeException() throws Exception {
+        Provider mockProviderRejects = new MockProvider("MockProviderRejects") {
+            public void setup() {
+                put("Cipher.FOO",
+                        MockCipherSpi.MustInitWithAlgorithmParameters_ThrowsNull.class.getName());
+                put("Cipher.FOO SupportedKeyClasses", MockKey.class.getName());
+            }
+        };
+        Provider mockProviderAccepts = new MockProvider("MockProviderAccepts") {
+            public void setup() {
+                put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
+                put("Cipher.FOO SupportedKeyClasses", MockKey.class.getName());
+            }
+        };
+
+        Security.addProvider(mockProviderRejects);
+        Security.addProvider(mockProviderAccepts);
+        try {
+            Cipher c = Cipher.getInstance("FOO");
+            c.init(Cipher.ENCRYPT_MODE, new MockKey(), AlgorithmParameters.getInstance("AES"));
+            assertEquals(mockProviderAccepts, c.getProvider());
+        } finally {
+            Security.removeProvider(mockProviderRejects.getName());
+            Security.removeProvider(mockProviderAccepts.getName());
+        }
+    }
+
+    public void testCipher_init_CallsInitWithMode() throws Exception {
+        Provider mockProviderOnlyEncrypt = new MockProvider("MockProviderOnlyEncrypt") {
+            public void setup() {
+                put("Cipher.FOO", MockCipherSpi.MustInitForEncryptModeOrRejects.class.getName());
+                put("Cipher.FOO SupportedKeyClasses", MockKey.class.getName());
+            }
+        };
+        Provider mockProviderAcceptsAll = new MockProvider("MockProviderAcceptsAll") {
+            public void setup() {
+                put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
+                put("Cipher.FOO SupportedKeyClasses", MockKey.class.getName());
+            }
+        };
+
+        Security.addProvider(mockProviderOnlyEncrypt);
+        Security.addProvider(mockProviderAcceptsAll);
+        try {
+            {
+                Cipher c = Cipher.getInstance("FOO");
+                c.init(Cipher.DECRYPT_MODE, new MockKey(), AlgorithmParameters.getInstance("AES"));
+                assertEquals(mockProviderAcceptsAll, c.getProvider());
+            }
+
+            {
+                Cipher c = Cipher.getInstance("FOO");
+                c.init(Cipher.ENCRYPT_MODE, new MockKey(), AlgorithmParameters.getInstance("AES"));
+                assertEquals(mockProviderOnlyEncrypt, c.getProvider());
+            }
+        } finally {
+            Security.removeProvider(mockProviderOnlyEncrypt.getName());
+            Security.removeProvider(mockProviderAcceptsAll.getName());
+        }
+    }
+
     public void test_getInstance() throws Exception {
         final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();
         PrintStream out = new PrintStream(errBuffer);
@@ -1162,6 +1268,57 @@
                     c.doFinal(new byte[1]).length);
         }
 
+        if (isPBE(algorithm)) {
+            if (algorithm.endsWith("RC4")) {
+                assertNull(cipherID + " getIV()", c.getIV());
+            } else {
+                assertNotNull(cipherID + " getIV()", c.getIV());
+            }
+        } else if (encryptSpec instanceof IvParameterSpec) {
+            assertEquals(cipherID + " getIV()",
+                    Arrays.toString(((IvParameterSpec) encryptSpec).getIV()),
+                    Arrays.toString(c.getIV()));
+        } else if (encryptSpec instanceof GCMParameterSpec) {
+            assertNotNull(c.getIV());
+            assertEquals(cipherID + " getIV()",
+                    Arrays.toString(((GCMParameterSpec) encryptSpec).getIV()),
+                    Arrays.toString(c.getIV()));
+        } else {
+            try {
+                assertNull(cipherID + " getIV()", c.getIV());
+            } catch (NullPointerException e) {
+                // Bouncycastle apparently has a bug here with AESWRAP, et al.
+                if (!("BC".equals(providerName) && isOnlyWrappingAlgorithm(algorithm))) {
+                    throw e;
+                }
+            }
+        }
+
+        AlgorithmParameters encParams = c.getParameters();
+        if (encryptSpec == null) {
+            assertNull(cipherID + " getParameters()", encParams);
+        } else if (encryptSpec instanceof GCMParameterSpec) {
+            GCMParameterSpec gcmDecryptSpec = (GCMParameterSpec) encParams
+                    .getParameterSpec(GCMParameterSpec.class);
+            assertEquals(cipherID + " getIV()",
+                    Arrays.toString(((GCMParameterSpec) encryptSpec).getIV()),
+                    Arrays.toString(gcmDecryptSpec.getIV()));
+            assertEquals(cipherID + " getTLen()", ((GCMParameterSpec) encryptSpec).getTLen(),
+                    gcmDecryptSpec.getTLen());
+        } else if (encryptSpec instanceof IvParameterSpec) {
+            IvParameterSpec ivDecryptSpec = (IvParameterSpec) encParams
+                    .getParameterSpec(IvParameterSpec.class);
+            assertEquals(cipherID + " getIV()",
+                    Arrays.toString(((IvParameterSpec) encryptSpec).getIV()),
+                    Arrays.toString(ivDecryptSpec.getIV()));
+        } else if (encryptSpec instanceof PBEParameterSpec) {
+            // Bouncycastle seems to be undecided about whether it returns this
+            // or not
+            if (!"BC".equals(providerName)) {
+                assertNotNull(cipherID + " getParameters()", encParams);
+            }
+        }
+
         final AlgorithmParameterSpec decryptSpec = getDecryptAlgorithmParameterSpec(encryptSpec, c);
         int decryptMode = getDecryptMode(algorithm);
 
@@ -1199,18 +1356,27 @@
             }
         }
 
-        AlgorithmParameters params = c.getParameters();
+        AlgorithmParameters decParams = c.getParameters();
         if (decryptSpec == null) {
-            assertNull(cipherID + " getParameters()", params);
+            assertNull(cipherID + " getParameters()", decParams);
+        } else if (decryptSpec instanceof GCMParameterSpec) {
+            GCMParameterSpec gcmDecryptSpec = (GCMParameterSpec) decParams
+                    .getParameterSpec(GCMParameterSpec.class);
+            assertEquals(cipherID + " getIV()",
+                    Arrays.toString(((GCMParameterSpec) decryptSpec).getIV()),
+                    Arrays.toString(gcmDecryptSpec.getIV()));
+            assertEquals(cipherID + " getTLen()", ((GCMParameterSpec) decryptSpec).getTLen(),
+                    gcmDecryptSpec.getTLen());
         } else if (decryptSpec instanceof IvParameterSpec) {
-            IvParameterSpec ivDecryptSpec = (IvParameterSpec) params.getParameterSpec(IvParameterSpec.class);
+            IvParameterSpec ivDecryptSpec = (IvParameterSpec) decParams
+                    .getParameterSpec(IvParameterSpec.class);
             assertEquals(cipherID + " getIV()",
                     Arrays.toString(((IvParameterSpec) decryptSpec).getIV()),
                     Arrays.toString(ivDecryptSpec.getIV()));
         } else if (decryptSpec instanceof PBEParameterSpec) {
-            // Bouncycastle seems to be schizophrenic about whther it returns this or not
+            // Bouncycastle seems to be undecided about whether it returns this or not
             if (!"BC".equals(providerName)) {
-                assertNotNull(cipherID + " getParameters()", params);
+                assertNotNull(cipherID + " getParameters()", decParams);
             }
         }
 
@@ -3388,4 +3554,63 @@
             assertEquals("", new String(buffer, 0, bytesProduced, StandardCharsets.US_ASCII));
         }
     }
+
+    /**
+     * If a provider rejects a key for "Cipher/Mode/Padding"", there might be another that
+     * accepts the key for "Cipher". Don't throw InvalidKeyException when trying the first one.
+     * http://b/22208820
+     */
+    public void testCipher_init_tryAllCombinationsBeforeThrowingInvalidKey()
+            throws Exception {
+        Provider mockProvider = new MockProvider("MockProvider") {
+            public void setup() {
+                put("Cipher.FOO/FOO/FOO", MockCipherSpi.AllKeyTypes.class.getName());
+                put("Cipher.FOO/FOO/FOO SupportedKeyClasses", "none");
+            }
+        };
+
+        Provider mockProvider2 = new MockProvider("MockProvider2") {
+            public void setup() {
+                put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
+            }
+        };
+
+        Security.addProvider(mockProvider);
+
+        try {
+            try {
+                // The provider installed doesn't accept the key.
+                Cipher c = Cipher.getInstance("FOO/FOO/FOO");
+                c.init(Cipher.DECRYPT_MODE, new MockKey());
+                fail("Expected InvalidKeyException");
+            } catch (InvalidKeyException expected) {
+            }
+
+            Security.addProvider(mockProvider2);
+
+            try {
+                // The new provider accepts "FOO" with this key. Use it despite the other provider
+                // accepts "FOO/FOO/FOO" but doesn't accept the key.
+                Cipher c = Cipher.getInstance("FOO/FOO/FOO");
+                c.init(Cipher.DECRYPT_MODE, new MockKey());
+                assertEquals("MockProvider2", c.getProvider().getName());
+            } finally {
+                Security.removeProvider(mockProvider2.getName());
+            }
+        } finally {
+            Security.removeProvider(mockProvider.getName());
+        }
+    }
+
+    /**
+     * Check that RSA with OAEPPadding is supported.
+     * http://b/22208820
+     */
+    public void test_RSA_OAEPPadding() throws Exception {
+        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+        keyGen.initialize(1024, SecureRandom.getInstance("SHA1PRNG"));
+        Cipher cipher = Cipher.getInstance("RSA/NONE/OAEPPadding");
+        cipher.init(Cipher.ENCRYPT_MODE, keyGen.generateKeyPair().getPublic());
+        cipher.doFinal(new byte[] {1,2,3,4});
+    }
 }
diff --git a/luni/src/test/java/libcore/javax/crypto/MockCipherSpi.java b/luni/src/test/java/libcore/javax/crypto/MockCipherSpi.java
index 6742cf3..c1b1bd2 100644
--- a/luni/src/test/java/libcore/javax/crypto/MockCipherSpi.java
+++ b/luni/src/test/java/libcore/javax/crypto/MockCipherSpi.java
@@ -25,6 +25,7 @@
 import java.security.spec.AlgorithmParameterSpec;
 
 import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
 import javax.crypto.CipherSpi;
 import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.NoSuchPaddingException;
@@ -56,6 +57,92 @@
     public static class AllKeyTypes extends MockCipherSpi {
     }
 
+    public static class MustInitWithAlgorithmParameterSpec_RejectsAll extends MockCipherSpi {
+        @Override
+        protected void engineInit(int opmode, Key key, SecureRandom random)
+                throws InvalidKeyException {
+            throw new AssertionError("Must have AlgorithmParameterSpec");
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+                SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+            throw new InvalidAlgorithmParameterException("expected rejection");
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+                SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+            throw new AssertionError("Must have AlgorithmParameterSpec");
+        }
+    }
+
+    public static class MustInitWithAlgorithmParameters_RejectsAll extends MockCipherSpi {
+        @Override
+        protected void engineInit(int opmode, Key key, SecureRandom random)
+                throws InvalidKeyException {
+            throw new AssertionError("Must have AlgorithmParameterSpec");
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+                SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+            throw new AssertionError("Must have AlgorithmParameterSpec");
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+                SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+            throw new InvalidAlgorithmParameterException("expected rejection");
+        }
+    }
+
+    public static class MustInitWithAlgorithmParameters_ThrowsNull extends MockCipherSpi {
+        @Override
+        protected void engineInit(int opmode, Key key, SecureRandom random)
+                throws InvalidKeyException {
+            throw new NullPointerException("expected rejection");
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+                SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+            throw new NullPointerException("expected rejection");
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+                SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+            throw new NullPointerException("expected rejection");
+        }
+    }
+
+    public static class MustInitForEncryptModeOrRejects extends MockCipherSpi {
+        @Override
+        protected void engineInit(int opmode, Key key, SecureRandom random)
+                throws InvalidKeyException {
+            if (opmode != Cipher.ENCRYPT_MODE) {
+                throw new InvalidKeyException("expected rejection");
+            }
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+                SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+            if (opmode != Cipher.ENCRYPT_MODE) {
+                throw new InvalidKeyException("expected rejection");
+            }
+        }
+
+        @Override
+        protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+                SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+            if (opmode != Cipher.ENCRYPT_MODE) {
+                throw new InvalidKeyException("expected rejection");
+            }
+        }
+    }
+
     public void checkKeyType(Key key) throws InvalidKeyException {
     }
 
diff --git a/luni/src/test/java/libcore/javax/crypto/MockKey.java b/luni/src/test/java/libcore/javax/crypto/MockKey.java
index 248e2de..1c758f3 100644
--- a/luni/src/test/java/libcore/javax/crypto/MockKey.java
+++ b/luni/src/test/java/libcore/javax/crypto/MockKey.java
@@ -25,7 +25,7 @@
 public class MockKey implements Key {
     @Override
     public String getAlgorithm() {
-        throw new UnsupportedOperationException("not implemented");
+        return "MOCK";
     }
 
     @Override
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParameterGeneratorTestDH.java b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParameterGeneratorTestDH.java
index e64fb9e..b3ff4ad7 100644
--- a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParameterGeneratorTestDH.java
+++ b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParameterGeneratorTestDH.java
@@ -15,7 +15,6 @@
  */
 package libcore.javax.crypto.spec;
 
-import dalvik.annotation.BrokenTest;
 import tests.security.AlgorithmParameterGeneratorTest;
 import tests.security.AlgorithmParameterKeyAgreementHelper;
 
@@ -26,9 +25,7 @@
         super("DH", new AlgorithmParameterKeyAgreementHelper("DH"));
     }
 
-    // Broken Test: Suffers from DH slowness, disabling for now
     public void testAlgorithmParameterGenerator() {
         super.testAlgorithmParameterGenerator();
     }
-
 }
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherPBETest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherPBETest.java
index f21374f..da070b6 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherPBETest.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherPBETest.java
@@ -15,8 +15,6 @@
  */
 package org.apache.harmony.crypto.tests.javax.crypto.func;
 
-import dalvik.annotation.AndroidOnly;
-
 import junit.framework.TestCase;
 
 public class CipherPBETest extends TestCase {
@@ -32,7 +30,6 @@
                 .getTotalFailuresNumber());
     }
 
-    @AndroidOnly("Not supported by RI (maybe with a different name)")
     public void test_PBEWithSHAand3KeyTripleDES() throws Exception {
         CipherPBEThread PBEWITHSHAAND3KEYTRIPLEDESCBC = new CipherPBEThread(
                 "PBEWITHSHAAND3-KEYTRIPLEDES-CBC", new int[] {112, 168},
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementFunctionalTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementFunctionalTest.java
index acb06ae..95f4191 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementFunctionalTest.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/KeyAgreementFunctionalTest.java
@@ -15,12 +15,9 @@
  */
 package org.apache.harmony.crypto.tests.javax.crypto.func;
 
-import dalvik.annotation.BrokenTest;
-
 import junit.framework.TestCase;
 
 public class KeyAgreementFunctionalTest extends TestCase {
-    @BrokenTest("Too slow - disabling for now")
     public void test_KeyAgreement() throws Exception {
         String[] algArray = {"DES", "DESede"};
 
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/interfaces/DHPublicKeyTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/interfaces/DHPublicKeyTest.java
index 471d670..bc7b338 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/interfaces/DHPublicKeyTest.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/interfaces/DHPublicKeyTest.java
@@ -22,8 +22,6 @@
 
 package org.apache.harmony.crypto.tests.javax.crypto.interfaces;
 
-import dalvik.annotation.BrokenTest;
-
 import junit.framework.TestCase;
 
 import java.math.BigInteger;
@@ -51,7 +49,6 @@
                 -6628103563352519193L);
     }
 
-    @BrokenTest("Too slow - disabling for now")
     public void test_getParams() throws Exception {
         KeyPairGenerator kg = KeyPairGenerator.getInstance("DH");
         kg.initialize(1024);
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
index 3625dee..1362fc6 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
@@ -17,7 +17,6 @@
 
 package org.apache.harmony.security.tests.java.security;
 
-import dalvik.annotation.AndroidOnly;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -259,8 +258,8 @@
     /**
      * java.security.Identity#removeCertificate(java.security.Certificate)
      */
-    @AndroidOnly("Spec says: Removing unknown certificates throw an exception. "
-            + "The RI ignores unknown certificates.")
+    // AndroidOnly("Spec says: Removing unknown certificates throw an exception. "
+    //        + "The RI ignores unknown certificates.")
     public void test_removeCertificateLjava_security_Certificate() throws Exception {
         IdentitySubclass sub = new IdentitySubclass("test",
                 new IdentityScopeSubclass());
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java
index aa0ec67..77588f6 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java
@@ -293,53 +293,8 @@
     }
 
     /**
-     * Two {@link SecureRandom} objects, created with
-     * {@link SecureRandom#getInstance(String)} and initialized before use
-     * with the same seed, should return the same results.<p>
-     *
-     * In the future, it may sense to disallow seeding {@code SecureRandom},
-     * as it tends to be error prone and open up security holes.
-     * See {@link SecureRandom} for more details about insecure seeding.
-     *
-     * Note that this only works with the Harmony "Crypto" provider.
-     */
-    public void testSameSeedGeneratesSameResults() throws Exception {
-        byte[] seed1 = { 'a', 'b', 'c' };
-        SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG", "Crypto");
-        sr1.setSeed(seed1);
-
-        byte[] seed2 = { 'a', 'b', 'c' };
-        SecureRandom sr2 = SecureRandom.getInstance("SHA1PRNG", "Crypto");
-        sr2.setSeed(seed2);
-
-        assertTrue(sr1.nextLong() == sr2.nextLong());
-    }
-
-    /**
-     * Assert that a {@link SecureRandom} object seeded from a constant
-     * seed always returns the same value, even across VM restarts.
-     *
-     * Future versions of Android may change the implementation of
-     * SHA1PRNG, so users of {@code SecureRandom} should not assume
-     * the same seed will always produce the same value.  This test
-     * is not a guarantee of future compatibility.
-     *
-     * In fact, this test only works with the Harmony "Crypto" provider.
-     */
-    public void testAlwaysSameValueWithSameSeed() throws Exception {
-        byte[] seed1 = { 'a', 'b', 'c' };
-        SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG", "Crypto");
-        sr1.setSeed(seed1);
-
-        // This long value has no special meaning and may change in the future.
-        assertEquals(6180693691264871500l, sr1.nextLong());
-    }
-
-    /**
      * Validate that calling {@link SecureRandom#setSeed} <b>after</b> generating
      * a random number compliments, but doesn't replace, the existing seed.
-     *
-     * Compare this test to {@link #testAlwaysSameValueWithSameSeed()}.
      */
     public void testSetSeedComplimentsAfterFirstRandomNumber() throws Exception {
         byte[] seed1 = { 'a', 'b', 'c' };
diff --git a/luni/src/test/java/tests/security/cert/X509CRLSelector2Test.java b/luni/src/test/java/tests/security/cert/X509CRLSelector2Test.java
index f2e814d..1e4dce9 100644
--- a/luni/src/test/java/tests/security/cert/X509CRLSelector2Test.java
+++ b/luni/src/test/java/tests/security/cert/X509CRLSelector2Test.java
@@ -1,7 +1,5 @@
 package tests.security.cert;
 
-import dalvik.annotation.AndroidOnly;
-
 import junit.framework.TestCase;
 
 import org.apache.harmony.security.asn1.ASN1Integer;
@@ -237,8 +235,6 @@
      * criteria, if specified minCRL value matches the selector, and if CRL with
      * inappropriate crlNumber value does not match the selector.
      */
-    @AndroidOnly("Uses specific class: " +
-            "org.apache.harmony.security.asn1.ASN1OctetString.")
     public void testSetMinCRLNumberLjava_math_BigInteger() {
         X509CRLSelector selector = new X509CRLSelector();
         BigInteger minCRL = new BigInteger("10000");
@@ -261,8 +257,6 @@
      * criteria, if specified maxCRL value matches the selector, and if CRL with
      * inappropriate crlNumber value does not match the selector.
      */
-    @AndroidOnly("Uses specific class: " +
-            "org.apache.harmony.security.asn1.ASN1OctetString.")
     public void testSetMaxCRLNumberLjava_math_BigInteger() {
         X509CRLSelector selector = new X509CRLSelector();
         BigInteger maxCRL = new BigInteger("10000");
@@ -459,9 +453,6 @@
      * crl which matche to the initial selector should match to the clone and
      * the change of clone should not cause the change of initial selector.
      */
-    @AndroidOnly("Uses specific classes: " +
-            "org.apache.harmony.security.asn1.ASN1OctetString, " +
-            "org.apache.harmony.security.asn1.ASN1Integer.")
     public void testClone() {
         X509CRLSelector selector = new X509CRLSelector();
         X500Principal iss1 = new X500Principal("O=First Org.");
diff --git a/luni/src/test/java/tests/security/cert/X509CRLTest.java b/luni/src/test/java/tests/security/cert/X509CRLTest.java
index c0163f3..746da9a 100644
--- a/luni/src/test/java/tests/security/cert/X509CRLTest.java
+++ b/luni/src/test/java/tests/security/cert/X509CRLTest.java
@@ -22,8 +22,6 @@
 
 package tests.security.cert;
 
-import dalvik.annotation.AndroidOnly;
-
 import junit.framework.Test;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
@@ -270,8 +268,8 @@
      * Check if the default implementation throws NullPointerException
      * on null input data.
      */
-    @AndroidOnly("Test filed on RI: getRevokedCertificate throws " +
-            "RuntimeException.")
+    // AndroidOnly("Test filed on RI: getRevokedCertificate throws " +
+    //        "RuntimeException.")
     public void testGetRevokedCertificate() {
         try {
             tbt_crl.getRevokedCertificate((X509Certificate) null);
diff --git a/luni/src/test/java/tests/security/interfaces/DSAPrivateKeyTest.java b/luni/src/test/java/tests/security/interfaces/DSAPrivateKeyTest.java
index 6cebda5..5f4abdd 100644
--- a/luni/src/test/java/tests/security/interfaces/DSAPrivateKeyTest.java
+++ b/luni/src/test/java/tests/security/interfaces/DSAPrivateKeyTest.java
@@ -32,9 +32,7 @@
      */
     public void test_getX() throws Exception {
         KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
-        keyGen.initialize(new DSAParameterSpec(Util.P, Util.Q, Util.G),
-                new SecureRandom(new MySecureRandomSpi(), null) {
-                });
+        keyGen.initialize(new DSAParameterSpec(Util.P, Util.Q, Util.G), new SecureRandom());
         KeyPair keyPair = keyGen.generateKeyPair();
         DSAPrivateKey key = (DSAPrivateKey) keyPair.getPrivate();
         assertNotNull("Invalid X value", key.getX());
diff --git a/luni/src/test/java/tests/security/interfaces/DSAPublicKeyTest.java b/luni/src/test/java/tests/security/interfaces/DSAPublicKeyTest.java
index 9fe4910..09e936d 100644
--- a/luni/src/test/java/tests/security/interfaces/DSAPublicKeyTest.java
+++ b/luni/src/test/java/tests/security/interfaces/DSAPublicKeyTest.java
@@ -42,9 +42,7 @@
 
         // Case 1: check with predefined p, q, g, x
         keyGen = KeyPairGenerator.getInstance("DSA");
-        keyGen.initialize(new DSAParameterSpec(Util.P, Util.Q, Util.G),
-                new SecureRandom(new MySecureRandomSpi(), null) {
-                });
+        keyGen.initialize(new DSAParameterSpec(Util.P, Util.Q, Util.G), new SecureRandom());
         keys = keyGen.generateKeyPair();
         priv = (DSAPrivateKey) keys.getPrivate();
         publ = (DSAPublicKey) keys.getPublic();
diff --git a/luni/src/test/java/tests/targets/security/MessageDigestTestMD2.java b/luni/src/test/java/tests/targets/security/MessageDigestTestMD2.java
index 6811bc0..4483da4 100644
--- a/luni/src/test/java/tests/targets/security/MessageDigestTestMD2.java
+++ b/luni/src/test/java/tests/targets/security/MessageDigestTestMD2.java
@@ -15,7 +15,6 @@
  */
 package tests.targets.security;
 
-import dalvik.annotation.AndroidOnly;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.Provider;
@@ -24,7 +23,6 @@
 
 public class MessageDigestTestMD2 extends TestCase {
 
-    @AndroidOnly("Android doesn't include MD2 message digest algorithm")
     public void testMessageDigest1() throws Exception{
         try {
             MessageDigest digest = MessageDigest.getInstance("MD2");
@@ -42,7 +40,6 @@
         }
     }
 
-    @AndroidOnly("Android allows usage of MD2 in third party providers")
     public void testMessageDigest2() throws Exception{
 
         Provider provider  = new MyProvider();
diff --git a/luni/src/test/java/tests/targets/security/SignatureTestMD2withRSA.java b/luni/src/test/java/tests/targets/security/SignatureTestMD2withRSA.java
index c9126ef..90ac2fa 100644
--- a/luni/src/test/java/tests/targets/security/SignatureTestMD2withRSA.java
+++ b/luni/src/test/java/tests/targets/security/SignatureTestMD2withRSA.java
@@ -15,7 +15,6 @@
  */
 package tests.targets.security;
 
-import dalvik.annotation.AndroidOnly;
 import java.security.InvalidKeyException;
 import java.security.InvalidParameterException;
 import java.security.NoSuchAlgorithmException;
@@ -29,7 +28,6 @@
 
 public class SignatureTestMD2withRSA extends TestCase {
 
-    @AndroidOnly("Android doesn't include MD2withRSA signature algorithm")
     public void testSignature() {
 
         // MD2 must not be part of android.
@@ -91,7 +89,6 @@
         }
     }
 
-    @AndroidOnly("Android allows usage of MD2withRSA in third party providers")
     public void testSignature2() throws Exception{
 
         Provider provider = new MyProvider();
diff --git a/luni/src/test/java/tests/targets/security/cert/CertificateTest.java b/luni/src/test/java/tests/targets/security/cert/CertificateTest.java
index dd06249..8044f4f 100644
--- a/luni/src/test/java/tests/targets/security/cert/CertificateTest.java
+++ b/luni/src/test/java/tests/targets/security/cert/CertificateTest.java
@@ -15,7 +15,6 @@
  */
 package tests.targets.security.cert;
 
-import dalvik.annotation.AndroidOnly;
 import java.io.ByteArrayInputStream;
 import java.security.KeyStore;
 import java.security.NoSuchAlgorithmException;
@@ -602,7 +601,6 @@
         }
     }
 
-    @AndroidOnly("MD2 is not supported by Android")
     public void testVerifyMD2() throws Exception {
         Provider[] providers = Security.getProviders("CertificateFactory.X509");
         for (Provider provider : providers) {
diff --git a/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java b/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java
index 6e2ff9d..b497c85 100644
--- a/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java
+++ b/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java
@@ -72,6 +72,8 @@
                 // Validate the entry name: make sure the unpacked file will exist beneath the
                 // targetDir.
                 String name = entry.getName();
+                // Note, we assume that nothing will quickly insert a symlink after createSubFile()
+                // that might invalidate the guarantees about name existing beneath targetDir.
                 File entryFile = FileUtils.createSubFile(targetDir, name);
 
                 if (entry.isDirectory()) {
diff --git a/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java b/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java
index 8b7da78..652b786 100644
--- a/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java
+++ b/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java
@@ -37,19 +37,18 @@
 
     /**
      * Creates a new {@link java.io.File} from the {@code parentDir} and {@code name}, but only if
-     * the
-     * resulting file would exist beneath {@code parentDir}. Useful if {@code name} could contain
-     * "/../" or symlinks. The returned object has an absolute path.
+     * the resulting file would exist beneath {@code parentDir}. Useful if {@code name} could
+     * contain "/../" or symlinks. The returned object has a canonicalized path.
      *
-     * @throws java.io.IOException
-     *         if the file would not exist beneath {@code parentDir}
+     * @throws java.io.IOException if the file would not exist beneath {@code parentDir}
      */
     public static File createSubFile(File parentDir, String name) throws IOException {
         // The subFile must exist beneath parentDir. If name contains "/../" this may not be the
         // case so we check.
-        File subFile = canonicalizeDirPath(new File(parentDir, name));
+        File subFile = new File(parentDir, name).getCanonicalFile();
         if (!subFile.getPath().startsWith(parentDir.getCanonicalPath())) {
-            throw new IOException(name + " must exist beneath " + parentDir);
+            throw new IOException(name + " must exist beneath " + parentDir +
+                    ". Canonicalized subpath: " + subFile);
         }
         return subFile;
     }
@@ -61,8 +60,8 @@
      * directories explicitly created will have their permissions set; existing directories are
      * untouched.
      *
-     * @throws IOException
-     *         if the directory or one of its parents did not already exist and could not be created
+     * @throws IOException if the directory or one of its parents did not already exist and could
+     *     not be created
      */
     public static void ensureDirectoriesExist(File dir, boolean makeWorldReadable)
             throws IOException {
@@ -87,14 +86,6 @@
         }
     }
 
-    /**
-     * Returns a file with all symlinks and relative paths such as "/../" resolved <em>except</em>
-     * for the base name (the last element of the path). Useful for detecting symlinks.
-     */
-    public static File canonicalizeDirPath(File file) throws IOException {
-        return new File(file.getParentFile().getCanonicalFile(), file.getName());
-    }
-
     public static void makeDirectoryWorldAccessible(File directory) throws IOException {
         if (!directory.isDirectory()) {
             throw new IOException(directory + " must be a directory");
@@ -150,7 +141,10 @@
     }
 
     public static boolean isSymlink(File file) throws IOException {
-        return !file.getCanonicalPath().equals(canonicalizeDirPath(file).getPath());
+        String baseName = file.getName();
+        String canonicalPathExceptBaseName =
+                new File(file.getParentFile().getCanonicalFile(), baseName).getPath();
+        return !file.getCanonicalPath().equals(canonicalPathExceptBaseName);
     }
 
     public static void deleteRecursive(File toDelete) throws IOException {
diff --git a/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java b/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java
index ce02bfe..d002820 100644
--- a/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java
+++ b/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java
@@ -113,21 +113,30 @@
     }
 
     public void testCreateSubFile() throws Exception {
-        File dir1 = createTempDir();
-        File subFile = FileUtils.createSubFile(dir1, "file");
-        assertFileCanonicalEquals(new File(dir1, "file"), subFile);
+        File dir1 = createTempDir().getCanonicalFile();
+
+        File actualSubFile = FileUtils.createSubFile(dir1, "file");
+        assertEquals(new File(dir1, "file"), actualSubFile);
+
+        File existingSubFile = createRegularFile(dir1, "file");
+        actualSubFile = FileUtils.createSubFile(dir1, "file");
+        assertEquals(existingSubFile, actualSubFile);
+
+        File existingSubDir = createDir(dir1, "subdir");
+        actualSubFile = FileUtils.createSubFile(dir1, "subdir");
+        assertEquals(existingSubDir, actualSubFile);
 
         assertCreateSubFileThrows(dir1, "../file");
         assertCreateSubFileThrows(dir1, "../../file");
         assertCreateSubFileThrows(dir1, "../otherdir/file");
 
-        File dir2 = createTempDir();
-        File dir2Subdir = createDir(dir2, "dir2Subdir");
-        File expectedSymlinkToDir2 = createSymlink(dir2Subdir, dir1, "symlinkToDir2");
+        File dir2 = createTempDir().getCanonicalFile();
+        createSymlink(dir2, dir1, "symlinkToDir2");
+        assertCreateSubFileThrows(dir1, "symlinkToDir2");
 
-        File actualSymlinkToDir2 = FileUtils.createSubFile(dir1, "symlinkToDir2");
-        assertEquals(expectedSymlinkToDir2, actualSymlinkToDir2);
+        assertCreateSubFileThrows(dir1, "symlinkToDir2/fileInSymlinkedDir");
 
+        createRegularFile(dir1, "symlinkToDir2/fileInSymlinkedDir");
         assertCreateSubFileThrows(dir1, "symlinkToDir2/fileInSymlinkedDir");
     }
 
@@ -295,10 +304,6 @@
                 (sb.st_mode & mask) == mask);
     }
 
-    private static void assertFileCanonicalEquals(File expected, File actual) throws IOException {
-        assertEquals(expected.getCanonicalFile(), actual.getCanonicalFile());
-    }
-
     private File createTempDir() {
         final String tempPrefix = getClass().getSimpleName();
         File tempDir = IoUtils.createTemporaryDirectory(tempPrefix);
diff --git a/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java b/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java
index 0958bbf..bb3d130 100644
--- a/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java
+++ b/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java
@@ -916,7 +916,7 @@
      * Get next parsing event - element content will be coalesced and only one
      * TEXT event must be returned for whole element content
      * (comments and processing instructions will be ignored and entity references
-     * must be expanded or exception mus be thrown if entity reference can not be expanded).
+     * must be expanded or exception must be thrown if entity reference can not be expanded).
      * If element content is empty (content is "") then no TEXT event will be reported.
      *
      * <p><b>NOTE:</b> empty element (such as &lt;tag/>) will be reported