am 8337fa4e: am c8596a95: am 157dae46: am 88051ed3: Merge "Add testInterfaceProperties() .  Move Ethernet verification out of testLoopback()." into kitkat-cts-dev automerge: 19679b0 automerge: 2cc1870

* commit '8337fa4e58ee38757a707d2d4829abe761f89a78':
  Add testInterfaceProperties() .  Move Ethernet verification out of testLoopback().
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 9f6d827..fb0b207 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -116,16 +116,6 @@
 LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
 include $(BUILD_JAVA_LIBRARY)
 
-# Path to the ICU4C data files in the Android device file system:
-icu4c_data := /system/usr/icu
-# TODO: It's quite hideous that this double-slash between icu4j and main is required.
-# It's because we provide a variable substition of the make-rule generated jar command
-# to substitute a processed ICUProperties.config file in place of the original.
-#
-# We can avoid this by filtering out ICUConfig.properties from our list of resources.
-icu4j_config_root := $(LOCAL_PATH)/../external/icu/icu4j//main/classes/core/src
-include external/icu/icu4j/adjust_icudt_path.mk
-
 ifeq ($(LIBCORE_SKIP_TESTS),)
 # Make the core-tests library.
 include $(CLEAR_VARS)
diff --git a/NativeCode.mk b/NativeCode.mk
index b21dd2d..379a1cb 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -117,6 +117,7 @@
 LOCAL_MODULE_TAGS := debug
 LOCAL_MODULE := libjavacore-unit-tests
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
+LOCAL_SHARED_LIBRARIES := libnativehelper
 LOCAL_CXX_STL := libc++
 include $(BUILD_NATIVE_TEST)
 
@@ -131,6 +132,7 @@
 LOCAL_MODULE_TAGS := debug
 LOCAL_MODULE := libjavacore-benchmarks
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
+LOCAL_SHARED_LIBRARIES := libnativehelper
 LOCAL_CXX_STL := libc++
 LOCAL_MULTILIB := both
 LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
@@ -175,6 +177,7 @@
     LOCAL_MODULE := libjavacoretests
     LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
     LOCAL_SHARED_LIBRARIES := libcrypto-host
+    LOCAL_MULTILIB := both
     LOCAL_CXX_STL := libc++
     include $(BUILD_HOST_SHARED_LIBRARY)
 endif # LIBCORE_SKIP_TESTS
diff --git a/benchmarks/src/benchmarks/ClassLoaderResourceBenchmark.java b/benchmarks/src/benchmarks/ClassLoaderResourceBenchmark.java
new file mode 100644
index 0000000..379eaec
--- /dev/null
+++ b/benchmarks/src/benchmarks/ClassLoaderResourceBenchmark.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+import com.google.caliper.SimpleBenchmark;
+
+import junit.framework.Assert;
+
+public class ClassLoaderResourceBenchmark extends SimpleBenchmark {
+
+  private static final String EXISTENT_RESOURCE = "java/util/logging/logging.properties";
+  private static final String MISSING_RESOURCE = "missing_entry";
+
+  public void timeGetBootResource_hit(int reps) {
+    ClassLoader currentClassLoader = getClass().getClassLoader();
+    Assert.assertNotNull(currentClassLoader.getResource(EXISTENT_RESOURCE));
+
+    for (int rep = 0; rep < reps; ++rep) {
+      currentClassLoader.getResource(EXISTENT_RESOURCE);
+    }
+  }
+
+  public void timeGetBootResource_miss(int reps) {
+    ClassLoader currentClassLoader = getClass().getClassLoader();
+    Assert.assertNull(currentClassLoader.getResource(MISSING_RESOURCE));
+
+    for (int rep = 0; rep < reps; ++rep) {
+      currentClassLoader.getResource(MISSING_RESOURCE);
+    }
+  }
+
+}
diff --git a/benchmarks/src/benchmarks/XmlSerializeBenchmark.java b/benchmarks/src/benchmarks/XmlSerializeBenchmark.java
new file mode 100644
index 0000000..7319490
--- /dev/null
+++ b/benchmarks/src/benchmarks/XmlSerializeBenchmark.java
@@ -0,0 +1,118 @@
+/*
+ * 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;
+
+import com.google.caliper.Param;
+import com.google.caliper.Runner;
+import com.google.caliper.SimpleBenchmark;
+
+import org.xmlpull.v1.*;
+
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Random;
+
+
+public class XmlSerializeBenchmark extends SimpleBenchmark {
+
+    @Param( {"0.99 0.7 0.7 0.7 0.7 0.7",
+            "0.999 0.3 0.3 0.95 0.9 0.9"})
+    String datasetAsString;
+
+    @Param( { "854328", "312547"} )
+    int seed;
+
+    double[] dataset;
+    private Constructor<? extends XmlSerializer> kxmlConstructor;
+    private Constructor<? extends XmlSerializer> fastConstructor;
+
+    private void serializeRandomXml(Constructor<? extends XmlSerializer> ctor, long seed)
+            throws Exception {
+        double contChance = dataset[0];
+        double levelUpChance = dataset[1];
+        double levelDownChance = dataset[2];
+        double attributeChance = dataset[3];
+        double writeChance1 = dataset[4];
+        double writeChance2 = dataset[5];
+
+        XmlSerializer serializer = (XmlSerializer) ctor.newInstance();
+
+        CharArrayWriter w = new CharArrayWriter();
+        serializer.setOutput(w);
+        int level = 0;
+        Random r = new Random(seed);
+        char[] toWrite = {'a','b','c','d','s','z'};
+        serializer.startDocument("UTF-8", true);
+        while(r.nextDouble() < contChance) {
+            while(level > 0 && r.nextDouble() < levelUpChance) {
+                serializer.endTag("aaaaaa", "bbbbbb");
+                level--;
+            }
+            while(r.nextDouble() < levelDownChance) {
+                serializer.startTag("aaaaaa", "bbbbbb");
+                level++;
+            }
+            serializer.startTag("aaaaaa", "bbbbbb");
+            level++;
+            while(r.nextDouble() < attributeChance) {
+                serializer.attribute("aaaaaa", "cccccc", "dddddd");
+            }
+            serializer.endTag("aaaaaa", "bbbbbb");
+            level--;
+            while(r.nextDouble() < writeChance1)
+                serializer.text(toWrite, 0, 5);
+            while(r.nextDouble() < writeChance2)
+                serializer.text("Textxtsxtxtxt ");
+        }
+        serializer.endDocument();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void setUp() throws Exception {
+        kxmlConstructor = (Constructor) Class.forName("org.kxml2.io.KXmlSerializer")
+                .getConstructor();
+        fastConstructor = (Constructor) Class.forName("com.android.internal.util.FastXmlSerializer")
+                .getConstructor();
+        String[] splitted = datasetAsString.split(" ");
+        dataset = new double[splitted.length];
+        for (int i = 0; i < splitted.length; i++) {
+            dataset[i] = Double.valueOf(splitted[i]);
+        }
+    }
+
+    private void internalTimeSerializer(Constructor<? extends XmlSerializer> ctor, int reps)
+            throws Exception {
+        for (int i = 0; i < reps; i++) {
+            serializeRandomXml(ctor, seed);
+        }
+    }
+
+    public void timeKxml(int reps) throws Exception {
+        internalTimeSerializer(kxmlConstructor, reps);
+    }
+
+    public void timeFast(int reps) throws Exception {
+        internalTimeSerializer(fastConstructor, reps);
+    }
+
+    public static void main(String[] args) {
+        Runner.main(XmlSerializeBenchmark.class, args);
+    }
+}
diff --git a/benchmarks/src/benchmarks/regression/StrictMathBenchmark.java b/benchmarks/src/benchmarks/regression/StrictMathBenchmark.java
index 44c030a..e844d93 100644
--- a/benchmarks/src/benchmarks/regression/StrictMathBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/StrictMathBenchmark.java
@@ -30,6 +30,36 @@
     private final int i = 1;
     private final long l = 1L;
 
+    /* Values for full line coverage of ceiling function */
+    private static final double[] CEIL_DOUBLES = new double[] {
+            3245817.2018463886,
+            1418139.083668501,
+            3.572936802189103E15,
+            -4.7828929737254625E249,
+            213596.58636369856,
+            6.891928421440976E-96,
+            -7.9318566885477E-36,
+            -1.9610339084804148E15,
+            -4.696725715628246E10,
+            3742491.296880909,
+            7.140274745333553E11
+    };
+
+    /* Values for full line coverage of floor function */
+    private static final double[] FLOOR_DOUBLES = new double[] {
+            7.140274745333553E11,
+            3742491.296880909,
+            -4.696725715628246E10,
+            -1.9610339084804148E15,
+            7.049948629370372E-56,
+            -7.702933170334643E-16,
+            -1.99657681810579,
+            -1.1659287182288336E236,
+            4.085518816513057E15,
+            -1500948.440658056,
+            -2.2316479921415575E7
+    };
+
     public void timeAbsD(int reps) {
         for (int rep = 0; rep < reps; ++rep) {
             StrictMath.abs(d);
@@ -84,9 +114,11 @@
         }
     }
 
-    public void timeCeil(int reps) {
+    public void timeCeilOverInterestingValues(int reps) {
         for (int rep = 0; rep < reps; ++rep) {
-            StrictMath.ceil(d);
+            for (int i = 0; i < CEIL_DOUBLES.length; ++i) {
+                StrictMath.ceil(CEIL_DOUBLES[i]);
+            }
         }
     }
 
@@ -126,9 +158,11 @@
         }
     }
 
-    public void timeFloor(int reps) {
+    public void timeFloorOverInterestingValues(int reps) {
         for (int rep = 0; rep < reps; ++rep) {
-            StrictMath.floor(d);
+            for (int i = 0; i < FLOOR_DOUBLES.length; ++i) {
+                StrictMath.floor(FLOOR_DOUBLES[i]);
+            }
         }
     }
 
diff --git a/benchmarks/src/benchmarks/regression/StringEqualsBenchmark.java b/benchmarks/src/benchmarks/regression/StringEqualsBenchmark.java
new file mode 100644
index 0000000..3ba2ac1
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/StringEqualsBenchmark.java
@@ -0,0 +1,268 @@
+/*
+ * 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.Param;
+import com.google.caliper.Runner;
+import com.google.caliper.SimpleBenchmark;
+import junit.framework.Assert;
+
+/**
+ * Benchmarks to measure the performance of String.equals for Strings of varying lengths.
+ * Each benchmarks makes 5 measurements, aiming at covering cases like strings of equal length
+ * that are not equal, identical strings with different references, strings with different endings,
+ * interned strings, and strings of different lengths.
+ */
+public class StringEqualsBenchmark extends SimpleBenchmark {
+    private final String long1 = "Ahead-of-time compilation is possible as the compiler may just"
+        + "convert an instruction thus: dex code: add-int v1000, v2000, v3000 C code: setIntRegter"
+        + "(1000, call_dex_add_int(getIntRegister(2000), getIntRegister(3000)) This means even lid"
+        + "instructions may have code generated, however, it is not expected that code generate in"
+        + "this way will perform well. The job of AOT verification is to tell the compiler that"
+        + "instructions are sound and provide tests to detect unsound sequences so slow path code"
+        + "may be generated. Other than for totally invalid code, the verification may fail at AOr"
+        + "run-time. At AOT time it can be because of incomplete information, at run-time it can e"
+        + "that code in a different apk that the application depends upon has changed. The Dalvik"
+        + "verifier would return a bool to state whether a Class were good or bad. In ART the fail"
+        + "case becomes either a soft or hard failure. Classes have new states to represent that a"
+        + "soft failure occurred at compile time and should be re-verified at run-time.";
+
+    private final String veryLong = "Garbage collection has two phases. The first distinguishes"
+        + "live objects from garbage objects.  The second is reclaiming the rage of garbage object"
+        + "In the mark-sweep algorithm used by Dalvik, the first phase is achievd by computing the"
+        + "closure of all reachable objects in a process known as tracing from theoots.  After the"
+        + "trace has completed, garbage objects are reclaimed.  Each of these operations can be"
+        + "parallelized and can be interleaved with the operation of the applicationTraditionally,"
+        + "the tracing phase dominates the time spent in garbage collection.  The greatreduction i"
+        + "pause time can be achieved by interleaving as much of this phase as possible with the"
+        + "application. If we simply ran the GC in a separate thread with no other changes, normal"
+        + "operation of an application would confound the trace.  Abstractly, the GC walks the h o"
+        + "all reachable objects.  When the application is paused, the object graph cannot change."
+        + "The GC can therefore walk this structure and assume that all reachable objects live."
+        + "When the application is running, this graph may be altered. New nodes may be addnd edge"
+        + "may be changed.  These changes may cause live objects to be hidden and falsely recla by"
+        + "the GC.  To avoid this problem a write barrier is used to intercept and record modifion"
+        + "to objects in a separate structure.  After performing its walk, the GC will revisit the"
+        + "updated objects and re-validate its assumptions.  Without a card table, the garbage"
+        + "collector would have to visit all objects reached during the trace looking for dirtied"
+        + "objects.  The cost of this operation would be proportional to the amount of live data."
+        + "With a card table, the cost of this operation is proportional to the amount of updateat"
+        + "The write barrier in Dalvik is a card marking write barrier.  Card marking is the proce"
+        + "of noting the location of object connectivity changes on a sub-page granularity.  A car"
+        + "is merely a colorful term for a contiguous extent of memory smaller than a page, common"
+        + "somewhere between 128- and 512-bytes.  Card marking is implemented by instrumenting all"
+        + "locations in the virtual machine which can assign a pointer to an object.  After themal"
+        + "pointer assignment has occurred, a byte is written to a byte-map spanning the heap whic"
+        + "corresponds to the location of the updated object.  This byte map is known as a card ta"
+        + "The garbage collector visits this card table and looks for written bytes to reckon the"
+        + "location of updated objects.  It then rescans all objects located on the dirty card,"
+        + "correcting liveness assumptions that were invalidated by the application.  While card"
+        + "marking imposes a small burden on the application outside of a garbage collection, the"
+        + "overhead of maintaining the card table is paid for by the reduced time spent inside"
+        + "garbage collection. With the concurrent garbage collection thread and a write barrier"
+        + "supported by the interpreter, JIT, and Runtime we modify garbage collection";
+
+    private final String[][] shortStrings = new String[][] {
+        // Equal, constant comparison
+        { "a", "a" },
+        // Different constants, first character different
+        { ":", " :"},
+        // Different constants, last character different, same length
+        { "ja M", "ja N"},
+        // Different constants, different lengths
+        {"$$$", "$$"},
+        // Force execution of code beyond reference equality check
+        {"hi", new String("hi")}
+    };
+
+    private final String[][] mediumStrings = new String[][] {
+        // Equal, constant comparison
+        { "Hello my name is ", "Hello my name is " },
+        // Different constants, different lengths
+        { "What's your name?", "Whats your name?" },
+        // Force execution of code beyond reference equality check
+        { "Android Runtime", new String("Android Runtime") },
+        // Different constants, last character different, same length
+        { "v3ry Cre@tiVe?****", "v3ry Cre@tiVe?***." },
+        // Different constants, first character different, same length
+        { "!@#$%^&*()_++*^$#@", "0@#$%^&*()_++*^$#@" }
+    };
+
+    private final String[][] longStrings = new String[][] {
+        // Force execution of code beyond reference equality check
+        { long1, new String(long1) },
+        // Different constants, last character different, same length
+        { long1 + "fun!", long1 + "----" },
+        // Equal, constant comparison
+        { long1 + long1, long1 + long1 },
+        // Different constants, different lengths
+        { long1 + "123456789", long1 + "12345678" },
+        // Different constants, first character different, same length
+        { "Android Runtime" + long1, "android Runtime" + long1 }
+    };
+
+    private final String[][] veryLongStrings = new String[][] {
+        // Force execution of code beyond reference equality check
+        { veryLong, new String(veryLong) },
+        // Different constants, different lengths
+        { veryLong + veryLong, veryLong + " " + veryLong },
+        // Equal, constant comparison
+        { veryLong + veryLong + veryLong, veryLong + veryLong + veryLong },
+        // Different constants, last character different, same length
+        { veryLong + "77777", veryLong + "99999" },
+        // Different constants, first character different
+        { "Android Runtime" + veryLong, "android Runtime" + veryLong }
+    };
+
+    private final String[][] endStrings = new String[][] {
+        // Different constants, medium but different lengths
+        { "Hello", "Hello " },
+        // Different constants, long but different lengths
+        { long1, long1 + "x"},
+        // Different constants, very long but different lengths
+        { veryLong, veryLong + "?"},
+        // Different constants, same medium lengths
+        { "How are you doing today?", "How are you doing today " },
+        // Different constants, short but different lengths
+        { "1", "1." }
+    };
+
+    private final String tmpStr1 = "012345678901234567890"
+        + "0123456789012345678901234567890123456789"
+        + "0123456789012345678901234567890123456789"
+        + "0123456789012345678901234567890123456789"
+        + "0123456789012345678901234567890123456789";
+
+    private final String tmpStr2 = "z012345678901234567890"
+        + "0123456789012345678901234567890123456789"
+        + "0123456789012345678901234567890123456789"
+        + "0123456789012345678901234567890123456789"
+        + "012345678901234567890123456789012345678x";
+
+    private final String[][] nonalignedStrings = new String[][] {
+        // Different non-word aligned medium length strings
+        { tmpStr1, tmpStr1.substring(1) },
+        // Different differently non-word aligned medium length strings
+        { tmpStr2, tmpStr2.substring(2) },
+        // Different non-word aligned long length strings
+        { long1, long1.substring(3) },
+        // Different non-word aligned very long length strings
+        { veryLong, veryLong.substring(1) },
+        // Equal non-word aligned constant strings
+        { "hello", "hello".substring(1) }
+    };
+
+    private final Object[] objects = new Object[] {
+        // Compare to Double object
+        new Double(1.5),
+        // Compare to Integer object
+        new Integer(9999999),
+        // Compare to String array
+        new String[] {"h", "i"},
+        // Compare to int array
+        new int[] {1, 2, 3},
+        // Compare to Character object
+        new Character('a')
+    };
+
+    // Check assumptions about how the compiler, new String(String), and String.intern() work.
+    // Any failures here would invalidate these benchmarks.
+    @Override protected void setUp() throws Exception {
+        // String constants are the same object
+        Assert.assertSame("abc", "abc");
+        // new String(String) makes a copy
+        Assert.assertNotSame("abc" , new String("abc"));
+        // Interned strings are treated like constants, so it is not necessary to
+        // separately benchmark interned strings.
+        Assert.assertSame("abc", "abc".intern());
+        Assert.assertSame("abc", new String("abc").intern());
+        // Compiler folds constant strings into new constants
+        Assert.assertSame(long1 + long1, long1 + long1);
+    }
+
+    // Benchmark cases of String.equals(null)
+    public void timeEqualsNull(int reps) {
+        for (int rep = 0; rep < reps; ++rep) {
+            for (int i = 0; i < mediumStrings.length; i++) {
+                mediumStrings[i][0].equals(null);
+            }
+        }
+    }
+
+    // Benchmark cases with very short (<5 character) Strings
+    public void timeEqualsShort(int reps) {
+        for (int rep = 0; rep < reps; ++rep) {
+            for (int i = 0; i < shortStrings.length; i++) {
+                shortStrings[i][0].equals(shortStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases with medium length (10-15 character) Strings
+    public void timeEqualsMedium(int reps) {
+        for (int rep = 0; rep < reps; ++rep) {
+            for (int i = 0; i < mediumStrings.length; i++) {
+                mediumStrings[i][0].equals(mediumStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases with long (>100 character) Strings
+    public void timeEqualsLong(int reps) {
+        for (int rep = 0; rep < reps; ++rep) {
+            for (int i = 0; i < longStrings.length; i++) {
+                longStrings[i][0].equals(longStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases with very long (>1000 character) Strings
+    public void timeEqualsVeryLong(int reps) {
+        for (int rep = 0; rep < reps; ++rep) {
+            for (int i = 0; i < veryLongStrings.length; i++) {
+                veryLongStrings[i][0].equals(veryLongStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases with non-word aligned Strings
+    public void timeEqualsNonWordAligned(int reps) {
+        for (int rep = 0; rep < reps; ++rep) {
+            for (int i = 0; i < nonalignedStrings.length; i++) {
+                nonalignedStrings[i][0].equals(nonalignedStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases with slight differences in the endings
+    public void timeEqualsEnd(int reps) {
+        for (int rep = 0; rep < reps; ++rep) {
+            for (int i = 0; i < endStrings.length; i++) {
+                endStrings[i][0].equals(endStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases of comparing a string to a non-string object
+    public void timeEqualsNonString(int reps) {
+        for (int rep = 0; rep < reps; ++rep) {
+            for (int i = 0; i < mediumStrings.length; i++) {
+                mediumStrings[i][0].equals(objects[i]);
+            }
+        }
+    }
+}
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java
index e25feb9..5552b1c 100644
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ b/dalvik/src/main/java/dalvik/system/DexPathList.java
@@ -27,11 +27,12 @@
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
-import java.util.zip.ZipFile;
 import java.util.zip.ZipEntry;
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
-import static android.system.OsConstants.*;
+import libcore.io.ClassPathURLStreamHandler;
+
+import static android.system.OsConstants.S_ISDIR;
 
 /**
  * A pair of lists of entries, associated with a {@code ClassLoader}.
@@ -117,8 +118,8 @@
 
         ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>();
         // save dexPath for BaseDexClassLoader
-        this.dexElements = makePathElements(splitDexPath(dexPath), optimizedDirectory,
-                                            suppressedExceptions);
+        this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,
+                                           suppressedExceptions);
 
         // Native libraries may exist in both the system and
         // application library paths, and we use this search order:
@@ -136,7 +137,7 @@
         List<File> allNativeLibraryDirectories = new ArrayList<>(nativeLibraryDirectories);
         allNativeLibraryDirectories.addAll(systemNativeLibraryDirectories);
 
-        this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, null,
+        this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories,
                                                           suppressedExceptions);
 
         if (suppressedExceptions.size() > 0) {
@@ -169,8 +170,7 @@
     /**
      * Splits the given dex path string into elements using the path
      * separator, pruning out any elements that do not refer to existing
-     * and readable files. (That is, directories are not included in the
-     * result.)
+     * and readable files.
      */
     private static List<File> splitDexPath(String path) {
         return splitPaths(path, false);
@@ -211,8 +211,31 @@
      * Makes an array of dex/resource path elements, one per element of
      * the given array.
      */
+    private static Element[] makeDexElements(List<File> files, File optimizedDirectory,
+                                             List<IOException> suppressedExceptions) {
+        return makeElements(files, optimizedDirectory, suppressedExceptions, false);
+    }
+
+    /**
+     * Makes an array of directory/zip path elements, one per element of the given array.
+     */
+    private static Element[] makePathElements(List<File> files,
+                                              List<IOException> suppressedExceptions) {
+        return makeElements(files, null, suppressedExceptions, true);
+    }
+
+    /*
+     * TODO (dimitry): Revert after GMS core stops relying on the existence of this
+     * method (see b/21957414 for details)
+     */
     private static Element[] makePathElements(List<File> files, File optimizedDirectory,
                                               List<IOException> suppressedExceptions) {
+        return makeElements(files, null, suppressedExceptions, true);
+    }
+
+    private static Element[] makeElements(List<File> files, File optimizedDirectory,
+                                          List<IOException> suppressedExceptions,
+                                          boolean ignoreDexFiles) {
         List<Element> elements = new ArrayList<>();
         /*
          * Open all files and load the (direct or contained) dex files
@@ -234,7 +257,7 @@
                 // Looking up resources in directories is useful for running libcore tests.
                 elements.add(new Element(file, true, null, null));
             } else if (file.isFile()) {
-                if (name.endsWith(DEX_SUFFIX)) {
+                if (!ignoreDexFiles && name.endsWith(DEX_SUFFIX)) {
                     // Raw dex file (not inside a zip/jar).
                     try {
                         dex = loadDexFile(file, optimizedDirectory);
@@ -244,17 +267,19 @@
                 } else {
                     zip = file;
 
-                    try {
-                        dex = loadDexFile(file, optimizedDirectory);
-                    } catch (IOException suppressed) {
-                        /*
-                         * IOException might get thrown "legitimately" by the DexFile constructor if
-                         * the zip file turns out to be resource-only (that is, no classes.dex file
-                         * in it).
-                         * Let dex == null and hang on to the exception to add to the tea-leaves for
-                         * when findClass returns null.
-                         */
-                        suppressedExceptions.add(suppressed);
+                    if (!ignoreDexFiles) {
+                        try {
+                            dex = loadDexFile(file, optimizedDirectory);
+                        } catch (IOException suppressed) {
+                            /*
+                             * IOException might get thrown "legitimately" by the DexFile constructor if
+                             * the zip file turns out to be resource-only (that is, no classes.dex file
+                             * in it).
+                             * Let dex == null and hang on to the exception to add to the tea-leaves for
+                             * when findClass returns null.
+                             */
+                            suppressedExceptions.add(suppressed);
+                        }
                     }
                 }
             } else {
@@ -408,7 +433,7 @@
     }
 
     /**
-     * Element of the dex/resource file path
+     * Element of the dex/resource/native library path
      */
     /*package*/ static class Element {
         private final File dir;
@@ -416,7 +441,7 @@
         private final File zip;
         private final DexFile dexFile;
 
-        private ZipFile zipFile;
+        private ClassPathURLStreamHandler urlHandler;
         private boolean initialized;
 
         public Element(File dir, boolean isDirectory, File zip, DexFile dexFile) {
@@ -449,7 +474,7 @@
             }
 
             try {
-                zipFile = new ZipFile(zip);
+                urlHandler = new ClassPathURLStreamHandler(zip.getPath());
             } catch (IOException ioe) {
                 /*
                  * Note: ZipException (a subclass of IOException)
@@ -458,25 +483,10 @@
                  * file).
                  */
                 System.logE("Unable to open zip file: " + zip, ioe);
-                zipFile = null;
+                urlHandler = null;
             }
         }
 
-        /**
-         * Returns true if entry with specified path exists and not compressed.
-         *
-         * Note that ZipEntry does not provide information about offset so we
-         * cannot reliably check if entry is page-aligned. For now we are going
-         * take optimistic approach and rely on (1) if library was extracted
-         * it would have been found by the previous step (2) if library was not extracted
-         * but STORED and not page-aligned the installation of the app would have failed
-         * because of checks in PackageManagerService.
-         */
-        private boolean isZipEntryExistsAndStored(ZipFile zipFile, String path) {
-            ZipEntry entry = zipFile.getEntry(path);
-            return entry != null && entry.getMethod() == ZipEntry.STORED;
-        }
-
         public String findNativeLibrary(String name) {
             maybeInit();
 
@@ -485,9 +495,13 @@
                 if (IoUtils.canOpenReadOnly(path)) {
                     return path;
                 }
-            } else if (zipFile != null) {
+            } else if (urlHandler != null) {
+                // Having a urlHandler means the element has a zip file.
+                // In this case Android supports loading the library iff
+                // it is stored in the zip uncompressed.
+
                 String entryName = new File(dir, name).getPath();
-                if (isZipEntryExistsAndStored(zipFile, entryName)) {
+                if (urlHandler.isEntryStored(entryName)) {
                   return zip.getPath() + zipSeparator + entryName;
                 }
             }
@@ -511,27 +525,12 @@
                 }
             }
 
-            if (zipFile == null || zipFile.getEntry(name) == null) {
-                /*
-                 * Either this element has no zip/jar file (first
-                 * clause), or the zip/jar file doesn't have an entry
-                 * for the given name (second clause).
+            if (urlHandler == null) {
+                /* This element has no zip/jar file.
                  */
                 return null;
             }
-
-            try {
-                /*
-                 * File.toURL() is compliant with RFC 1738 in
-                 * always creating absolute path names. If we
-                 * construct the URL by concatenating strings, we
-                 * might end up with illegal URLs for relative
-                 * names.
-                 */
-                return new URL("jar:" + zip.toURL() + "!/" + name);
-            } catch (MalformedURLException ex) {
-                throw new RuntimeException(ex);
-            }
+            return urlHandler.getEntryUrlOrNull(name);
         }
     }
 }
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/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java
index d9f3d91..e8f8e29 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java
@@ -819,7 +819,7 @@
     }
 
     public void test_getReuseAddress() throws Exception {
-        DatagramSocket theSocket = new DatagramSocket();
+        DatagramSocket theSocket = new DatagramSocket(null);
         theSocket.setReuseAddress(true);
         assertTrue("getReuseAddress false when it should be true", theSocket.getReuseAddress());
         theSocket.setReuseAddress(false);
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/ArraysTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ArraysTest.java
index 277abce..8b4844c 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ArraysTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ArraysTest.java
@@ -2217,7 +2217,7 @@
                 long[] b = new long[a.length];
 
                 for (int i = 0; i < a.length; i++) {
-                    b[i] = (int) a[i];
+                    b[i] = (long) a[i];
                 }
                 return b;
             }
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/javax/security/auth/x500/X500PrincipalTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/x500/X500PrincipalTest.java
index 34011c7..34978bc 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/x500/X500PrincipalTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/security/auth/x500/X500PrincipalTest.java
@@ -1679,12 +1679,10 @@
      * compares with expected value of name - "\nB"
      */
     public void testNameSpecialChars_RFC1779_01() throws Exception {
-        //FIXME see testNameSpecialChars_RFC2253_01
-        //        String dn = "CN=\\\nB";
-        //        X500Principal principal = new X500Principal(dn);
-        //        String s = principal.getName(X500Principal.RFC1779);
-        //        assertEquals("CN=\"\nB\"", s);
-
+        String dn = "CN=\\\nB";
+        X500Principal principal = new X500Principal(dn);
+        String s = principal.getName(X500Principal.RFC1779);
+        assertEquals("CN=\"\nB\"", s);
     }
 
     /**
@@ -1693,14 +1691,8 @@
      * compares with expected value of name - \\nB
      */
     public void testNameSpecialChars_RFC2253_01() throws Exception {
-
-        try {
-            // compatibility issue:
-            // don't accept escaped \n because it is not a special char
-            new X500Principal("CN=\\\nB");
-            fail("No expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-        }
+        X500Principal p = new X500Principal("CN=\\\nB");
+        assertEquals("CN=\nB", p.getName(X500Principal.RFC2253));
     }
 
     /**
@@ -2208,7 +2200,15 @@
         String dn = "CN=A\nB";
         X500Principal principal = new X500Principal(dn);
         String s = principal.getName(X500Principal.RFC1779);
-        assertEquals("CN=A\nB", s);
+        assertEquals("CN=\"A\nB\"", s);
+    }
+
+
+    public void testNamePlus_RFC1779() throws Exception {
+        String dn = "CN=A\\+B";
+        X500Principal principal = new X500Principal(dn);
+        String s = principal.getName(X500Principal.RFC1779);
+        assertEquals("CN=\"A+B\"", s);
     }
 
     /**
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
index 388f34c..bc54f89 100644
--- a/libart/src/main/java/java/lang/Class.java
+++ b/libart/src/main/java/java/lang/Class.java
@@ -159,7 +159,14 @@
     /** Lazily computed name of this class; always prefer calling getName(). */
     private transient String name;
 
-    /** The superclass, or null if this is java.lang.Object, an interface or primitive type. */
+    /**
+     * The superclass, or null if this is java.lang.Object or a primitive type.
+     *
+     * Note that interfaces have java.lang.Object as their
+     * superclass. This doesn't match the expectations of
+     * getSuperClass() which needs to check for interfaces and return
+     * null.
+     */
     private transient Class<? super T> superClass;
 
     /** If class verify fails, we must return same error on subsequent tries. */
diff --git a/libart/src/main/java/java/lang/VMClassLoader.java b/libart/src/main/java/java/lang/VMClassLoader.java
index d180a4d..a9d6253 100644
--- a/libart/src/main/java/java/lang/VMClassLoader.java
+++ b/libart/src/main/java/java/lang/VMClassLoader.java
@@ -16,33 +16,58 @@
 
 package java.lang;
 
-import java.net.MalformedURLException;
+import java.io.File;
+import java.io.IOException;
 import java.net.URL;
+import java.net.URLStreamHandler;
 import java.util.ArrayList;
 import java.util.List;
+import libcore.io.ClassPathURLStreamHandler;
 
 class VMClassLoader {
 
+    private static final ClassPathURLStreamHandler[] bootClassPathUrlHandlers;
+    static {
+        bootClassPathUrlHandlers = createBootClassPathUrlHandlers();
+    }
+
+    /**
+     * Creates an array of ClassPathURLStreamHandler objects for handling resource loading from
+     * the boot classpath.
+     */
+    private static ClassPathURLStreamHandler[] createBootClassPathUrlHandlers() {
+        String[] bootClassPathEntries = getBootClassPathEntries();
+        ArrayList<String> zipFileUris = new ArrayList<String>(bootClassPathEntries.length);
+        ArrayList<URLStreamHandler> urlStreamHandlers =
+                new ArrayList<URLStreamHandler>(bootClassPathEntries.length);
+        for (String bootClassPathEntry : bootClassPathEntries) {
+            try {
+                String entryUri = new File(bootClassPathEntry).toURI().toString();
+
+                // We assume all entries are zip or jar files.
+                URLStreamHandler urlStreamHandler =
+                        new ClassPathURLStreamHandler(bootClassPathEntry);
+                zipFileUris.add(entryUri);
+                urlStreamHandlers.add(urlStreamHandler);
+            } catch (IOException e) {
+                // Skip it
+                System.logE("Unable to open boot classpath entry: " + bootClassPathEntry, e);
+            }
+        }
+        return urlStreamHandlers.toArray(new ClassPathURLStreamHandler[urlStreamHandlers.size()]);
+    }
+
     /**
      * Get a resource from a file in the bootstrap class path.
      *
-     * It would be simpler to just walk through the class path elements
-     * ourselves, but that would require reopening Jar files.
-     *
-     * We assume that the bootclasspath can't change once the VM has
-     * started.  This assumption seems to be supported by the spec.
+     * We assume that the bootclasspath can't change once the VM has started.
+     * This assumption seems to be supported by the spec.
      */
     static URL getResource(String name) {
-        int numEntries = getBootClassPathSize();
-        for (int i = 0; i < numEntries; i++) {
-            String urlStr = getBootClassPathResource(name, i);
-            if (urlStr != null) {
-                try {
-                    return new URL(urlStr);
-                } catch (MalformedURLException mue) {
-                    mue.printStackTrace();
-                    // unexpected; keep going
-                }
+        for (ClassPathURLStreamHandler urlHandler : bootClassPathUrlHandlers) {
+            URL url = urlHandler.getEntryUrlOrNull(name);
+            if (url != null) {
+                return url;
             }
         }
         return null;
@@ -53,16 +78,10 @@
      */
     static List<URL> getResources(String name) {
         ArrayList<URL> list = new ArrayList<URL>();
-        int numEntries = getBootClassPathSize();
-        for (int i = 0; i < numEntries; i++) {
-            String urlStr = getBootClassPathResource(name, i);
-            if (urlStr != null) {
-                try {
-                    list.add(new URL(urlStr));
-                } catch (MalformedURLException mue) {
-                    mue.printStackTrace();
-                    // unexpected; keep going
-                }
+        for (ClassPathURLStreamHandler urlHandler : bootClassPathUrlHandlers) {
+            URL url = urlHandler.getEntryUrlOrNull(name);
+            if (url != null) {
+                list.add(url);
             }
         }
         return list;
@@ -73,6 +92,6 @@
     /**
      * Boot class path manipulation, for getResources().
      */
-    native private static int getBootClassPathSize();
-    native private static String getBootClassPathResource(String name, int index);
+    native private static String[] getBootClassPathEntries();
+
 }
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java
index a1e87c8..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); }
@@ -540,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 8832f3d..0908b88 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();
@@ -489,6 +490,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();
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/lang/StrictMath.java b/luni/src/main/java/java/lang/StrictMath.java
index 2e848f2..5c9638b 100644
--- a/luni/src/main/java/java/lang/StrictMath.java
+++ b/luni/src/main/java/java/lang/StrictMath.java
@@ -300,7 +300,7 @@
         int ix, hx, id;
 
         final long bits = Double.doubleToRawLongBits(x);
-        hx = (int) (bits >>> 32);
+        hx = highBits(bits);
         ix = hx & 0x7fffffff;
         if (ix >= 0x44100000) { /* if |x| >= 2^66 */
             if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (((int) bits) != 0))) {
@@ -404,12 +404,12 @@
         final long yBits = Double.doubleToRawLongBits(y);
         final long xBits = Double.doubleToRawLongBits(x);
 
-        hx = (int) (xBits >>> 32); // __HI(x);
+        hx = highBits(xBits); // __HI(x);
         ix = hx & 0x7fffffff;
-        lx = (int) xBits; // __LO(x);
-        hy = (int) (yBits >>> 32); // __HI(y);
+        lx = lowBits(xBits); // __LO(x);
+        hy = highBits(yBits); // __HI(y);
         iy = hy & 0x7fffffff;
-        ly = (int) yBits; // __LO(y);
+        ly = lowBits(yBits); // __LO(y);
         if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000)
                 || ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) { /* x or y is NaN */
             return x + y;
@@ -525,14 +525,14 @@
         int sign; // caution: should be unsigned
         long bits = Double.doubleToRawLongBits(x);
 
-        hx = (int) (bits >>> 32);
+        hx = highBits(bits);
         sign = hx & 0x80000000; /* sign= sign(x) */
         hx ^= sign;
         if (hx >= 0x7ff00000) {
             return (x + x); /* ieee_cbrt(NaN,INF) is itself */
         }
 
-        if ((hx | ((int) bits)) == 0) {
+        if ((hx | lowBits(bits)) == 0) {
             return x; /* ieee_cbrt(0) is itself */
         }
 
@@ -599,8 +599,79 @@
      * <li>{@code ceil(-infinity) = -infinity}</li>
      * <li>{@code ceil(NaN) = NaN}</li>
      * </ul>
+     *
+     * @param d
+     *          the double value whose ceiling will be computed.
+     * @return the ceiling of the argument.
      */
-    public static native double ceil(double d);
+    public static double ceil(double d) {
+        final long bits = Double.doubleToRawLongBits(d);
+        int highBits = highBits(bits); // high word of d
+        int lowBits = lowBits(bits); // low word of d
+        int exp = ((highBits >> 20) & 0x7ff) - 0x3ff; // value of exponent
+
+        /* negative exponent */
+        if (exp < 0) {
+            if (HUGE + d > 0.0) {
+                if (highBits < 0) { // if |d| < 1 return -0
+                    highBits = 0x80000000;
+                } else if ((highBits | lowBits) != 0) {
+                    // raise inexact if d != 0, this is ignored by Java
+                    highBits = 0x3ff00000; // return 1
+                }
+                lowBits = 0;
+            }
+        }
+        /* exponent in range [0, 20) */
+        else if (exp < 20) {
+            int i = (0x000fffff) >> exp; // careful, should be unsigned
+            /* d is integral */
+            if (((highBits & i) | lowBits) == 0) {
+                return d;
+            }
+            if (HUGE + d > 0.0) { // raise inexact flag: this is ignored by Java
+                if (highBits > 0) {
+                    highBits += (0x00100000) >> exp;
+                }
+                highBits &= (~i);
+                lowBits = 0;
+            }
+        }
+        /* exponent in range (51, inf) */
+        else if (exp > 51) {
+            /* inf or NaN */
+            if (exp == 0x400) {
+                return d + d;
+            }
+            return d; // d is integral
+        }
+        /* exponent in range [21,51] */
+        else {
+            int i = (0xffffffff) >>> (exp - 20); // careful, should be unsigned
+            /* d is integral */
+            if ((lowBits & i) == 0) {
+                return d;
+            }
+            /* raise inexact flag: this is ignored by Java */
+            if (HUGE + d > 0.0) {
+                if (highBits > 0) {
+                    if (exp == 20) {
+                        highBits += 1;
+                    } else {
+                        // careful, j should be unsigned
+                        int j = (int)(lowBits + (1 << (52 - exp)));
+                        if ((lowBits < 0) && (j >= 0)) {
+                             highBits += 1; // carry occurred
+                        }
+                        lowBits = j;
+                    }
+                }
+                lowBits &= (~i);
+            }
+        }
+        /* combine highBits and unsigned lowBits for final result */
+        return Double.longBitsToDouble(((long)highBits << 32) + (lowBits & 0xFFFFFFFFL));
+    }
 
     private static final long ONEBITS = Double.doubleToRawLongBits(1.00000000000000000000e+00)
             & 0x00000000ffffffffL;
@@ -624,7 +695,7 @@
         double t, w;
         int ix;
         final long bits = Double.doubleToRawLongBits(x);
-        ix = (int) (bits >>> 32) & 0x7fffffff;
+        ix = highBits(bits) & 0x7fffffff;
 
         /* x is INF or NaN */
         if (ix >= 0x7ff00000) {
@@ -715,8 +786,8 @@
         int k = 0, xsb;
         int hx; // should be unsigned, be careful!
         final long bits = Double.doubleToRawLongBits(x);
-        int lowBits = (int) bits;
-        int highBits = (int) (bits >>> 32);
+        int lowBits = lowBits(bits);
+        int highBits = highBits(bits);
         hx = highBits & 0x7fffffff;
         xsb = (highBits >>> 31) & 1;
 
@@ -814,8 +885,8 @@
         int k, xsb;
         long yBits = 0;
         final long bits = Double.doubleToRawLongBits(x);
-        int highBits = (int) (bits >>> 32);
-        int lowBits = (int) (bits);
+        int highBits = highBits(bits);
+        int lowBits = lowBits(bits);
         int hx = highBits & 0x7fffffff; // caution: should be unsigned!
         xsb = highBits & 0x80000000; /* sign bit of x */
         y = xsb == 0 ? x : -x; /* y = |x| */
@@ -930,8 +1001,79 @@
      * <li>{@code floor(-infinity) = -infinity}</li>
      * <li>{@code floor(NaN) = NaN}</li>
      * </ul>
+     *
+     * @param d
+     *          the double value whose floor will be computed.
+     * @return the floor of the argument.
      */
-    public static native double floor(double d);
+    public static double floor(double d) {
+        final long bits = Double.doubleToRawLongBits(d);
+        int highBits = highBits(bits); // high word of d
+        int lowBits = lowBits(bits); // low word of d
+        int exp = ((highBits >> 20) & 0x7ff) - 0x3ff; // value of exponent
+
+        /* negative exponent */
+        if (exp < 0) {
+            if (HUGE + d > 0.0) {
+                if (highBits >= 0) { // if |d| < 1
+                    highBits = 0;
+                } else if (((highBits & 0x7fffffff) | lowBits) != 0) {
+                    // raise inexact if d != 0, this is ignored by Java
+                    highBits = 0xbff00000;
+                }
+                lowBits = 0;
+            }
+        }
+        /* exponent in range [0, 20) */
+        else if (exp < 20) {
+            int i = (0x000fffff) >> exp; // careful, should be unsigned
+            /* d is integral */
+            if (((highBits & i) | lowBits) == 0) {
+                return d;
+            }
+            if (HUGE + d > 0.0) { // raise inexact flag: this is ignored by Java
+                if (highBits < 0) {
+                    highBits += (0x00100000) >> exp;
+                }
+                highBits &= (~i);
+                lowBits = 0;
+            }
+        }
+        /* exponent in range (51, inf) */
+        else if (exp > 51) {
+            /* inf or NaN */
+            if (exp == 0x400) {
+                return d + d;
+            }
+            return d; // d is integral
+        }
+        /* exponent in range [21,51] */
+        else {
+            int i = (0xffffffff) >>> (exp - 20); // careful, should be unsigned
+            /* d is integral */
+            if ((lowBits & i) == 0) {
+                return d;
+            }
+            /* raise inexact flag: this is ignored by java */
+            if (HUGE + d > 0.0) {
+                if (highBits < 0) {
+                    if (exp == 20) {
+                        highBits += 1;
+                    } else {
+                        // careful, j should be unsigned
+                        int j = (int)(lowBits + (1 << (52 - exp)));
+                        if ((lowBits < 0) && (j >= 0)) {
+                             highBits += 1; // carry occurred
+                        }
+                        lowBits = j;
+                    }
+                }
+                lowBits &= (~i);
+            }
+        }
+        /* combine highBits and unsigned lowBits for final result */
+        return Double.longBitsToDouble(((long)highBits << 32) + (lowBits & 0xFFFFFFFFL));
+    }
 
     /**
      * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i>
@@ -1016,8 +1158,8 @@
         int lx; // watch out, should be unsigned
 
         long bits = Double.doubleToRawLongBits(x);
-        hx = (int) (bits >>> 32); /* high word of x */
-        lx = (int) bits; /* low word of x */
+        hx = highBits(bits); /* high word of x */
+        lx = lowBits(bits); /* low word of x */
 
         if (hx < 0x00100000) { /* x < 2**-1022 */
             if (((hx & 0x7fffffff) | lx) == 0) {
@@ -1031,7 +1173,7 @@
             k -= 54;
             x *= TWO54; /* subnormal number, scale up x */
             bits = Double.doubleToRawLongBits(x);
-            hx = (int) (bits >>> 32); /* high word of x */
+            hx = highBits(bits); /* high word of x */
         }
 
         if (hx >= 0x7ff00000) {
@@ -1119,8 +1261,8 @@
         int i, k = 0, hx;
         int lx; // careful: lx should be unsigned!
         long bits = Double.doubleToRawLongBits(x);
-        hx = (int) (bits >> 32); /* high word of x */
-        lx = (int) bits; /* low word of x */
+        hx = highBits(bits); /* high word of x */
+        lx = lowBits(bits); /* low word of x */
         if (hx < 0x00100000) { /* x < 2**-1022 */
             if (((hx & 0x7fffffff) | lx) == 0) {
                 return -TWO54 / 0.0; /* ieee_log(+-0)=-inf */
@@ -1133,7 +1275,7 @@
             k -= 54;
             x *= TWO54; /* subnormal number, scale up x */
             bits = Double.doubleToRawLongBits(x);
-            hx = (int) (bits >> 32); /* high word of x */
+            hx = highBits(bits); /* high word of x */
         }
 
         if (hx >= 0x7ff00000) {
@@ -1186,7 +1328,7 @@
         int k, hx, hu = 0, ax;
 
         final long bits = Double.doubleToRawLongBits(x);
-        hx = (int) (bits >>> 32); /* high word of x */
+        hx = highBits(bits); /* high word of x */
         ax = hx & 0x7fffffff;
 
         k = 1;
@@ -1221,13 +1363,13 @@
             if (hx < 0x43400000) {
                 u = 1.0 + x;
                 uBits = Double.doubleToRawLongBits(u);
-                hu = (int) (uBits >>> 32);
+                hu = highBits(uBits);
                 k = (hu >> 20) - 1023;
                 c = (k > 0) ? 1.0 - (u - x) : x - (u - 1.0);/* correction term */
                 c /= u;
             } else {
                 uBits = Double.doubleToRawLongBits(x);
-                hu = (int) (uBits >>> 32);
+                hu = highBits(uBits);
                 k = (hu >> 20) - 1023;
                 c = 0;
             }
@@ -1603,7 +1745,7 @@
         int ix, jx;
         final long bits = Double.doubleToRawLongBits(x);
 
-        jx = (int) (bits >>> 32);
+        jx = highBits(bits);
         ix = jx & 0x7fffffff;
 
         /* x is INF or NaN */
@@ -1720,7 +1862,7 @@
 
         final long bits = Double.doubleToRawLongBits(x);
         /* High word of |x|. */
-        jx = (int) (bits >>> 32);
+        jx = highBits(bits);
         ix = jx & 0x7fffffff;
 
         /* x is INF or NaN */
@@ -2091,4 +2233,14 @@
         }
         return 0;
     }
+
+    // Returns the high word of the argument as an int.
+    private static int highBits(long bits) {
+        return (int) (bits >>> 32);
+    }
+
+    // Returns the low word of the argument as an int.
+    private static int lowBits(long bits) {
+        return (int) bits;
+    }
 }
diff --git a/luni/src/main/java/java/lang/System.java b/luni/src/main/java/java/lang/System.java
index c5d9a89..81da814 100644
--- a/luni/src/main/java/java/lang/System.java
+++ b/luni/src/main/java/java/lang/System.java
@@ -845,14 +845,22 @@
         // On Android, each app gets its own temporary directory.
         // (See android.app.ActivityThread.) This is just a fallback default,
         // useful only on the host.
-        p.put("java.io.tmpdir", "/tmp");
+        // We check first if the property has not been set already: note that it
+        // can only be set from the command line through the '-Djava.io.tmpdir=' option.
+        if (!unchangeableSystemProperties.containsKey("java.io.tmpdir")) {
+           p.put("java.io.tmpdir", "/tmp");
+        }
 
         // Android has always had an empty "user.home" (see docs for getProperty).
         // This is not useful for normal android apps which need to use android specific
         // APIs such as {@code Context.getFilesDir} and {@code Context.getCacheDir} but
         // we make it changeable for backward compatibility, so that they can change it
         // to a writeable location if required.
-        p.put("user.home", "");
+        // We check first if the property has not been set already: note that it
+        // can only be set from the command line through the '-Duser.home=' option.
+        if (!unchangeableSystemProperties.containsKey("user.home")) {
+            p.put("user.home", "");
+        }
     }
 
     private static Properties createSystemProperties() {
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/net/MulticastSocket.java b/luni/src/main/java/java/net/MulticastSocket.java
index 24e66c5..2d8fdd6 100644
--- a/luni/src/main/java/java/net/MulticastSocket.java
+++ b/luni/src/main/java/java/net/MulticastSocket.java
@@ -41,7 +41,9 @@
      * @throws IOException if an error occurs.
      */
     public MulticastSocket() throws IOException {
+        super((SocketAddress) null);
         setReuseAddress(true);
+        bind(null);
     }
 
     /**
@@ -51,8 +53,7 @@
      * @throws IOException if an error occurs.
      */
     public MulticastSocket(int port) throws IOException {
-        super(port);
-        setReuseAddress(true);
+        this(new InetSocketAddress(Inet6Address.ANY, port));
     }
 
     /**
@@ -64,8 +65,11 @@
      * @throws IOException if an error occurs.
      */
     public MulticastSocket(SocketAddress localAddress) throws IOException {
-        super(localAddress);
+        super((SocketAddress) null);
         setReuseAddress(true);
+        if (localAddress != null) {
+            bind(localAddress);
+        }
     }
 
     /**
diff --git a/luni/src/main/java/java/nio/ByteOrder.java b/luni/src/main/java/java/nio/ByteOrder.java
index 286c970..508c8ef 100644
--- a/luni/src/main/java/java/nio/ByteOrder.java
+++ b/luni/src/main/java/java/nio/ByteOrder.java
@@ -32,13 +32,10 @@
      */
     public static final ByteOrder LITTLE_ENDIAN;
 
-    private static native boolean isLittleEndian();
-
     static {
-        boolean isLittleEndian = isLittleEndian();
-        BIG_ENDIAN = new ByteOrder("BIG_ENDIAN", isLittleEndian);
-        LITTLE_ENDIAN = new ByteOrder("LITTLE_ENDIAN", !isLittleEndian);
-        NATIVE_ORDER = isLittleEndian ? LITTLE_ENDIAN : BIG_ENDIAN;
+        BIG_ENDIAN = new ByteOrder("BIG_ENDIAN", true /* needs swap */);
+        LITTLE_ENDIAN = new ByteOrder("LITTLE_ENDIAN", false /* needs swap */);
+        NATIVE_ORDER = LITTLE_ENDIAN;
     }
 
     private final String name;
diff --git a/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java b/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
index 5dfdd9f..38be0c2 100644
--- a/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
+++ b/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
@@ -202,7 +202,7 @@
 
     private void setPosition(CharBuffer out) {
         if (out.hasArray()) {
-            out.position(out.position() + data[OUTPUT_OFFSET] - out.arrayOffset());
+            out.position(out.position() + data[OUTPUT_OFFSET]);
         } else {
             out.put(output, 0, data[OUTPUT_OFFSET]);
         }
diff --git a/luni/src/main/java/java/util/Locale.java b/luni/src/main/java/java/util/Locale.java
index 875955d..a9f6333 100644
--- a/luni/src/main/java/java/util/Locale.java
+++ b/luni/src/main/java/java/util/Locale.java
@@ -2226,7 +2226,13 @@
             }
         }
 
-        final String languageCode = Builder.normalizeAndValidateLanguage(subtags[0], strict);
+        // The BCP-47 language tag "und" is mapped to the Locale languageCode "" here in
+        // forLanguageTag() for compatibility with JDK behaviour.
+        String languageCode = Builder.normalizeAndValidateLanguage(subtags[0], strict);
+        if (UNDETERMINED_LANGUAGE.equals(languageCode)) {
+          languageCode = "";
+        }
+
         String scriptCode = "";
         int nextSubtag = 1;
         if (lastSubtag > nextSubtag) {
diff --git a/luni/src/main/java/java/util/jar/StrictJarFile.java b/luni/src/main/java/java/util/jar/StrictJarFile.java
index a73ca2a..e4cda0e 100644
--- a/luni/src/main/java/java/util/jar/StrictJarFile.java
+++ b/luni/src/main/java/java/util/jar/StrictJarFile.java
@@ -40,6 +40,8 @@
  */
 public final class StrictJarFile {
 
+    private final String fileName;
+
     private final long nativeHandle;
 
     // NOTE: It's possible to share a file descriptor with the native
@@ -55,24 +57,34 @@
     private boolean closed;
 
     public StrictJarFile(String fileName) throws IOException, SecurityException {
+        this.fileName = fileName;
         this.nativeHandle = nativeOpenJarFile(fileName);
         this.raf = new RandomAccessFile(fileName, "r");
 
         try {
             // Read the MANIFEST and signature files up front and try to
             // parse them. We never want to accept a JAR File with broken signatures
-            // or manifests, so it's best to throw as early as possible.
+            // or manifests, so it's best to throw as early as possible. It is valid
+            // for a jar file to be missing a manifest and it's treated the same
+            // as any other unsigned jar.
             HashMap<String, byte[]> metaEntries = getMetaEntries();
-            this.manifest = new Manifest(metaEntries.get(JarFile.MANIFEST_NAME), true);
-            this.verifier = new JarVerifier(fileName, manifest, metaEntries);
-            Set<String> files = this.manifest.getEntries().keySet();
-            for (String file : files) {
-                if (findEntry(file) == null) {
-                    throw new SecurityException(fileName + ": File " + file + " in manifest does not exist");
+            byte[] manifestBytes = metaEntries.get(JarFile.MANIFEST_NAME);
+            if (manifestBytes == null) {
+                this.manifest = null;
+                this.verifier = null;
+                isSigned = false;
+            } else {
+                this.manifest = new Manifest(manifestBytes, true);
+                this.verifier = new JarVerifier(fileName, manifest, metaEntries);
+                Set<String> files = this.manifest.getEntries().keySet();
+                for (String file : files) {
+                    if (findEntry(file) == null) {
+                        throw new SecurityException(
+                                fileName + ": File " + file + " in manifest does not exist");
+                    }
                 }
+                isSigned = verifier.readCertificates() && verifier.isSignedJar();
             }
-
-            isSigned = verifier.readCertificates() && verifier.isSignedJar();
         } catch (IOException | SecurityException e) {
             nativeClose(this.nativeHandle);
             IoUtils.closeQuietly(this.raf);
@@ -82,6 +94,10 @@
         guard.open("close");
     }
 
+    public String getName() {
+        return fileName;
+    }
+
     public Manifest getManifest() {
         return manifest;
     }
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/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/libcore/icu/RelativeDateTimeFormatter.java b/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java
index e2afa61..7278175 100644
--- a/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java
+++ b/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java
@@ -65,7 +65,7 @@
    * This is the internal API that implements the functionality of
    * DateUtils.getRelativeTimeSpanString(long, long, long, int), which is to
    * return a string describing 'time' as a time relative to 'now' such as
-   * '5 minutes ago', or 'in 2 days'. More examples can be found in DateUtils'
+   * '5 minutes ago', or 'In 2 days'. More examples can be found in DateUtils'
    * doc.
    *
    * In the implementation below, it selects the appropriate time unit based on
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/ClassPathURLStreamHandler.java b/luni/src/main/java/libcore/io/ClassPathURLStreamHandler.java
new file mode 100644
index 0000000..2f26b14
--- /dev/null
+++ b/luni/src/main/java/libcore/io/ClassPathURLStreamHandler.java
@@ -0,0 +1,172 @@
+/*
+ * 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.io;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.util.jar.JarFile;
+import java.util.jar.StrictJarFile;
+import java.util.zip.ZipEntry;
+import libcore.net.url.JarHandler;
+
+/**
+ * A {@link URLStreamHandler} for a specific class path {@link JarFile}. This class avoids the need
+ * to open a jar file multiple times to read resources if the jar file can be held open. The
+ * {@link URLConnection} objects created are a subclass of {@link JarURLConnection}.
+ *
+ * <p>Use {@link #getEntryUrlOrNull(String)} to obtain a URL backed by this stream handler.
+ */
+public class ClassPathURLStreamHandler extends JarHandler {
+  private final String fileUri;
+  private final StrictJarFile jarFile;
+
+  public ClassPathURLStreamHandler(String jarFileName) throws IOException {
+    // We use StrictJarFile because it is much less heap memory hungry than ZipFile / JarFile.
+    jarFile = new StrictJarFile(jarFileName);
+
+    // File.toURI() is compliant with RFC 1738 in always creating absolute path names. If we
+    // construct the URL by concatenating strings, we might end up with illegal URLs for relative
+    // names.
+    this.fileUri = new File(jarFileName).toURI().toString();
+  }
+
+  /**
+   * Returns a URL backed by this stream handler for the named resource, or {@code null} if the
+   * entry cannot be found under the exact name presented.
+   */
+  public URL getEntryUrlOrNull(String entryName) {
+    if (jarFile.findEntry(entryName) != null) {
+      try {
+        // We rely on the URL/the stream handler to deal with any url encoding necessary here, and
+        // we assume it is completely reversible.
+        return new URL("jar", null, -1, fileUri + "!/" + entryName, this);
+      } catch (MalformedURLException e) {
+        throw new RuntimeException("Invalid entry name", e);
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Returns true if entry with specified name exists and stored (not compressed),
+   * and false otherwise.
+   */
+  public boolean isEntryStored(String entryName) {
+    ZipEntry entry = jarFile.findEntry(entryName);
+    return entry != null && entry.getMethod() == ZipEntry.STORED;
+  }
+
+  @Override
+  protected URLConnection openConnection(URL url) throws IOException {
+    return new ClassPathURLConnection(url, jarFile);
+  }
+
+  public void close() throws IOException {
+    jarFile.close();
+  }
+
+  private static class ClassPathURLConnection extends JarURLConnection {
+
+    private final StrictJarFile strictJarFile;
+    private ZipEntry jarEntry;
+    private InputStream jarInput;
+    private boolean closed;
+    private JarFile jarFile;
+
+    public ClassPathURLConnection(URL url, StrictJarFile strictJarFile)
+            throws MalformedURLException {
+      super(url);
+      this.strictJarFile = strictJarFile;
+    }
+
+    @Override
+    public void connect() throws IOException {
+      if (!connected) {
+          this.jarEntry = strictJarFile.findEntry(getEntryName());
+          if (jarEntry == null) {
+              throw new FileNotFoundException(
+                      "URL does not correspond to an entry in the zip file. URL=" + url
+                              + ", zipfile=" + strictJarFile.getName());
+          }
+          connected = true;
+      }
+    }
+
+    @Override
+    public JarFile getJarFile() throws IOException {
+        connect();
+
+        // This is expensive because we only pretend that we wrap a JarFile.
+        if (jarFile == null) {
+            jarFile = new JarFile(strictJarFile.getName());
+        }
+        return jarFile;
+    }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+      if (closed) {
+        throw new IllegalStateException("JarURLConnection InputStream has been closed");
+      }
+      connect();
+      if (jarInput != null) {
+        return jarInput;
+      }
+      return jarInput = new FilterInputStream(strictJarFile.getInputStream(jarEntry)) {
+        @Override
+        public void close() throws IOException {
+          super.close();
+          closed = true;
+        }
+      };
+    }
+
+    /**
+     * Returns the content type of the entry based on the name of the entry. Returns
+     * non-null results ("content/unknown" for unknown types).
+     *
+     * @return the content type
+     */
+    @Override
+    public String getContentType() {
+      String cType = guessContentTypeFromName(getEntryName());
+      if (cType == null) {
+        cType = "content/unknown";
+      }
+      return cType;
+    }
+
+    @Override
+    public int getContentLength() {
+      try {
+        connect();
+        return (int) getJarEntry().getSize();
+      } catch (IOException e) {
+        // Ignored
+      }
+      return -1;
+    }
+  }
+}
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index cb77573..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); }
@@ -169,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 6d28b95..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;
@@ -162,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 151809d..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;
@@ -252,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/libcore/util/ZoneInfoDB.java b/luni/src/main/java/libcore/util/ZoneInfoDB.java
index fd8570c..d2cb9ab 100644
--- a/luni/src/main/java/libcore/util/ZoneInfoDB.java
+++ b/luni/src/main/java/libcore/util/ZoneInfoDB.java
@@ -18,17 +18,11 @@
 
 import android.system.ErrnoException;
 import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.channels.FileChannel.MapMode;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.TimeZone;
 import libcore.io.BufferIterator;
-import libcore.io.IoUtils;
 import libcore.io.MemoryMappedFile;
 
 /**
@@ -253,6 +247,13 @@
     public boolean hasTimeZone(String id) throws IOException {
       return cache.get(id) != null;
     }
+
+    @Override protected void finalize() throws Throwable {
+      if (mappedFile != null) {
+        mappedFile.close();
+      }
+      super.finalize();
+    }
   }
 
   private ZoneInfoDB() {
diff --git a/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java b/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
index 171d9c2..71afa9d 100644
--- a/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
+++ b/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
@@ -251,9 +251,10 @@
             sb.append('=');
             if (value.escapedString == value.getHexString()) {
                 sb.append(value.getHexString().toUpperCase(Locale.US));
-            } else if (value.escapedString.length() != value.rawString.length()) {
+            } else if (value.escapedString.length() != value.rawString.length()
+                    || value.hasQEN) {
                 // was escaped
-                value.appendQEString(sb);
+                value.appendQuotedString(sb);
             } else {
                 sb.append(value.escapedString);
             }
diff --git a/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java b/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
index b3eb200..b38b78a 100644
--- a/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
+++ b/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
@@ -51,16 +51,16 @@
 
     public byte[] bytes; //FIXME remove??? bytes to be encoded
 
-    public boolean hasQE; // raw string contains '"' or '\'
+    public boolean hasQEN; // raw string contains '"', '\' or '\n'
 
     public final String rawString;
 
-    public AttributeValue(String parsedString, boolean hasQorE, ObjectIdentifier oid) {
+    public AttributeValue(String parsedString, boolean mustBeOutputWithQuotes, ObjectIdentifier oid) {
         wasEncoded = false;
 
-        this.hasQE = hasQorE;
+        this.hasQEN = mustBeOutputWithQuotes;
         this.rawString = parsedString;
-        this.escapedString = makeEscaped(rawString); // overwrites hasQE
+        this.escapedString = makeEscaped(rawString); // overwrites hasQEN
 
         int tag;
         if (oid == AttributeTypeAndValue.EMAILADDRESS || oid == AttributeTypeAndValue.DC) {
@@ -180,9 +180,9 @@
         return (Collection<?>) new ASN1SetOf(type).decode(encoded);
     }
 
-    public void appendQEString(StringBuilder sb) {
+    public void appendQuotedString(StringBuilder sb) {
         sb.append('"');
-        if (hasQE) {
+        if (hasQEN) {
             char c;
             for (int i = 0; i < rawString.length(); i++) {
                 c = rawString.charAt(i);
@@ -247,11 +247,16 @@
 
             case '"':
             case '\\':
-                hasQE = true;
                 buf.append('\\');
                 buf.append(ch);
+                hasQEN = true;
                 break;
-
+            case '\n':
+                // New line is treated specially in other contexts (that's we need to set hasQEN)
+                // but shouldn't be escaped (see rfc2253, rfc 1779 and RI).
+                buf.append(ch);
+                hasQEN = true;
+                break;
             case ',':
             case '+':
             case '<':
diff --git a/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java b/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java
index 2f6fcb9..f15cc81 100644
--- a/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java
+++ b/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java
@@ -50,8 +50,8 @@
     /** distinguished name chars */
     private final char[] chars;
 
-    /** raw string contains '"' or '\' */
-    private boolean hasQE;
+    /** raw string contains '"', '\' or '\n' */
+    private boolean hasQEN;
 
     /** DER encoding of currently parsed item */
     private byte[] encoded;
@@ -67,7 +67,7 @@
      * Returns the next attribute type: (ALPHA 1*keychar) / oid
      */
     private String nextAT() throws IOException {
-        hasQE = false; // reset
+        hasQEN = false; // reset
 
         // skip preceding space chars, they can present after
         // comma or semicolon (compatibility with RFC 1779)
@@ -271,7 +271,11 @@
         switch (ch) {
         case '"':
         case '\\':
-            hasQE = true;
+        // <CR> Is not a special character in RFC2253, but it is in RFC1779. The Javadoc in the RI for
+        // X500Principal says that names are according to RFC2253 but ones according to RFC1779
+        // should also be accepted.
+        case '\n':
+            hasQEN = true;
             return ch;
         case ',':
         case '=':
@@ -403,7 +407,7 @@
 
             switch (chars[pos]) {
             case '"':
-                atav.add(new AttributeTypeAndValue(oid, new AttributeValue(quotedAV(), hasQE, oid)));
+                atav.add(new AttributeTypeAndValue(oid, new AttributeValue(quotedAV(), hasQEN, oid)));
                 break;
             case '#':
                 atav.add(new AttributeTypeAndValue(oid, new AttributeValue(hexAV(), encoded)));
@@ -416,7 +420,7 @@
                 break;
             default:
                 atav.add(new AttributeTypeAndValue(oid,
-                                                   new AttributeValue(escapedAV(), hasQE, oid)));
+                                                   new AttributeValue(escapedAV(), hasQEN, oid)));
             }
 
             if (pos >= chars.length) {
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/Register.cpp b/luni/src/main/native/Register.cpp
index acc1e4f..787a149 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_nio_ByteOrder);
     REGISTER(register_java_text_Bidi);
     REGISTER(register_java_util_jar_StrictJarFile);
     REGISTER(register_java_util_regex_Matcher);
diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp
index a11ea76..3cc9b06 100644
--- a/luni/src/main/native/android_system_OsConstants.cpp
+++ b/luni/src/main/native/android_system_OsConstants.cpp
@@ -35,6 +35,7 @@
 #endif
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/un.h>
 #include <sys/wait.h>
 #include <sys/xattr.h>
 #include <unistd.h>
@@ -211,6 +212,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
@@ -550,6 +552,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);
diff --git a/luni/src/main/native/java_lang_StrictMath.cpp b/luni/src/main/native/java_lang_StrictMath.cpp
index e8c6dfb..d0bb8ce 100644
--- a/luni/src/main/native/java_lang_StrictMath.cpp
+++ b/luni/src/main/native/java_lang_StrictMath.cpp
@@ -42,14 +42,6 @@
     return ieee_remainder(a, b);
 }
 
-static jdouble StrictMath_floor(JNIEnv*, jclass, jdouble a) {
-    return ieee_floor(a);
-}
-
-static jdouble StrictMath_ceil(JNIEnv*, jclass, jdouble a) {
-    return ieee_ceil(a);
-}
-
 static jdouble StrictMath_rint(JNIEnv*, jclass, jdouble a) {
     return ieee_rint(a);
 }
@@ -68,9 +60,7 @@
 
 static JNINativeMethod gMethods[] = {
     NATIVE_METHOD(StrictMath, IEEEremainder, "!(DD)D"),
-    NATIVE_METHOD(StrictMath, ceil, "!(D)D"),
     NATIVE_METHOD(StrictMath, cos, "!(D)D"),
-    NATIVE_METHOD(StrictMath, floor, "!(D)D"),
     NATIVE_METHOD(StrictMath, hypot, "!(DD)D"),
     NATIVE_METHOD(StrictMath, nextafter, "!(DD)D"),
     NATIVE_METHOD(StrictMath, pow, "!(DD)D"),
diff --git a/luni/src/main/native/java_nio_ByteOrder.cpp b/luni/src/main/native/java_nio_ByteOrder.cpp
deleted file mode 100644
index 3269bc2..0000000
--- a/luni/src/main/native/java_nio_ByteOrder.cpp
+++ /dev/null
@@ -1,32 +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 "ByteOrder"
-
-#include "JNIHelp.h"
-#include "JniConstants.h"
-
-static jboolean ByteOrder_isLittleEndian(JNIEnv*, jclass) {
-    int i = 1;
-    return *reinterpret_cast<jbyte*>(&i) == 1;
-}
-
-static JNINativeMethod gMethods[] = {
-    NATIVE_METHOD(ByteOrder, isLittleEndian, "!()Z"),
-};
-void register_java_nio_ByteOrder(JNIEnv* env) {
-    jniRegisterNativeMethods(env, "java/nio/ByteOrder", 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 03d0784..09dc5a0 100644
--- a/luni/src/main/native/java_util_jar_StrictJarFile.cpp
+++ b/luni/src/main/native/java_util_jar_StrictJarFile.cpp
@@ -98,11 +98,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) {
@@ -115,7 +115,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);
@@ -141,7 +141,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_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index 99b76f9..1f2f008 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -57,6 +57,7 @@
 #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>
@@ -317,8 +318,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) {
@@ -327,6 +360,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,
@@ -448,8 +490,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.
@@ -465,6 +524,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(
@@ -497,6 +573,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(
@@ -546,6 +647,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");
@@ -579,7 +682,7 @@
     throwErrnoException(env, is_sockname ? "getsockname" : "getpeername");
     return NULL;
   }
-  return makeSocketAddress(env, ss);
+  return makeSocketAddress(env, ss, byteCount);
 }
 
 class Passwd {
@@ -618,14 +721,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;
     }
@@ -1435,7 +1538,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;
 }
 
@@ -1818,6 +1924,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) {
@@ -1856,7 +1970,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"),
@@ -1970,6 +2084,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 73ed7cb..78ec37a 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_nio_ByteOrder.cpp \
     java_text_Bidi.cpp \
     java_util_jar_StrictJarFile.cpp \
     java_util_regex_Matcher.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/dalvik/system/JniTest.java b/luni/src/test/java/dalvik/system/JniTest.java
index 37e687d..19f820e 100644
--- a/luni/src/test/java/dalvik/system/JniTest.java
+++ b/luni/src/test/java/dalvik/system/JniTest.java
@@ -361,8 +361,6 @@
         assertEquals(Object.class, envGetSuperclass(String.class));
         assertEquals(null, envGetSuperclass(Object.class));
         assertEquals(null, envGetSuperclass(int.class));
-
-        // incorrect! the spec says this should be null. http://b/5652725
-        assertEquals(Object.class, envGetSuperclass(Runnable.class));
+        assertEquals(null, envGetSuperclass(Runnable.class));
     }
 }
diff --git a/luni/src/test/java/libcore/io/ClassPathURLStreamHandlerTest.java b/luni/src/test/java/libcore/io/ClassPathURLStreamHandlerTest.java
new file mode 100644
index 0000000..eb66c3a
--- /dev/null
+++ b/luni/src/test/java/libcore/io/ClassPathURLStreamHandlerTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.io;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.net.UnknownServiceException;
+import java.util.Arrays;
+
+import tests.support.resource.Support_Resources;
+
+public class ClassPathURLStreamHandlerTest extends TestCase {
+
+    // A well formed jar file with 6 entries.
+    private static final String JAR = "ClassPathURLStreamHandlerTest.jar";
+    private static final String ENTRY_IN_ROOT = "root.txt";
+    private static final String ENTRY_IN_SUBDIR = "foo/bar/baz.txt";
+    private static final String ENTRY_STORED = "stored_file.txt";
+    private static final String ENTRY_WITH_SPACES_ENCODED = "file%20with%20spaces.txt";
+    private static final String ENTRY_WITH_SPACES_UNENCODED = "file with spaces.txt";
+    private static final String ENTRY_THAT_NEEDS_ESCAPING = "file_with_percent20_%20.txt";
+    private static final String ENTRY_WITH_RELATIVE_PATH = "foo/../foo/bar/baz.txt";
+    private static final String MISSING_ENTRY = "Wrong.resource";
+
+    private File jarFile;
+
+    @Override
+    protected void setUp() {
+        File resources = Support_Resources.createTempFolder();
+        Support_Resources.copyFile(resources, null, JAR);
+        jarFile = new File(resources, JAR);
+    }
+
+    public void testConstructor() throws Exception {
+        try {
+            ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler("Missing.file");
+            fail("Should throw IOException");
+        } catch (IOException expected) {
+        }
+
+        String fileName = jarFile.getCanonicalPath();
+        ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler(fileName);
+        streamHandler.close();
+    }
+
+    public void testGetEntryOrNull() throws Exception {
+        String fileName = jarFile.getCanonicalPath();
+        ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler(fileName);
+
+        assertNotNull(streamHandler.getEntryUrlOrNull(ENTRY_IN_ROOT));
+        assertNotNull(streamHandler.getEntryUrlOrNull(ENTRY_IN_SUBDIR));
+        assertNotNull(streamHandler.getEntryUrlOrNull(ENTRY_WITH_SPACES_UNENCODED));
+        assertNotNull(streamHandler.getEntryUrlOrNull(ENTRY_THAT_NEEDS_ESCAPING));
+
+        // getEntryOrNull() performs an exact match on the entry name.
+        assertNull(streamHandler.getEntryUrlOrNull(MISSING_ENTRY));
+        assertNull(streamHandler.getEntryUrlOrNull("/" + ENTRY_IN_ROOT));
+        assertNull(streamHandler.getEntryUrlOrNull("/" + ENTRY_IN_SUBDIR));
+        assertNull(streamHandler.getEntryUrlOrNull(ENTRY_WITH_SPACES_ENCODED));
+        assertNull(streamHandler.getEntryUrlOrNull(ENTRY_WITH_RELATIVE_PATH));
+        streamHandler.close();
+    }
+
+    public void testIsEntryStored() throws IOException {
+        String fileName = jarFile.getCanonicalPath();
+        ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler(fileName);
+
+        assertFalse(streamHandler.isEntryStored("this/file/does/not/exist.txt"));
+        // This one is compressed
+        assertFalse(streamHandler.isEntryStored(ENTRY_IN_SUBDIR));
+        assertTrue(streamHandler.isEntryStored(ENTRY_STORED));
+    }
+
+    public void testOpenConnection() throws Exception {
+        String fileName = jarFile.getCanonicalPath();
+        ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler(fileName);
+
+        assertOpenConnectionOk(jarFile, ENTRY_IN_ROOT, streamHandler);
+        assertOpenConnectionOk(jarFile, ENTRY_IN_SUBDIR, streamHandler);
+        assertOpenConnectionOk(jarFile, ENTRY_WITH_SPACES_ENCODED, streamHandler);
+        assertOpenConnectionOk(jarFile, ENTRY_WITH_SPACES_UNENCODED, streamHandler);
+
+        assertOpenConnectionConnectFails(jarFile, ENTRY_WITH_RELATIVE_PATH, streamHandler);
+        assertOpenConnectionConnectFails(jarFile, MISSING_ENTRY, streamHandler);
+        assertOpenConnectionConnectFails(jarFile, ENTRY_THAT_NEEDS_ESCAPING, streamHandler);
+
+        streamHandler.close();
+    }
+
+    private void assertOpenConnectionConnectFails(
+            File jarFile, String entryName, URLStreamHandler streamHandler) throws IOException {
+
+        URL standardUrl = createJarUrl(jarFile, entryName, null /* use default stream handler */);
+        try {
+            standardUrl.openConnection().connect();
+            fail();
+        } catch (FileNotFoundException expected) {
+        }
+
+        URL actualUrl = createJarUrl(jarFile, entryName, streamHandler);
+        try {
+            actualUrl.openConnection().connect();
+            fail();
+        } catch (FileNotFoundException expected) {
+        }
+    }
+
+    private static void assertOpenConnectionOk(File jarFile, String entryName,
+            ClassPathURLStreamHandler streamHandler) throws IOException {
+        URL standardUrl = createJarUrl(jarFile, entryName, null /* use default stream handler */);
+        URLConnection standardUrlConnection = standardUrl.openConnection();
+        assertNotNull(standardUrlConnection);
+
+        URL actualUrl = createJarUrl(jarFile, entryName, streamHandler);
+        URLConnection actualUrlConnection = actualUrl.openConnection();
+        assertNotNull(actualUrlConnection);
+        assertBehaviorSame(standardUrlConnection, actualUrlConnection);
+    }
+
+    private static void assertBehaviorSame(URLConnection standardURLConnection,
+            URLConnection actualUrlConnection) throws IOException {
+
+        JarURLConnection standardJarUrlConnection = (JarURLConnection) standardURLConnection;
+        JarURLConnection actualJarUrlConnection = (JarURLConnection) actualUrlConnection;
+
+        byte[] actualBytes = Streams.readFully(actualJarUrlConnection.getInputStream());
+        byte[] standardBytes = Streams.readFully(standardJarUrlConnection.getInputStream());
+        assertEquals(Arrays.toString(standardBytes), Arrays.toString(actualBytes));
+
+        try {
+            actualJarUrlConnection.getOutputStream();
+            fail();
+        } catch (UnknownServiceException expected) {
+        }
+
+        assertEquals(
+                standardJarUrlConnection.getJarFile().getName(),
+                actualJarUrlConnection.getJarFile().getName());
+
+        assertEquals(
+                standardJarUrlConnection.getJarEntry().getName(),
+                actualJarUrlConnection.getJarEntry().getName());
+
+        assertEquals(
+                standardJarUrlConnection.getJarFileURL(),
+                actualJarUrlConnection.getJarFileURL());
+
+        assertEquals(
+                standardJarUrlConnection.getContentType(),
+                actualJarUrlConnection.getContentType());
+
+        assertEquals(
+                standardJarUrlConnection.getContentLength(),
+                actualJarUrlConnection.getContentLength());
+    }
+
+    private static URL createJarUrl(File jarFile, String entryName, URLStreamHandler streamHandler)
+            throws MalformedURLException {
+        return new URL("jar", null, -1, jarFile.toURI() + "!/" + entryName, streamHandler);
+    }
+
+}
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index 9b38ee9..f1d6668 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -22,6 +22,8 @@
 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;
@@ -30,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;
@@ -70,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);
@@ -90,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);
@@ -119,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!";
@@ -135,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 {
@@ -220,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);
@@ -253,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);
@@ -341,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 {
@@ -373,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) {
@@ -407,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");
@@ -421,58 +426,72 @@
     checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, false);
   }
 
-    private static void assertPartial(byte[] expected, byte[] actual) {
-        for (int i = 0; i < expected.length; i++) {
-            if (expected[i] != actual[i]) {
-                fail("Expected " + Arrays.toString(expected) + " but found "
-                        + Arrays.toString(actual));
-            }
-        }
+  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";
+  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);
+    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();
+    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);
-            }
+    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));
-            assertPartial(VALUE_CAKE, tmp);
+      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);
-            }
+      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));
-            assertPartial(VALUE_PIE, tmp);
+      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);
-            }
+      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();
-        }
+    } 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/nio/charset/CharsetDecoderTest.java b/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java
index e874a1b..4fa6e0c 100644
--- a/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java
+++ b/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java
@@ -105,4 +105,15 @@
         assertEquals(1, cb.position());
         assertEquals('\u2603', cb.get(0));
     }
+
+    public void testBufferWithNonZeroOffset() {
+        CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
+        CharBuffer cb = CharBuffer.allocate(128);
+        cb.position(42);
+        CharBuffer out = cb.slice();
+        CoderResult cr = decoder.decode(
+                ByteBuffer.wrap(new byte[] { 'h', 'e', 'l', 'l', 'o'}), out, false);
+        assertTrue(cr.isUnderflow());
+        assertEquals(5, out.position());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java
index 9005f25..7d7fde1 100644
--- a/luni/src/test/java/libcore/java/util/LocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/LocaleTest.java
@@ -791,7 +791,7 @@
 
     public void test_setLanguageTag_malformedTags() {
         Locale l = fromLanguageTag("a", false);
-        assertEquals("und", l.getLanguage());
+        assertEquals("", l.getLanguage());
         assertEquals("", l.getCountry());
         assertEquals("", l.getVariant());
         assertEquals("", l.getScript());
@@ -994,8 +994,7 @@
 
         // Empty builder.
         Locale l = b.build();
-        // TODO: Fix this. We should return "und" and not NULL.
-        // assertEquals("und", l.toLanguageTag());
+        assertEquals("und", l.toLanguageTag());
 
         // Only language.
         b = new Locale.Builder();
@@ -1134,7 +1133,7 @@
 
         // Irregular grandfathered locale.
         Locale enochian = Locale.forLanguageTag("i-enochian");
-        assertEquals("und", enochian.getLanguage());
+        assertEquals("", enochian.getLanguage());
         assertEquals("i-enochian", enochian.getExtension(Locale.PRIVATE_USE_EXTENSION));
         assertEquals("", enochian.getCountry());
         assertEquals("", enochian.getScript());
@@ -1195,7 +1194,7 @@
             System.setUnchangeableSystemProperty("user.locale", "dexx-Latn-DE");
 
             l = Locale.getDefaultLocaleFromSystemProperties();
-            assertEquals("und", l.getLanguage());
+            assertEquals("", l.getLanguage());
             assertEquals("DE", l.getCountry());
         } finally {
             System.setUnchangeableSystemProperty("user.language", userLanguage);
diff --git a/luni/src/test/java/libcore/java/util/jar/StrictJarFileTest.java b/luni/src/test/java/libcore/java/util/jar/StrictJarFileTest.java
index 9496ad0..d44918c 100644
--- a/luni/src/test/java/libcore/java/util/jar/StrictJarFileTest.java
+++ b/luni/src/test/java/libcore/java/util/jar/StrictJarFileTest.java
@@ -50,6 +50,7 @@
         Support_Resources.copyFile(resources, null, JAR_1);
         String fileName = (new File(resources, JAR_1)).getCanonicalPath();
         StrictJarFile jarFile = new StrictJarFile(fileName);
+        assertEquals(fileName, jarFile.getName());
         jarFile.close();
     }
 
@@ -173,6 +174,18 @@
         assertThrowsOnInit("removed.jar");
     }
 
+    public void testJarWithNoManifest() throws Exception {
+        String jarFileName = "StrictJarFileTestNoManifest.jar";
+        Support_Resources.copyFile(resources, null, jarFileName);
+        StrictJarFile jarFile = new StrictJarFile(
+                new File(resources,  jarFileName).getAbsolutePath());
+
+        assertNull(jarFile.getManifest());
+        ZipEntry entry = jarFile.findEntry("Test.class");
+        assertNotNull(entry);
+        assertNull(jarFile.getCertificateChains(entry));
+    }
+
     private void assertThrowsOnInit(String name) throws Exception {
         Support_Resources.copyFile(resources, null,  name);
         try {
diff --git a/luni/src/test/java/libcore/java/util/prefs/OldAbstractPreferencesTest.java b/luni/src/test/java/libcore/java/util/prefs/OldAbstractPreferencesTest.java
index 693f0c2..0f8ed99 100644
--- a/luni/src/test/java/libcore/java/util/prefs/OldAbstractPreferencesTest.java
+++ b/luni/src/test/java/libcore/java/util/prefs/OldAbstractPreferencesTest.java
@@ -37,6 +37,12 @@
 
     static final String nodeName = "mock";
 
+    /** Timeout used for Object.wait when no action is expected. */
+    static final long NO_ACTION_EXPECTED_TIMEOUT = 200;
+
+    /** Timeout used for Object.wait when an action is expected. */
+    static final long ACTION_EXPECTED_TIMEOUT = 0; // Wait indefinitely
+
     private PreferencesFactory defaultFactory;
 
     AbstractPreferences pref;
@@ -885,7 +891,9 @@
         }
 
         public synchronized void assertChanged(boolean expected) throws InterruptedException {
-            wait(100);
+            if (!flagChange) {
+              wait(expected ? ACTION_EXPECTED_TIMEOUT : NO_ACTION_EXPECTED_TIMEOUT);
+            }
             assertEquals(expected, flagChange);
             flagChange = false;
         }
@@ -933,12 +941,16 @@
         }
 
         public synchronized void assertAdded(boolean expected) throws InterruptedException {
-            wait(100);
+            if (!flagAdded) {
+              wait(expected ? ACTION_EXPECTED_TIMEOUT : NO_ACTION_EXPECTED_TIMEOUT);
+            }
             assertEquals(expected, flagAdded);
         }
 
         public synchronized void assertRemoved(boolean expected) throws InterruptedException {
-            wait(100);
+            if (!flagRemoved) {
+              wait(expected ? ACTION_EXPECTED_TIMEOUT : NO_ACTION_EXPECTED_TIMEOUT);
+            }
             assertEquals(expected, flagRemoved);
         }
     }
diff --git a/luni/src/test/java/libcore/java/util/zip/Zip64FileTest.java b/luni/src/test/java/libcore/java/util/zip/Zip64FileTest.java
index 1b733f9..0986472 100644
--- a/luni/src/test/java/libcore/java/util/zip/Zip64FileTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/Zip64FileTest.java
@@ -16,10 +16,13 @@
 
 package libcore.java.util.zip;
 
+import libcore.io.Streams;
+
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Enumeration;
 import java.util.zip.ZipEntry;
@@ -43,6 +46,16 @@
             assertTrue(entries.hasMoreElements());
             ZipEntry ze = entries.nextElement();
             assertEquals(2, ze.getSize());
+            InputStream is = null;
+            try {
+                is = zf.getInputStream(ze);
+                byte[] uncompressed = Streams.readFully(is);
+                assertEquals(2, uncompressed.length);
+            } finally {
+                if (is != null) {
+                    is.close();
+                }
+            }
         } finally {
             if (zf != null) {
                 zf.close();
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 3c7ff0e..dce0e62 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -988,9 +988,20 @@
 
         Security.addProvider(mockProviderInvalid);
         try {
-            Cipher.getInstance("FOO");
-            fail("Should not find any matching providers");
-        } catch (NoSuchAlgorithmException expected) {
+            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;
+            }
         } finally {
             Security.removeProvider(mockProviderInvalid.getName());
         }
@@ -2471,10 +2482,6 @@
             (byte) 0x19, (byte) 0x35,
     };
 
-    private static final byte[][] AES_KEYS = new byte[][] {
-            AES_128_KEY, AES_192_KEY, AES_256_KEY,
-    };
-
     private static final String[] AES_MODES = new String[] {
             "AES/ECB",
             "AES/CBC",
@@ -2590,7 +2597,42 @@
     /*
      * Test key generation:
      * openssl rand -hex 16
-     * echo 'ceaa31952dfd3d0f5af4b2042ba06094' | sed 's/\(..\)/(byte) 0x\1, /g'
+     * echo '787bdeecf05556eac5d3d865e435f6d9' | sed 's/\(..\)/(byte) 0x\1, /g'
+     */
+    private static final byte[] AES_192_CTR_NoPadding_TestVector_1_IV = new byte[] {
+            (byte) 0x78, (byte) 0x7b, (byte) 0xde, (byte) 0xec, (byte) 0xf0, (byte) 0x55,
+            (byte) 0x56, (byte) 0xea, (byte) 0xc5, (byte) 0xd3, (byte) 0xd8, (byte) 0x65,
+            (byte) 0xe4, (byte) 0x35, (byte) 0xf6, (byte) 0xd9,
+
+    };
+
+    /*
+     * Test vector generation:
+     * echo -n 'AES-192 is a silly option' | recode ../x1 | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] AES_192_CTR_NoPadding_TestVector_1_Plaintext = new byte[] {
+            (byte) 0x41, (byte) 0x45, (byte) 0x53, (byte) 0x2D, (byte) 0x31, (byte) 0x39,
+            (byte) 0x32, (byte) 0x20, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x61,
+            (byte) 0x20, (byte) 0x73, (byte) 0x69, (byte) 0x6C, (byte) 0x6C, (byte) 0x79,
+            (byte) 0x20, (byte) 0x6F, (byte) 0x70, (byte) 0x74, (byte) 0x69, (byte) 0x6F,
+            (byte) 0x6E
+    };
+
+    /*
+     * Test vector generation:
+     * echo -n 'AES-192 is a silly option' | openssl enc -aes-192-ctr -K 5a7a3d7e40b64ed996f7afa15f97fd595e27db6af428e342 -iv 787bdeecf05556eac5d3d865e435f6d9 | recode ../x1 | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] AES_192_CTR_NoPadding_TestVector_1_Ciphertext = new byte[] {
+            (byte) 0xE9, (byte) 0xC6, (byte) 0xA0, (byte) 0x40, (byte) 0xC2, (byte) 0x6A,
+            (byte) 0xB5, (byte) 0x20, (byte) 0xFE, (byte) 0x9E, (byte) 0x65, (byte) 0xB7,
+            (byte) 0x7C, (byte) 0x5E, (byte) 0xFE, (byte) 0x1F, (byte) 0xF1, (byte) 0x6F,
+            (byte) 0x20, (byte) 0xAC, (byte) 0x37, (byte) 0xE9, (byte) 0x75, (byte) 0xE3,
+            (byte) 0x52
+    };
+
+    /*
+     * Test key generation: openssl rand -hex 16 echo
+     * 'ceaa31952dfd3d0f5af4b2042ba06094' | sed 's/\(..\)/(byte) 0x\1, /g'
      */
     private static final byte[] AES_256_CBC_PKCS5Padding_TestVector_1_IV = new byte[] {
             (byte) 0xce, (byte) 0xaa, (byte) 0x31, (byte) 0x95, (byte) 0x2d, (byte) 0xfd,
@@ -2699,6 +2741,12 @@
                 AES_128_GCM_TestVector_1_Plaintext,
                 AES_128_GCM_TestVector_1_Encrypted));
         if (IS_UNLIMITED) {
+            CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/CTR/NoPadding", AES_192_KEY,
+                    AES_192_CTR_NoPadding_TestVector_1_IV,
+                    null,
+                    AES_192_CTR_NoPadding_TestVector_1_Plaintext,
+                    AES_192_CTR_NoPadding_TestVector_1_Plaintext,
+                    AES_192_CTR_NoPadding_TestVector_1_Ciphertext));
             CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/CBC/PKCS5Padding", AES_256_KEY,
                     AES_256_CBC_PKCS5Padding_TestVector_1_IV,
                     null,
@@ -2789,7 +2837,8 @@
         // empty decrypt
         {
             if (!isAEAD(p.transformation)
-                    && (StandardNames.IS_RI || provider.equals("AndroidOpenSSL"))) {
+                    && (StandardNames.IS_RI || provider.equals("AndroidOpenSSL") ||
+                            (provider.equals("BC") && p.transformation.contains("/CTR/")))) {
                 assertEquals(Arrays.toString(new byte[0]),
                              Arrays.toString(c.doFinal()));
 
@@ -2799,7 +2848,7 @@
             } else if (provider.equals("BC") || isAEAD(p.transformation)) {
                 try {
                     c.doFinal();
-                    fail();
+                    fail(p.transformation + " " + provider);
                 } catch (IllegalBlockSizeException maybe) {
                     if (isAEAD(p.transformation)) {
                         throw maybe;
@@ -2812,7 +2861,7 @@
                 try {
                     c.update(new byte[0]);
                     c.doFinal();
-                    fail();
+                    fail(p.transformation + " " + provider);
                 } catch (IllegalBlockSizeException maybe) {
                     if (isAEAD(p.transformation)) {
                         throw maybe;
diff --git a/luni/src/test/java/libcore/xml/PullParserTest.java b/luni/src/test/java/libcore/xml/PullParserTest.java
index c59b358..b204c88 100644
--- a/luni/src/test/java/libcore/xml/PullParserTest.java
+++ b/luni/src/test/java/libcore/xml/PullParserTest.java
@@ -766,6 +766,16 @@
         assertRelaxedParseFailure("<!DOCTYPE foo [<!ELEMENT foo EMPTY"); // EOF in read('>')
     }
 
+    public void testWhitespacesAfterDOCTYPE() throws Exception {
+        XmlPullParser parser = newPullParser();
+        String test = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+            "<!DOCTYPE root [\n" +
+            "<!ENTITY dummy \"dummy\">\n" +
+            "]>  \n" +
+            "<root></root>";
+        assertParseSuccess(test, parser);
+    }
+
     private void assertParseFailure(String xml) throws Exception {
         XmlPullParser parser = newPullParser();
         assertParseFailure(xml, parser);
@@ -787,6 +797,12 @@
         }
     }
 
+    private void assertParseSuccess(String xml, XmlPullParser parser) throws Exception {
+        parser.setInput(new StringReader(xml));
+        while (parser.next() != XmlPullParser.END_DOCUMENT) {
+        }
+    }
+
     /**
      * Creates a new pull parser.
      */
diff --git a/luni/src/test/resources/math_important_numbers.csv b/luni/src/test/resources/math_important_numbers.csv
index 3c71a4e..89a7525 100644
--- a/luni/src/test/resources/math_important_numbers.csv
+++ b/luni/src/test/resources/math_important_numbers.csv
@@ -630,6 +630,20 @@
 ceil,-0x1.0p0,-0x1.0p0,-1.0
 ceil,-0x0.0p0,-0x1.0p-1,-0.5
 ceil,0x1.0p0,0x1.0p-1,0.5
+ceil,0x0.0p2047,0x0.0p2047,infty
+ceil,-0x0.0p2047,-0x0.0p2047,-infty
+ceil,0x1.0p2047,0x1.0p2047,NaN
+ceil,0x1.4c7eb53cccp39,0x1.4c7eb53ccab5fp39,7.140274745333553E11
+ceil,0x1.c8d8ep21,0x1.c8d8da6003191p21,3742491.296880909
+ceil,-0x1.5deeef088p35,-0x1.5deeef088909fp35,-4.696725715628246E10
+ceil,-0x1.bde332607a678p50,-0x1.bde332607a67bp50,-1.9610339084804148E15
+ceil,-0x0.0p0,-0x1.5162455ecd513p-117,-7.9318566885477E-36
+ceil,0x1.0p0,0x1.d71300e409ec1p-317,6.891928421440976E-96
+ceil,0x1.a12e8p17,0x1.a12e4b0df7367p17,213596.58636369856
+ceil,-0x1.5607af3b1eb1dp829,-0x1.5607af3b1eb1dp829,-4.7828929737254625E249
+ceil,0x1.9632259cc7e5ep51,0x1.9632259cc7e5ep51,3.572936802189103E15
+ceil,0x1.5a39cp20,0x1.5a39b156b4c84p20,1418139.083668501
+ceil,0x1.8c37dp21,0x1.8c37c99d61a3bp21,3245817.2018463886
 ceil,-0x1.8p2,-0x1.921fb54442d18p2,-6.283185307179586
 ceil,-0x1.8p2,-0x1.815e630c155e1p2,-6.021385919380436
 ceil,-0x1.4p2,-0x1.709d10d3e7eabp2,-5.759586531581287
@@ -687,6 +701,20 @@
 floor,-0x1.0p0,-0x1.0p0,-1.0
 floor,-0x1.0p0,-0x1.0p-1,-0.5
 floor,0x0.0p0,0x1.0p-1,0.5
+floor,0x0.0p2047,0x0.0p2047,infty
+floor,-0x0.0p2047,-0x0.0p2047,-infty
+floor,0x1.0p2047,0x1.0p2047,NaN
+floor,0x1.4c7eb53ccap39,0x1.4c7eb53ccab5fp39,7.140274745333553E11
+floor,0x1.c8d8d8p21,0x1.c8d8da6003191p21,3742491.296880909
+floor,-0x1.5deeef08ap35,-0x1.5deeef088909fp35,-4.696725715628246E10
+floor,-0x1.bde332607a67cp50,-0x1.bde332607a67bp50,-1.9610339084804148E15
+floor,0x0.0p0,0x1.ba884e7f0bc51p-184,7.049948629370372E-56
+floor,-0x1.0p0,-0x1.bc0b3abd1b587p-51,-7.702933170334643E-16
+floor,-0x1.0p1,-0x1.ff1fa889b752ep0,-1.99657681810579
+floor,-0x1.255b340ab85a3p784,-0x1.255b340ab85a3p784,-1.1659287182288336E236
+floor,0x1.d0783f3901842p51,0x1.d0783f3901842p51,4.085518816513057E15
+floor,-0x1.6e715p20,-0x1.6e71470cef763p20,-1500948.440658056
+floor,-0x1.5485cp24,-0x1.5485bfebe1e42p24,-2.2316479921415575E7
 floor,-0x1.cp2,-0x1.921fb54442d18p2,-6.283185307179586
 floor,-0x1.cp2,-0x1.815e630c155e1p2,-6.021385919380436
 floor,-0x1.8p2,-0x1.709d10d3e7eabp2,-5.759586531581287
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index cfd519a..1ea6b06 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -311,25 +311,29 @@
         // Only available with the SunPKCS11-NSS provider,
         // which seems to be enabled in OpenJDK 6 but not Oracle Java 6
         if (Security.getProvider("SunPKCS11-NSS") != null) {
-            provide("AlgorithmParameters", "EC");
             provide("Cipher", "AES/CBC/NOPADDING");
             provide("Cipher", "DES/CBC/NOPADDING");
             provide("Cipher", "DESEDE/CBC/NOPADDING");
             provide("Cipher", "RSA/ECB/PKCS1PADDING");
             provide("KeyAgreement", "DH");
-            provide("KeyAgreement", "ECDH");
             provide("KeyFactory", "DH");
-            provide("KeyFactory", "EC");
             provide("KeyPairGenerator", "DH");
-            provide("KeyPairGenerator", "EC");
             provide("KeyStore", "PKCS11");
             provide("MessageDigest", "SHA1");
             provide("SecretKeyFactory", "AES");
             provide("SecretKeyFactory", "ARCFOUR");
             provide("SecureRandom", "PKCS11");
             provide("Signature", "DSA");
-            provide("Signature", "NONEWITHECDSA");
             provide("Signature", "RAWDSA");
+        }
+
+        if (Security.getProvider("SunPKCS11-NSS") != null ||
+                Security.getProvider("SunEC") != null) {
+            provide("AlgorithmParameters", "EC");
+            provide("KeyAgreement", "ECDH");
+            provide("KeyFactory", "EC");
+            provide("KeyPairGenerator", "EC");
+            provide("Signature", "NONEWITHECDSA");
             provide("Signature", "SHA1WITHECDSA");
             provide("Signature", "SHA224WITHECDSA");
             provide("Signature", "SHA256WITHECDSA");
diff --git a/support/src/test/java/libcore/java/security/TestKeyStore.java b/support/src/test/java/libcore/java/security/TestKeyStore.java
index bd64360..425cefa 100644
--- a/support/src/test/java/libcore/java/security/TestKeyStore.java
+++ b/support/src/test/java/libcore/java/security/TestKeyStore.java
@@ -31,8 +31,6 @@
 import java.io.ByteArrayInputStream;
 import java.io.PrintStream;
 import java.math.BigInteger;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.security.KeyFactory;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
@@ -98,6 +96,9 @@
     }
 
     private static final boolean TEST_MANAGERS = true;
+    private static final byte[] LOCAL_HOST_ADDRESS = { 127, 0, 0, 1 };
+    private static final String LOCAL_HOST_NAME = "localhost";
+
 
     public final KeyStore keyStore;
     public final char[] storePassword;
@@ -156,16 +157,12 @@
                 .signer(ROOT_CA.getPrivateKey("RSA", "RSA"))
                 .rootCa(ROOT_CA.getRootCertificate("RSA"))
                 .build();
-        try {
-            SERVER = new Builder()
-                    .aliasPrefix("server")
-                    .signer(INTERMEDIATE_CA.getPrivateKey("RSA", "RSA"))
-                    .rootCa(INTERMEDIATE_CA.getRootCertificate("RSA"))
-                    .addSubjectAltNameIpAddress(InetAddress.getLocalHost().getAddress())
-                    .build();
-        } catch (UnknownHostException e) {
-            throw new RuntimeException(e);
-        }
+        SERVER = new Builder()
+                .aliasPrefix("server")
+                .signer(INTERMEDIATE_CA.getPrivateKey("RSA", "RSA"))
+                .rootCa(INTERMEDIATE_CA.getRootCertificate("RSA"))
+                .addSubjectAltNameIpAddress(LOCAL_HOST_ADDRESS)
+                .build();
         CLIENT = new TestKeyStore(createClient(INTERMEDIATE_CA.keyStore), null, null);
         CLIENT_CERTIFICATE = new Builder()
                 .aliasPrefix("client")
@@ -529,11 +526,7 @@
         }
 
         private X500Principal localhost() {
-            try {
-                return new X500Principal("CN=" + InetAddress.getLocalHost().getHostName());
-            } catch (UnknownHostException e) {
-                throw new RuntimeException(e);
-            }
+            return new X500Principal("CN=" + LOCAL_HOST_NAME);
         }
     }
 
diff --git a/support/src/test/java/tests/resources/ClassPathURLStreamHandlerTest.jar b/support/src/test/java/tests/resources/ClassPathURLStreamHandlerTest.jar
new file mode 100644
index 0000000..ef810a7
--- /dev/null
+++ b/support/src/test/java/tests/resources/ClassPathURLStreamHandlerTest.jar
Binary files differ
diff --git a/support/src/test/java/tests/resources/StrictJarFileTestNoManifest.jar b/support/src/test/java/tests/resources/StrictJarFileTestNoManifest.jar
new file mode 100644
index 0000000..f16cb2a
--- /dev/null
+++ b/support/src/test/java/tests/resources/StrictJarFileTestNoManifest.jar
Binary files differ
diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java
index a90db3b..2e32bf1 100644
--- a/xml/src/main/java/org/kxml2/io/KXmlParser.java
+++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java
@@ -604,6 +604,7 @@
         }
 
         read('>');
+        skip();
     }
 
     /**
diff --git a/xml/src/main/java/org/kxml2/io/KXmlSerializer.java b/xml/src/main/java/org/kxml2/io/KXmlSerializer.java
index bfdeece..399462d 100644
--- a/xml/src/main/java/org/kxml2/io/KXmlSerializer.java
+++ b/xml/src/main/java/org/kxml2/io/KXmlSerializer.java
@@ -27,17 +27,13 @@
 
 public class KXmlSerializer implements XmlSerializer {
 
+    private static final int BUFFER_LEN = 8192;
+    private final char[] mText = new char[BUFFER_LEN];
+    private int mPos;
+
     //    static final String UNDEFINED = ":";
 
-    // BEGIN android-added
-    /** size (in characters) for the write buffer */
-    private static final int WRITE_BUFFER_SIZE = 500;
-    // END android-added
-
-    // BEGIN android-changed
-    // (Guarantee that the writer is always buffered.)
-    private BufferedWriter writer;
-    // END android-changed
+    private Writer writer;
 
     private boolean pending;
     private int auto;
@@ -52,6 +48,41 @@
     private boolean unicode;
     private String encoding;
 
+    private void append(char c) throws IOException {
+        if (mPos >= BUFFER_LEN) {
+            flushBuffer();
+        }
+        mText[mPos++] = c;
+    }
+
+    private void append(String str, int i, int length) throws IOException {
+        while (length > 0) {
+            if (mPos == BUFFER_LEN) {
+                flushBuffer();
+            }
+            int batch = BUFFER_LEN - mPos;
+            if (batch > length) {
+                batch = length;
+            }
+            str.getChars(i, i + batch, mText, mPos);
+            i += batch;
+            length -= batch;
+            mPos += batch;
+        }
+    }
+
+    private void append(String str) throws IOException {
+        append(str, 0, str.length());
+    }
+
+    private final void flushBuffer() throws IOException {
+        if(mPos > 0) {
+            writer.write(mText, 0, mPos);
+            writer.flush();
+            mPos = 0;
+        }
+    }
+
     private final void check(boolean close) throws IOException {
         if (!pending)
             return;
@@ -67,17 +98,16 @@
         indent[depth] = indent[depth - 1];
 
         for (int i = nspCounts[depth - 1]; i < nspCounts[depth]; i++) {
-            writer.write(' ');
-            writer.write("xmlns");
+            append(" xmlns");
             if (!nspStack[i * 2].isEmpty()) {
-                writer.write(':');
-                writer.write(nspStack[i * 2]);
+                append(':');
+                append(nspStack[i * 2]);
             }
             else if (getNamespace().isEmpty() && !nspStack[i * 2 + 1].isEmpty())
                 throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
-            writer.write("=\"");
+            append("=\"");
             writeEscaped(nspStack[i * 2 + 1], '"');
-            writer.write('"');
+            append('"');
         }
 
         if (nspCounts.length <= depth + 1) {
@@ -89,7 +119,11 @@
         nspCounts[depth + 1] = nspCounts[depth];
         //   nspCounts[depth + 2] = nspCounts[depth];
 
-        writer.write(close ? " />" : ">");
+        if (close) {
+            append(" />");
+        } else {
+            append('>');
+        }
     }
 
     private final void writeEscaped(String s, int quot) throws IOException {
@@ -100,22 +134,22 @@
                 case '\r':
                 case '\t':
                     if(quot == -1)
-                        writer.write(c);
+                        append(c);
                     else
-                        writer.write("&#"+((int) c)+';');
+                        append("&#"+((int) c)+';');
                     break;
                 case '&' :
-                    writer.write("&amp;");
+                    append("&amp;");
                     break;
                 case '>' :
-                    writer.write("&gt;");
+                    append("&gt;");
                     break;
                 case '<' :
-                    writer.write("&lt;");
+                    append("&lt;");
                     break;
                 default:
                     if (c == quot) {
-                        writer.write(c == '"' ? "&quot;" : "&apos;");
+                        append(c == '"' ? "&quot;" : "&apos;");
                         break;
                     }
                     // BEGIN android-changed: refuse to output invalid characters
@@ -128,9 +162,9 @@
                     boolean allowedInXml = (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
                     if (allowedInXml) {
                         if (unicode || c < 127) {
-                            writer.write(c);
+                            append(c);
                         } else {
-                            writer.write("&#" + ((int) c) + ";");
+                            append("&#" + ((int) c) + ";");
                         }
                     } else if (Character.isHighSurrogate(c) && i < s.length() - 1) {
                         writeSurrogate(c, s.charAt(i + 1));
@@ -157,9 +191,9 @@
         }*/
 
     public void docdecl(String dd) throws IOException {
-        writer.write("<!DOCTYPE");
-        writer.write(dd);
-        writer.write(">");
+        append("<!DOCTYPE");
+        append(dd);
+        append('>');
     }
 
     public void endDocument() throws IOException {
@@ -171,9 +205,9 @@
 
     public void entityRef(String name) throws IOException {
         check(false);
-        writer.write('&');
-        writer.write(name);
-        writer.write(';');
+        append('&');
+        append(name);
+        append(';');
     }
 
     public boolean getFeature(String name) {
@@ -301,14 +335,7 @@
     }
 
     public void setOutput(Writer writer) {
-        // BEGIN android-changed
-        // Guarantee that the writer is always buffered.
-        if (writer instanceof BufferedWriter) {
-            this.writer = (BufferedWriter) writer;
-        } else {
-            this.writer = new BufferedWriter(writer, WRITE_BUFFER_SIZE);
-        }
-        // END android-changed
+        this.writer = writer;
 
         // elementStack = new String[12]; //nsp/prefix/name
         //nspCounts = new int[4];
@@ -343,7 +370,7 @@
     }
 
     public void startDocument(String encoding, Boolean standalone) throws IOException {
-        writer.write("<?xml version='1.0' ");
+        append("<?xml version='1.0' ");
 
         if (encoding != null) {
             this.encoding = encoding;
@@ -353,18 +380,17 @@
         }
 
         if (this.encoding != null) {
-            writer.write("encoding='");
-            writer.write(this.encoding);
-            writer.write("' ");
+            append("encoding='");
+            append(this.encoding);
+            append("' ");
         }
 
         if (standalone != null) {
-            writer.write("standalone='");
-            writer.write(
-                standalone.booleanValue() ? "yes" : "no");
-            writer.write("' ");
+            append("standalone='");
+            append(standalone.booleanValue() ? "yes" : "no");
+            append("' ");
         }
-        writer.write("?>");
+        append("?>");
     }
 
     public XmlSerializer startTag(String namespace, String name)
@@ -375,9 +401,9 @@
         //            namespace = "";
 
         if (indent[depth]) {
-            writer.write("\r\n");
+            append("\r\n");
             for (int i = 0; i < depth; i++)
-                writer.write("  ");
+                append("  ");
         }
 
         int esp = depth * 3;
@@ -407,13 +433,13 @@
         elementStack[esp++] = prefix;
         elementStack[esp] = name;
 
-        writer.write('<');
+        append('<');
         if (!prefix.isEmpty()) {
-            writer.write(prefix);
-            writer.write(':');
+            append(prefix);
+            append(':');
         }
 
-        writer.write(name);
+        append(name);
 
         pending = true;
 
@@ -457,24 +483,24 @@
                 }
                 */
 
-        writer.write(' ');
+        append(' ');
         if (!prefix.isEmpty()) {
-            writer.write(prefix);
-            writer.write(':');
+            append(prefix);
+            append(':');
         }
-        writer.write(name);
-        writer.write('=');
+        append(name);
+        append('=');
         char q = value.indexOf('"') == -1 ? '"' : '\'';
-        writer.write(q);
+        append(q);
         writeEscaped(value, q);
-        writer.write(q);
+        append(q);
 
         return this;
     }
 
     public void flush() throws IOException {
         check(false);
-        writer.flush();
+        flushBuffer();
     }
     /*
         public void close() throws IOException {
@@ -503,19 +529,19 @@
         }
         else {
             if (indent[depth + 1]) {
-                writer.write("\r\n");
+                append("\r\n");
                 for (int i = 0; i < depth; i++)
-                    writer.write("  ");
+                    append("  ");
             }
 
-            writer.write("</");
+            append("</");
             String prefix = elementStack[depth * 3 + 1];
             if (!prefix.isEmpty()) {
-                writer.write(prefix);
-                writer.write(':');
+                append(prefix);
+                append(':');
             }
-            writer.write(name);
-            writer.write('>');
+            append(name);
+            append('>');
         }
 
         nspCounts[depth + 1] = nspCounts[depth];
@@ -552,24 +578,24 @@
         // BEGIN android-changed: ]]> is not allowed within a CDATA,
         // so break and start a new one when necessary.
         data = data.replace("]]>", "]]]]><![CDATA[>");
-        writer.write("<![CDATA[");
+        append("<![CDATA[");
         for (int i = 0; i < data.length(); ++i) {
             char ch = data.charAt(i);
             boolean allowedInCdata = (ch >= 0x20 && ch <= 0xd7ff) ||
                     (ch == '\t' || ch == '\n' || ch == '\r') ||
                     (ch >= 0xe000 && ch <= 0xfffd);
             if (allowedInCdata) {
-                writer.write(ch);
+                append(ch);
             } else if (Character.isHighSurrogate(ch) && i < data.length() - 1) {
                 // Character entities aren't valid in CDATA, so break out for this.
-                writer.write("]]>");
+                append("]]>");
                 writeSurrogate(ch, data.charAt(++i));
-                writer.write("<![CDATA[");
+                append("<![CDATA[");
             } else {
                 reportInvalidCharacter(ch);
             }
         }
-        writer.write("]]>");
+        append("]]>");
         // END android-changed
     }
 
@@ -583,22 +609,22 @@
         // seems likely to upset anything expecting modified UTF-8 rather than "real" UTF-8. It seems more
         // conservative in a Java environment to use an entity reference instead.
         int codePoint = Character.toCodePoint(high, low);
-        writer.write("&#" + codePoint + ";");
+        append("&#" + codePoint + ";");
     }
     // END android-added
 
     public void comment(String comment) throws IOException {
         check(false);
-        writer.write("<!--");
-        writer.write(comment);
-        writer.write("-->");
+        append("<!--");
+        append(comment);
+        append("-->");
     }
 
     public void processingInstruction(String pi)
         throws IOException {
         check(false);
-        writer.write("<?");
-        writer.write(pi);
-        writer.write("?>");
+        append("<?");
+        append(pi);
+        append("?>");
     }
 }
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