Integrate luni module (but not tests) to Harmony r772995.

Notable changes
     - Stripped "@since Android 1.0" from many files. Most files
       are now 100% the same in Dalvik and Harmony.
     - AbstractStringBuilder.reverse() supports surrogates
     - AbstractStringBuilder shares less to waste less memory
     - Bitset optimized
     - BufferedInputStream changed to support unsynchronized close()
     - BufferedOutputStream does flushInternal
     - BufferedReader supports EBCDIC NEL
     - Collections.synchronizedList().indexOf() does a copy for more concurrency
     - Classes in nio module changed: DatagramChannelImpl, SocketChannelImpl
       and ServerSocketChannelImpl (these depend on internal APIs changed in
       this update)
     - DataInputStream/DataOutputStream now use a small buffer to limit the
       number of times the underlying stream is accessed
     - Date now has a minutes offset, more efficient toString()
     - ExposedByteArrayInputStream: new internal class
     - DeleteOnExit moved to top-level class
     - FileDescriptor.isValid() now non-native
     - Float, Double lessThan optimized (fix for compare(-0.0F, 0.0F) still pending)
     - FileURLConnection now guesses content types from streams
     - HashMap iterator changes
     - Hashtable iterator changes
     - INetworkSystem
       - removes bind2(), createMulticastSocket, sendStream(),
       - renames createSocket to createStreamSocket
     - JarURLConnection rewritten
     - LinkedHashMap: new iterator
     - Locale, Currency, TimeZone: now use ICU in Harmony, plain Java in Dalvik
     - ObjectInputStream: Accessor objects in Harmony, direct native in Dalvik
     - ProxyClassFile - many changes
     - String - optimized ascii for toLowerCase, toUpperCase, compare
     - Timer - rewritten
     - TreeMap - rewritten
     - URLClassLoader - new
     - URLConnection - new guessContentTypeFromStream(), uses org.apache.harmony.awt.www.content
       to lookup content type handlers
diff --git a/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java b/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java
index eb2920e..d93c156 100644
--- a/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java
+++ b/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java
@@ -21,6 +21,7 @@
 import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.SideEffect;
 
 import java.math.BigInteger;
 import java.security.AlgorithmParameters;
@@ -221,6 +222,7 @@
         method = "finalize",
         args = {}
     )
+    @SideEffect("Causes OutOfMemoryError to test finalization")
     public void test_finalize () {
         Mock_ExemptionMechanism mem = new Mock_ExemptionMechanism(null, null, "Name");
         assertNotNull(mem);
diff --git a/luni-kernel/src/main/java/java/lang/Class.java b/luni-kernel/src/main/java/java/lang/Class.java
index 70ae3c1..6adf4db 100644
--- a/luni-kernel/src/main/java/java/lang/Class.java
+++ b/luni-kernel/src/main/java/java/lang/Class.java
@@ -440,7 +440,8 @@
      * @see ClassLoader#isSystemClassLoader()
      */
     ClassLoader getClassLoaderImpl() {
-        return getClassLoader(this);
+        ClassLoader loader = getClassLoader(this);
+        return loader == null ? BootClassLoader.getInstance() : loader;
     }
 
     /*
diff --git a/luni-kernel/src/main/java/java/lang/Thread.java b/luni-kernel/src/main/java/java/lang/Thread.java
index 89d7ed6..484c258 100644
--- a/luni-kernel/src/main/java/java/lang/Thread.java
+++ b/luni-kernel/src/main/java/java/lang/Thread.java
@@ -79,10 +79,10 @@
     private static class ParkState {
         /** park state indicating unparked */
         private static final int UNPARKED = 1;
-    
+
         /** park state indicating preemptively unparked */
         private static final int PREEMPTIVELY_UNPARKED = 2;
-    
+
         /** park state indicating parked */
         private static final int PARKED = 3;
     }
@@ -122,21 +122,21 @@
 
     /**
      * The maximum priority value allowed for a thread.
-     * 
+     *
      * @since Android 1.0
      */
     public final static int MAX_PRIORITY = 10;
 
     /**
      * The minimum priority value allowed for a thread.
-     * 
+     *
      * @since Android 1.0
      */
     public final static int MIN_PRIORITY = 1;
 
     /**
      * The normal (default) priority value assigned to threads.
-     * 
+     *
      * @since Android 1.0
      */
     public final static int NORM_PRIORITY = 5;
@@ -200,7 +200,7 @@
 
     /** the park state of the thread */
     private int parkState = ParkState.UNPARKED;
-        
+
     /**
      * Constructs a new {@code Thread} with no {@code Runnable} object and a
      * newly generated name. The new {@code Thread} will belong to the same
@@ -208,7 +208,7 @@
      *
      * @see java.lang.ThreadGroup
      * @see java.lang.Runnable
-     * 
+     *
      * @since Android 1.0
      */
     public Thread() {
@@ -219,14 +219,14 @@
      * Constructs a new {@code Thread} with a {@code Runnable} object and a
      * newly generated name. The new {@code Thread} will belong to the same
      * {@code ThreadGroup} as the {@code Thread} calling this constructor.
-     * 
+     *
      * @param runnable
      *            a {@code Runnable} whose method <code>run</code> will be
      *            executed by the new {@code Thread}
      *
      * @see java.lang.ThreadGroup
      * @see java.lang.Runnable
-     * 
+     *
      * @since Android 1.0
      */
     public Thread(Runnable runnable) {
@@ -237,13 +237,13 @@
      * Constructs a new {@code Thread} with a {@code Runnable} object and name
      * provided. The new {@code Thread} will belong to the same {@code
      * ThreadGroup} as the {@code Thread} calling this constructor.
-     * 
+     *
      * @param runnable
      *            a {@code Runnable} whose method <code>run</code> will be
      *            executed by the new {@code Thread}
      * @param threadName
      *            the name for the {@code Thread} being created
-     * 
+     *
      * @see java.lang.ThreadGroup
      * @see java.lang.Runnable
      *
@@ -261,10 +261,10 @@
      * Constructs a new {@code Thread} with no {@code Runnable} object and the
      * name provided. The new {@code Thread} will belong to the same {@code
      * ThreadGroup} as the {@code Thread} calling this constructor.
-     * 
+     *
      * @param threadName
      *            the name for the {@code Thread} being created
-     * 
+     *
      * @see java.lang.ThreadGroup
      * @see java.lang.Runnable
      *
@@ -282,7 +282,7 @@
      * Constructs a new {@code Thread} with a {@code Runnable} object and a
      * newly generated name. The new {@code Thread} will belong to the {@code
      * ThreadGroup} passed as parameter.
-     * 
+     *
      * @param group
      *            {@code ThreadGroup} to which the new {@code Thread} will
      *            belong
@@ -298,7 +298,7 @@
      * @see java.lang.Runnable
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public Thread(ThreadGroup group, Runnable runnable) {
@@ -308,7 +308,7 @@
     /**
      * Constructs a new {@code Thread} with a {@code Runnable} object, the given
      * name and belonging to the {@code ThreadGroup} passed as parameter.
-     * 
+     *
      * @param group
      *            ThreadGroup to which the new {@code Thread} will belong
      * @param runnable
@@ -325,7 +325,7 @@
      * @see java.lang.Runnable
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public Thread(ThreadGroup group, Runnable runnable, String threadName) {
@@ -339,7 +339,7 @@
     /**
      * Constructs a new {@code Thread} with no {@code Runnable} object, the
      * given name and belonging to the {@code ThreadGroup} passed as parameter.
-     * 
+     *
      * @param group
      *            {@code ThreadGroup} to which the new {@code Thread} will belong
      * @param threadName
@@ -353,7 +353,7 @@
      * @see java.lang.Runnable
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public Thread(ThreadGroup group, String threadName) {
@@ -367,7 +367,7 @@
     /**
      * Constructs a new {@code Thread} with a {@code Runnable} object, the given
      * name and belonging to the {@code ThreadGroup} passed as parameter.
-     * 
+     *
      * @param group
      *            {@code ThreadGroup} to which the new {@code Thread} will
      *            belong
@@ -389,7 +389,7 @@
      * @see java.lang.Runnable
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
@@ -528,9 +528,9 @@
     /**
      * Returns the number of active {@code Thread}s in the running {@code
      * Thread}'s group and its subgroups.
-     * 
+     *
      * @return the number of {@code Thread}s
-     * 
+     *
      * @since Android 1.0
      */
     public static int activeCount() {
@@ -542,14 +542,14 @@
      * there's none installed, this method is a no-op. If there's a
      * SecurityManager installed, {@link SecurityManager#checkAccess(Thread)} is
      * called for that SecurityManager.
-     * 
+     *
      * @throws SecurityException
      *             if a SecurityManager is installed and it does not allow
      *             access to the Thread.
-     * 
+     *
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public final void checkAccess() {
@@ -564,12 +564,12 @@
 
     /**
      * Returns the number of stack frames in this thread.
-     * 
+     *
      * @return Number of stack frames
      * @deprecated The results of this call were never well defined. To make
      *             things worse, it would depend on whether the Thread was
      *             suspended or not, and suspend was deprecated too.
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -581,7 +581,7 @@
      * Returns the Thread of the caller, that is, the current Thread.
      *
      * @return the current Thread.
-     * 
+     *
      * @since Android 1.0
      */
     public static Thread currentThread() {
@@ -592,7 +592,7 @@
      * Destroys the receiver without any monitor cleanup.
      *
      * @deprecated Not implemented.
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -603,9 +603,9 @@
     /**
      * Prints to the standard error stream a text representation of the current
      * stack for this Thread.
-     * 
+     *
      * @see Throwable#printStackTrace()
-     * 
+     *
      * @since Android 1.0
      */
     public static void dumpStack() {
@@ -617,7 +617,7 @@
      * receiver - and subgroups - into the array <code>threads</code> passed as
      * parameter. If the array passed as parameter is too small no exception is
      * thrown - the extra elements are simply not copied.
-     * 
+     *
      * @param threads
      *            array into which the Threads will be copied
      * @return How many Threads were copied over
@@ -626,7 +626,7 @@
      *             {@link SecurityManager#checkAccess(Thread)}
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public static int enumerate(Thread[] threads) {
@@ -640,13 +640,13 @@
      * Returns the stack traces of all the currently live threads and puts them
      * into the given map.
      * </p>
-     * 
+     *
      * @return A Map of current Threads to StackTraceElement arrays.
      * @throws SecurityException
      *             if the current SecurityManager fails the
      *             {@link SecurityManager#checkPermission(java.security.Permission)}
      *             call.
-     * 
+     *
      * @since Android 1.0
      */
     public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
@@ -684,14 +684,14 @@
      * </ol>
      * are satisfied, a security check for
      * <code>RuntimePermission("getClassLoader")</code> is performed first.
-     * 
+     *
      * @return ClassLoader The context ClassLoader
      * @see java.lang.ClassLoader
      * @see #getContextClassLoader()
-     * 
+     *
      * @throws SecurityException
      *             if the aforementioned security check fails.
-     *             
+     *
      * @since Android 1.0
      */
     public ClassLoader getContextClassLoader() {
@@ -719,7 +719,7 @@
      *
      * @return an {@link UncaughtExceptionHandler} or <code>null</code> if
      *         none exists.
-     * 
+     *
      * @since Android 1.0
      */
     public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
@@ -731,9 +731,9 @@
      * generated on thread creation, is unique to the thread, and doesn't change
      * during the lifetime of the thread; the ID may be reused after the thread
      * has been terminated.
-     * 
+     *
      * @return the thread's ID.
-     * 
+     *
      * @since Android 1.0
      */
     public long getId() {
@@ -744,7 +744,7 @@
      * Returns the name of the Thread.
      *
      * @return the Thread's name
-     * 
+     *
      * @since Android 1.0
      */
     public final String getName() {
@@ -756,7 +756,7 @@
      *
      * @return the Thread's priority
      * @see Thread#setPriority
-     * 
+     *
      * @since Android 1.0
      */
     public final int getPriority() {
@@ -770,13 +770,13 @@
      * The <code>RuntimePermission("getStackTrace")</code> is checked before
      * returning a result.
      * </p>
-     * 
+     *
      * @return an array of StackTraceElements.
      * @throws SecurityException
      *             if the current SecurityManager fails the
      *             {@link SecurityManager#checkPermission(java.security.Permission)}
      *             call.
-     * 
+     *
      * @since Android 1.0
      */
     public StackTraceElement[] getStackTrace() {
@@ -792,9 +792,9 @@
     /**
      * Returns the current state of the Thread. This method is useful for
      * monitoring purposes.
-     * 
+     *
      * @return a {@link State} value.
-     * 
+     *
      * @since Android 1.0
      */
     public State getState() {
@@ -805,7 +805,7 @@
         // deletes the reference we won't run into a null reference later.
         VMThread thread = vmThread;
         if (thread != null) {
-            // If the Thread Object became invalid or was not yet started,  
+            // If the Thread Object became invalid or was not yet started,
             // getStatus() will return -1.
             int state = thread.getStatus();
             if(state != -1) {
@@ -814,12 +814,12 @@
         }
         return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW;
     }
-    
+
     /**
      * Returns the ThreadGroup to which this Thread belongs.
-     * 
+     *
      * @return the Thread's ThreadGroup
-     * 
+     *
      * @since Android 1.0
      */
     public final ThreadGroup getThreadGroup() {
@@ -835,9 +835,9 @@
      * Returns the thread's uncaught exception handler. If not explicitly set,
      * then the ThreadGroup's handler is returned. If the thread is terminated,
      * then <code>null</code> is returned.
-     * 
+     *
      * @return an {@link UncaughtExceptionHandler} instance or {@code null}.
-     * 
+     *
      * @since Android 1.0
      */
     public UncaughtExceptionHandler getUncaughtExceptionHandler() {
@@ -870,14 +870,14 @@
      * their interrupt status set and return immediately. They don't receive an
      * exception in this case.
      * <ul>
-     * 
+     *
      * @throws SecurityException
      *             if <code>checkAccess()</code> fails with a SecurityException
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
      * @see Thread#interrupted
      * @see Thread#isInterrupted
-     * 
+     *
      * @since Android 1.0
      */
     public void interrupt() {
@@ -898,12 +898,12 @@
      * <code>currentThread()</code>) has a pending interrupt request (<code>
      * true</code>) or not (<code>false</code>). It also has the side-effect of
      * clearing the flag.
-     * 
+     *
      * @return a <code>boolean</code> indicating the interrupt status
      * @see Thread#currentThread
      * @see Thread#interrupt
      * @see Thread#isInterrupted
-     * 
+     *
      * @since Android 1.0
      */
     public static boolean interrupted() {
@@ -915,10 +915,10 @@
      * still runs code (hasn't died yet). Returns <code>false</code> either if
      * the receiver hasn't been started yet or if it has already started and run
      * to completion and died.
-     * 
+     *
      * @return a <code>boolean</code> indicating the lifeness of the Thread
      * @see Thread#start
-     * 
+     *
      * @since Android 1.0
      */
     public final boolean isAlive() {
@@ -936,7 +936,7 @@
      *
      * @return a <code>boolean</code> indicating whether the Thread is a daemon
      * @see Thread#setDaemon
-     * 
+     *
      * @since Android 1.0
      */
     public final boolean isDaemon() {
@@ -951,7 +951,7 @@
      * @return a <code>boolean</code> indicating the interrupt status
      * @see Thread#interrupt
      * @see Thread#interrupted
-     * 
+     *
      * @since Android 1.0
      */
     public boolean isInterrupted() {
@@ -971,7 +971,7 @@
      *         the receiver while it was in the <code>join()</code> call
      * @see Object#notifyAll
      * @see java.lang.ThreadDeath
-     * 
+     *
      * @since Android 1.0
      */
     public final void join() throws InterruptedException {
@@ -997,7 +997,7 @@
      *         the receiver while it was in the <code>join()</code> call
      * @see Object#notifyAll
      * @see java.lang.ThreadDeath
-     * 
+     *
      * @since Android 1.0
      */
     public final void join(long millis) throws InterruptedException {
@@ -1015,7 +1015,7 @@
      *         the receiver while it was in the <code>join()</code> call
      * @see Object#notifyAll
      * @see java.lang.ThreadDeath
-     * 
+     *
      * @since Android 1.0
      */
     public final void join(long millis, int nanos) throws InterruptedException {
@@ -1067,12 +1067,12 @@
      * suspended, or suspended and already resumed. If the receiver is
      * suspended, however, makes it resume to the point where it was when it was
      * suspended.
-     * 
+     *
      * @throws SecurityException
      *             if <code>checkAccess()</code> fails with a SecurityException
      * @see Thread#suspend()
      * @deprecated Used with deprecated method {@link Thread#suspend}
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -1090,7 +1090,7 @@
      * holds. If no Runnable is set, does nothing.
      *
      * @see Thread#start
-     * 
+     *
      * @since Android 1.0
      */
     public void run() {
@@ -1111,7 +1111,7 @@
      *         checkPermission call.
      * @see java.lang.ClassLoader
      * @see #getContextClassLoader()
-     * 
+     *
      * @since Android 1.0
      */
     public void setContextClassLoader(ClassLoader cl) {
@@ -1126,13 +1126,13 @@
     /**
      * Set if the receiver is a daemon Thread or not. This can only be done
      * before the Thread starts running.
-     * 
+     *
      * @param isDaemon
      *            indicates whether the Thread should be daemon or not
      * @throws SecurityException
      *             if <code>checkAccess()</code> fails with a SecurityException
      * @see Thread#isDaemon
-     * 
+     *
      * @since Android 1.0
      */
     public final void setDaemon(boolean isDaemon) {
@@ -1156,13 +1156,13 @@
      * The <code>RuntimePermission("setDefaultUncaughtExceptionHandler")</code>
      * is checked prior to setting the handler.
      * </p>
-     * 
+     *
      * @param handler
      *            The handler to set or <code>null</code>.
      * @throws SecurityException
      *             if the current SecurityManager fails the checkPermission
      *             call.
-     * 
+     *
      * @since Android 1.0
      */
     public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
@@ -1197,7 +1197,7 @@
      * @throws SecurityException if <code>checkAccess()</code> fails with a
      *         SecurityException
      * @see Thread#getName
-     * 
+     *
      * @since Android 1.0
      */
     public final void setName(String threadName) {
@@ -1220,7 +1220,7 @@
      * be the parameter that was passed - it will depend on the receiver's
      * ThreadGroup. The priority cannot be set to be higher than the receiver's
      * ThreadGroup's maxPriority().
-     * 
+     *
      * @param priority
      *            new priority for the Thread
      * @throws SecurityException
@@ -1229,7 +1229,7 @@
      *             if the new priority is greater than Thread.MAX_PRIORITY or
      *             less than Thread.MIN_PRIORITY
      * @see Thread#getPriority
-     * 
+     *
      * @since Android 1.0
      */
     public final void setPriority(int priority) {
@@ -1256,12 +1256,12 @@
      * Sets the uncaught exception handler. This handler is invoked in case this
      * Thread dies due to an unhandled exception.
      * </p>
-     * 
+     *
      * @param handler
      *            The handler to set or <code>null</code>.
      * @throws SecurityException
      *             if the current SecurityManager fails the checkAccess call.
-     * 
+     *
      * @since Android 1.0
      */
     public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
@@ -1274,14 +1274,14 @@
      * Causes the thread which sent this message to sleep for the given interval
      * of time (given in milliseconds). The precision is not guaranteed - the
      * Thread may sleep more or less than requested.
-     * 
+     *
      * @param time
      *            The time to sleep in milliseconds.
      * @throws InterruptedException
      *             if <code>interrupt()</code> was called for this Thread while
      *             it was sleeping
      * @see Thread#interrupt()
-     * 
+     *
      * @since Android 1.0
      */
     public static void sleep(long time) throws InterruptedException {
@@ -1292,7 +1292,7 @@
      * Causes the thread which sent this message to sleep for the given interval
      * of time (given in milliseconds and nanoseconds). The precision is not
      * guaranteed - the Thread may sleep more or less than requested.
-     * 
+     *
      * @param millis
      *            The time to sleep in milliseconds.
      * @param nanos
@@ -1301,7 +1301,7 @@
      *             if <code>interrupt()</code> was called for this Thread while
      *             it was sleeping
      * @see Thread#interrupt()
-     * 
+     *
      * @since Android 1.0
      */
     public static void sleep(long millis, int nanos) throws InterruptedException {
@@ -1314,9 +1314,9 @@
      * Thread calling <code>start()</code>).
      *
      * @throws IllegalThreadStateException if the Thread has been started before
-     * 
+     *
      * @see Thread#run
-     * 
+     *
      * @since Android 1.0
      */
     public synchronized void start() {
@@ -1338,7 +1338,7 @@
      *         SecurityException
      * @deprecated because stopping a thread in this manner is unsafe and can
      * leave your application and the VM in an unpredictable state.
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -1359,7 +1359,7 @@
      *         <code>null</code>
      * @deprecated because stopping a thread in this manner is unsafe and can
      * leave your application and the VM in an unpredictable state.
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -1388,12 +1388,12 @@
      * resume()</code> is sent to it. Suspend requests are not queued, which
      * means that N requests are equivalent to just one - only one resume
      * request is needed in this case.
-     * 
+     *
      * @throws SecurityException
      *             if <code>checkAccess()</code> fails with a SecurityException
      * @see Thread#resume()
      * @deprecated May cause deadlocks.
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -1409,9 +1409,9 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * Thread. It includes the Thread's name, priority, and group name.
-     * 
+     *
      * @return a printable representation for the receiver.
-     * 
+     *
      * @since Android 1.0
      */
     @Override
@@ -1422,7 +1422,7 @@
     /**
      * Causes the calling Thread to yield execution time to another Thread that
      * is ready to run. The actual scheduling is implementation-dependent.
-     * 
+     *
      * @since Android 1.0
      */
     public static void yield() {
@@ -1436,7 +1436,7 @@
      * @param object the object to test for the monitor lock
      * @return true if the current thread has a monitor lock on the specified
      *         object; false otherwise
-     *         
+     *
      * @since Android 1.0
      */
     public static boolean holdsLock(Object object) {
@@ -1448,7 +1448,7 @@
      * terminated by an uncaught exception. Upon such termination, the handler
      * is notified of the terminating thread and causal exception. If there is
      * no explicit handler set then the thread's group is the default handler.
-     * 
+     *
      * @since Android 1.0
      */
     public static interface UncaughtExceptionHandler {
@@ -1459,7 +1459,7 @@
          *
          * @param thread the thread that has an uncaught exception
          * @param ex the exception that was thrown
-         * 
+         *
          * @since Android 1.0
          */
         void uncaughtException(Thread thread, Throwable ex);
@@ -1482,7 +1482,7 @@
             parkState = ParkState.PREEMPTIVELY_UNPARKED;
             return;
         }
-        
+
         synchronized (vmt) {
             switch (parkState) {
                 case ParkState.PREEMPTIVELY_UNPARKED: {
@@ -1506,12 +1506,12 @@
             }
         }
     }
-    
+
     /**
      * Implementation of <code>parkFor()</code>. See {@link LangAccessImpl}.
      * This method must only be called when <code>this</code> is the current
      * thread.
-     * 
+     *
      * @param nanos number of nanoseconds to park for
      */
     /*package*/ void parkFor(long nanos) {
@@ -1521,7 +1521,7 @@
             // Running threads should always have an associated vmThread.
             throw new AssertionError();
         }
-        
+
         synchronized (vmt) {
             switch (parkState) {
                 case ParkState.PREEMPTIVELY_UNPARKED: {
@@ -1545,7 +1545,7 @@
                          */
                         if (parkState == ParkState.PARKED) {
                             parkState = ParkState.UNPARKED;
-                        }                            
+                        }
                     }
                     break;
                 }
@@ -1553,7 +1553,7 @@
                     throw new AssertionError(
                             "shouldn't happen: attempt to repark");
                 }
-            }       
+            }
         }
     }
 
@@ -1561,7 +1561,7 @@
      * Implementation of <code>parkUntil()</code>. See {@link LangAccessImpl}.
      * This method must only be called when <code>this</code> is the current
      * thread.
-     * 
+     *
      * @param time absolute milliseconds since the epoch to park until
      */
     /*package*/ void parkUntil(long time) {
@@ -1571,7 +1571,7 @@
             // Running threads should always have an associated vmThread.
             throw new AssertionError();
         }
-        
+
         synchronized (vmt) {
             /*
              * Note: This conflates the two time bases of "wall clock"
diff --git a/luni/src/main/java/java/io/BufferedInputStream.java b/luni/src/main/java/java/io/BufferedInputStream.java
index 0b9afc3..22379dd 100644
--- a/luni/src/main/java/java/io/BufferedInputStream.java
+++ b/luni/src/main/java/java/io/BufferedInputStream.java
@@ -30,68 +30,49 @@
  * drawback is that some extra space is required to hold the buffer and that
  * copying takes place when filling that buffer, but this is usually outweighed
  * by the performance benefits.
- * 
+ *
  * <p/>A typical application pattern for the class looks like this:<p/>
- * 
+ *
  * <pre>
  * BufferedInputStream buf = new BufferedInputStream(new FileInputStream(&quot;file.java&quot;));
  * </pre>
- * 
+ *
  * @see BufferedOutputStream
- * 
- * @since Android 1.0
  */
 public class BufferedInputStream extends FilterInputStream {
-    // BEGIN android-changed
-    // The address of the buffer should not be cached in a register.
-    // This was changed to be more close to the RI.
     /**
      * The buffer containing the current bytes read from the target InputStream.
-     * 
-     * @since Android 1.0
      */
     protected volatile byte[] buf;
-    // END android-changed
 
     /**
      * The total number of bytes inside the byte array {@code buf}.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
     /**
      * The current limit, which when passed, invalidates the current mark.
-     * 
-     * @since Android 1.0
      */
     protected int marklimit;
 
     /**
      * The currently marked position. -1 indicates no mark has been set or the
      * mark has been invalidated.
-     * 
-     * @since Android 1.0
      */
     protected int markpos = -1;
 
     /**
      * The current position within the byte array {@code buf}.
-     * 
-     * @since Android 1.0
      */
     protected int pos;
 
-    private boolean closed = false;
-
     /**
      * Constructs a new {@code BufferedInputStream} on the {@link InputStream}
      * {@code in}. The default buffer size (8 KB) is allocated and all reads
      * can now be filtered through this stream.
-     * 
+     *
      * @param in
      *            the InputStream the buffer reads from.
-     * @since Android 1.0
      */
     public BufferedInputStream(InputStream in) {
         super(in);
@@ -116,14 +97,13 @@
      * Constructs a new {@code BufferedInputStream} on the {@link InputStream}
      * {@code in}. The buffer size is specified by the parameter {@code size}
      * and all reads are now filtered through this stream.
-     * 
+     *
      * @param in
      *            the input stream the buffer reads from.
      * @param size
      *            the size of buffer to allocate.
      * @throws IllegalArgumentException
      *             if {@code size < 0}.
-     * @since Android 1.0
      */
     public BufferedInputStream(InputStream in, int size) {
         super(in);
@@ -138,43 +118,43 @@
      * Returns the number of bytes that are available before this stream will
      * block. This method returns the number of bytes available in the buffer
      * plus those available in the source stream.
-     * 
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if this stream is closed.
-     * @since Android 1.0
      */
     @Override
     public synchronized int available() throws IOException {
-        if (buf == null) {
+        InputStream localIn = in; // 'in' could be invalidated by close()
+        if (buf == null || localIn == null) {
             // K0059=Stream is closed
             throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
-        return count - pos + in.available();
+        return count - pos + localIn.available();
     }
 
     /**
      * Closes this stream. The source stream is closed and any resources
      * associated with it are released.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
-    public synchronized void close() throws IOException {
-        if (null != in) {
-            super.close();
-            in = null;
-        }
+    public void close() throws IOException {
         buf = null;
-        closed = true;
+        InputStream localIn = in;
+        in = null;
+        if (localIn != null) {
+            localIn.close();
+        }
     }
 
-    private int fillbuf() throws IOException {
+    private int fillbuf(InputStream localIn, byte[] localBuf)
+            throws IOException {
         if (markpos == -1 || (pos - markpos >= marklimit)) {
             /* Mark position not set or exceeded readlimit */
-            int result = in.read(buf);
+            int result = localIn.read(localBuf);
             if (result > 0) {
                 markpos = -1;
                 pos = 0;
@@ -182,22 +162,25 @@
             }
             return result;
         }
-        if (markpos == 0 && marklimit > buf.length) {
-            /* Increase buffer size to accomodate the readlimit */
-            int newLength = buf.length * 2;
+        if (markpos == 0 && marklimit > localBuf.length) {
+            /* Increase buffer size to accommodate the readlimit */
+            int newLength = localBuf.length * 2;
             if (newLength > marklimit) {
                 newLength = marklimit;
             }
             byte[] newbuf = new byte[newLength];
-            System.arraycopy(buf, 0, newbuf, 0, buf.length);
-            buf = newbuf;
+            System.arraycopy(localBuf, 0, newbuf, 0, localBuf.length);
+            // Reassign buf, which will invalidate any local references
+            // FIXME: what if buf was null?
+            localBuf = buf = newbuf;
         } else if (markpos > 0) {
-            System.arraycopy(buf, markpos, buf, 0, buf.length - markpos);
+            System.arraycopy(localBuf, markpos, localBuf, 0, localBuf.length
+                    - markpos);
         }
         /* Set the new position and mark position */
         pos -= markpos;
         count = markpos = 0;
-        int bytesread = in.read(buf, pos, buf.length - pos);
+        int bytesread = localIn.read(localBuf, pos, localBuf.length - pos);
         count = bytesread <= 0 ? pos : pos + bytesread;
         return bytesread;
     }
@@ -209,12 +192,11 @@
      * position if {@code readlimit} has not been surpassed. The underlying
      * buffer may be increased in size to allow {@code readlimit} number of
      * bytes to be supported.
-     * 
+     *
      * @param readlimit
      *            the number of bytes that can be read before the mark is
      *            invalidated.
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public synchronized void mark(int readlimit) {
@@ -225,11 +207,10 @@
     /**
      * Indicates whether {@code BufferedInputStream} supports the {@code mark()}
      * and {@code reset()} methods.
-     * 
+     *
      * @return {@code true} for BufferedInputStreams.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -241,28 +222,39 @@
      * range from 0 to 255. Returns -1 if the end of the source string has been
      * reached. If the internal buffer does not contain any available bytes then
      * it is filled from the source stream and the first byte is returned.
-     * 
+     *
      * @return the byte read or -1 if the end of the source stream has been
      *         reached.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read() throws IOException {
-        if (in == null) {
+        // Use local refs since buf and in may be invalidated by an
+        // unsynchronized close()
+        byte[] localBuf = buf;
+        InputStream localIn = in;
+        if (localBuf == null || localIn == null) {
             // K0059=Stream is closed
             throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
 
         /* Are there buffered bytes available? */
-        if (pos >= count && fillbuf() == -1) {
+        if (pos >= count && fillbuf(localIn, localBuf) == -1) {
             return -1; /* no, fill buffer */
         }
+        // localBuf may have been invalidated by fillbuf
+        if (localBuf != buf) {
+            localBuf = buf;
+            if (localBuf == null) {
+                // K0059=Stream is closed
+                throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+            }
+        }
 
         /* Did filling the buffer fail with -1 (EOF)? */
         if (count - pos > 0) {
-            return buf[pos++] & 0xFF;
+            return localBuf[pos++] & 0xFF;
         }
         return -1;
     }
@@ -275,7 +267,7 @@
      * mark has not been set and the requested number of bytes is larger than
      * the receiver's buffer size, this implementation bypasses the buffer and
      * simply places the results directly into {@code buffer}.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -291,12 +283,14 @@
      * @throws IOException
      *             if the stream is already closed or another IOException
      *             occurs.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read(byte[] buffer, int offset, int length)
             throws IOException {
-        if (closed) {
+        // Use local ref since buf may be invalidated by an unsynchronized
+        // close()
+        byte[] localBuf = buf;
+        if (localBuf == null) {
             // K0059=Stream is closed
             throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
@@ -316,7 +310,9 @@
         if (length == 0) {
             return 0;
         }
-        if (null == buf) {
+        InputStream localIn = in;
+        if (localIn == null) {
+            // K0059=Stream is closed
             throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
 
@@ -324,9 +320,9 @@
         if (pos < count) {
             /* There are bytes available in the buffer. */
             int copylength = count - pos >= length ? length : count - pos;
-            System.arraycopy(buf, pos, buffer, offset, copylength);
+            System.arraycopy(localBuf, pos, buffer, offset, copylength);
             pos += copylength;
-            if (copylength == length || in.available() == 0) {
+            if (copylength == length || localIn.available() == 0) {
                 return copylength;
             }
             offset += copylength;
@@ -341,24 +337,33 @@
              * If we're not marked and the required size is greater than the
              * buffer, simply read the bytes directly bypassing the buffer.
              */
-            if (markpos == -1 && required >= buf.length) {
-                read = in.read(buffer, offset, required);
+            if (markpos == -1 && required >= localBuf.length) {
+                read = localIn.read(buffer, offset, required);
                 if (read == -1) {
                     return required == length ? -1 : length - required;
                 }
             } else {
-                if (fillbuf() == -1) {
+                if (fillbuf(localIn, localBuf) == -1) {
                     return required == length ? -1 : length - required;
                 }
+                // localBuf may have been invalidated by fillbuf
+                if (localBuf != buf) {
+                    localBuf = buf;
+                    if (localBuf == null) {
+                        // K0059=Stream is closed
+                        throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+                    }
+                }
+
                 read = count - pos >= required ? required : count - pos;
-                System.arraycopy(buf, pos, buffer, offset, read);
+                System.arraycopy(localBuf, pos, buffer, offset, read);
                 pos += read;
             }
             required -= read;
             if (required == 0) {
                 return length;
             }
-            if (in.available() == 0) {
+            if (localIn.available() == 0) {
                 return length - required;
             }
             offset += read;
@@ -367,13 +372,12 @@
 
     /**
      * Resets this stream to the last marked location.
-     * 
+     *
      * @throws IOException
      *             if this stream is closed, no mark has been set or the mark is
      *             no longer valid because more than {@code readlimit} bytes
      *             have been read since setting the mark.
      * @see #mark(int)
-     * @since Android 1.0
      */
     @Override
     public synchronized void reset() throws IOException {
@@ -383,7 +387,7 @@
          * so it is preferable to avoid loading up the whole big set of
          * messages just for these cases.
          */
-        if (closed) {
+        if (buf == null) {
             throw new IOException("Stream is closed");
         }
         if (-1 == markpos) {
@@ -397,24 +401,31 @@
      * Skips {@code amount} number of bytes in this stream. Subsequent
      * {@code read()}'s will not return these bytes unless {@code reset()} is
      * used.
-     * 
+     *
      * @param amount
      *            the number of bytes to skip. {@code skip} does nothing and
      *            returns 0 if {@code amount} is less than zero.
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public synchronized long skip(long amount) throws IOException {
-        if (null == in) {
+        // Use local refs since buf and in may be invalidated by an
+        // unsynchronized close()
+        byte[] localBuf = buf;
+        InputStream localIn = in;
+        if (localBuf == null) {
             // K0059=Stream is closed
             throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
         if (amount < 1) {
             return 0;
         }
+        if (localIn == null) {
+            // K0059=Stream is closed
+            throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+        }
 
         if (count - pos >= amount) {
             pos += amount;
@@ -425,7 +436,7 @@
 
         if (markpos != -1) {
             if (amount <= marklimit) {
-                if (fillbuf() == -1) {
+                if (fillbuf(localIn, localBuf) == -1) {
                     return read;
                 }
                 if (count - pos >= amount - read) {
@@ -437,9 +448,7 @@
                 pos = count;
                 return read;
             }
-            markpos = -1;
         }
-        return read + in.skip(amount - read);
+        return read + localIn.skip(amount - read);
     }
 }
-
diff --git a/luni/src/main/java/java/io/BufferedOutputStream.java b/luni/src/main/java/java/io/BufferedOutputStream.java
index 835d13f..6d52dee 100644
--- a/luni/src/main/java/java/io/BufferedOutputStream.java
+++ b/luni/src/main/java/java/io/BufferedOutputStream.java
@@ -30,40 +30,33 @@
  * drawback is that some extra space is required to hold the buffer and that
  * copying takes place when flushing that buffer, but this is usually outweighed
  * by the performance benefits.
- * 
+ *
  * <p/>A typical application pattern for the class looks like this:<p/>
- * 
+ *
  * <pre>
  * BufferedOutputStream buf = new BufferedOutputStream(new FileOutputStream(&quot;file.java&quot;));
  * </pre>
- * 
+ *
  * @see BufferedInputStream
- * 
- * @since Android 1.0
  */
 public class BufferedOutputStream extends FilterOutputStream {
     /**
      * The buffer containing the bytes to be written to the target stream.
-     * 
-     * @since Android 1.0
      */
     protected byte[] buf;
 
     /**
      * The total number of bytes inside the byte array {@code buf}.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
     /**
      * Constructs a new {@code BufferedOutputStream} on the {@link OutputStream}
      * {@code out}. The buffer size is set to the default value of 8 KB.
-     * 
+     *
      * @param out
      *            the {@code OutputStream} for which write operations are
      *            buffered.
-     * @since Android 1.0
      */
     public BufferedOutputStream(OutputStream out) {
         super(out);
@@ -87,14 +80,13 @@
     /**
      * Constructs a new {@code BufferedOutputStream} on the {@link OutputStream}
      * {@code out}. The buffer size is set to {@code size}.
-     * 
+     *
      * @param out
      *            the output stream for which write operations are buffered.
      * @param size
      *            the size of the buffer in bytes.
      * @throws IllegalArgumentException
      *             if {@code size <= 0}.
-     * @since Android 1.0
      */
     public BufferedOutputStream(OutputStream out, int size) {
         super(out);
@@ -108,17 +100,13 @@
     /**
      * Flushes this stream to ensure all pending data is written out to the
      * target stream. In addition, the target stream is flushed.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to flush this stream.
-     * @since Android 1.0
      */
     @Override
     public synchronized void flush() throws IOException {
-        if (count > 0) {
-            out.write(buf, 0, count);
-        }
-        count = 0;
+        flushInternal();
         out.flush();
     }
 
@@ -128,7 +116,7 @@
      * bytes, they are copied in. If not, the buffered bytes plus the bytes in
      * {@code buffer} are written to the target stream, the target is flushed,
      * and the buffer is cleared.
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @param offset
@@ -144,7 +132,8 @@
      *             if an error occurs attempting to write to this stream.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
+     * @throws ArrayIndexOutOfBoundsException
+     *             If offset or count is outside of bounds.
      */
     @Override
     public synchronized void write(byte[] buffer, int offset, int length)
@@ -153,6 +142,13 @@
             // K0047=buffer is null
             throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
         }
+
+        if (length >= buf.length) {
+            flushInternal();
+            out.write(buffer, offset, length);
+            return;
+        }
+
         // BEGIN android-changed
         // Exception priorities (in case of multiple errors) differ from
         // RI, but are spec-compliant.
@@ -163,32 +159,15 @@
             throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
         }
         // END android-changed
-        if (count == 0 && length >= buf.length) {
-            out.write(buffer, offset, length);
-            return;
+
+        // flush the internal buffer first if we have not enough space left
+        if (length >= (buf.length - count)) {
+            flushInternal();
         }
-        int available = buf.length - count;
-        if (length < available) {
-            available = length;
-        }
-        if (available > 0) {
-            System.arraycopy(buffer, offset, buf, count, available);
-            count += available;
-        }
-        if (count == buf.length) {
-            out.write(buf, 0, buf.length);
-            count = 0;
-            if (length > available) {
-                offset += available;
-                available = length - available;
-                if (available >= buf.length) {
-                    out.write(buffer, offset, available);
-                } else {
-                    System.arraycopy(buffer, offset, buf, count, available);
-                    count += available;
-                }
-            }
-        }
+
+        // the length is always less than (buf.length - count) here so arraycopy is safe
+        System.arraycopy(buffer, offset, buf, count, length);
+        count += length;
     }
 
     /**
@@ -197,12 +176,11 @@
      * copied into the buffer and the count incremented. Otherwise, the buffer
      * plus {@code oneByte} are written to the target stream, the target is
      * flushed, and the buffer is reset.
-     * 
+     *
      * @param oneByte
      *            the byte to be written.
      * @throws IOException
      *             if an error occurs attempting to write to this stream.
-     * @since Android 1.0
      */
     @Override
     public synchronized void write(int oneByte) throws IOException {
@@ -212,4 +190,14 @@
         }
         buf[count++] = (byte) oneByte;
     }
+
+    /**
+     * Flushes only internal buffer.
+     */
+    private void flushInternal() throws IOException {
+        if (count > 0) {
+            out.write(buf, 0, count);
+        }
+        count = 0;
+    }
 }
diff --git a/luni/src/main/java/java/io/BufferedReader.java b/luni/src/main/java/java/io/BufferedReader.java
index e82e538..875840c 100644
--- a/luni/src/main/java/java/io/BufferedReader.java
+++ b/luni/src/main/java/java/io/BufferedReader.java
@@ -30,16 +30,15 @@
  * some extra space is required to hold the buffer and that copying takes place
  * when filling that buffer, but this is usually outweighed by the performance
  * benefits.
- * 
+ *
  * <p/>A typical application pattern for the class looks like this:<p/>
- * 
+ *
  * <pre>
  * BufferedReader buf = new BufferedReader(new FileReader(&quot;file.java&quot;));
  * </pre>
- * 
+ *
  * @see BufferedWriter
- * 
- * @since Android 1.0
+ * @since 1.1
  */
 public class BufferedReader extends Reader {
 
@@ -58,10 +57,9 @@
     /**
      * Constructs a new BufferedReader on the Reader {@code in}. The
      * buffer gets the default size (8 KB).
-     * 
+     *
      * @param in
      *            the Reader that is buffered.
-     * @since Android 1.0
      */
     public BufferedReader(Reader in) {
         super(in);
@@ -87,14 +85,13 @@
     /**
      * Constructs a new BufferedReader on the Reader {@code in}. The buffer
      * size is specified by the parameter {@code size}.
-     * 
+     *
      * @param in
      *            the Reader that is buffered.
      * @param size
      *            the size of the buffer to allocate.
      * @throws IllegalArgumentException
      *             if {@code size <= 0}.
-     * @since Android 1.0
      */
     public BufferedReader(Reader in, int size) {
         super(in);
@@ -109,10 +106,9 @@
      * Closes this reader. This implementation closes the buffered source reader
      * and releases the buffer. Nothing is done if this reader has already been
      * closed.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this reader.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -158,7 +154,7 @@
 
     /**
      * Indicates whether or not this reader is closed.
-     * 
+     *
      * @return {@code true} if this reader is closed, {@code false}
      *         otherwise.
      */
@@ -171,7 +167,7 @@
      * indicates how many characters can be read before the mark is invalidated.
      * Calling {@code reset()} will reposition the reader back to the marked
      * position if {@code readlimit} has not been surpassed.
-     * 
+     *
      * @param readlimit
      *            the number of characters that can be read before the mark is
      *            invalidated.
@@ -181,7 +177,6 @@
      *             if an error occurs while setting a mark in this reader.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public void mark(int readlimit) throws IOException {
@@ -200,11 +195,10 @@
     /**
      * Indicates whether this reader supports the {@code mark()} and
      * {@code reset()} methods. This implementation returns {@code true}.
-     * 
+     *
      * @return {@code true} for {@code BufferedReader}.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -217,12 +211,11 @@
      * character from the buffer. If there are no characters available in the
      * buffer, it fills the buffer and then returns a character. It returns -1
      * if there are no more characters in the source reader.
-     * 
+     *
      * @return the character read or -1 if the end of the source reader has been
      *         reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -234,6 +227,7 @@
             if (pos < count || fillbuf() != -1) {
                 return buf[pos++];
             }
+            markpos = -1;
             return -1;
         }
     }
@@ -246,7 +240,7 @@
      * has not been set and the requested number of characters is larger than
      * this readers buffer size, BufferedReader bypasses the buffer and simply
      * places the results directly into {@code buffer}.
-     * 
+     *
      * @param buffer
      *            the character array to store the characters read.
      * @param offset
@@ -263,7 +257,6 @@
      *             {@code buffer}.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buffer, int offset, int length) throws IOException {
@@ -336,13 +329,13 @@
      * Returns the next line of text available from this reader. A line is
      * represented by zero or more characters followed by {@code '\n'},
      * {@code '\r'}, {@code "\r\n"} or the end of the reader. The string does
-     * not include the newline sequence.
-     * 
+     * not include the newline sequence. In EBCDIC systems, a new line can also
+     * be represented by the {@code &#92;u0085} (NEL) character.
+     *
      * @return the contents of the line or {@code null} if no characters were
      *         read before the end of the reader has been reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     public String readLine() throws IOException {
         synchronized (lock) {
@@ -355,7 +348,10 @@
             }
             for (int charPos = pos; charPos < count; charPos++) {
                 char ch = buf[charPos];
-                if (ch > '\r') {
+                // BEGIN android-note
+                // a switch statement may be more efficient
+                // END android-note
+                if ((ch > '\r') && (ch != '\u0085')) {
                     continue;
                 }
                 if (ch == '\n') {
@@ -370,6 +366,11 @@
                         pos++;
                     }
                     return res;
+                } else if (ch == '\u0085') {
+                    /* Also handle the EBCDIC NEL character */
+                    String res = new String(buf, pos, charPos - pos);
+                    pos = charPos + 1;
+                    return res;
                 }
             }
 
@@ -393,8 +394,11 @@
                     }
                 }
                 for (int charPos = pos; charPos < count; charPos++) {
+                    // BEGIN android-note
+                    // use a local variable for buf[charPos] and a switch statement
+                    // END android-note
                     if (eol == '\0') {
-                        if ((buf[charPos] == '\n' || buf[charPos] == '\r')) {
+                        if ((buf[charPos] == '\n' || buf[charPos] == '\r') || (buf[charPos] == '\u0085')) {
                             eol = buf[charPos];
                         }
                     } else if (eol == '\r' && (buf[charPos] == '\n')) {
@@ -424,7 +428,7 @@
 
     /**
      * Indicates whether this reader is ready to be read without blocking.
-     * 
+     *
      * @return {@code true} if this reader will not block when {@code read} is
      *         called, {@code false} if unknown or blocking will occur.
      * @throws IOException
@@ -432,7 +436,6 @@
      * @see #read()
      * @see #read(char[], int, int)
      * @see #readLine()
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -448,12 +451,11 @@
      * Resets this reader's position to the last {@code mark()} location.
      * Invocations of {@code read()} and {@code skip()} will occur from this new
      * location.
-     * 
+     *
      * @throws IOException
      *             if this reader is closed or no mark has been set.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -473,7 +475,7 @@
      * {@code read()}s will not return these characters unless {@code reset()}
      * is used. Skipping characters may invalidate a mark if {@code readlimit}
      * is surpassed.
-     * 
+     *
      * @param amount
      *            the maximum number of characters to skip.
      * @return the number of characters actually skipped.
@@ -484,7 +486,6 @@
      * @see #mark(int)
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public long skip(long amount) throws IOException {
diff --git a/luni/src/main/java/java/io/BufferedWriter.java b/luni/src/main/java/java/io/BufferedWriter.java
index 761b9c5..86949fa 100644
--- a/luni/src/main/java/java/io/BufferedWriter.java
+++ b/luni/src/main/java/java/io/BufferedWriter.java
@@ -33,16 +33,14 @@
  * some extra space is required to hold the buffer and that copying takes place
  * when filling that buffer, but this is usually outweighed by the performance
  * benefits.
- * 
+ *
  * <p/>A typical application pattern for the class looks like this:<p/>
- * 
+ *
  * <pre>
  * BufferedWriter buf = new BufferedWriter(new FileWriter(&quot;file.java&quot;));
  * </pre>
- * 
+ *
  * @see BufferedReader
- * 
- * @since Android 1.0
  */
 public class BufferedWriter extends Writer {
 
@@ -59,10 +57,9 @@
      * Constructs a new {@code BufferedWriter} with {@code out} as the writer
      * for which to buffer write operations. The buffer size is set to the
      * default value of 8 KB.
-     * 
+     *
      * @param out
      *            the writer for which character writing is buffered.
-     * @since Android 1.0
      */
     public BufferedWriter(Writer out) {
         super(out);
@@ -88,14 +85,13 @@
      * Constructs a new {@code BufferedWriter} with {@code out} as the writer
      * for which to buffer write operations. The buffer size is set to {@code
      * size}.
-     * 
+     *
      * @param out
      *            the writer for which character writing is buffered.
      * @param size
      *            the size of the buffer in bytes.
      * @throws IllegalArgumentException
      *             if {@code size <= 0}.
-     * @since Android 1.0
      */
     public BufferedWriter(Writer out, int size) {
         super(out);
@@ -110,16 +106,15 @@
      * Closes this writer. The contents of the buffer are flushed, the target
      * writer is closed, and the buffer is released. Only the first invocation
      * of close has any effect.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this writer.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
         synchronized (lock) {
             if (!isClosed()) {
-                flush();
+                flushInternal();
                 out.close();
                 buf = null;
                 out = null;
@@ -130,10 +125,9 @@
     /**
      * Flushes this writer. The contents of the buffer are committed to the
      * target writer and it is then flushed.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while flushing this writer.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -141,17 +135,24 @@
             if (isClosed()) {
                 throw new IOException(Msg.getString("K005d")); //$NON-NLS-1$
             }
-            if (pos > 0) {
-                out.write(buf, 0, pos);
-            }
-            pos = 0;
+            flushInternal();
             out.flush();
         }
     }
 
     /**
+     * Flushes the internal buffer.
+     */
+    private void flushInternal() throws IOException {
+        if (pos > 0) {
+            out.write(buf, 0, pos);
+        }
+        pos = 0;
+    }
+
+    /**
      * Indicates whether this writer is closed.
-     * 
+     *
      * @return {@code true} if this writer is closed, {@code false} otherwise.
      */
     private boolean isClosed() {
@@ -162,10 +163,9 @@
      * Writes a newline to this writer. A newline is determined by the System
      * property "line.separator". The target writer may or may not be flushed
      * when a newline is written.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to write to this writer.
-     * @since Android 1.0
      */
     public void newLine() throws IOException {
         write(lineSeparator, 0, lineSeparator.length());
@@ -176,7 +176,7 @@
      * {@code cbuf} to this writer. If {@code count} is greater than this
      * writer's buffer, then the buffer is flushed and the characters are
      * written directly to the target writer.
-     * 
+     *
      * @param cbuf
      *            the array containing characters to write.
      * @param offset
@@ -189,7 +189,6 @@
      *             {@code cbuf}.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] cbuf, int offset, int count) throws IOException {
@@ -243,12 +242,11 @@
      * Writes the character {@code oneChar} to this writer. If the buffer
      * gets full by writing this character, this writer is flushed. Only the
      * lower two bytes of the integer {@code oneChar} are written.
-     * 
+     *
      * @param oneChar
      *            the character to write.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) throws IOException {
@@ -270,7 +268,7 @@
      * then this writer is flushed and the remaining characters are written
      * directly to the target writer. If count is negative no characters are
      * written to the buffer. This differs from the behavior of the superclass.
-     * 
+     *
      * @param str
      *            the non-null String containing characters to write.
      * @param offset
@@ -283,7 +281,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code offset + count} is greater
      *             than the length of {@code str}.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int count) throws IOException {
diff --git a/luni/src/main/java/java/io/ByteArrayInputStream.java b/luni/src/main/java/java/io/ByteArrayInputStream.java
index 1564ca5..f0b7219 100644
--- a/luni/src/main/java/java/io/ByteArrayInputStream.java
+++ b/luni/src/main/java/java/io/ByteArrayInputStream.java
@@ -23,48 +23,38 @@
 
 /**
  * A specialized {@link InputStream } for reading the contents of a byte array.
- * 
+ *
  * @see ByteArrayOutputStream
- * 
- * @since Android 1.0
  */
 public class ByteArrayInputStream extends InputStream {
     /**
      * The {@code byte} array containing the bytes to stream over.
-     * 
-     * @since Android 1.0
      */
     protected byte[] buf;
 
     /**
      * The current position within the byte array.
-     * 
-     * @since Android 1.0
      */
     protected int pos;
 
     /**
-     * The current mark position.
-     * 
-     * @since Android 1.0
+     * The current mark position. Initially set to 0 or the <code>offset</code>
+     * parameter within the constructor.
      */
     protected int mark;
 
     /**
      * The total number of bytes initially available in the byte array
      * {@code buf}.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
     /**
      * Constructs a new {@code ByteArrayInputStream} on the byte array
      * {@code buf}.
-     * 
+     *
      * @param buf
      *            the byte array to stream over.
-     * @since Android 1.0
      */
     public ByteArrayInputStream(byte buf[]) {
         this.mark = 0;
@@ -76,14 +66,13 @@
      * Constructs a new {@code ByteArrayInputStream} on the byte array
      * {@code buf} with the initial position set to {@code offset} and the
      * number of bytes available set to {@code offset} + {@code length}.
-     * 
+     *
      * @param buf
      *            the byte array to stream over.
      * @param offset
      *            the initial position in {@code buf} to start streaming from.
      * @param length
      *            the number of bytes available for streaming.
-     * @since Android 1.0
      */
     public ByteArrayInputStream(byte[] buf, int offset, int length) {
         // BEGIN android-note
@@ -99,9 +88,8 @@
      * Returns the number of bytes that are available before this stream will
      * block. This method returns the number of bytes yet to be read from the
      * source byte array.
-     * 
+     *
      * @return the number of bytes available before blocking.
-     * @since Android 1.0
      */
     @Override
     public synchronized int available() {
@@ -110,10 +98,9 @@
 
     /**
      * Closes this stream and frees resources associated with this stream.
-     * 
+     *
      * @throws IOException
      *             if an I/O error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -124,12 +111,11 @@
      * Sets a mark position in this ByteArrayInputStream. The parameter
      * {@code readlimit} is ignored. Sending {@code reset()} will reposition the
      * stream back to the marked position.
-     * 
+     *
      * @param readlimit
      *            ignored.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public synchronized void mark(int readlimit) {
@@ -140,11 +126,10 @@
      * Indicates whether this stream supports the {@code mark()} and
      * {@code reset()} methods. Returns {@code true} since this class supports
      * these methods.
-     * 
+     *
      * @return always {@code true}.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -155,9 +140,8 @@
      * Reads a single byte from the source byte array and returns it as an
      * integer in the range from 0 to 255. Returns -1 if the end of the source
      * array has been reached.
-     * 
+     *
      * @return the byte read or -1 if the end of this stream has been reached.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read() {
@@ -168,7 +152,7 @@
      * Reads at most {@code len} bytes from this stream and stores
      * them in byte array {@code b} starting at {@code offset}. This
      * implementation reads bytes from the source byte array.
-     * 
+     *
      * @param b
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -183,8 +167,7 @@
      *             {@code offset + length} is greater than the size of
      *             {@code b}.
      * @throws NullPointerException
-     *             if {@code b} is null.
-     * @since Android 1.0
+     *             if {@code b} is {@code null}.
      */
     @Override
     public synchronized int read(byte[] b, int offset, int length) {
@@ -222,9 +205,8 @@
      * Resets this stream to the last marked location. This implementation
      * resets the position to either the marked position, the start position
      * supplied in the constructor or 0 if neither has been provided.
-     * 
+     *
      * @see #mark(int)
-     * @since Android 1.0
      */
     @Override
     public synchronized void reset() {
@@ -236,11 +218,10 @@
      * {@code read()}s will not return these bytes unless {@code reset()} is
      * used. This implementation skips {@code count} number of bytes in the
      * target stream. It does nothing and returns 0 if {@code n} is negative.
-     * 
+     *
      * @param n
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
-     * @since Android 1.0
      */
     @Override
     public synchronized long skip(long n) {
diff --git a/luni/src/main/java/java/io/ByteArrayOutputStream.java b/luni/src/main/java/java/io/ByteArrayOutputStream.java
index 8c6fa05..4d5a738 100644
--- a/luni/src/main/java/java/io/ByteArrayOutputStream.java
+++ b/luni/src/main/java/java/io/ByteArrayOutputStream.java
@@ -24,23 +24,17 @@
  * (internal) byte array. As bytes are written to this stream, the byte array
  * may be expanded to hold more bytes. When the writing is considered to be
  * finished, a copy of the byte array can be requested from the class.
- * 
+ *
  * @see ByteArrayInputStream
- * 
- * @since Android 1.0
  */
 public class ByteArrayOutputStream extends OutputStream {
     /**
      * The byte array containing the bytes written.
-     * 
-     * @since Android 1.0
      */
     protected byte[] buf;
 
     /**
      * The number of bytes written.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
@@ -48,8 +42,6 @@
      * Constructs a new ByteArrayOutputStream with a default size of 32 bytes.
      * If more than 32 bytes are written to this instance, the underlying byte
      * array will expand.
-     * 
-     * @since Android 1.0
      */
     public ByteArrayOutputStream() {
         super();
@@ -60,13 +52,12 @@
      * Constructs a new {@code ByteArrayOutputStream} with a default size of
      * {@code size} bytes. If more than {@code size} bytes are written to this
      * instance, the underlying byte array will expand.
-     * 
+     *
      * @param size
      *            initial size for the underlying byte array, must be
      *            non-negative.
      * @throws IllegalArgumentException
      *             if {@code size} < 0.
-     * @since Android 1.0
      */
     public ByteArrayOutputStream(int size) {
         super();
@@ -79,10 +70,9 @@
 
     /**
      * Closes this stream. This releases system resources used for this stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while attempting to close this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -109,8 +99,6 @@
      * Resets this stream to the beginning of the underlying byte array. All
      * subsequent writes will overwrite any bytes previously stored in this
      * stream.
-     * 
-     * @since Android 1.0
      */
     public synchronized void reset() {
         count = 0;
@@ -118,9 +106,8 @@
 
     /**
      * Returns the total number of bytes written to this stream so far.
-     * 
+     *
      * @return the number of bytes written to this stream.
-     * @since Android 1.0
      */
     public int size() {
         return count;
@@ -130,9 +117,8 @@
      * Returns the contents of this ByteArrayOutputStream as a byte array. Any
      * changes made to the receiver after returning will not be reflected in the
      * byte array returned to the caller.
-     * 
+     *
      * @return this stream's current contents as a byte array.
-     * @since Android 1.0
      */
     public synchronized byte[] toByteArray() {
         byte[] newArray = new byte[count];
@@ -144,9 +130,8 @@
      * Returns the contents of this ByteArrayOutputStream as a string. Any
      * changes made to the receiver after returning will not be reflected in the
      * string returned to the caller.
-     * 
+     *
      * @return this stream's current contents as a string.
-     * @since Android 1.0
      */
 
     @Override
@@ -161,13 +146,12 @@
      * {@code c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))}. This method is
      * deprecated and either {@link #toString()} or {@link #toString(String)}
      * should be used.
-     * 
+     *
      * @param hibyte
      *            the high byte of each resulting Unicode character.
      * @return this stream's current contents as a string with the high byte set
      *         to {@code hibyte}.
      * @deprecated Use {@link #toString()}.
-     * @since Android 1.0
      */
     @Deprecated
     public String toString(int hibyte) {
@@ -181,14 +165,13 @@
     /**
      * Returns the contents of this ByteArrayOutputStream as a string converted
      * according to the encoding declared in {@code enc}.
-     * 
+     *
      * @param enc
      *            a string representing the encoding to use when translating
      *            this stream to a string.
      * @return this stream's current contents as an encoded string.
      * @throws UnsupportedEncodingException
      *             if the provided encoding is not supported.
-     * @since Android 1.0
      */
     public String toString(String enc) throws UnsupportedEncodingException {
         return new String(buf, 0, count, enc);
@@ -197,18 +180,19 @@
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * offset {@code index} to this stream.
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @param offset
      *            the initial position in {@code buffer} to retrieve bytes.
      * @param len
      *            the number of bytes of {@code buffer} to write.
+     * @throws NullPointerException
+     *             if {@code buffer} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code len < 0}, or if
      *             {@code offset + len} is greater than the length of
      *             {@code buffer}.
-     * @since Android 1.0
      */
     @Override
     public synchronized void write(byte[] buffer, int offset, int len) {
@@ -239,28 +223,26 @@
     /**
      * Writes the specified byte {@code oneByte} to the OutputStream. Only the
      * low order byte of {@code oneByte} is written.
-     * 
+     *
      * @param oneByte
      *            the byte to be written.
-     * @since Android 1.0
      */
     @Override
     public synchronized void write(int oneByte) {
         if (count == buf.length) {
             expand(1);
         }
-        buf[count++] = (byte)oneByte;
+        buf[count++] = (byte) oneByte;
     }
 
     /**
      * Takes the contents of this stream and writes it to the output stream
      * {@code out}.
-     * 
+     *
      * @param out
      *            an OutputStream on which to write the contents of this stream.
      * @throws IOException
      *             if an error occurs while writing to {@code out}.
-     * @since Android 1.0
      */
     public synchronized void writeTo(OutputStream out) throws IOException {
         out.write(buf, 0, count);
diff --git a/luni/src/main/java/java/io/CharArrayReader.java b/luni/src/main/java/java/io/CharArrayReader.java
index 95a8826..d2757f6 100644
--- a/luni/src/main/java/java/io/CharArrayReader.java
+++ b/luni/src/main/java/java/io/CharArrayReader.java
@@ -21,37 +21,27 @@
 
 /**
  * A specialized {@link Reader} for reading the contents of a char array.
- * 
+ *
  * @see CharArrayWriter
- * 
- * @since Android 1.0
  */
 public class CharArrayReader extends Reader {
     /**
      * The buffer for characters.
-     * 
-     * @since Android 1.0 
      */
     protected char buf[];
 
     /**
      * The current buffer position.
-     * 
-     * @since Android 1.0 
      */
     protected int pos;
 
     /**
      * The current mark position.
-     * 
-     * @since Android 1.0
      */
     protected int markedPos = -1;
 
     /**
      * The ending index of the buffer.
-     *
-     * @since Android 1.0 
      */
     protected int count;
 
@@ -59,10 +49,9 @@
      * Constructs a CharArrayReader on the char array {@code buf}. The size of
      * the reader is set to the length of the buffer and the object to to read
      * from is set to {@code buf}.
-     * 
+     *
      * @param buf
      *            the char array from which to read.
-     * @since Android 1.0
      */
     public CharArrayReader(char[] buf) {
         super(buf);
@@ -74,7 +63,7 @@
      * Constructs a CharArrayReader on the char array {@code buf}. The size of
      * the reader is set to {@code length} and the start position from which to
      * read the buffer is set to {@code offset}.
-     * 
+     *
      * @param buf
      *            the char array from which to read.
      * @param offset
@@ -84,7 +73,6 @@
      * @throws IllegalArgumentException
      *             if {@code offset < 0} or {@code length < 0}, or if
      *             {@code offset} is greater than the size of {@code buf} .
-     * @since Android 1.0
      */
     public CharArrayReader(char[] buf, int offset, int length) {
         super(buf);
@@ -92,7 +80,7 @@
         // Exception priorities (in case of multiple errors) differ from
         // RI, but are spec-compliant.
         // made implicit null check explicit,
-        // removed redundant check, used (offset | length) < 0 instead of 
+        // removed redundant check, used (offset | length) < 0 instead of
         // (offset < 0) || (length < 0) to safe one operation
         if (buf == null) {
             throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
@@ -103,6 +91,7 @@
         // END android-changed
         this.buf = buf;
         this.pos = offset;
+        this.markedPos = offset;
 
         /* This is according to spec */
         this.count = this.pos + length < buf.length ? length : buf.length;
@@ -112,8 +101,6 @@
      * This method closes this CharArrayReader. Once it is closed, you can no
      * longer read from it. Only the first invocation of this method has any
      * effect.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void close() {
@@ -126,7 +113,7 @@
 
     /**
      * Indicates whether this reader is open.
-     * 
+     *
      * @return {@code true} if the reader is open, {@code false} otherwise.
      */
     private boolean isOpen() {
@@ -135,7 +122,7 @@
 
     /**
      * Indicates whether this reader is closed.
-     * 
+     *
      * @return {@code true} if the reader is closed, {@code false} otherwise.
      */
     private boolean isClosed() {
@@ -147,12 +134,11 @@
      * ignored for CharArrayReaders. Calling {@code reset()} will reposition the
      * reader back to the marked position provided the mark has not been
      * invalidated.
-     * 
+     *
      * @param readLimit
      *            ignored for CharArrayReaders.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public void mark(int readLimit) throws IOException {
@@ -167,11 +153,10 @@
     /**
      * Indicates whether this reader supports the {@code mark()} and
      * {@code reset()} methods.
-     * 
+     *
      * @return {@code true} for CharArrayReader.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -182,12 +167,11 @@
      * Reads a single character from this reader and returns it as an integer
      * with the two higher-order bytes set to 0. Returns -1 if no more
      * characters are available from this reader.
-     * 
+     *
      * @return the character read as an int or -1 if the end of the reader has
      *         been reached.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -207,7 +191,7 @@
      * stores them at {@code offset} in the character array {@code buf}.
      * Returns the number of characters actually read or -1 if the end of reader
      * was encountered.
-     * 
+     *
      * @param buffer
      *            the character array to store the characters read.
      * @param offset
@@ -223,7 +207,6 @@
      *             {@code buffer}.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buffer, int offset, int len) throws IOException {
@@ -264,12 +247,11 @@
      * {@code false} if this reader may or may not block when {@code read} is
      * called. The implementation in CharArrayReader always returns {@code true}
      * even when it has been closed.
-     * 
+     *
      * @return {@code true} if this reader will not block when {@code read} is
      *         called, {@code false} if unknown or blocking will occur.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -286,10 +268,9 @@
      * Invocations of {@code read()} and {@code skip()} will occur from this new
      * location. If this reader has not been marked, it is reset to the
      * beginning of the string.
-     * 
+     *
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -305,13 +286,12 @@
      * Skips {@code count} number of characters in this reader. Subsequent
      * {@code read()}s will not return these characters unless {@code reset()}
      * is used. This method does nothing and returns 0 if {@code n} is negative.
-     * 
+     *
      * @param n
      *            the number of characters to skip.
      * @return the number of characters actually skipped.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public long skip(long n) throws IOException {
diff --git a/luni/src/main/java/java/io/CharArrayWriter.java b/luni/src/main/java/java/io/CharArrayWriter.java
index 7e58b2b..6b3fa39 100644
--- a/luni/src/main/java/java/io/CharArrayWriter.java
+++ b/luni/src/main/java/java/io/CharArrayWriter.java
@@ -24,33 +24,25 @@
  * char array. As bytes are written to this writer, the char array may be
  * expanded to hold more characters. When the writing is considered to be
  * finished, a copy of the char array can be requested from the class.
- * 
+ *
  * @see CharArrayReader
- * 
- * @since Android 1.0
  */
 public class CharArrayWriter extends Writer {
 
     /**
      * The buffer for characters.
-     * 
-     * @since Android 1.0
      */
     protected char[] buf;
 
     /**
      * The ending index of the buffer.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
     /**
-     * Constructs a new CharArrayWriter which has a buffer allocated with the
-     * default size of 32 characters. This buffer is also used as the
+     * Constructs a new {@code CharArrayWriter} which has a buffer allocated
+     * with the default size of 32 characters. This buffer is also used as the
      * {@code lock} to synchronize access to this writer.
-     * 
-     * @since Android 1.0
      */
     public CharArrayWriter() {
         super();
@@ -59,15 +51,14 @@
     }
 
     /**
-     * Constructs a new CharArrayWriter which has a buffer allocated with the
-     * size of {@code initialSize} characters. The buffer is also used as the
-     * {@code lock} to synchronize access to this writer.
-     * 
+     * Constructs a new {@code CharArrayWriter} which has a buffer allocated
+     * with the size of {@code initialSize} characters. The buffer is also used
+     * as the {@code lock} to synchronize access to this writer.
+     *
      * @param initialSize
      *            the initial size of this CharArrayWriters buffer.
      * @throws IllegalArgumentException
      *             if {@code initialSize < 0}.
-     * @since Android 1.0
      */
     public CharArrayWriter(int initialSize) {
         super();
@@ -79,9 +70,7 @@
     }
 
     /**
-     * Closes this writer. The implementation in CharArrayWriter does nothing.
-     * 
-     * @since Android 1.0
+     * Closes this writer. The implementation in {@code CharArrayWriter} does nothing.
      */
     @Override
     public void close() {
@@ -94,15 +83,14 @@
             return;
         }
 
-        char[] newbuf = new char[buf.length + (2 * i)];
+        int newLen = Math.max(2 * buf.length, count + i);
+        char[] newbuf = new char[newLen];
         System.arraycopy(buf, 0, newbuf, 0, count);
         buf = newbuf;
     }
 
     /**
-     * Flushes this writer. The implementation in CharArrayWriter does nothing.
-     * 
-     * @since Android 1.0
+     * Flushes this writer. The implementation in {@code CharArrayWriter} does nothing.
      */
     @Override
     public void flush() {
@@ -113,8 +101,6 @@
      * Resets this writer. The current write position is reset to the beginning
      * of the buffer. All written characters are lost and the size of this
      * writer is set to 0.
-     * 
-     * @since Android 1.0
      */
     public void reset() {
         synchronized (lock) {
@@ -126,9 +112,8 @@
      * Returns the size of this writer, that is the number of characters it
      * stores. This number changes if this writer is reset or when more
      * characters are written to it.
-     * 
+     *
      * @return this CharArrayWriter's current size in characters.
-     * @since Android 1.0
      */
     public int size() {
         synchronized (lock) {
@@ -140,9 +125,8 @@
      * Returns the contents of the receiver as a char array. The array returned
      * is a copy and any modifications made to this writer after calling this
      * method are not reflected in the result.
-     * 
+     *
      * @return this CharArrayWriter's contents as a new char array.
-     * @since Android 1.0
      */
     public char[] toCharArray() {
         synchronized (lock) {
@@ -153,12 +137,11 @@
     }
 
     /**
-     * Returns the contents of this CharArrayWriter as a string. The string
-     * returned is a copy and any modifications made to this writer after
+     * Returns the contents of this {@code CharArrayWriter} as a string. The
+     * string returned is a copy and any modifications made to this writer after
      * calling this method are not reflected in the result.
-     * 
+     *
      * @return this CharArrayWriters contents as a new string.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -170,7 +153,7 @@
     /**
      * Writes {@code count} characters starting at {@code offset} in {@code c}
      * to this writer.
-     * 
+     *
      * @param c
      *            the non-null array containing characters to write.
      * @param offset
@@ -180,7 +163,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code len < 0}, or if
      *             {@code offset + len} is bigger than the size of {@code c}.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] c, int offset, int len) {
@@ -210,10 +192,9 @@
      * Writes the specified character {@code oneChar} to this writer.
      * This implementation writes the two low order bytes of the integer
      * {@code oneChar} to the buffer.
-     * 
+     *
      * @param oneChar
      *            the character to write.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) {
@@ -226,7 +207,7 @@
     /**
      * Writes {@code count} number of characters starting at {@code offset} from
      * the string {@code str} to this CharArrayWriter.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
      * @param offset
@@ -234,12 +215,11 @@
      * @param len
      *            the number of characters to retrieve and write.
      * @throws NullPointerException
-     *             if {@code str} is null.
+     *             if {@code str} is {@code null}.
      * @throws StringIndexOutOfBoundsException
      *             if {@code offset < 0} or {@code len < 0}, or if
      *             {@code offset + len} is bigger than the length of
      *             {@code str}.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int len) {
@@ -264,17 +244,16 @@
     }
 
     /**
-     * Writes the contents of this CharArrayWriter to another Writer. The output
-     * is all the characters that have been written to the receiver since the
-     * last reset or since it was created.
-     * 
+     * Writes the contents of this {@code CharArrayWriter} to another {@code
+     * Writer}. The output is all the characters that have been written to the
+     * receiver since the last reset or since it was created.
+     *
      * @param out
-     *            the non-null Writer on which to write the contents.
+     *            the non-null {@code Writer} on which to write the contents.
      * @throws NullPointerException
-     *             if {@code out} is null.
+     *             if {@code out} is {@code null}.
      * @throws IOException
      *             if an error occurs attempting to write out the contents.
-     * @since Android 1.0
      */
     public void writeTo(Writer out) throws IOException {
         synchronized (lock) {
@@ -283,13 +262,12 @@
     }
 
     /**
-     * Appends a char {@code c} to the CharArrayWriter. The method works the
-     * same way as {@code write(c)}.
-     * 
+     * Appends a char {@code c} to the {@code CharArrayWriter}. The method works
+     * the same way as {@code write(c)}.
+     *
      * @param c
      *            the character appended to the CharArrayWriter.
      * @return this CharArrayWriter.
-     * @since Android 1.0
      */
     @Override
     public CharArrayWriter append(char c) {
@@ -298,14 +276,14 @@
     }
 
     /**
-     * Appends a CharSequence {@code csq} to the CharArrayWriter. The method
+     * Appends a {@code CharSequence} to the {@code CharArrayWriter}. The method
      * works the same way as {@code write(csq.toString())}. If {@code csq} is
-     * null, then it will be substituted with the string "null".
-     * 
+     * {@code null}, then it will be substituted with the string {@code "null"}.
+     *
      * @param csq
-     *            the CharSequence appended to the CharArrayWriter, may be null.
+     *            the {@code CharSequence} appended to the {@code
+     *            CharArrayWriter}, may be {@code null}.
      * @return this CharArrayWriter.
-     * @since Android 1.0
      */
     @Override
     public CharArrayWriter append(CharSequence csq) {
@@ -318,26 +296,27 @@
     }
 
     /**
-     * Append a subsequence of a CharSequence {@code csq} to the
-     * CharArrayWriter. The first and last characters of the subsequence are
-     * specified by the parameters {@code start} and {@code end}. The
-     * CharArrayWriter.append({@code csq}) works the same way as
-     * {@code CharArrayWriter.write(csq.subSequence(start, end).toString)}. If
-     * {@code csq} is null, then it will be substituted with the string "null".
-     * 
+     * Append a subsequence of a {@code CharSequence} to the {@code
+     * CharArrayWriter}. The first and last characters of the subsequence are
+     * specified by the parameters {@code start} and {@code end}. A call to
+     * {@code CharArrayWriter.append(csq)} works the same way as {@code
+     * CharArrayWriter.write(csq.subSequence(start, end).toString)}. If {@code
+     * csq} is {@code null}, then it will be substituted with the string {@code
+     * "null"}.
+     *
      * @param csq
-     *            the CharSequence appended to the CharArrayWriter, may be null.
+     *            the {@code CharSequence} appended to the {@code
+     *            CharArrayWriter}, may be {@code null}.
      * @param start
-     *            the index of the first character in the CharSequence appended
-     *            to the CharArrayWriter.
+     *            the index of the first character in the {@code CharSequence}
+     *            appended to the {@code CharArrayWriter}.
      * @param end
-     *            the index of the character after the last one in the
-     *            CharSequence appended to the CharArrayWriter.
+     *            the index of the character after the last one in the {@code
+     *            CharSequence} appended to the {@code CharArrayWriter}.
      * @return this CharArrayWriter.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0}, {@code end < 0}, {@code start > end},
      *             or if {@code end} is greater than the length of {@code csq}.
-     * @since Android 1.0
      */
     @Override
     public CharArrayWriter append(CharSequence csq, int start, int end) {
diff --git a/luni/src/main/java/java/io/CharConversionException.java b/luni/src/main/java/java/io/CharConversionException.java
index 2247527..97dc186 100644
--- a/luni/src/main/java/java/io/CharConversionException.java
+++ b/luni/src/main/java/java/io/CharConversionException.java
@@ -19,8 +19,6 @@
 
 /**
  * The top level class for character conversion exceptions.
- * 
- * @since Android 1.0
  */
 public class CharConversionException extends IOException {
 
@@ -29,8 +27,6 @@
     /**
      * Constructs a new {@code CharConversionException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public CharConversionException() {
         super();
@@ -39,10 +35,9 @@
     /**
      * Constructs a new {@code CharConversionException} with its stack trace and
      * detail message filled in.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public CharConversionException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/Closeable.java b/luni/src/main/java/java/io/Closeable.java
index 015b39a..94b6bd8 100644
--- a/luni/src/main/java/java/io/Closeable.java
+++ b/luni/src/main/java/java/io/Closeable.java
@@ -21,18 +21,15 @@
  * are not used any longer. This usually includes all sorts of
  * {@link InputStream}s and {@link OutputStream}s. Calling the {@code close}
  * method releases resources that the object holds.
- * 
- * @since Android 1.0
  */
 public interface Closeable {
 
     /**
      * Closes the object and release any system resources it holds. If the
      * object has already been closed, then invoking this method has no effect.
-     * 
+     *
      * @throws IOException
      *             if any error occurs when closing the object.
-     * @since Android 1.0
      */
     public void close() throws IOException;
 }
\ No newline at end of file
diff --git a/luni/src/main/java/java/io/DataInput.java b/luni/src/main/java/java/io/DataInput.java
index a199d2f..02a28d9 100644
--- a/luni/src/main/java/java/io/DataInput.java
+++ b/luni/src/main/java/java/io/DataInput.java
@@ -23,13 +23,12 @@
  * {@link DataOutput}. Types that can be read include byte, 16-bit short, 32-bit
  * int, 32-bit float, 64-bit long, 64-bit double, byte strings, and MUTF-8
  * strings.
- *  
+ *
  * <h3>MUTF-8 (Modified UTF-8) Encoding</h3>
  * <p>
  * When encoding strings as UTF, implementations of {@code DataInput} and
  * {@code DataOutput} use a slightly modified form of UTF-8, hereafter referred
  * to as MUTF-8. This form is identical to standard UTF-8, except:
- * </p>
  * <ul>
  * <li>Only the one-, two-, and three-byte encodings are used.</li>
  * <li>Code points in the range <code>U+10000</code> &hellip;
@@ -42,12 +41,9 @@
  * further information about character encoding. MUTF-8 is actually closer to
  * the (relatively less well-known) encoding <a
  * href="http://www.unicode.org/reports/tr26/">CESU-8</a> than to UTF-8 per se.
- * </p>
- * 
+ *
  * @see DataInputStream
  * @see RandomAccessFile
- * 
- * @since Android 1.0
  */
 public interface DataInput {
     /**
@@ -59,7 +55,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeBoolean(boolean)
-     * @since Android 1.0
      */
     public abstract boolean readBoolean() throws IOException;
 
@@ -72,7 +67,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeByte(int)
-     * @since Android 1.0
      */
     public abstract byte readByte() throws IOException;
 
@@ -85,7 +79,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeChar(int)
-     * @since Android 1.0
      */
     public abstract char readChar() throws IOException;
 
@@ -98,7 +91,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeDouble(double)
-     * @since Android 1.0
      */
     public abstract double readDouble() throws IOException;
 
@@ -111,7 +103,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeFloat(float)
-     * @since Android 1.0
      */
     public abstract float readFloat() throws IOException;
 
@@ -127,7 +118,6 @@
      *             if an I/O error occurs while reading.
      * @see DataOutput#write(byte[])
      * @see DataOutput#write(byte[], int, int)
-     * @since Android 1.0
      */
     public abstract void readFully(byte[] buffer) throws IOException;
 
@@ -149,7 +139,6 @@
      *             if an I/O error occurs while reading.
      * @see DataOutput#write(byte[])
      * @see DataOutput#write(byte[], int, int)
-     * @since Android 1.0
      */
     public abstract void readFully(byte[] buffer, int offset, int count)
             throws IOException;
@@ -163,7 +152,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeInt(int)
-     * @since Android 1.0
      */
     public abstract int readInt() throws IOException;
 
@@ -179,7 +167,6 @@
      *         request can be satisfied.
      * @throws IOException
      *             if an I/O error occurs while reading.
-     * @since Android 1.0
      */
     public abstract String readLine() throws IOException;
 
@@ -192,7 +179,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeLong(long)
-     * @since Android 1.0
      */
     public abstract long readLong() throws IOException;
 
@@ -205,7 +191,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeShort(int)
-     * @since Android 1.0
      */
     public abstract short readShort() throws IOException;
 
@@ -218,7 +203,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeByte(int)
-     * @since Android 1.0
      */
     public abstract int readUnsignedByte() throws IOException;
 
@@ -231,7 +215,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeShort(int)
-     * @since Android 1.0
      */
     public abstract int readUnsignedShort() throws IOException;
 
@@ -244,7 +227,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeUTF(java.lang.String)
-     * @since Android 1.0
      */
     public abstract String readUTF() throws IOException;
 
@@ -258,7 +240,6 @@
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if a problem occurs during skipping.
-     * @since Android 1.0
      */
     public abstract int skipBytes(int count) throws IOException;
 }
diff --git a/luni/src/main/java/java/io/DataInputStream.java b/luni/src/main/java/java/io/DataInputStream.java
index 88b10a5..42e38a2 100644
--- a/luni/src/main/java/java/io/DataInputStream.java
+++ b/luni/src/main/java/java/io/DataInputStream.java
@@ -21,38 +21,38 @@
 import org.apache.harmony.luni.util.Util;
 
 /**
- * Wraps an existing {@link InputStream} and reads typed data from it. 
+ * Wraps an existing {@link InputStream} and reads typed data from it.
  * Typically, this stream has been written by a DataOutputStream. Types that can
  * be read include byte, 16-bit short, 32-bit int, 32-bit float, 64-bit long,
  * 64-bit double, byte strings, and strings encoded in
  * {@link DataInput modified UTF-8}.
- * 
+ *
  * @see DataOutputStream
- * 
- * @since Android 1.0
  */
 public class DataInputStream extends FilterInputStream implements DataInput {
 
+    byte[] buff;
+
     /**
      * Constructs a new DataInputStream on the InputStream {@code in}. All
      * reads are then filtered through this stream. Note that data read by this
      * stream is not in a human readable format and was most likely created by a
      * DataOutputStream.
-     * 
+     *
      * @param in
      *            the source InputStream the filter reads from.
      * @see DataOutputStream
      * @see RandomAccessFile
-     * @since Android 1.0
      */
     public DataInputStream(InputStream in) {
         super(in);
+        buff = new byte[8];
     }
 
     /**
      * Reads bytes from this stream into the byte array {@code buffer}. Returns
      * the number of bytes that have been read.
-     * 
+     *
      * @param buffer
      *            the buffer to read bytes into.
      * @return the number of bytes that have been read or -1 if the end of the
@@ -61,7 +61,6 @@
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#write(byte[])
      * @see DataOutput#write(byte[], int, int)
-     * @since Android 1.0
      */
     @Override
     public final int read(byte[] buffer) throws IOException {
@@ -73,7 +72,7 @@
      * the byte array {@code buffer} starting at {@code offset}. Returns the
      * number of bytes that have been read or -1 if no bytes have been read and
      * the end of the stream has been reached.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -87,7 +86,6 @@
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#write(byte[])
      * @see DataOutput#write(byte[], int, int)
-     * @since Android 1.0
      */
     @Override
     public final int read(byte[] buffer, int offset, int length)
@@ -97,7 +95,7 @@
 
     /**
      * Reads a boolean from this stream.
-     * 
+     *
      * @return the next boolean value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before one byte
@@ -105,7 +103,6 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeBoolean(boolean)
-     * @since Android 1.0
      */
     public final boolean readBoolean() throws IOException {
         int temp = in.read();
@@ -117,7 +114,7 @@
 
     /**
      * Reads an 8-bit byte value from this stream.
-     * 
+     *
      * @return the next byte value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before one byte
@@ -125,7 +122,6 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeByte(int)
-     * @since Android 1.0
      */
     public final byte readByte() throws IOException {
         int temp = in.read();
@@ -137,7 +133,7 @@
 
     /**
      * Reads a 16-bit character value from this stream.
-     * 
+     *
      * @return the next char value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before two bytes
@@ -145,20 +141,29 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeChar(int)
-     * @since Android 1.0
      */
     public final char readChar() throws IOException {
-        int b1 = in.read();
-        int b2 = in.read();
-        if ((b1 | b2) < 0) {
+        if (readToBuff(2) < 0){
             throw new EOFException();
         }
-        return (char) ((b1 << 8) + b2);
+        return (char) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
+
+    }
+
+    private int readToBuff(int count) throws IOException {
+        int offset = 0;
+
+        while(offset < count) {
+            int bytesRead = in.read(buff, offset, count - offset);
+            if(bytesRead == -1) return bytesRead;
+            offset += bytesRead;
+        }
+        return offset;
     }
 
     /**
      * Reads a 64-bit double value from this stream.
-     * 
+     *
      * @return the next double value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before eight
@@ -166,7 +171,6 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeDouble(double)
-     * @since Android 1.0
      */
     public final double readDouble() throws IOException {
         return Double.longBitsToDouble(readLong());
@@ -174,7 +178,7 @@
 
     /**
      * Reads a 32-bit float value from this stream.
-     * 
+     *
      * @return the next float value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before four
@@ -182,7 +186,6 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeFloat(float)
-     * @since Android 1.0
      */
     public final float readFloat() throws IOException {
         return Float.intBitsToFloat(readInt());
@@ -192,7 +195,7 @@
      * Reads bytes from this stream into the byte array {@code buffer}. This
      * method will block until {@code buffer.length} number of bytes have been
      * read.
-     * 
+     *
      * @param buffer
      *            to read bytes into.
      * @throws EOFException
@@ -202,7 +205,6 @@
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#write(byte[])
      * @see DataOutput#write(byte[], int, int)
-     * @since Android 1.0
      */
     public final void readFully(byte[] buffer) throws IOException {
         readFully(buffer, 0, buffer.length);
@@ -213,7 +215,7 @@
      * buffer} starting at the position {@code offset}. This method blocks until
      * {@code length} bytes have been read. If {@code length} is zero, then this
      * method returns without reading any bytes.
-     * 
+     *
      * @param buffer
      *            the byte array into which the data is read.
      * @param offset
@@ -232,7 +234,6 @@
      * @throws NullPointerException
      *             if {@code buffer} or the source stream are null.
      * @see java.io.DataInput#readFully(byte[], int, int)
-     * @since Android 1.0
      */
     public final void readFully(byte[] buffer, int offset, int length)
             throws IOException {
@@ -271,7 +272,7 @@
 
     /**
      * Reads a 32-bit integer value from this stream.
-     * 
+     *
      * @return the next int value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before four
@@ -279,25 +280,13 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeInt(int)
-     * @since Android 1.0
      */
     public final int readInt() throws IOException {
-        // BEGIN android-changed
-        byte[] buf = new byte[4];
-        int nread = 0;
-        while (nread < 4) {
-          int nbytes = in.read(buf, nread, 4 - nread);
-          if (nbytes == -1) {
-              throw new EOFException();
-          }
-          nread += nbytes;
+        if (readToBuff(4) < 0){
+            throw new EOFException();
         }
-        int b1 = buf[0] & 0xff;
-        int b2 = buf[1] & 0xff;
-        int b3 = buf[2] & 0xff;
-        int b4 = buf[3] & 0xff;
-        return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
-        // END android-changed
+        return ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16) |
+            ((buff[2] & 0xff) << 8) | (buff[3] & 0xff);
     }
 
     /**
@@ -305,13 +294,12 @@
      * source stream. A line is represented by zero or more characters followed
      * by {@code '\n'}, {@code '\r'}, {@code "\r\n"} or the end of the stream.
      * The string does not include the newline sequence.
-     * 
+     *
      * @return the contents of the line or {@code null} if no characters were
      *         read before the end of the source stream has been reached.
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @deprecated Use {@link BufferedReader}
-     * @since Android 1.0
      */
     @Deprecated
     public final String readLine() throws IOException {
@@ -350,7 +338,7 @@
 
     /**
      * Reads a 64-bit long value from this stream.
-     * 
+     *
      * @return the next long value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before eight
@@ -358,24 +346,22 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeLong(long)
-     * @since Android 1.0
      */
     public final long readLong() throws IOException {
-        int i1 = readInt();
-        int b1 = in.read();
-        int b2 = in.read();
-        int b3 = in.read();
-        int b4 = in.read();
-        if ((b1 | b2 | b3 | b4) < 0) {
+        if (readToBuff(8) < 0){
             throw new EOFException();
         }
-        return (((long) i1) << 32) + ((long) b1 << 24) + (b2 << 16) + (b3 << 8)
-                + b4;
+        int i1 = ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16) |
+            ((buff[2] & 0xff) << 8) | (buff[3] & 0xff);
+        int i2 = ((buff[4] & 0xff) << 24) | ((buff[5] & 0xff) << 16) |
+            ((buff[6] & 0xff) << 8) | (buff[7] & 0xff);
+
+        return ((i1 & 0xffffffffL) << 32) | (i2 & 0xffffffffL);
     }
 
     /**
      * Reads a 16-bit short value from this stream.
-     * 
+     *
      * @return the next short value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before two bytes
@@ -383,29 +369,18 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeShort(int)
-     * @since Android 1.0
      */
     public final short readShort() throws IOException {
-        // BEGIN android-changed
-        byte[] buf = new byte[2];
-        int nread = 0;
-        while (nread < 2) {
-          int nbytes = in.read(buf, nread, 2 - nread);
-          if (nbytes == -1) {
-              throw new EOFException();
-          }
-          nread += nbytes;
+        if (readToBuff(2) < 0){
+            throw new EOFException();
         }
-        int b1 = buf[0] & 0xff;
-        int b2 = buf[1] & 0xff;
-        return (short) ((b1 << 8) + b2);
-        // END android-changed
+        return (short) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
     }
 
     /**
      * Reads an unsigned 8-bit byte value from this stream and returns it as an
      * int.
-     * 
+     *
      * @return the next unsigned byte value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream has been reached before one
@@ -413,7 +388,6 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeByte(int)
-     * @since Android 1.0
      */
     public final int readUnsignedByte() throws IOException {
         int temp = in.read();
@@ -426,7 +400,7 @@
     /**
      * Reads a 16-bit unsigned short value from this stream and returns it as an
      * int.
-     * 
+     *
      * @return the next unsigned short value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before two bytes
@@ -434,21 +408,18 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeShort(int)
-     * @since Android 1.0
      */
     public final int readUnsignedShort() throws IOException {
-        int b1 = in.read();
-        int b2 = in.read();
-        if ((b1 | b2) < 0) {
+        if (readToBuff(2) < 0){
             throw new EOFException();
         }
-        return ((b1 << 8) + b2);
+        return (char) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
     }
 
     /**
      * Reads an string encoded in {@link DataInput modified UTF-8} from this
      * stream.
-     * 
+     *
      * @return the next {@link DataInput MUTF-8} encoded string read from the
      *         source stream.
      * @throws EOFException if the end of the input is reached before the read
@@ -456,90 +427,28 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeUTF(java.lang.String)
-     * @since Android 1.0
      */
     public final String readUTF() throws IOException {
-        int utfSize = readUnsignedShort();
-        return decodeUTF(utfSize);
+        return decodeUTF(readUnsignedShort());
     }
 
-    // BEGIN android-removed
-    // static final int MAX_BUF_SIZE = 8192;
-    //
-    // private static class CacheLock {
-    // }
-    //
-    // static final Object cacheLock = new CacheLock();
-    //
-    // static boolean useShared = true;
-    //
-    // static byte[] byteBuf = new byte[0];
-    //
-    // static char[] charBuf = new char[0];
-    // END android-removed
 
     String decodeUTF(int utfSize) throws IOException {
-        // BEGIN android-removed
-        // byte[] buf;
-        // char[] out = null;
-        // boolean makeBuf = true;
-        //
-        // /*
-        //  * Try to avoid the synchronization -- if we get a stale value for
-        //  * useShared then there is no foul below, but those that sync on the
-        //  * lock must see the right value.
-        //  */
-        // if (utfSize <= MAX_BUF_SIZE && useShared) {
-        //     synchronized (cacheLock) {
-        //         if (useShared) {
-        //             useShared = false;
-        //             makeBuf = false;
-        //         }
-        //     }
-        // }
-        // if (makeBuf) {
-        //     buf = new byte[utfSize];
-        //     out = new char[utfSize];
-        // } else {
-        //     /*
-        //      * Need to 'sample' byteBuf and charBuf before using them because
-        //      * they are not protected by the cacheLock. They may get out of sync
-        //      * with the static and one another, but that is ok because we
-        //      * explicitly check and fix their length after sampling.
-        //      */
-        //     buf = byteBuf;
-        //     if (buf.length < utfSize) {
-        //         buf = byteBuf = new byte[utfSize];
-        //     }
-        //     out = charBuf;
-        //     if (out.length < utfSize) {
-        //         out = charBuf = new char[utfSize];
-        //     }
-        // }
-        // END android-removed
-        // BEGIN android-added
+        return decodeUTF(utfSize, this);
+    }
+
+    private static String decodeUTF(int utfSize, DataInput in) throws IOException {
         byte[] buf = new byte[utfSize];
         char[] out = new char[utfSize];
-        // END android-added
-        readFully(buf, 0, utfSize);
-        String result;
-        result = Util.convertUTF8WithBuf(buf, out, 0, utfSize);
-        // BEGIN android-removed
-        // if (!makeBuf) {
-        //     /*
-        //      * Do not synchronize useShared on cacheLock, it will make it back
-        //      * to main storage at some point, and no harm until it does.
-        //      */
-        //     useShared = true;
-        // }
-        //END android-removed
-        return result;
+        in.readFully(buf, 0, utfSize);
+
+        return Util.convertUTF8WithBuf(buf, out, 0, utfSize);
     }
 
     /**
      * Reads a string encoded in {@link DataInput modified UTF-8} from the
      * {@code DataInput} stream {@code in}.
-     * 
+     *
      * @param in
      *            the input stream to read from.
      * @return the next {@link DataInput MUTF-8} encoded string from the source
@@ -547,19 +456,18 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutputStream#writeUTF(java.lang.String)
-     * @since Android 1.0
      */
     public static final String readUTF(DataInput in) throws IOException {
-        return in.readUTF();
+        return decodeUTF(in.readUnsignedShort(), in);
     }
 
     /**
      * Skips {@code count} number of bytes in this stream. Subsequent {@code
      * read()}s will not return these bytes unless {@code reset()} is used.
-     * 
+     *
      * This method will not throw an {@link EOFException} if the end of the
      * input is reached before {@code count} bytes where skipped.
-     * 
+     *
      * @param count
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
@@ -567,7 +475,6 @@
      *             if a problem occurs during skipping.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     public final int skipBytes(int count) throws IOException {
         int skipped = 0;
diff --git a/luni/src/main/java/java/io/DataOutput.java b/luni/src/main/java/java/io/DataOutput.java
index d028a18..8275958 100644
--- a/luni/src/main/java/java/io/DataOutput.java
+++ b/luni/src/main/java/java/io/DataOutput.java
@@ -23,35 +23,29 @@
  * DataInput. Types that can be written include byte, 16-bit short, 32-bit int,
  * 32-bit float, 64-bit long, 64-bit double, byte strings, and {@link DataInput
  * MUTF-8} encoded strings.
- * 
+ *
  * @see DataOutputStream
  * @see RandomAccessFile
- * 
- * @since Android 1.0
  */
 public interface DataOutput {
 
     /**
      * Writes the entire contents of the byte array {@code buffer} to this
      * stream.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readFully(byte[])
      * @see DataInput#readFully(byte[], int, int)
-     * @since Android 1.0
      */
     public abstract void write(byte[] buffer) throws IOException;
-    // BEGIN android-note
-    // changed array notation to be consistent with the rest of harmony
-    // END android-note
 
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * offset {@code index}.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -62,7 +56,6 @@
      *             if an I/O error occurs while writing.
      * @see DataInput#readFully(byte[])
      * @see DataInput#readFully(byte[], int, int)
-     * @since Android 1.0
      */
     public abstract void write(byte[] buffer, int offset, int count) throws IOException;
     // BEGIN android-note
@@ -71,51 +64,47 @@
 
     /**
      * Writes the specified 8-bit byte.
-     * 
+     *
      * @param oneByte
      *            the byte to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readByte()
-     * @since Android 1.0
      */
     public abstract void write(int oneByte) throws IOException;
 
     /**
      * Writes the specified boolean.
-     * 
+     *
      * @param val
      *            the boolean value to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readBoolean()
-     * @since Android 1.0
      */
     public abstract void writeBoolean(boolean val) throws IOException;
 
     /**
      * Writes the specified 8-bit byte.
-     * 
+     *
      * @param val
      *            the byte value to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readByte()
      * @see DataInput#readUnsignedByte()
-     * @since Android 1.0
      */
     public abstract void writeByte(int val) throws IOException;
 
     /**
      * Writes the low order 8-bit bytes from the specified string.
-     * 
+     *
      * @param str
      *            the string containing the bytes to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readFully(byte[])
      * @see DataInput#readFully(byte[],int,int)
-     * @since Android 1.0
      */
     public abstract void writeBytes(String str) throws IOException;
 
@@ -123,106 +112,95 @@
      * Writes the specified 16-bit character. Only the two least significant
      * bytes of the integer {@code oneByte} are written, with the higher one
      * written first. This represents the Unicode value of the char.
-     * 
+     *
      * @param val
      *            the character to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readChar()
-     * @since Android 1.0
      */
     public abstract void writeChar(int val) throws IOException;
-    // BEGIN android-note
-    // renamed parameter because it was misleading
-    // END android-note
 
     /**
      * Writes the 16-bit characters contained in {@code str}.
-     * 
+     *
      * @param str
      *            the string that contains the characters to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readChar()
-     * @since Android 1.0
      */
     public abstract void writeChars(String str) throws IOException;
 
     /**
      * Writes the specified 64-bit double. The resulting output is the eight
      * bytes returned by {@link Double#doubleToLongBits(double)}.
-     * 
+     *
      * @param val
      *            the double to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readDouble()
-     * @since Android 1.0
      */
     public abstract void writeDouble(double val) throws IOException;
 
     /**
      * Writes the specified 32-bit float. The resulting output is the four bytes
      * returned by {@link Float#floatToIntBits(float)}.
-     * 
+     *
      * @param val
      *            the float to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readFloat()
-     * @since Android 1.0
      */
     public abstract void writeFloat(float val) throws IOException;
 
     /**
      * Writes the specified 32-bit int. The resulting output is the four bytes,
      * highest order first, of {@code val}.
-     * 
+     *
      * @param val
      *            the int to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readInt()
-     * @since Android 1.0
      */
     public abstract void writeInt(int val) throws IOException;
 
     /**
      * Writes the specified 64-bit long. The resulting output is the eight
      * bytes, highest order first, of {@code val}.
-     * 
+     *
      * @param val
      *            the long to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readLong()
-     * @since Android 1.0
      */
     public abstract void writeLong(long val) throws IOException;
 
     /**
      * Writes the specified 16-bit short. Only the lower two bytes of {@code
      * val} are written with the higher one written first.
-     * 
+     *
      * @param val
      *            the short to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readShort()
      * @see DataInput#readUnsignedShort()
-     * @since Android 1.0
      */
     public abstract void writeShort(int val) throws IOException;
 
     /**
      * Writes the specified string encoded in {@link DataInput modified UTF-8}.
-     * 
+     *
      * @param str
      *            the string to write encoded in {@link DataInput modified UTF-8}.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readUTF()
-     * @since Android 1.0
      */
     public abstract void writeUTF(String str) throws IOException;
 }
diff --git a/luni/src/main/java/java/io/DataOutputStream.java b/luni/src/main/java/java/io/DataOutputStream.java
index 7f45c58..18e04a5 100644
--- a/luni/src/main/java/java/io/DataOutputStream.java
+++ b/luni/src/main/java/java/io/DataOutputStream.java
@@ -24,41 +24,37 @@
  * Typically, this stream can be read in by DataInputStream. Types that can be
  * written include byte, 16-bit short, 32-bit int, 32-bit float, 64-bit long,
  * 64-bit double, byte strings, and {@link DataInput MUTF-8} encoded strings.
- * 
+ *
  * @see DataInputStream
- * 
- * @since Android 1.0
  */
 public class DataOutputStream extends FilterOutputStream implements DataOutput {
 
     /**
      * The number of bytes written out so far.
-     * 
-     * @since Android 1.0
      */
     protected int written;
+    byte buff[];
 
     /**
      * Constructs a new {@code DataOutputStream} on the {@code OutputStream}
      * {@code out}. Note that data written by this stream is not in a human
      * readable form but can be reconstructed by using a {@link DataInputStream}
      * on the resulting output.
-     * 
+     *
      * @param out
      *            the target stream for writing.
-     * @since Android 1.0
      */
     public DataOutputStream(OutputStream out) {
         super(out);
+        buff = new byte[8];
     }
 
     /**
      * Flushes this stream to ensure all pending data is sent out to the target
      * stream. This implementation then also flushes the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to flush this stream.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -67,9 +63,8 @@
 
     /**
      * Returns the total number of bytes written to the target stream so far.
-     * 
+     *
      * @return the number of bytes written to the target stream.
-     * @since Android 1.0
      */
     public final int size() {
         if (written < 0) {
@@ -81,7 +76,7 @@
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * {@code offset} to the target stream.
-     * 
+     *
      * @param buffer
      *            the buffer to write to the target stream.
      * @param offset
@@ -94,7 +89,6 @@
      *             if {@code buffer} is {@code null}.
      * @see DataInputStream#readFully(byte[])
      * @see DataInputStream#readFully(byte[], int, int)
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int count) throws IOException {
@@ -111,13 +105,12 @@
     /**
      * Writes a byte to the target stream. Only the least significant byte of
      * the integer {@code oneByte} is written.
-     * 
+     *
      * @param oneByte
      *            the byte to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readByte()
-     * @since Android 1.0
      */
     @Override
     public void write(int oneByte) throws IOException {
@@ -127,13 +120,12 @@
 
     /**
      * Writes a boolean to the target stream.
-     * 
+     *
      * @param val
      *            the boolean value to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readBoolean()
-     * @since Android 1.0
      */
     public final void writeBoolean(boolean val) throws IOException {
         out.write(val ? 1 : 0);
@@ -143,14 +135,13 @@
     /**
      * Writes an 8-bit byte to the target stream. Only the least significant
      * byte of the integer {@code val} is written.
-     * 
+     *
      * @param val
      *            the byte value to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readByte()
      * @see DataInputStream#readUnsignedByte()
-     * @since Android 1.0
      */
     public final void writeByte(int val) throws IOException {
         out.write(val);
@@ -159,14 +150,13 @@
 
     /**
      * Writes the low order bytes from a string to the target stream.
-     * 
+     *
      * @param str
      *            the string containing the bytes to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readFully(byte[])
      * @see DataInputStream#readFully(byte[],int,int)
-     * @since Android 1.0
      */
     public final void writeBytes(String str) throws IOException {
         if (str.length() == 0) {
@@ -184,31 +174,30 @@
      * Writes a 16-bit character to the target stream. Only the two lower bytes
      * of the integer {@code val} are written, with the higher one written
      * first. This corresponds to the Unicode value of {@code val}.
-     * 
+     *
      * @param val
      *            the character to write to the target stream
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readChar()
-     * @since Android 1.0
      */
     public final void writeChar(int val) throws IOException {
-        out.write(val >> 8);
-        out.write(val);
+        buff[0] = (byte) (val >> 8);
+        buff[1] = (byte) val;
+        out.write(buff, 0, 2);
         written += 2;
     }
 
     /**
      * Writes the 16-bit characters contained in {@code str} to the target
      * stream.
-     * 
+     *
      * @param str
      *            the string that contains the characters to write to this
      *            stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readChar()
-     * @since Android 1.0
      */
     public final void writeChars(String str) throws IOException {
         byte newBytes[] = new byte[str.length() * 2];
@@ -224,13 +213,12 @@
     /**
      * Writes a 64-bit double to the target stream. The resulting output is the
      * eight bytes resulting from calling Double.doubleToLongBits().
-     * 
+     *
      * @param val
      *            the double to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readDouble()
-     * @since Android 1.0
      */
     public final void writeDouble(double val) throws IOException {
         writeLong(Double.doubleToLongBits(val));
@@ -239,13 +227,12 @@
     /**
      * Writes a 32-bit float to the target stream. The resulting output is the
      * four bytes resulting from calling Float.floatToIntBits().
-     * 
+     *
      * @param val
      *            the float to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readFloat()
-     * @since Android 1.0
      */
     public final void writeFloat(float val) throws IOException {
         writeInt(Float.floatToIntBits(val));
@@ -254,63 +241,68 @@
     /**
      * Writes a 32-bit int to the target stream. The resulting output is the
      * four bytes, highest order first, of {@code val}.
-     * 
+     *
      * @param val
      *            the int to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readInt()
-     * @since Android 1.0
      */
     public final void writeInt(int val) throws IOException {
-        out.write(val >> 24);
-        out.write(val >> 16);
-        out.write(val >> 8);
-        out.write(val);
+        buff[0] = (byte) (val >> 24);
+        buff[1] = (byte) (val >> 16);
+        buff[2] = (byte) (val >> 8);
+        buff[3] = (byte) val;
+        out.write(buff, 0, 4);
         written += 4;
     }
 
     /**
      * Writes a 64-bit long to the target stream. The resulting output is the
      * eight bytes, highest order first, of {@code val}.
-     * 
+     *
      * @param val
      *            the long to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readLong()
-     * @since Android 1.0
      */
     public final void writeLong(long val) throws IOException {
-        writeInt((int) (val >> 32));
-        writeInt((int) val);
+        buff[0] = (byte) (val >> 56);
+        buff[1] = (byte) (val >> 48);
+        buff[2] = (byte) (val >> 40);
+        buff[3] = (byte) (val >> 32);
+        buff[4] = (byte) (val >> 24);
+        buff[5] = (byte) (val >> 16);
+        buff[6] = (byte) (val >> 8);
+        buff[7] = (byte) val;
+        out.write(buff, 0, 8);
+        written += 8;
     }
 
     /**
      * Writes the specified 16-bit short to the target stream. Only the lower
      * two bytes of the integer {@code val} are written, with the higher one
      * written first.
-     * 
+     *
      * @param val
      *            the short to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readShort()
      * @see DataInputStream#readUnsignedShort()
-     * @since Android 1.0
      */
     public final void writeShort(int val) throws IOException {
-        writeChar(val);
+        buff[0] = (byte) (val >> 8);
+        buff[1] = (byte) val;
+        out.write(buff, 0, 2);
+        written += 2;
     }
-    
-    // BEGIN android-added
-    static final int MAX_BUF_SIZE = 8192;
-    // END android-added
-    
+
     /**
      * Writes the specified encoded in {@link DataInput modified UTF-8} to this
      * stream.
-     * 
+     *
      * @param str
      *            the string to write to the target stream encoded in
      *            {@link DataInput modified UTF-8}.
@@ -319,58 +311,14 @@
      * @throws UTFDataFormatException
      *             if the encoded string is longer than 65535 bytes.
      * @see DataInputStream#readUTF()
-     * @since Android 1.0
      */
     public final void writeUTF(String str) throws IOException {
-        int length = str.length();
-        // BEGIN android-changed
-        if (length <= MAX_BUF_SIZE / 3) {
-            int size = length * 3;
-            byte[] utfBytes = new byte[size];
-            // boolean makeBuf = true;
-            // synchronized (DataInputStream.byteBuf) {
-            //     if (DataInputStream.useShared) {
-            //         DataInputStream.useShared = false;
-            //         makeBuf = false;
-            //     }
-            // }
-            // if (makeBuf) {
-            //     utfBytes = new byte[size];
-            // } else {
-            //     if (DataInputStream.byteBuf.length < size) {
-            //         DataInputStream.byteBuf = new byte[size];
-            //     }
-            //     utfBytes = DataInputStream.byteBuf;
-            // }
-            int utfIndex = 0;
-            for (int i = 0; i < length; i++) {
-                int charValue = str.charAt(i);
-                if (charValue > 0 && charValue <= 127) {
-                    utfBytes[utfIndex++] = (byte) charValue;
-                } else if (charValue <= 2047) {
-                    utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
-                } else {
-                    utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
-                }
-            }
-            writeShort(utfIndex);
-            write(utfBytes, 0, utfIndex);
-            // if (!makeBuf) {
-            //     DataInputStream.useShared = true;
-            // }
-        } else {
-            long utfCount;
-            if (length <= 65535 && (utfCount = countUTFBytes(str)) <= 65535) {
-                writeShort((int) utfCount);
-                writeUTFBytes(str, utfCount);
-            } else {
-                throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
-            }
+        long utfCount = countUTFBytes(str);
+        if (utfCount > 65535) {
+            throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
         }
-        // END android-changed
+        writeShort((int) utfCount);
+        writeUTFBytes(str, utfCount);
     }
 
     long countUTFBytes(String str) {
@@ -389,76 +337,23 @@
     }
 
     void writeUTFBytes(String str, long count) throws IOException {
-        boolean single = true;
         int size = (int) count;
-        // BEGIN android-changed
-        if (count > MAX_BUF_SIZE) {
-            single = false;
-            size = MAX_BUF_SIZE;
-        }
+        int length = str.length();
         byte[] utfBytes = new byte[size];
-        // END android-changed
-        // BEGIN android-removed
-        // boolean makeBuf = true;
-        // if (DataInputStream.useShared) {
-        //     synchronized (DataInputStream.cacheLock) {
-        //         if (DataInputStream.useShared) {
-        //             DataInputStream.useShared = false;
-        //             makeBuf = false;
-        //         }
-        //     }
-        // }
-        // if (makeBuf) {
-        //     utfBytes = new byte[size];
-        // } else {
-        //     // byteBuf is not protected by the cacheLock, so sample it first
-        //     utfBytes = DataInputStream.byteBuf;
-        //     if (utfBytes.length < size) {
-        //         utfBytes = DataInputStream.byteBuf = new byte[size];
-        //     }
-        // }
-        // END android-removed
-
-        int utfIndex = 0, i = 0, length = str.length();
-        int end = length;
-        while (i < length) {
-            if (!single) {
-                end = i + ((utfBytes.length - utfIndex) / 3);
-                if (end > length) {
-                    end = length;
-                }
-            }
-            for (int j = i; j < end; j++) {
-                int charValue = str.charAt(j);
-                if (charValue > 0 && charValue <= 127) {
-                    utfBytes[utfIndex++] = (byte) charValue;
-                } else if (charValue <= 2047) {
-                    utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
-                } else {
-                    utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
-                }
-            }
-            if (single || utfIndex > utfBytes.length - 300) {
-                write(utfBytes, 0, utfIndex);
-                if (single) {
-                    return;
-                }
-                utfIndex = 0;
-            }
-            i = end;
+        int utfIndex = 0;
+        for (int i = 0; i < length; i++) {
+            int charValue = str.charAt(i);
+            if (charValue > 0 && charValue <= 127) {
+                utfBytes[utfIndex++] = (byte) charValue;
+            } else if (charValue <= 2047) {
+                utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
+                utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
+            } else {
+                utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
+                utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
+                utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
+             }
         }
-        if (utfIndex > 0) {
-            write(utfBytes, 0, utfIndex);
-        }
-        // BEGIN android-removed
-        // if (!makeBuf) {
-        //     // Update the useShared flag optimistically (see DataInputStream
-        //     // equivalent)
-        //     DataInputStream.useShared = true;
-        // }
-        // END android-removed
+        write(utfBytes, 0, utfIndex);
     }
 }
diff --git a/luni/src/main/java/java/io/EOFException.java b/luni/src/main/java/java/io/EOFException.java
index 40beadd..7999f43 100644
--- a/luni/src/main/java/java/io/EOFException.java
+++ b/luni/src/main/java/java/io/EOFException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a program encounters the end of a file or stream during an input
  * operation.
- * 
- * @since Android 1.0
  */
 public class EOFException extends IOException {
 
@@ -29,8 +27,6 @@
 
     /**
      * Constructs a new {@code EOFException} with its stack trace filled in.
-     * 
-     * @since Android 1.0
      */
     public EOFException() {
         super();
@@ -42,7 +38,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public EOFException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/EmulatedFields.java b/luni/src/main/java/java/io/EmulatedFields.java
index 4ef241d..a947a52 100644
--- a/luni/src/main/java/java/io/EmulatedFields.java
+++ b/luni/src/main/java/java/io/EmulatedFields.java
@@ -103,17 +103,18 @@
     }
 
     /**
-     * Return a boolean indicating if the field named <code>name</code> has
-     * been assigned a value explicitly (false) or if it still holds a default
-     * value for the type (true) because it hasn't been assigned to yet.
+     * Returns {@code true} indicating the field called {@code name} has not had
+     * a value explicitly assigned and that it still holds a default value for
+     * its type, or {@code false} indicating that the field named has been
+     * assigned a value explicitly.
      * 
      * @param name
-     *            a String, the name of the field to test
-     * @return <code>true</code> if <code>name</code> still holds its
-     *         default value, <code>false</code> otherwise
+     *            the name of the field to test.
+     * @return {@code true} if {@code name} still holds its default value,
+     *         {@code false} otherwise
      * 
      * @throws IllegalArgumentException
-     *             If <code>name</code> is null
+     *             if {@code name} is {@code null}
      */
     public boolean defaulted(String name) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, null);
@@ -124,23 +125,23 @@
     }
 
     /**
-     * Find and return an ObjectSlot that corresponds to a field named
-     * <code>fieldName</code> and type <code>fieldType</code>. If the field
-     * type <code>fieldType</code> corresponds to a primitive type, the field
-     * type has to match exactly or <code>null</code> is returned. If the
-     * field type <code>fieldType</code> corresponds to an object type, the
-     * field type has to be compatible in terms of assignment, or null is
-     * returned. If <code>fieldType</code> is <code>null</code>, no such
-     * compatibility checking is performed and the slot is returned.
+     * Finds and returns an ObjectSlot that corresponds to a field named {@code
+     * fieldName} and type {@code fieldType}. If the field type {@code
+     * fieldType} corresponds to a primitive type, the field type has to match
+     * exactly or {@code null} is returned. If the field type {@code fieldType}
+     * corresponds to an object type, the field type has to be compatible in
+     * terms of assignment, or null is returned. If {@code fieldType} is {@code
+     * null}, no such compatibility checking is performed and the slot is
+     * returned.
      * 
      * @param fieldName
-     *            A String, the name of the field to find
+     *            the name of the field to find
      * @param fieldType
-     *            A Class, the type of the field. This will be used to test
-     *            compatibility. If null, no testing is done, the corresponding
-     *            slot is returned.
-     * @return If there is no field with that name, or no compatible field
-     *         (relative to <code>fieldType</code>)
+     *            the type of the field. This will be used to test
+     *            compatibility. If {@code null}, no testing is done, the
+     *            corresponding slot is returned.
+     * @return the object slot, or {@code null} if there is no field with that
+     *         name, or no compatible field (relative to {@code fieldType})
      */
     private ObjectSlot findSlot(String fieldName, Class<?> fieldType) {
         boolean isPrimitive = fieldType != null && fieldType.isPrimitive();
@@ -187,19 +188,19 @@
     }
 
     /**
-     * Find and return the byte value of a given field named <code>name</code>
+     * Finds and returns the byte value of a given field named {@code name}
      * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public byte get(String name, byte defaultValue)
             throws IllegalArgumentException {
@@ -213,19 +214,19 @@
     }
 
     /**
-     * Find and return the char value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the char value of a given field named {@code name} in the
+     * receiver. If the field has not been assigned any value yet, the default
+     * value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public char get(String name, char defaultValue)
             throws IllegalArgumentException {
@@ -239,19 +240,19 @@
     }
 
     /**
-     * Find and return the double value of a given field named <code>name</code>
+     * Finds and returns the double value of a given field named {@code name}
      * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public double get(String name, double defaultValue)
             throws IllegalArgumentException {
@@ -265,19 +266,19 @@
     }
 
     /**
-     * Find and return the float value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the float value of a given field named {@code name} in
+     * the receiver. If the field has not been assigned any value yet, the
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public float get(String name, float defaultValue)
             throws IllegalArgumentException {
@@ -291,19 +292,19 @@
     }
 
     /**
-     * Find and return the int value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the int value of a given field named {@code name} in the
+     * receiver. If the field has not been assigned any value yet, the default
+     * value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public int get(String name, int defaultValue)
             throws IllegalArgumentException {
@@ -317,19 +318,19 @@
     }
 
     /**
-     * Find and return the long value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the long value of a given field named {@code name} in the
+     * receiver. If the field has not been assigned any value yet, the default
+     * value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public long get(String name, long defaultValue)
             throws IllegalArgumentException {
@@ -343,19 +344,19 @@
     }
 
     /**
-     * Find and return the Object value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the Object value of a given field named {@code name} in
+     * the receiver. If the field has not been assigned any value yet, the
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public Object get(String name, Object defaultValue)
             throws IllegalArgumentException {
@@ -368,19 +369,19 @@
     }
 
     /**
-     * Find and return the short value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the short value of a given field named {@code name} in
+     * the receiver. If the field has not been assigned any value yet, the
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public short get(String name, short defaultValue)
             throws IllegalArgumentException {
@@ -394,20 +395,19 @@
     }
 
     /**
-     * Find and return the boolean value of a given field named
-     * <code>name</code> in the receiver. If the field has not been assigned
-     * any value yet, the default value <code>defaultValue</code> is returned
-     * instead.
+     * Finds and returns the boolean value of a given field named {@code name} in
+     * the receiver. If the field has not been assigned any value yet, the
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public boolean get(String name, boolean defaultValue)
             throws IllegalArgumentException {
@@ -421,16 +421,16 @@
     }
 
     /**
-     * Find and set the byte value of a given field named <code>name</code> in
-     * the receiver.
+     * Find and set the byte value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, byte value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Byte.TYPE);
@@ -442,16 +442,16 @@
     }
 
     /**
-     * Find and set the char value of a given field named <code>name</code> in
-     * the receiver.
+     * Find and set the char value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, char value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Character.TYPE);
@@ -463,16 +463,16 @@
     }
 
     /**
-     * Find and set the double value of a given field named <code>name</code>
-     * in the receiver.
+     * Find and set the double value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, double value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Double.TYPE);
@@ -484,16 +484,16 @@
     }
 
     /**
-     * Find and set the float value of a given field named <code>name</code>
-     * in the receiver.
+     * Find and set the float value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, float value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Float.TYPE);
@@ -505,16 +505,16 @@
     }
 
     /**
-     * Find and set the int value of a given field named <code>name</code> in
-     * the receiver.
+     * Find and set the int value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, int value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Integer.TYPE);
@@ -526,16 +526,16 @@
     }
 
     /**
-     * Find and set the long value of a given field named <code>name</code> in
-     * the receiver.
+     * Find and set the long value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, long value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Long.TYPE);
@@ -547,16 +547,16 @@
     }
 
     /**
-     * Find and set the Object value of a given field named <code>name</code>
-     * in the receiver.
+     * Find and set the Object value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, Object value) throws IllegalArgumentException {
         Class<?> valueClass = null;
@@ -572,16 +572,16 @@
     }
 
     /**
-     * Find and set the short value of a given field named <code>name</code>
-     * in the receiver.
+     * Find and set the short value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, short value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Short.TYPE);
@@ -593,16 +593,16 @@
     }
 
     /**
-     * Find and set the boolean value of a given field named <code>name</code>
-     * in the receiver.
+     * Find and set the boolean value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, boolean value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Boolean.TYPE);
diff --git a/luni/src/main/java/java/io/Externalizable.java b/luni/src/main/java/java/io/Externalizable.java
index 03049eb..d07f0b7 100644
--- a/luni/src/main/java/java/io/Externalizable.java
+++ b/luni/src/main/java/java/io/Externalizable.java
@@ -20,8 +20,6 @@
 /**
  * Defines an interface for classes that want to be serializable, but have their
  * own binary representation.
- * 
- * @since Android 1.0
  */
 public interface Externalizable extends Serializable {
     /**
@@ -33,7 +31,6 @@
      *             if an error occurs attempting to read from {@code input}.
      * @throws ClassNotFoundException
      *             if the class of the instance being loaded cannot be found.
-     * @since Android 1.0
      */
     public void readExternal(ObjectInput input) throws IOException,
             ClassNotFoundException;
@@ -45,7 +42,6 @@
      *            the ObjectOutput to write the object to.
      * @throws IOException
      *             if an error occurs attempting to write to {@code output}.
-     * @since Android 1.0
      */
     public void writeExternal(ObjectOutput output) throws IOException;
 }
diff --git a/luni/src/main/java/java/io/File.java b/luni/src/main/java/java/io/File.java
index f4e8623..e34ab18 100644
--- a/luni/src/main/java/java/io/File.java
+++ b/luni/src/main/java/java/io/File.java
@@ -21,15 +21,11 @@
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.security.AccessController;
+import java.security.SecureRandom;
 import java.util.ArrayList;
-// BEGIN android-added
-import java.util.Collections;
-// END android-added
 import java.util.List;
 
-// BEGIN android-removed
-// import org.apache.harmony.luni.util.DeleteOnExit;
-// END android-removed
+import org.apache.harmony.luni.util.DeleteOnExit;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 import org.apache.harmony.luni.util.Util;
@@ -45,50 +41,39 @@
  * <p>
  * When manipulating file paths, the static fields of this class may be used to
  * determine the platform specific separators.
- * 
+ *
  * @see java.io.Serializable
  * @see java.lang.Comparable
- * 
- * @since Android 1.0
  */
 public class File implements Serializable, Comparable<File> {
+
     private static final long serialVersionUID = 301077366599181567L;
 
+    private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
     private String path;
 
     transient byte[] properPath;
 
     /**
-     * The system dependent file separator character. Since Android is a Unix-
-     * based system, this defaults to '/'.
-     * 
-     * @since Android 1.0
+     * The system dependent file separator character.
      */
     public static final char separatorChar;
 
     /**
      * The system dependent file separator string. The initial value of this
-     * field is the system property "file.separator". Since Android is a Unix-
-     * based system, this defaults to "/".
-     * 
-     * @since Android 1.0
+     * field is the system property "file.separator".
      */
     public static final String separator;
 
     /**
-     * The system dependent path separator character. Since Android is a Unix-
-     * based system, this defaults to ':'.
-     * 
-     * @since Android 1.0
+     * The system dependent path separator character.
      */
     public static final char pathSeparatorChar;
 
     /**
      * The system dependent path separator string. The initial value of this
-     * field is the system property "path.separator". Since Android is a Unix-
-     * based system, this defaults to ':'.
-     * 
-     * @since Android 1.0
+     * field is the system property "path.separator".
      */
     public static final String pathSeparator;
 
@@ -115,14 +100,13 @@
 
     /**
      * Constructs a new file using the specified directory and name.
-     * 
+     *
      * @param dir
      *            the directory where the file is stored.
      * @param name
      *            the file's name.
      * @throws NullPointerException
-     *             if {@code name} is null.
-     * @since Android 1.0
+     *             if {@code name} is {@code null}.
      */
     public File(File dir, String name) {
         if (name == null) {
@@ -137,10 +121,9 @@
 
     /**
      * Constructs a new file using the specified path.
-     * 
+     *
      * @param path
      *            the path to be used for the file.
-     * @since Android 1.0
      */
     public File(String path) {
         // path == null check & NullPointerException thrown by fixSlashes
@@ -150,14 +133,13 @@
     /**
      * Constructs a new File using the specified directory path and file name,
      * placing a path separator between the two.
-     * 
+     *
      * @param dirPath
      *            the path to the directory where the file is stored.
      * @param name
      *            the file's name.
      * @throws NullPointerException
-     *             if {@code name} is null.
-     * @since Android 1.0
+     *             if {@code name} is {@code null}.
      */
     public File(String dirPath, String name) {
         if (name == null) {
@@ -175,7 +157,7 @@
      * needs to be an absolute and hierarchical Unified Resource Identifier with
      * file scheme and non-empty path component, but with undefined authority,
      * query or fragment components.
-     * 
+     *
      * @param uri
      *            the Unified Resource Identifier that is used to construct this
      *            file.
@@ -183,7 +165,6 @@
      *             if {@code uri} does not comply with the conditions above.
      * @see #toURI
      * @see java.net.URI
-     * @since Android 1.0
      */
     public File(URI uri) {
         // check pre-conditions
@@ -193,7 +174,7 @@
 
     private String calculatePath(String dirPath, String name) {
         dirPath = fixSlashes(dirPath);
-        if (!name.equals("")) { //$NON-NLS-1$
+        if (!name.equals(EMPTY_STRING) || dirPath.equals(EMPTY_STRING)) {
             // Remove all the proceeding separator chars from name
             name = fixSlashes(name);
 
@@ -217,36 +198,37 @@
         return dirPath;
     }
 
+    @SuppressWarnings("nls")
     private void checkURI(URI uri) {
         if (!uri.isAbsolute()) {
-            throw new IllegalArgumentException(Msg.getString("K031a", uri)); //$NON-NLS-1$
-        } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) { //$NON-NLS-1$
-            throw new IllegalArgumentException(Msg.getString("K031b", uri)); //$NON-NLS-1$
+            throw new IllegalArgumentException(Msg.getString("K031a", uri));
+        } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) {
+            throw new IllegalArgumentException(Msg.getString("K031b", uri));
         }
 
         String temp = uri.getScheme();
-        if (temp == null || !temp.equals("file")) { //$NON-NLS-1$
-            throw new IllegalArgumentException(Msg.getString("K031c", uri)); //$NON-NLS-1$
+        if (temp == null || !temp.equals("file")) {
+            throw new IllegalArgumentException(Msg.getString("K031c", uri));
         }
 
         temp = uri.getRawPath();
         if (temp == null || temp.length() == 0) {
-            throw new IllegalArgumentException(Msg.getString("K031d", uri)); //$NON-NLS-1$
+            throw new IllegalArgumentException(Msg.getString("K031d", uri));
         }
 
         if (uri.getRawAuthority() != null) {
-            throw new IllegalArgumentException(Msg.getString(
-                    "K031e", new String[] { "authority", uri.toString() })); //$NON-NLS-1$ //$NON-NLS-2$
+            throw new IllegalArgumentException(Msg.getString("K031e",
+                    new String[] { "authority", uri.toString() }));
         }
 
         if (uri.getRawQuery() != null) {
-            throw new IllegalArgumentException(Msg.getString(
-                    "K031e", new String[] { "query", uri.toString() })); //$NON-NLS-1$//$NON-NLS-2$
+            throw new IllegalArgumentException(Msg.getString("K031e",
+                    new String[] { "query", uri.toString() }));
         }
 
         if (uri.getRawFragment() != null) {
-            throw new IllegalArgumentException(Msg.getString(
-                    "K031e", new String[] { "fragment", uri.toString() })); //$NON-NLS-1$ //$NON-NLS-2$
+            throw new IllegalArgumentException(Msg.getString("K031e",
+                    new String[] { "fragment", uri.toString() }));
         }
     }
 
@@ -259,9 +241,8 @@
      * file systems, each with its own platform-dependent root. Further, the
      * canonical pathname of any file on the system will always begin with one
      * of the returned file system roots.
-     * 
+     *
      * @return the array of file system roots.
-     * @since Android 1.0
      */
     public static File[] listRoots() {
         byte[][] rootsList = rootsImpl();
@@ -293,7 +274,8 @@
         char newPath[] = origPath.toCharArray();
         for (int i = 0; i < length; i++) {
             char pathChar = newPath[i];
-            if (pathChar == '\\' || pathChar == '/') {
+            if ((separatorChar == '\\' && pathChar == '\\')
+                || pathChar == '/') {
                 /* UNC Name requires 2 leading slashes */
                 if ((foundSlash && i == uncIndex) || !foundSlash) {
                     newPath[newLength++] = separatorChar;
@@ -319,42 +301,40 @@
                 && (newLength > (uncIndex + 1) || (newLength == 2 && newPath[0] != separatorChar))) {
             newLength--;
         }
-        String tempPath = new String(newPath, 0, newLength);
-        // If it's the same keep it identical for SecurityManager purposes
-        if (!tempPath.equals(origPath)) {
-            return tempPath;
-        }
-        return origPath;
+
+        return new String(newPath, 0, newLength);
     }
 
     /**
      * Indicates whether the current context is allowed to read from this file.
-     * 
+     *
      * @return {@code true} if this file can be read, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             read request.
-     * @since Android 1.0
      */
     public boolean canRead() {
+        if (path.length() == 0) {
+            return false;
+        }
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkRead(path);
         }
+        byte[] pp = properPath(true);
         // BEGIN android-changed
-        return exists() && isReadableImpl(properPath(true));
+        return exists() && isReadableImpl(pp);
         // END android-changed
     }
 
     /**
      * Indicates whether the current context is allowed to write to this file.
-     * 
+     *
      * @return {@code true} if this file can be written, {@code false}
      *         otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0
      */
     public boolean canWrite() {
         SecurityManager security = System.getSecurityManager();
@@ -375,13 +355,12 @@
     /**
      * Returns the relative sort ordering of the paths for this file and the
      * file {@code another}. The ordering is platform dependent.
-     * 
+     *
      * @param another
      *            a file to compare this file to
      * @return an int determined by comparing the two paths. Possible values are
      *         described in the Comparable interface.
      * @see Comparable
-     * @since Android 1.0
      */
     public int compareTo(File another) {
         if (caseSensitive) {
@@ -392,13 +371,12 @@
 
     /**
      * Deletes this file. Directories must be empty before they will be deleted.
-     * 
+     *
      * @return {@code true} if this file was deleted, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             request.
      * @see java.lang.SecurityManager#checkDelete
-     * @since Android 1.0
      */
     public boolean delete() {
         SecurityManager security = System.getSecurityManager();
@@ -418,13 +396,12 @@
 
     /**
      * Schedules this file to be automatically deleted once the virtual machine
-     * terminates. This will only happen when the virtual machine terminates 
+     * terminates. This will only happen when the virtual machine terminates
      * normally as described by the Java Language Specification section 12.9.
-     * 
+     *
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             request.
-     * @since Android 1.0
      */
     public void deleteOnExit() {
         SecurityManager security = System.getSecurityManager();
@@ -439,12 +416,11 @@
     /**
      * Compares {@code obj} to this file and returns {@code true} if they
      * represent the <em>same</em> object using a path specific comparison.
-     * 
+     *
      * @param obj
      *            the object to compare this file with.
      * @return {@code true} if {@code obj} is the same as this object,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -460,13 +436,13 @@
     /**
      * Returns a boolean indicating whether this file can be found on the
      * underlying file system.
-     * 
+     *
      * @return {@code true} if this file exists, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
      * @see #getPath
-     * @since Android 1.0
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      */
     public boolean exists() {
         if (path.length() == 0) {
@@ -483,22 +459,20 @@
 
     /**
      * Returns the absolute path of this file.
-     * 
+     *
      * @return the absolute file path.
      * @see java.lang.SecurityManager#checkPropertyAccess
-     * @since Android 1.0
      */
     public String getAbsolutePath() {
         byte[] absolute = properPath(false);
-        return Util.toString(absolute);
+        return Util.toUTF8String(absolute);
     }
 
     /**
      * Returns a new file constructed using the absolute path of this file.
-     * 
+     *
      * @return a new file from this file's absolute path.
      * @see java.lang.SecurityManager#checkPropertyAccess
-     * @since Android 1.0
      */
     public File getAbsoluteFile() {
         return new File(this.getAbsolutePath());
@@ -513,42 +487,20 @@
      * with a direct directory reference. If the file does not exist,
      * getCanonicalPath() may not resolve any references and simply returns an
      * absolute path name or throws an IOException.
-     * 
+     *
      * @return the canonical path of this file.
      * @throws IOException
      *             if an I/O error occurs.
      * @see java.lang.SecurityManager#checkPropertyAccess
-     * @since Android 1.0
      */
     public String getCanonicalPath() throws IOException {
         byte[] result = properPath(false);
-
-        boolean exists = false;
-        byte[] pathBytes = result;
-        do {
-            byte[] linkBytes = getLinkImpl(pathBytes);
-            if (linkBytes == pathBytes) {
-                break;
-            }
-            if (linkBytes[0] == separatorChar) {
-                pathBytes = linkBytes;
-            } else {
-                int index = pathBytes.length - 1;
-                while (pathBytes[index] != separatorChar) {
-                    index--;
-                }
-                byte[] temp = new byte[index + 1 + linkBytes.length];
-                System.arraycopy(pathBytes, 0, temp, 0, index + 1);
-                System.arraycopy(linkBytes, 0, temp, index + 1,
-                        linkBytes.length);
-                pathBytes = temp;
-            }
-            exists = existsImpl(pathBytes);
-        } while (exists);
-        if (exists) {
-            result = pathBytes;
+        if(separatorChar == '/') {
+            // resolve the full path first
+            result = resolveLink(result, result.length, false);
+            // resolve the parent directories
+            result = resolve(result);
         }
-
         int numSeparators = 1;
         for (int i = 0; i < result.length; i++) {
             if (result[i] == separatorChar) {
@@ -614,18 +566,104 @@
         newResult[newLength] = 0;
         newResult = getCanonImpl(newResult);
         newLength = newResult.length;
-        return Util.toString(newResult, 0, newLength);
+        return Util.toUTF8String(newResult, 0, newLength);
+    }
+
+    /*
+     * Resolve symbolic links in the parent directories.
+     */
+    private byte[] resolve(byte[] newResult) throws IOException {
+        int last = 1, nextSize, linkSize;
+        byte[] linkPath = newResult, bytes;
+        boolean done, inPlace;
+        for (int i = 1; i <= newResult.length; i++) {
+            if (i == newResult.length || newResult[i] == separatorChar) {
+                done = i >= newResult.length - 1;
+                // if there is only one segment, do nothing
+                if (done && linkPath.length == 1) {
+                    return newResult;
+                }
+                inPlace = false;
+                if (linkPath == newResult) {
+                    bytes = newResult;
+                    // if there are no symbolic links, terminate the C string
+                    // instead of copying
+                    if (!done) {
+                        inPlace = true;
+                        newResult[i] = '\0';
+                    }
+                } else {
+                    nextSize = i - last + 1;
+                    linkSize = linkPath.length;
+                    if (linkPath[linkSize - 1] == separatorChar) {
+                        linkSize--;
+                    }
+                    bytes = new byte[linkSize + nextSize];
+                    System.arraycopy(linkPath, 0, bytes, 0, linkSize);
+                    System.arraycopy(newResult, last - 1, bytes, linkSize,
+                            nextSize);
+                    // the full path has already been resolved
+                }
+                if (done) {
+                    return bytes;
+                }
+                linkPath = resolveLink(bytes, inPlace ? i : bytes.length, true);
+                if (inPlace) {
+                    newResult[i] = '/';
+                }
+                last = i + 1;
+            }
+        }
+        throw new InternalError();
+    }
+
+    /*
+     * Resolve a symbolic link. While the path resolves to an existing path,
+     * keep resolving. If an absolute link is found, resolve the parent
+     * directories if resolveAbsolute is true.
+     */
+    private byte[] resolveLink(byte[] pathBytes, int length,
+            boolean resolveAbsolute) throws IOException {
+        boolean restart = false;
+        byte[] linkBytes, temp;
+        do {
+            linkBytes = getLinkImpl(pathBytes);
+            if (linkBytes == pathBytes) {
+                break;
+            }
+            if (linkBytes[0] == separatorChar) {
+                // link to an absolute path, if resolving absolute paths,
+                // resolve the parent dirs again
+                restart = resolveAbsolute;
+                pathBytes = linkBytes;
+            } else {
+                int last = length - 1;
+                while (pathBytes[last] != separatorChar) {
+                    last--;
+                }
+                last++;
+                temp = new byte[last + linkBytes.length];
+                System.arraycopy(pathBytes, 0, temp, 0, last);
+                System.arraycopy(linkBytes, 0, temp, last, linkBytes.length);
+                pathBytes = temp;
+            }
+            length = pathBytes.length;
+        } while (existsImpl(pathBytes));
+        // resolve the parent directories
+        if (restart) {
+            return resolve(pathBytes);
+        }
+        return pathBytes;
     }
 
     /**
      * Returns a new file created using the canonical path of this file.
      * Equivalent to {@code new File(this.getCanonicalPath())}.
-     * 
+     *
      * @return the new file constructed from this file's canonical path.
      * @throws IOException
      *             if an I/O error occurs.
      * @see java.lang.SecurityManager#checkPropertyAccess
-     * @since Android 1.0
      */
     public File getCanonicalFile() throws IOException {
         return new File(getCanonicalPath());
@@ -635,10 +673,9 @@
 
     /**
      * Returns the name of the file or directory represented by this file.
-     * 
+     *
      * @return this file's name or an empty string if there is no name part in
      *         the file's path.
-     * @since Android 1.0
      */
     public String getName() {
         int separatorIndex = path.lastIndexOf(separator);
@@ -650,9 +687,8 @@
      * Returns the pathname of the parent of this file. This is the path up to
      * but not including the last name. {@code null} is returned if there is no
      * parent.
-     * 
+     *
      * @return this file's parent pathname or {@code null}.
-     * @since Android 1.0
      */
     public String getParent() {
         int length = path.length(), firstInPath = 0;
@@ -677,9 +713,8 @@
      * Returns a new file made from the pathname of the parent of this file.
      * This is the path up to but not including the last name. {@code null} is
      * returned when there is no parent.
-     * 
+     *
      * @return a new file representing this file's parent or {@code null}.
-     * @since Android 1.0
      */
     public File getParentFile() {
         String tempParent = getParent();
@@ -691,9 +726,8 @@
 
     /**
      * Returns the path of this file.
-     * 
+     *
      * @return this file's path.
-     * @since Android 1.0
      */
     public String getPath() {
         return path;
@@ -702,10 +736,9 @@
     /**
      * Returns an integer hash code for the receiver. Any two objects for which
      * {@code equals} returns {@code true} must return the same hash code.
-     * 
+     *
      * @return this files's hash value.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -721,11 +754,10 @@
      * the character '/'; on Windows it is absolute if either it starts with
      * '\', '/', '\\' (to represent a file server), or a letter followed by a
      * colon.
-     * 
+     *
      * @return {@code true} if this file's pathname is absolute, {@code false}
      *         otherwise.
      * @see #getPath
-     * @since Android 1.0
      */
     public boolean isAbsolute() {
         // BEGIN android-changed
@@ -741,13 +773,12 @@
     /**
      * Indicates if this file represents a <em>directory</em> on the
      * underlying file system.
-     * 
+     *
      * @return {@code true} if this file is a directory, {@code false}
      *         otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
      */
     public boolean isDirectory() {
         if (path.length() == 0) {
@@ -765,12 +796,11 @@
     /**
      * Indicates if this file represents a <em>file</em> on the underlying
      * file system.
-     * 
+     *
      * @return {@code true} if this file is a file, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
      */
     public boolean isFile() {
         if (path.length() == 0) {
@@ -787,16 +817,15 @@
 
     /**
      * Returns whether or not this file is a hidden file as defined by the
-     * operating system. The notion of "hidden" is system-dependent. For
-     * Unix systems (like Android) a file is considered hidden if its name
-     * starts with a ".". For Windows systems there is an explicit flag in the
-     * file system for this purpose.
-     * 
+     * operating system. The notion of "hidden" is system-dependent. For Unix
+     * systems a file is considered hidden if its name starts with a ".". For
+     * Windows systems there is an explicit flag in the file system for this
+     * purpose.
+     *
      * @return {@code true} if the file is hidden, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
      */
     public boolean isHidden() {
         if (path.length() == 0) {
@@ -822,12 +851,11 @@
     /**
      * Returns the time when this file was last modified, measured in
      * milliseconds since January 1st, 1970, midnight.
-     * 
+     *
      * @return the time when this file was last modified.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
      */
     public long lastModified() {
         SecurityManager security = System.getSecurityManager();
@@ -847,7 +875,7 @@
     /**
      * Sets the time this file was last modified, measured in milliseconds since
      * January 1st, 1970, midnight.
-     * 
+     *
      * @param time
      *            the last modification time for this file.
      * @return {@code true} if the operation is successful, {@code false}
@@ -857,7 +885,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies write
      *             access to this file.
-     * @since Android 1.0
      */
     public boolean setLastModified(long time) {
         if (time < 0) {
@@ -875,13 +902,12 @@
     /**
      * Marks this file or directory to be read-only as defined by the operating
      * system.
-     * 
+     *
      * @return {@code true} if the operation is successful, {@code false}
      *         otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies write
      *             access to this file.
-     * @since Android 1.0
      */
     public boolean setReadOnly() {
         SecurityManager security = System.getSecurityManager();
@@ -895,12 +921,11 @@
 
     /**
      * Returns the length of this file in bytes.
-     * 
+     *
      * @return the number of bytes in this file.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
      */
     public long length() {
         SecurityManager security = System.getSecurityManager();
@@ -914,35 +939,42 @@
 
     /**
      * Returns an array of strings with the file names in the directory
-     * represented by this file. The result is {@ null} if this file is not a
-     * directory.
+     * represented by this file. The result is {@code null} if this file is not
+     * a directory.
      * <p>
      * The entries {@code .} and {@code ..} representing the current and parent
      * directory are not returned as part of the list.
-     * </p>
-     * 
+     *
      * @return an array of strings with file names or {@code null}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
      * @see #isDirectory
-     * @since Android 1.0
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      */
     public java.lang.String[] list() {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkRead(path);
         }
-        if (!isDirectory()) {
+
+        if (path.length() == 0) {
             return null;
         }
-        byte[][] implList = listImpl(properPath(true));
+
+        byte[] bs = properPath(true);
+        if (!isDirectoryImpl(bs) || !existsImpl(bs) || !isReadableImpl(bs)) {
+            return null;
+        }
+
+        byte[][] implList = listImpl(bs);
         if (implList == null) {
+            // empty list
             return new String[0];
         }
         String result[] = new String[implList.length];
         for (int index = 0; index < implList.length; index++) {
-            result[index] = Util.toString(implList[index]);
+            result[index] = Util.toUTF8String(implList[index]);
         }
         return result;
     }
@@ -952,13 +984,13 @@
      * file. The result is {@code null} if this file is not a directory. The
      * paths of the files in the array are absolute if the path of this file is
      * absolute, they are relative otherwise.
-     * 
+     *
      * @return an array of files or {@code null}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
      * @see #list
-     * @since Android 1.0
+     * @see #isDirectory
      */
     public File[] listFiles() {
         String[] tempNames = list();
@@ -982,8 +1014,7 @@
      * <p>
      * The entries {@code .} and {@code ..} representing the current and parent
      * directories are not returned as part of the list.
-     * </p>
-     * 
+     *
      * @param filter
      *            the filter to match names against, may be {@code null}.
      * @return an array of files or {@code null}.
@@ -991,7 +1022,9 @@
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
      * @see #list(FilenameFilter filter)
-     * @since Android 1.0
+     * @see #getPath
+     * @see #isDirectory
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      */
     public File[] listFiles(FilenameFilter filter) {
         String[] tempNames = list(filter);
@@ -1014,25 +1047,33 @@
      * <p>
      * The entries {@code .} and {@code ..} representing the current and parent
      * directories are not returned as part of the list.
-     * </p>
-     * 
+     *
      * @param filter
      *            the filter to match names against, may be {@code null}.
      * @return an array of files or {@code null}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
+     * @see #getPath
+     * @see #isDirectory
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      */
     public File[] listFiles(FileFilter filter) {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkRead(path);
         }
-        if (!isDirectory()) {
+
+        if (path.length() == 0) {
             return null;
         }
-        byte[][] implList = listImpl(properPath(true));
+
+        byte[] bs = properPath(true);
+        if (!isDirectoryImpl(bs) || !existsImpl(bs) || !isReadableImpl(bs)) {
+            return null;
+        }
+
+        byte[][] implList = listImpl(bs);
         if (implList == null) {
             return new File[0];
         }
@@ -1056,38 +1097,46 @@
      * <p>
      * The entries {@code .} and {@code ..} representing the current and parent
      * directories are not returned as part of the list.
-     * </p>
-     * 
+     *
      * @param filter
      *            the filter to match names against, may be {@code null}.
      * @return an array of files or {@code null}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
+     * @see #getPath
+     * @see #isDirectory
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      */
     public java.lang.String[] list(FilenameFilter filter) {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkRead(path);
         }
-        if (!isDirectory()) {
+
+        if (path.length() == 0) {
             return null;
         }
-        byte[][] implList = listImpl(properPath(true));
+
+        byte[] bs = properPath(true);
+        if (!isDirectoryImpl(bs) || !existsImpl(bs) || !isReadableImpl(bs)) {
+            return null;
+        }
+
+        byte[][] implList = listImpl(bs);
         if (implList == null) {
+            // empty list
             return new String[0];
         }
-        java.util.Vector<String> tempResult = new java.util.Vector<String>();
+        List<String> tempResult = new ArrayList<String>();
         for (int index = 0; index < implList.length; index++) {
             String aName = Util.toString(implList[index]);
             if (filter == null || filter.accept(this, aName)) {
-                tempResult.addElement(aName);
+                tempResult.add(aName);
             }
         }
-        String[] result = new String[tempResult.size()];
-        tempResult.copyInto(result);
-        return result;
+
+        return tempResult.toArray(new String[tempResult.size()]);
     }
 
     private synchronized static native byte[][] listImpl(byte[] path);
@@ -1095,14 +1144,13 @@
     /**
      * Creates the directory named by the trailing filename of this file. Does
      * not create the complete path required to create this directory.
-     * 
+     *
      * @return {@code true} if the directory has been created, {@code false}
      *         otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies write
      *             access for this file.
      * @see #mkdirs
-     * @since Android 1.0
      */
     public boolean mkdir() {
         SecurityManager security = System.getSecurityManager();
@@ -1117,7 +1165,7 @@
     /**
      * Creates the directory named by the trailing filename of this file,
      * including the complete directory path required to create this directory.
-     * 
+     *
      * @return {@code true} if the necessary directories have been created,
      *         {@code false} if the target directory already exists or one of
      *         the directories can not be created.
@@ -1125,7 +1173,6 @@
      *             if a {@code SecurityManager} is installed and it denies write
      *             access for this file.
      * @see #mkdir
-     * @since Android 1.0
      */
     public boolean mkdirs() {
         /* If the terminal directory already exists, answer false */
@@ -1151,7 +1198,7 @@
     /**
      * Creates a new, empty file on the file system according to the path
      * information stored in this file.
-     * 
+     *
      * @return {@code true} if the file has been created, {@code false} if it
      *         already exists.
      * @throws IOException
@@ -1160,7 +1207,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies write
      *             access for this file.
-     * @since Android 1.0
      */
     public boolean createNewFile() throws IOException {
         SecurityManager security = System.getSecurityManager();
@@ -1215,10 +1261,11 @@
 
     /**
      * Creates an empty temporary file using the given prefix and suffix as part
-     * of the file name. If suffix is null, {@code .tmp} is used. This method
-     * is a convenience method that calls {@link #createTempFile(String, String,
-     * File)} with the third argument being {@code null}.
-     * 
+     * of the file name. If suffix is {@code null}, {@code .tmp} is used. This
+     * method is a convenience method that calls
+     * {@link #createTempFile(String, String, File)} with the third argument
+     * being {@code null}.
+     *
      * @param prefix
      *            the prefix to the temp file name.
      * @param suffix
@@ -1226,7 +1273,6 @@
      * @return the temporary file.
      * @throws IOException
      *             if an error occurs when writing the file.
-     * @since Android 1.0
      */
     public static File createTempFile(String prefix, String suffix)
             throws IOException {
@@ -1236,7 +1282,7 @@
     /**
      * Creates an empty temporary file in the given directory using the given
      * prefix and suffix as part of the file name.
-     * 
+     *
      * @param prefix
      *            the prefix to the temp file name.
      * @param suffix
@@ -1246,26 +1292,30 @@
      *            {@code null} for the default location for temporary files,
      *            which is taken from the "java.io.tmpdir" system property. It
      *            may be necessary to set this property to an existing, writable
-     *            directory for this method to work properly. 
+     *            directory for this method to work properly.
      * @return the temporary file.
      * @throws IllegalArgumentException
      *             if the length of {@code prefix} is less than 3.
      * @throws IOException
      *             if an error occurs when writing the file.
-     * @since Android 1.0
      */
+    @SuppressWarnings("nls")
     public static File createTempFile(String prefix, String suffix,
             File directory) throws IOException {
         // Force a prefix null check first
         if (prefix.length() < 3) {
-            throw new IllegalArgumentException(Msg.getString("K006b")); //$NON-NLS-1$
+            throw new IllegalArgumentException(Msg.getString("K006b"));
         }
-        String newSuffix = suffix == null ? ".tmp" : suffix; //$NON-NLS-1$
-        String tmpDir = "."; //$NON-NLS-1$
-        tmpDir = AccessController.doPrivileged(new PriviAction<String>(
-                "java.io.tmpdir", ".")); //$NON-NLS-1$//$NON-NLS-2$
-        File result, tmpDirFile = directory == null ? new File(tmpDir)
-                : directory;
+        String newSuffix = suffix == null ? ".tmp" : suffix;
+        File tmpDirFile;
+        if (directory == null) {
+            String tmpDir = AccessController.doPrivileged(
+                new PriviAction<String>("java.io.tmpdir", "."));
+            tmpDirFile = new File(tmpDir);
+        } else {
+            tmpDirFile = directory;
+        }
+        File result;
         do {
             result = genTempFile(prefix, newSuffix, tmpDirFile);
         } while (!result.createNewFile());
@@ -1274,7 +1324,7 @@
 
     private static File genTempFile(String prefix, String suffix, File directory) {
         if (counter == 0) {
-            int newInt = new java.util.Random().nextInt();
+            int newInt = new SecureRandom().nextInt();
             counter = ((newInt / 65535) & 0xFFFF) + 0x2710;
         }
         StringBuilder newName = new StringBuilder();
@@ -1290,7 +1340,7 @@
      * Returns a string representing the proper path for this file. If this file
      * path is absolute, the user.dir property is not prepended, otherwise it
      * is.
-     * 
+     *
      * @param internal
      *            is user.dir internal.
      * @return the proper path.
@@ -1311,7 +1361,7 @@
             userdir = System.getProperty("user.dir"); //$NON-NLS-1$
         }
         if (path.length() == 0) {
-            return properPath = Util.getBytes(userdir);
+            return properPath = Util.getUTF8Bytes(userdir);
         }
         int length = userdir.length();
         if (length > 0 && userdir.charAt(length - 1) == separatorChar) {
@@ -1328,14 +1378,13 @@
     /**
      * Renames this file to the name represented by the {@code dest} file. This
      * works for both normal files and directories.
-     * 
+     *
      * @param dest
      *            the file containing the new name.
      * @return {@code true} if the File was renamed, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies write
      *             access for this file or the {@code dest} file.
-     * @since Android 1.0
      */
     public boolean renameTo(java.io.File dest) {
         SecurityManager security = System.getSecurityManager();
@@ -1351,9 +1400,8 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * file.
-     * 
+     *
      * @return a printable representation of this file.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -1364,22 +1412,22 @@
      * Returns a Uniform Resource Identifier for this file. The URI is system
      * dependent and may not be transferable between different operating / file
      * systems.
-     * 
+     *
      * @return an URI for this file.
-     * @since Android 1.0
      */
+    @SuppressWarnings("nls")
     public URI toURI() {
         String name = getAbsoluteName();
         try {
-            if (!name.startsWith("/")) { //$NON-NLS-1$
+            if (!name.startsWith("/")) {
                 // start with sep.
-                return new URI("file", null, //$NON-NLS-1$
-                        new StringBuilder(name.length() + 1).append('/')
-                                .append(name).toString(), null, null);
-            } else if (name.startsWith("//")) { //$NON-NLS-1$
-                return new URI("file", name, null); // UNC path //$NON-NLS-1$
+                return new URI("file", null, new StringBuilder(
+                        name.length() + 1).append('/').append(name).toString(),
+                        null, null);
+            } else if (name.startsWith("//")) {
+                return new URI("file", "", name, null); // UNC path
             }
-            return new URI("file", null, name, null, null); //$NON-NLS-1$
+            return new URI("file", null, name, null, null);
         } catch (URISyntaxException e) {
             // this should never happen
             return null;
@@ -1390,22 +1438,23 @@
      * Returns a Uniform Resource Locator for this file. The URL is system
      * dependent and may not be transferable between different operating / file
      * systems.
-     * 
-     * @return an URL for this file.
+     *
+     * @return a URL for this file.
      * @throws java.net.MalformedURLException
-     *             if the path cannot be transformed into an URL.
-     * @since Android 1.0
+     *             if the path cannot be transformed into a URL.
      */
+    @SuppressWarnings("nls")
     public URL toURL() throws java.net.MalformedURLException {
         String name = getAbsoluteName();
-        if (!name.startsWith("/")) { //$NON-NLS-1$
+        if (!name.startsWith("/")) {
             // start with sep.
-            return new URL("file", "", -1, new StringBuilder(name.length() + 1) //$NON-NLS-1$ //$NON-NLS-2$
-                    .append('/').append(name).toString(), null);
-        } else if (name.startsWith("//")) { //$NON-NLS-1$
-            return new URL("file:" + name); // UNC path //$NON-NLS-1$
+            return new URL(
+                    "file", EMPTY_STRING, -1, new StringBuilder(name.length() + 1) //$NON-NLS-1$
+                            .append('/').append(name).toString(), null);
+        } else if (name.startsWith("//")) {
+            return new URL("file:" + name); // UNC path
         }
-        return new URL("file", "", -1, name, null); //$NON-NLS-1$ //$NON-NLS-2$
+        return new URL("file", EMPTY_STRING, -1, name, null);
     }
 
     private String getAbsoluteName() {
@@ -1436,60 +1485,3 @@
         path = path.replace(inSeparator, separatorChar);
     }
 }
-
-// BEGIN android-added
-/**
- * Implements the actual DeleteOnExit mechanism. Is registered as a shutdown
- * hook in the Runtime, once it is actually being used.
- */
-class DeleteOnExit extends Thread {
-    
-    /**
-     * Our singleton instance.
-     */
-    private static DeleteOnExit instance;
-    
-    /**
-     * Our list of files scheduled for deletion.
-     */
-    private ArrayList<String> files = new ArrayList<String>();
-    
-    /**
-     * Returns our singleton instance, creating it if necessary.
-     */
-    public static synchronized DeleteOnExit getInstance() {
-        if (instance == null) {
-            instance = new DeleteOnExit();
-            Runtime.getRuntime().addShutdownHook(instance);
-        }
-        
-        return instance;
-    }
-    
-    /**
-     * Schedules a file for deletion.
-     * 
-     * @param filename The file to delete.
-     */
-    public void addFile(String filename) {
-        synchronized(files) {
-            if (!files.contains(filename)) {
-                files.add(filename);
-            }
-        }
-    }
-    
-    /**
-     * Does the actual work. Note we (a) first sort the files lexicographically
-     * and then (b) delete them in reverse order. This is to make sure files
-     * get deleted before their parent directories.
-     */
-    @Override
-    public void run() {
-        Collections.sort(files);
-        for (int i = files.size() - 1; i >= 0; i--) {
-            new File(files.get(i)).delete();
-        }
-    }
-}
-// END android-added
diff --git a/luni/src/main/java/java/io/FileDescriptor.java b/luni/src/main/java/java/io/FileDescriptor.java
index e131c88..15eb983 100644
--- a/luni/src/main/java/java/io/FileDescriptor.java
+++ b/luni/src/main/java/java/io/FileDescriptor.java
@@ -30,33 +30,25 @@
  * System.err streams respectively.
  * <p>
  * Applications should not create new FileDescriptors.
- * 
+ *
  * @see FileInputStream#getFD()
  * @see FileOutputStream#getFD()
  * @see RandomAccessFile#getFD()
- * 
- * @since Android 1.0
  */
 public final class FileDescriptor {
 
     /**
      * The FileDescriptor representing standard input.
-     * 
-     * @since Android 1.0
      */
     public static final FileDescriptor in = new FileDescriptor();
 
     /**
      * FileDescriptor representing standard out.
-     * 
-     * @since Android 1.0
      */
     public static final FileDescriptor out = new FileDescriptor();
 
     /**
      * FileDescriptor representing standard error.
-     * 
-     * @since Android 1.0
      */
     public static final FileDescriptor err = new FileDescriptor();
 
@@ -68,8 +60,8 @@
      */
     int descriptor = -1;
     // END android-changed
-    
-    boolean readOnly = false; 
+
+    boolean readOnly = false;
 
     private static native void oneTimeInitialization();
 
@@ -84,8 +76,6 @@
     /**
      * Constructs a new FileDescriptor containing an invalid handle. The
      * contained handle is usually modified by native code at a later point.
-     * 
-     * @since Android 1.0
      */
     public FileDescriptor() {
         super();
@@ -94,10 +84,9 @@
     /**
      * Ensures that data which is buffered within the underlying implementation
      * is written out to the appropriate device before returning.
-     * 
+     *
      * @throws SyncFailedException
      *             when the operation fails.
-     * @since Android 1.0
      */
     public void sync() throws SyncFailedException {
         // if the descriptor is a read-only one, do nothing
@@ -105,15 +94,16 @@
             syncImpl();
         }
     }
-    
+
     private native void syncImpl() throws SyncFailedException;
 
     /**
      * Indicates whether this FileDescriptor is valid.
-     * 
+     *
      * @return {@code true} if this FileDescriptor is valid, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
-    public native boolean valid();
+    public boolean valid() {
+        return descriptor != -1;
+    }
 }
diff --git a/luni/src/main/java/java/io/FileFilter.java b/luni/src/main/java/java/io/FileFilter.java
index 674ce13..5638dd9 100644
--- a/luni/src/main/java/java/io/FileFilter.java
+++ b/luni/src/main/java/java/io/FileFilter.java
@@ -24,21 +24,18 @@
 /**
  * An interface for filtering {@link File} objects based on their names
  * or other information.
- * 
+ *
  * @see File#listFiles(FileFilter)
- * 
- * @since Android 1.0
  */
 public interface FileFilter {
 
     /**
      * Indicating whether a specific file should be included in a pathname list.
-     * 
+     *
      * @param pathname
      *            the abstract file to check.
      * @return {@code true} if the file should be included, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public abstract boolean accept(File pathname);
 }
diff --git a/luni/src/main/java/java/io/FileInputStream.java b/luni/src/main/java/java/io/FileInputStream.java
index c39d1e7..1243262 100644
--- a/luni/src/main/java/java/io/FileInputStream.java
+++ b/luni/src/main/java/java/io/FileInputStream.java
@@ -31,11 +31,9 @@
  * Since this may induce some performance penalty, in particular if many small
  * read requests are made, a FileInputStream is often wrapped by a
  * BufferedInputStream.
- * 
+ *
  * @see BufferedInputStream
  * @see FileOutputStream
- * 
- * @since Android 1.0
  */
 public class FileInputStream extends InputStream implements Closeable {
     /**
@@ -58,7 +56,7 @@
 
     /**
      * Constructs a new {@code FileInputStream} based on {@code file}.
-     * 
+     *
      * @param file
      *            the file from which this stream reads.
      * @throws FileNotFoundException
@@ -66,7 +64,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             read request.
-     * @since Android 1.0
      */
     public FileInputStream(File file) throws FileNotFoundException {
         super();
@@ -90,7 +87,7 @@
      * Constructs a new {@code FileInputStream} on the {@link FileDescriptor}
      * {@code fd}. The file must already be open, therefore no
      * {@code FileNotFoundException} will be thrown.
-     * 
+     *
      * @param fd
      *            the FileDescriptor from which this stream reads.
      * @throws NullPointerException
@@ -98,7 +95,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             read request.
-     * @since Android 1.0
      */
     public FileInputStream(FileDescriptor fd) {
         super();
@@ -121,7 +117,7 @@
      * Constructs a new {@code FileInputStream} on the file named
      * {@code fileName}. The path of {@code fileName} may be absolute or
      * relative to the system property {@code "user.dir"}.
-     * 
+     *
      * @param fileName
      *            the path and name of the file from which this stream reads.
      * @throws FileNotFoundException
@@ -129,7 +125,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             read request.
-     * @since Android 1.0
      */
     public FileInputStream(String fileName) throws FileNotFoundException {
         this(null == fileName ? (File) null : new File(fileName));
@@ -139,11 +134,10 @@
      * Returns the number of bytes that are available before this stream will
      * block. This method always returns the size of the file minus the current
      * position.
-     * 
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if an error occurs in this stream.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -157,7 +151,7 @@
         // use.
 
         return fileSystem.ioctlAvailable(fd.descriptor);
-        // END android-added 
+        // END android-added
 
         // BEGIN android-deleted
         // synchronized (repositioningLock) {
@@ -179,10 +173,9 @@
 
     /**
      * Closes this stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to close this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -203,10 +196,9 @@
     /**
      * Ensures that all resources for this stream are released when it is about
      * to be garbage collected.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to finalize this stream.
-     * @since Android 1.0
      */
     @Override
     protected void finalize() throws IOException {
@@ -220,10 +212,8 @@
      * that is the same as the current position of this stream within the file.
      * All changes made to the underlying file descriptor state via the channel
      * are visible by the input stream and vice versa.
-     * </p>
-     * 
+     *
      * @return the file channel for this stream.
-     * @since Android 1.0
      */
     public FileChannel getChannel() {
         // BEGIN android-changed
@@ -240,12 +230,11 @@
     /**
      * Returns the {@link FileDescriptor} representing the operating system
      * resource for this stream.
-     * 
+     *
      * @return the {@code FileDescriptor} for this stream.
      * @throws IOException
      *             if an error occurs while getting this stream's
      *             {@code FileDescriptor}.
-     * @since Android 1.0
      */
     public final FileDescriptor getFD() throws IOException {
         return fd;
@@ -255,11 +244,10 @@
      * Reads a single byte from this stream and returns it as an integer in the
      * range from 0 to 255. Returns -1 if the end of this stream has been
      * reached.
-     * 
+     *
      * @return the byte read or -1 if the end of this stream has been reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -271,14 +259,13 @@
     /**
      * Reads bytes from this stream and stores them in the byte array
      * {@code buffer}.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @return the number of bytes actually read or -1 if the end of the stream
      *         has been reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer) throws IOException {
@@ -288,7 +275,7 @@
     /**
      * Reads at most {@code count} bytes from this stream and stores them in the
      * byte array {@code buffer} starting at {@code offset}.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -304,7 +291,6 @@
      *             {@code buffer}.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int count) throws IOException {
@@ -338,14 +324,13 @@
      * Skips {@code count} number of bytes in this stream. Subsequent
      * {@code read()}'s will not return these bytes unless {@code reset()} is
      * used. This method may perform multiple reads to read {@code count} bytes.
-     * 
+     *
      * @param count
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if {@code count < 0}, this stream is closed or another
      *             IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
diff --git a/luni/src/main/java/java/io/FileNotFoundException.java b/luni/src/main/java/java/io/FileNotFoundException.java
index a0f5bc6..2ab9e89 100644
--- a/luni/src/main/java/java/io/FileNotFoundException.java
+++ b/luni/src/main/java/java/io/FileNotFoundException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when a file specified by a program cannot be found.
- * 
- * @since Android 1.0
  */
 public class FileNotFoundException extends IOException {
 
@@ -29,8 +27,6 @@
     /**
      * Constructs a new {@code FileNotFoundException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public FileNotFoundException() {
         super();
@@ -42,7 +38,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public FileNotFoundException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/FileOutputStream.java b/luni/src/main/java/java/io/FileOutputStream.java
index 00ae5d8..f0b25c9 100644
--- a/luni/src/main/java/java/io/FileOutputStream.java
+++ b/luni/src/main/java/java/io/FileOutputStream.java
@@ -31,10 +31,10 @@
  * Since this may induce some performance penalty, in particular if many small
  * write requests are made, a FileOutputStream is often wrapped by a
  * BufferedOutputStream.
- * 
+ *
  * @see BufferedOutputStream
  * @see FileInputStream
- * 
+ *
  * @since Android 1.0
  */
 public class FileOutputStream extends OutputStream implements Closeable {
@@ -55,7 +55,7 @@
     /**
      * Constructs a new FileOutputStream on the File {@code file}. If the file
      * exists, it is overwritten.
-     * 
+     *
      * @param file
      *            the file to which this stream writes.
      * @throws FileNotFoundException
@@ -63,7 +63,7 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0            
+     * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
      */
     public FileOutputStream(File file) throws FileNotFoundException {
         this(file, false);
@@ -73,7 +73,7 @@
      * Constructs a new FileOutputStream on the File {@code file}. The
      * parameter {@code append} determines whether or not the file is opened and
      * appended to or just opened and overwritten.
-     * 
+     *
      * @param file
      *            the file to which this stream writes.
      * @param append
@@ -83,7 +83,8 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0
+     * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
+     * @see java.lang.SecurityManager#checkWrite(String)
      */
     public FileOutputStream(File file, boolean append)
             throws FileNotFoundException {
@@ -104,7 +105,7 @@
      * Constructs a new FileOutputStream on the FileDescriptor {@code fd}. The
      * file must already be open, therefore no {@code FileNotFoundException}
      * will be thrown.
-     * 
+     *
      * @param fd
      *            the FileDescriptor to which this stream writes.
      * @throws NullPointerException
@@ -112,7 +113,7 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0
+     * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
      */
     public FileOutputStream(FileDescriptor fd) {
         super();
@@ -133,7 +134,7 @@
      * Constructs a new FileOutputStream on the file named {@code filename}. If
      * the file exists, it is overwritten. The {@code filename} may be absolute
      * or relative to the system property {@code "user.dir"}.
-     * 
+     *
      * @param filename
      *            the name of the file to which this stream writes.
      * @throws FileNotFoundException
@@ -141,7 +142,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0
      */
     public FileOutputStream(String filename) throws FileNotFoundException {
         this(filename, false);
@@ -152,17 +152,16 @@
      * The parameter {@code append} determines whether or not the file is opened
      * and appended to or just opened and overwritten. The {@code filename} may
      * be absolute or relative to the system property {@code "user.dir"}.
-     * 
-     * @param append
-     *            indicates whether or not to append to an existing file.
+     *
      * @param filename
      *            the name of the file to which this stream writes.
+     * @param append
+     *            indicates whether or not to append to an existing file.
      * @throws FileNotFoundException
      *             if the file cannot be opened for writing.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0
      */
     public FileOutputStream(String filename, boolean append)
             throws FileNotFoundException {
@@ -172,10 +171,9 @@
     /**
      * Closes this stream. This implementation closes the underlying operating
      * system resources allocated to represent this stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to close this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -204,10 +202,9 @@
     /**
      * Frees any resources allocated for this stream before it is garbage
      * collected. This method is called from the Java Virtual Machine.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to finalize this stream.
-     * @since Android 1.0
      */
     @Override
     protected void finalize() throws IOException {
@@ -221,10 +218,8 @@
      * file that is the same as the current position of this stream within the
      * file. All changes made to the underlying file descriptor state via the
      * channel are visible by the output stream and vice versa.
-     * </p>
-     * 
+     *
      * @return the file channel representation for this stream.
-     * @since Android 1.0
      */
     public FileChannel getChannel() {
         return channel;
@@ -233,12 +228,11 @@
     /**
      * Returns a FileDescriptor which represents the lowest level representation
      * of an operating system stream resource.
-     * 
+     *
      * @return a FileDescriptor representing this stream.
      * @throws IOException
      *             if an error occurs attempting to get the FileDescriptor of
      *             this stream.
-     * @since Android 1.0
      */
     public final FileDescriptor getFD() throws IOException {
         return fd;
@@ -247,13 +241,12 @@
     /**
      * Writes the entire contents of the byte array {@code buffer} to this
      * stream.
-     * 
+     *
      * @param buffer
      *            the buffer to be written to the file.
      * @throws IOException
      *             if this stream is closed or an error occurs attempting to
      *             write to this stream.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer) throws IOException {
@@ -263,7 +256,7 @@
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * {@code offset} to this stream.
-     * 
+     *
      * @param buffer
      *            the buffer to write to this stream.
      * @param offset
@@ -279,7 +272,6 @@
      *             write to this stream.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int count) throws IOException {
@@ -308,13 +300,12 @@
     /**
      * Writes the specified byte {@code oneByte} to this stream. Only the low
      * order byte of the integer {@code oneByte} is written.
-     * 
+     *
      * @param oneByte
      *            the byte to be written.
      * @throws IOException
      *             if this stream is closed an error occurs attempting to write
      *             to this stream.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneByte) throws IOException {
diff --git a/luni/src/main/java/java/io/FilePermission.java b/luni/src/main/java/java/io/FilePermission.java
index 3702ac7..610adee 100644
--- a/luni/src/main/java/java/io/FilePermission.java
+++ b/luni/src/main/java/java/io/FilePermission.java
@@ -34,7 +34,6 @@
  * and directories contained in that directory. If the pathname
  * ends in {@code /-}, it includes all the files and directories in that
  * directory <i>recursively</i>. The following pathnames have a special meaning:
- * </p>
  * <ul>
  *   <li>
  *     "*": all files in the current directory;
@@ -46,8 +45,6 @@
  *     "&lt;&lt;ALL FILES&gt;&gt;": any file and directory in the file system.
  *   </li>
  * </ul>
- * 
- * @since Android 1.0
  */
 public final class FilePermission extends Permission implements Serializable {
     
@@ -87,8 +84,7 @@
      *             it contains a string other than "read", "write", "execute"
      *             and "delete".
      * @throws NullPointerException
-     *             if {@code path} is null.
-     * @since Android 1.0
+     *             if {@code path} is {@code null}.
      */
     public FilePermission(String path, String actions) {
         super(path);
@@ -197,7 +193,6 @@
      * Returns the actions associated with this file permission.
      * 
      * @return the actions associated with this file permission.
-     * @since Android 1.0
      */
     @Override
     public String getActions() {
@@ -213,7 +208,6 @@
      *            the object to check equality with.
      * @return {@code true} if this file permission is equal to {@code obj},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -245,7 +239,6 @@
      *            the permission to check.
      * @return {@code true} if the argument permission is implied by the
      *         receiver, and {@code false} if it is not.
-     * @since Android 1.0
      */
     @Override
     public boolean implies(Permission p) {
@@ -361,7 +354,6 @@
      * 
      * @return A new PermissionCollection object suitable for storing
      *         FilePermission objects.
-     * @since Android 1.0
      */
     @Override
     public PermissionCollection newPermissionCollection() {
@@ -372,7 +364,6 @@
      * Calculates the hash code value for this file permission.
      * 
      * @return the hash code value for this file permission.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
diff --git a/luni/src/main/java/java/io/FilePermissionCollection.java b/luni/src/main/java/java/io/FilePermissionCollection.java
index 9d49b79..3049442 100644
--- a/luni/src/main/java/java/io/FilePermissionCollection.java
+++ b/luni/src/main/java/java/io/FilePermissionCollection.java
@@ -25,8 +25,6 @@
 /**
  * Collects {@link FilePermission} objects and allows to query whether a
  * particular permission is implied by it.
- * 
- * @since Android 1.0
  */
 final class FilePermissionCollection extends PermissionCollection implements
         Serializable {
diff --git a/luni/src/main/java/java/io/FileReader.java b/luni/src/main/java/java/io/FileReader.java
index 90cd454..c62fdeb 100644
--- a/luni/src/main/java/java/io/FileReader.java
+++ b/luni/src/main/java/java/io/FileReader.java
@@ -27,8 +27,6 @@
  * 
  * @see BufferedReader
  * @see FileWriter
- *
- * @since Android 1.0
  */
 public class FileReader extends InputStreamReader {
 
@@ -39,7 +37,6 @@
      *            a File to be opened for reading characters from.
      * @throws FileNotFoundException
      *             if {@code file} does not exist.
-     * @since Android 1.0             
      */
     public FileReader(File file) throws FileNotFoundException {
         super(new FileInputStream(file));
@@ -52,7 +49,6 @@
      * 
      * @param fd
      *            the previously opened file descriptor.
-     * @since Android 1.0
      */
     public FileReader(FileDescriptor fd) {
         super(new FileInputStream(fd));
@@ -65,7 +61,6 @@
      *            an absolute or relative path specifying the file to open.
      * @throws FileNotFoundException
      *             if there is no file named {@code filename}.
-     * @since Android 1.0
      */
     public FileReader(String filename) throws FileNotFoundException {
         super(new FileInputStream(filename));
diff --git a/luni/src/main/java/java/io/FileWriter.java b/luni/src/main/java/java/io/FileWriter.java
index 63aee88..86a9af8 100644
--- a/luni/src/main/java/java/io/FileWriter.java
+++ b/luni/src/main/java/java/io/FileWriter.java
@@ -27,8 +27,6 @@
  * 
  * @see BufferedWriter
  * @see FileReader
- *
- * @since Android 1.0
  */
 public class FileWriter extends OutputStreamWriter {
 
@@ -39,7 +37,6 @@
      *            the non-null File to write bytes to.
      * @throws IOException
      *             if {@code file} cannot be opened for writing.
-     * @since Android 1.0
      */
     public FileWriter(File file) throws IOException {
         super(new FileOutputStream(file));
@@ -56,7 +53,6 @@
      *            indicates whether or not to append to an existing file.
      * @throws IOException
      *             if the {@code file} cannot be opened for writing.
-     * @since Android 1.0
      */
     public FileWriter(File file, boolean append) throws IOException {
         super(new FileOutputStream(file, append));
@@ -67,7 +63,6 @@
      * 
      * @param fd
      *            the non-null FileDescriptor to write bytes to.
-     * @since Android 1.0
      */
     public FileWriter(FileDescriptor fd) {
         super(new FileOutputStream(fd));
@@ -80,7 +75,6 @@
      *            the non-null name of the file to write bytes to.
      * @throws IOException
      *             if the file cannot be opened for writing.
-     * @since Android 1.0
      */
     public FileWriter(String filename) throws IOException {
         super(new FileOutputStream(new File(filename)));
@@ -97,7 +91,6 @@
      *            indicates whether or not to append to an existing file.
      * @throws IOException
      *             if the {@code file} cannot be opened for writing.
-     * @since Android 1.0
      */
     public FileWriter(String filename, boolean append) throws IOException {
         super(new FileOutputStream(filename, append));
diff --git a/luni/src/main/java/java/io/FilenameFilter.java b/luni/src/main/java/java/io/FilenameFilter.java
index 40a6cca..a51bcc6 100644
--- a/luni/src/main/java/java/io/FilenameFilter.java
+++ b/luni/src/main/java/java/io/FilenameFilter.java
@@ -21,9 +21,8 @@
  * An interface for filtering {@link File} objects based on their names
  * or the directory they reside in.
  * 
+ * @see File
  * @see File#list(FilenameFilter)
- * 
- * @since Android 1.0
  */
 public interface FilenameFilter {
 
@@ -34,10 +33,9 @@
      *            the directory in which the {@code filename} was found.
      * @param filename
      *            the name of the file in {@code dir} to test.
-     * @return  {@code true} if the filename matches the filter 
-     *            and can be included in the list, {@code false} 
+     * @return  {@code true} if the filename matches the filter
+     *            and can be included in the list, {@code false}
      *            otherwise.
-     * @since Android 1.0
      */
     public abstract boolean accept(File dir, String filename);
 }
diff --git a/luni/src/main/java/java/io/FilterInputStream.java b/luni/src/main/java/java/io/FilterInputStream.java
index 5110060..0baa409 100644
--- a/luni/src/main/java/java/io/FilterInputStream.java
+++ b/luni/src/main/java/java/io/FilterInputStream.java
@@ -26,21 +26,13 @@
  * from this class.
  * 
  * @see FilterOutputStream
- * 
- * @since Android 1.0
  */
 public class FilterInputStream extends InputStream {
 
-    // BEGIN android-changed
-    // The underlying input stream address should not be cached in a register.
-    // This was changed to be more close to the RI.
     /**
      * The source input stream that is filtered.
-     * 
-     * @since Android 1.0
      */
     protected volatile InputStream in;
-    // END android-changed
 
     /**
      * Constructs a new {@code FilterInputStream} with the specified input
@@ -48,7 +40,6 @@
      * 
      * @param in
      *            the non-null InputStream to filter reads on.
-     * @since Android 1.0
      */
     protected FilterInputStream(InputStream in) {
         super();
@@ -57,12 +48,11 @@
 
     /**
      * Returns the number of bytes that are available before this stream will
-     * block. 
-     *  
+     * block.
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if an error occurs in this stream.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -74,7 +64,6 @@
      * 
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -88,14 +77,12 @@
      * position, provided that {@code readlimit} has not been surpassed.
      * <p>
      * This implementation sets a mark in the filtered stream.
-     * </p>
-     * 
+     *
      * @param readlimit
      *            the number of bytes that can be read from this stream before
      *            the mark is invalidated.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public synchronized void mark(int readlimit) {
@@ -112,7 +99,6 @@
      * @see #mark(int)
      * @see #reset()
      * @see #skip(long)
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -128,7 +114,6 @@
      *         reached.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -147,7 +132,6 @@
      *         filtered stream has been reached while reading.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer) throws IOException {
@@ -172,7 +156,6 @@
      *         filtered stream has been reached while reading.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int count) throws IOException {
@@ -189,7 +172,6 @@
      *             bytes have been read since setting the mark.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public synchronized void reset() throws IOException {
@@ -208,12 +190,10 @@
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
      * @see #mark(int)
-     * @see #reset()  
-     * @since Android 1.0          
+     * @see #reset()
      */
     @Override
     public long skip(long count) throws IOException {
         return in.skip(count);
     }
 }
-
diff --git a/luni/src/main/java/java/io/FilterOutputStream.java b/luni/src/main/java/java/io/FilterOutputStream.java
index 212b22e..66765f9 100644
--- a/luni/src/main/java/java/io/FilterOutputStream.java
+++ b/luni/src/main/java/java/io/FilterOutputStream.java
@@ -26,27 +26,22 @@
  * decompression of the underlying stream. Output streams that wrap another
  * output stream and provide some additional functionality on top of it usually
  * inherit from this class.
- * 
+ *
  * @see FilterOutputStream
- * 
- * @since Android 1.0
  */
 public class FilterOutputStream extends OutputStream {
 
     /**
      * The target output stream for this filter stream.
-     * 
-     * @since Android 1.0
      */
     protected OutputStream out;
 
     /**
      * Constructs a new {@code FilterOutputStream} with {@code out} as its
      * target stream.
-     * 
+     *
      * @param out
      *            the target stream that this stream writes to.
-     * @since Android 1.0
      */
     public FilterOutputStream(OutputStream out) {
         this.out = out;
@@ -54,10 +49,9 @@
 
     /**
      * Closes this stream. This implementation closes the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to close this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -73,10 +67,9 @@
     /**
      * Ensures that all pending data is sent out to the target stream. This
      * implementation flushes the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to flush this stream.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -87,12 +80,11 @@
      * Writes the entire contents of the byte array {@code buffer} to this
      * stream. This implementation writes the {@code buffer} to the target
      * stream.
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @throws IOException
      *             if an I/O error occurs while writing to this stream.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer) throws IOException {
@@ -105,7 +97,7 @@
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * {@code offset} to the target stream.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -118,7 +110,6 @@
      *             {@code buffer}.
      * @throws IOException
      *             if an I/O error occurs while writing to this stream.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int count) throws IOException {
@@ -149,12 +140,11 @@
     /**
      * Writes one byte to the target stream. Only the low order byte of the
      * integer {@code oneByte} is written.
-     * 
+     *
      * @param oneByte
      *            the byte to be written.
      * @throws IOException
      *             if an I/O error occurs while writing to this stream.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneByte) throws IOException {
diff --git a/luni/src/main/java/java/io/FilterReader.java b/luni/src/main/java/java/io/FilterReader.java
index 7fa96b5..e8e06dd 100644
--- a/luni/src/main/java/java/io/FilterReader.java
+++ b/luni/src/main/java/java/io/FilterReader.java
@@ -26,15 +26,11 @@
  * class.
  * 
  * @see FilterWriter
- * 
- * @since Android 1.0
  */
 public abstract class FilterReader extends Reader {
 
     /**
      * The target Reader which is being filtered.
-     * 
-     * @since Android 1.0
      */
     protected Reader in;
 
@@ -43,7 +39,6 @@
      * 
      * @param in
      *            The non-null Reader to filter reads on.
-     * @since Android 1.0
      */
     protected FilterReader(Reader in) {
         super(in);
@@ -55,7 +50,6 @@
      * 
      * @throws IOException
      *             if an error occurs while closing this reader.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -71,7 +65,6 @@
      * position, provided that {@code readlimit} has not been surpassed.
      * <p>
      * This implementation sets a mark in the filtered reader.
-     * </p>
      * 
      * @param readlimit
      *            the number of bytes that can be read from this reader before
@@ -80,7 +73,6 @@
      *             if an error occurs while marking this reader.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public synchronized void mark(int readlimit) throws IOException {
@@ -98,7 +90,6 @@
      * @see #mark(int)
      * @see #reset()
      * @see #skip(long)
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -116,7 +107,6 @@
      *         been reached.
      * @throws IOException
      *             if an error occurs while reading from this reader.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -142,7 +132,6 @@
      *         filtered reader has been reached while reading.
      * @throws IOException
      *             if an error occurs while reading from this reader.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buffer, int offset, int count) throws IOException {
@@ -161,7 +150,6 @@
      *         is called, {@code false} if unknown or blocking will occur.
      * @throws IOException
      *             if the reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -182,7 +170,6 @@
      *             {@code mark()} and {@code reset()}.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -205,7 +192,6 @@
      * @see #mark(int)
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
diff --git a/luni/src/main/java/java/io/FilterWriter.java b/luni/src/main/java/java/io/FilterWriter.java
index 66c1d34..cd48f64 100644
--- a/luni/src/main/java/java/io/FilterWriter.java
+++ b/luni/src/main/java/java/io/FilterWriter.java
@@ -24,26 +24,22 @@
  * decompression of the underlying writer. Writers that wrap another writer and
  * provide some additional functionality on top of it usually inherit from this
  * class.
- * 
+ *
  * @see FilterReader
- * 
- * @since Android 1.0
  */
 public abstract class FilterWriter extends Writer {
 
     /**
      * The Writer being filtered.
-     * @since Android 1.0
      */
     protected Writer out;
 
     /**
      * Constructs a new FilterWriter on the Writer {@code out}. All writes are
      * now filtered through this writer.
-     * 
+     *
      * @param out
      *            the target Writer to filter writes on.
-     * @since Android 1.0
      */
     protected FilterWriter(Writer out) {
         super(out);
@@ -52,10 +48,9 @@
 
     /**
      * Closes this writer. This implementation closes the target writer.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to close this writer.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -67,10 +62,9 @@
     /**
      * Flushes this writer to ensure all pending data is sent out to the target
      * writer. This implementation flushes the target writer.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to flush this writer.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -82,7 +76,7 @@
     /**
      * Writes {@code count} characters from the char array {@code buffer}
      * starting at position {@code offset} to the target writer.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -91,7 +85,6 @@
      *            the number of characters in {@code buffer} to write.
      * @throws IOException
      *             if an error occurs while writing to this writer.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] buffer, int offset, int count) throws IOException {
@@ -106,12 +99,11 @@
     /**
      * Writes the specified character {@code oneChar} to the target writer. Only the
      * two least significant bytes of the integer {@code oneChar} are written.
-     * 
+     *
      * @param oneChar
      *            the char to write to the target writer.
      * @throws IOException
      *             if an error occurs while writing to this writer.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) throws IOException {
@@ -124,7 +116,7 @@
      * Writes {@code count} characters from the string {@code str} starting at
      * position {@code index} to this writer. This implementation writes
      * {@code str} to the target writer.
-     * 
+     *
      * @param str
      *            the string to be written.
      * @param offset
@@ -133,7 +125,6 @@
      *            the number of chars in {@code str} to write.
      * @throws IOException
      *             if an error occurs while writing to this writer.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int count) throws IOException {
diff --git a/luni/src/main/java/java/io/Flushable.java b/luni/src/main/java/java/io/Flushable.java
index 55fcc92..c36de30 100644
--- a/luni/src/main/java/java/io/Flushable.java
+++ b/luni/src/main/java/java/io/Flushable.java
@@ -20,17 +20,14 @@
  * Defines an interface for classes that can (or need to) be flushed, typically
  * before some output processing is considered to be finished and the object
  * gets closed.
- * 
- * @since Android 1.0
  */
 public interface Flushable {
     /**
      * Flushes the object by writing out any buffered data to the underlying
      * output.
-     * 
+     *
      * @throws IOException
      *             if there are any issues writing the data.
-     * @since Android 1.0
      */
     void flush() throws IOException;
 }
diff --git a/luni/src/main/java/java/io/IOException.java b/luni/src/main/java/java/io/IOException.java
index 869a6d0..24cea9f 100644
--- a/luni/src/main/java/java/io/IOException.java
+++ b/luni/src/main/java/java/io/IOException.java
@@ -22,8 +22,6 @@
  * calling the constructor, as usual. Note there are also several subclasses of
  * this class for more specific error situations, such as
  * {@link FileNotFoundException} or {@link EOFException}.
- * 
- * @since Android 1.0
  */
 public class IOException extends Exception {
 
@@ -31,8 +29,6 @@
 
     /**
      * Constructs a new {@code IOException} with its stack trace filled in.
-     * 
-     * @since Android 1.0
      */
     public IOException() {
         super();
@@ -44,7 +40,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IOException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/InputStream.java b/luni/src/main/java/java/io/InputStream.java
index 23fd89c..f20ce7d 100644
--- a/luni/src/main/java/java/io/InputStream.java
+++ b/luni/src/main/java/java/io/InputStream.java
@@ -34,10 +34,8 @@
  * <p>
  * Many specialized input streams for purposes like reading from a file already
  * exist in this package.
- * 
+ *
  * @see OutputStream
- * 
- * @since Android 1.0
  */
 public abstract class InputStream extends Object implements Closeable {
 
@@ -46,8 +44,6 @@
     /**
      * This constructor does nothing. It is provided for signature
      * compatibility.
-     * 
-     * @since Android 1.0
      */
     public InputStream() {
         /* empty */
@@ -57,11 +53,10 @@
      * Returns the number of bytes that are available before this stream will
      * block. This implementation always returns 0. Subclasses should override
      * and indicate the correct number of bytes available.
-     * 
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if an error occurs in this stream.
-     * @since Android 1.0
      */
     public int available() throws IOException {
         return 0;
@@ -70,10 +65,9 @@
     /**
      * Closes this stream. Concrete implementations of this class should free
      * any resources during close. This implementation does nothing.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     public void close() throws IOException {
         /* empty */
@@ -87,14 +81,12 @@
      * <p>
      * This default implementation does nothing and concrete subclasses must
      * provide their own implementation.
-     * </p>
-     * 
+     *
      * @param readlimit
      *            the number of bytes that can be read from this stream before
      *            the mark is invalidated.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     public void mark(int readlimit) {
         /* empty */
@@ -103,11 +95,10 @@
     /**
      * Indicates whether this stream supports the {@code mark()} and
      * {@code reset()} methods. The default implementation returns {@code false}.
-     * 
+     *
      * @return always {@code false}.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     public boolean markSupported() {
         return false;
@@ -118,24 +109,22 @@
      * range from 0 to 255. Returns -1 if the end of the stream has been
      * reached. Blocks until one byte has been read, the end of the source
      * stream is detected or an exception is thrown.
-     * 
+     *
      * @return the byte read or -1 if the end of stream has been reached.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     public abstract int read() throws IOException;
 
     /**
      * Reads bytes from this stream and stores them in the byte array {@code b}.
-     * 
+     *
      * @param b
      *            the byte array in which to store the bytes read.
      * @return the number of bytes actually read or -1 if the end of the stream
      *         has been reached.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     public int read(byte[] b) throws IOException {
         // BEGIN android-note
@@ -147,7 +136,7 @@
     /**
      * Reads at most {@code length} bytes from this stream and stores them in
      * the byte array {@code b} starting at {@code offset}.
-     * 
+     *
      * @param b
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -163,7 +152,6 @@
      *             {@code b}.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     public int read(byte[] b, int offset, int length) throws IOException {
         // BEGIN android-note
@@ -195,7 +183,7 @@
                 }
                 throw e;
             }
-            b[offset + i] = (byte)c;
+            b[offset + i] = (byte) c;
         }
         return length;
     }
@@ -208,11 +196,9 @@
      * <p>
      * This implementation always throws an {@code IOException} and concrete
      * subclasses should provide the proper implementation.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     public synchronized void reset() throws IOException {
         throw new IOException();
@@ -225,14 +211,12 @@
      * <p>
      * This default implementation reads {@code n} bytes into a temporary
      * buffer. Concrete subclasses should provide their own implementation.
-     * </p>
-     * 
+     *
      * @param n
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     public long skip(long n) throws IOException {
         if (n <= 0) {
diff --git a/luni/src/main/java/java/io/InputStreamReader.java b/luni/src/main/java/java/io/InputStreamReader.java
index 0f74b14..0fdcb9a 100644
--- a/luni/src/main/java/java/io/InputStreamReader.java
+++ b/luni/src/main/java/java/io/InputStreamReader.java
@@ -26,15 +26,11 @@
 import java.nio.charset.MalformedInputException;
 import java.nio.charset.UnmappableCharacterException;
 import java.security.AccessController;
-import java.util.HashMap;
 
+import org.apache.harmony.luni.util.HistoricalNamesUtil;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 
-// BEGIN android-note
-// Later changes from Harmony have been integrated into this version.
-// END android-note
-
 /**
  * A class for turning a byte stream into a character stream. Data read from the
  * source input stream is converted into characters by either a default or a
@@ -42,10 +38,8 @@
  * "file.encoding" system property. {@code InputStreamReader} contains a buffer
  * of bytes read from the source stream and converts these into characters as
  * needed. The buffer size is 8K.
- * 
+ *
  * @see OutputStreamWriter
- * 
- * @since Android 1.0
  */
 public class InputStreamReader extends Reader {
     private InputStream in;
@@ -63,10 +57,9 @@
      * {@code in}. This constructor sets the character converter to the encoding
      * specified in the "file.encoding" property and falls back to ISO 8859_1
      * (ISO-Latin-1) if the property doesn't exist.
-     * 
+     *
      * @param in
      *            the input stream from which to read characters.
-     * @since Android 1.0
      */
     public InputStreamReader(InputStream in) {
         super(in);
@@ -85,7 +78,7 @@
      * character converter that is used to decode bytes into characters is
      * identified by name by {@code enc}. If the encoding cannot be found, an
      * UnsupportedEncodingException error is thrown.
-     * 
+     *
      * @param in
      *            the InputStream from which to read characters.
      * @param enc
@@ -94,7 +87,6 @@
      *             if {@code enc} is {@code null}.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code enc} cannot be found.
-     * @since Android 1.0
      */
     public InputStreamReader(InputStream in, final String enc)
             throws UnsupportedEncodingException {
@@ -117,12 +109,11 @@
     /**
      * Constructs a new InputStreamReader on the InputStream {@code in} and
      * CharsetDecoder {@code dec}.
-     * 
+     *
      * @param in
      *            the source InputStream from which to read characters.
      * @param dec
      *            the CharsetDecoder used by the character conversion.
-     * @since Android 1.0
      */
     public InputStreamReader(InputStream in, CharsetDecoder dec) {
         super(in);
@@ -135,12 +126,11 @@
     /**
      * Constructs a new InputStreamReader on the InputStream {@code in} and
      * Charset {@code charset}.
-     * 
+     *
      * @param in
      *            the source InputStream from which to read characters.
      * @param charset
      *            the Charset that defines the character converter
-     * @since Android 1.0
      */
     public InputStreamReader(InputStream in, Charset charset) {
         super(in);
@@ -154,10 +144,9 @@
     /**
      * Closes this reader. This implementation closes the source InputStream and
      * releases all local storage.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to close this reader.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -178,10 +167,9 @@
     /**
      * Returns the name of the encoding used to convert bytes into characters.
      * The value {@code null} is returned if this reader has been closed.
-     * 
+     *
      * @return the name of the character converter or {@code null} if this
      *         reader is closed.
-     * @since Android 1.0
      */
     public String getEncoding() {
         if (!isOpen()) {
@@ -190,172 +178,17 @@
         return HistoricalNamesUtil.getHistoricalName(decoder.charset().name());
     }
 
-    /*
-     * helper for getEncoding()
-     */
-    @SuppressWarnings("nls")
-    static class HistoricalNamesUtil {
-        private static HashMap<String, String> historicalNames = new HashMap<String, String>();
-        static {
-            historicalNames.put("Big5-HKSCS", "Big5_HKSCS");
-            historicalNames.put("EUC-JP", "EUC_JP");
-            historicalNames.put("EUC-KR", "EUC_KR");
-            historicalNames.put("GB2312", "EUC_CN");
-            historicalNames.put("IBM-Thai", "Cp838");
-            historicalNames.put("IBM00858", "Cp858");
-            historicalNames.put("IBM01140", "Cp1140");
-            historicalNames.put("IBM01141", "Cp1141");
-            historicalNames.put("IBM01142", "Cp1142");
-            historicalNames.put("IBM01143", "Cp1143");
-            historicalNames.put("IBM01144", "Cp1144");
-            historicalNames.put("IBM01145", "Cp1145");
-            historicalNames.put("IBM01146", "Cp1146");
-            historicalNames.put("IBM01147", "Cp1147");
-            historicalNames.put("IBM01148", "Cp1148");
-            historicalNames.put("IBM01149", "Cp1149");
-            historicalNames.put("IBM037", "Cp037");
-            historicalNames.put("IBM1026", "Cp1026");
-            historicalNames.put("IBM1047", "Cp1047");
-            historicalNames.put("IBM273", "Cp273");
-            historicalNames.put("IBM277", "Cp277");
-            historicalNames.put("IBM278", "Cp278");
-            historicalNames.put("IBM280", "Cp280");
-            historicalNames.put("IBM284", "Cp284");
-            historicalNames.put("IBM285", "Cp285");
-            historicalNames.put("IBM297", "Cp297");
-            historicalNames.put("IBM420", "Cp420");
-            historicalNames.put("IBM424", "Cp424");
-            historicalNames.put("IBM437", "Cp437");
-            historicalNames.put("IBM500", "Cp500");
-            historicalNames.put("IBM775", "Cp775");
-            historicalNames.put("IBM850", "Cp850");
-            historicalNames.put("IBM852", "Cp852");
-            historicalNames.put("IBM855", "Cp855");
-            historicalNames.put("IBM857", "Cp857");
-            historicalNames.put("IBM860", "Cp860");
-            historicalNames.put("IBM861", "Cp861");
-            historicalNames.put("IBM862", "Cp862");
-            historicalNames.put("IBM863", "Cp863");
-            historicalNames.put("IBM864", "Cp864");
-            historicalNames.put("IBM865", "Cp865");
-            historicalNames.put("IBM866", "Cp866");
-            historicalNames.put("IBM868", "Cp868");
-            historicalNames.put("IBM869", "Cp869");
-            historicalNames.put("IBM870", "Cp870");
-            historicalNames.put("IBM871", "Cp871");
-            historicalNames.put("IBM918", "Cp918");
-            historicalNames.put("ISO-2022-CN", "ISO2022CN");
-            historicalNames.put("ISO-2022-JP", "ISO2022JP");
-            historicalNames.put("ISO-2022-KR", "ISO2022KR");
-            historicalNames.put("ISO-8859-1", "ISO8859_1");
-            historicalNames.put("ISO-8859-13", "ISO8859_13");
-            historicalNames.put("ISO-8859-15", "ISO8859_15");
-            historicalNames.put("ISO-8859-2", "ISO8859_2");
-            historicalNames.put("ISO-8859-3", "ISO8859_3");
-            historicalNames.put("ISO-8859-4", "ISO8859_4");
-            historicalNames.put("ISO-8859-5", "ISO8859_5");
-            historicalNames.put("ISO-8859-6", "ISO8859_6");
-            historicalNames.put("ISO-8859-7", "ISO8859_7");
-            historicalNames.put("ISO-8859-8", "ISO8859_8");
-            historicalNames.put("ISO-8859-9", "ISO8859_9");
-            historicalNames.put("KOI8-R", "KOI8_R");
-            historicalNames.put("Shift_JIS", "SJIS");
-            historicalNames.put("TIS-620", "TIS620");
-            historicalNames.put("US-ASCII", "ASCII");
-            historicalNames.put("UTF-16BE", "UnicodeBigUnmarked");
-            historicalNames.put("UTF-16LE", "UnicodeLittleUnmarked");
-            historicalNames.put("UTF-8", "UTF8");
-            historicalNames.put("windows-1250", "Cp1250");
-            historicalNames.put("windows-1251", "Cp1251");
-            historicalNames.put("windows-1252", "Cp1252");
-            historicalNames.put("windows-1253", "Cp1253");
-            historicalNames.put("windows-1254", "Cp1254");
-            historicalNames.put("windows-1255", "Cp1255");
-            historicalNames.put("windows-1256", "Cp1256");
-            historicalNames.put("windows-1257", "Cp1257");
-            historicalNames.put("windows-1258", "Cp1258");
-            historicalNames.put("windows-31j", "MS932");
-            historicalNames.put("x-Big5-Solaris", "Big5_Solaris");
-            historicalNames.put("x-euc-jp-linux", "EUC_JP_LINUX");
-            historicalNames.put("x-EUC-TW", "EUC_TW");
-            historicalNames.put("x-eucJP-Open", "EUC_JP_Solaris");
-            historicalNames.put("x-IBM1006", "Cp1006");
-            historicalNames.put("x-IBM1025", "Cp1025");
-            historicalNames.put("x-IBM1046", "Cp1046");
-            historicalNames.put("x-IBM1097", "Cp1097");
-            historicalNames.put("x-IBM1098", "Cp1098");
-            historicalNames.put("x-IBM1112", "Cp1112");
-            historicalNames.put("x-IBM1122", "Cp1122");
-            historicalNames.put("x-IBM1123", "Cp1123");
-            historicalNames.put("x-IBM1124", "Cp1124");
-            historicalNames.put("x-IBM1381", "Cp1381");
-            historicalNames.put("x-IBM1383", "Cp1383");
-            historicalNames.put("x-IBM33722", "Cp33722");
-            historicalNames.put("x-IBM737", "Cp737");
-            historicalNames.put("x-IBM856", "Cp856");
-            historicalNames.put("x-IBM874", "Cp874");
-            historicalNames.put("x-IBM875", "Cp875");
-            historicalNames.put("x-IBM921", "Cp921");
-            historicalNames.put("x-IBM922", "Cp922");
-            historicalNames.put("x-IBM930", "Cp930");
-            historicalNames.put("x-IBM933", "Cp933");
-            historicalNames.put("x-IBM935", "Cp935");
-            historicalNames.put("x-IBM937", "Cp937");
-            historicalNames.put("x-IBM939", "Cp939");
-            historicalNames.put("x-IBM942", "Cp942");
-            historicalNames.put("x-IBM942C", "Cp942C");
-            historicalNames.put("x-IBM943", "Cp943");
-            historicalNames.put("x-IBM943C", "Cp943C");
-            historicalNames.put("x-IBM948", "Cp948");
-            historicalNames.put("x-IBM949", "Cp949");
-            historicalNames.put("x-IBM949C", "Cp949C");
-            historicalNames.put("x-IBM950", "Cp950");
-            historicalNames.put("x-IBM964", "Cp964");
-            historicalNames.put("x-IBM970", "Cp970");
-            historicalNames.put("x-ISCII91", "ISCII91");
-            historicalNames.put("x-ISO-2022-CN-CNS", "ISO2022CN");
-            historicalNames.put("x-ISO-2022-CN-GB", "ISO2022CN");
-            historicalNames.put("x-JISAutoDetect", "JISAutoDetect");
-            historicalNames.put("x-MacArabic", "MacArabic");
-            historicalNames.put("x-MacCentralEurope", "MacCentralEurope");
-            historicalNames.put("x-MacCroatian", "MacCroatian");
-            historicalNames.put("x-MacCyrillic", "MacCyrillic");
-            historicalNames.put("x-MacDingbat", "MacDingbat");
-            historicalNames.put("x-MacGreek", "MacGreek");
-            historicalNames.put("x-MacHebrew", "MacHebrew");
-            historicalNames.put("x-MacIceland", "MacIceland");
-            historicalNames.put("x-MacRoman", "MacRoman");
-            historicalNames.put("x-MacRomania", "MacRomania");
-            historicalNames.put("x-MacSymbol", "MacSymbol");
-            historicalNames.put("x-MacThai", "MacThai");
-            historicalNames.put("x-MacTurkish", "MacTurkish");
-            historicalNames.put("x-MacUkraine", "MacUkraine");
-            historicalNames.put("x-MS950-HKSCS", "MS950_HKSCS");
-            historicalNames.put("x-mswin-936", "MS936");
-            historicalNames.put("x-PCK", "PCK");
-            historicalNames.put("x-windows-874", "MS874");
-            historicalNames.put("x-windows-949", "MS949");
-            historicalNames.put("x-windows-950", "MS950");
-        }
-
-        public static String getHistoricalName(String name) {
-            return (!historicalNames.containsKey(name) ? name : historicalNames
-                    .get(name));
-        }
-    }
-
     /**
      * Reads a single character from this reader and returns it as an integer
      * with the two higher-order bytes set to 0. Returns -1 if the end of the
      * reader has been reached. The byte value is either obtained from
      * converting bytes in this reader's buffer or by first filling the buffer
      * from the source InputStream and then reading from the buffer.
-     * 
+     *
      * @return the character read or -1 if the end of the reader has been
      *         reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -377,7 +210,7 @@
      * been reached. The bytes are either obtained from converting bytes in this
      * reader's buffer or by first filling the buffer from the source
      * InputStream and then reading from the buffer.
-     * 
+     *
      * @param buf
      *            the array to store the characters read.
      * @param offset
@@ -393,7 +226,6 @@
      *             {@code buf}.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buf, int offset, int length) throws IOException {
@@ -465,10 +297,7 @@
 
             if (result == CoderResult.UNDERFLOW && endOfInput) {
                 result = decoder.decode(bytes, out, true);
-                // FIXME: should flush at first, but seems ICU has a bug that it
-                // will throw IAE if some malform/unmappable bytes found during
-                // decoding
-                // result = decoder.flush(out);
+                decoder.flush(out);
                 decoder.reset();
             }
             if (result.isMalformed()) {
@@ -496,12 +325,11 @@
      * {@code read()} is called. This implementation returns {@code true} if
      * there are bytes available in the buffer or the source stream has bytes
      * available.
-     * 
+     *
      * @return {@code true} if the receiver will not block when {@code read()}
      *         is called, {@code false} if unknown or blocking will occur.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
diff --git a/luni/src/main/java/java/io/InterruptedIOException.java b/luni/src/main/java/java/io/InterruptedIOException.java
index de11d28..4d537fc 100644
--- a/luni/src/main/java/java/io/InterruptedIOException.java
+++ b/luni/src/main/java/java/io/InterruptedIOException.java
@@ -21,8 +21,6 @@
  * Signals that a blocking I/O operation has been interrupted. The number of
  * bytes that were transferred successfully before the interruption took place
  * is stored in a field of the exception.
- * 
- * @since Android 1.0
  */
 public class InterruptedIOException extends IOException {
 
@@ -30,16 +28,12 @@
 
     /**
      * The number of bytes transferred before the I/O interrupt occurred.
-     * 
-     * @since Android 1.0
      */
     public int bytesTransferred;
 
     /**
      * Constructs a new {@code InterruptedIOException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public InterruptedIOException() {
         super();
@@ -51,7 +45,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InterruptedIOException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/InvalidClassException.java b/luni/src/main/java/java/io/InvalidClassException.java
index 10764b5..4712bb6 100644
--- a/luni/src/main/java/java/io/InvalidClassException.java
+++ b/luni/src/main/java/java/io/InvalidClassException.java
@@ -30,8 +30,6 @@
  * 
  * @see ObjectInputStream #readObject()
  * @see ObjectInputValidation#validateObject()
- * 
- * @since Android 1.0
  */
 public class InvalidClassException extends ObjectStreamException {
 
@@ -39,8 +37,6 @@
 
     /**
      * The fully qualified name of the class that caused the problem.
-     * 
-     * @since Android 1.0
      */
     public String classname;
 
@@ -50,7 +46,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InvalidClassException(String detailMessage) {
         super(detailMessage);
@@ -65,7 +60,6 @@
      *            the name of the class that caused the exception.
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InvalidClassException(String className, String detailMessage) {
         super(detailMessage);
@@ -80,7 +74,6 @@
      * 
      * @return the detail message, possibly concatenated with the name of the
      *         class that caused the problem.
-     * @since Android 1.0
      */
     @Override
     public String getMessage() {
diff --git a/luni/src/main/java/java/io/InvalidObjectException.java b/luni/src/main/java/java/io/InvalidObjectException.java
index a2bb5df..365209d 100644
--- a/luni/src/main/java/java/io/InvalidObjectException.java
+++ b/luni/src/main/java/java/io/InvalidObjectException.java
@@ -22,8 +22,6 @@
  * 
  * @see ObjectInputStream#registerValidation(ObjectInputValidation, int)
  * @see ObjectInputValidation#validateObject()
- * 
- * @since Android 1.0
  */
 public class InvalidObjectException extends ObjectStreamException {
 
@@ -35,7 +33,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InvalidObjectException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/LineNumberInputStream.java b/luni/src/main/java/java/io/LineNumberInputStream.java
index 3bb3997..1a40177 100644
--- a/luni/src/main/java/java/io/LineNumberInputStream.java
+++ b/luni/src/main/java/java/io/LineNumberInputStream.java
@@ -27,10 +27,8 @@
  * line terminator sequences are {@code '\r'}, {@code '\n'} and {@code "\r\n"}.
  * When using {@code read}, line terminator sequences are always translated into
  * {@code '\n'}.
- * 
+ *
  * @deprecated Use {@link LineNumberReader}
- * 
- * @since Android 1.0
  */
 @Deprecated
 public class LineNumberInputStream extends FilterInputStream {
@@ -46,10 +44,9 @@
     /**
      * Constructs a new {@code LineNumberInputStream} on the {@link InputStream}
      * {@code in}. Line numbers are counted for all data read from this stream.
-     * 
+     *
      * @param in
      *            The non-null input stream to count line numbers.
-     * @since Android 1.0
      */
     public LineNumberInputStream(InputStream in) {
         super(in);
@@ -63,12 +60,10 @@
      * which are converted into {@code '\n'} by this stream. Therefore,
      * {@code available} returns only {@code in.available() / 2} bytes as
      * result.
-     * </p>
-     * 
+     *
      * @return the guaranteed number of bytes available before blocking.
      * @throws IOException
      *             if an error occurs in this stream.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -77,9 +72,8 @@
 
     /**
      * Returns the current line number for this stream. Numbering starts at 0.
-     * 
+     *
      * @return the current line number.
-     * @since Android 1.0
      */
     public int getLineNumber() {
         return lineNumber;
@@ -94,14 +88,12 @@
      * line number count.
      * <p>
      * This implementation sets a mark in the filtered stream.
-     * </p>
-     * 
+     *
      * @param readlimit
      *            the number of bytes that can be read from this stream before
      *            the mark is invalidated.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public void mark(int readlimit) {
@@ -119,14 +111,13 @@
      * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
      * {@code "\r\n"}. Line terminator sequences are always translated into
      * {@code '\n'}.
-     * </p>
-     * 
+     *
      * @return the byte read or -1 if the end of the filtered stream has been
      *         reached.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
+    @SuppressWarnings("fallthrough")
     @Override
     public int read() throws IOException {
         int currentChar = lastChar;
@@ -159,8 +150,7 @@
      * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
      * {@code "\r\n"}. Line terminator sequences are always translated into
      * {@code '\n'}.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read.
      * @param offset
@@ -178,7 +168,6 @@
      *             if this stream is closed or another IOException occurs.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
@@ -217,14 +206,13 @@
     /**
      * Resets this stream to the last marked location. It also resets the line
      * count to what is was when this stream was marked.
-     * 
+     *
      * @throws IOException
      *             if this stream is already closed, no mark has been set or the
      *             mark is no longer valid because more than {@code readlimit}
      *             bytes have been read since setting the mark.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -237,12 +225,11 @@
      * Sets the line number of this stream to the specified
      * {@code lineNumber}. Note that this may have side effects on the
      * line number associated with the last marked position.
-     * 
+     *
      * @param lineNumber
      *            the new lineNumber value.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     public void setLineNumber(int lineNumber) {
         this.lineNumber = lineNumber;
@@ -254,7 +241,7 @@
      * used. This implementation skips {@code count} number of bytes in the
      * filtered stream and increments the line number count whenever line
      * terminator sequences are skipped.
-     * 
+     *
      * @param count
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
@@ -263,7 +250,6 @@
      * @see #mark(int)
      * @see #read()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
diff --git a/luni/src/main/java/java/io/LineNumberReader.java b/luni/src/main/java/java/io/LineNumberReader.java
index 8110426..8ecdd95 100644
--- a/luni/src/main/java/java/io/LineNumberReader.java
+++ b/luni/src/main/java/java/io/LineNumberReader.java
@@ -22,8 +22,6 @@
  * while reading the data. The line number starts at 0 and is incremented any
  * time {@code '\r'}, {@code '\n'} or {@code "\r\n"} is read. The class has an
  * internal buffer for its data. The size of the buffer defaults to 8 KB.
- * 
- * @since Android 1.0
  */
 public class LineNumberReader extends BufferedReader {
 
@@ -38,10 +36,9 @@
     /**
      * Constructs a new LineNumberReader on the Reader {@code in}. The internal
      * buffer gets the default size (8 KB).
-     * 
+     *
      * @param in
      *            the Reader that is buffered.
-     * @since Android 1.0
      */
     public LineNumberReader(Reader in) {
         super(in);
@@ -50,14 +47,13 @@
     /**
      * Constructs a new LineNumberReader on the Reader {@code in}. The size of
      * the internal buffer is specified by the parameter {@code size}.
-     * 
+     *
      * @param in
      *            the Reader that is buffered.
      * @param size
      *            the size of the buffer to allocate.
      * @throws IllegalArgumentException
      *             if {@code size <= 0}.
-     * @since Android 1.0
      */
     public LineNumberReader(Reader in, int size) {
         super(in, size);
@@ -65,9 +61,8 @@
 
     /**
      * Returns the current line number for this reader. Numbering starts at 0.
-     * 
+     *
      * @return the current line number.
-     * @since Android 1.0
      */
     public int getLineNumber() {
         synchronized (lock) {
@@ -82,7 +77,7 @@
      * position, provided that {@code readlimit} has not been surpassed. The
      * line number associated with this marked position is also stored so that
      * it can be restored when {@code reset()} is called.
-     * 
+     *
      * @param readlimit
      *            the number of characters that can be read from this stream
      *            before the mark is invalidated.
@@ -90,7 +85,6 @@
      *             if an error occurs while setting the mark in this reader.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public void mark(int readlimit) throws IOException {
@@ -110,14 +104,13 @@
      * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
      * {@code "\r\n"}. Line terminator sequences are always translated into
      * {@code '\n'}.
-     * </p>
-     * 
+     *
      * @return the character read or -1 if the end of the source reader has been
      *         reached.
      * @throws IOException
      *             if the reader is closed or another IOException occurs.
-     * @since Android 1.0
      */
+    @SuppressWarnings("fallthrough")
     @Override
     public int read() throws IOException {
         synchronized (lock) {
@@ -148,8 +141,7 @@
      * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
      * {@code "\r\n"}. Line terminator sequences are always translated into
      * {@code '\n'}.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the array in which to store the characters read.
      * @param offset
@@ -161,7 +153,6 @@
      *         source reader has been reached while reading.
      * @throws IOException
      *             if this reader is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buffer, int offset, int count) throws IOException {
@@ -193,28 +184,17 @@
      * represented by 0 or more characters followed by {@code '\r'},
      * {@code '\n'}, {@code "\r\n"} or the end of the stream. The returned
      * string does not include the newline sequence.
-     * 
+     *
      * @return the contents of the line or {@code null} if no characters have
      *         been read before the end of the stream has been reached.
      * @throws IOException
      *             if this reader is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public String readLine() throws IOException {
         synchronized (lock) {
-            /* Typical Line Length */
-            StringBuilder result = new StringBuilder(80);
-            while (true) {
-                int character = read();
-                if (character == -1) {
-                    return result.length() != 0 ? result.toString() : null;
-                }
-                if (character == '\n') {
-                    return result.toString();
-                }
-                result.append((char) character);
-            }
+            lineNumber++;
+            return super.readLine();
         }
     }
 
@@ -222,14 +202,13 @@
      * Resets this reader to the last marked location. It also resets the line
      * count to what is was when this reader was marked. This implementation
      * resets the source reader.
-     * 
+     *
      * @throws IOException
      *             if this reader is already closed, no mark has been set or the
      *             mark is no longer valid because more than {@code readlimit}
      *             bytes have been read since setting the mark.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -244,12 +223,11 @@
      * Sets the line number of this reader to the specified {@code lineNumber}.
      * Note that this may have side effects on the line number associated with
      * the last marked position.
-     * 
+     *
      * @param lineNumber
      *            the new line number value.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     public void setLineNumber(int lineNumber) {
         synchronized (lock) {
@@ -263,7 +241,7 @@
      * is used. This implementation skips {@code count} number of characters in
      * the source reader and increments the line number count whenever line
      * terminator sequences are skipped.
-     * 
+     *
      * @param count
      *            the number of characters to skip.
      * @return the number of characters actually skipped.
@@ -274,7 +252,6 @@
      * @see #mark(int)
      * @see #read()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
diff --git a/luni/src/main/java/java/io/NotActiveException.java b/luni/src/main/java/java/io/NotActiveException.java
index 402eabe..51f4d3f 100644
--- a/luni/src/main/java/java/io/NotActiveException.java
+++ b/luni/src/main/java/java/io/NotActiveException.java
@@ -29,8 +29,6 @@
  * <li>{@link ObjectInputStream#registerValidation(ObjectInputValidation, int)}</li>
  * <li>{@link ObjectOutputStream#defaultWriteObject()}</li>
  * </ul>
- * 
- * @since Android 1.0
  */
 public class NotActiveException extends ObjectStreamException {
 
@@ -39,8 +37,6 @@
     /**
      * Constructs a new {@code NotActiveException} with its stack trace filled
      * in.
-     * 
-     * @since Android 1.0
      */
     public NotActiveException() {
         super();
@@ -52,7 +48,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NotActiveException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/NotSerializableException.java b/luni/src/main/java/java/io/NotSerializableException.java
index ac57a76..f6e93a7 100644
--- a/luni/src/main/java/java/io/NotSerializableException.java
+++ b/luni/src/main/java/java/io/NotSerializableException.java
@@ -26,8 +26,6 @@
  * 
  * @see ObjectOutput#writeObject(Object)
  * @see ObjectOutputStream#writeObject(Object)
- * 
- * @since Android 1.0
  */
 public class NotSerializableException extends ObjectStreamException {
 
@@ -36,8 +34,6 @@
     /**
      * Constructs a new {@code NotSerializableException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public NotSerializableException() {
         super();
@@ -49,7 +45,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NotSerializableException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/ObjectInput.java b/luni/src/main/java/java/io/ObjectInput.java
index 7ca3cbe..3b32553 100644
--- a/luni/src/main/java/java/io/ObjectInput.java
+++ b/luni/src/main/java/java/io/ObjectInput.java
@@ -22,8 +22,6 @@
  * 
  * @see ObjectInputStream
  * @see ObjectOutput
- * 
- * @since Android 1.0
  */
 public interface ObjectInput extends DataInput {
     /**
@@ -33,7 +31,6 @@
      * @return the number of bytes available.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public int available() throws IOException;
 
@@ -43,7 +40,6 @@
      * 
      * @throws IOException
      *             if an I/O error occurs while closing the input stream.
-     * @since Android 1.0
      */
     public void close() throws IOException;
 
@@ -55,7 +51,6 @@
      * @return the byte read or -1 if the end of this stream has been reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read() throws IOException;
 
@@ -69,7 +64,6 @@
      *         reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read(byte[] buffer) throws IOException;
 
@@ -89,7 +83,6 @@
      *         reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read(byte[] buffer, int offset, int count) throws IOException;
 
@@ -102,7 +95,6 @@
      *             if the object's class cannot be found.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public Object readObject() throws ClassNotFoundException, IOException;
 
@@ -117,7 +109,6 @@
      * 
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0             
      */
     public long skip(long toSkip) throws IOException;
 }
diff --git a/luni/src/main/java/java/io/ObjectInputStream.java b/luni/src/main/java/java/io/ObjectInputStream.java
index 9483ab0..7dc87ff 100644
--- a/luni/src/main/java/java/io/ObjectInputStream.java
+++ b/luni/src/main/java/java/io/ObjectInputStream.java
@@ -17,6 +17,11 @@
 
 package java.io;
 
+// BEGIN android-note
+// Harmony uses ObjectAccessors to access fields through JNI. Android has not
+// yet migrated that API. As a consequence, there's a lot of changes here...
+// END android-note
+
 import java.io.EmulatedFields.ObjectSlot;
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
@@ -27,14 +32,20 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.IdentityHashMap;
+import java.util.HashMap;
 import java.util.Iterator;
 
 // BEGIN android-added
 import dalvik.system.VMStack;
 // END android-added
 
+// BEGIN android-removed
+// import org.apache.harmony.misc.accessors.ObjectAccessor;
+// import org.apache.harmony.misc.accessors.AccessorFactory;
+// END android-removed
+
+import org.apache.harmony.kernel.vm.VM;
+import org.apache.harmony.luni.internal.nls.Messages;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 
@@ -42,18 +53,19 @@
  * A specialized {@link InputStream} that is able to read (deserialize) Java
  * objects as well as primitive data types (int, byte, char etc.). The data has
  * typically been saved using an ObjectOutputStream.
- * 
+ *
  * @see ObjectOutputStream
  * @see ObjectInput
  * @see Serializable
  * @see Externalizable
- * 
- * @since Android 1.0
  */
 public class ObjectInputStream extends InputStream implements ObjectInput,
         ObjectStreamConstants {
 
-    private static InputStream emptyStream = new ByteArrayInputStream(
+    // BEGIN android-note
+    // this is non-static to avoid sync contention. Would static be faster?
+    // END android-note
+    private InputStream emptyStream = new ByteArrayInputStream(
             new byte[0]);
 
     // To put into objectsRead when reading unsharedObject
@@ -85,7 +97,7 @@
     private boolean enableResolve;
 
     // Table mapping Integer (handle) -> Object
-    private Hashtable<Integer, Object> objectsRead;
+    private HashMap<Integer, Object> objectsRead;
 
     // Used by defaultReadObject
     private Object currentObject;
@@ -109,10 +121,8 @@
     // Handle for the current class descriptor
     private Integer descriptorHandle;
 
-    // cache for readResolve methods
-    private IdentityHashMap<Class<?>, Object> readResolveCache;
-
-    private static final Hashtable<String, Class<?>> PRIMITIVE_CLASSES = new Hashtable<String, Class<?>>();
+    private static final HashMap<String, Class<?>> PRIMITIVE_CLASSES =
+        new HashMap<String, Class<?>>();
 
     static {
         PRIMITIVE_CLASSES.put("byte", byte.class); //$NON-NLS-1$
@@ -125,6 +135,10 @@
         PRIMITIVE_CLASSES.put("double", double.class); //$NON-NLS-1$
     }
 
+    // BEGIN android-removed
+    // private ObjectAccessor accessor = AccessorFactory.getObjectAccessor();
+    // END android-removed
+
     // Internal type used to keep track of validators & corresponding priority
     static class InputValidationDesc {
         ObjectInputValidation validator;
@@ -135,22 +149,19 @@
     /**
      * GetField is an inner class that provides access to the persistent fields
      * read from the source stream.
-     * 
-     * @since Android 1.0
      */
     public abstract static class GetField {
         /**
          * Gets the ObjectStreamClass that describes a field.
-         * 
+         *
          * @return the descriptor class for a serialized field.
-         * @since Android 1.0
          */
         public abstract ObjectStreamClass getObjectStreamClass();
 
         /**
          * Indicates if the field identified by {@code name} is defaulted. This
          * means that it has no value in this stream.
-         * 
+         *
          * @param name
          *            the name of the field to check.
          * @return {@code true} if the field is defaulted, {@code false}
@@ -160,7 +171,6 @@
          * @throws IOException
          *             if an error occurs while reading from the source input
          *             stream.
-         * @since Android 1.0
          */
         public abstract boolean defaulted(String name) throws IOException,
                 IllegalArgumentException;
@@ -168,7 +178,7 @@
         /**
          * Gets the value of the boolean field identified by {@code name} from
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -181,7 +191,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code boolean}.
-         * @since Android 1.0
          */
         public abstract boolean get(String name, boolean defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -189,7 +198,7 @@
         /**
          * Gets the value of the character field identified by {@code name} from
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -202,7 +211,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code char}.
-         * @since Android 1.0
          */
         public abstract char get(String name, char defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -210,7 +218,7 @@
         /**
          * Gets the value of the byte field identified by {@code name} from the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -223,7 +231,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code byte}.
-         * @since Android 1.0
          */
         public abstract byte get(String name, byte defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -231,7 +238,7 @@
         /**
          * Gets the value of the short field identified by {@code name} from the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -244,7 +251,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code short}.
-         * @since Android 1.0
          */
         public abstract short get(String name, short defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -252,7 +258,7 @@
         /**
          * Gets the value of the integer field identified by {@code name} from
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -265,15 +271,14 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code int}.
-         * @since Android 1.0
          */
         public abstract int get(String name, int defaultValue)
                 throws IOException, IllegalArgumentException;
 
-       /**
+        /**
          * Gets the value of the long field identified by {@code name} from the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -286,7 +291,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code long}.
-         * @since Android 1.0
          */
         public abstract long get(String name, long defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -294,7 +298,7 @@
         /**
          * Gets the value of the float field identified by {@code name} from the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -307,7 +311,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code float} is
          *             not {@code char}.
-         * @since Android 1.0
          */
         public abstract float get(String name, float defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -315,7 +318,7 @@
         /**
          * Gets the value of the double field identified by {@code name} from
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -328,7 +331,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code double}.
-         * @since Android 1.0
          */
         public abstract double get(String name, double defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -336,7 +338,7 @@
         /**
          * Gets the value of the object field identified by {@code name} from
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -349,7 +351,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code Object}.
-         * @since Android 1.0
          */
         public abstract Object get(String name, Object defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -359,14 +360,13 @@
      * Constructs a new ObjectInputStream. This default constructor can be used
      * by subclasses that do not want to use the public constructor if it
      * allocates unneeded data.
-     * 
+     *
      * @throws IOException
      *             if an error occurs when creating this stream.
      * @throws SecurityException
      *             if a security manager is installed and it denies subclassing
      *             this class.
      * @see SecurityManager#checkPermission(java.security.Permission)
-     * @since Android 1.0
      */
     protected ObjectInputStream() throws IOException, SecurityException {
         super();
@@ -382,7 +382,7 @@
     /**
      * Constructs a new ObjectInputStream that reads from the InputStream
      * {@code input}.
-     * 
+     *
      * @param input
      *            the non-null source InputStream to filter reads on.
      * @throws IOException
@@ -393,7 +393,6 @@
      * @throws SecurityException
      *             if a security manager is installed and it denies subclassing
      *             this class.
-     * @since Android 1.0
      */
     public ObjectInputStream(InputStream input)
             throws StreamCorruptedException, IOException {
@@ -437,7 +436,6 @@
         primitiveTypes = new DataInputStream(this);
         enableResolve = false;
         this.subclassOverridingImplementation = false;
-        this.readResolveCache = new IdentityHashMap<Class<?>, Object>();
         resetState();
         nestedLevels = 0;
         // So read...() methods can be used by
@@ -452,12 +450,11 @@
      * Returns the number of bytes of primitive data that can be read from this
      * stream without blocking. This method should not be used at any arbitrary
      * position; just when reading primitive data types (int, char etc).
-     * 
+     *
      * @return the number of available primitive data bytes.
      * @throws IOException
      *             if any I/O problem occurs while computing the available
      *             bytes.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -470,7 +467,7 @@
      * Checks to if it is ok to read primitive types from this stream at
      * this point. One is not supposed to read primitive types when about to
      * read an object, for example, so an exception has to be thrown.
-     * 
+     *
      * @throws IOException
      *             If any IO problem occurred when trying to read primitive type
      *             or if it is illegal to read primitive types
@@ -514,10 +511,9 @@
 
     /**
      * Closes this stream. This implementation closes the source stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -528,7 +524,7 @@
      * Default method to read objects from this stream. Serializable fields
      * defined in the object's class and superclasses are read from the source
      * stream.
-     * 
+     *
      * @throws ClassNotFoundException
      *             if the object's class cannot be found.
      * @throws IOException
@@ -536,7 +532,6 @@
      * @throws NotActiveException
      *             if this method is not called from {@code readObject()}.
      * @see ObjectOutputStream#defaultWriteObject
-     * @since Android 1.0
      */
     public void defaultReadObject() throws IOException, ClassNotFoundException,
             NotActiveException {
@@ -552,7 +547,7 @@
      * Enables object replacement for this stream. By default this is not
      * enabled. Only trusted subclasses (loaded with system class loader) are
      * allowed to change this status.
-     * 
+     *
      * @param enable
      *            {@code true} to enable object replacement; {@code false} to
      *            disable it.
@@ -562,7 +557,6 @@
      *             object replacement for this stream.
      * @see #resolveObject
      * @see ObjectOutputStream#enableReplaceObject
-     * @since Android 1.0
      */
     protected boolean enableResolveObject(boolean enable)
             throws SecurityException {
@@ -581,7 +575,7 @@
 
     /**
      * Checks if two classes belong to the same package.
-     * 
+     *
      * @param c1
      *            one of the classes to test.
      * @param c2
@@ -594,12 +588,9 @@
         String nameC2 = c2.getName();
         int indexDotC1 = nameC1.lastIndexOf('.');
         int indexDotC2 = nameC2.lastIndexOf('.');
-        // BEGIN android-changed
-        // copied from newer version of harmony
         if (indexDotC1 != indexDotC2) {
             return false; // cannot be in the same package if indices are not
         }
-        // END android-changed
         // the same
         if (indexDotC1 < 0) {
             return true; // both of them are in default package
@@ -608,16 +599,17 @@
                 nameC2.substring(0, indexDotC2));
     }
 
+    // BEGIN android-added
     /**
      * Create and return a new instance of class {@code instantiationClass}
      * but running the constructor defined in class
      * {@code constructorClass} (same as {@code instantiationClass}
      * or a superclass).
-     * 
+     *
      * Has to be native to avoid visibility rules and to be able to have
      * {@code instantiationClass} not the same as
      * {@code constructorClass} (no such API in java.lang.reflect).
-     * 
+     *
      * @param instantiationClass
      *            The new object will be an instance of this class
      * @param constructorClass
@@ -626,26 +618,27 @@
      */
     private static native Object newInstance(Class<?> instantiationClass,
             Class<?> constructorClass);
+    // END android-added
 
     /**
      * Return the next {@code int} handle to be used to indicate cyclic
      * references being loaded from the stream.
-     * 
+     *
      * @return the next handle to represent the next cyclic reference
      */
-    private int nextHandle() {
-        return this.currentHandle++;
+    private Integer nextHandle() {
+        return Integer.valueOf(this.currentHandle++);
     }
 
     /**
      * Return the next token code (TC) from the receiver, which indicates what
      * kind of object follows
-     * 
+     *
      * @return the next TC from the receiver
-     * 
+     *
      * @throws IOException
      *             If an IO error occurs
-     * 
+     *
      * @see ObjectStreamConstants
      */
     private byte nextTC() throws IOException {
@@ -670,12 +663,11 @@
      * Reads a single byte from the source stream and returns it as an integer
      * in the range from 0 to 255. Returns -1 if the end of the source stream
      * has been reached. Blocks if no input is available.
-     * 
+     *
      * @return the byte read or -1 if the end of the source stream has been
      *         reached.
      * @throws IOException
      *             if an error occurs while reading from this stream.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -688,7 +680,7 @@
      * in byte array {@code buffer} starting at offset {@code count}. Blocks
      * until {@code count} bytes have been read, the end of the source stream is
      * detected or an exception is thrown.
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read.
      * @param offset
@@ -706,7 +698,6 @@
      *             if an error occurs while reading from this stream.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
@@ -734,9 +725,9 @@
      * Reads and returns an array of raw bytes with primitive data. The array
      * will have up to 255 bytes. The primitive data will be in the format
      * described by {@code DataOutputStream}.
-     * 
+     *
      * @return The primitive data read, as raw bytes
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the primitive data.
      */
@@ -750,9 +741,9 @@
      * Reads and returns an array of raw bytes with primitive data. The array
      * will have more than 255 bytes. The primitive data will be in the format
      * described by {@code DataOutputStream}.
-     * 
+     *
      * @return The primitive data read, as raw bytes
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the primitive data.
      */
@@ -764,14 +755,13 @@
 
     /**
      * Reads a boolean from the source stream.
-     * 
+     *
      * @return the boolean value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public boolean readBoolean() throws IOException {
         return primitiveTypes.readBoolean();
@@ -779,14 +769,13 @@
 
     /**
      * Reads a byte (8 bit) from the source stream.
-     * 
+     *
      * @return the byte value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public byte readByte() throws IOException {
         return primitiveTypes.readByte();
@@ -794,14 +783,13 @@
 
     /**
      * Reads a character (16 bit) from the source stream.
-     * 
+     *
      * @return the char value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public char readChar() throws IOException {
         return primitiveTypes.readChar();
@@ -809,7 +797,7 @@
 
     /**
      * Reads and discards block data and objects until TC_ENDBLOCKDATA is found.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the optional class
      *             annotation.
@@ -834,9 +822,9 @@
     /**
      * Reads a class descriptor (an {@code ObjectStreamClass}) from the
      * stream.
-     * 
+     *
      * @return the class descriptor read from the stream
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -855,8 +843,7 @@
                 ObjectStreamClass streamClass = ObjectStreamClass
                         .lookup(proxyClass);
                 streamClass.setLoadFields(new ObjectStreamField[0]);
-                registerObjectRead(streamClass, Integer.valueOf(nextHandle()),
-                        false);
+                registerObjectRead(streamClass, nextHandle(), false);
                 checkedSetSuperClassDesc(streamClass, readClassDesc());
                 return streamClass;
             case TC_REFERENCE:
@@ -872,11 +859,11 @@
     /**
      * Reads the content of the receiver based on the previously read token
      * {@code tc}.
-     * 
+     *
      * @param tc
      *            The token code for the next item in the stream
      * @return the object read from the stream
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -922,11 +909,11 @@
     /**
      * Reads the content of the receiver based on the previously read token
      * {@code tc}. Primitive data content is considered an error.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return the object read from the stream
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -990,9 +977,9 @@
     /**
      * Reads the next item from the stream assuming it is a cyclic reference to
      * an object previously read. Return the actual object previously read.
-     * 
+     *
      * @return the object previously read from the stream
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -1006,14 +993,13 @@
 
     /**
      * Reads a double (64 bit) from the source stream.
-     * 
+     *
      * @return the double value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public double readDouble() throws IOException {
         return primitiveTypes.readDouble();
@@ -1029,9 +1015,9 @@
      * When exceptions are found normally in the object graph, they are loaded
      * as a regular object, and not by this method. In that case, the set of
      * "known objects" is not reset.
-     * 
+     *
      * @return the exception read
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the exception
      *             object.
@@ -1064,17 +1050,17 @@
     /**
      * Reads a collection of field descriptors (name, type name, etc) for the
      * class descriptor {@code cDesc} (an {@code ObjectStreamClass})
-     * 
+     *
      * @param cDesc
      *            The class descriptor (an {@code ObjectStreamClass})
      *            for which to write field information
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the field
      *             descriptors.
      * @throws ClassNotFoundException
      *             If a class for one of the field types could not be found
-     * 
+     *
      * @see #readObject()
      */
     private void readFieldDescriptors(ObjectStreamClass cDesc)
@@ -1109,17 +1095,45 @@
                     enableResolve = old;
                 }
             }
+
+            classSig = formatClassSig(classSig);
             ObjectStreamField f = new ObjectStreamField(classSig, fieldName);
             fields[i] = f;
         }
     }
 
+    /*
+     * Format the class signature for ObjectStreamField, for example,
+     * "[L[Ljava.lang.String;;" is converted to "[Ljava.lang.String;"
+     */
+    private static String formatClassSig(String classSig) {
+        int start = 0;
+        int end = classSig.length();
+
+        if (end <= 0) {
+            return classSig;
+        }
+
+        while (classSig.startsWith("[L", start) //$NON-NLS-1$
+                && classSig.charAt(end - 1) == ';') {
+            start += 2;
+            end--;
+        }
+
+        if (start > 0) {
+            start -= 2;
+            end++;
+            return classSig.substring(start, end);
+        }
+        return classSig;
+    }
+
     /**
      * Reads the persistent fields of the object that is currently being read
      * from the source stream. The values read are stored in a GetField object
      * that provides access to the persistent fields. This GetField object is
      * then returned.
-     * 
+     *
      * @return the GetField object from which persistent fields can be accessed
      *         by name.
      * @throws ClassNotFoundException
@@ -1129,7 +1143,6 @@
      *             if an error occurs while reading from this stream.
      * @throws NotActiveException
      *             if this stream is currently not reading an object.
-     * @since Android 1.0
      */
     public GetField readFields() throws IOException, ClassNotFoundException,
             NotActiveException {
@@ -1146,11 +1159,11 @@
     /**
      * Reads a collection of field values for the emulated fields
      * {@code emulatedFields}
-     * 
+     *
      * @param emulatedFields
      *            an {@code EmulatedFieldsForLoading}, concrete subclass
      *            of {@code GetField}
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the field values.
      * @throws InvalidClassException
@@ -1159,7 +1172,7 @@
      * @throws OptionalDataException
      *             If optional data could not be found when reading the
      *             exception graph
-     * 
+     *
      * @see #readFields
      * @see #readObject()
      */
@@ -1206,13 +1219,13 @@
      * This is the default mechanism, when emulated fields (an
      * {@code GetField}) are not used. Actual values to load are stored
      * directly into the object {@code obj}.
-     * 
+     *
      * @param obj
      *            Instance in which the fields will be set.
      * @param classDesc
      *            A class descriptor (an {@code ObjectStreamClass})
      *            defining which fields should be loaded.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the field values.
      * @throws InvalidClassException
@@ -1223,7 +1236,7 @@
      *             exception graph
      * @throws ClassNotFoundException
      *             If a class of an object being de-serialized can not be found
-     * 
+     *
      * @see #readFields
      * @see #readObject()
      */
@@ -1238,9 +1251,16 @@
         }
 
         for (ObjectStreamField fieldDesc : fields) {
+
+            // BEGIN android-removed
+            // // get associated Field
+            // long fieldID = fieldDesc.getFieldID(accessor, declaringClass);
+            // END android-removed
+
             // Code duplication starts, just because Java is typed
             if (fieldDesc.isPrimitive()) {
                 try {
+                    // BEGIN android-changed
                     switch (fieldDesc.getTypeCode()) {
                         case 'B':
                             setField(obj, declaringClass, fieldDesc.getName(),
@@ -1278,19 +1298,22 @@
                             throw new StreamCorruptedException(Msg.getString(
                                     "K00d5", fieldDesc.getTypeCode())); //$NON-NLS-1$
                     }
+                    // END android-changed
                 } catch (NoSuchFieldError err) {
                 }
             } else {
                 // Object type (array included).
                 String fieldName = fieldDesc.getName();
                 boolean setBack = false;
+                // BEGIN android-added
                 ObjectStreamField field = classDesc.getField(fieldName);
-                if (mustResolve && field == null) {
+                // END android-added
+                if (mustResolve && fieldDesc == null) {
                     setBack = true;
                     mustResolve = false;
                 }
                 Object toSet;
-                if (field != null && field.isUnshared()) {
+                if (fieldDesc != null && fieldDesc.isUnshared()) {
                     toSet = readUnshared();
                 } else {
                     toSet = readObject();
@@ -1298,18 +1321,9 @@
                 if (setBack) {
                     mustResolve = true;
                 }
-                if (field != null) {
+                if (fieldDesc != null) {
                     if (toSet != null) {
-                        // BEGIN android-removed
-                        // Class<?> fieldType = field.getType();
-                        // END android-removed
-                        // BEGIN android-added
-                        // Originally getTypeInternal() was called getType().
-                        // After the semantics of getType() changed inside
-                        // Harmony, the check below wasn't adjusted and didn't
-                        // work anymore.
-                        Class<?> fieldType = field.getTypeInternal();
-                        // END android-added                        
+                        Class<?> fieldType = fieldDesc.getType();
                         Class<?> valueType = toSet.getClass();
                         if (!fieldType.isAssignableFrom(valueType)) {
                             throw new ClassCastException(Msg.getString(
@@ -1319,8 +1333,10 @@
                                                     + fieldName }));
                         }
                         try {
+                            // BEGIN android-changed
                             objSetField(obj, declaringClass, fieldName, field
                                     .getTypeString(), toSet);
+                            // END android-changed
                         } catch (NoSuchFieldError e) {
                             // Ignored
                         }
@@ -1332,14 +1348,13 @@
 
     /**
      * Reads a float (32 bit) from the source stream.
-     * 
+     *
      * @return the float value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public float readFloat() throws IOException {
         return primitiveTypes.readFloat();
@@ -1348,7 +1363,7 @@
     /**
      * Reads bytes from the source stream into the byte array {@code buffer}.
      * This method will block until {@code buffer.length} bytes have been read.
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read.
      * @throws EOFException
@@ -1356,7 +1371,6 @@
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public void readFully(byte[] buffer) throws IOException {
         primitiveTypes.readFully(buffer);
@@ -1366,7 +1380,7 @@
      * Reads bytes from the source stream into the byte array {@code buffer}.
      * This method will block until {@code length} number of bytes have been
      * read.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -1379,7 +1393,6 @@
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public void readFully(byte[] buffer, int offset, int length)
             throws IOException {
@@ -1394,13 +1407,13 @@
      * (corresponding to class descriptor {@code classDesc}) defines
      * private instance method {@code readObject} it will be used to load
      * field values.
-     * 
+     *
      * @param object
      *            Instance into which stored field values loaded.
      * @param classDesc
      *            A class descriptor (an {@code ObjectStreamClass})
      *            defining which fields should be loaded.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the field values in
      *             the hierarchy.
@@ -1409,7 +1422,7 @@
      * @throws NotActiveException
      *             If {@code defaultReadObject} is called from the wrong
      *             context.
-     * 
+     *
      * @see #defaultReadObject
      * @see #readObject()
      */
@@ -1449,7 +1462,7 @@
                 int index = findStreamSuperclass(superclass, streamClassList,
                         lastIndex);
                 if (index == -1) {
-                    readObjectNoData(object, superclass);
+                    readObjectNoData(object, superclass, ObjectStreamClass.lookupStreamClass(superclass));
                 } else {
                     for (int j = lastIndex; j <= index; j++) {
                         readObjectForClass(object, streamClassList.get(j));
@@ -1483,16 +1496,13 @@
         return -1;
     }
 
-    private void readObjectNoData(Object object, Class<?> cl)
+    private void readObjectNoData(Object object, Class<?> cl, ObjectStreamClass classDesc)
             throws ObjectStreamException {
-        if (!ObjectStreamClass.isSerializable(cl)) {
+        if (!classDesc.isSerializable()) {
             return;
         }
-
-        final Method readMethod = ObjectStreamClass
-                .getPrivateReadObjectNoDataMethod(cl);
-        if (readMethod != null) {
-            AccessController.doPrivileged(new PriviAction<Object>(readMethod));
+        if (classDesc.hasMethodReadObjectNoData()){
+            final Method readMethod = classDesc.getMethodReadObjectNoData();
             try {
                 readMethod.invoke(object, new Object[0]);
             } catch (InvocationTargetException e) {
@@ -1507,6 +1517,7 @@
                 throw new RuntimeException(e.toString());
             }
         }
+
     }
 
     private void readObjectForClass(Object object, ObjectStreamClass classDesc)
@@ -1518,12 +1529,12 @@
 
         boolean hadWriteMethod = (classDesc.getFlags() & SC_WRITE_METHOD) > 0;
         Class<?> targetClass = classDesc.forClass();
+
         final Method readMethod;
         if (targetClass == null || !mustResolve) {
             readMethod = null;
         } else {
-            readMethod = ObjectStreamClass
-                    .getPrivateReadObjectMethod(targetClass);
+            readMethod = classDesc.getMethodReadObject();
         }
         try {
             if (readMethod != null) {
@@ -1562,30 +1573,27 @@
 
     /**
      * Reads an integer (32 bit) from the source stream.
-     * 
+     *
      * @return the integer value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public int readInt() throws IOException {
         return primitiveTypes.readInt();
     }
 
     /**
-     * Reads the next line from the source stream. Lines are terminated by 
+     * Reads the next line from the source stream. Lines are terminated by
      * {@code '\r'}, {@code '\n'}, {@code "\r\n"} or an {@code EOF}.
-     * 
+     *
      * @return the string read from the source stream.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
      * @deprecated Use {@link BufferedReader}
-     * @since Android 1.0
      */
-    @SuppressWarnings("deprecation")
     @Deprecated
     public String readLine() throws IOException {
         return primitiveTypes.readLine();
@@ -1593,14 +1601,13 @@
 
     /**
      * Reads a long (64 bit) from the source stream.
-     * 
+     *
      * @return the long value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public long readLong() throws IOException {
         return primitiveTypes.readLong();
@@ -1609,11 +1616,11 @@
     /**
      * Read a new array from the receiver. It is assumed the array has not been
      * read yet (not a cyclic reference). Return the array read.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return the array read
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the array.
      * @throws ClassNotFoundException
@@ -1629,7 +1636,7 @@
             throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
         }
 
-        Integer newHandle = Integer.valueOf(nextHandle());
+        Integer newHandle = nextHandle();
 
         // Array size
         int size = input.readInt();
@@ -1690,6 +1697,10 @@
             // Array of Objects
             Object[] objectArray = (Object[]) result;
             for (int i = 0; i < size; i++) {
+                // TODO: This place is the opportunity for enhancement
+                //      We can implement writing elements through fast-path,
+                //      without setting up the context (see readObject()) for
+                //      each element with public API
                 objectArray[i] = readObject();
             }
         }
@@ -1703,11 +1714,11 @@
     /**
      * Reads a new class from the receiver. It is assumed the class has not been
      * read yet (not a cyclic reference). Return the class read.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return The {@code java.lang.Class} read from the stream.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class.
      * @throws ClassNotFoundException
@@ -1718,10 +1729,9 @@
         ObjectStreamClass classDesc = readClassDesc();
 
         if (classDesc != null) {
-            Integer newHandle = Integer.valueOf(nextHandle());
             Class<?> localClass = classDesc.forClass();
             if (localClass != null) {
-                registerObjectRead(localClass, newHandle, unshared);
+                registerObjectRead(localClass, nextHandle(), unshared);
             }
             return localClass;
         }
@@ -1753,11 +1763,9 @@
         ObjectStreamClass classDesc;
         primitiveData = input;
         Integer oldHandle = descriptorHandle;
-        descriptorHandle = Integer.valueOf(nextHandle());
+        descriptorHandle = nextHandle();
         classDesc = readClassDescriptor();
-        if (descriptorHandle != null) {
-            registerObjectRead(classDesc, descriptorHandle, false);
-        }
+        registerObjectRead(classDesc, descriptorHandle, false);
         descriptorHandle = oldHandle;
         primitiveData = emptyStream;
         classDesc.setClass(resolveClass(classDesc));
@@ -1789,7 +1797,7 @@
             ClassNotFoundException, IOException {
         // read classdesc for Enum first
         ObjectStreamClass classDesc = readEnumDesc();
-        Integer newHandle = Integer.valueOf(nextHandle());
+        Integer newHandle = nextHandle();
         // read name after class desc
         String name;
         byte tc = nextTC();
@@ -1818,11 +1826,11 @@
      * Reads a new class descriptor from the receiver. It is assumed the class
      * descriptor has not been read yet (not a cyclic reference). Return the
      * class descriptor read.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return The {@code ObjectStreamClass} read from the stream.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -1835,21 +1843,17 @@
         // subclasses during readClassDescriptor()
         primitiveData = input;
         Integer oldHandle = descriptorHandle;
-        descriptorHandle = Integer.valueOf(nextHandle());
+        descriptorHandle = nextHandle();
         ObjectStreamClass newClassDesc = readClassDescriptor();
-        if (descriptorHandle != null) {
-            registerObjectRead(newClassDesc, descriptorHandle, unshared);
-        }
+        registerObjectRead(newClassDesc, descriptorHandle, unshared);
         descriptorHandle = oldHandle;
         primitiveData = emptyStream;
 
         // We need to map classDesc to class.
         try {
             newClassDesc.setClass(resolveClass(newClassDesc));
-            // Check SUIDs
-            verifySUID(newClassDesc);
-            // Check base name of the class
-            verifyBaseName(newClassDesc);
+            // Check SUIDs & base name of the class
+            verifyAndInit(newClassDesc);
         } catch (ClassNotFoundException e) {
             if (mustResolve) {
                 throw e;
@@ -1877,9 +1881,9 @@
      * Reads a new proxy class descriptor from the receiver. It is assumed the
      * proxy class descriptor has not been read yet (not a cyclic reference).
      * Return the proxy class descriptor read.
-     * 
+     *
      * @return The {@code Class} read from the stream.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -1901,33 +1905,33 @@
 
     /**
      * Reads a class descriptor from the source stream.
-     * 
+     *
      * @return the class descriptor read from the source stream.
      * @throws ClassNotFoundException
      *             if a class for one of the objects cannot be found.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     protected ObjectStreamClass readClassDescriptor() throws IOException,
             ClassNotFoundException {
 
         ObjectStreamClass newClassDesc = new ObjectStreamClass();
         String name = input.readUTF();
-        if ("".equals(name)) {
-            throw new IOException("The stream is corrupted.");
+        if (name.length() == 0) {
+            // luni.07 = The stream is corrupted
+            throw new IOException(Messages.getString("luni.07")); //$NON-NLS-1$
         }
         newClassDesc.setName(name);
         newClassDesc.setSerialVersionUID(input.readLong());
         newClassDesc.setFlags(input.readByte());
 
-        // We must register the class descriptor before reading field
-        // descriptors.
-        // if called outside of readObject, the descriptorHandle might be null
-        descriptorHandle = (null == descriptorHandle ? Integer
-                .valueOf(nextHandle()) : descriptorHandle);
+        /*
+         * We must register the class descriptor before reading field
+         * descriptors. If called outside of readObject, the descriptorHandle
+         * might be null.
+         */
+        descriptorHandle = (null == descriptorHandle ? nextHandle() : descriptorHandle);
         registerObjectRead(newClassDesc, descriptorHandle, false);
-        descriptorHandle = null;
 
         readFieldDescriptors(newClassDesc);
         return newClassDesc;
@@ -1936,7 +1940,7 @@
     /**
      * Creates the proxy class that implements the interfaces specified in
      * {@code interfaceNames}.
-     * 
+     *
      * @param interfaceNames
      *            the interfaces used to create the proxy class.
      * @return the proxy class.
@@ -1946,16 +1950,15 @@
      * @throws IOException
      *             if an error occurs while reading from the source stream.
      * @see ObjectOutputStream#annotateProxyClass(Class)
-     * @since Android 1.0
      */
     protected Class<?> resolveProxyClass(String[] interfaceNames)
             throws IOException, ClassNotFoundException {
-        // BEGIN android-removed
+        // TODO: This method is opportunity for performance enhancement
+        //       We can cache the classloader and recently used interfaces.
+        // BEGIN android-changed
         // ClassLoader loader = VM.getNonBootstrapClassLoader();
-        // END android-removed
-        // BEGIN android-added
         ClassLoader loader = ClassLoader.getSystemClassLoader();
-        // END android-added
+        // END android-changed
         Class<?>[] interfaces = new Class<?>[interfaceNames.length];
         for (int i = 0; i < interfaceNames.length; i++) {
             interfaces[i] = Class.forName(interfaceNames[i], false, loader);
@@ -1969,61 +1972,19 @@
 
     /**
      * Write a new handle describing a cyclic reference from the stream.
-     * 
+     *
      * @return the handle read
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the handle
      */
-    private Integer readNewHandle() throws IOException {
-        return Integer.valueOf(input.readInt());
+    private int readNewHandle() throws IOException {
+        return input.readInt();
     }
 
-    /**
-     * Read a new object from the stream. It is assumed the object has not been
-     * loaded yet (not a cyclic reference). Return the object read.
-     * 
-     * If the object implements {@code Externalizable} its
-     * {@code readExternal} is called. Otherwise, all fields described by
-     * the class hierarchy are loaded. Each class can define how its declared
-     * instance fields are loaded by defining a private method
-     * {@code readObject}
-     * 
-     * @param unshared
-     *            read the object unshared
-     * @return the object read
-     * 
-     * @throws IOException
-     *             If an IO exception happened when reading the object.
-     * @throws OptionalDataException
-     *             If optional data could not be found when reading the object
-     *             graph
-     * @throws ClassNotFoundException
-     *             If a class for one of the objects could not be found
-     */
-    private Object readNewObject(boolean unshared)
-            throws OptionalDataException, ClassNotFoundException, IOException {
-        ObjectStreamClass classDesc = readClassDesc();
+    private Class<?> resolveConstructorClass(Class<?> objectClass, boolean wasSerializable, boolean wasExternalizable)
+        throws OptionalDataException, ClassNotFoundException, IOException {
 
-        if (classDesc == null) {
-            throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
-        }
-
-        Integer newHandle = Integer.valueOf(nextHandle());
-
-        // Note that these values come from the Stream, and in fact it could be
-        // that the classes have been changed so that the info below now
-        // conflicts with the newer class
-        boolean wasExternalizable = (classDesc.getFlags() & SC_EXTERNALIZABLE) > 0;
-        boolean wasSerializable = (classDesc.getFlags() & SC_SERIALIZABLE) > 0;
-
-        // Maybe we should cache the values above in classDesc ? It may be the
-        // case that when reading classDesc we may need to read more stuff
-        // depending on the values above
-        Class<?> objectClass = classDesc.forClass();
-
-        Object result, registeredResult = null;
-        if (objectClass != null) {
             // The class of the instance may not be the same as the class of the
             // constructor to run
             // This is the constructor to run if Externalizable
@@ -2083,9 +2044,71 @@
                 }
             }
 
+            return constructorClass;
+    }
+
+    /**
+     * Read a new object from the stream. It is assumed the object has not been
+     * loaded yet (not a cyclic reference). Return the object read.
+     *
+     * If the object implements <code>Externalizable</code> its
+     * <code>readExternal</code> is called. Otherwise, all fields described by
+     * the class hierarchy are loaded. Each class can define how its declared
+     * instance fields are loaded by defining a private method
+     * <code>readObject</code>
+     *
+     * @param unshared
+     *            read the object unshared
+     * @return the object read
+     *
+     * @throws IOException
+     *             If an IO exception happened when reading the object.
+     * @throws OptionalDataException
+     *             If optional data could not be found when reading the object
+     *             graph
+     * @throws ClassNotFoundException
+     *             If a class for one of the objects could not be found
+     */
+    private Object readNewObject(boolean unshared)
+            throws OptionalDataException, ClassNotFoundException, IOException {
+        ObjectStreamClass classDesc = readClassDesc();
+
+        if (classDesc == null) {
+            throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
+        }
+
+        Integer newHandle = nextHandle();
+
+        // Note that these values come from the Stream, and in fact it could be
+        // that the classes have been changed so that the info below now
+        // conflicts with the newer class
+        boolean wasExternalizable = (classDesc.getFlags() & SC_EXTERNALIZABLE) > 0;
+        boolean wasSerializable = (classDesc.getFlags() & SC_SERIALIZABLE) > 0;
+
+
+        // Maybe we should cache the values above in classDesc ? It may be the
+        // case that when reading classDesc we may need to read more stuff
+        // depending on the values above
+        Class<?> objectClass = classDesc.forClass();
+
+        Object result, registeredResult = null;
+        if (objectClass != null) {
+
+            // BEGIN android-changed
+            // long constructor = classDesc.getConstructor();
+            // if (constructor == ObjectStreamClass.CONSTRUCTOR_IS_NOT_RESOLVED) {
+            //     constructor = accessor.getMethodID(resolveConstructorClass(objectClass, wasSerializable, wasExternalizable), null, new Class[0]);
+            //     classDesc.setConstructor(constructor);
+            // }
+            Class constructorClass = resolveConstructorClass(objectClass, wasSerializable, wasExternalizable);
+            // END android-changed
+
             // Now we know which class to instantiate and which constructor to
             // run. We are allowed to run the constructor.
+            // BEGIN android-changed
+            // result = accessor.newInstance(objectClass, constructor, null);
             result = newInstance(objectClass, constructorClass);
+            // END android-changed
             registerObjectRead(result, newHandle, unshared);
 
             registeredResult = result;
@@ -2131,38 +2154,23 @@
         }
 
         if (objectClass != null) {
-            Object readResolveMethod = readResolveCache.get(objectClass);
-            if (readResolveMethod != this) {
-                if (readResolveMethod == null) {
-                    final Method readResolve = ObjectStreamClass
-                            .methodReadResolve(objectClass);
-                    if (readResolve == null) {
-                        readResolveCache.put(objectClass, this);
-                        readResolveMethod = null;
+
+            if (classDesc.hasMethodReadResolve()){
+                Method methodReadResolve = classDesc.getMethodReadResolve();
+                try {
+                    result = methodReadResolve.invoke(result, (Object[]) null);
+                } catch (IllegalAccessException iae) {
+                } catch (InvocationTargetException ite) {
+                    Throwable target = ite.getTargetException();
+                    if (target instanceof ObjectStreamException) {
+                        throw (ObjectStreamException) target;
+                    } else if (target instanceof Error) {
+                        throw (Error) target;
                     } else {
-                        // Has replacement method
-                        AccessController.doPrivileged(new PriviAction<Object>(
-                                readResolve));
-                        readResolveCache.put(objectClass, readResolve);
-                        readResolveMethod = readResolve;
+                        throw (RuntimeException) target;
                     }
                 }
-                if (readResolveMethod != null) {
-                    try {
-                        result = ((Method) readResolveMethod).invoke(result,
-                                (Object[]) null);
-                    } catch (IllegalAccessException iae) {
-                    } catch (InvocationTargetException ite) {
-                        Throwable target = ite.getTargetException();
-                        if (target instanceof ObjectStreamException) {
-                            throw (ObjectStreamException) target;
-                        } else if (target instanceof Error) {
-                            throw (Error) target;
-                        } else {
-                            throw (RuntimeException) target;
-                        }
-                    }
-                }
+
             }
         }
         // We get here either if class-based replacement was not needed or if it
@@ -2183,7 +2191,7 @@
     /**
      * Read a string encoded in {@link DataInput modified UTF-8} from the
      * receiver. Return the string read.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return the string just read.
@@ -2195,8 +2203,7 @@
         if (enableResolve) {
             result = resolveObject(result);
         }
-        int newHandle = nextHandle();
-        registerObjectRead(result, Integer.valueOf(newHandle), unshared);
+		registerObjectRead(result, nextHandle(), unshared);
 
         return result;
     }
@@ -2204,11 +2211,11 @@
     /**
      * Read a new String in UTF format from the receiver. Return the string
      * read.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return the string just read.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the String.
      */
@@ -2218,15 +2225,14 @@
         if (enableResolve) {
             result = resolveObject(result);
         }
-        int newHandle = nextHandle();
-        registerObjectRead(result, Integer.valueOf(newHandle), unshared);
+        registerObjectRead(result, nextHandle(), unshared);
 
         return result;
     }
 
     /**
      * Reads the next object from the source stream.
-     * 
+     *
      * @return the object read from the source stream.
      * @throws ClassNotFoundException
      *             if the class of one of the objects in the object graph cannot
@@ -2236,7 +2242,6 @@
      * @throws OptionalDataException
      *             if primitive data types were found instead of an object.
      * @see ObjectOutputStream#writeObject(Object)
-     * @since Android 1.0
      */
     public final Object readObject() throws OptionalDataException,
             ClassNotFoundException, IOException {
@@ -2245,7 +2250,7 @@
 
     /**
      * Reads the next unshared object from the source stream.
-     * 
+     *
      * @return the new object read.
      * @throws ClassNotFoundException
      *             if the class of one of the objects in the object graph cannot
@@ -2253,7 +2258,6 @@
      * @throws IOException
      *             if an error occurs while reading from the source stream.
      * @see ObjectOutputStream#writeUnshared
-     * @since Android 1.0
      */
     public Object readUnshared() throws IOException, ClassNotFoundException {
         return readObject(true);
@@ -2347,7 +2351,7 @@
     /**
      * Method to be overriden by subclasses to read the next object from the
      * source stream.
-     * 
+     *
      * @return the object read from the source stream.
      * @throws ClassNotFoundException
      *             if the class of one of the objects in the object graph cannot
@@ -2357,7 +2361,6 @@
      * @throws OptionalDataException
      *             if primitive data types were found instead of an object.
      * @see ObjectOutputStream#writeObjectOverride
-     * @since Android 1.0
      */
     protected Object readObjectOverride() throws OptionalDataException,
             ClassNotFoundException, IOException {
@@ -2370,11 +2373,10 @@
 
     /**
      * Reads a short (16 bit) from the source stream.
-     * 
+     *
      * @return the short value read from the source stream.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public short readShort() throws IOException {
         return primitiveTypes.readShort();
@@ -2382,13 +2384,12 @@
 
     /**
      * Reads and validates the ObjectInputStream header from the source stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while reading from the source stream.
      * @throws StreamCorruptedException
      *             if the source stream does not contain readable serialized
      *             objects.
-     * @since Android 1.0
      */
     protected void readStreamHeader() throws IOException,
             StreamCorruptedException {
@@ -2401,7 +2402,7 @@
 
     /**
      * Reads an unsigned byte (8 bit) from the source stream.
-     * 
+     *
      * @return the unsigned byte value read from the source stream packaged in
      *         an integer.
      * @throws EOFException
@@ -2409,7 +2410,6 @@
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public int readUnsignedByte() throws IOException {
         return primitiveTypes.readUnsignedByte();
@@ -2417,7 +2417,7 @@
 
     /**
      * Reads an unsigned short (16 bit) from the source stream.
-     * 
+     *
      * @return the unsigned short value read from the source stream packaged in
      *         an integer.
      * @throws EOFException
@@ -2425,7 +2425,6 @@
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public int readUnsignedShort() throws IOException {
         return primitiveTypes.readUnsignedShort();
@@ -2434,7 +2433,7 @@
     /**
      * Reads a string encoded in {@link DataInput modified UTF-8} from the
      * source stream.
-     * 
+     *
      * @return the string encoded in {@link DataInput modified UTF-8} read from
      *         the source stream.
      * @throws EOFException
@@ -2442,7 +2441,6 @@
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public String readUTF() throws IOException {
         return primitiveTypes.readUTF();
@@ -2450,11 +2448,11 @@
 
     /**
      * Return the object previously read tagged with handle {@code handle}.
-     * 
+     *
      * @param handle
      *            The handle that this object was assigned when it was read.
      * @return the object previously read.
-     * 
+     *
      * @throws InvalidObjectException
      *             If there is no previously read object with this handle
      */
@@ -2472,14 +2470,14 @@
     /**
      * Assume object {@code obj} has been read, and assign a handle to
      * it, {@code handle}.
-     * 
+     *
      * @param obj
      *            Non-null object being loaded.
      * @param handle
      *            An Integer, the handle to this object
      * @param unshared
      *            Boolean, indicates that caller is reading in unshared mode
-     * 
+     *
      * @see #nextHandle
      */
     private void registerObjectRead(Object obj, Integer handle, boolean unshared) {
@@ -2494,7 +2492,7 @@
      * a class that implements "special" deserialization rules. It can be called
      * multiple times. Validation callbacks are then done in order of decreasing
      * priority, defined by {@code priority}.
-     * 
+     *
      * @param object
      *            an object that can validate itself by receiving a callback.
      * @param priority
@@ -2512,7 +2510,7 @@
         Object instanceBeingRead = this.currentObject;
 
         // We can't be called from just anywhere. There are rules.
-        if (instanceBeingRead == null) {
+        if (instanceBeingRead == null && nestedLevels == 0) {
             throw new NotActiveException();
         }
         if (object == null) {
@@ -2552,7 +2550,7 @@
      * Reset the collection of objects already loaded by the receiver.
      */
     private void resetSeenObjects() {
-        objectsRead = new Hashtable<Integer, Object>();
+        objectsRead = new HashMap<Integer, Object>();
         currentHandle = baseWireHandle;
         primitiveData = emptyStream;
     }
@@ -2572,7 +2570,7 @@
     /**
      * Loads the Java class corresponding to the class descriptor {@code
      * osClass} that has just been read from the source stream.
-     * 
+     *
      * @param osClass
      *            an ObjectStreamClass read from the source stream.
      * @return a Class corresponding to the descriptor {@code osClass}.
@@ -2581,18 +2579,24 @@
      * @throws IOException
      *             if an I/O error occurs while creating the class.
      * @see ObjectOutputStream#annotateClass(Class)
-     * @since Android 1.0
      */
     protected Class<?> resolveClass(ObjectStreamClass osClass)
             throws IOException, ClassNotFoundException {
-        String className = osClass.getName();
-        // if it is primitive class, for example, long.class
-        Class<?> cls = PRIMITIVE_CLASSES.get(className);
+        // fastpath: obtain cached value
+        Class<?> cls = osClass.forClass();
         if (null == cls) {
-            // not primitive class
-            // Use the first non-null ClassLoader on the stack. If null, use the
-            // system class loader
-            return Class.forName(className, true, callerClassLoader);
+            // slowpath: resolve the class
+            String className = osClass.getName();
+
+            // if it is primitive class, for example, long.class
+            cls = PRIMITIVE_CLASSES.get(className);
+
+            if (null == cls) {
+                // not primitive class
+                // Use the first non-null ClassLoader on the stack. If null, use
+                // the system class loader
+                cls = Class.forName(className, true, callerClassLoader);
+            }
         }
         return cls;
     }
@@ -2602,7 +2606,7 @@
      * object} with a new object. Object substitution has to be activated first
      * with calling {@code enableResolveObject(true)}. This implementation just
      * returns {@code object}.
-     * 
+     *
      * @param object
      *            the original object for which a replacement may be defined.
      * @return the replacement object for {@code object}.
@@ -2612,262 +2616,71 @@
      * @see #enableResolveObject
      * @see ObjectOutputStream#enableReplaceObject
      * @see ObjectOutputStream#replaceObject
-     * @since Android 1.0
      */
     protected Object resolveObject(Object object) throws IOException {
         // By default no object replacement. Subclasses can override
         return object;
     }
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code byte} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
+    // BEGIN android-added
+
+    /*
+     * These methods set the value of a field named fieldName of instance. The
+     * field is declared by declaringClass. The field is the same type as the
+     * value parameter.
+     *
+     * these methods could be implemented non-natively on top of
+     * java.lang.reflect at the expense of extra object creation
+     * (java.lang.reflect.Field). Otherwise Serialization could not fetch
+     * private fields, except by the use of a native method like this one.
+     *
+     * @throws NoSuchFieldError If the field does not exist.
      */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, byte value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code char} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
+
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, char value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code double} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
+
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, double value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code float} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, float value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code int} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, int value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code long} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, long value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new value {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            Class which declares the field
-     * @param fieldName
-     *            Name of the field to set
-     * @param fieldTypeName
-     *            Name of the class defining the type of the field
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void objSetField(Object instance,
             Class<?> declaringClass, String fieldName, String fieldTypeName,
             Object value) throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code short} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, short value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code boolean} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, boolean value)
             throws NoSuchFieldError;
 
+    // END android-added
+
     /**
      * Skips {@code length} bytes on the source stream. This method should not
      * be used to skip bytes at any arbitrary position, just when reading
      * primitive data types (int, char etc).
-     * 
+     *
      * @param length
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
@@ -2875,7 +2688,6 @@
      *             if an error occurs while skipping bytes on the source stream.
      * @throws NullPointerException
      *             if the source stream is {@code null}.
-     * @since Android 1.0
      */
     public int skipBytes(int length) throws IOException {
         // To be used with available. Ok to call if reading primitive buffer
@@ -2896,50 +2708,31 @@
     }
 
     /**
-     * Verify if the SUID for descriptor {@code loadedStreamClass}matches
-     * the SUID of the corresponding loaded class.
-     * 
+     * Verify if the SUID & the base name for descriptor
+     * <code>loadedStreamClass</code>matches
+     * the SUID & the base name of the corresponding loaded class and
+     * init private fields.
+     *
      * @param loadedStreamClass
      *            An ObjectStreamClass that was loaded from the stream.
-     * 
+     *
      * @throws InvalidClassException
      *             If the SUID of the stream class does not match the VM class
      */
-    private void verifySUID(ObjectStreamClass loadedStreamClass)
+    private void verifyAndInit(ObjectStreamClass loadedStreamClass)
             throws InvalidClassException {
+
         Class<?> localClass = loadedStreamClass.forClass();
-        // Instances of java.lang.Class are always Serializable, even if their
-        // instances aren't (e.g. java.lang.Object.class). We cannot call lookup
-        // because it returns null if the parameter represents instances that
-        // cannot be serialized, and that is not what we want. If we are loading
-        // an instance of java.lang.Class, we better have the corresponding
-        // ObjectStreamClass.
         ObjectStreamClass localStreamClass = ObjectStreamClass
                 .lookupStreamClass(localClass);
+
         if (loadedStreamClass.getSerialVersionUID() != localStreamClass
                 .getSerialVersionUID()) {
             throw new InvalidClassException(loadedStreamClass.getName(), Msg
                     .getString("K00da", loadedStreamClass, //$NON-NLS-1$
                             localStreamClass));
         }
-    }
 
-    /**
-     * Verify if the base name for descriptor {@code loadedStreamClass}
-     * matches the base name of the corresponding loaded class.
-     * 
-     * @param loadedStreamClass
-     *            An ObjectStreamClass that was loaded from the stream.
-     * 
-     * @throws InvalidClassException
-     *             If the base name of the stream class does not match the VM
-     *             class
-     */
-    private void verifyBaseName(ObjectStreamClass loadedStreamClass)
-            throws InvalidClassException {
-        Class<?> localClass = loadedStreamClass.forClass();
-        ObjectStreamClass localStreamClass = ObjectStreamClass
-                .lookupStreamClass(localClass);
         String loadedClassBaseName = getBaseName(loadedStreamClass.getName());
         String localClassBaseName = getBaseName(localStreamClass.getName());
 
@@ -2948,10 +2741,12 @@
                     .getString("KA015", loadedClassBaseName, //$NON-NLS-1$
                             localClassBaseName));
         }
+
+        loadedStreamClass.initPrivateFields(localStreamClass);
     }
 
     private static String getBaseName(String fullName) {
-        int k = fullName.lastIndexOf("."); //$NON-NLS-1$
+        int k = fullName.lastIndexOf('.');
 
         if (k == -1 || k == (fullName.length() - 1)) {
             return fullName;
diff --git a/luni/src/main/java/java/io/ObjectInputValidation.java b/luni/src/main/java/java/io/ObjectInputValidation.java
index f1cae74..3dce15e 100644
--- a/luni/src/main/java/java/io/ObjectInputValidation.java
+++ b/luni/src/main/java/java/io/ObjectInputValidation.java
@@ -22,10 +22,7 @@
  * example, the validation of a whole graph of objects after all of them have
  * been loaded.
  * 
- * @see ObjectInputStream
  * @see ObjectInputStream#registerValidation(ObjectInputValidation, int)
- * 
- * @since Android 1.0
  */
 public interface ObjectInputValidation {
     /**
@@ -33,7 +30,6 @@
      * 
      * @throws InvalidObjectException
      *             if this object fails to validate itself.
-     * @since Android 1.0
      */
     public void validateObject() throws InvalidObjectException;
 }
diff --git a/luni/src/main/java/java/io/ObjectOutput.java b/luni/src/main/java/java/io/ObjectOutput.java
index cd68439..6680457 100644
--- a/luni/src/main/java/java/io/ObjectOutput.java
+++ b/luni/src/main/java/java/io/ObjectOutput.java
@@ -22,8 +22,6 @@
  * 
  * @see ObjectOutputStream
  * @see ObjectInput
- * 
- * @since Android 1.0
  */
 public interface ObjectOutput extends DataOutput {
     /**
@@ -32,7 +30,6 @@
      * 
      * @throws IOException
      *             if an error occurs while closing the target stream.
-     * @since Android 1.0
      */
     public void close() throws IOException;
 
@@ -42,7 +39,6 @@
      * 
      * @throws IOException
      *             if an error occurs while flushing the target stream.
-     * @since Android 1.0
      */
     public void flush() throws IOException;
 
@@ -54,7 +50,6 @@
      *            the buffer to write.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void write(byte[] buffer) throws IOException;
 
@@ -72,7 +67,6 @@
      *            stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void write(byte[] buffer, int offset, int count) throws IOException;
 
@@ -85,7 +79,6 @@
      *            the byte to write.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void write(int value) throws IOException;
 
@@ -96,7 +89,6 @@
      *            the object to write.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeObject(Object obj) throws IOException;
 }
diff --git a/luni/src/main/java/java/io/ObjectOutputStream.java b/luni/src/main/java/java/io/ObjectOutputStream.java
index 5da4950..e3c1471 100644
--- a/luni/src/main/java/java/io/ObjectOutputStream.java
+++ b/luni/src/main/java/java/io/ObjectOutputStream.java
@@ -20,27 +20,40 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
-import java.security.AccessController;
 import java.util.IdentityHashMap;
 
-import org.apache.harmony.luni.util.PriviAction;
+
+// BEGIN android-note
+// Harmony uses ObjectAccessors to access fields through JNI. Android has not
+// yet migrated that API. As a consequence, there's a lot of changes here...
+// END android-note
+
+// BEGIN android-removed
+// import org.apache.harmony.misc.accessors.ObjectAccessor;
+// import org.apache.harmony.misc.accessors.AccessorFactory;
+// END android-removed
+
+import org.apache.harmony.luni.util.Msg;
 
 /**
  * A specialized {@link OutputStream} that is able to write (serialize) Java
  * objects as well as primitive data types (int, byte, char etc.). The data can
  * later be loaded using an ObjectInputStream.
- * 
+ *
  * @see ObjectInputStream
  * @see ObjectOutput
  * @see Serializable
  * @see Externalizable
- * 
- * @since Android 1.0
  */
 public class ObjectOutputStream extends OutputStream implements ObjectOutput,
         ObjectStreamConstants {
 
     /*
+     * Mask to zero SC_BLOC_DATA bit.
+     */
+    private static final byte NOT_SC_BLOCK_DATA = (byte) (SC_BLOCK_DATA ^ 0xFF);
+
+    /*
      * How many nested levels to writeObject. We may not need this.
      */
     private int nestedLevels;
@@ -107,136 +120,129 @@
      */
     private boolean subclassOverridingImplementation;
 
+
+    // BEGIN android-removed
+    // private ObjectAccessor accessor = AccessorFactory.getObjectAccessor();
+    // END android-removed
+
     /*
-     * cache for writeReplace methods
+     * Descriptor for java.lang.reflect.Proxy
      */
-    private IdentityHashMap<Class<?>, Object> writeReplaceCache;
+    private final ObjectStreamClass proxyClassDesc = ObjectStreamClass.lookup(Proxy.class);
 
     /**
      * PutField is an inner class to provide access to the persistent fields
      * that are written to the target stream.
-     * 
-     * @since Android 1.0
      */
     public static abstract class PutField {
         /**
          * Puts the value of the boolean field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, boolean value);
 
         /**
          * Puts the value of the character field identified by {@code name} to
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, char value);
 
         /**
          * Puts the value of the byte field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, byte value);
 
         /**
          * Puts the value of the short field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, short value);
 
         /**
          * Puts the value of the integer field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, int value);
 
         /**
          * Puts the value of the long field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, long value);
 
         /**
          * Puts the value of the float field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, float value);
 
         /**
          * Puts the value of the double field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, double value);
 
         /**
          * Puts the value of the Object field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, Object value);
 
         /**
          * Writes the fields to the target stream {@code out}.
-         * 
+         *
          * @param out
          *            the target stream
          * @throws IOException
          *             if an error occurs while writing to the target stream.
          * @deprecated This method is unsafe and may corrupt the target stream.
          *             Use ObjectOutputStream#writeFields() instead.
-         * @since Android 1.0
          */
         @Deprecated
         public abstract void write(ObjectOutput out) throws IOException;
@@ -246,14 +252,13 @@
      * Constructs a new {@code ObjectOutputStream}. This default constructor can
      * be used by subclasses that do not want to use the public constructor if
      * it allocates unneeded data.
-     * 
+     *
      * @throws IOException
      *             if an error occurs when creating this stream.
      * @throws SecurityException
      *             if a security manager is installed and it denies subclassing
      *             this class.
      * @see SecurityManager#checkPermission(java.security.Permission)
-     * @since Android 1.0
      */
     protected ObjectOutputStream() throws IOException, SecurityException {
         super();
@@ -271,17 +276,16 @@
     /**
      * Constructs a new ObjectOutputStream that writes to the OutputStream
      * {@code output}.
-     * 
+     *
      * @param output
      *            the non-null OutputStream to filter writes on.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing the object stream
      *             header
      * @throws SecurityException
      *             if a security manager is installed and it denies subclassing
      *             this class.
-     * @since Android 1.0
      */
     public ObjectOutputStream(OutputStream output) throws IOException {
         Class<?> implementationClass = getClass();
@@ -316,7 +320,6 @@
         this.enableReplace = false;
         this.protocolVersion = PROTOCOL_VERSION_2;
         this.subclassOverridingImplementation = false;
-        this.writeReplaceCache = new IdentityHashMap<Class<?>, Object>();
 
         resetState();
         this.nestedException = new StreamCorruptedException();
@@ -333,13 +336,12 @@
      * stream. This optional data can be read when deserializing the class
      * descriptor (ObjectStreamClass) for this class from an input stream. By
      * default, no extra data is saved.
-     * 
+     *
      * @param aClass
      *            the class to annotate.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see ObjectInputStream#resolveClass(ObjectStreamClass)
-     * @since Android 1.0
      */
     protected void annotateClass(Class<?> aClass) throws IOException {
         // By default no extra info is saved. Subclasses can override
@@ -349,13 +351,12 @@
      * Writes optional information for a proxy class to the target stream. This
      * optional data can be read when deserializing the proxy class from an
      * input stream. By default, no extra data is saved.
-     * 
+     *
      * @param aClass
      *            the proxy class to annotate.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see ObjectInputStream#resolveProxyClass(String[])
-     * @since Android 1.0
      */
     protected void annotateProxyClass(Class<?> aClass) throws IOException {
         // By default no extra info is saved. Subclasses can override
@@ -377,10 +378,9 @@
     /**
      * Closes this stream. Any buffered data is flushed. This implementation
      * closes the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -393,7 +393,7 @@
      * Computes the collection of emulated fields that users can manipulate to
      * store a representation different than the one declared by the class of
      * the object being dumped.
-     * 
+     *
      * @see #writeFields
      * @see #writeFieldValues(EmulatedFieldsForDumping)
      */
@@ -405,13 +405,12 @@
      * Default method to write objects to this stream. Serializable fields
      * defined in the object's class and superclasses are written to the output
      * stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @throws NotActiveException
      *             if this method is not called from {@code writeObject()}.
      * @see ObjectInputStream#defaultReadObject
-     * @since Android 1.0
      */
     public void defaultWriteObject() throws IOException {
         // We can't be called from just anywhere. There are rules.
@@ -424,13 +423,12 @@
     /**
      * Writes buffered data to the target stream. This is similar to {@code
      * flush} but the flush is not propagated to the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     protected void drain() throws IOException {
-        if (primitiveTypes == null) {
+        if (primitiveTypes == null || primitiveTypesBuffer == null) {
             return;
         }
 
@@ -462,7 +460,7 @@
     /**
      * Dumps the parameter {@code obj} only if it is {@code null}
      * or an object that has already been dumped previously.
-     * 
+     *
      * @param obj
      *            Object to check if an instance previously dumped by this
      *            stream.
@@ -470,14 +468,14 @@
      *         method does nothing). Integer, if {@code obj} is an
      *         instance which has been dumped already. In this case this method
      *         saves the cyclic reference.
-     * 
+     *
      * @throws IOException
      *             If an error occurs attempting to save {@code null} or
      *             a cyclic reference.
      */
     private Integer dumpCycle(Object obj) throws IOException {
         // If the object has been saved already, save its handle only
-        Integer handle = registeredObjectHandleFor(obj);
+        Integer handle = objectsWritten.get(obj);
         if (handle != null) {
             writeCyclicReference(handle);
             return handle;
@@ -489,7 +487,7 @@
      * Enables object replacement for this stream. By default this is not
      * enabled. Only trusted subclasses (loaded with system class loader) are
      * allowed to change this status.
-     * 
+     *
      * @param enable
      *            {@code true} to enable object replacement; {@code false} to
      *            disable it.
@@ -499,7 +497,6 @@
      *             object replacement for this stream.
      * @see #replaceObject
      * @see ObjectInputStream#enableResolveObject
-     * @since Android 1.0
      */
     protected boolean enableReplaceObject(boolean enable)
             throws SecurityException {
@@ -519,11 +516,10 @@
     /**
      * Writes buffered data to the target stream and calls the {@code flush}
      * method of the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing to or flushing the output
      *             stream.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -531,212 +527,64 @@
         output.flush();
     }
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a boolean.
+    // BEGIN android-added
+    /*
+     * These methods get the value of a field named fieldName of object
+     * instance. The field is declared by declaringClass. The field is the same
+     * type as the method return value.
      *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
+     * these methods could be implemented non-natively on top of
+     * java.lang.reflect at the expense of extra object creation
+     * (java.lang.reflect.Field). Otherwise Serialization could not fetch
+     * private fields, except by the use of a native method like this one.
      *
      * @throws NoSuchFieldError If the field does not exist.
      */
+
     private static native boolean getFieldBool(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a byte
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native byte getFieldByte(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a char.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native char getFieldChar(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a double.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native double getFieldDouble(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a float.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native float getFieldFloat(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * an int.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native int getFieldInt(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a long.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native long getFieldLong(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * an Object type whose name is {@code fieldTypeName}.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @param fieldTypeName Name of the class that defines the type of this field
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native Object getFieldObj(Object instance,
             Class<?> declaringClass, String fieldName, String fieldTypeName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a short.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native short getFieldShort(Object instance,
             Class<?> declaringClass, String fieldName);
+    // END android-added
 
     /**
-     * Return the next {@code int} handle to be used to indicate cyclic
+     * Return the next <code>Integer</code> handle to be used to indicate cyclic
      * references being saved to the stream.
-     * 
-     * @return int, the next handle to represent the next cyclic reference
+     *
+     * @return the next handle to represent the next cyclic reference
      */
-    private int nextHandle() {
-        return this.currentHandle++;
+    private Integer nextHandle() {
+        return Integer.valueOf(this.currentHandle++);
     }
 
     /**
      * Gets this stream's {@code PutField} object. This object provides access
      * to the persistent fields that are eventually written to the output
      * stream. It is used to transfer the values from the fields of the object
-     * that is currently being written to the persistent fields. 
-     * 
+     * that is currently being written to the persistent fields.
+     *
      * @return the PutField object from which persistent fields can be accessed
      *         by name.
      * @throws IOException
@@ -744,7 +592,6 @@
      * @throws NotActiveException
      *             if this method is not called from {@code writeObject()}.
      * @see ObjectInputStream#defaultReadObject
-     * @since Android 1.0
      */
     public PutField putFields() throws IOException {
         // We can't be called from just anywhere. There are rules.
@@ -758,39 +605,25 @@
     }
 
     /**
-     * Return the {@code Integer} handle used to tag object
-     * {@code obj} as an instance that has been dumped already. Return
-     * {@code null} if object {@code obj} has not been saved yet.
-     * 
-     * @param obj
-     *            the object
-     * @return null if object {@code obj} has not been saved yet. Integer
-     *         The handle that this object was assigned when it was saved.
-     */
-    private Integer registeredObjectHandleFor(Object obj) {
-        return objectsWritten.get(obj);
-    }
-
-    /**
      * Assume object {@code obj} has not been dumped yet, and assign a
      * handle to it
-     * 
+     *
      * @param obj
      *            Non-null object being dumped.
      * @return the handle that this object is being assigned.
-     * 
+     *
      * @see #nextHandle
      */
     private Integer registerObjectWritten(Object obj) {
-        Integer handle = Integer.valueOf(nextHandle());
-        registerObjectWritten(obj, handle);
+        Integer handle = nextHandle();
+        objectsWritten.put(obj, handle);
         return handle;
     }
 
     /**
      * Remove the unshared object from the table, and restore any previous
      * handle.
-     * 
+     *
      * @param obj
      *            Non-null object being dumped.
      * @param previousHandle
@@ -798,33 +631,18 @@
      */
     private void removeUnsharedReference(Object obj, Integer previousHandle) {
         if (previousHandle != null) {
-            registerObjectWritten(obj, previousHandle);
+            objectsWritten.put(obj, previousHandle);
         } else {
             objectsWritten.remove(obj);
         }
     }
 
     /**
-     * Assume object {@code obj} has not been dumped yet, and assign a
-     * handle to it, {@code handle}.
-     * 
-     * @param obj
-     *            Non-null object being dumped.
-     * @param handle
-     *            An Integer, the handle to this object
-     * 
-     * @see #nextHandle
-     */
-    private void registerObjectWritten(Object obj, Integer handle) {
-        objectsWritten.put(obj, handle);
-    }
-
-    /**
      * Allows trusted subclasses to substitute the specified original {@code
      * object} with a new object. Object substitution has to be activated first
      * with calling {@code enableReplaceObject(true)}. This implementation just
      * returns {@code object}.
-     * 
+     *
      * @param object
      *            the original object for which a replacement may be defined.
      * @return the replacement object for {@code object}.
@@ -834,7 +652,6 @@
      * @see #enableReplaceObject
      * @see ObjectInputStream#enableResolveObject
      * @see ObjectInputStream#resolveObject
-     * @since Android 1.0
      */
     protected Object replaceObject(Object object) throws IOException {
         // By default no object replacement. Subclasses can override
@@ -847,11 +664,10 @@
      * point. Objects previously written are no longer remembered, so they will
      * be written again (instead of a cyclical reference) if found in the object
      * graph.
-     * 
+     *
      * @throws IOException
      *             if {@code reset()} is called during the serialization of an
      *             object.
-     * @since Android 1.0
      */
     public void reset() throws IOException {
         // First we flush what we have
@@ -869,7 +685,7 @@
      * Reset the collection of objects already dumped by the receiver. If the
      * objects are found again in the object graph, the receiver will dump them
      * again, instead of a handle (cyclic reference).
-     * 
+     *
      */
     private void resetSeenObjects() {
         objectsWritten = new IdentityHashMap<Object, Integer>();
@@ -880,7 +696,7 @@
      * Reset the receiver. The collection of objects already dumped by the
      * receiver is reset, and internal structures are also reset so that the
      * receiver knows it is in a fresh clean state.
-     * 
+     *
      */
     private void resetState() {
         resetSeenObjects();
@@ -889,7 +705,7 @@
 
     /**
      * Sets the specified protocol version to be used by this stream.
-     * 
+     *
      * @param version
      *            the protocol version to be used. Use a {@code
      *            PROTOCOL_VERSION_x} constant from {@code
@@ -900,13 +716,16 @@
      *             if an I/O error occurs.
      * @see ObjectStreamConstants#PROTOCOL_VERSION_1
      * @see ObjectStreamConstants#PROTOCOL_VERSION_2
-     * @since Android 1.0
      */
     public void useProtocolVersion(int version) throws IOException {
+        if (!objectsWritten.isEmpty()) {
+            // KA028=Cannot set protocol version when stream in use
+            throw new IllegalStateException(Msg.getString("KA028")); //$NON-NLS-1$
+        }
         if (version != ObjectStreamConstants.PROTOCOL_VERSION_1
                 && version != ObjectStreamConstants.PROTOCOL_VERSION_2) {
-            throw new IllegalArgumentException(org.apache.harmony.luni.util.Msg
-                    .getString("K00b3", version)); //$NON-NLS-1$
+            // K00b3=Unknown protocol\: {0}
+            throw new IllegalArgumentException(Msg.getString("K00b3", version)); //$NON-NLS-1$
         }
         protocolVersion = version;
     }
@@ -914,12 +733,11 @@
     /**
      * Writes the entire contents of the byte array {@code buffer} to the output
      * stream. Blocks until all bytes are written.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer) throws IOException {
@@ -931,7 +749,7 @@
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * offset {@code index} to the target stream. Blocks until all bytes are
      * written.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -941,7 +759,6 @@
      *            stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int length) throws IOException {
@@ -953,12 +770,11 @@
      * Writes a single byte to the target stream. Only the least significant
      * byte of the integer {@code value} is written to the stream. Blocks until
      * the byte is actually written.
-     * 
+     *
      * @param value
      *            the byte to write.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     @Override
     public void write(int value) throws IOException {
@@ -968,12 +784,11 @@
 
     /**
      * Writes a boolean to the target stream.
-     * 
+     *
      * @param value
      *            the boolean value to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeBoolean(boolean value) throws IOException {
         checkWritePrimitiveTypes();
@@ -982,12 +797,11 @@
 
     /**
      * Writes a byte (8 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the byte to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeByte(int value) throws IOException {
         checkWritePrimitiveTypes();
@@ -998,12 +812,11 @@
      * Writes the string {@code value} as a sequence of bytes to the target
      * stream. Only the least significant byte of each character in the string
      * is written.
-     * 
+     *
      * @param value
      *            the string to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeBytes(String value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1012,12 +825,11 @@
 
     /**
      * Writes a character (16 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the character to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeChar(int value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1027,12 +839,11 @@
     /**
      * Writes the string {@code value} as a sequence of characters to the target
      * stream.
-     * 
+     *
      * @param value
      *            the string to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeChars(String value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1042,14 +853,14 @@
     /**
      * Write a class descriptor {@code classDesc} (an
      * {@code ObjectStreamClass}) to the stream.
-     * 
+     *
      * @param classDesc
      *            The class descriptor (an {@code ObjectStreamClass}) to
      *            be dumped
      * @param unshared
      *            Write the object unshared
      * @return the handle assigned to the class descriptor
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the class
      *             descriptor.
@@ -1066,12 +877,16 @@
         }
         if (handle == null) {
             Class<?> classToWrite = classDesc.forClass();
-            Integer previousHandle = objectsWritten.get(classDesc);
+            Integer previousHandle = null;
+            if (unshared) {
+                previousHandle = objectsWritten.get(classDesc);
+            }
             // If we got here, it is a new (non-null) classDesc that will have
             // to be registered as well
-            handle = registerObjectWritten(classDesc);
+            handle = nextHandle();
+            objectsWritten.put(classDesc, handle);
 
-            if (Proxy.isProxyClass(classToWrite)) {
+            if (classDesc.isProxy()) {
                 output.writeByte(TC_PROXYCLASSDESC);
                 Class<?>[] interfaces = classToWrite.getInterfaces();
                 output.writeInt(interfaces.length);
@@ -1080,7 +895,7 @@
                 }
                 annotateProxyClass(classToWrite);
                 output.writeByte(TC_ENDBLOCKDATA);
-                writeClassDescForClass(Proxy.class);
+                writeClassDesc(proxyClassDesc, false);
                 if (unshared) {
                     // remove reference to unshared object
                     removeUnsharedReference(classDesc, previousHandle);
@@ -1112,31 +927,12 @@
     }
 
     /**
-     * Writes a class descriptor (an {@code ObjectStreamClass}) that
-     * corresponds to the {@code java.lang.Class objClass} to the stream.
-     * 
-     * @param objClass
-     *            The class for which a class descriptor (an
-     *            {@code ObjectStreamClass}) will be dumped.
-     * @return the handle assigned to the class descriptor
-     * 
-     * @throws IOException
-     *             If an IO exception happened when writing the class
-     *             descriptor.
-     * 
-     */
-    private Integer writeClassDescForClass(Class<?> objClass)
-            throws IOException {
-        return writeClassDesc(ObjectStreamClass.lookup(objClass), false);
-    }
-
-    /**
      * Writes a handle representing a cyclic reference (object previously
      * dumped).
-     * 
+     *
      * @param handle
      *            The Integer handle that represents an object previously seen
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the cyclic
      *             reference.
@@ -1148,12 +944,11 @@
 
     /**
      * Writes a double (64 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the double to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeDouble(double value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1164,17 +959,17 @@
      * Writes a collection of field descriptors (name, type name, etc) for the
      * class descriptor {@code classDesc} (an
      * {@code ObjectStreamClass})
-     * 
+     *
      * @param classDesc
      *            The class descriptor (an {@code ObjectStreamClass})
      *            for which to write field information
      * @param externalizable
      *            true if the descriptors are externalizable
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the field
      *             descriptors.
-     * 
+     *
      * @see #writeObject(Object)
      */
     private void writeFieldDescriptors(ObjectStreamClass classDesc,
@@ -1207,13 +1002,12 @@
      * Writes the fields of the object currently being written to the target
      * stream. The field values are buffered in the currently active {@code
      * PutField} object, which can be accessed by calling {@code putFields()}.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @throws NotActiveException
      *             if there are no fields to write to the target stream.
      * @see #putFields
-     * @since Android 1.0
      */
     public void writeFields() throws IOException {
         // Has to have fields to write
@@ -1226,14 +1020,14 @@
     /**
      * Writes a collection of field values for the emulated fields
      * {@code emulatedFields}
-     * 
+     *
      * @param emulatedFields
      *            an {@code EmulatedFieldsForDumping}, concrete subclass
      *            of {@code PutField}
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the field values.
-     * 
+     *
      * @see #writeFields
      * @see #writeObject(Object)
      */
@@ -1279,32 +1073,37 @@
         }
     }
 
+
     /**
      * Writes a collection of field values for the fields described by class
      * descriptor {@code classDesc} (an {@code ObjectStreamClass}).
      * This is the default mechanism, when emulated fields (an
      * {@code PutField}) are not used. Actual values to dump are fetched
      * directly from object {@code obj}.
-     * 
+     *
      * @param obj
      *            Instance from which to fetch field values to dump.
      * @param classDesc
      *            A class descriptor (an {@code ObjectStreamClass})
      *            defining which fields should be dumped.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the field values.
-     * 
+     *
      * @see #writeObject(Object)
      */
     private void writeFieldValues(Object obj, ObjectStreamClass classDesc)
             throws IOException {
         ObjectStreamField[] fields = classDesc.fields();
         Class<?> declaringClass = classDesc.forClass();
-        for (int i = 0; i < fields.length; i++) {
+        for(ObjectStreamField fieldDesc : fields) {
             try {
+
+                // BEGIN android-changed
+                // // get associated Field
+                // long fieldID = fieldDesc.getFieldID(accessor, declaringClass);
+
                 // Code duplication starts, just because Java is typed
-                ObjectStreamField fieldDesc = fields[i];
                 if (fieldDesc.isPrimitive()) {
                     switch (fieldDesc.getTypeCode()) {
                         case 'B':
@@ -1346,14 +1145,15 @@
                     }
                 } else {
                     // Object type (array included).
-                    Object field = getFieldObj(obj, declaringClass, fieldDesc
+                    Object objField = getFieldObj(obj, declaringClass, fieldDesc
                             .getName(), fieldDesc.getTypeString());
                     if (fieldDesc.isUnshared()) {
-                        writeUnshared(field);
+                        writeUnshared(objField);
                     } else {
-                        writeObject(field);
+                        writeObject(objField);
                     }
                 }
+                // END android-changed
             } catch (NoSuchFieldError nsf) {
                 // The user defined serialPersistentFields but did not provide
                 // the glue to transfer values,
@@ -1366,12 +1166,11 @@
 
     /**
      * Writes a float (32 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the float to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeFloat(float value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1386,19 +1185,19 @@
      * (corresponding to class descriptor {@code classDesc}) defines
      * private instance method {@code writeObject} it will be used to
      * dump field values.
-     * 
+     *
      * @param object
      *            Instance from which to fetch field values to dump.
      * @param classDesc
      *            A class descriptor (an {@code ObjectStreamClass})
      *            defining which fields should be dumped.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the field values in
      *             the hierarchy.
      * @throws NotActiveException
      *             If the given object is not active
-     * 
+     *
      * @see #defaultWriteObject
      * @see #writeObject(Object)
      */
@@ -1423,14 +1222,9 @@
 
         // See if the object has a writeObject method. If so, run it
         boolean executed = false;
-        Class<?> targetClass = classDesc.forClass();
         try {
-            final Method method = ObjectStreamClass
-                    .getPrivateWriteObjectMethod(targetClass);
-            if (method != null) {
-                // We have to be able to fetch its value, even if it is
-                // private
-                AccessController.doPrivileged(new PriviAction<Object>(method));
+            if (classDesc.hasMethodWriteObject()){
+                final Method method = classDesc.getMethodWriteObject();
                 try {
                     method.invoke(object, new Object[] { this });
                     executed = true;
@@ -1447,6 +1241,7 @@
                 }
             }
 
+
             if (executed) {
                 drain();
                 output.writeByte(TC_ENDBLOCKDATA);
@@ -1466,12 +1261,11 @@
 
     /**
      * Writes an integer (32 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the integer to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeInt(int value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1480,12 +1274,11 @@
 
     /**
      * Writes a long (64 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the long to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeLong(long value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1497,7 +1290,7 @@
      * component type {@code componentType} into the receiver. It is
      * assumed the array has not been dumped yet. Return an {@code Integer}
      * that represents the handle for this object (array) which is dumped here.
-     * 
+     *
      * @param array
      *            The array object to dump
      * @param arrayClass
@@ -1507,20 +1300,19 @@
      *            A {@code java.lang.Class} representing the array
      *            component type
      * @return the handle assigned to the array
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the array.
      */
-    private Integer writeNewArray(Object array, Class<?> arrayClass,
+    private Integer writeNewArray(Object array, Class<?> arrayClass, ObjectStreamClass arrayClDesc,
             Class<?> componentType, boolean unshared) throws IOException {
         output.writeByte(TC_ARRAY);
-        writeClassDescForClass(arrayClass);
+        writeClassDesc(arrayClDesc, false);
 
-        Integer previousHandle = objectsWritten.get(array);
-        Integer handle = registerObjectWritten(array);
-        if (unshared) {
-            // remove reference to unshared object
-            removeUnsharedReference(array, previousHandle);
+        Integer handle = nextHandle();
+
+        if (!unshared) {
+            objectsWritten.put(array, handle);
         }
 
         // Now we have code duplication just because Java is typed. We have to
@@ -1585,6 +1377,10 @@
             Object[] objectArray = (Object[]) array;
             output.writeInt(objectArray.length);
             for (int i = 0; i < objectArray.length; i++) {
+                // TODO: This place is the opportunity for enhancement
+                //      We can implement writing elements through fast-path,
+                //      without setting up the context (see writeObject()) for
+                //      each element with public API
                 writeObject(objectArray[i]);
             }
         }
@@ -1597,11 +1393,11 @@
      * descriptor ({@code ObjectStreamClass}) that corresponds to them.
      * Return an {@code Integer} that represents the handle for this
      * object (class) which is dumped here.
-     * 
+     *
      * @param object
      *            The {@code java.lang.Class} object to dump
      * @return the handle assigned to the class being dumped
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the class.
      */
@@ -1614,21 +1410,20 @@
         // We cannot call lookup because it returns null if the parameter
         // represents instances that cannot be serialized, and that is not what
         // we want.
+        ObjectStreamClass clDesc = ObjectStreamClass.lookupStreamClass(object);
 
         // The handle for the classDesc is NOT the handle for the class object
         // being dumped. We must allocate a new handle and return it.
-        if (object.isEnum()) {
-            writeEnumDesc(object, unshared);
+        if (clDesc.isEnum()) {
+            writeEnumDesc(object, clDesc, unshared);
         } else {
-            writeClassDesc(ObjectStreamClass.lookupStreamClass(object),
-                    unshared);
+            writeClassDesc(clDesc, unshared);
         }
 
-        Integer previousHandle = objectsWritten.get(object);
-        Integer handle = registerObjectWritten(object);
-        if (unshared) {
-            // remove reference to unshared object
-            removeUnsharedReference(object, previousHandle);
+        Integer handle = nextHandle();
+
+        if (!unshared) {
+            objectsWritten.put(object, handle);
         }
 
         return handle;
@@ -1640,10 +1435,10 @@
      * descriptors for the superclass chain will be dumped as well. Return an
      * {@code Integer} that represents the handle for this object (class
      * descriptor) which is dumped here.
-     * 
+     *
      * @param classDesc
      *            The {@code ObjectStreamClass} object to dump
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the class
      *             descriptor.
@@ -1653,15 +1448,15 @@
         output.writeUTF(classDesc.getName());
         output.writeLong(classDesc.getSerialVersionUID());
         byte flags = classDesc.getFlags();
-        boolean externalizable = false;
-        externalizable = ObjectStreamClass.isExternalizable(classDesc
-                .forClass());
-        if (protocolVersion != PROTOCOL_VERSION_1) {
-            // Change for 1.2. Objects can be saved in old format
-            // (PROTOCOL_VERSION_1) or in the 1.2 format (PROTOCOL_VERSION_2).
-            // Nested "if" check to optimize checking. Second check is more
-            // expensive.
-            if (externalizable) {
+
+        boolean externalizable = classDesc.isExternalizable();
+
+        if (externalizable) {
+            if (protocolVersion == PROTOCOL_VERSION_1) {
+                flags &= NOT_SC_BLOCK_DATA;
+            } else {
+                // Change for 1.2. Objects can be saved in old format
+                // (PROTOCOL_VERSION_1) or in the 1.2 format (PROTOCOL_VERSION_2).
                 flags |= SC_BLOCK_DATA;
             }
         }
@@ -1676,12 +1471,11 @@
 
     /**
      * Writes a class descriptor to the target stream.
-     * 
+     *
      * @param classDesc
      *            the class descriptor to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     protected void writeClassDescriptor(ObjectStreamClass classDesc)
             throws IOException {
@@ -1695,14 +1489,14 @@
      * This is used to dump the exception instance that happened (if any) when
      * dumping the original object graph. The set of seen objects will be reset
      * just before and just after dumping this exception object.
-     * 
+     *
      * When exceptions are found normally in the object graph, they are dumped
      * as a regular object, and not by this method. In that case, the set of
      * "known objects" is not reset.
-     * 
+     *
      * @param ex
      *            Exception object to dump
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the exception
      *             object.
@@ -1719,13 +1513,13 @@
      * the receiver. It is assumed the object has not been dumped yet. Return an
      * {@code Integer} that represents the handle for this object which
      * is dumped here.
-     * 
+     *
      * If the object implements {@code Externalizable} its
      * {@code writeExternal} is called. Otherwise, all fields described
      * by the class hierarchy is dumped. Each class can define how its declared
      * instance fields are dumped by defining a private method
      * {@code writeObject}
-     * 
+     *
      * @param object
      *            The object to dump
      * @param theClass
@@ -1734,11 +1528,11 @@
      * @param unshared
      *            Write the object unshared
      * @return the handle assigned to the object
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the object.
      */
-    private Integer writeNewObject(Object object, Class<?> theClass,
+    private Integer writeNewObject(Object object, Class<?> theClass, ObjectStreamClass clDesc,
             boolean unshared) throws IOException {
         // Not String, not null, not array, not cyclic reference
 
@@ -1746,8 +1540,8 @@
         currentPutField = null; // null it, to make sure one will be computed if
         // needed
 
-        boolean externalizable = ObjectStreamClass.isExternalizable(theClass);
-        boolean serializable = ObjectStreamClass.isSerializable(theClass);
+        boolean externalizable = clDesc.isExternalizable();
+        boolean serializable = clDesc.isSerializable();
         if (!externalizable && !serializable) {
             // Object is neither externalizable nor serializable. Error
             throw new NotSerializableException(theClass.getName());
@@ -1755,16 +1549,20 @@
 
         // Either serializable or externalizable, now we can save info
         output.writeByte(TC_OBJECT);
-        writeClassDescForClass(theClass);
-        Integer previousHandle = objectsWritten.get(object);
-        Integer handle = registerObjectWritten(object);
+        writeClassDesc(clDesc, false);
+        Integer previousHandle = null;
+        if (unshared) {
+            previousHandle = objectsWritten.get(object);
+        }
+        Integer handle = nextHandle();
+        objectsWritten.put(object, handle);
 
         // This is how we know what to do in defaultWriteObject. And it is also
         // used by defaultWriteObject to check if it was called from an invalid
         // place.
         // It allows writeExternal to call defaultWriteObject and have it work.
         currentObject = object;
-        currentClass = ObjectStreamClass.lookup(theClass);
+        currentClass = clDesc;
         try {
             if (externalizable) {
                 boolean noBlockData = protocolVersion == PROTOCOL_VERSION_1;
@@ -1808,11 +1606,11 @@
      * String has not been dumped yet. Return an {@code Integer} that
      * represents the handle for this object (String) which is dumped here.
      * Strings are saved encoded with {@link DataInput modified UTF-8}.
-     * 
+     *
      * @param object
      *            the string to dump.
      * @return the handle assigned to the String being dumped
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the String.
      */
@@ -1828,19 +1626,19 @@
         }
         output.writeUTFBytes(object, count);
 
-        Integer previousHandle = objectsWritten.get(object);
-        Integer handle = registerObjectWritten(object);
-        if (unshared) {
-            // remove reference to unshared object
-            removeUnsharedReference(object, previousHandle);
+        Integer handle = nextHandle();
+
+        if (!unshared) {
+            objectsWritten.put(object, handle);
         }
+
         return handle;
     }
 
     /**
      * Write a special tag that indicates the value {@code null} into the
      * receiver.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the tag for
      *             {@code null}.
@@ -1851,13 +1649,12 @@
 
     /**
      * Writes an object to the target stream.
-     * 
+     *
      * @param object
      *            the object to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see ObjectInputStream#readObject()
-     * @since Android 1.0
      */
     public final void writeObject(Object object) throws IOException {
         writeObject(object, false);
@@ -1868,13 +1665,12 @@
      * to {@code writeObject}, except that it always writes a new object to the
      * stream versus the use of back-referencing for identical objects by
      * {@code writeObject}.
-     * 
+     *
      * @param object
      *            the object to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see ObjectInputStream#readUnshared()
-     * @since Android 1.0
      */
     public void writeUnshared(Object object) throws IOException {
         writeObject(object, true);
@@ -1919,7 +1715,7 @@
 
     /**
      * Write object {@code object} into the receiver's underlying stream.
-     * 
+     *
      * @param object
      *            The object to write
      * @param unshared
@@ -1931,10 +1727,10 @@
      *            A boolean indicating if stream-based replacement should be
      *            computed (if supported) for the object.
      * @return the handle assigned to the final object being dumped
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the object
-     * 
+     *
      * @see ObjectInputStream#readObject()
      */
     private Integer writeObjectInternal(Object object, boolean unshared,
@@ -1955,6 +1751,8 @@
 
         // Non-null object, first time seen...
         Class<?> objClass = object.getClass();
+        ObjectStreamClass clDesc = ObjectStreamClass.lookupStreamClass(objClass);
+
         nestedLevels++;
         try {
 
@@ -1969,58 +1767,41 @@
                 }
             }
 
-            if (ObjectStreamClass.isSerializable(object.getClass())
+            if (clDesc.isSerializable()
                     && computeClassBasedReplacement) {
-                Object writeReplaceMethod = writeReplaceCache.get(objClass);
-                if (writeReplaceMethod != this) {
-                    if (writeReplaceMethod == null) {
-                        final Method writeReplace = ObjectStreamClass
-                                .methodWriteReplace(objClass);
-                        if (writeReplace == null) {
-                            writeReplaceCache.put(objClass, this);
-                            writeReplaceMethod = null;
+                if(clDesc.hasMethodWriteReplace()){
+                    Method methodWriteReplace = clDesc.getMethodWriteReplace();
+                    Object replObj = null;
+                    try {
+                        replObj = methodWriteReplace.invoke(object, (Object[]) null);
+                    } catch (IllegalAccessException iae) {
+                        replObj = object;
+                    } catch (InvocationTargetException ite) {
+                        // WARNING - Not sure this is the right thing to do
+                        // if we can't run the method
+                        Throwable target = ite.getTargetException();
+                        if (target instanceof ObjectStreamException) {
+                            throw (ObjectStreamException) target;
+                        } else if (target instanceof Error) {
+                            throw (Error) target;
                         } else {
-                            // Has replacement method
-                            AccessController
-                                    .doPrivileged(new PriviAction<Object>(
-                                            writeReplace));
-                            writeReplaceCache.put(objClass, writeReplace);
-                            writeReplaceMethod = writeReplace;
+                            throw (RuntimeException) target;
                         }
                     }
-                    if (writeReplaceMethod != null) {
-                        Object classBasedReplacement;
-                        try {
-                            classBasedReplacement = ((Method) writeReplaceMethod)
-                                    .invoke(object, (Object[]) null);
-                        } catch (IllegalAccessException iae) {
-                            classBasedReplacement = object;
-                        } catch (InvocationTargetException ite) {
-                            // WARNING - Not sure this is the right thing to do
-                            // if we can't run the method
-                            Throwable target = ite.getTargetException();
-                            if (target instanceof ObjectStreamException) {
-                                throw (ObjectStreamException) target;
-                            } else if (target instanceof Error) {
-                                throw (Error) target;
-                            } else {
-                                throw (RuntimeException) target;
-                            }
+                    if (replObj != object) {
+                        // All over, class-based replacement off this time.
+                        Integer replacementHandle = writeObjectInternal(
+                                replObj, false, false,
+                                computeStreamReplacement);
+                        // Make the original object also map to the same
+                        // handle.
+                        if (replacementHandle != null) {
+                            objectsWritten.put(object, replacementHandle);
                         }
-                        if (classBasedReplacement != object) {
-                            // All over, class-based replacement off this time.
-                            Integer replacementHandle = writeObjectInternal(
-                                    classBasedReplacement, false, false,
-                                    computeStreamReplacement);
-                            // Make the original object also map to the same
-                            // handle.
-                            if (replacementHandle != null) {
-                                registerObjectWritten(object, replacementHandle);
-                            }
-                            return replacementHandle;
-                        }
+                        return replacementHandle;
                     }
                 }
+
             }
 
             // We get here either if class-based replacement was not needed or
@@ -2036,7 +1817,7 @@
                             computeClassBasedReplacement, false);
                     // Make the original object also map to the same handle.
                     if (replacementHandle != null) {
-                        registerObjectWritten(object, replacementHandle);
+                        objectsWritten.put(object, replacementHandle);
                     }
                     return replacementHandle;
                 }
@@ -2061,7 +1842,7 @@
 
             // Is it an Array ?
             if (objClass.isArray()) {
-                return writeNewArray(object, objClass, objClass
+                return writeNewArray(object, objClass, clDesc, objClass
                         .getComponentType(), unshared);
             }
 
@@ -2070,20 +1851,23 @@
             }
 
             // Not a String or Class or Array. Default procedure.
-            return writeNewObject(object, objClass, unshared);
+            return writeNewObject(object, objClass, clDesc, unshared);
         } finally {
             nestedLevels--;
         }
     }
 
     // write for Enum Class Desc only, which is different from other classes
-    private ObjectStreamClass writeEnumDesc(Class<?> theClass, boolean unshared)
+    private ObjectStreamClass writeEnumDesc(Class<?> theClass, ObjectStreamClass classDesc, boolean unshared)
             throws IOException {
         // write classDesc, classDesc for enum is different
-        ObjectStreamClass classDesc = ObjectStreamClass.lookup(theClass);
+
         // set flag for enum, the flag is (SC_SERIALIZABLE | SC_ENUM)
         classDesc.setFlags((byte) (SC_SERIALIZABLE | SC_ENUM));
-        Integer previousHandle = objectsWritten.get(classDesc);
+        Integer previousHandle = null;
+        if (unshared) {
+            previousHandle = objectsWritten.get(classDesc);
+        }
         Integer handle = null;
         if (!unshared) {
             handle = dumpCycle(classDesc);
@@ -2092,7 +1876,7 @@
             Class<?> classToWrite = classDesc.forClass();
             // If we got here, it is a new (non-null) classDesc that will have
             // to be registered as well
-            registerObjectWritten(classDesc);
+            objectsWritten.put(classDesc, nextHandle());
 
             output.writeByte(TC_CLASSDESC);
             if (protocolVersion == PROTOCOL_VERSION_1) {
@@ -2109,11 +1893,11 @@
             drain(); // flush primitive types in the annotation
             output.writeByte(TC_ENDBLOCKDATA);
             // write super class
-            ObjectStreamClass superClass = classDesc.getSuperclass();
-            if (null != superClass) {
+            ObjectStreamClass superClassDesc = classDesc.getSuperclass();
+            if (null != superClassDesc) {
                 // super class is also enum
-                superClass.setFlags((byte) (SC_SERIALIZABLE | SC_ENUM));
-                writeEnumDesc(superClass.forClass(), unshared);
+                superClassDesc.setFlags((byte) (SC_SERIALIZABLE | SC_ENUM));
+                writeEnumDesc(superClassDesc.forClass(), superClassDesc, unshared);
             } else {
                 output.writeByte(TC_NULL);
             }
@@ -2137,18 +1921,26 @@
             // write enum only
             theClass = theClass.getSuperclass();
         }
-        ObjectStreamClass classDesc = writeEnumDesc(theClass, unshared);
+        ObjectStreamClass classDesc = ObjectStreamClass.lookup(theClass);
+        writeEnumDesc(theClass, classDesc, unshared);
 
-        Integer previousHandle = objectsWritten.get(object);
-        Integer handle = registerObjectWritten(object);
+        Integer previousHandle = null;
+        if (unshared) {
+            previousHandle = objectsWritten.get(object);
+        }
+        Integer handle = nextHandle();
+        objectsWritten.put(object, handle);
 
         ObjectStreamField[] fields = classDesc.getSuperclass().fields();
         Class<?> declaringClass = classDesc.getSuperclass().forClass();
         // Only write field "name" for enum class, which is the second field of
         // enum, that is fields[1]. Ignore all non-fields and fields.length < 2
         if (null != fields && fields.length > 1) {
+            // BEGIN android-changed
             String str = (String) getFieldObj(object, declaringClass, fields[1]
                     .getName(), fields[1].getTypeString());
+            // END android-changed
+
             Integer strhandle = null;
             if (!unshared) {
                 strhandle = dumpCycle(str);
@@ -2169,31 +1961,26 @@
     /**
      * Method to be overridden by subclasses to write {@code object} to the
      * target stream.
-     * 
+     *
      * @param object
      *            the object to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     protected void writeObjectOverride(Object object) throws IOException {
-        // BEGIN android-changed
-        // copied from newer version of harmony
         if (!subclassOverridingImplementation) {
             // Subclasses must override.
             throw new IOException();
         }
-        // END android-changed
     }
 
     /**
      * Writes a short (16 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the short to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeShort(int value) throws IOException {
         checkWritePrimitiveTypes();
@@ -2202,10 +1989,9 @@
 
     /**
      * Writes the {@link ObjectOutputStream} header to the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     protected void writeStreamHeader() throws IOException {
         output.writeShort(STREAM_MAGIC);
@@ -2215,12 +2001,11 @@
     /**
      * Writes a string encoded with {@link DataInput modified UTF-8} to the
      * target stream.
-     * 
+     *
      * @param value
      *            the string to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeUTF(String value) throws IOException {
         checkWritePrimitiveTypes();
diff --git a/luni/src/main/java/java/io/ObjectStreamClass.java b/luni/src/main/java/java/io/ObjectStreamClass.java
index 37b1f17..ac356ea 100644
--- a/luni/src/main/java/java/io/ObjectStreamClass.java
+++ b/luni/src/main/java/java/io/ObjectStreamClass.java
@@ -22,6 +22,7 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
 import java.security.AccessController;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -33,18 +34,17 @@
 
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
+import org.apache.harmony.luni.util.ThreadLocalCache;
 
 /**
  * Represents a descriptor for identifying a class during serialization and
  * deserialization. Information contained in the descriptor includes the name
  * and SUID of the class as well as field names and types. Information inherited
  * from the superclasses is also taken into account.
- * 
+ *
  * @see ObjectOutputStream
  * @see ObjectInputStream
  * @see java.lang.Class
- * 
- * @since Android 1.0
  */
 public class ObjectStreamClass implements Serializable {
 
@@ -55,6 +55,8 @@
     // Name of the field that contains the SUID value (if present)
     private static final String UID_FIELD_NAME = "serialVersionUID"; //$NON-NLS-1$
 
+    static final long CONSTRUCTOR_IS_NOT_RESOLVED = -1;
+
     private static final int CLASS_MODIFIERS_MASK;
 
     private static final int FIELD_MODIFIERS_MASK;
@@ -98,8 +100,6 @@
 
     /**
      * Constant indicating that the class has no Serializable fields.
-     * 
-     * @since Android 1.0
      */
     public static final ObjectStreamField[] NO_FIELDS = new ObjectStreamField[0];
 
@@ -135,9 +135,36 @@
 
     static final Class<ObjectStreamClass> OBJECTSTREAMCLASSCLASS = ObjectStreamClass.class;
 
-    // Table mapping instances of java.lang.Class to to corresponding instances
-    // of ObjectStreamClass
-    private static final WeakHashMap<Class<?>, ObjectStreamClass> classesAndDescriptors = new WeakHashMap<Class<?>, ObjectStreamClass>();
+    private transient Method methodWriteReplace;
+
+    private transient Method methodReadResolve;
+
+    private transient Method methodWriteObject;
+
+    private transient Method methodReadObject;
+
+    private transient Method methodReadObjectNoData;
+
+    /**
+     * Indicates whether the class properties resolved
+     *
+     * @see #resolveProperties()
+     */
+    private transient boolean arePropertiesResolved;
+
+    /**
+     * Cached class properties
+     *
+     * @see #resolveProperties()
+     * @see #isSerializable()
+     * @see #isExternalizable()
+     * @see #isProxy()
+     * @see #isEnum()
+     */
+    private transient boolean isSerializable;
+    private transient boolean isExternalizable;
+    private transient boolean isProxy;
+    private transient boolean isEnum;
 
     // ClassDesc //
 
@@ -167,6 +194,17 @@
     // Array of ObjectStreamField describing the serialized fields of this class
     private transient ObjectStreamField[] loadFields;
 
+    // MethodID for deserialization constructor
+    private transient long constructor = CONSTRUCTOR_IS_NOT_RESOLVED;
+
+    void setConstructor(long newConstructor) {
+        constructor = newConstructor;
+    }
+
+    long getConstructor() {
+        return constructor;
+    }
+
     /*
      * If an ObjectStreamClass describes an Externalizable class, it (the
      * descriptor) should not have field descriptors (ObjectStreamField) at all.
@@ -183,22 +221,24 @@
     }
 
     /**
-     * Adds an extra entry mapping a given class {@code cl} to its class
-     * descriptor, which will be computed (an ObjectStreamClass). If
-     * {@code computeSUID} is true, this method will compute the SUID for
-     * this class.
-     * 
+     * Compute class descriptor for a given class <code>cl</code>.
+     *
      * @param cl
      *            a java.langClass for which to compute the corresponding
      *            descriptor
-     * @param computeSUID
-     *            a boolean indicating if SUID should be computed or not.
      * @return the computer class descriptor
      */
-    private static ObjectStreamClass addToCache(Class<?> cl, boolean computeSUID) {
+    private static ObjectStreamClass createClassDesc(Class<?> cl) {
 
         ObjectStreamClass result = new ObjectStreamClass();
 
+        boolean isArray = cl.isArray();
+        boolean serializable = isSerializable(cl);
+        boolean externalizable = isExternalizable(cl);
+
+        result.isSerializable = serializable;
+        result.isExternalizable = externalizable;
+
         // Now we fill in the values
         result.setName(cl.getName());
         result.setClass(cl);
@@ -208,45 +248,73 @@
         }
 
         Field[] declaredFields = null;
-        if (computeSUID) {
-            // Lazy computation, to save speed & space
-            declaredFields = cl.getDeclaredFields();
-            result.setSerialVersionUID((cl.isEnum() || (cl == Enum.class)) ? 0
-                    : computeSerialVersionUID(cl, declaredFields));
+
+        // Compute the SUID
+        if(serializable || externalizable) {
+            if (result.isEnum() || result.isProxy()) {
+                result.setSerialVersionUID(0L);
+            } else {
+                declaredFields = cl.getDeclaredFields();
+                result.setSerialVersionUID(computeSerialVersionUID(cl,
+                        declaredFields));
+            }
         }
 
-        boolean serializable = isSerializable(cl);
         // Serializables need field descriptors
-        if (serializable && !cl.isArray()) {
+        if (serializable && !isArray) {
             if (declaredFields == null) {
-
                 declaredFields = cl.getDeclaredFields();
             }
             result.buildFieldDescriptors(declaredFields);
         } else {
             // Externalizables or arrays do not need FieldDesc info
-            result.setFields(new ObjectStreamField[0]);
+            result.setFields(NO_FIELDS);
+        }
+
+        // Copy all fields to loadFields - they should be read by default in
+        // ObjectInputStream.defaultReadObject() method
+        ObjectStreamField[] fields = result.getFields();
+
+        if (fields != null) {
+            ObjectStreamField[] loadFields = new ObjectStreamField[fields.length];
+
+            for (int i = 0; i < fields.length; ++i) {
+                loadFields[i] = new ObjectStreamField(fields[i].getName(),
+                        fields[i].getType(), fields[i].isUnshared());
+
+                // resolve type string to init typeString field in
+                // ObjectStreamField
+                loadFields[i].getTypeString();
+            }
+            result.setLoadFields(loadFields);
         }
 
         byte flags = 0;
-        boolean externalizable = isExternalizable(cl);
         if (externalizable) {
             flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
+            flags |= ObjectStreamConstants.SC_BLOCK_DATA; // use protocol version 2 by default
         } else if (serializable) {
             flags |= ObjectStreamConstants.SC_SERIALIZABLE;
         }
-        if (getPrivateWriteObjectMethod(cl) != null) {
+        result.methodWriteReplace = findMethod(cl, "writeReplace"); //$NON-NLS-1$
+        result.methodReadResolve = findMethod(cl, "readResolve"); //$NON-NLS-1$
+        result.methodWriteObject = findPrivateMethod(cl, "writeObject", //$NON-NLS-1$
+                WRITE_PARAM_TYPES);
+        result.methodReadObject = findPrivateMethod(cl, "readObject", //$NON-NLS-1$
+                READ_PARAM_TYPES);
+        result.methodReadObjectNoData = findPrivateMethod(cl,
+                "readObjectNoData", EMPTY_CONSTRUCTOR_PARAM_TYPES); //$NON-NLS-1$
+        if (result.hasMethodWriteObject()) {
             flags |= ObjectStreamConstants.SC_WRITE_METHOD;
         }
         result.setFlags(flags);
-        classesAndDescriptors.put(cl, result);
 
         return result;
     }
 
     /**
      * Builds the collection of field descriptors for the receiver
-     * 
+     *
      * @param declaredFields
      *            collection of java.lang.reflect.Field for which to compute
      *            field descriptors
@@ -315,12 +383,12 @@
         }
         fields = _fields;
     }
-    
+
     /**
      * Compute and return the Serial Version UID of the class {@code cl}.
      * The value is computed based on the class name, superclass chain, field
      * names, method names, modifiers, etc.
-     * 
+     *
      * @param cl
      *            a java.lang.Class for which to compute the SUID
      * @param fields
@@ -477,7 +545,7 @@
                     /*
                      * write name, modifier & "descriptor" of all but private
                      * ones
-                     * 
+                     *
                      * constructor.getName() returns the constructor name as
                      * typed, not the VM name
                      */
@@ -534,7 +602,7 @@
     /**
      * Returns what the serializaton specification calls "descriptor" given a
      * field signature.
-     * 
+     *
      * @param signature
      *            a field signature
      * @return containing the descriptor
@@ -546,7 +614,7 @@
     /**
      * Return what the serializaton specification calls "descriptor" given a
      * method/constructor signature.
-     * 
+     *
      * @param signature
      *            a method or constructor signature
      * @return containing the descriptor
@@ -558,7 +626,7 @@
     /**
      * Return the java.lang.reflect.Field {@code serialPersistentFields}
      * if class {@code cl} implements it. Return null otherwise.
-     * 
+     *
      * @param cl
      *            a java.lang.Class which to test
      * @return {@code java.lang.reflect.Field} if the class has
@@ -583,10 +651,9 @@
 
     /**
      * Returns the class (java.lang.Class) for this descriptor.
-     * 
+     *
      * @return the class in the local VM that this descriptor represents;
      *         {@code null} if there is no corresponding class.
-     * @since Android 1.0
      */
     public Class<?> forClass() {
         if (resolvedClass != null) {
@@ -597,7 +664,7 @@
 
     /**
      * Return a String representing the signature for a Constructor {@code c}.
-     * 
+     *
      * @param c
      *            a java.lang.reflect.Constructor for which to compute the
      *            signature
@@ -608,12 +675,11 @@
     /**
      * Gets a field descriptor of the class represented by this class
      * descriptor.
-     * 
+     *
      * @param name
      *            the name of the desired field.
      * @return the field identified by {@code name} or {@code null} if there is
      *         no such field.
-     * @since Android 1.0
      */
     public ObjectStreamField getField(String name) {
         ObjectStreamField[] allFields = getFields();
@@ -629,20 +695,18 @@
     /**
      * Returns the collection of field descriptors for the fields of the
      * corresponding class
-     * 
+     *
      * @return the receiver's collection of declared fields for the class it
      *         represents
      */
     ObjectStreamField[] fields() {
         if (fields == null) {
-            synchronized(this){ 
-                Class<?> forCl = forClass();
-                if (forCl != null && isSerializable(forCl) && !forCl.isArray()) {
-                    buildFieldDescriptors(forCl.getDeclaredFields());
-                } else {
-                    // Externalizables or arrays do not need FieldDesc info
-                    setFields(new ObjectStreamField[0]);
-                }
+            Class<?> forCl = forClass();
+            if (forCl != null && isSerializable() && !forCl.isArray()) {
+                buildFieldDescriptors(forCl.getDeclaredFields());
+            } else {
+                // Externalizables or arrays do not need FieldDesc info
+                setFields(NO_FIELDS);
             }
         }
         return fields;
@@ -651,10 +715,9 @@
     /**
      * Returns a collection of field descriptors for the serialized fields of
      * the class represented by this class descriptor.
-     * 
+     *
      * @return an array of field descriptors or an array of length zero if there
      *         are no fields in this descriptor's class.
-     * @since Android 1.0
      */
     public ObjectStreamField[] getFields() {
         copyFieldAttributes();
@@ -662,9 +725,9 @@
     }
 
     /**
-     * If a Class uses "serialPersistentFields" to define the serialized fields, 
+     * If a Class uses "serialPersistentFields" to define the serialized fields,
      * this.loadFields cannot get the "unshared" information when deserializing
-     * fields using current implementation of ObjectInputStream. This method 
+     * fields using current implementation of ObjectInputStream. This method
      * provides a way to copy the "unshared" attribute from this.fields.
      *
      */
@@ -672,7 +735,7 @@
         if ((loadFields == null) || fields == null) {
             return;
         }
-        
+
         for (int i = 0; i < loadFields.length; i++) {
             ObjectStreamField loadField = loadFields[i];
             String name = loadField.getName();
@@ -690,7 +753,7 @@
     /**
      * Returns the collection of field descriptors for the input fields of the
      * corresponding class
-     * 
+     *
      * @return the receiver's collection of input fields for the class it
      *         represents
      */
@@ -700,7 +763,7 @@
 
     /**
      * Return a String representing the signature for a field {@code f}.
-     * 
+     *
      * @param f
      *            a java.lang.reflect.Field for which to compute the signature
      * @return the field's signature
@@ -709,11 +772,11 @@
 
     /**
      * Returns the flags for this descriptor, where possible combined values are
-     * 
+     *
      * ObjectStreamConstants.SC_WRITE_METHOD
      * ObjectStreamConstants.SC_SERIALIZABLE
      * ObjectStreamConstants.SC_EXTERNALIZABLE
-     * 
+     *
      * @return byte the receiver's flags for the class it represents
      */
     byte getFlags() {
@@ -722,7 +785,7 @@
 
     /**
      * Return a String representing the signature for a method {@code m}.
-     * 
+     *
      * @param m
      *            a java.lang.reflect.Method for which to compute the signature
      * @return the method's signature
@@ -731,9 +794,8 @@
 
     /**
      * Returns the name of the class represented by this descriptor.
-     * 
+     *
      * @return the fully qualified name of the class this descriptor represents.
-     * @since Android 1.0
      */
     public String getName() {
         return className;
@@ -742,9 +804,8 @@
     /**
      * Returns the Serial Version User ID of the class represented by this
      * descriptor.
-     * 
+     *
      * @return the SUID for the class represented by this descriptor.
-     * @since Android 1.0
      */
     public long getSerialVersionUID() {
         return svUID;
@@ -753,7 +814,7 @@
     /**
      * Returns the descriptor (ObjectStreamClass) of the superclass of the class
      * represented by the receiver.
-     * 
+     *
      * @return an ObjectStreamClass representing the superclass of the class
      *         represented by the receiver.
      */
@@ -767,7 +828,7 @@
      * compiler-generated, it is used by the serialization code to compute SUID.
      * This is unfortunate, since it may depend on compiler optimizations in
      * some cases.
-     * 
+     *
      * @param cl
      *            a java.lang.Class which to test
      * @return {@code true} if the class has <clinit> {@code false}
@@ -776,84 +837,15 @@
     private static native boolean hasClinit(Class<?> cl);
 
     /**
-     * Return true if the given class {@code cl} implements private
-     * method {@code readObject()}.
-     * 
-     * @param cl
-     *            a java.lang.Class which to test
-     * @return {@code true} if the class implements readObject
-     *         {@code false} if the class does not implement readObject
-     */
-    static Method getPrivateReadObjectMethod(Class<?> cl) {
-        try {
-            Method method = cl
-                    .getDeclaredMethod("readObject", READ_PARAM_TYPES); //$NON-NLS-1$
-            if (Modifier.isPrivate(method.getModifiers())
-                    && method.getReturnType() == VOID_CLASS) {
-                return method;
-            }
-        } catch (NoSuchMethodException nsm) {
-            // Ignored
-        }
-        return null;
-    }
-
-    /**
-     * Return true if the given class {@code cl} implements private
-     * method {@code readObject()}.
-     * 
-     * @param cl
-     *            a java.lang.Class which to test
-     * @return {@code true} if the class implements readObject
-     *         {@code false} if the class does not implement readObject
-     */
-    static Method getPrivateReadObjectNoDataMethod(Class<?> cl) {
-        try {
-            Method method = cl.getDeclaredMethod("readObjectNoData", //$NON-NLS-1$
-                    EMPTY_CONSTRUCTOR_PARAM_TYPES);
-            if (Modifier.isPrivate(method.getModifiers())
-                    && method.getReturnType() == VOID_CLASS) {
-                return method;
-            }
-        } catch (NoSuchMethodException nsm) {
-            // Ignored
-        }
-        return null;
-    }
-
-    /**
-     * Return true if the given class {@code cl} implements private
-     * method {@code writeObject()}.
-     * 
-     * @param cl
-     *            a java.lang.Class which to test
-     * @return {@code true} if the class implements writeObject
-     *         {@code false} if the class does not implement writeObject
-     */
-    static Method getPrivateWriteObjectMethod(Class<?> cl) {
-        try {
-            Method method = cl.getDeclaredMethod("writeObject", //$NON-NLS-1$
-                    WRITE_PARAM_TYPES);
-            if (Modifier.isPrivate(method.getModifiers())
-                    && method.getReturnType() == VOID_CLASS) {
-                return method;
-            }
-        } catch (NoSuchMethodException nsm) {
-            // Ignored
-        }
-        return null;
-    }
-
-    /**
      * Return true if instances of class {@code cl} are Externalizable,
      * false otherwise.
-     * 
+     *
      * @param cl
      *            a java.lang.Class which to test
      * @return {@code true} if instances of the class are Externalizable
      *         {@code false} if instances of the class are not
      *         Externalizable
-     * 
+     *
      * @see Object#hashCode
      */
     static boolean isExternalizable(Class<?> cl) {
@@ -865,7 +857,7 @@
      * <code>typecode<code> describes a primitive type
      *
      * @param typecode a char describing the typecode
-     * @return {@code true} if the typecode represents a primitive type 
+     * @return {@code true} if the typecode represents a primitive type
      * {@code false} if the typecode represents an Object type (including arrays)
      *
      * @see Object#hashCode
@@ -877,13 +869,13 @@
     /**
      * Return true if instances of class {@code cl} are Serializable,
      * false otherwise.
-     * 
+     *
      * @param cl
      *            a java.lang.Class which to test
      * @return {@code true} if instances of the class are Serializable
      *         {@code false} if instances of the class are not
      *         Serializable
-     * 
+     *
      * @see Object#hashCode
      */
     static boolean isSerializable(Class<?> cl) {
@@ -891,8 +883,65 @@
     }
 
     /**
+     * Resolves the class properties, if they weren't already
+     */
+    private void resolveProperties() {
+        if (arePropertiesResolved) {
+            return;
+        }
+
+        Class<?> cl = forClass();
+        isProxy = Proxy.isProxyClass(cl);
+        isEnum = Enum.class.isAssignableFrom(cl);
+        isSerializable = isSerializable(cl);
+        isExternalizable = isExternalizable(cl);
+
+        arePropertiesResolved = true;
+    }
+
+    /**
+     * Answers whether the class for this descriptor is serializable
+     *
+     * @return true if class implements Serializable
+     */
+    boolean isSerializable() {
+        resolveProperties();
+        return isSerializable;
+    }
+
+    /**
+     * Answers whether the class for this descriptor is serializable
+     *
+     * @return true if class implements Serializable
+     */
+    boolean isExternalizable() {
+        resolveProperties();
+        return isExternalizable;
+    }
+
+    /**
+     * Answers whether the class for this descriptor is proxied class
+     *
+     * @return true if class is proxied
+     */
+    boolean isProxy() {
+        resolveProperties();
+        return isProxy;
+    }
+
+    /**
+     * Answers whether the class for this descriptor is subclass of Enum
+     *
+     * @return true if class is subclass of Enum
+     */
+    boolean isEnum() {
+        resolveProperties();
+        return isEnum;
+    }
+
+    /**
      * Return a little endian long stored in a given position of the buffer
-     * 
+     *
      * @param buffer
      *            a byte array with the byte representation of the number
      * @param position
@@ -911,83 +960,67 @@
      * Returns the descriptor corresponding to the class {@code cl}. If the
      * class is not serializable or externalizable then {@code null} is
      * returned.
-     * 
+     *
      * @param cl
      *            a java.langClass for which to obtain the corresponding
      *            descriptor
      * @return the corresponding descriptor if the {@code cl} is serializable or
      *         externalizable; {@code null} otherwise.
-     * @since Android 1.0
      */
     public static ObjectStreamClass lookup(Class<?> cl) {
-        boolean serializable = isSerializable(cl);
-        boolean externalizable = isExternalizable(cl);
+        ObjectStreamClass osc = lookupStreamClass(cl);
 
-        // Has to be either Serializable or Externalizable
-        if (!serializable && !externalizable) {
-            return null;
+        if (osc.isSerializable() || osc.isExternalizable()) {
+            return osc;
         }
 
-        return lookupStreamClass(cl, true);
+        return null;
     }
 
     /**
      * Return the descriptor (ObjectStreamClass) corresponding to the class
      * {@code cl}. Returns an ObjectStreamClass even if instances of the
      * class cannot be serialized
-     * 
+     *
      * @param cl
      *            a java.langClass for which to obtain the corresponding
      *            descriptor
      * @return the corresponding descriptor
      */
     static ObjectStreamClass lookupStreamClass(Class<?> cl) {
-        return lookupStreamClass(cl, isSerializable(cl) || isExternalizable(cl));
-    }
 
-    /**
-     * Return the descriptor (ObjectStreamClass) corresponding to the class
-     * {@code cl}. Returns an ObjectStreamClass even if instances of the
-     * class cannot be serialized
-     * 
-     * @param cl
-     *            a {@code java.langClass} for which to obtain the
-     *            corresponding descriptor
-     * @param computeSUID
-     *            a boolean indicating if SUID should be computed or not.
-     * @return the corresponding descriptor
-     */
-    private static synchronized ObjectStreamClass lookupStreamClass(
-            Class<?> cl, boolean computeSUID) {
-        // Synchronized because of the lookup table 'classesAndDescriptors'
-        ObjectStreamClass cachedValue = classesAndDescriptors.get(cl);
-        if (cachedValue != null) {
-            return cachedValue;
+        WeakHashMap<Class<?>,ObjectStreamClass> tlc = OSCThreadLocalCache.oscWeakHashMap.get();
+
+        ObjectStreamClass cachedValue = tlc.get(cl);
+        if (cachedValue == null) {
+            cachedValue = createClassDesc(cl);
+            tlc.put(cl, cachedValue);
         }
-        return addToCache(cl, computeSUID);
+        return cachedValue;
+
     }
 
     /**
-     * Return the java.lang.reflect.Method {@code readResolve} if class
-     * {@code cl} implements it. Return null otherwise.
-     * 
+     * Return the java.lang.reflect.Method if class <code>cl</code> implements
+     * <code>methodName</code> . Return null otherwise.
+     *
      * @param cl
      *            a java.lang.Class which to test
-     * @return {@code java.lang.reflect.Method} if the class implements
-     *         readResolve {@code null} if the class does not implement
-     *         readResolve
+     * @return <code>java.lang.reflect.Method</code> if the class implements
+     *         writeReplace <code>null</code> if the class does not implement
+     *         writeReplace
      */
-    static Method methodReadResolve(Class<?> cl) {
+    static Method findMethod(Class<?> cl, String methodName) {
         Class<?> search = cl;
+        Method method = null;
         while (search != null) {
             try {
-                Method method = search.getDeclaredMethod(
-                        "readResolve", (Class[]) null); //$NON-NLS-1$
+                method = search.getDeclaredMethod(methodName, (Class[]) null);
                 if (search == cl
                         || (method.getModifiers() & Modifier.PRIVATE) == 0) {
+                    method.setAccessible(true);
                     return method;
                 }
-                return null;
             } catch (NoSuchMethodException nsm) {
             }
             search = search.getSuperclass();
@@ -996,37 +1029,81 @@
     }
 
     /**
-     * Return the java.lang.reflect.Method {@code writeReplace} if class
-     * {@code cl} implements it. Return null otherwise.
-     * 
+     * Return the java.lang.reflect.Method if class <code>cl</code> implements
+     * private <code>methodName</code> . Return null otherwise.
+     *
      * @param cl
      *            a java.lang.Class which to test
      * @return {@code java.lang.reflect.Method} if the class implements
      *         writeReplace {@code null} if the class does not implement
      *         writeReplace
      */
-    static Method methodWriteReplace(Class<?> cl) {
-        Class<?> search = cl;
-        while (search != null) {
-            try {
-                Method method = search.getDeclaredMethod(
-                        "writeReplace", (Class[]) null); //$NON-NLS-1$
-                if (search == cl
-                        || (method.getModifiers() & Modifier.PRIVATE) == 0) {
-                    return method;
-                }
-                return null;
-            } catch (NoSuchMethodException nsm) {
-                // Ignored
+    static Method findPrivateMethod(Class<?> cl, String methodName,
+            Class<?>[] param) {
+        try {
+            Method method = cl.getDeclaredMethod(methodName, param);
+            if (Modifier.isPrivate(method.getModifiers())
+                    && method.getReturnType() == VOID_CLASS) {
+                method.setAccessible(true);
+                return method;
             }
-            search = search.getSuperclass();
+        } catch (NoSuchMethodException nsm) {
+            // Ignored
         }
         return null;
     }
 
+    boolean hasMethodWriteReplace() {
+        return (methodWriteReplace != null);
+    }
+
+    Method getMethodWriteReplace() {
+        return methodWriteReplace;
+    }
+
+    boolean hasMethodReadResolve() {
+        return (methodReadResolve != null);
+    }
+
+    Method getMethodReadResolve() {
+        return methodReadResolve;
+    }
+
+    boolean hasMethodWriteObject() {
+        return (methodWriteObject != null);
+    }
+
+    Method getMethodWriteObject() {
+        return methodWriteObject;
+    }
+
+    boolean hasMethodReadObject() {
+        return (methodReadObject != null);
+    }
+
+    Method getMethodReadObject() {
+        return methodReadObject;
+    }
+
+    boolean hasMethodReadObjectNoData() {
+        return (methodReadObjectNoData != null);
+    }
+
+    Method getMethodReadObjectNoData() {
+        return methodReadObjectNoData;
+    }
+
+    void initPrivateFields(ObjectStreamClass desc) {
+        methodWriteReplace = desc.methodWriteReplace;
+        methodReadResolve = desc.methodReadResolve;
+        methodWriteObject = desc.methodWriteObject;
+        methodReadObject = desc.methodReadObject;
+        methodReadObjectNoData = desc.methodReadObjectNoData;
+    }
+
     /**
      * Set the class (java.lang.Class) that the receiver represents
-     * 
+     *
      * @param c
      *            aClass, the new class that the receiver describes
      */
@@ -1037,7 +1114,7 @@
     /**
      * Set the collection of field descriptors for the fields of the
      * corresponding class
-     * 
+     *
      * @param f
      *            ObjectStreamField[], the receiver's new collection of declared
      *            fields for the class it represents
@@ -1049,7 +1126,7 @@
     /**
      * Set the collection of field descriptors for the input fields of the
      * corresponding class
-     * 
+     *
      * @param f
      *            ObjectStreamField[], the receiver's new collection of input
      *            fields for the class it represents
@@ -1060,11 +1137,11 @@
 
     /**
      * Set the flags for this descriptor, where possible combined values are
-     * 
+     *
      * ObjectStreamConstants.SC_WRITE_METHOD
      * ObjectStreamConstants.SC_SERIALIZABLE
      * ObjectStreamConstants.SC_EXTERNALIZABLE
-     * 
+     *
      * @param b
      *            byte, the receiver's new flags for the class it represents
      */
@@ -1074,7 +1151,7 @@
 
     /**
      * Set the name of the class represented by the receiver
-     * 
+     *
      * @param newName
      *            a String, the new fully qualified name of the class the
      *            receiver represents
@@ -1085,7 +1162,7 @@
 
     /**
      * Set the Serial Version User ID of the class represented by the receiver
-     * 
+     *
      * @param l
      *            a long, the new SUID for the class represented by the receiver
      */
@@ -1096,7 +1173,7 @@
     /**
      * Set the descriptor for the superclass of the class described by the
      * receiver
-     * 
+     *
      * @param c
      *            an ObjectStreamClass, the new ObjectStreamClass for the
      *            superclass of the class represented by the receiver
@@ -1124,13 +1201,24 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * descriptor.
-     * 
+     *
      * @return a printable representation of this descriptor.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
         return getName() + ": static final long serialVersionUID =" //$NON-NLS-1$
                 + getSerialVersionUID() + "L;"; //$NON-NLS-1$
     }
+
+    static class OSCThreadLocalCache extends ThreadLocalCache {
+
+        // thread-local cache for ObjectStreamClass.lookup
+        public static ThreadLocalCache<WeakHashMap<Class<?>,ObjectStreamClass>> oscWeakHashMap = new ThreadLocalCache<WeakHashMap<Class<?>,ObjectStreamClass>>() {
+            protected WeakHashMap<Class<?>,ObjectStreamClass> initialValue() {
+                return new WeakHashMap<Class<?>,ObjectStreamClass>();
+            }
+        };
+
+    }
+
 }
diff --git a/luni/src/main/java/java/io/ObjectStreamConstants.java b/luni/src/main/java/java/io/ObjectStreamConstants.java
index 8f7ad66..01b0109 100644
--- a/luni/src/main/java/java/io/ObjectStreamConstants.java
+++ b/luni/src/main/java/java/io/ObjectStreamConstants.java
@@ -19,168 +19,122 @@
 
 /**
  * A helper interface with constants used by the serialization implementation.
- * 
- * @since Android 1.0
  */
 public abstract interface ObjectStreamConstants {
 
     /**
      * The stream header's magic number.
-     * 
-     * @since Android 1.0
      */
     public static final short STREAM_MAGIC = (short) 0xaced;
 
     /**
      * The stream header's version number.
-     * 
-     * @since Android 1.0
      */
     public static final short STREAM_VERSION = 5;
 
     // These are tags to indicate the stream contents
-    
+
     /**
      * The minimum tag value.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_BASE = 0x70;
 
     /**
      * Tag to mark a {@code null} object reference.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_NULL = (byte) 0x70;
 
     /**
      * Tag to mark a reference to an object that has already been written to the
      * stream.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_REFERENCE = (byte) 0x71;
 
     /**
      * Tag to mark a new class descriptor.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_CLASSDESC = (byte) 0x72;
 
     /**
      * Tag to mark a new object.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_OBJECT = (byte) 0x73;
 
     /**
      * Tag to mark a new string.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_STRING = (byte) 0x74;
 
     /**
      * Tag to mark a new array.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_ARRAY = (byte) 0x75;
 
     /**
      * Tag to mark a reference to a class.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_CLASS = (byte) 0x76;
 
     /**
      * Tag to mark a block of optional data. The byte following this tag
      * indicates the size of the block.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_BLOCKDATA = (byte) 0x77;
 
     /**
      * Tag to mark the end of block data blocks for an object.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_ENDBLOCKDATA = (byte) 0x78;
 
     /**
      * Tag to mark a stream reset.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_RESET = (byte) 0x79;
 
     /**
      * Tag to mark a long block of data. The long following this tag
      * indicates the size of the block.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_BLOCKDATALONG = (byte) 0x7A;
 
     /**
      * Tag to mark an exception.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_EXCEPTION = (byte) 0x7B;
 
     /**
      * Tag to mark a long string.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_LONGSTRING = (byte) 0x7C;
 
     /**
      * Tag to mark a new proxy class descriptor.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_PROXYCLASSDESC = (byte) 0x7D;
 
     /**
      * The maximum tag value.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_MAX = 0x7E;
 
     /**
      * Handle for the first object that gets serialized.
-     * 
-     * @since Android 1.0
      */
     public static final int baseWireHandle = 0x007e0000;
 
     /**
      * Stream protocol version 1.
-     * 
-     * @since Android 1.0
      */
     public static final int PROTOCOL_VERSION_1 = 1;
 
     /**
      * Stream protocol version 2.
-     * 
-     * @since Android 1.0
      */
     public static final int PROTOCOL_VERSION_2 = 2;
 
     /**
      * Permission constant to enable subclassing of ObjectInputStream and
      * ObjectOutputStream.
-     * 
-     * @since Android 1.0
      */
     public static final SerializablePermission SUBCLASS_IMPLEMENTATION_PERMISSION = new SerializablePermission(
             "enableSubclassImplementation"); //$NON-NLS-1$
@@ -188,8 +142,6 @@
     /**
      * Permission constant to enable object substitution during serialization
      * and deserialization.
-     * 
-     * @since Android 1.0
      */
     public static final SerializablePermission SUBSTITUTION_PERMISSION = new SerializablePermission(
             "enableSubstitution"); //$NON-NLS-1$
@@ -199,47 +151,35 @@
     /**
      * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates
      * that a serializable class has its own {@code writeObject} method.
-     * 
-     * @since Android 1.0
      */
     public static final byte SC_WRITE_METHOD = 0x01; // If SC_SERIALIZABLE
 
     /**
      * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates
      * that a class is serializable.
-     * 
-     * @since Android 1.0
      */
     public static final byte SC_SERIALIZABLE = 0x02;
 
     /**
      * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates
      * that a class is externalizable.
-     * 
-     * @since Android 1.0
      */
     public static final byte SC_EXTERNALIZABLE = 0x04;
 
     /**
      * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates
      * that an externalizable class is written in block data mode.
-     * 
-     * @since Android 1.0
      */
     public static final byte SC_BLOCK_DATA = 0x08; // If SC_EXTERNALIZABLE
 
     /**
      * Tag to mark a new enum.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_ENUM = 0x7E;
 
     /**
      * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates
      * that a class is an enum type.
-     * 
-     * @since Android 1.0
      */
     public static final byte SC_ENUM = 0x10;
 }
diff --git a/luni/src/main/java/java/io/ObjectStreamException.java b/luni/src/main/java/java/io/ObjectStreamException.java
index a06b102..c3ad7dc 100644
--- a/luni/src/main/java/java/io/ObjectStreamException.java
+++ b/luni/src/main/java/java/io/ObjectStreamException.java
@@ -28,8 +28,6 @@
  * @see OptionalDataException
  * @see StreamCorruptedException
  * @see WriteAbortedException
- * 
- * @since Android 1.0
  */
 public abstract class ObjectStreamException extends IOException {
 
@@ -38,8 +36,6 @@
     /**
      * Constructs a new {@code ObjectStreamException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     protected ObjectStreamException() {
         super();
@@ -51,7 +47,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     protected ObjectStreamException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/ObjectStreamField.java b/luni/src/main/java/java/io/ObjectStreamField.java
index 95deb7b..3baebf7 100644
--- a/luni/src/main/java/java/io/ObjectStreamField.java
+++ b/luni/src/main/java/java/io/ObjectStreamField.java
@@ -17,22 +17,32 @@
 
 package java.io;
 
+// BEGIN android-note
+// Harmony uses ObjectAccessors to access fields through JNI. Android has not
+// yet migrated that API.
+// END android-note
+
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
 import java.util.Comparator;
 
+// BEGIN android-removed
+// import org.apache.harmony.misc.accessors.ObjectAccessor;
+// END android-removed
+
 /**
  * Describes a field for the purpose of serialization. Classes can define the
  * collection of fields that are serialized, which may be different from the set
  * of all declared fields.
- * 
+ *
  * @see ObjectOutputStream#writeFields()
  * @see ObjectInputStream#readFields()
- * 
- * @since Android 1.0
  */
 public class ObjectStreamField implements Comparable<Object> {
 
+    static final int FIELD_IS_NOT_RESOLVED = -1;
+    static final int FIELD_IS_ABSENT = -2;
+
     // Declared name of the field
     private String name;
 
@@ -49,16 +59,32 @@
 
     private boolean isDeserialized;
 
+    private long assocFieldID = FIELD_IS_NOT_RESOLVED;
+
+    // BEGIN android-removed
+    // long getFieldID(ObjectAccessor accessor, Class<?> declaringClass) {
+    //     if (assocFieldID != FIELD_IS_NOT_RESOLVED) {
+    //         return assocFieldID;
+    //     } else {
+    //         try {
+    //             assocFieldID = accessor.getFieldID(declaringClass, name);
+    //         } catch(NoSuchFieldError e) {
+    //             assocFieldID = FIELD_IS_ABSENT;
+    //         }
+    //         return assocFieldID;
+    //     }
+    // }
+    // END android-removed
+
     /**
      * Constructs an ObjectStreamField with the specified name and type.
-     * 
+     *
      * @param name
      *            the name of the field.
      * @param cl
      *            the type of the field.
      * @throws NullPointerException
      *             if {@code name} or {@code cl} is {@code null}.
-     * @since Android 1.0
      */
     public ObjectStreamField(String name, Class<?> cl) {
         if (name == null || cl == null) {
@@ -71,7 +97,7 @@
     /**
      * Constructs an ObjectStreamField with the specified name, type and the
      * indication if it is unshared.
-     * 
+     *
      * @param name
      *            the name of the field.
      * @param cl
@@ -82,7 +108,6 @@
      * @throws NullPointerException
      *             if {@code name} or {@code cl} is {@code null}.
      * @see ObjectOutputStream#writeUnshared(Object)
-     * @since Android 1.0
      */
     public ObjectStreamField(String name, Class<?> cl, boolean unshared) {
         if (name == null || cl == null) {
@@ -97,7 +122,7 @@
     /**
      * Constructs an ObjectStreamField with the given name and the given type.
      * The type may be null.
-     * 
+     *
      * @param signature
      *            A String representing the type of the field
      * @param name
@@ -117,13 +142,12 @@
      * of the compared fields has a primitive type and the other one not. If so,
      * the field with the primitive type is considered to be "smaller". If both
      * fields are equal, their names are compared.
-     * 
+     *
      * @param o
      *            the object to compare with.
      * @return -1 if this field is "smaller" than field {@code o}, 0 if both
      *         fields are equal; 1 if this field is "greater" than field {@code
      *         o}.
-     * @since Android 1.0
      */
     public int compareTo(Object o) {
         ObjectStreamField f = (ObjectStreamField) o;
@@ -139,34 +163,14 @@
         // Either both primitives or both not primitives. Compare based on name.
         return this.getName().compareTo(f.getName());
     }
-    
+
     // BEGIN android-removed
     // There shouldn't be an implementation of these methods.
-    // /**
-    //  * Indicates if this field descriptor is equal to {@code arg0}. Field
-    //  * descriptors are equal if their name is equal.
-    //  * 
-    //  * @param arg0
-    //  *            the object to check equality with.
-    //  * @return {@code true} if the name of this field descriptor is equal to the
-    //  *         name of {@code arg0}, {@code false} otherwise.
-    //  * @since Android 1.0
-    //  */
     // @Override
     // public boolean equals(Object arg0) {
-    //     // BEGIN android-changed
-    //     // copied from newer harmony version
-    //     return (arg0 instanceof ObjectStreamField) && compareTo(arg0) == 0;
-    //     // END android-changed
+    //     return (arg0 instanceof ObjectStreamField) && (compareTo(arg0) == 0);
     // }
-    // 
-    // /**
-    //  * Returns a hash code for this field descriptor. The hash code of this
-    //  * field's name is returned.
-    //  * 
-    //  * @return the field's hash code.
-    //  * @since Android 1.0
-    //  */
+    //
     // @Override
     // public int hashCode() {
     //     return getName().hashCode();
@@ -175,9 +179,8 @@
 
     /**
      * Gets the name of this field.
-     * 
+     *
      * @return the field's name.
-     * @since Android 1.0
      */
     public String getName() {
         return name;
@@ -185,9 +188,8 @@
 
     /**
      * Gets the offset of this field in the object.
-     * 
+     *
      * @return this field's offset.
-     * @since Android 1.0
      */
     public int getOffset() {
         return offset;
@@ -196,7 +198,7 @@
     /**
      * Return the type of the field the receiver represents, this is an internal
      * method
-     * 
+     *
      * @return A Class object representing the type of the field
      */
     // BEGIN android-note
@@ -211,9 +213,8 @@
 
     /**
      * Gets the type of this field.
-     * 
+     *
      * @return a {@code Class} object representing the type of the field.
-     * @since Android 1.0
      */
     public Class<?> getType() {
         Class<?> cl = getTypeInternal();
@@ -226,7 +227,7 @@
     /**
      * Gets a character code for the type of this field. The following codes are
      * used:
-     * 
+     *
      * <pre>
      * B     byte
      * C     char
@@ -239,9 +240,8 @@
      * Z     boolean
      * [     array
      * </pre>
-     * 
+     *
      * @return the field's type code.
-     * @since Android 1.0
      */
     public char getTypeCode() {
         Class<?> t = getTypeInternal();
@@ -278,10 +278,9 @@
     /**
      * Gets the type signature used by the VM to represent the type of this
      * field.
-     * 
+     *
      * @return the signature of this field's class or {@code null} if this
      *         field's type is primitive.
-     * @since Android 1.0
      */
     public String getTypeString() {
         if (isPrimitive()) {
@@ -298,10 +297,9 @@
 
     /**
      * Indicates whether this field's type is a primitive type.
-     * 
+     *
      * @return {@code true} if this field's type is primitive; {@code false} if
      *         the type of this field is a regular class.
-     * @since Android 1.0
      */
     public boolean isPrimitive() {
         Class<?> t = getTypeInternal();
@@ -310,10 +308,9 @@
 
     /**
      * Sets this field's offset in the object.
-     * 
+     *
      * @param newValue
      *            the field's new offset.
-     * @since Android 1.0
      */
     protected void setOffset(int newValue) {
         this.offset = newValue;
@@ -322,9 +319,8 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * field descriptor.
-     * 
+     *
      * @return a printable representation of this descriptor.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -335,7 +331,7 @@
     /**
      * Sorts the fields for dumping. Primitive types come first, then regular
      * types.
-     * 
+     *
      * @param fields
      *            ObjectStreamField[] fields to be sorted
      */
@@ -396,9 +392,8 @@
 
     /**
      * Indicats whether this field is unshared.
-     * 
+     *
      * @return {@code true} if this field is unshared, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isUnshared() {
         return unshared;
diff --git a/luni/src/main/java/java/io/OptionalDataException.java b/luni/src/main/java/java/io/OptionalDataException.java
index 891bfdd..39d3d5d 100644
--- a/luni/src/main/java/java/io/OptionalDataException.java
+++ b/luni/src/main/java/java/io/OptionalDataException.java
@@ -25,8 +25,6 @@
  * @see ObjectInputStream#available()
  * @see ObjectInputStream#readObject()
  * @see ObjectInputStream#skipBytes(int)
- * 
- * @since Android 1.0
  */
 public class OptionalDataException extends ObjectStreamException {
 
@@ -34,24 +32,18 @@
 
     /**
      * {@code true} indicates that there is no more primitive data available.
-     * 
-     * @since Android 1.0
      */
     public boolean eof;
 
     /**
      * The number of bytes of primitive data (int, char, long etc.) that are
      * available.
-     * 
-     * @since Android 1.0
      */
     public int length;
 
     /**
      * Constructs a new {@code OptionalDataException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     OptionalDataException() {
         super();
@@ -63,7 +55,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     OptionalDataException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/OutputStream.java b/luni/src/main/java/java/io/OutputStream.java
index 5531ab5..2172411 100644
--- a/luni/src/main/java/java/io/OutputStream.java
+++ b/luni/src/main/java/java/io/OutputStream.java
@@ -32,17 +32,13 @@
  * <p>
  * Many specialized output streams for purposes like writing to a file already
  * exist in this package.
- * 
+ *
  * @see InputStream
- * 
- * @since Android 1.0
  */
 public abstract class OutputStream implements Closeable, Flushable {
 
     /**
      * Default constructor.
-     * 
-     * @since Android 1.0
      */
     public OutputStream() {
         super();
@@ -51,10 +47,9 @@
     /**
      * Closes this stream. Implementations of this method should free any
      * resources used by the stream. This implementation does nothing.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     public void close() throws IOException {
         /* empty */
@@ -63,10 +58,9 @@
     /**
      * Flushes this stream. Implementations of this method should ensure that
      * any buffered data is written out. This implementation does nothing.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while flushing this stream.
-     * @since Android 1.0
      */
     public void flush() throws IOException {
         /* empty */
@@ -75,12 +69,11 @@
     /**
      * Writes the entire contents of the byte array {@code buffer} to this
      * stream.
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @throws IOException
      *             if an error occurs while writing to this stream.
-     * @since Android 1.0
      */
     public void write(byte[] buffer) throws IOException {
         // BEGIN android-note
@@ -92,7 +85,7 @@
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * position {@code offset} to this stream.
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @param offset
@@ -106,7 +99,6 @@
      *             if {@code offset < 0} or {@code count < 0}, or if
      *             {@code offset + count} is bigger than the length of
      *             {@code buffer}.
-     * @since Android 1.0
      */
     public void write(byte[] buffer, int offset, int count) throws IOException {
         // BEGIN android-note
@@ -134,12 +126,11 @@
     /**
      * Writes a single byte to this stream. Only the least significant byte of
      * the integer {@code oneByte} is written to the stream.
-     * 
+     *
      * @param oneByte
      *            the byte to be written.
      * @throws IOException
      *             if an error occurs while writing to this stream.
-     * @since Android 1.0
      */
     public abstract void write(int oneByte) throws IOException;
 }
diff --git a/luni/src/main/java/java/io/OutputStreamWriter.java b/luni/src/main/java/java/io/OutputStreamWriter.java
index d6cc91e..6e6cc50 100644
--- a/luni/src/main/java/java/io/OutputStreamWriter.java
+++ b/luni/src/main/java/java/io/OutputStreamWriter.java
@@ -25,6 +25,7 @@
 import java.nio.charset.CodingErrorAction;
 import java.security.AccessController;
 
+import org.apache.harmony.luni.util.HistoricalNamesUtil;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 
@@ -35,10 +36,8 @@
  * "file.encoding" system property. {@code OutputStreamWriter} contains a buffer
  * of bytes to be written to target stream and converts these into characters as
  * needed. The buffer size is 8K.
- * 
+ *
  * @see InputStreamReader
- * 
- * @since Android 1.0
  */
 public class OutputStreamWriter extends Writer {
 
@@ -52,10 +51,9 @@
      * Constructs a new OutputStreamWriter using {@code out} as the target
      * stream to write converted characters to. The default character encoding
      * is used.
-     * 
+     *
      * @param out
      *            the non-null target stream to write converted bytes to.
-     * @since Android 1.0
      */
     public OutputStreamWriter(OutputStream out) {
         super(out);
@@ -73,7 +71,7 @@
      * stream to write converted characters to and {@code enc} as the character
      * encoding. If the encoding cannot be found, an
      * UnsupportedEncodingException error is thrown.
-     * 
+     *
      * @param out
      *            the target stream to write converted bytes to.
      * @param enc
@@ -82,7 +80,6 @@
      *             if {@code enc} is {@code null}.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code enc} cannot be found.
-     * @since Android 1.0
      */
     public OutputStreamWriter(OutputStream out, final String enc)
             throws UnsupportedEncodingException {
@@ -104,12 +101,11 @@
      * Constructs a new OutputStreamWriter using {@code out} as the target
      * stream to write converted characters to and {@code cs} as the character
      * encoding.
-     * 
+     *
      * @param out
      *            the target stream to write converted bytes to.
      * @param cs
      *            the {@code Charset} that specifies the character encoding.
-     * @since Android 1.0
      */
     public OutputStreamWriter(OutputStream out, Charset cs) {
         super(out);
@@ -123,12 +119,11 @@
      * Constructs a new OutputStreamWriter using {@code out} as the target
      * stream to write converted characters to and {@code enc} as the character
      * encoder.
-     * 
+     *
      * @param out
      *            the target stream to write converted bytes to.
      * @param enc
      *            the character encoder used for character conversion.
-     * @since Android 1.0
      */
     public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
         super(out);
@@ -144,11 +139,9 @@
      * <p>
      * Only the first invocation of this method has any effect. Subsequent calls
      * do nothing.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this writer.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -168,10 +161,9 @@
      * Flushes this writer. This implementation ensures that all buffered bytes
      * are written to the target stream. After writing the bytes, the target
      * stream is flushed as well.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while flushing this writer.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -197,17 +189,15 @@
     /**
      * Gets the name of the encoding that is used to convert characters to
      * bytes.
-     * 
+     *
      * @return the string describing the converter or {@code null} if this
      *         writer is closed.
-     * @since Android 1.0
      */
     public String getEncoding() {
         if (encoder == null) {
             return null;
         }
-        return InputStreamReader.HistoricalNamesUtil.getHistoricalName(encoder
-                .charset().name());
+        return HistoricalNamesUtil.getHistoricalName(encoder.charset().name());
     }
 
     /**
@@ -215,7 +205,7 @@
      * to this writer. The characters are immediately converted to bytes by the
      * character converter and stored in a local buffer. If the buffer gets full
      * as a result of the conversion, this writer is flushed.
-     * 
+     *
      * @param buf
      *            the array containing characters to write.
      * @param offset
@@ -229,7 +219,6 @@
      * @throws IOException
      *             if this writer has already been closed or another I/O error
      *             occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] buf, int offset, int count) throws IOException {
@@ -273,12 +262,11 @@
      * of the integer {@code oneChar} are immediately converted to bytes by the
      * character converter and stored in a local buffer. If the buffer gets full
      * by converting this character, this writer is flushed.
-     * 
+     *
      * @param oneChar
      *            the character to write.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) throws IOException {
@@ -294,7 +282,7 @@
      * to this writer. The characters are immediately converted to bytes by the
      * character converter and stored in a local buffer. If the buffer gets full
      * as a result of the conversion, this writer is flushed.
-     * 
+     *
      * @param str
      *            the string containing characters to write.
      * @param offset
@@ -308,7 +296,6 @@
      *             if {@code offset < 0} or {@code count < 0}, or if
      *             {@code offset + count} is bigger than the length of
      *             {@code str}.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int count) throws IOException {
diff --git a/luni/src/main/java/java/io/PipedInputStream.java b/luni/src/main/java/java/io/PipedInputStream.java
index 5562c58..d06143d 100644
--- a/luni/src/main/java/java/io/PipedInputStream.java
+++ b/luni/src/main/java/java/io/PipedInputStream.java
@@ -23,10 +23,8 @@
  * Receives information from a communications pipe. When two threads want to
  * pass data back and forth, one creates a piped output stream and the other one
  * creates a piped input stream.
- * 
+ *
  * @see PipedOutputStream
- * 
- * @since Android 1.0
  */
 public class PipedInputStream extends InputStream {
 
@@ -36,29 +34,21 @@
 
     /**
      * The circular buffer through which data is passed.
-     * 
-     * @since Android 1.0
      */
     protected byte buffer[];
 
     /**
      * The index in {@code buffer} where the next byte will be written.
-     * 
-     * @since Android 1.0
      */
     protected int in = -1;
 
     /**
      * The index in {@code buffer} where the next byte will be read.
-     * 
-     * @since Android 1.0
      */
     protected int out = 0;
 
     /**
      * The size of the default pipe in bytes.
-     * 
-     * @since Android 1.0
      */
     protected static final int PIPE_SIZE = 1024;
 
@@ -71,8 +61,6 @@
      * Constructs a new unconnected {@code PipedInputStream}. The resulting
      * stream must be connected to a {@link PipedOutputStream} before data may
      * be read from it.
-     * 
-     * @since Android 1.0
      */
     public PipedInputStream() {
         /* empty */
@@ -82,12 +70,11 @@
      * Constructs a new {@code PipedInputStream} connected to the
      * {@link PipedOutputStream} {@code out}. Any data written to the output
      * stream can be read from the this input stream.
-     * 
+     *
      * @param out
      *            the piped output stream to connect to.
      * @throws IOException
      *             if this stream or {@code out} are already connected.
-     * @since Android 1.0
      */
     public PipedInputStream(PipedOutputStream out) throws IOException {
         connect(out);
@@ -97,11 +84,10 @@
      * Returns the number of bytes that are available before this stream will
      * block. This implementation returns the number of bytes written to this
      * pipe that have not been read yet.
-     * 
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if an error occurs in this stream.
-     * @since Android 1.0
      */
     @Override
     public synchronized int available() throws IOException {
@@ -114,10 +100,9 @@
     /**
      * Closes this stream. This implementation releases the buffer used for the
      * pipe and notifies all threads waiting to read or write.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -134,12 +119,11 @@
      * Connects this {@code PipedInputStream} to a {@link PipedOutputStream}.
      * Any data written to the output stream becomes readable in this input
      * stream.
-     * 
+     *
      * @param src
      *            the source output stream.
      * @throws IOException
      *             if either stream is already connected.
-     * @since Android 1.0
      */
     public void connect(PipedOutputStream src) throws IOException {
         src.connect(this);
@@ -155,15 +139,13 @@
      * Separate threads should be used to read from a {@code PipedInputStream}
      * and to write to the connected {@link PipedOutputStream}. If the same
      * thread is used, a deadlock may occur.
-     * </p>
-     * 
+     *
      * @return the byte read or -1 if the end of the source stream has been
      *         reached.
      * @throws IOException
      *             if this stream is closed or not connected to an output
      *             stream, or if the thread writing to the connected output
      *             stream is no longer alive.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read() throws IOException {
@@ -180,16 +162,15 @@
          */
         lastReader = Thread.currentThread();
         try {
-            boolean first = true;
+            int attempts = 3;
             while (in == -1) {
                 // Are we at end of stream?
                 if (isClosed) {
                     return -1;
                 }
-                if (!first && lastWriter != null && !lastWriter.isAlive()) {
+                if ((attempts-- <= 0) && lastWriter != null && !lastWriter.isAlive()) {
                     throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
                 }
-                first = false;
                 // Notify callers of receive()
                 notifyAll();
                 wait(1000);
@@ -219,8 +200,7 @@
      * Separate threads should be used to read from a {@code PipedInputStream}
      * and to write to the connected {@link PipedOutputStream}. If the same
      * thread is used, a deadlock may occur.
-     * </p>
-     * 
+     *
      * @param bytes
      *            the array in which to store the bytes read.
      * @param offset
@@ -278,16 +258,15 @@
          */
         lastReader = Thread.currentThread();
         try {
-            boolean first = true;
+            int attempts = 3;
             while (in == -1) {
                 // Are we at end of stream?
                 if (isClosed) {
                     return -1;
                 }
-                if (!first && lastWriter != null && !lastWriter.isAlive()) {
+                if ((attempts-- <= 0) && lastWriter != null && !lastWriter.isAlive()) {
                     throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
                 }
-                first = false;
                 // Notify callers of receive()
                 notifyAll();
                 wait(1000);
@@ -342,8 +321,7 @@
      * {@code in} in the {@code buffer}.
      * <p>
      * This method blocks as long as {@code buffer} is full.
-     * </p>
-     * 
+     *
      * @param oneByte
      *            the byte to store in this pipe.
      * @throws InterruptedIOException
diff --git a/luni/src/main/java/java/io/PipedOutputStream.java b/luni/src/main/java/java/io/PipedOutputStream.java
index 3041f70..15ee930 100644
--- a/luni/src/main/java/java/io/PipedOutputStream.java
+++ b/luni/src/main/java/java/io/PipedOutputStream.java
@@ -23,10 +23,8 @@
  * Places information on a communications pipe. When two threads want to pass
  * data back and forth, one creates a piped output stream and the other one
  * creates a piped input stream.
- * 
+ *
  * @see PipedInputStream
- * 
- * @since Android 1.0
  */
 public class PipedOutputStream extends OutputStream {
 
@@ -39,8 +37,6 @@
      * Constructs a new unconnected {@code PipedOutputStream}. The resulting
      * stream must be connected to a {@link PipedInputStream} before data can be
      * written to it.
-     * 
-     * @since Android 1.0
      */
     public PipedOutputStream() {
         super();
@@ -50,12 +46,11 @@
      * Constructs a new {@code PipedOutputStream} connected to the
      * {@link PipedInputStream} {@code dest}. Any data written to this stream
      * can be read from the target stream.
-     * 
+     *
      * @param dest
      *            the piped input stream to connect to.
      * @throws IOException
      *             if this stream or {@code dest} are already connected.
-     * @since Android 1.0
      */
     public PipedOutputStream(PipedInputStream dest) throws IOException {
         super();
@@ -65,10 +60,9 @@
     /**
      * Closes this stream. If this stream is connected to an input stream, the
      * input stream is closed and the pipe is disconnected.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -82,12 +76,11 @@
     /**
      * Connects this stream to a {@link PipedInputStream}. Any data written to
      * this output stream becomes readable in the input stream.
-     * 
+     *
      * @param stream
      *            the destination input stream.
      * @throws IOException
      *             if either stream is already connected.
-     * @since Android 1.0
      */
     public void connect(PipedInputStream stream) throws IOException {
         if (null == stream) {
@@ -109,10 +102,9 @@
     /**
      * Notifies the readers of this {@link PipedInputStream} that bytes can be
      * read. This method does nothing if this stream is not connected.
-     * 
+     *
      * @throws IOException
      *             if an I/O error occurs while flushing this stream.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -131,8 +123,7 @@
      * Separate threads should be used to write to a {@code PipedOutputStream}
      * and to read from the connected {@link PipedInputStream}. If the same
      * thread is used, a deadlock may occur.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -151,7 +142,6 @@
      *             if this stream is not connected, if the target stream is
      *             closed or if the thread reading from the target stream is no
      *             longer alive. This case is currently not handled correctly.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int count) throws IOException {
@@ -173,8 +163,7 @@
      * Separate threads should be used to write to a {@code PipedOutputStream}
      * and to read from the connected {@link PipedInputStream}. If the same
      * thread is used, a deadlock may occur.
-     * </p>
-     * 
+     *
      * @param oneByte
      *            the byte to write.
      * @throws InterruptedIOException
@@ -185,7 +174,6 @@
      *             if this stream is not connected, if the target stream is
      *             closed or if the thread reading from the target stream is no
      *             longer alive. This case is currently not handled correctly.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneByte) throws IOException {
diff --git a/luni/src/main/java/java/io/PipedReader.java b/luni/src/main/java/java/io/PipedReader.java
index a0af9a5..251ac90 100644
--- a/luni/src/main/java/java/io/PipedReader.java
+++ b/luni/src/main/java/java/io/PipedReader.java
@@ -23,10 +23,8 @@
  * Receives information on a communications pipe. When two threads want to pass
  * data back and forth, one creates a piped writer and the other creates a piped
  * reader.
- * 
+ *
  * @see PipedWriter
- * 
- * @since Android 1.0
  */
 public class PipedReader extends Reader {
 
@@ -66,9 +64,8 @@
      * Constructs a new unconnected {@code PipedReader}. The resulting reader
      * must be connected to a {@code PipedWriter} before data may be read from
      * it.
-     * 
+     *
      * @see PipedWriter
-     * @since Android 1.0
      */
     public PipedReader() {
         data = new char[PIPE_SIZE];
@@ -78,12 +75,11 @@
      * Constructs a new {@code PipedReader} connected to the {@link PipedWriter}
      * {@code out}. Any data written to the writer can be read from the this
      * reader.
-     * 
+     *
      * @param out
      *            the {@code PipedWriter} to connect to.
      * @throws IOException
      *             if {@code out} is already connected.
-     * @since Android 1.0
      */
     public PipedReader(PipedWriter out) throws IOException {
         this();
@@ -93,10 +89,9 @@
     /**
      * Closes this reader. This implementation releases the buffer used for
      * the pipe and notifies all threads waiting to read or write.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this reader.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -112,13 +107,12 @@
     /**
      * Connects this {@code PipedReader} to a {@link PipedWriter}. Any data
      * written to the writer becomes readable in this reader.
-     * 
+     *
      * @param src
      *            the writer to connect to.
      * @throws IOException
      *             if this reader is closed or already connected, or if {@code
      *             src} is already connected.
-     * @since Android 1.0
      */
     public void connect(PipedWriter src) throws IOException {
         synchronized (lock) {
@@ -128,7 +122,7 @@
 
     /**
      * Establishes the connection to the PipedWriter.
-     * 
+     *
      * @throws IOException
      *             If this Reader is already connected.
      */
@@ -154,13 +148,11 @@
      * Separate threads should be used to read from a {@code PipedReader} and to
      * write to the connected {@link PipedWriter}. If the same thread is used,
      * a deadlock may occur.
-     * </p>
-     * 
+     *
      * @return the character read or -1 if the end of the reader has been
      *         reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -179,8 +171,7 @@
      * Separate threads should be used to read from a {@code PipedReader} and to
      * write to the connected {@link PipedWriter}. If the same thread is used, a
      * deadlock may occur.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the character array in which to store the characters read.
      * @param offset
@@ -298,14 +289,13 @@
      * called, {@code false} if unknown or blocking will occur. This
      * implementation returns {@code true} if the internal buffer contains
      * characters that can be read.
-     * 
+     *
      * @return always {@code false}.
      * @throws IOException
      *             if this reader is closed or not connected, or if some other
      *             I/O error occurs.
      * @see #read()
      * @see #read(char[], int, int)
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -326,10 +316,10 @@
      * <P>
      * If the buffer is full and the thread sending #receive is interrupted, the
      * InterruptedIOException will be thrown.
-     * 
+     *
      * @param oneChar
      *            the char to store into the pipe.
-     * 
+     *
      * @throws IOException
      *             If the stream is already closed or another IOException
      *             occurs.
@@ -380,14 +370,14 @@
      * <P>
      * If the buffer is full and the thread sending #receive is interrupted, the
      * InterruptedIOException will be thrown.
-     * 
+     *
      * @param chars
      *            the char array to store into the pipe.
      * @param offset
      *            offset to start reading from
      * @param count
      *            total characters to read
-     * 
+     *
      * @throws IOException
      *             If the stream is already closed or another IOException
      *             occurs.
diff --git a/luni/src/main/java/java/io/PipedWriter.java b/luni/src/main/java/java/io/PipedWriter.java
index 98a73c9..5fc968d 100644
--- a/luni/src/main/java/java/io/PipedWriter.java
+++ b/luni/src/main/java/java/io/PipedWriter.java
@@ -23,10 +23,8 @@
  * Places information on a communications pipe. When two threads want to pass
  * data back and forth, one creates a piped writer and the other creates a piped
  * reader.
- * 
+ *
  * @see PipedReader
- * 
- * @since Android 1.0
  */
 public class PipedWriter extends Writer {
     /**
@@ -40,9 +38,8 @@
      * Constructs a new unconnected {@code PipedWriter}. The resulting writer
      * must be connected to a {@code PipedReader} before data may be written to
      * it.
-     * 
+     *
      * @see PipedReader
-     * @since Android 1.0
      */
     public PipedWriter() {
         super();
@@ -52,12 +49,11 @@
      * Constructs a new {@code PipedWriter} connected to the {@link PipedReader}
      * {@code dest}. Any data written to this writer can be read from {@code
      * dest}.
-     * 
+     *
      * @param dest
      *            the {@code PipedReader} to connect to.
      * @throws IOException
      *             if {@code dest} is already connected.
-     * @since Android 1.0
      */
     public PipedWriter(PipedReader dest) throws IOException {
         super(dest);
@@ -68,10 +64,9 @@
      * Closes this writer. If a {@link PipedReader} is connected to this writer,
      * it is closed as well and the pipe is disconnected. Any data buffered in
      * the reader can still be read.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this writer.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -88,13 +83,12 @@
     /**
      * Connects this {@code PipedWriter} to a {@link PipedReader}. Any data
      * written to this writer becomes readable in the reader.
-     * 
+     *
      * @param stream
      *            the reader to connect to.
      * @throws IOException
      *             if this writer is closed or already connected, or if {@code
      *             stream} is already connected.
-     * @since Android 1.0
      */
     public void connect(PipedReader stream) throws IOException {
         synchronized (lock) {
@@ -112,10 +106,9 @@
     /**
      * Notifies the readers of this {@code PipedReader} that characters can be read. This
      * method does nothing if this Writer is not connected.
-     * 
+     *
      * @throws IOException
      *             if an I/O error occurs while flushing this writer.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -132,8 +125,7 @@
      * Separate threads should be used to write to a {@code PipedWriter} and to
      * read from the connected {@code PipedReader}. If the same thread is used,
      * a deadlock may occur.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -155,7 +147,6 @@
      *             correctly.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] buffer, int offset, int count) throws IOException {
@@ -194,8 +185,7 @@
      * Separate threads should be used to write to a {@code PipedWriter} and to
      * read from the connected {@code PipedReader}. If the same thread is used,
      * a deadlock may occur.
-     * </p>
-     * 
+     *
      * @param c
      *            the character to write.
      * @throws InterruptedIOException
@@ -207,7 +197,6 @@
      *             reader is closed or if the thread reading from the target
      *             reader is no longer alive. This case is currently not handled
      *             correctly.
-     * @since Android 1.0
      */
     @Override
     public void write(int c) throws IOException {
diff --git a/luni/src/main/java/java/io/PrintStream.java b/luni/src/main/java/java/io/PrintStream.java
index 0aae645..29d460e 100644
--- a/luni/src/main/java/java/io/PrintStream.java
+++ b/luni/src/main/java/java/io/PrintStream.java
@@ -18,6 +18,7 @@
 package java.io;
 
 import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
 import java.security.AccessController;
 import java.util.Formatter;
 import java.util.IllegalFormatException;
@@ -33,8 +34,6 @@
  * so that they can be read back in. No {@code IOException} is thrown by this
  * class. Instead, callers should use {@link #checkError()} to see if a problem
  * has occurred in this stream.
- * 
- * @since Android 1.0
  */
 public class PrintStream extends FilterOutputStream implements Appendable,
         Closeable {
@@ -63,12 +62,11 @@
      * Constructs a new {@code PrintStream} with {@code out} as its target
      * stream. By default, the new print stream does not automatically flush its
      * contents to the target stream when a newline is encountered.
-     * 
+     *
      * @param out
      *            the target output stream.
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream(OutputStream out) {
         super(out);
@@ -82,7 +80,7 @@
      * stream. The parameter {@code autoflush} determines if the print stream
      * automatically flushes its contents to the target stream when a newline is
      * encountered.
-     * 
+     *
      * @param out
      *            the target output stream.
      * @param autoflush
@@ -90,7 +88,6 @@
      *            newline sequence.
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream(OutputStream out, boolean autoflush) {
         super(out);
@@ -105,7 +102,7 @@
      * stream and using the character encoding {@code enc} while writing. The
      * parameter {@code autoflush} determines if the print stream automatically
      * flushes its contents to the target stream when a newline is encountered.
-     * 
+     *
      * @param out
      *            the target output stream.
      * @param autoflush
@@ -117,7 +114,6 @@
      *             if {@code out} or {@code enc} are {@code null}.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code enc} is not supported.
-     * @since Android 1.0
      */
     public PrintStream(OutputStream out, boolean autoflush, String enc)
             throws UnsupportedEncodingException {
@@ -126,7 +122,11 @@
             throw new NullPointerException();
         }
         this.autoflush = autoflush;
-        if (!Charset.isSupported(enc)) {
+        try {
+            if (!Charset.isSupported(enc)) {
+                throw new UnsupportedEncodingException(enc);
+            }
+        } catch (IllegalCharsetNameException e) {
             throw new UnsupportedEncodingException(enc);
         }
         encoding = enc;
@@ -135,7 +135,7 @@
     /**
      * Constructs a new {@code PrintStream} with {@code file} as its target. The
      * virtual machine's default character set is used for character encoding.
-     * 
+     *
      * @param file
      *            the target file. If the file already exists, its contents are
      *            removed, otherwise a new file is created.
@@ -144,7 +144,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies writing to the
      *             target file.
-     * @since Android 1.0
      */
     public PrintStream(File file) throws FileNotFoundException {
         super(new FileOutputStream(file));
@@ -153,7 +152,7 @@
     /**
      * Constructs a new {@code PrintStream} with {@code file} as its target. The
      * character set named {@code csn} is used for character encoding.
-     * 
+     *
      * @param file
      *            the target file. If the file already exists, its contents are
      *            removed, otherwise a new file is created.
@@ -168,7 +167,6 @@
      *             target file.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code csn} is not supported.
-     * @since Android 1.0
      */
     public PrintStream(File file, String csn) throws FileNotFoundException,
             UnsupportedEncodingException {
@@ -186,7 +184,7 @@
      * Constructs a new {@code PrintStream} with the file identified by
      * {@code fileName} as its target. The virtual machine's default character
      * set is used for character encoding.
-     * 
+     *
      * @param fileName
      *            the target file's name. If the file already exists, its
      *            contents are removed, otherwise a new file is created.
@@ -195,7 +193,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies writing to the
      *             target file.
-     * @since Android 1.0
      */
     public PrintStream(String fileName) throws FileNotFoundException {
         this(new File(fileName));
@@ -205,7 +202,7 @@
      * Constructs a new {@code PrintStream} with the file identified by
      * {@code fileName} as its target. The character set named {@code csn} is
      * used for character encoding.
-     * 
+     *
      * @param fileName
      *            the target file's name. If the file already exists, its
      *            contents are removed, otherwise a new file is created.
@@ -220,7 +217,6 @@
      *             target file.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code csn} is not supported.
-     * @since Android 1.0
      */
     public PrintStream(String fileName, String csn)
             throws FileNotFoundException, UnsupportedEncodingException {
@@ -229,12 +225,11 @@
 
     /**
      * Flushes this stream and returns the value of the error flag.
-     * 
+     *
      * @return {@code true} if either an {@code IOException} has been thrown
      *         previously or if {@code setError()} has been called;
      *         {@code false} otherwise.
-     * @see #setError()         
-     * @since Android 1.0
+     * @see #setError()
      */
     public boolean checkError() {
         if (out != null) {
@@ -247,8 +242,6 @@
      * Closes this print stream. Flushes this stream and then closes the target
      * stream. If an I/O error occurs, this stream's error state is set to
      * {@code true}.
-     * 
-     * @since Android 1.0
      */
     @Override
     public synchronized void close() {
@@ -267,8 +260,6 @@
      * Ensures that all pending data is sent out to the target stream. It also
      * flushes the target stream. If an I/O error occurs, this stream's error
      * state is set to {@code true}.
-     * 
-     * @since Android 1.0
      */
     @Override
     public synchronized void flush() {
@@ -288,7 +279,7 @@
      * target stream using the specified format string and arguments. For the
      * locale, the default value of the current virtual machine instance is
      * used.
-     * 
+     *
      * @param format
      *            the format string used for {@link java.util.Formatter#format}.
      * @param args
@@ -302,7 +293,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream format(String format, Object... args) {
         return format(Locale.getDefault(), format, args);
@@ -311,7 +301,7 @@
     /**
      * Writes a string formatted by an intermediate {@link Formatter} to this
      * stream using the specified locale, format string and arguments.
-     * 
+     *
      * @param l
      *            the locale used in the method. No localization will be applied
      *            if {@code l} is {@code null}.
@@ -328,7 +318,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream format(Locale l, String format, Object... args) {
         if (format == null) {
@@ -342,7 +331,7 @@
      * Prints a formatted string. The behavior of this method is the same as
      * this stream's {@code #format(String, Object...)} method. For the locale,
      * the default value of the current virtual machine instance is used.
-     * 
+     *
      * @param format
      *            the format string used for
      *            {@link java.util.Formatter#format}.
@@ -357,7 +346,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream printf(String format, Object... args) {
         return format(format, args);
@@ -366,7 +354,7 @@
     /**
      * Prints a formatted string. The behavior of this method is the same as
      * this stream's {@code #format(Locale, String, Object...)} method.
-     * 
+     *
      * @param l
      *            the locale used in the method. No localization will be applied
      *            if {@code l} is {@code null}.
@@ -383,7 +371,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream printf(Locale l, String format, Object... args) {
         return format(l, format, args);
@@ -399,11 +386,10 @@
     /**
      * Prints the string representation of the specified character array
      * to the target stream.
-     * 
+     *
      * @param charArray
      *            the character array to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(char[] charArray) {
         print(new String(charArray, 0, charArray.length));
@@ -412,11 +398,10 @@
     /**
      * Prints the string representation of the specified character to the target
      * stream.
-     * 
+     *
      * @param ch
      *            the character to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(char ch) {
         print(String.valueOf(ch));
@@ -425,11 +410,10 @@
     /**
      * Prints the string representation of the specified double to the target
      * stream.
-     * 
+     *
      * @param dnum
      *            the double value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(double dnum) {
         print(String.valueOf(dnum));
@@ -438,12 +422,11 @@
     /**
      * Prints the string representation of the specified float to the target
      * stream.
-     * 
+     *
      * @param fnum
      *            the float value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(float fnum) {
         print(String.valueOf(fnum));
     }
@@ -451,12 +434,11 @@
     /**
      * Prints the string representation of the specified integer to the target
      * stream.
-     * 
+     *
      * @param inum
      *            the integer value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(int inum) {
         print(String.valueOf(inum));
     }
@@ -464,12 +446,11 @@
     /**
      * Prints the string representation of the specified long to the target
      * stream.
-     * 
+     *
      * @param lnum
      *            the long value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(long lnum) {
         print(String.valueOf(lnum));
     }
@@ -477,12 +458,11 @@
     /**
      * Prints the string representation of the specified object to the target
      * stream.
-     * 
+     *
      * @param obj
      *            the object to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(Object obj) {
         print(String.valueOf(obj));
     }
@@ -494,12 +474,10 @@
      * {@code write(int)}.
      * <p>
      * If an I/O error occurs, this stream's error state is set to {@code true}.
-     * </p>
-     * 
+     *
      * @param str
      *            the string to print to the target stream.
      * @see #write(int)
-     * @since Android 1.0
      */
     public synchronized void print(String str) {
         if (out == null) {
@@ -525,12 +503,11 @@
     /**
      * Prints the string representation of the specified boolean to the target
      * stream.
-     * 
+     *
      * @param bool
      *            the boolean value to print the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(boolean bool) {
         print(String.valueOf(bool));
     }
@@ -538,8 +515,6 @@
     /**
      * Prints the string representation of the system property
      * {@code "line.separator"} to the target stream.
-     * 
-     * @since Android 1.0
      */
     public void println() {
         newline();
@@ -549,11 +524,10 @@
      * Prints the string representation of the specified character array
      * followed by the system property {@code "line.separator"} to the target
      * stream.
-     * 
+     *
      * @param charArray
      *            the character array to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(char[] charArray) {
         println(new String(charArray, 0, charArray.length));
@@ -562,11 +536,10 @@
     /**
      * Prints the string representation of the specified character followed by
      * the system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param ch
      *            the character to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(char ch) {
         println(String.valueOf(ch));
@@ -575,11 +548,10 @@
     /**
      * Prints the string representation of the specified double followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param dnum
      *            the double value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(double dnum) {
         println(String.valueOf(dnum));
@@ -588,12 +560,11 @@
     /**
      * Prints the string representation of the specified float followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param fnum
      *            the float value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
    public void println(float fnum) {
         println(String.valueOf(fnum));
     }
@@ -601,12 +572,12 @@
    /**
      * Prints the string representation of the specified integer followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param inum
      *            the integer value to print to the target stream.
      * @see #print(String)
      * @since Android 1.0
-     */   
+     */
     public void println(int inum) {
         println(String.valueOf(inum));
     }
@@ -614,12 +585,12 @@
     /**
      * Prints the string representation of the specified long followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param lnum
      *            the long value to print to the target stream.
      * @see #print(String)
      * @since Android 1.0
-     */   
+     */
     public void println(long lnum) {
         println(String.valueOf(lnum));
     }
@@ -627,12 +598,12 @@
     /**
      * Prints the string representation of the specified object followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param obj
      *            the object to print to the target stream.
      * @see #print(String)
      * @since Android 1.0
-     */   
+     */
     public void println(Object obj) {
         println(String.valueOf(obj));
     }
@@ -645,7 +616,7 @@
      * <p>
      * If an I/O error occurs, this stream's error state is set to {@code true}.
      * </p>
-     * 
+     *
      * @param str
      *            the string to print to the target stream.
      * @see #write(int)
@@ -659,20 +630,17 @@
     /**
      * Prints the string representation of the specified boolean followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param bool
      *            the boolean value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(boolean bool) {
         println(String.valueOf(bool));
     }
 
     /**
      * Sets the error flag of this print stream to {@code true}.
-     * 
-     * @since Android 1.0
      */
     protected void setError() {
         ioError = true;
@@ -685,8 +653,7 @@
      * <p>
      * This stream's error flag is set to {@code true} if this stream is closed
      * or an I/O error occurs.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @param offset
@@ -697,7 +664,6 @@
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is bigger than the length of {@code buffer}.
      * @see #flush()
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int count) {
@@ -738,11 +704,9 @@
      * <p>
      * This stream's error flag is set to {@code true} if it is closed or an I/O
      * error occurs.
-     * </p>
-     * 
+     *
      * @param oneByte
      *            the byte to be written
-     * @since Android 1.0
      */
     @Override
     public synchronized void write(int oneByte) {
@@ -763,11 +727,10 @@
     /**
      * Appends the character {@code c} to the target stream. This method works
      * the same way as {@link #print(char)}.
-     * 
+     *
      * @param c
      *            the character to append to the target stream.
      * @return this stream.
-     * @since Android 1.0
      */
     public PrintStream append(char c) {
         print(c);
@@ -779,11 +742,10 @@
      * method works the same way as {@code PrintStream.print(csq.toString())}.
      * If {@code csq} is {@code null}, then the string "null" is written to the
      * target stream.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target stream.
      * @return this stream.
-     * @since Android 1.0
      */
     public PrintStream append(CharSequence csq) {
         if (null == csq) {
@@ -800,7 +762,7 @@
      * PrintStream.print(csq.subsequence(start, end).toString())}. If {@code
      * csq} is {@code null}, then the specified subsequence of the string "null"
      * will be written to the target stream.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target stream.
      * @param start
@@ -814,7 +776,6 @@
      *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
      *             either {@code start} or {@code end} are greater or equal than
      *             the length of {@code csq}.
-     * @since Android 1.0
      */
     public PrintStream append(CharSequence csq, int start, int end) {
         if (null == csq) {
diff --git a/luni/src/main/java/java/io/PrintWriter.java b/luni/src/main/java/java/io/PrintWriter.java
index 0c5189d..f87707d 100644
--- a/luni/src/main/java/java/io/PrintWriter.java
+++ b/luni/src/main/java/java/io/PrintWriter.java
@@ -25,24 +25,16 @@
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 
-// BEGIN android-note
-// added @return comment to #printf(Locale l, String format, Object... args)
-// END android-note
-
 /**
  * Wraps either an existing {@link OutputStream} or an existing {@link Writer}
  * and provides convenience methods for printing common data types in a human
  * readable format. No {@code IOException} is thrown by this class. Instead,
  * callers should use {@link #checkError()} to see if a problem has occurred in
  * this writer.
- * 
- * @since Android 1.0
  */
 public class PrintWriter extends Writer {
     /**
      * The writer to print data to.
-     * 
-     * @since Android 1.0
      */
     protected Writer out;
 
@@ -64,12 +56,11 @@
      * Constructs a new {@code PrintWriter} with {@code out} as its target
      * stream. By default, the new print writer does not automatically flush its
      * contents to the target stream when a newline is encountered.
-     * 
+     *
      * @param out
      *            the target output stream.
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter(OutputStream out) {
         this(new OutputStreamWriter(out), false);
@@ -80,7 +71,7 @@
      * stream. The parameter {@code autoflush} determines if the print writer
      * automatically flushes its contents to the target stream when a newline is
      * encountered.
-     * 
+     *
      * @param out
      *            the target output stream.
      * @param autoflush
@@ -88,7 +79,6 @@
      *            newline sequence.
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter(OutputStream out, boolean autoflush) {
         this(new OutputStreamWriter(out), autoflush);
@@ -98,12 +88,11 @@
      * Constructs a new {@code PrintWriter} with {@code wr} as its target
      * writer. By default, the new print writer does not automatically flush its
      * contents to the target writer when a newline is encountered.
-     * 
+     *
      * @param wr
      *            the target writer.
      * @throws NullPointerException
      *             if {@code wr} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter(Writer wr) {
         this(wr, false);
@@ -114,7 +103,7 @@
      * writer. The parameter {@code autoflush} determines if the print writer
      * automatically flushes its contents to the target writer when a newline is
      * encountered.
-     * 
+     *
      * @param wr
      *            the target writer.
      * @param autoflush
@@ -122,7 +111,6 @@
      *            newline sequence.
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter(Writer wr, boolean autoflush) {
         super(wr);
@@ -135,7 +123,7 @@
      * virtual machine's default character set is used for character encoding.
      * The print writer does not automatically flush its contents to the target
      * file when a newline is encountered. The output to the file is buffered.
-     * 
+     *
      * @param file
      *            the target file. If the file already exists, its contents are
      *            removed, otherwise a new file is created.
@@ -144,7 +132,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies writing to the
      *             target file.
-     * @since Android 1.0
      */
     public PrintWriter(File file) throws FileNotFoundException {
         // BEGIN android-modified
@@ -160,7 +147,7 @@
      * character set named {@code csn} is used for character encoding.
      * The print writer does not automatically flush its contents to the target
      * file when a newline is encountered. The output to the file is buffered.
-     * 
+     *
      * @param file
      *            the target file. If the file already exists, its contents are
      *            removed, otherwise a new file is created.
@@ -175,7 +162,6 @@
      *             target file.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code csn} is not supported.
-     * @since Android 1.0
      */
     public PrintWriter(File file, String csn) throws FileNotFoundException,
             UnsupportedEncodingException {
@@ -193,7 +179,7 @@
      * used for character encoding. The print writer does not automatically
      * flush its contents to the target file when a newline is encountered. The
      * output to the file is buffered.
-     * 
+     *
      * @param fileName
      *            the target file's name. If the file already exists, its
      *            contents are removed, otherwise a new file is created.
@@ -202,7 +188,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies writing to the
      *             target file.
-     * @since Android 1.0
      */
     public PrintWriter(String fileName) throws FileNotFoundException {
         // BEGIN android-modified
@@ -219,7 +204,7 @@
      * character encoding. The print writer does not automatically flush its
      * contents to the target file when a newline is encountered. The output to
      * the file is buffered.
-     * 
+     *
      * @param fileName
      *            the target file's name. If the file already exists, its
      *            contents are removed, otherwise a new file is created.
@@ -234,7 +219,6 @@
      *             target file.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code csn} is not supported.
-     * @since Android 1.0
      */
     public PrintWriter(String fileName, String csn)
             throws FileNotFoundException, UnsupportedEncodingException {
@@ -248,12 +232,11 @@
 
     /**
      * Flushes this writer and returns the value of the error flag.
-     * 
+     *
      * @return {@code true} if either an {@code IOException} has been thrown
      *         previously or if {@code setError()} has been called;
      *         {@code false} otherwise.
-     * @see #setError()         
-     * @since Android 1.0
+     * @see #setError()
      */
     public boolean checkError() {
         if (out != null) {
@@ -265,8 +248,6 @@
     /**
      * Closes this print writer. Flushes this writer and then closes the target.
      * If an I/O error occurs, this writer's error flag is set to {@code true}.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void close() {
@@ -286,8 +267,6 @@
      * Ensures that all pending data is sent out to the target. It also
      * flushes the target. If an I/O error occurs, this writer's error
      * state is set to {@code true}.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void flush() {
@@ -309,7 +288,7 @@
      * target using the specified format string and arguments. For the locale,
      * the default value of the current virtual machine instance is used. If
      * automatic flushing is enabled then the buffer is flushed as well.
-     * 
+     *
      * @param format
      *            the format string used for {@link java.util.Formatter#format}.
      * @param args
@@ -323,7 +302,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter format(String format, Object... args) {
         return format(Locale.getDefault(), format, args);
@@ -333,7 +311,7 @@
      * Writes a string formatted by an intermediate {@code Formatter} to the
      * target using the specified locale, format string and arguments. If
      * automatic flushing is enabled then this writer is flushed.
-     * 
+     *
      * @param l
      *            the locale used in the method. No localization will be applied
      *            if {@code l} is {@code null}.
@@ -350,7 +328,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter format(Locale l, String format, Object... args) {
         if (format == null) {
@@ -367,7 +344,7 @@
      * Prints a formatted string. The behavior of this method is the same as
      * this writer's {@code #format(String, Object...)} method. For the locale,
      * the default value of the current virtual machine instance is used.
-     * 
+     *
      * @param format
      *            the format string used for {@link java.util.Formatter#format}.
      * @param args
@@ -381,7 +358,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter printf(String format, Object... args) {
         return format(format, args);
@@ -390,7 +366,7 @@
     /**
      * Prints a formatted string. The behavior of this method is the same as
      * this writer's {@code #format(Locale, String, Object...)} method.
-     * 
+     *
      * @param l
      *            the locale used in the method. No localization will be applied
      *            if {@code l} is {@code null}.
@@ -407,7 +383,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter printf(Locale l, String format, Object... args) {
         return format(l, format, args);
@@ -426,11 +401,10 @@
     /**
      * Prints the string representation of the specified character array
      * to the target.
-     * 
+     *
      * @param charArray
      *            the character array to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(char[] charArray) {
         print(new String(charArray, 0, charArray.length));
@@ -439,11 +413,10 @@
     /**
      * Prints the string representation of the specified character to the
      * target.
-     * 
+     *
      * @param ch
      *            the character to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(char ch) {
         print(String.valueOf(ch));
@@ -451,23 +424,21 @@
 
     /**
      * Prints the string representation of the specified double to the target.
-     * 
+     *
      * @param dnum
      *            the double value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(double dnum) {
         print(String.valueOf(dnum));
     }
 
-   /**
+    /**
      * Prints the string representation of the specified float to the target.
-     * 
+     *
      * @param fnum
      *            the float value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(float fnum) {
         print(String.valueOf(fnum));
@@ -475,23 +446,21 @@
 
     /**
      * Prints the string representation of the specified integer to the target.
-     * 
+     *
      * @param inum
      *            the integer value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(int inum) {
         print(String.valueOf(inum));
     }
 
     /**
      * Prints the string representation of the specified long to the target.
-     * 
+     *
      * @param lnum
      *            the long value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(long lnum) {
         print(String.valueOf(lnum));
@@ -499,12 +468,11 @@
 
     /**
      * Prints the string representation of the specified object to the target.
-     * 
+     *
      * @param obj
      *            the object to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(Object obj) {
         print(String.valueOf(obj));
     }
@@ -515,12 +483,10 @@
      * The bytes are then written to the target with {@code write(int)}.
      * <p>
      * If an I/O error occurs, this writer's error flag is set to {@code true}.
-     * </p>
-     * 
+     *
      * @param str
      *            the string to print to the target.
      * @see #write(int)
-     * @since Android 1.0
      */
     public void print(String str) {
         write(str != null ? str : String.valueOf((Object) null));
@@ -528,12 +494,11 @@
 
     /**
      * Prints the string representation of the specified boolean to the target.
-     * 
+     *
      * @param bool
      *            the boolean value to print the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(boolean bool) {
         print(String.valueOf(bool));
     }
@@ -542,8 +507,6 @@
      * Prints the string representation of the system property {@code
      * "line.separator"} to the target. Flushes this writer if the autoflush
      * flag is set to {@code true}.
-     * 
-     * @since Android 1.0
      */
     public void println() {
         synchronized (lock) {
@@ -555,11 +518,10 @@
      * Prints the string representation of the specified character array
      * followed by the system property {@code "line.separator"} to the target.
      * Flushes this writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param charArray
      *            the character array to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(char[] charArray) {
         println(new String(charArray, 0, charArray.length));
@@ -569,11 +531,10 @@
      * Prints the string representation of the specified character followed by
      * the system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param ch
      *            the character to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(char ch) {
         println(String.valueOf(ch));
@@ -583,11 +544,10 @@
      * Prints the string representation of the specified double followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param dnum
      *            the double value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(double dnum) {
         println(String.valueOf(dnum));
@@ -597,12 +557,11 @@
      * Prints the string representation of the specified float followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param fnum
      *            the float value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(float fnum) {
         println(String.valueOf(fnum));
     }
@@ -611,12 +570,11 @@
      * Prints the string representation of the specified integer followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param inum
      *            the integer value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(int inum) {
         println(String.valueOf(inum));
     }
@@ -625,12 +583,11 @@
      * Prints the string representation of the specified long followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param lnum
      *            the long value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(long lnum) {
         println(String.valueOf(lnum));
     }
@@ -639,12 +596,11 @@
      * Prints the string representation of the specified object followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param obj
      *            the object to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(Object obj) {
         println(String.valueOf(obj));
     }
@@ -657,12 +613,10 @@
      * is flushed if the autoflush flag is set to {@code true}.
      * <p>
      * If an I/O error occurs, this writer's error flag is set to {@code true}.
-     * </p>
-     * 
+     *
      * @param str
      *            the string to print to the target.
      * @see #write(int)
-     * @since Android 1.0
      */
     public void println(String str) {
         synchronized (lock) {
@@ -675,20 +629,17 @@
      * Prints the string representation of the specified boolean followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param bool
      *            the boolean value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(boolean bool) {
         println(String.valueOf(bool));
     }
 
     /**
      * Sets the error flag of this writer to {@code true}.
-     * 
-     * @since Android 1.0
      */
     protected void setError() {
         synchronized (lock) {
@@ -698,10 +649,9 @@
 
     /**
      * Writes the character buffer {@code buf} to the target.
-     * 
+     *
      * @param buf
      *            the non-null array containing characters to write.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] buf) {
@@ -717,8 +667,7 @@
      * <p>
      * This writer's error flag is set to {@code true} if this writer is closed
      * or an I/O error occurs.
-     * </p>
-     * 
+     *
      * @param buf
      *            the buffer to write to the target.
      * @param offset
@@ -728,7 +677,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is greater than the length of {@code buf}.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] buf, int offset, int count) {
@@ -744,11 +692,9 @@
      * <p>
      * This writer's error flag is set to {@code true} if this writer is closed
      * or an I/O error occurs.
-     * </p>
-     * 
+     *
      * @param oneChar
      *            the character to write to the target.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) {
@@ -774,10 +720,9 @@
 
     /**
      * Writes the characters from the specified string to the target.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
-     * @since Android 1.0
      */
     @Override
     public void write(String str) {
@@ -787,7 +732,7 @@
     /**
      * Writes {@code count} characters from {@code str} starting at {@code
      * offset} to the target.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
      * @param offset
@@ -797,7 +742,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is greater than the length of {@code str}.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int count) {
@@ -805,12 +749,11 @@
     }
 
     /**
-     * Appends the character {@code c} to the target. 
-     * 
+     * Appends the character {@code c} to the target.
+     *
      * @param c
      *            the character to append to the target.
      * @return this writer.
-     * @since Android 1.0
      */
     @Override
     public PrintWriter append(char c) {
@@ -823,11 +766,10 @@
      * method works the same way as {@code PrintWriter.print(csq.toString())}.
      * If {@code csq} is {@code null}, then the string "null" is written
      * to the target.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @return this writer.
-     * @since Android 1.0
      */
     @Override
     public PrintWriter append(CharSequence csq) {
@@ -845,7 +787,7 @@
      * PrintWriter.print(csq.subsequence(start, end).toString())}. If {@code
      * csq} is {@code null}, then the specified subsequence of the string "null"
      * will be written to the target.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @param start
@@ -859,7 +801,6 @@
      *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
      *             either {@code start} or {@code end} are greater or equal than
      *             the length of {@code csq}.
-     * @since Android 1.0
      */
     @Override
     public PrintWriter append(CharSequence csq, int start, int end) {
diff --git a/luni/src/main/java/java/io/PushbackInputStream.java b/luni/src/main/java/java/io/PushbackInputStream.java
index c397c86..1784012 100644
--- a/luni/src/main/java/java/io/PushbackInputStream.java
+++ b/luni/src/main/java/java/io/PushbackInputStream.java
@@ -25,14 +25,10 @@
  * this useful. The number of bytes which may be pushed back can be specified
  * during construction. If the buffer of pushed back bytes is empty, bytes are
  * read from the underlying input stream.
- * 
- * @since Android 1.0
  */
 public class PushbackInputStream extends FilterInputStream {
     /**
      * The buffer that contains pushed-back bytes.
-     * 
-     * @since Android 1.0
      */
     protected byte[] buf;
 
@@ -40,8 +36,6 @@
      * The current position within {@code buf}. A value equal to
      * {@code buf.length} indicates that no bytes are available. A value of 0
      * indicates that the buffer is full.
-     * 
-     * @since Android 1.0
      */
     protected int pos;
 
@@ -49,10 +43,9 @@
      * Constructs a new {@code PushbackInputStream} with the specified input
      * stream as source. The size of the pushback buffer is set to the default
      * value of 1 byte.
-     * 
+     *
      * @param in
      *            the source input stream.
-     * @since Android 1.0
      */
     public PushbackInputStream(InputStream in) {
         super(in);
@@ -63,14 +56,13 @@
     /**
      * Constructs a new {@code PushbackInputStream} with {@code in} as source
      * input stream. The size of the pushback buffer is set to {@code size}.
-     * 
+     *
      * @param in
      *            the source input stream.
      * @param size
      *            the size of the pushback buffer.
      * @throws IllegalArgumentException
      *             if {@code size} is negative.
-     * @since Android 1.0
      */
     public PushbackInputStream(InputStream in, int size) {
         super(in);
@@ -85,12 +77,11 @@
      * Returns the number of bytes that are available before this stream will
      * block. This is the sum of the bytes available in the pushback buffer and
      * those available from the source stream.
-     * 
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if this stream is closed or an I/O error occurs in the source
      *             stream.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -103,10 +94,9 @@
     /**
      * Closes this stream. This implementation closes the source stream
      * and releases the pushback buffer.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -121,11 +111,10 @@
      * Indicates whether this stream supports the {@code mark(int)} and
      * {@code reset()} methods. {@code PushbackInputStream} does not support
      * them, so it returns {@code false}.
-     * 
+     *
      * @return always {@code false}.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -138,13 +127,12 @@
      * available bytes then a byte from the source input stream is returned.
      * Blocks until one byte has been read, the end of the source stream is
      * detected or an exception is thrown.
-     * 
+     *
      * @return the byte read or -1 if the end of the source stream has been
      *         reached.
      * @throws IOException
      *             if this stream is closed or an I/O error occurs while reading
      *             from this stream.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -166,7 +154,7 @@
      * from the pushback buffer first, then from the source stream if more bytes
      * are required. Blocks until {@code count} bytes have been read, the end of
      * the source stream is detected or an exception is thrown.
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read from this stream.
      * @param offset
@@ -185,7 +173,6 @@
      *             reading from this stream.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
@@ -234,13 +221,12 @@
     /**
      * Skips {@code count} bytes in this stream. This implementation skips bytes
      * in the pushback buffer first and then in the source stream if necessary.
-     * 
+     *
      * @param count
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
@@ -270,14 +256,12 @@
      * contents of {@code buffer}, an {@code IOException} is thrown. Parts of
      * {@code buffer} may have already been copied to the pushback buffer when
      * the exception is thrown.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer containing the bytes to push back to this stream.
      * @throws IOException
      *             if the free space in the internal pushback buffer is not
      *             sufficient to store the contents of {@code buffer}.
-     * @since Android 1.0
      */
     public void unread(byte[] buffer) throws IOException {
         unread(buffer, 0, buffer.length);
@@ -294,8 +278,7 @@
      * subset of {@code buffer}, an {@code IOException} is thrown. Parts of
      * {@code buffer} may have already been copied to the pushback buffer when
      * the exception is thrown.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer containing the bytes to push back to this stream.
      * @param offset
@@ -309,7 +292,6 @@
      * @throws IOException
      *             if the free space in the internal pushback buffer is not
      *             sufficient to store the selected contents of {@code buffer}.
-     * @since Android 1.0
      */
     public void unread(byte[] buffer, int offset, int length)
             throws IOException {
@@ -345,14 +327,12 @@
      * <p>
      * If this stream's internal pushback buffer cannot store the byte, an
      * {@code IOException} is thrown.
-     * </p>
-     * 
+     *
      * @param oneByte
      *            the byte to push back to this stream.
      * @throws IOException
      *             if this stream is closed or the internal pushback buffer is
      *             full.
-     * @since Android 1.0
      */
     public void unread(int oneByte) throws IOException {
         if (buf == null) {
@@ -367,11 +347,10 @@
     /**
      * Marks the current position in this stream. Setting a mark is not
      * supported in this class; this implementation does nothing.
-     * 
+     *
      * @param readlimit
      *            the number of bytes that can be read from this stream before
      *            the mark is invalidated; this parameter is ignored.
-     * @since Android 1.0
      */
     @Override
     public void mark(int readlimit) {
@@ -382,10 +361,9 @@
      * Resets this stream to the last marked position. Resetting the stream is
      * not supported in this class; this implementation always throws an
      * {@code IOException}.
-     * 
+     *
      * @throws IOException
      *             if this method is called.
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
diff --git a/luni/src/main/java/java/io/PushbackReader.java b/luni/src/main/java/java/io/PushbackReader.java
index 484caf3..606ecb4 100644
--- a/luni/src/main/java/java/io/PushbackReader.java
+++ b/luni/src/main/java/java/io/PushbackReader.java
@@ -25,8 +25,6 @@
  * find this useful. The number of characters which may be pushed back can be
  * specified during construction. If the buffer of pushed back bytes is empty,
  * characters are read from the underlying reader.
- * 
- * @since Android 1.0
  */
 public class PushbackReader extends FilterReader {
     /**
@@ -45,10 +43,9 @@
      * Constructs a new {@code PushbackReader} with the specified reader as
      * source. The size of the pushback buffer is set to the default value of 1
      * character.
-     * 
+     *
      * @param in
      *            the source reader.
-     * @since Android 1.0
      */
     public PushbackReader(Reader in) {
         super(in);
@@ -59,14 +56,13 @@
     /**
      * Constructs a new {@code PushbackReader} with {@code in} as source reader.
      * The size of the pushback buffer is set to {@code size}.
-     * 
+     *
      * @param in
      *            the source reader.
      * @param size
      *            the size of the pushback buffer.
      * @throws IllegalArgumentException
      *             if {@code size} is negative.
-     * @since Android 1.0
      */
     public PushbackReader(Reader in, int size) {
         super(in);
@@ -80,10 +76,9 @@
     /**
      * Closes this reader. This implementation closes the source reader
      * and releases the pushback buffer.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this reader.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -97,13 +92,12 @@
      * Marks the current position in this stream. Setting a mark is not
      * supported in this class; this implementation always throws an
      * {@code IOException}.
-     * 
+     *
      * @param readAheadLimit
      *            the number of character that can be read from this reader
      *            before the mark is invalidated; this parameter is ignored.
      * @throws IOException
      *             if this method is called.
-     * @since Android 1.0
      */
     @Override
     public void mark(int readAheadLimit) throws IOException {
@@ -114,11 +108,10 @@
      * Indicates whether this reader supports the {@code mark(int)} and
      * {@code reset()} methods. {@code PushbackReader} does not support them, so
      * it returns {@code false}.
-     * 
+     *
      * @return always {@code false}.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -132,13 +125,12 @@
      * available characters then a character from the source reader is returned.
      * Blocks until one character has been read, the end of the source reader is
      * detected or an exception is thrown.
-     * 
+     *
      * @return the character read or -1 if the end of the source reader has been
      *         reached.
      * @throws IOException
      *             if this reader is closed or an I/O error occurs while reading
      *             from this reader.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -164,7 +156,7 @@
      * read from the pushback buffer first, then from the source reader if more
      * bytes are required. Blocks until {@code count} characters have been read,
      * the end of the source reader is detected or an exception is thrown.
-     * 
+     *
      * @param buffer
      *            the array in which to store the characters read from this
      *            reader.
@@ -182,7 +174,6 @@
      * @throws IOException
      *             if this reader is closed or another I/O error occurs while
      *             reading from this reader.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buffer, int offset, int count) throws IOException {
@@ -236,7 +227,7 @@
      * Indicates whether this reader is ready to be read without blocking.
      * Returns {@code true} if this reader will not block when {@code read} is
      * called, {@code false} if unknown or blocking will occur.
-     * 
+     *
      * @return {@code true} if the receiver will not block when
      *         {@code read()} is called, {@code false} if unknown
      *         or blocking will occur.
@@ -244,7 +235,6 @@
      *             if this reader is closed or some other I/O error occurs.
      * @see #read()
      * @see #read(char[], int, int)
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -260,10 +250,9 @@
      * Resets this reader to the last marked position. Resetting the reader is
      * not supported in this class; this implementation always throws an
      * {@code IOException}.
-     * 
+     *
      * @throws IOException
      *             if this method is called.
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -279,8 +268,7 @@
      * contents of {@code buffer}, an {@code IOException} is thrown. Parts of
      * {@code buffer} may have already been copied to the pushback buffer when
      * the exception is thrown.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer containing the characters to push back to this
      *            reader.
@@ -288,7 +276,6 @@
      *             if this reader is closed or the free space in the internal
      *             pushback buffer is not sufficient to store the contents of
      *             {@code buffer}.
-     * @since Android 1.0
      */
     public void unread(char[] buffer) throws IOException {
         unread(buffer, 0, buffer.length);
@@ -305,8 +292,7 @@
      * subset of {@code buffer}, an {@code IOException} is thrown. Parts of
      * {@code buffer} may have already been copied to the pushback buffer when
      * the exception is thrown.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer containing the characters to push back to this
      *            reader.
@@ -324,7 +310,6 @@
      *             contents of {@code buffer}.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     public void unread(char[] buffer, int offset, int count) throws IOException {
         synchronized (lock) {
@@ -361,14 +346,12 @@
      * <p>
      * If this reader's internal pushback buffer cannot store the character, an
      * {@code IOException} is thrown.
-     * </p>
-     * 
+     *
      * @param oneChar
      *            the character to push back to this stream.
      * @throws IOException
      *             if this reader is closed or the internal pushback buffer is
      *             full.
-     * @since Android 1.0
      */
     public void unread(int oneChar) throws IOException {
         synchronized (lock) {
@@ -386,14 +369,13 @@
      * Skips {@code count} characters in this reader. This implementation skips
      * characters in the pushback buffer first and then in the source reader if
      * necessary.
-     * 
+     *
      * @param count
      *            the number of characters to skip.
      * @return the number of characters actually skipped.
      * @throws IllegalArgumentException if {@code count < 0}.
      * @throws IOException
      *             if this reader is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
diff --git a/luni/src/main/java/java/io/RandomAccessFile.java b/luni/src/main/java/java/io/RandomAccessFile.java
index 7152116..37d77f5 100644
--- a/luni/src/main/java/java/io/RandomAccessFile.java
+++ b/luni/src/main/java/java/io/RandomAccessFile.java
@@ -33,8 +33,6 @@
  * opened in read/write mode, write operations are available as well. The
  * position of the next read or write operation can be moved forwards and
  * backwards after every operation.
- * 
- * @since Android 1.0
  */
 public class RandomAccessFile implements DataInput, DataOutput, Closeable {
     /**
@@ -51,7 +49,7 @@
     private IFileSystem fileSystem = Platform.getFileSystem();
 
     private boolean isReadOnly;
-    
+
     // BEGIN android-added
     private int options;
     // END android-added
@@ -61,12 +59,11 @@
 
     private Object repositionLock = new RepositionLock();
 
-    // BEGIN android-changed
     /**
      * Constructs a new {@code RandomAccessFile} based on {@code file} and opens
-     * it according to the access string in {@code mode}. 
+     * it according to the access string in {@code mode}.
      * <p><a id="accessmode"/>
-     * {@code mode} may have one of following values: 
+     * {@code mode} may have one of following values:
      * <table border="0">
      * <tr>
      * <td>{@code "r"}</td>
@@ -90,7 +87,7 @@
      * file's content must be written synchronously to the target device.</td>
      * </tr>
      * </table>
-     * </p>
+     *
      * @param file
      *            the file to open.
      * @param mode
@@ -107,16 +104,17 @@
      *             access request according to {@code mode}.
      * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
-     * @since Android 1.0
      */
     public RandomAccessFile(File file, String mode)
             throws FileNotFoundException {
         super();
 
+        // BEGIN android-changed
         options = 0;
-        
+        // END android-changed
+
         fd = new FileDescriptor();
-       
+
         if (mode.equals("r")) { //$NON-NLS-1$
             isReadOnly = true;
             fd.readOnly = true;
@@ -143,8 +141,12 @@
                 security.checkWrite(file.getPath());
             }
         }
-        
+
         fd.descriptor = fileSystem.open(file.properPath(true), options);
+        // BEGIN android-removed
+        // channel = FileChannelFactory.getFileChannel(this, fd.descriptor,
+        //         options);
+        // END android-removed
 
         // if we are in "rws" mode, attempt to sync file+metadata
         if (syncMetadata) {
@@ -155,14 +157,13 @@
             }
         }
     }
-    // END android-changed
 
     /**
      * Constructs a new {@code RandomAccessFile} based on the file named {@code
      * fileName} and opens it according to the access string in {@code mode}.
      * The file path may be specified absolutely or relative to the system
      * property {@code "user.dir"}.
-     * 
+     *
      * @param fileName
      *            the name of the file to open.
      * @param mode
@@ -179,7 +180,6 @@
      *             access request according to {@code mode}.
      * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
-     * @since Android 1.0
      */
     public RandomAccessFile(String fileName, String mode)
             throws FileNotFoundException {
@@ -188,10 +188,9 @@
 
     /**
      * Closes this file.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this file.
-     * @since Android 1.0
      */
     public void close() throws IOException {
         // BEGIN android-changed
@@ -208,39 +207,34 @@
         // END android-changed
     }
 
-    // BEGIN android-changed
     /**
      * Gets this file's {@link FileChannel} object.
      * <p>
-     * The file channel's {@link FileChannel.#position() position} is the same
+     * The file channel's {@link FileChannel#position() position} is the same
      * as this file's file pointer offset (see {@link #getFilePointer()}). Any
      * changes made to this file's file pointer offset are also visible in the
      * file channel's position and vice versa.
-     * </p>
-     * 
+     *
      * @return this file's file channel instance.
-     * @since Android 1.0
      */
-    public final FileChannel getChannel() {
-        synchronized(this) {
-            if(channel == null) {
-                channel = FileChannelFactory.getFileChannel(this, fd.descriptor,
-                        options);
-            }
-            return channel;
+    public final synchronized FileChannel getChannel() {
+        // BEGIN android-added
+        if(channel == null) {
+            channel = FileChannelFactory.getFileChannel(this, fd.descriptor,
+                    options);
         }
+        // END android-added
+        return channel;
     }
-    // END android-changed
 
     /**
      * Gets this file's {@link FileDescriptor}. This represents the operating
      * system resource for this random access file.
-     * 
+     *
      * @return this file's file descriptor object.
      * @throws IOException
      *             if an error occurs while getting the file descriptor of this
      *             file.
-     * @since Android 1.0
      */
     public final FileDescriptor getFD() throws IOException {
         return fd;
@@ -249,13 +243,12 @@
     /**
      * Gets the current position within this file. All reads and
      * writes take place at the current file pointer position.
-     * 
+     *
      * @return the current offset in bytes from the beginning of the file.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while getting the file pointer of this
      *             file.
-     * @since Android 1.0
      */
     public long getFilePointer() throws IOException {
         openCheck();
@@ -265,7 +258,7 @@
     /**
      * Checks to see if the file is currently open. Returns silently if it is,
      * and throws an exception if it is not.
-     * 
+     *
      * @throws IOException
      *             the receiver is closed.
      */
@@ -277,11 +270,10 @@
 
     /**
      * Returns the length of this file in bytes.
-     * 
+     *
      * @return the file's length in bytes.
      * @throws IOException
      *             if this file is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     public long length() throws IOException {
         openCheck();
@@ -301,11 +293,10 @@
      * as an integer in the range from 0 to 255. Returns -1 if the end of the
      * file has been reached. Blocks until one byte has been read, the end of
      * the file is detected or an exception is thrown.
-     * 
+     *
      * @return the byte read or -1 if the end of the file has been reached.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read() throws IOException {
         openCheck();
@@ -321,14 +312,13 @@
      * byte array {@code buffer}. The maximum number of bytes read corresponds
      * to the size of {@code buffer}. Blocks until at least one byte has been
      * read.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @return the number of bytes actually read or -1 if the end of the file
      *         has been reached.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read(byte[] buffer) throws IOException {
         return read(buffer, 0, buffer.length);
@@ -339,7 +329,7 @@
      * and stores them in the byte array {@code buffer} starting at {@code
      * offset}. Blocks until {@code count} bytes have been read, the end of the
      * file is reached or an exception is thrown.
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read from this file.
      * @param offset
@@ -354,7 +344,6 @@
      *             offset + count} is greater than the size of {@code buffer}.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read(byte[] buffer, int offset, int count) throws IOException {
         // have to have four comparisions to not miss integer overflow cases
@@ -383,14 +372,13 @@
      * Reads a boolean from the current position in this file. Blocks until one
      * byte has been read, the end of the file is reached or an exception is
      * thrown.
-     * 
+     *
      * @return the next boolean value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeBoolean(boolean)
-     * @since Android 1.0
      */
     public final boolean readBoolean() throws IOException {
         int temp = this.read();
@@ -404,14 +392,13 @@
      * Reads an 8-bit byte from the current position in this file. Blocks until
      * one byte has been read, the end of the file is reached or an exception is
      * thrown.
-     * 
+     *
      * @return the next signed 8-bit byte value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeBoolean(boolean)
-     * @since Android 1.0
      */
     public final byte readByte() throws IOException {
         int temp = this.read();
@@ -425,15 +412,14 @@
      * Reads a 16-bit character from the current position in this file. Blocks until
      * two bytes have been read, the end of the file is reached or an exception is
      * thrown.
-     * 
+     *
      * @return the next char value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeChar(int)
-     * @since Android 1.0
-     */    
+     */
     public final char readChar() throws IOException {
         byte[] buffer = new byte[2];
         if (read(buffer, 0, buffer.length) != buffer.length) {
@@ -446,14 +432,13 @@
      * Reads a 64-bit double from the current position in this file. Blocks
      * until eight bytes have been read, the end of the file is reached or an
      * exception is thrown.
-     * 
+     *
      * @return the next double value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeDouble(double)
-     * @since Android 1.0
      */
     public final double readDouble() throws IOException {
         return Double.longBitsToDouble(readLong());
@@ -463,14 +448,13 @@
      * Reads a 32-bit float from the current position in this file. Blocks
      * until four bytes have been read, the end of the file is reached or an
      * exception is thrown.
-     * 
+     *
      * @return the next float value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeFloat(float)
-     * @since Android 1.0
      */
     public final float readFloat() throws IOException {
         return Float.intBitsToFloat(readInt());
@@ -480,7 +464,7 @@
      * Reads bytes from this file into {@code buffer}. Blocks until {@code
      * buffer.length} number of bytes have been read, the end of the file is
      * reached or an exception is thrown.
-     * 
+     *
      * @param buffer
      *            the buffer to read bytes into.
      * @throws EOFException
@@ -489,7 +473,6 @@
      *             if this file is closed or another I/O error occurs.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0             
      */
     public final void readFully(byte[] buffer) throws IOException {
         readFully(buffer, 0, buffer.length);
@@ -499,7 +482,7 @@
      * Read bytes from this file into {@code buffer} starting at offset {@code
      * offset}. This method blocks until {@code count} number of bytes have been
      * read.
-     * 
+     *
      * @param buffer
      *            the buffer to read bytes into.
      * @param offset
@@ -516,7 +499,6 @@
      *             if this file is closed or another I/O error occurs.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     public final void readFully(byte[] buffer, int offset, int count)
             throws IOException {
@@ -547,14 +529,13 @@
      * Reads a 32-bit integer from the current position in this file. Blocks
      * until four bytes have been read, the end of the file is reached or an
      * exception is thrown.
-     * 
+     *
      * @return the next int value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeInt(int)
-     * @since Android 1.0
      */
     public final int readInt() throws IOException {
         byte[] buffer = new byte[4];
@@ -573,13 +554,11 @@
      * <p>
      * Blocks until a line terminating sequence has been read, the end of the
      * file is reached or an exception is thrown.
-     * </p>
-     * 
+     *
      * @return the contents of the line or {@code null} if no characters have
      *         been read before the end of the file has been reached.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public final String readLine() throws IOException {
         StringBuilder line = new StringBuilder(80); // Typical line length
@@ -615,14 +594,13 @@
      * Reads a 64-bit long from the current position in this file. Blocks until
      * eight bytes have been read, the end of the file is reached or an
      * exception is thrown.
-     * 
+     *
      * @return the next long value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeLong(long)
-     * @since Android 1.0
      */
     public final long readLong() throws IOException {
         byte[] buffer = new byte[8];
@@ -641,14 +619,13 @@
      * Reads a 16-bit short from the current position in this file. Blocks until
      * two bytes have been read, the end of the file is reached or an exception
      * is thrown.
-     * 
+     *
      * @return the next short value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeShort(int)
-     * @since Android 1.0
      */
     public final short readShort() throws IOException {
         byte[] buffer = new byte[2];
@@ -662,14 +639,13 @@
      * Reads an unsigned 8-bit byte from the current position in this file and
      * returns it as an integer. Blocks until one byte has been read, the end of
      * the file is reached or an exception is thrown.
-     * 
+     *
      * @return the next unsigned byte value from this file as an int.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeByte(int)
-     * @since Android 1.0
      */
     public final int readUnsignedByte() throws IOException {
         int temp = this.read();
@@ -683,14 +659,13 @@
      * Reads an unsigned 16-bit short from the current position in this file and
      * returns it as an integer. Blocks until two bytes have been read, the end of
      * the file is reached or an exception is thrown.
-     * 
+     *
      * @return the next unsigned short value from this file as an int.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeShort(int)
-     * @since Android 1.0
      */
     public final int readUnsignedShort() throws IOException {
         byte[] buffer = new byte[2];
@@ -706,7 +681,7 @@
      * is determined by the first two bytes read from the file. Blocks until all
      * required bytes have been read, the end of the file is reached or an
      * exception is thrown.
-     * 
+     *
      * @return the next string encoded in {@link DataInput modified UTF-8} from
      *         this file.
      * @throws EOFException
@@ -716,7 +691,6 @@
      * @throws UTFDataFormatException
      *             if the bytes read cannot be decoded into a character string.
      * @see #writeUTF(String)
-     * @since Android 1.0
      */
     public final String readUTF() throws IOException {
         int utfSize = readUnsignedShort();
@@ -736,13 +710,12 @@
      * position may be greater than the current length of the file, but the
      * file's length will only change if the moving of the pointer is followed
      * by a {@code write} operation.
-     * 
+     *
      * @param pos
      *            the new file pointer position.
      * @throws IOException
      *             if this file is closed, {@code pos < 0} or another I/O error
      *             occurs.
-     * @since Android 1.0
      */
     public void seek(long pos) throws IOException {
         if (pos < 0) {
@@ -761,14 +734,13 @@
      * file to the new end are undefined. The file is truncated if its current
      * size is bigger than {@code newLength}. If the current file pointer
      * position is in the truncated part, it is set to the end of the file.
-     * 
+     *
      * @param newLength
      *            the new file length in bytes.
      * @throws IllegalArgumentException
      *             if {@code newLength < 0}.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public void setLength(long newLength) throws IOException {
         openCheck();
@@ -793,13 +765,12 @@
      * bytes are skipped if the end of the file is reached or an exception is
      * thrown during the operation. Nothing is done if {@code count} is
      * negative.
-     * 
+     *
      * @param count
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int skipBytes(int count) throws IOException {
         if (count > 0) {
@@ -815,7 +786,7 @@
     /**
      * Writes the entire contents of the byte array {@code buffer} to this file,
      * starting at the current file pointer.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @throws IOException
@@ -824,7 +795,6 @@
      * @see #read(byte[],int,int)
      * @see #readFully(byte[])
      * @see #readFully(byte[],int,int)
-     * @since Android 1.0
      */
     public void write(byte[] buffer) throws IOException {
         write(buffer, 0, buffer.length);
@@ -834,7 +804,7 @@
      * Writes {@code count} bytes from the byte array {@code buffer} to this
      * file, starting at the current file pointer and using {@code offset} as
      * the first position within {@code buffer} to get bytes.
-     * 
+     *
      * @param buffer
      *            the buffer to write to this file.
      * @param offset
@@ -848,7 +818,6 @@
      *             if an I/O error occurs while writing to this file.
      * @see #read(byte[], int, int)
      * @see #readFully(byte[], int, int)
-     * @since Android 1.0
      */
     public void write(byte[] buffer, int offset, int count) throws IOException {
         // BEGIN android-changed
@@ -883,13 +852,12 @@
     /**
      * Writes a byte to this file, starting at the current file pointer. Only
      * the least significant byte of the integer {@code oneByte} is written.
-     * 
+     *
      * @param oneByte
      *            the byte to write to this file.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #read()
-     * @since Android 1.0
      */
     public void write(int oneByte) throws IOException {
         openCheck();
@@ -907,13 +875,12 @@
 
     /**
      * Writes a boolean to this file, starting at the current file pointer.
-     * 
+     *
      * @param val
      *            the boolean to write to this file.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #readBoolean()
-     * @since Android 1.0
      */
     public final void writeBoolean(boolean val) throws IOException {
         write(val ? 1 : 0);
@@ -922,14 +889,13 @@
     /**
      * Writes an 8-bit byte to this file, starting at the current file pointer.
      * Only the least significant byte of the integer {@code val} is written.
-     * 
+     *
      * @param val
      *            the byte to write to this file.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #readByte()
      * @see #readUnsignedByte()
-     * @since Android 1.0
      */
     public final void writeByte(int val) throws IOException {
         write(val & 0xFF);
@@ -938,7 +904,7 @@
     /**
      * Writes the low order 8-bit bytes from a string to this file, starting at
      * the current file pointer.
-     * 
+     *
      * @param str
      *            the string containing the bytes to write to this file
      * @throws IOException
@@ -947,7 +913,6 @@
      * @see #read(byte[],int,int)
      * @see #readFully(byte[])
      * @see #readFully(byte[],int,int)
-     * @since Android 1.0
      */
     public final void writeBytes(String str) throws IOException {
         byte bytes[] = new byte[str.length()];
@@ -957,18 +922,16 @@
         write(bytes);
     }
 
-
     /**
      * Writes a 16-bit character to this file, starting at the current file
      * pointer. Only the two least significant bytes of the integer {@code val}
      * are written, with the high byte first.
-     * 
+     *
      * @param val
      *            the char to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readChar()
-     * @since Android 1.0
      */
     public final void writeChar(int val) throws IOException {
         byte[] buffer = new byte[2];
@@ -981,13 +944,12 @@
      * Writes the 16-bit characters from a string to this file, starting at the
      * current file pointer. Each character is written in the same way as with
      * {@link #writeChar(int)}, with its high byte first.
-     * 
+     *
      * @param str
      *            the string to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readChar()
-     * @since Android 1.0
      */
     public final void writeChars(String str) throws IOException {
         byte newBytes[] = new byte[str.length() * 2];
@@ -1003,13 +965,12 @@
      * Writes a 64-bit double to this file, starting at the current file
      * pointer. The eight bytes returned by
      * {@link Double#doubleToLongBits(double)} are written to this file.
-     * 
+     *
      * @param val
      *            the double to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readDouble()
-     * @since Android 1.0
      */
     public final void writeDouble(double val) throws IOException {
         writeLong(Double.doubleToLongBits(val));
@@ -1019,13 +980,12 @@
      * Writes a 32-bit float to this file, starting at the current file pointer.
      * The four bytes returned by {@link Float#floatToIntBits(float)} are
      * written to this file.
-     * 
+     *
      * @param val
      *            the float to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readFloat()
-     * @since Android 1.0
      */
     public final void writeFloat(float val) throws IOException {
         writeInt(Float.floatToIntBits(val));
@@ -1035,13 +995,12 @@
      * Writes a 32-bit integer to this file, starting at the current file
      * pointer. The four bytes of the integer are written with the highest byte
      * first.
-     * 
+     *
      * @param val
      *            the int to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readInt()
-     * @since Android 1.0
      */
     public final void writeInt(int val) throws IOException {
         byte[] buffer = new byte[4];
@@ -1056,13 +1015,12 @@
      * Writes a 64-bit long to this file, starting at the current file
      * pointer. The eight bytes of the long are written with the highest byte
      * first.
-     * 
+     *
      * @param val
      *            the long to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readLong()
-     * @since Android 1.0
      */
     public final void writeLong(long val) throws IOException {
         byte[] buffer = new byte[8];
@@ -1082,13 +1040,13 @@
      * Writes a 16-bit short to this file, starting at the current file
      * pointer. Only the two least significant bytes of the integer {@code val}
      * are written, with the high byte first.
-     * 
+     *
      * @param val
      *            the short to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readShort()
-     * @since Android 1.0
+     * @see DataInput#readUnsignedShort()
      */
     public final void writeShort(int val) throws IOException {
         writeChar(val);
@@ -1097,7 +1055,7 @@
     /**
      * Writes a string encoded with {@link DataInput modified UTF-8} to this
      * file, starting at the current file pointer.
-     * 
+     *
      * @param str
      *            the string to write in {@link DataInput modified UTF-8}
      *            format.
@@ -1106,7 +1064,6 @@
      * @throws UTFDataFormatException
      *             if the encoded string is longer than 65535 bytes.
      * @see #readUTF()
-     * @since Android 1.0
      */
     public final void writeUTF(String str) throws IOException {
         int utfCount = 0, length = str.length();
diff --git a/luni/src/main/java/java/io/Reader.java b/luni/src/main/java/java/io/Reader.java
index 42fb9ee..1f78f5a 100644
--- a/luni/src/main/java/java/io/Reader.java
+++ b/luni/src/main/java/java/io/Reader.java
@@ -33,24 +33,18 @@
  * <p>
  * Many specialized readers for purposes like reading from a file already exist
  * in this package.
- * 
+ *
  * @see Writer
- * 
- * @since Android 1.0
  */
 public abstract class Reader implements Readable, Closeable {
     /**
      * The object used to synchronize access to the reader.
-     * 
-     * @since Android 1.0
      */
     protected Object lock;
 
     /**
      * Constructs a new {@code Reader} with {@code this} as the object used to
      * synchronize critical sections.
-     * 
-     * @since Android 1.0
      */
     protected Reader() {
         super();
@@ -60,12 +54,11 @@
     /**
      * Constructs a new {@code Reader} with {@code lock} used to synchronize
      * critical sections.
-     * 
+     *
      * @param lock
      *            the {@code Object} used to synchronize critical sections.
      * @throws NullPointerException
      *             if {@code lock} is {@code null}.
-     * @since Android 1.0
      */
     protected Reader(Object lock) {
         if (lock == null) {
@@ -77,10 +70,9 @@
     /**
      * Closes this reader. Implementations of this method should free any
      * resources associated with the reader.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this reader.
-     * @since Android 1.0
      */
     public abstract void close() throws IOException;
 
@@ -92,8 +84,7 @@
      * <p>
      * This default implementation simply throws an {@code IOException};
      * subclasses must provide their own implementation.
-     * </p>
-     * 
+     *
      * @param readLimit
      *            the number of characters that can be read before the mark is
      *            invalidated.
@@ -103,7 +94,6 @@
      *             if an error occurs while setting a mark in this reader.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     public void mark(int readLimit) throws IOException {
         throw new IOException();
@@ -113,9 +103,8 @@
      * Indicates whether this reader supports the {@code mark()} and
      * {@code reset()} methods. This default implementation returns
      * {@code false}.
-     * 
+     *
      * @return always {@code false}.
-     * @since Android 1.0
      */
     public boolean markSupported() {
         return false;
@@ -125,12 +114,11 @@
      * Reads a single character from this reader and returns it as an integer
      * with the two higher-order bytes set to 0. Returns -1 if the end of the
      * reader has been reached.
-     * 
+     *
      * @return the character read or -1 if the end of the reader has been
      *         reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     public int read() throws IOException {
         synchronized (lock) {
@@ -146,14 +134,13 @@
      * Reads characters from this reader and stores them in the character array
      * {@code buf} starting at offset 0. Returns the number of characters
      * actually read or -1 if the end of the reader has been reached.
-     * 
+     *
      * @param buf
      *            character array to store the characters read.
      * @return the number of characters read or -1 if the end of the reader has
      *         been reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     public int read(char[] buf) throws IOException {
         // BEGIN android-note
@@ -167,7 +154,7 @@
      * at {@code offset} in the character array {@code buf}. Returns the number
      * of characters actually read or -1 if the end of the reader has been
      * reached.
-     * 
+     *
      * @param buf
      *            the character array to store the characters read.
      * @param offset
@@ -179,7 +166,6 @@
      *         been reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     public abstract int read(char[] buf, int offset, int count)
             throws IOException;
@@ -192,14 +178,13 @@
      * Returns {@code true} if this reader will not block when {@code read} is
      * called, {@code false} if unknown or blocking will occur. This default
      * implementation always returns {@code false}.
-     * 
+     *
      * @return always {@code false}.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
      * @see #read()
      * @see #read(char[])
      * @see #read(char[], int, int)
-     * @since Android 1.0
      */
     public boolean ready() throws IOException {
         return false;
@@ -211,12 +196,11 @@
      * location. If this reader has not been marked, the behavior of
      * {@code reset()} is implementation specific. This default
      * implementation throws an {@code IOException}.
-     * 
+     *
      * @throws IOException
      *             always thrown in this default implementation.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     public void reset() throws IOException {
         throw new IOException();
@@ -227,7 +211,7 @@
      * {@code read} methods will not return these characters unless {@code
      * reset()} is used. This method may perform multiple reads to read {@code
      * count} characters.
-     * 
+     *
      * @param count
      *            the maximum number of characters to skip.
      * @return the number of characters actually skipped.
@@ -238,7 +222,6 @@
      * @see #mark(int)
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     public long skip(long count) throws IOException {
         if (count < 0) {
@@ -267,7 +250,7 @@
 
     /**
      * Reads characters and puts them into the {@code target} character buffer.
-     * 
+     *
      * @param target
      *            the destination character buffer.
      * @return the number of characters put into {@code target} or -1 if the end
@@ -278,7 +261,6 @@
      *             if {@code target} is {@code null}.
      * @throws ReadOnlyBufferException
      *             if {@code target} is read-only.
-     * @since Android 1.0
      */
     public int read(CharBuffer target) throws IOException {
         if (null == target) {
diff --git a/luni/src/main/java/java/io/SequenceInputStream.java b/luni/src/main/java/java/io/SequenceInputStream.java
index 1b946b5..3719021 100644
--- a/luni/src/main/java/java/io/SequenceInputStream.java
+++ b/luni/src/main/java/java/io/SequenceInputStream.java
@@ -28,8 +28,6 @@
  * Concatenates two or more existing {@link InputStream}s. Reads are taken from
  * the first stream until it ends, then the next stream is used, until the last
  * stream returns end of file.
- * 
- * @since Android 1.0
  */
 public class SequenceInputStream extends InputStream {
     /**
@@ -45,14 +43,13 @@
     /**
      * Constructs a new {@code SequenceInputStream} using the two streams
      * {@code s1} and {@code s2} as the sequence of streams to read from.
-     * 
+     *
      * @param s1
      *            the first stream to get bytes from.
      * @param s2
      *            the second stream to get bytes from.
      * @throws NullPointerException
      *             if {@code s1} is {@code null}.
-     * @since Android 1.0
      */
     public SequenceInputStream(InputStream s1, InputStream s2) {
         if (s1 == null) {
@@ -68,12 +65,11 @@
      * Constructs a new SequenceInputStream using the elements returned from
      * Enumeration {@code e} as the stream sequence. The instances returned by
      * {@code e.nextElement()} must be of type {@link InputStream}.
-     * 
+     *
      * @param e
      *            the enumeration of {@code InputStreams} to get bytes from.
      * @throws NullPointerException
      *             if any of the elements in {@code e} is {@code null}.
-     * @since Android 1.0
      */
     public SequenceInputStream(Enumeration<? extends InputStream> e) {
         this.e = e;
@@ -87,12 +83,11 @@
 
     /**
      * Returns the number of bytes that are available before the current input stream will
-     * block. 
-     * 
+     * block.
+     *
      * @return the number of bytes available in the current input stream before blocking.
      * @throws IOException
      *             if an I/O error occurs in the current input stream.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -103,11 +98,10 @@
     }
 
     /**
-     * Closes all streams in this sequence of input stream. 
-     * 
+     * Closes all streams in this sequence of input stream.
+     *
      * @throws IOException
      *             if an error occurs while closing any of the input streams.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -119,7 +113,7 @@
 
     /**
      * Sets up the next InputStream or leaves it alone if there are none left.
-     * 
+     *
      * @throws IOException
      */
     private void nextStream() throws IOException {
@@ -142,14 +136,13 @@
      * stream first; if the end of this stream has been reached, it reads from
      * the next one. Blocks until one byte has been read, the end of the last
      * input stream in the sequence has been reached, or an exception is thrown.
-     * 
+     *
      * @return the byte read or -1 if either the end of the last stream in the
      *         sequence has been reached or this input stream sequence is
      *         closed.
      * @throws IOException
      *             if an error occurs while reading the current source input
      *             stream.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -179,7 +172,7 @@
      * If a substream has already reached the end when this call is made, it
      * will close that substream and start with the next one. If there are no
      * more substreams it will return -1.
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read.
      * @param offset
@@ -197,7 +190,6 @@
      *             if an I/O error occurs.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int count) throws IOException {
diff --git a/luni/src/main/java/java/io/Serializable.java b/luni/src/main/java/java/io/Serializable.java
index 17690e3..9cd7816 100644
--- a/luni/src/main/java/java/io/Serializable.java
+++ b/luni/src/main/java/java/io/Serializable.java
@@ -28,13 +28,9 @@
  * <p>
  * {@code private void writeObject(java.io.ObjectOutputStream out) throws
  * IOException}
- * </p>
  * <p>
  * {@code private void readObject(java.io.ObjectInputStream in) throws
  * IOException, ClassNotFoundException}
- * </p>
- * 
- * @since Android 1.0
  */
 public interface Serializable {
     /* empty */
diff --git a/luni/src/main/java/java/io/StreamCorruptedException.java b/luni/src/main/java/java/io/StreamCorruptedException.java
index 1181507..9d25727 100644
--- a/luni/src/main/java/java/io/StreamCorruptedException.java
+++ b/luni/src/main/java/java/io/StreamCorruptedException.java
@@ -25,8 +25,6 @@
  * 
  * @see ObjectInputStream
  * @see OptionalDataException
- * 
- * @since Android 1.0
  */
 public class StreamCorruptedException extends ObjectStreamException {
 
@@ -35,8 +33,6 @@
     /**
      * Constructs a new {@code StreamCorruptedException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public StreamCorruptedException() {
         super();
@@ -48,7 +44,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public StreamCorruptedException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/StreamTokenizer.java b/luni/src/main/java/java/io/StreamTokenizer.java
index 391fca8..d39e5a8 100644
--- a/luni/src/main/java/java/io/StreamTokenizer.java
+++ b/luni/src/main/java/java/io/StreamTokenizer.java
@@ -23,51 +23,37 @@
  * and different comment styles. The class can be used for limited processing
  * of source code of programming languages like Java, although it is nowhere
  * near a full parser.
- * 
- * @since Android 1.0
  */
 public class StreamTokenizer {
     /**
      * Contains a number if the current token is a number ({@code ttype} ==
      * {@code TT_NUMBER}).
-     * 
-     * @since Android 1.0
      */
     public double nval;
 
     /**
      * Contains a string if the current token is a word ({@code ttype} ==
      * {@code TT_WORD}).
-     * 
-     * @since Android 1.0
      */
     public String sval;
 
     /**
      * The constant representing the end of the stream.
-     * 
-     * @since Android 1.0
      */
     public static final int TT_EOF = -1;
 
     /**
      * The constant representing the end of the line.
-     * 
-     * @since Android 1.0
      */
     public static final int TT_EOL = '\n';
 
     /**
      * The constant representing a number token.
-     * 
-     * @since Android 1.0
      */
     public static final int TT_NUMBER = -2;
 
     /**
      * The constant representing a word token.
-     * 
-     * @since Android 1.0
      */
     public static final int TT_WORD = -3;
 
@@ -89,8 +75,6 @@
      * whether {@code eolIsSignificant} is {@code true}.</li>
      * <li> {@code TT_EOF} - the end of the stream has been reached.</li>
      * </ul>
-     * 
-     * @since Android 1.0
      */
     public int ttype = TT_UNKNOWN;
 
@@ -135,7 +119,7 @@
      * specification.
      */
     private StreamTokenizer() {
-        /**
+        /*
          * Initialize the default state per specification. All byte values 'A'
          * through 'Z', 'a' through 'z', and '\u00A0' through '\u00FF' are
          * considered to be alphabetic.
@@ -176,7 +160,6 @@
      * @throws NullPointerException
      *             if {@code is} is {@code null}.
      * @deprecated Use {@link #StreamTokenizer(Reader)}
-     * @since Android 1.0
      */
     @Deprecated
     public StreamTokenizer(InputStream is) {
@@ -205,7 +188,6 @@
      * 
      * @param r
      *            the source reader from which to parse tokens.
-     * @since Android 1.0
      */
     public StreamTokenizer(Reader r) {
         this();
@@ -221,7 +203,6 @@
      * 
      * @param ch
      *            the character to be considered a comment character.
-     * @since Android 1.0
      */
     public void commentChar(int ch) {
         if (0 <= ch && ch < tokenTypes.length) {
@@ -235,7 +216,6 @@
      * 
      * @param flag
      *            {@code true} if EOL is significant, {@code false} otherwise.
-     * @since Android 1.0
      */
     public void eolIsSignificant(boolean flag) {
         isEOLSignificant = flag;
@@ -245,7 +225,6 @@
      * Returns the current line number.
      * 
      * @return this tokenizer's current line number.
-     * @since Android 1.0
      */
     public int lineno() {
         return lineNumber;
@@ -258,7 +237,6 @@
      * @param flag
      *            {@code true} if {@code sval} should be converted to lower
      *            case, {@code false} otherwise.
-     * @since Android 1.0
      */
     public void lowerCaseMode(boolean flag) {
         forceLowercase = flag;
@@ -272,7 +250,6 @@
      * @return the value of {@code ttype}.
      * @throws IOException
      *             if an I/O error occurs while parsing the next token.
-     * @since Android 1.0             
      */
     public int nextToken() throws IOException {
         if (pushBackToken) {
@@ -507,7 +484,6 @@
      * 
      * @param ch
      *            the character to be considered an ordinary character.
-     * @since Android 1.0
      */
     public void ordinaryChar(int ch) {
         if (0 <= ch && ch < tokenTypes.length) {
@@ -525,7 +501,6 @@
      *            the first character in the range of ordinary characters.
      * @param hi
      *            the last character in the range of ordinary characters.
-     * @since Android 1.0
      */
     public void ordinaryChars(int low, int hi) {
         if (low < 0) {
@@ -541,8 +516,6 @@
 
     /**
      * Specifies that this tokenizer shall parse numbers.
-     * 
-     * @since Android 1.0
      */
     public void parseNumbers() {
         for (int i = '0'; i <= '9'; i++) {
@@ -555,8 +528,6 @@
     /**
      * Indicates that the current token should be pushed back and returned again
      * the next time {@code nextToken()} is called.
-     * 
-     * @since Android 1.0
      */
     public void pushBack() {
         pushBackToken = true;
@@ -568,7 +539,6 @@
      * 
      * @param ch
      *            the character to be considered a quote character.
-     * @since Android 1.0
      */
     public void quoteChar(int ch) {
         if (0 <= ch && ch < tokenTypes.length) {
@@ -586,8 +556,6 @@
 
     /**
      * Specifies that all characters shall be treated as ordinary characters.
-     * 
-     * @since Android 1.0
      */
     public void resetSyntax() {
         for (int i = 0; i < 256; i++) {
@@ -602,7 +570,6 @@
      * @param flag
      *            {@code true} if {@code //} should be recognized as the start
      *            of a comment, {@code false} otherwise.
-     * @since Android 1.0
      */
     public void slashSlashComments(boolean flag) {
         slashSlashComments = flag;
@@ -616,7 +583,6 @@
      * @param flag
      *            {@code true} if {@code /*} should be recognized as the start
      *            of a comment, {@code false} otherwise.
-     * @since Android 1.0
      */
     public void slashStarComments(boolean flag) {
         slashStarComments = flag;
@@ -626,7 +592,6 @@
      * Returns the state of this tokenizer in a readable format.
      * 
      * @return the current state of this tokenizer.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -648,8 +613,6 @@
                 result.append(sval);
                 break;
             default:
-                // BEGIN android-changed
-                // copied from a newer version of harmony
                 if (ttype == TT_UNKNOWN || tokenTypes[ttype] == TOKEN_QUOTE) {
                     result.append(sval);
                 } else {
@@ -657,7 +620,6 @@
                     result.append((char) ttype);
                     result.append('\'');
                 }
-                // END android-changed
         }
         result.append("], line "); //$NON-NLS-1$
         result.append(lineNumber);
@@ -672,7 +634,6 @@
      *            the first character in the range of whitespace characters.
      * @param hi
      *            the last character in the range of whitespace characters.
-     * @since Android 1.0
      */
     public void whitespaceChars(int low, int hi) {
         if (low < 0) {
@@ -695,7 +656,6 @@
      *            the first character in the range of word characters.
      * @param hi
      *            the last character in the range of word characters.
-     * @since Android 1.0
      */
     public void wordChars(int low, int hi) {
         if (low < 0) {
diff --git a/luni/src/main/java/java/io/StringBufferInputStream.java b/luni/src/main/java/java/io/StringBufferInputStream.java
index 6e20ab6..cc4ab81 100644
--- a/luni/src/main/java/java/io/StringBufferInputStream.java
+++ b/luni/src/main/java/java/io/StringBufferInputStream.java
@@ -22,31 +22,23 @@
 /**
  * A specialized {@link InputStream} that reads bytes from a {@code String} in
  * a sequential manner.
- * 
+ *
  * @deprecated Use {@link StringReader}
- * 
- * @since Android 1.0
  */
 @Deprecated
 public class StringBufferInputStream extends InputStream {
     /**
      * The source string containing the data to read.
-     * 
-     * @since Android 1.0
      */
     protected String buffer;
 
     /**
      * The total number of characters in the source string.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
     /**
      * The current position within the source string.
-     * 
-     * @since Android 1.0
      */
     protected int pos;
 
@@ -54,12 +46,11 @@
      * Construct a new {@code StringBufferInputStream} with {@code str} as
      * source. The size of the stream is set to the {@code length()} of the
      * string.
-     * 
+     *
      * @param str
      *            the source string for this stream.
      * @throws NullPointerException
      *             if {@code str} is {@code null}.
-     * @since Android 1.0
      */
     public StringBufferInputStream(String str) {
         if (str == null) {
@@ -72,9 +63,8 @@
     /**
      * Returns the number of bytes that are available before this stream will
      * block.
-     * 
+     *
      * @return the number of bytes available before blocking.
-     * @since Android 1.0
      */
     @Override
     public synchronized int available() {
@@ -85,10 +75,9 @@
      * Reads a single byte from the source string and returns it as an integer
      * in the range from 0 to 255. Returns -1 if the end of the source string
      * has been reached.
-     * 
+     *
      * @return the byte read or -1 if the end of the source string has been
      *         reached.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read() {
@@ -98,7 +87,7 @@
     /**
      * Reads at most {@code length} bytes from the source string and stores them
      * in the byte array {@code b} starting at {@code offset}.
-     * 
+     *
      * @param b
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -114,7 +103,6 @@
      *             {@code b}.
      * @throws NullPointerException
      *             if {@code b} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read(byte[] b, int offset, int length) {
@@ -153,8 +141,6 @@
 
     /**
      * Resets this stream to the beginning of the source string.
-     * 
-     * @since Android 1.0
      */
     @Override
     public synchronized void reset() {
@@ -166,11 +152,10 @@
      * returns 0 if {@code n} is negative. Less than {@code n} characters are
      * skipped if the end of the source string is reached before the operation
      * completes.
-     * 
+     *
      * @param n
      *            the number of characters to skip.
      * @return the number of characters actually skipped.
-     * @since Android 1.0
      */
     @Override
     public synchronized long skip(long n) {
diff --git a/luni/src/main/java/java/io/StringReader.java b/luni/src/main/java/java/io/StringReader.java
index 3a19429..0a9e9bb 100644
--- a/luni/src/main/java/java/io/StringReader.java
+++ b/luni/src/main/java/java/io/StringReader.java
@@ -22,10 +22,8 @@
 /**
  * A specialized {@link Reader} that reads characters from a {@code String} in
  * a sequential manner.
- * 
+ *
  * @see StringWriter
- * 
- * @since Android 1.0
  */
 public class StringReader extends Reader {
     private String str;
@@ -40,13 +38,12 @@
      * Construct a new {@code StringReader} with {@code str} as source. The size
      * of the reader is set to the {@code length()} of the string and the Object
      * to synchronize access through is set to {@code str}.
-     * 
+     *
      * @param str
      *            the source string for this reader.
-     * @since Android 1.0
      */
     public StringReader(String str) {
-        super(str);
+        super();
         this.str = str;
         this.count = str.length();
     }
@@ -55,22 +52,15 @@
      * Closes this reader. Once it is closed, read operations on this reader
      * will throw an {@code IOException}. Only the first invocation of this
      * method has any effect.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void close() {
-        synchronized (lock) {
-            if (isClosed()) {
-                return;
-            }
-            str = null;
-        }
+        str = null;
     }
 
     /**
      * Returns a boolean indicating whether this reader is closed.
-     * 
+     *
      * @return {@code true} if closed, otherwise {@code false}.
      */
     private boolean isClosed() {
@@ -81,7 +71,7 @@
      * Sets a mark position in this reader. The parameter {@code readLimit} is
      * ignored for this class. Calling {@code reset()} will reposition the
      * reader back to the marked position.
-     * 
+     *
      * @param readLimit
      *            ignored for {@code StringReader} instances.
      * @throws IllegalArgumentException
@@ -90,7 +80,6 @@
      *             if this reader is closed.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public void mark(int readLimit) throws IOException {
@@ -109,9 +98,8 @@
     /**
      * Indicates whether this reader supports the {@code mark()} and {@code
      * reset()} methods. This implementation returns {@code true}.
-     * 
+     *
      * @return always {@code true}.
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -122,12 +110,11 @@
      * Reads a single character from the source string and returns it as an
      * integer with the two higher-order bytes set to 0. Returns -1 if the end
      * of the source string has been reached.
-     * 
+     *
      * @return the character read or -1 if the end of the source string has been
      *         reached.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -147,7 +134,7 @@
      * them at {@code offset} in the character array {@code buf}. Returns the
      * number of characters actually read or -1 if the end of the source string
      * has been reached.
-     * 
+     *
      * @param buf
      *            the character array to store the characters read.
      * @param offset
@@ -162,14 +149,12 @@
      *             {@code offset + len} is greater than the size of {@code buf}.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buf, int offset, int len) throws IOException {
         // BEGIN android-note
         // changed array notation to be consistent with the rest of harmony
         // END android-note
-        // avoid int overflow
         // BEGIN android-changed
         // Exception priorities (in case of multiple errors) differ from
         // RI, but are spec-compliant.
@@ -178,14 +163,18 @@
         if (buf == null) {
             throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
         }
-        if ((offset | len) < 0 || len > buf.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
-        }
-        // END android-changed
         synchronized (lock) {
+            // avoid int overflow
+            if ((offset | len) < 0 || len > buf.length - offset) {
+                throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+            }
+            // END android-changed
             if (isClosed()) {
                 throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
             }
+            if (len == 0) {
+                return 0;
+            }
             if (pos == this.count) {
                 return -1;
             }
@@ -200,13 +189,12 @@
     /**
      * Indicates whether this reader is ready to be read without blocking. This
      * implementation always returns {@code true}.
-     * 
+     *
      * @return always {@code true}.
      * @throws IOException
      *             if this reader is closed.
      * @see #read()
      * @see #read(char[], int, int)
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -223,12 +211,11 @@
      * Invocations of {@code read()} and {@code skip()} will occur from this new
      * location. If this reader has not been marked, it is reset to the
      * beginning of the source string.
-     * 
+     *
      * @throws IOException
      *             if this reader is closed.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -244,7 +231,7 @@
      * Skips {@code amount} characters in the source string. Subsequent calls of
      * {@code read} methods will not return these characters unless {@code
      * reset()} is used.
-     * 
+     *
      * @param ns
      *            the maximum number of characters to skip.
      * @return the number of characters actually skipped or 0 if {@code ns < 0}.
@@ -253,7 +240,6 @@
      * @see #mark(int)
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public long skip(long ns) throws IOException {
diff --git a/luni/src/main/java/java/io/StringWriter.java b/luni/src/main/java/java/io/StringWriter.java
index 01a6db8..45f6c16 100644
--- a/luni/src/main/java/java/io/StringWriter.java
+++ b/luni/src/main/java/java/io/StringWriter.java
@@ -26,10 +26,8 @@
  * in a sequential manner, appending them in the process. The result can later
  * be queried using the {@link #StringWriter(int)} or {@link #toString()}
  * methods.
- * 
+ *
  * @see StringReader
- * 
- * @since Android 1.0
  */
 public class StringWriter extends Writer {
 
@@ -40,8 +38,6 @@
      * allocated with the default size of 16 characters. The {@code
      * StringBuffer} is also the {@code lock} used to synchronize access to this
      * writer.
-     * 
-     * @since Android 1.0
      */
     public StringWriter() {
         super();
@@ -54,10 +50,9 @@
      * allocated with a size of {@code initialSize} characters. The {@code
      * StringBuffer} is also the {@code lock} used to synchronize access to this
      * writer.
-     * 
+     *
      * @param initialSize
      *            the intial size of the target string buffer.
-     * @since Android 1.0
      */
     public StringWriter(int initialSize) {
         if (initialSize < 0) {
@@ -71,10 +66,9 @@
      * Calling this method has no effect. In contrast to most {@code Writer} subclasses,
      * the other methods in {@code StringWriter} do not throw an {@code IOException} if
      * {@code close()} has been called.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this writer.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -83,8 +77,6 @@
 
     /**
      * Calling this method has no effect.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void flush() {
@@ -94,33 +86,27 @@
     /**
      * Gets a reference to this writer's internal {@link StringBuffer}. Any
      * changes made to the returned buffer are reflected in this writer.
-     * 
+     *
      * @return a reference to this writer's internal {@code StringBuffer}.
-     * @since Android 1.0
      */
     public StringBuffer getBuffer() {
-        synchronized (lock) {
-            return buf;
-        }
+        return buf;
     }
 
     /**
      * Gets a copy of the contents of this writer as a string.
-     * 
+     *
      * @return this writer's contents as a string.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
-        synchronized (lock) {
-            return buf.toString();
-        }
+        return buf.toString();
     }
 
     /**
      * Writes {@code count} characters starting at {@code offset} in {@code buf}
      * to this writer's {@code StringBuffer}.
-     * 
+     *
      * @param cbuf
      *            the non-null character array to write.
      * @param offset
@@ -130,7 +116,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is greater than the size of {@code buf}.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] cbuf, int offset, int count) {
@@ -147,45 +132,40 @@
             throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
         }
         // END android-changed
-        synchronized (lock) {
-            this.buf.append(cbuf, offset, count);
+        if (count == 0) {
+            return;
         }
+        buf.append(cbuf, offset, count);
     }
 
     /**
      * Writes one character to this writer's {@code StringBuffer}. Only the two
      * least significant bytes of the integer {@code oneChar} are written.
-     * 
+     *
      * @param oneChar
      *            the character to write to this writer's {@code StringBuffer}.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) {
-        synchronized (lock) {
-            buf.append((char) oneChar);
-        }
+        buf.append((char) oneChar);
     }
 
     /**
      * Writes the characters from the specified string to this writer's {@code
      * StringBuffer}.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
-     * @since Android 1.0
      */
     @Override
     public void write(String str) {
-        synchronized (lock) {
-            buf.append(str);
-        }
+        buf.append(str);
     }
 
     /**
      * Writes {@code count} characters from {@code str} starting at {@code
      * offset} to this writer's {@code StringBuffer}.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
      * @param offset
@@ -195,24 +175,20 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is greater than the length of {@code str}.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int count) {
         String sub = str.substring(offset, offset + count);
-        synchronized (lock) {
-            buf.append(sub);
-        }
+        buf.append(sub);
     }
 
     /**
      * Appends the character {@code c} to this writer's {@code StringBuffer}.
      * This method works the same way as {@link #write(int)}.
-     * 
+     *
      * @param c
      *            the character to append to the target stream.
      * @return this writer.
-     * @since Android 1.0
      */
     @Override
     public StringWriter append(char c) {
@@ -225,18 +201,17 @@
      * StringBuffer}. This method works the same way as {@code
      * StringWriter.write(csq.toString())}. If {@code csq} is {@code null}, then
      * the string "null" is written to the target stream.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @return this writer.
-     * @since Android 1.0
      */
     @Override
     public StringWriter append(CharSequence csq) {
         if (null == csq) {
-            append(TOKEN_NULL, 0, TOKEN_NULL.length());
+            write(TOKEN_NULL);
         } else {
-            append(csq, 0, csq.length());
+            write(csq.toString());
         }
         return this;
     }
@@ -247,7 +222,7 @@
      * StringWriter.writer(csq.subsequence(start, end).toString())}. If {@code
      * csq} is {@code null}, then the specified subsequence of the string "null"
      * will be written to the target.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @param start
@@ -261,7 +236,6 @@
      *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
      *             either {@code start} or {@code end} are greater or equal than
      *             the length of {@code csq}.
-     * @since Android 1.0
      */
     @Override
     public StringWriter append(CharSequence csq, int start, int end) {
diff --git a/luni/src/main/java/java/io/SyncFailedException.java b/luni/src/main/java/java/io/SyncFailedException.java
index 2f8d9c7..c4f7340 100644
--- a/luni/src/main/java/java/io/SyncFailedException.java
+++ b/luni/src/main/java/java/io/SyncFailedException.java
@@ -20,8 +20,6 @@
 /**
  * Signals that the {@link FileDescriptor#sync()} method has failed to
  * complete.
- * 
- * @since Android 1.0
  */
 public class SyncFailedException extends IOException {
 
@@ -33,7 +31,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public SyncFailedException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/UTFDataFormatException.java b/luni/src/main/java/java/io/UTFDataFormatException.java
index 20a7abe..215e3e2 100644
--- a/luni/src/main/java/java/io/UTFDataFormatException.java
+++ b/luni/src/main/java/java/io/UTFDataFormatException.java
@@ -22,9 +22,7 @@
  * likely while reading some {@link DataInputStream}.
  * 
  * @see DataInputStream#readUTF()
-  * 
- * @since Android 1.0
-*/
+ */
 public class UTFDataFormatException extends IOException {
 
     private static final long serialVersionUID = 420743449228280612L;
@@ -32,8 +30,6 @@
     /**
      * Constructs a new {@code UTFDataFormatException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public UTFDataFormatException() {
         super();
@@ -45,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UTFDataFormatException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/UnsupportedEncodingException.java b/luni/src/main/java/java/io/UnsupportedEncodingException.java
index deeab29..eca6c81 100644
--- a/luni/src/main/java/java/io/UnsupportedEncodingException.java
+++ b/luni/src/main/java/java/io/UnsupportedEncodingException.java
@@ -18,11 +18,8 @@
 package java.io;
 
 /**
- * Signals that a requested character encoding is not available, either because
- * it is not included a specific Android system, or because the encoding name
- * is simply incorrect.
- * 
- * @since Android 1.0
+ * Thrown when a program asks for a particular character converter that is
+ * unavailable.
  */
 public class UnsupportedEncodingException extends IOException {
 
@@ -31,8 +28,6 @@
     /**
      * Constructs a new {@code UnsupportedEncodingException} with its stack
      * trace filled in.
-     * 
-     * @since Android 1.0
      */
     public UnsupportedEncodingException() {
         super();
@@ -44,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnsupportedEncodingException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/io/WriteAbortedException.java b/luni/src/main/java/java/io/WriteAbortedException.java
index 02c2f70..11ee1fe 100644
--- a/luni/src/main/java/java/io/WriteAbortedException.java
+++ b/luni/src/main/java/java/io/WriteAbortedException.java
@@ -26,8 +26,6 @@
  * object.
  * 
  * @see ObjectInputStream#readObject()
- * 
- * @since Android 1.0
  */
 public class WriteAbortedException extends ObjectStreamException {
 
@@ -36,8 +34,6 @@
     /**
      * The exception that occured when writeObject() was attempting to serialize
      * the object.
-     * 
-     * @since Android 1.0
      */
     public Exception detail;
 
@@ -50,7 +46,6 @@
      *            the detail message for this exception.
      * @param rootCause
      *            the exception that was thrown when serializing the object.
-     * @since Android 1.0
      */
     public WriteAbortedException(String detailMessage, Exception rootCause) {
         super(detailMessage);
@@ -64,7 +59,6 @@
      * time.
      * 
      * @return the exception message.
-     * @since Android 1.0
      */
     @Override
     public String getMessage() {
@@ -79,7 +73,6 @@
      * Gets the cause of this exception or {@code null} if there is no cause.
      * 
      * @return the exception cause.
-     * @since Android 1.0
      */
     @Override
     public Throwable getCause() {
diff --git a/luni/src/main/java/java/io/Writer.java b/luni/src/main/java/java/io/Writer.java
index 5505e80..dfb37c5 100644
--- a/luni/src/main/java/java/io/Writer.java
+++ b/luni/src/main/java/java/io/Writer.java
@@ -31,10 +31,8 @@
  * <p>
  * Many specialized readers for purposes like reading from a file already exist
  * in this package.
- * 
+ *
  * @see Reader
- * 
- * @since Android 1.0
  */
 public abstract class Writer implements Appendable, Closeable, Flushable {
 
@@ -42,16 +40,12 @@
 
     /**
      * The object used to synchronize access to the writer.
-     * 
-     * @since Android 1.0
      */
     protected Object lock;
 
     /**
      * Constructs a new {@code Writer} with {@code this} as the object used to
      * synchronize critical sections.
-     * 
-     * @since Android 1.0
      */
     protected Writer() {
         super();
@@ -61,12 +55,11 @@
     /**
      * Constructs a new {@code Writer} with {@code lock} used to synchronize
      * critical sections.
-     * 
+     *
      * @param lock
      *            the {@code Object} used to synchronize critical sections.
      * @throws NullPointerException
      *             if {@code lock} is {@code null}.
-     * @since Android 1.0
      */
     protected Writer(Object lock) {
         if (lock == null) {
@@ -78,31 +71,28 @@
     /**
      * Closes this writer. Implementations of this method should free any
      * resources associated with the writer.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this writer.
-     * @since Android 1.0
      */
     public abstract void close() throws IOException;
 
     /**
      * Flushes this writer. Implementations of this method should ensure that
      * all buffered characters are written to the target.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while flushing this writer.
-     * @since Android 1.0
      */
     public abstract void flush() throws IOException;
 
     /**
      * Writes the entire character buffer {@code buf} to the target.
-     * 
+     *
      * @param buf
      *            the non-null array containing characters to write.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public void write(char[] buf) throws IOException {
         // BEGIN android-note
@@ -114,7 +104,7 @@
     /**
      * Writes {@code count} characters starting at {@code offset} in {@code buf}
      * to the target.
-     * 
+     *
      * @param buf
      *            the non-null character array to write.
      * @param offset
@@ -126,7 +116,6 @@
      *             offset + count} is greater than the size of {@code buf}.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public abstract void write(char[] buf, int offset, int count)
             throws IOException;
@@ -137,12 +126,11 @@
     /**
      * Writes one character to the target. Only the two least significant bytes
      * of the integer {@code oneChar} are written.
-     * 
+     *
      * @param oneChar
      *            the character to write to the target.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public void write(int oneChar) throws IOException {
         synchronized (lock) {
@@ -154,12 +142,11 @@
 
     /**
      * Writes the characters from the specified string to the target.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public void write(String str) throws IOException {
         char buf[] = new char[str.length()];
@@ -172,7 +159,7 @@
     /**
      * Writes {@code count} characters from {@code str} starting at {@code
      * offset} to the target.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
      * @param offset
@@ -184,7 +171,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is greater than the length of {@code str}.
-     * @since Android 1.0
      */
     public void write(String str, int offset, int count) throws IOException {
         if (count < 0) { // other cases tested by getChars()
@@ -201,13 +187,12 @@
     /**
      * Appends the character {@code c} to the target. This method works the same
      * way as {@link #write(int)}.
-     * 
+     *
      * @param c
      *            the character to append to the target stream.
      * @return this writer.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public Writer append(char c) throws IOException {
         write(c);
@@ -219,13 +204,12 @@
      * works the same way as {@code Writer.write(csq.toString())}. If {@code
      * csq} is {@code null}, then the string "null" is written to the target
      * stream.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @return this writer.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public Writer append(CharSequence csq) throws IOException {
         if (null == csq) {
@@ -242,7 +226,7 @@
      * Writer.writer(csq.subsequence(start, end).toString())}. If {@code
      * csq} is {@code null}, then the specified subsequence of the string "null"
      * will be written to the target.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @param start
@@ -258,7 +242,6 @@
      *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
      *             either {@code start} or {@code end} are greater or equal than
      *             the length of {@code csq}.
-     * @since Android 1.0
      */
     public Writer append(CharSequence csq, int start, int end)
             throws IOException {
diff --git a/luni/src/main/java/java/lang/AbstractMethodError.java b/luni/src/main/java/java/lang/AbstractMethodError.java
index cdfa0ec..4d5238a 100644
--- a/luni/src/main/java/java/lang/AbstractMethodError.java
+++ b/luni/src/main/java/java/lang/AbstractMethodError.java
@@ -22,8 +22,6 @@
  * <p>
  * Note that this can only occur when inconsistent class files have been loaded,
  * since invoking an abstract method is a compile time error.
- * </p>
- * @since Android 1.0
  */
 public class AbstractMethodError extends IncompatibleClassChangeError {
 
@@ -32,8 +30,6 @@
     /**
      * Constructs a new {@code AbstractMethodError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public AbstractMethodError() {
         super();
@@ -42,10 +38,9 @@
     /**
      * Constructs a new {@code AbstractMethodError} with the current stack trace
      * and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public AbstractMethodError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/AbstractStringBuilder.java b/luni/src/main/java/java/lang/AbstractStringBuilder.java
index 39459a0..06f8c50 100644
--- a/luni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/luni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -23,15 +23,13 @@
 import org.apache.harmony.luni.util.Msg;
 
 /**
- * <p>
  * A modifiable {@link CharSequence sequence of characters} for use in creating
  * and modifying Strings. This class is intended as a base class for
  * {@link StringBuffer} and {@link StringBuilder}.
- * </p>
  *
  * @see StringBuffer
  * @see StringBuilder
- * @since Android 1.0
+ * @since 1.5
  */
 abstract class AbstractStringBuilder {
 
@@ -95,8 +93,8 @@
     }
 
     private void enlargeBuffer(int min) {
-        int twice = (value.length << 1) + 2;
-        char[] newData = new char[min > twice ? min : twice];
+        int newSize = ((value.length >> 1) + value.length) + 2;
+        char[] newData = new char[min > newSize ? min : newSize];
         System.arraycopy(value, 0, newData, 0, count);
         value = newData;
         shared = false;
@@ -106,9 +104,6 @@
         int newSize = count + 4;
         if (newSize > value.length) {
             enlargeBuffer(newSize);
-        } else if (shared) {
-            value = value.clone();
-            shared = false;
         }
         value[count++] = 'n';
         value[count++] = 'u';
@@ -120,9 +115,6 @@
         int newSize = count + chars.length;
         if (newSize > value.length) {
             enlargeBuffer(newSize);
-        } else if (shared) {
-            value = value.clone();
-            shared = false;
         }
         System.arraycopy(chars, 0, value, count, chars.length);
         count = newSize;
@@ -137,9 +129,6 @@
             int newSize = count + length;
             if (newSize > value.length) {
                 enlargeBuffer(newSize);
-            } else if (shared) {
-                value = value.clone();
-                shared = false;
             }
             System.arraycopy(chars, start, value, count, length);
             count = newSize;
@@ -152,10 +141,6 @@
         if (count == value.length) {
             enlargeBuffer(count + 1);
         }
-        if (shared) {
-            value = value.clone();
-            shared = false;
-        }
         value[count++] = ch;
     }
 
@@ -168,9 +153,6 @@
         int newSize = count + adding;
         if (newSize > value.length) {
             enlargeBuffer(newSize);
-        } else if (shared) {
-            value = value.clone();
-            shared = false;
         }
         // BEGIN android-changed
         string._getChars(0, adding, value, count);
@@ -213,7 +195,7 @@
 
     /**
      * Returns the number of characters that can be held without growing.
-     * 
+     *
      * @return the capacity
      * @see #ensureCapacity
      * @see #length
@@ -224,7 +206,7 @@
 
     /**
      * Retrieves the character at the {@code index}.
-     * 
+     *
      * @param index
      *            the index of the character to retrieve.
      * @return the char value.
@@ -296,20 +278,21 @@
      * value of either the {@code minimumCapacity} or the current capacity
      * multiplied by two plus two. Although this is the general policy, there is
      * no guarantee that the capacity will change.
-     * 
+     *
      * @param min
      *            the new minimum capacity to set.
      */
     public void ensureCapacity(int min) {
         if (min > value.length) {
-            enlargeBuffer(min);
+            int twice = (value.length << 1) + 2;
+            enlargeBuffer(twice > min ? twice : min);
         }
     }
 
     /**
      * Copies the requested sequence of characters to the {@code char[]} passed
      * starting at {@code destStart}.
-     * 
+     *
      * @param start
      *            the inclusive start index of the characters to copy.
      * @param end
@@ -343,7 +326,7 @@
         }
     }
 
-    final void insert0(int index, char chars[], int start, int length) {
+    final void insert0(int index, char[] chars, int start, int length) {
         if (0 <= index && index <= count) {
             // start + length could overflow, start/length maybe MaxInt
             if (start >= 0 && 0 <= length && length <= chars.length - start) {
@@ -354,8 +337,9 @@
                 }
                 return;
             }
-            throw new StringIndexOutOfBoundsException("offset " + start
-                    + ", len " + length + ", array.length " + chars.length);
+            throw new StringIndexOutOfBoundsException("offset " + start //$NON-NLS-1$
+                    + ", length " + length //$NON-NLS-1$
+                    + ", char[].length " + chars.length); //$NON-NLS-1$
         }
         throw new StringIndexOutOfBoundsException(index);
     }
@@ -401,7 +385,7 @@
 
     /**
      * The current length.
-     * 
+     *
      * @return the number of characters contained in this instance.
      */
     public int length() {
@@ -481,15 +465,72 @@
             return;
         }
         if (!shared) {
-            for (int i = 0, end = count, mid = count / 2; i < mid; i++) {
-                char temp = value[--end];
-                value[end] = value[i];
-                value[i] = temp;
+            int end = count - 1;
+            char frontHigh = value[0];
+            char endLow = value[end];
+            boolean allowFrontSur = true, allowEndSur = true;
+            for (int i = 0, mid = count / 2; i < mid; i++, --end) {
+                char frontLow = value[i + 1];
+                char endHigh = value[end - 1];
+                boolean surAtFront = allowFrontSur && frontLow >= 0xdc00
+                        && frontLow <= 0xdfff && frontHigh >= 0xd800
+                        && frontHigh <= 0xdbff;
+                if (surAtFront && (count < 3)) {
+                    return;
+                }
+                boolean surAtEnd = allowEndSur && endHigh >= 0xd800
+                        && endHigh <= 0xdbff && endLow >= 0xdc00
+                        && endLow <= 0xdfff;
+                allowFrontSur = allowEndSur = true;
+                if (surAtFront == surAtEnd) {
+                    if (surAtFront) {
+                        // both surrogates
+                        value[end] = frontLow;
+                        value[end - 1] = frontHigh;
+                        value[i] = endHigh;
+                        value[i + 1] = endLow;
+                        frontHigh = value[i + 2];
+                        endLow = value[end - 2];
+                        i++;
+                        end--;
+                    } else {
+                        // neither surrogates
+                        value[end] = frontHigh;
+                        value[i] = endLow;
+                        frontHigh = frontLow;
+                        endLow = endHigh;
+                    }
+                } else {
+                    if (surAtFront) {
+                        // surrogate only at the front
+                        value[end] = frontLow;
+                        value[i] = endLow;
+                        endLow = endHigh;
+                        allowFrontSur = false;
+                    } else {
+                        // surrogate only at the end
+                        value[end] = frontHigh;
+                        value[i] = endHigh;
+                        frontHigh = frontLow;
+                        allowEndSur = false;
+                    }
+                }
+            }
+            if ((count & 1) == 1 && (!allowFrontSur || !allowEndSur)) {
+                value[end] = allowFrontSur ? endLow : frontHigh;
             }
         } else {
             char[] newData = new char[value.length];
             for (int i = 0, end = count; i < count; i++) {
-                newData[--end] = value[i];
+                char high = value[i];
+                if ((i + 1) < count && high >= 0xd800 && high <= 0xdbff) {
+                    char low = value[i + 1];
+                    if (low >= 0xdc00 && low <= 0xdfff) {
+                        newData[--end] = low;
+                        i++;
+                    }
+                }
+                newData[--end] = high;
             }
             value = newData;
             shared = false;
@@ -498,7 +539,7 @@
 
     /**
      * Sets the character at the {@code index}.
-     * 
+     *
      * @param index
      *            the zero-based index of the character to replace.
      * @param ch
@@ -522,7 +563,7 @@
      * Sets the current length to a new value. If the new length is larger than
      * the current length, then the new characters at the end of this object
      * will contain the {@code char} value of {@code \u0000}.
-     * 
+     *
      * @param length
      *            the new length of this StringBuffer.
      * @exception IndexOutOfBoundsException
@@ -533,16 +574,16 @@
         if (length < 0) {
             throw new StringIndexOutOfBoundsException(length);
         }
-        if (count < length) {
-            if (length > value.length) {
-                enlargeBuffer(length);
+        if (length > value.length) {
+            enlargeBuffer(length);
+        } else {
+            if (shared) {
+                char[] newData = new char[value.length];
+                System.arraycopy(value, 0, newData, 0, count);
+                value = newData;
+                shared = false;
             } else {
-                if (shared) {
-                    char[] newData = new char[value.length];
-                    System.arraycopy(value, 0, newData, 0, count);
-                    value = newData;
-                    shared = false;
-                } else {
+                if (count < length) {
                     Arrays.fill(value, count, length, (char) 0);
                 }
             }
@@ -553,7 +594,7 @@
     /**
      * Returns the String value of the subsequence from the {@code start} index
      * to the current end.
-     * 
+     *
      * @param start
      *            the inclusive start index to begin the subsequence.
      * @return a String containing the subsequence.
@@ -567,8 +608,8 @@
                 return ""; //$NON-NLS-1$
             }
 
-            shared = true;
-            return new String(start, count - start, value);
+            // Remove String sharing for more performance
+            return new String(value, start, count - start);
         }
         throw new StringIndexOutOfBoundsException(start);
     }
@@ -576,7 +617,7 @@
     /**
      * Returns the String value of the subsequence from the {@code start} index
      * to the {@code end} index.
-     * 
+     *
      * @param start
      *            the inclusive start index to begin the subsequence.
      * @param end
@@ -592,7 +633,7 @@
                 return ""; //$NON-NLS-1$
             }
 
-            shared = true;
+            // Remove String sharing for more performance
             return new String(value, start, end - start);
         }
         throw new StringIndexOutOfBoundsException();
@@ -600,7 +641,7 @@
 
     /**
      * Returns the current String representation.
-     * 
+     *
      * @return a String containing the characters in this instance.
      */
     @Override
@@ -608,8 +649,10 @@
         if (count == 0) {
             return ""; //$NON-NLS-1$
         }
-
-        if (count >= 256 && count <= (value.length >> 1)) {
+        // Optimize String sharing for more performance
+        int wasted = value.length - count;
+        if (wasted >= 256
+                || (wasted >= INITIAL_CAPACITY && wasted >= (count >> 1))) {
             return new String(value, 0, count);
         }
         shared = true;
@@ -619,7 +662,7 @@
     /**
      * Returns a {@code CharSequence} of the subsequence from the {@code start}
      * index to the {@code end} index.
-     * 
+     *
      * @param start
      *            the inclusive start index to begin the subsequence.
      * @param end
@@ -628,6 +671,7 @@
      * @throws IndexOutOfBoundsException
      *             if {@code start} is negative, greater than {@code end} or if
      *             {@code end} is greater than the current {@link #length()}.
+     * @since 1.4
      */
     public CharSequence subSequence(int start, int end) {
         return substring(start, end);
@@ -636,12 +680,13 @@
     /**
      * Searches for the first index of the specified character. The search for
      * the character starts at the beginning and moves towards the end.
-     * 
+     *
      * @param string
      *            the string to find.
      * @return the index of the specified character, -1 if the character isn't
      *         found.
      * @see #lastIndexOf(String)
+     * @since 1.4
      */
     public int indexOf(String string) {
         return indexOf(string, 0);
@@ -650,7 +695,7 @@
     /**
      * Searches for the index of the specified character. The search for the
      * character starts at the specified offset and moves towards the end.
-     * 
+     *
      * @param subString
      *            the string to find.
      * @param start
@@ -658,6 +703,7 @@
      * @return the index of the specified character, -1 if the character isn't
      *         found
      * @see #lastIndexOf(String,int)
+     * @since 1.4
      */
     public int indexOf(String subString, int start) {
         if (start < 0) {
@@ -698,12 +744,15 @@
     /**
      * Searches for the last index of the specified character. The search for
      * the character starts at the end and moves towards the beginning.
-     * 
+     *
      * @param string
      *            the string to find.
      * @return the index of the specified character, -1 if the character isn't
      *         found.
-     * @see String#lastIndexOf(String)
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
+     * @see String#lastIndexOf(java.lang.String)
+     * @since 1.4
      */
     public int lastIndexOf(String string) {
         return lastIndexOf(string, count);
@@ -712,14 +761,17 @@
     /**
      * Searches for the index of the specified character. The search for the
      * character starts at the specified offset and moves towards the beginning.
-     * 
+     *
      * @param subString
      *            the string to find.
      * @param start
      *            the starting offset.
      * @return the index of the specified character, -1 if the character isn't
      *         found.
+     * @throws NullPointerException
+     *             if {@code subString} is {@code null}.
      * @see String#lastIndexOf(String,int)
+     * @since 1.4
      */
     public int lastIndexOf(String subString, int start) {
         int subCount = subString.length();
@@ -762,6 +814,8 @@
     /**
      * Trims off any extra capacity beyond the current length. Note, this method
      * is NOT guaranteed to change the capacity of this object.
+     *
+     * @since 1.5
      */
     public void trimToSize() {
         if (count < value.length) {
@@ -774,7 +828,7 @@
 
     /**
      * Retrieves the Unicode code point value at the {@code index}.
-     * 
+     *
      * @param index
      *            the index to the {@code char} code unit.
      * @return the Unicode code point value.
@@ -783,6 +837,7 @@
      *             {@link #length()}.
      * @see Character
      * @see Character#codePointAt(char[], int, int)
+     * @since 1.5
      */
     public int codePointAt(int index) {
         if (index < 0 || index >= count) {
@@ -793,7 +848,7 @@
 
     /**
      * Retrieves the Unicode code point value that precedes the {@code index}.
-     * 
+     *
      * @param index
      *            the index to the {@code char} code unit within this object.
      * @return the Unicode code point value.
@@ -801,7 +856,8 @@
      *             if {@code index} is less than 1 or greater than
      *             {@link #length()}.
      * @see Character
-     * @see Character#codePointBefore(char[], int)
+     * @see Character#codePointBefore(char[], int, int)
+     * @since 1.5
      */
     public int codePointBefore(int index) {
         if (index < 1 || index > count) {
@@ -811,11 +867,9 @@
     }
 
     /**
-     * <p>
      * Calculates the number of Unicode code points between {@code beginIndex}
      * and {@code endIndex}.
-     * </p>
-     * 
+     *
      * @param beginIndex
      *            the inclusive beginning index of the subsequence.
      * @param endIndex
@@ -827,6 +881,7 @@
      *             {@link #length()}.
      * @see Character
      * @see Character#codePointCount(char[], int, int)
+     * @since 1.5
      */
     public int codePointCount(int beginIndex, int endIndex) {
         if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
@@ -837,11 +892,9 @@
     }
 
     /**
-     * <p>
      * Returns the index that is offset {@code codePointOffset} code points from
      * {@code index}.
-     * </p>
-     * 
+     *
      * @param index
      *            the index to calculate the offset from.
      * @param codePointOffset
@@ -855,6 +908,7 @@
      *             {@code codePointOffset}.
      * @see Character
      * @see Character#offsetByCodePoints(char[], int, int, int, int)
+     * @since 1.5
      */
     public int offsetByCodePoints(int index, int codePointOffset) {
         return Character.offsetByCodePoints(value, 0, count, index,
diff --git a/luni/src/main/java/java/lang/Appendable.java b/luni/src/main/java/java/lang/Appendable.java
index 1b4e702..ca4b532 100644
--- a/luni/src/main/java/java/lang/Appendable.java
+++ b/luni/src/main/java/java/lang/Appendable.java
@@ -27,16 +27,13 @@
  * <p>
  * {@code Appendable} itself does not guarantee thread safety. This
  * responsibility is up to the implementing class.
- * </p>
  * <p>
  * Implementing classes can choose different exception handling mechanism. They
  * can choose to throw exceptions other than {@code IOException} or they do not
  * throw any exceptions at all and use error codes instead.
- * </p>
- * @since Android 1.0
  */
 public interface Appendable {
-    
+
     /**
      * Appends the specified character.
      * 
@@ -45,7 +42,6 @@
      * @return this {@code Appendable}.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     Appendable append(char c) throws IOException;
 
@@ -55,14 +51,12 @@
      * limited size.
      * <p>
      * If {@code csq} is {@code null}, the characters "null" are appended.
-     * </p>
-     * 
+     *
      * @param csq
      *            the character sequence to append.
      * @return this {@code Appendable}.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     Appendable append(CharSequence csq) throws IOException;
 
@@ -73,7 +67,6 @@
      * to calling {@code append(csq.subSequence(start, end))}.
      * <p>
      * If {@code csq} is {@code null}, the characters "null" are appended.
-     * </p>
      * 
      * @param csq
      *            the character sequence to append.
@@ -89,7 +82,6 @@
      *             or {@code end} is greater than the length of {@code csq}.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     Appendable append(CharSequence csq, int start, int end) throws IOException;
 }
diff --git a/luni/src/main/java/java/lang/ArithmeticException.java b/luni/src/main/java/java/lang/ArithmeticException.java
index 74671fc..a6ab2a0 100644
--- a/luni/src/main/java/java/lang/ArithmeticException.java
+++ b/luni/src/main/java/java/lang/ArithmeticException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when the an invalid arithmetic operation is attempted.
- * 
- * @since Android 1.0
  */
 public class ArithmeticException extends RuntimeException {
 
@@ -29,8 +27,6 @@
     /**
      * Constructs a new {@code ArithmeticException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public ArithmeticException() {
         super();
@@ -39,10 +35,9 @@
     /**
      * Constructs a new {@code ArithmeticException} with the current stack trace
      * and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ArithmeticException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java b/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
index 0f231d3..d43a7e6 100644
--- a/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
+++ b/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
@@ -22,8 +22,6 @@
 /**
  * Thrown when the an array is indexed with a value less than zero, or greater
  * than or equal to the size of the array.
- * 
- * @since Android 1.0
  */
 public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
 
@@ -32,8 +30,6 @@
     /**
      * Constructs a new {@code ArrayIndexOutOfBoundsException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public ArrayIndexOutOfBoundsException() {
         super();
@@ -46,7 +42,6 @@
      * 
      * @param index
      *            the invalid index.
-     * @since Android 1.0
      */
     public ArrayIndexOutOfBoundsException(int index) {
         super(Msg.getString("K0052", index)); //$NON-NLS-1$
@@ -55,10 +50,9 @@
     /**
      * Constructs a new {@code ArrayIndexOutOfBoundsException} with the current
      * stack trace and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ArrayIndexOutOfBoundsException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/ArrayStoreException.java b/luni/src/main/java/java/lang/ArrayStoreException.java
index b69697a..6cb9c8f 100644
--- a/luni/src/main/java/java/lang/ArrayStoreException.java
+++ b/luni/src/main/java/java/lang/ArrayStoreException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a program attempts to store an element of an incompatible type in
  * an array.
- * 
- * @since Android 1.0
  */
 public class ArrayStoreException extends RuntimeException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code ArrayStoreException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public ArrayStoreException() {
         super();
@@ -40,10 +36,9 @@
     /**
      * Constructs a new {@code ArrayStoreException} with the current stack trace
      * and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ArrayStoreException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/AssertionError.java b/luni/src/main/java/java/lang/AssertionError.java
index 8d3368b..e4d4ed0 100644
--- a/luni/src/main/java/java/lang/AssertionError.java
+++ b/luni/src/main/java/java/lang/AssertionError.java
@@ -19,8 +19,8 @@
 
 /**
  * Thrown when an assertion has failed.
- * 
- * @since Android 1.0
+ *
+ * @since 1.4
  */
 public class AssertionError extends Error {
 
@@ -28,8 +28,6 @@
 
     /**
      * Constructs a new {@code AssertionError} with no message.
-     * 
-     * @since Android 1.0
      */
     public AssertionError() {
         super();
@@ -44,7 +42,6 @@
      * @param detailMessage
      *            the object to be converted into the detail message and
      *            optionally the cause.
-     * @since Android 1.0
      */
     public AssertionError(Object detailMessage) {
         super(String.valueOf(detailMessage),
@@ -58,7 +55,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(boolean detailMessage) {
         this(String.valueOf(detailMessage));
@@ -70,7 +66,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(char detailMessage) {
         this(String.valueOf(detailMessage));
@@ -82,7 +77,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(int detailMessage) {
         this(Integer.toString(detailMessage));
@@ -94,7 +88,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(long detailMessage) {
         this(Long.toString(detailMessage));
@@ -106,7 +99,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(float detailMessage) {
         this(Float.toString(detailMessage));
@@ -118,7 +110,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(double detailMessage) {
         this(Double.toString(detailMessage));
diff --git a/luni/src/main/java/java/lang/Boolean.java b/luni/src/main/java/java/lang/Boolean.java
index c49c384..9c476a4 100644
--- a/luni/src/main/java/java/lang/Boolean.java
+++ b/luni/src/main/java/java/lang/Boolean.java
@@ -21,8 +21,8 @@
 
 /**
  * The wrapper for the primitive type {@code boolean}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.0
  */
 public final class Boolean implements Serializable, Comparable<Boolean> {
 
@@ -36,8 +36,6 @@
     /**
      * The {@link Class} object that represents the primitive type {@code
      * boolean}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Boolean> TYPE = (Class<Boolean>) new boolean[0]
@@ -49,16 +47,12 @@
     /**
      * The {@code Boolean} object that represents the primitive value
      * {@code true}.
-     * 
-     * @since Android 1.0
      */
     public static final Boolean TRUE = new Boolean(true);
 
     /**
      * The {@code Boolean} object that represents the primitive value
      * {@code false}.
-     * 
-     * @since Android 1.0
      */
     public static final Boolean FALSE = new Boolean(false);
 
@@ -68,10 +62,9 @@
      * "true" using a non-case sensitive comparison, the result will be a
      * Boolean representing the primitive value {@code true}, otherwise it will
      * be a Boolean representing the primitive value {@code false}.
-     * 
+     *
      * @param string
      *            the string representing a boolean value.
-     * @since Android 1.0
      */
     public Boolean(String string) {
         this(parseBoolean(string));
@@ -80,10 +73,9 @@
     /**
      * Constructs a new {@code Boolean} with the specified primitive boolean
      * value.
-     * 
+     *
      * @param value
      *            the primitive boolean value, {@code true} or {@code false}.
-     * @since Android 1.0
      */
     public Boolean(boolean value) {
         this.value = value;
@@ -92,9 +84,8 @@
     /**
      * Gets the primitive value of this boolean, either {@code true} or
      * {@code false}.
-     * 
+     *
      * @return this object's primitive value, {@code true} or {@code false}.
-     * @since Android 1.0
      */
     public boolean booleanValue() {
         return value;
@@ -104,12 +95,11 @@
      * Compares this instance with the specified object and indicates if they
      * are equal. In order to be equal, {@code o} must be an instance of
      * {@code Boolean} and have the same boolean value as this object.
-     * 
+     *
      * @param o
      *            the object to compare this boolean with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Boolean}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -120,7 +110,7 @@
     /**
      * Compares this object to the specified boolean object to determine their
      * relative order.
-     * 
+     *
      * @param that
      *            the boolean object to compare this object to.
      * @return 0 if the value of this boolean and the value of {@code that} are
@@ -129,7 +119,7 @@
      *         negative value if the value if this boolean is {@code false} and
      *         the value of {@code that} is {@code true}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.5
      */
     public int compareTo(Boolean that) {
         if (that == null) {
@@ -145,10 +135,9 @@
 
     /**
      * Returns an integer hash code for this boolean.
-     * 
+     *
      * @return this boolean's hash code, which is {@code 1231} for {@code true}
      *         values and {@code 1237} for {@code false} values.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -158,10 +147,9 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * boolean.
-     * 
+     *
      * @return "true" if the value of this boolean is {@code true}, "false"
      *         otherwise.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -171,14 +159,13 @@
     /**
      * Returns the {@code boolean} value of the system property identified by
      * {@code string}.
-     * 
+     *
      * @param string
      *            the name of the requested system property.
      * @return {@code true} if the system property named by {@code string}
      *         exists and it is equal to "true" using case insensitive
      *         comparison, {@code false} otherwise.
      * @see System#getProperty(String)
-     * @since Android 1.0
      */
     public static boolean getBoolean(String string) {
         if (string == null || string.length() == 0) {
@@ -189,25 +176,24 @@
 
     /**
      * Parses the specified string as a {@code boolean}.
-     * 
+     *
      * @param s
      *            the string representation of a boolean value.
      * @return {@code true} if {@code s} is not {@code null} and is equal to
      *         {@code "true"} using case insensitive comparison, {@code false}
      *         otherwise.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static boolean parseBoolean(String s) {
         return "true".equalsIgnoreCase(s); //$NON-NLS-1$
     }
 
     /**
-     * Converts the specified boolean to its string representation. 
-     * 
+     * Converts the specified boolean to its string representation.
+     *
      * @param value
      *            the boolean to convert.
      * @return "true" if {@code value} is {@code true}, "false" otherwise.
-     * @since Android 1.0
      */
     public static String toString(boolean value) {
         return String.valueOf(value);
@@ -215,13 +201,12 @@
 
     /**
      * Parses the specified string as a boolean value.
-     * 
+     *
      * @param string
      *            the string representation of a boolean value.
      * @return {@code Boolean.TRUE} if {@code string} is equal to "true" using
      *         case insensitive comparison, {@code Boolean.FALSE} otherwise.
      * @see #parseBoolean(String)
-     * @since Android 1.0
      */
     public static Boolean valueOf(String string) {
         return parseBoolean(string) ? Boolean.TRUE : Boolean.FALSE;
@@ -233,13 +218,11 @@
      * If it is not necessary to get a new {@code Boolean} instance, it is
      * recommended to use this method instead of the constructor, since it
      * returns its static instances, which results in better performance.
-     * </p>
-     * 
+     *
      * @param b
      *            the boolean to convert to a {@code Boolean}.
      * @return {@code Boolean.TRUE} if {@code b} is equal to {@code true},
      *         {@code Boolean.FALSE} otherwise.
-     * @since Android 1.0
      */
     public static Boolean valueOf(boolean b) {
         return b ? Boolean.TRUE : Boolean.FALSE;
diff --git a/luni/src/main/java/java/lang/Byte.java b/luni/src/main/java/java/lang/Byte.java
index a74b539..7e20493 100644
--- a/luni/src/main/java/java/lang/Byte.java
+++ b/luni/src/main/java/java/lang/Byte.java
@@ -19,10 +19,11 @@
 
 /**
  * The wrapper for the primitive type {@code byte}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.1
  */
-public final class Byte extends Number implements Comparable<Byte> {    
+public final class Byte extends Number implements Comparable<Byte> {
+
     private static final long serialVersionUID = -7183698231559129828L;
 
     /**
@@ -32,30 +33,24 @@
 
     /**
      * The maximum {@code Byte} value, 2<sup>7</sup>-1.
-     * 
-     * @since Android 1.0
      */
     public static final byte MAX_VALUE = (byte) 0x7F;
 
     /**
      * The minimum {@code Byte} value, -2<sup>7</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final byte MIN_VALUE = (byte) 0x80;
-    
+
     /**
      * The number of bits needed to represent a {@code Byte} value in two's
      * complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 8;
 
     /**
      * The {@link Class} object that represents the primitive type {@code byte}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Byte> TYPE = (Class<Byte>) new byte[0].getClass()
@@ -63,7 +58,7 @@
 
     // Note: This can't be set to "byte.class", since *that* is
     // defined to be "java.lang.Byte.TYPE";
-    
+
     /**
      * A cache of instances used by {@link #valueOf(byte)} and auto-boxing.
      */
@@ -71,10 +66,9 @@
 
     /**
      * Constructs a new {@code Byte} with the specified primitive byte value.
-     * 
+     *
      * @param value
      *            the primitive byte value to store in the new instance.
-     * @since Android 1.0
      */
     public Byte(byte value) {
         this.value = value;
@@ -82,13 +76,12 @@
 
     /**
      * Constructs a new {@code Byte} from the specified string.
-     * 
+     *
      * @param string
      *            the string representation of a single byte value.
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into a byte value.
      * @see #parseByte(String)
-     * @since Android 1.0
      */
     public Byte(String string) throws NumberFormatException {
         this(parseByte(string));
@@ -96,9 +89,8 @@
 
     /**
      * Gets the primitive value of this byte.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public byte byteValue() {
@@ -108,7 +100,7 @@
     /**
      * Compares this object to the specified byte object to determine their
      * relative order.
-     * 
+     *
      * @param object
      *            the byte object to compare this object to.
      * @return a negative value if the value of this byte is less than the value
@@ -116,7 +108,7 @@
      *         {@code object} are equal; a positive value if the value of this
      *         byte is greater than the value of {@code object}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Byte object) {
         return value > object.value ? 1 : (value < object.value ? -1 : 0);
@@ -127,13 +119,12 @@
      * string can be decoded into a single byte value. The string may be an
      * optional minus sign "-" followed by a hexadecimal ("0x..." or "#..."),
      * octal ("0..."), or decimal ("...") representation of a byte.
-     * 
+     *
      * @param string
      *            a string representation of a single byte value.
      * @return a {@code Byte} containing the value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} can not be parsed as a byte value.
-     * @since Android 1.0
      */
     public static Byte decode(String string) throws NumberFormatException {
         int intValue = Integer.decode(string).intValue();
@@ -153,12 +144,11 @@
      * Compares this object with the specified object and indicates if they are
      * equal. In order to be equal, {@code object} must be an instance of
      * {@code Byte} and have the same byte value as this object.
-     * 
+     *
      * @param object
      *            the object to compare this byte with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Byte}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -189,14 +179,13 @@
     /**
      * Parses the specified string as a signed decimal byte value. The ASCII
      * character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of a single byte value.
      * @return the primitive byte value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a byte value.
-     * @since Android 1.0
      */
     public static byte parseByte(String string) throws NumberFormatException {
         int intValue = Integer.parseInt(string);
@@ -210,7 +199,7 @@
     /**
      * Parses the specified string as a signed byte value using the specified
      * radix. The ASCII character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of a single byte value.
      * @param radix
@@ -222,7 +211,6 @@
      *             {@code radix < Character.MIN_RADIX},
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a byte value.
-     * @since Android 1.0
      */
     public static byte parseByte(String string, int radix)
             throws NumberFormatException {
@@ -247,11 +235,10 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * specified byte value.
-     * 
+     *
      * @param value
      *            the byte to convert to a string.
      * @return a printable representation of {@code value}.
-     * @since Android 1.0
      */
     public static String toString(byte value) {
         return Integer.toString(value);
@@ -259,7 +246,7 @@
 
     /**
      * Parses the specified string as a signed decimal byte value.
-     * 
+     *
      * @param string
      *            the string representation of a single byte value.
      * @return a {@code Byte} instance containing the byte value represented by
@@ -268,7 +255,6 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a byte value.
      * @see #parseByte(String)
-     * @since Android 1.0
      */
     public static Byte valueOf(String string) throws NumberFormatException {
         return valueOf(parseByte(string));
@@ -277,7 +263,7 @@
     /**
      * Parses the specified string as a signed byte value using the specified
      * radix.
-     * 
+     *
      * @param string
      *            the string representation of a single byte value.
      * @param radix
@@ -290,25 +276,23 @@
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a byte value.
      * @see #parseByte(String, int)
-     * @since Android 1.0
      */
     public static Byte valueOf(String string, int radix)
             throws NumberFormatException {
         return valueOf(parseByte(string, radix));
     }
-    
+
     /**
      * Returns a {@code Byte} instance for the specified byte value.
      * <p>
      * If it is not necessary to get a new {@code Byte} instance, it is
      * recommended to use this method instead of the constructor, since it
      * maintains a cache of instances which may result in better performance.
-     * </p>
-     * 
+     *
      * @param b
      *            the byte value to store in the instance.
      * @return a {@code Byte} instance containing {@code b}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Byte valueOf(byte b) {
         synchronized (CACHE) {
diff --git a/luni/src/main/java/java/lang/CharSequence.java b/luni/src/main/java/java/lang/CharSequence.java
index 1901192..fc1ecd3 100644
--- a/luni/src/main/java/java/lang/CharSequence.java
+++ b/luni/src/main/java/java/lang/CharSequence.java
@@ -21,37 +21,33 @@
 /**
  * This interface represents an ordered set of characters and defines the
  * methods to probe them.
- * 
- * @since Android 1.0
  */
 public interface CharSequence {
 
     /**
      * Returns the number of characters in this sequence.
-     * 
+     *
      * @return the number of characters.
-     * @since Android 1.0
      */
     public int length();
 
     /**
      * Returns the character at the specified index, with the first character
      * having index zero.
-     * 
+     *
      * @param index
      *            the index of the character to return.
      * @return the requested character.
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0} or {@code index} is greater than the
      *             length of this sequence.
-     * @since Android 1.0
      */
     public char charAt(int index);
 
     /**
      * Returns a {@code CharSequence} from the {@code start} index (inclusive)
      * to the {@code end} index (exclusive) of this sequence.
-     * 
+     *
      * @param start
      *            the start offset of the sub-sequence. It is inclusive, that
      *            is, the index of the first character that is included in the
@@ -65,16 +61,14 @@
      *             if {@code start < 0}, {@code end < 0}, {@code start > end},
      *             or if {@code start} or {@code end} are greater than the
      *             length of this sequence.
-     * @since Android 1.0
      */
     public CharSequence subSequence(int start, int end);
 
     /**
      * Returns a string with the same characters in the same order as in this
      * sequence.
-     * 
+     *
      * @return a string based on this sequence.
-     * @since Android 1.0
      */
     public String toString();
 }
diff --git a/luni/src/main/java/java/lang/Character.java b/luni/src/main/java/java/lang/Character.java
index 564e37a..8e83b48 100644
--- a/luni/src/main/java/java/lang/Character.java
+++ b/luni/src/main/java/java/lang/Character.java
@@ -21,7 +21,7 @@
 // BEGIN android-removed
 // import java.util.SortedMap;
 // import java.util.TreeMap;
-// 
+//
 // import org.apache.harmony.luni.util.BinarySearch;
 // END android-removed
 
@@ -36,7 +36,6 @@
  * Character data is based upon the Unicode Standard, 4.0. The Unicode
  * specification, character tables and other information are available at <a
  * href="http://www.unicode.org/">http://www.unicode.org/</a>.
- * </p>
  * <p>
  * Unicode characters are referred to as <i>code points</i>. The range of valid
  * code points is U+0000 to U+10FFFF. The <i>Basic Multilingual Plane (BMP)</i>
@@ -47,14 +46,12 @@
  * supplementary character are made up of a <i>high surrogate</i> with a value
  * range of 0xD800 to 0xDBFF and a <i>low surrogate</i> with a value range of
  * 0xDC00 to 0xDFFF.
- * </p>
  * <p>
  * On the Java platform a {@code char} value represents either a single BMP code
  * point or a UTF-16 unit that's part of a surrogate pair. The {@code int} type
  * is used to represent all Unicode code points.
- * </p>
- * 
- * @since Android 1.0
+ *
+ * @since 1.0
  */
 public final class Character implements Serializable, Comparable<Character> {
     private static final long serialVersionUID = 3786198910865385080L;
@@ -63,36 +60,26 @@
 
     /**
      * The minimum {@code Character} value.
-     * 
-     * @since Android 1.0
      */
     public static final char MIN_VALUE = '\u0000';
 
     /**
      * The maximum {@code Character} value.
-     * 
-     * @since Android 1.0
      */
     public static final char MAX_VALUE = '\uffff';
 
     /**
      * The minimum radix used for conversions between characters and integers.
-     * 
-     * @since Android 1.0
      */
     public static final int MIN_RADIX = 2;
 
     /**
      * The maximum radix used for conversions between characters and integers.
-     * 
-     * @since Android 1.0
      */
     public static final int MAX_RADIX = 36;
 
     /**
      * The {@link Class} object that represents the primitive type {@code char}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Character> TYPE = (Class<Character>) new char[0]
@@ -103,437 +90,415 @@
 
     /**
      * Unicode category constant Cn.
-     * 
-     * @since Android 1.0
      */
     public static final byte UNASSIGNED = 0;
 
     /**
      * Unicode category constant Lu.
-     * 
-     * @since Android 1.0
      */
     public static final byte UPPERCASE_LETTER = 1;
 
     /**
      * Unicode category constant Ll.
-     * 
-     * @since Android 1.0
      */
     public static final byte LOWERCASE_LETTER = 2;
 
     /**
      * Unicode category constant Lt.
-     * 
-     * @since Android 1.0
      */
     public static final byte TITLECASE_LETTER = 3;
 
     /**
      * Unicode category constant Lm.
-     * 
-     * @since Android 1.0
      */
     public static final byte MODIFIER_LETTER = 4;
 
     /**
      * Unicode category constant Lo.
-     * 
-     * @since Android 1.0
      */
     public static final byte OTHER_LETTER = 5;
 
     /**
      * Unicode category constant Mn.
-     * 
-     * @since Android 1.0
      */
     public static final byte NON_SPACING_MARK = 6;
 
     /**
      * Unicode category constant Me.
-     * 
-     * @since Android 1.0
      */
     public static final byte ENCLOSING_MARK = 7;
 
     /**
      * Unicode category constant Mc.
-     * 
-     * @since Android 1.0
      */
     public static final byte COMBINING_SPACING_MARK = 8;
 
     /**
      * Unicode category constant Nd.
-     * 
-     * @since Android 1.0
      */
     public static final byte DECIMAL_DIGIT_NUMBER = 9;
 
     /**
      * Unicode category constant Nl.
-     * 
-     * @since Android 1.0
      */
     public static final byte LETTER_NUMBER = 10;
 
     /**
      * Unicode category constant No.
-     * 
-     * @since Android 1.0
      */
     public static final byte OTHER_NUMBER = 11;
 
     /**
      * Unicode category constant Zs.
-     * 
-     * @since Android 1.0
      */
     public static final byte SPACE_SEPARATOR = 12;
 
     /**
      * Unicode category constant Zl.
-     * 
-     * @since Android 1.0
      */
     public static final byte LINE_SEPARATOR = 13;
 
     /**
      * Unicode category constant Zp.
-     * 
-     * @since Android 1.0
      */
     public static final byte PARAGRAPH_SEPARATOR = 14;
 
     /**
      * Unicode category constant Cc.
-     * 
-     * @since Android 1.0
      */
     public static final byte CONTROL = 15;
 
     /**
      * Unicode category constant Cf.
-     * 
-     * @since Android 1.0
      */
     public static final byte FORMAT = 16;
 
     /**
      * Unicode category constant Co.
-     * 
-     * @since Android 1.0
      */
     public static final byte PRIVATE_USE = 18;
 
     /**
      * Unicode category constant Cs.
-     * 
-     * @since Android 1.0
      */
     public static final byte SURROGATE = 19;
 
     /**
      * Unicode category constant Pd.
-     * 
-     * @since Android 1.0
      */
     public static final byte DASH_PUNCTUATION = 20;
 
     /**
      * Unicode category constant Ps.
-     * 
-     * @since Android 1.0
      */
     public static final byte START_PUNCTUATION = 21;
 
     /**
      * Unicode category constant Pe.
-     * 
-     * @since Android 1.0
      */
     public static final byte END_PUNCTUATION = 22;
 
     /**
      * Unicode category constant Pc.
-     * 
-     * @since Android 1.0
      */
     public static final byte CONNECTOR_PUNCTUATION = 23;
 
     /**
      * Unicode category constant Po.
-     * 
-     * @since Android 1.0
      */
     public static final byte OTHER_PUNCTUATION = 24;
 
     /**
      * Unicode category constant Sm.
-     * 
-     * @since Android 1.0
      */
     public static final byte MATH_SYMBOL = 25;
 
     /**
      * Unicode category constant Sc.
-     * 
-     * @since Android 1.0
      */
     public static final byte CURRENCY_SYMBOL = 26;
 
     /**
      * Unicode category constant Sk.
-     * 
-     * @since Android 1.0
      */
     public static final byte MODIFIER_SYMBOL = 27;
 
     /**
      * Unicode category constant So.
-     * 
-     * @since Android 1.0
      */
     public static final byte OTHER_SYMBOL = 28;
 
     /**
      * Unicode category constant Pi.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte INITIAL_QUOTE_PUNCTUATION = 29;
 
     /**
      * Unicode category constant Pf.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte FINAL_QUOTE_PUNCTUATION = 30;
 
     /**
      * Unicode bidirectional constant.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_UNDEFINED = -1;
 
     /**
      * Unicode bidirectional constant L.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = 0;
 
     /**
      * Unicode bidirectional constant R.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = 1;
 
     /**
      * Unicode bidirectional constant AL.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = 2;
 
     /**
      * Unicode bidirectional constant EN.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = 3;
 
     /**
      * Unicode bidirectional constant ES.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = 4;
 
     /**
      * Unicode bidirectional constant ET.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = 5;
 
     /**
      * Unicode bidirectional constant AN.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_ARABIC_NUMBER = 6;
 
     /**
      * Unicode bidirectional constant CS.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = 7;
 
     /**
      * Unicode bidirectional constant NSM.
      *
-     * @since Android 1.0
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_NONSPACING_MARK = 8;
 
     /**
      * Unicode bidirectional constant BN.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = 9;
 
     /**
      * Unicode bidirectional constant B.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = 10;
 
     /**
      * Unicode bidirectional constant S.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = 11;
 
     /**
      * Unicode bidirectional constant WS.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_WHITESPACE = 12;
 
     /**
      * Unicode bidirectional constant ON.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_OTHER_NEUTRALS = 13;
 
     /**
      * Unicode bidirectional constant LRE.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = 14;
 
     /**
      * Unicode bidirectional constant LRO.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = 15;
 
     /**
      * Unicode bidirectional constant RLE.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = 16;
 
     /**
      * Unicode bidirectional constant RLO.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = 17;
 
     /**
      * Unicode bidirectional constant PDF.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = 18;
-    
+
     /**
      * The minimum value of a high surrogate or leading surrogate unit in UTF-16
      * encoding, {@code '\uD800'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MIN_HIGH_SURROGATE = '\uD800';
 
     /**
      * The maximum value of a high surrogate or leading surrogate unit in UTF-16
      * encoding, {@code '\uDBFF'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MAX_HIGH_SURROGATE = '\uDBFF';
 
     /**
      * The minimum value of a low surrogate or trailing surrogate unit in UTF-16
      * encoding, {@code '\uDC00'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MIN_LOW_SURROGATE = '\uDC00';
 
     /**
      * The maximum value of a low surrogate or trailing surrogate unit in UTF-16
      * encoding, {@code '\uDFFF'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MAX_LOW_SURROGATE = '\uDFFF';
 
     /**
      * The minimum value of a surrogate unit in UTF-16 encoding, {@code '\uD800'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MIN_SURROGATE = '\uD800';
 
     /**
      * The maximum value of a surrogate unit in UTF-16 encoding, {@code '\uDFFF'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MAX_SURROGATE = '\uDFFF';
 
     /**
      * The minimum value of a supplementary code point, {@code U+010000}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x10000;
 
     /**
      * The minimum code point value, {@code U+0000}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int MIN_CODE_POINT = 0x000000;
 
     /**
      * The maximum code point value, {@code U+10FFFF}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int MAX_CODE_POINT = 0x10FFFF;
 
     /**
-     * The number of bits required to represent a {@code Character} value in
-     * two's compliment form.
-     * 
-     * @since Android 1.0
+     * The number of bits required to represent a {@code Character} value
+     * unsigned form.
+     *
+     * @since 1.5
      */
     public static final int SIZE = 16;
 
     // BEGIN android-removed
-    // removed strings containing information about chars that now are read from
-    // icu data.
+    // Unicode 3.0.1 (same as Unicode 3.0.0)
+    // private static final String bidiKeys = ...
+
+    // private static final char[] bidiValues = ...
+
+    // private static final char[] mirrored = ...
+
+    // Unicode 3.0.1 (same as Unicode 3.0.0)
+    // private static final String typeKeys = ...
+
+    // private static final char[] typeValues = ...
+
+    // private static final int[] typeValuesCache = ...
+
+    // Unicode 3.0.1 (same as Unicode 3.0.0)
+    // private static final String uppercaseKeys = ...
+
+    // private static final char[] uppercaseValues = ...
+
+    // private static final int[] uppercaseValuesCache = ...
+
+    // private static final String lowercaseKeys = ...
+
+    // private static final char[] lowercaseValues = ...
+
+    // private static final int[] lowercaseValuesCache = ...
+
+    // private static final String digitKeys = ...
+
+    // private static final char[] digitValues = ...
     // END android-removed
-    
+
+    // BEGIN android-note
+    // put this in a helper class so that it's only initialized on demand?
+    // END android-note
     private static final char[] typeTags = "\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0000\u0000\u0000\u0000\u0000\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0000\u0000\u0000\u0000\u0003\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0000\u0000\u0000\u0000\u0002"
             .getValue();
-    
+
+    // BEGIN android-note
+    // put this in a helper class so that it's only initialized on demand?
+    // END android-note
     private static final byte[] DIRECTIONALITY = new byte[] {
             DIRECTIONALITY_LEFT_TO_RIGHT, DIRECTIONALITY_RIGHT_TO_LEFT,
             DIRECTIONALITY_EUROPEAN_NUMBER,
@@ -557,24 +522,28 @@
     private static final int ISJAVAPART = 2;
 
     // BEGIN android-removed
-    // removed strings containing information about chars that now are read from
-    // icu data.
+    // Unicode 3.0.1 (same as Unicode 3.0.0)
+    // private static final String titlecaseKeys = ...
+
+    // private static final char[] titlecaseValues = ...
+
+    // Unicode 3.0.0 (NOT the same as Unicode 3.0.1)
+    // private static final String numericKeys = ...
+
+    // private static final char[] numericValues = ...
     // END android-removed
-    
-    /**
+
+    /*
      * Represents a subset of the Unicode character set.
-     * 
-     * @since Android 1.0
      */
     public static class Subset {
         String name;
 
         /**
          * Constructs a new {@code Subset}.
-         * 
+         *
          * @param string
          *            this subset's name.
-         * @since Android 1.0
          */
         protected Subset(String string) {
             if (string == null) {
@@ -586,12 +555,11 @@
         /**
          * Compares this character subset with the specified object. Uses
          * {@link java.lang.Object#equals(Object)} to do the comparison.
-         * 
+         *
          * @param object
          *            the object to compare this character subset with.
          * @return {@code true} if {@code object} is this subset, that is, if
          *         {@code object == this}; {@code false} otherwise.
-         * @since Android 1.0
          */
         @Override
         public final boolean equals(Object object) {
@@ -600,10 +568,9 @@
 
         /**
          * Returns the integer hash code for this character subset.
-         * 
+         *
          * @return this subset's hash code, which is the hash code computed by
          *         {@link java.lang.Object#hashCode()}.
-         * @since Android 1.0
          */
         @Override
         public final int hashCode() {
@@ -612,9 +579,8 @@
 
         /**
          * Returns the string representation of this subset.
-         * 
+         *
          * @return this subset's name.
-         * @since Android 1.0
          */
         @Override
         public final String toString() {
@@ -622,799 +588,796 @@
         }
     }
 
-    // BEGIN android-changed
-    
     /**
      * Represents a block of Unicode characters, as defined by the Unicode 4.0.1
      * specification.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.2
      */
     public static final class UnicodeBlock extends Subset {
         /**
          * The &quot;Surrogates Area&quot; Unicode Block.
-         * 
+         *
          * @deprecated As of Java 5, this block has been replaced by
          *             {@link #HIGH_SURROGATES},
          *             {@link #HIGH_PRIVATE_USE_SURROGATES} and
          *             {@link #LOW_SURROGATES}.
-         * @since Android 1.0
          */
         @Deprecated
-        public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA");
+        public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA", 0x0, 0x0);
         /**
-         * The &quot;Basic Latin&quot; Unicode Block. 
+         * The &quot;Basic Latin&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BASIC_LATIN = new UnicodeBlock("BASIC_LATIN");
+        public static final UnicodeBlock BASIC_LATIN = new UnicodeBlock("BASIC_LATIN", 0x0, 0x7f);
         /**
-         * The &quot;Latin-1 Supplement&quot; Unicode Block. 
+         * The &quot;Latin-1 Supplement&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LATIN_1_SUPPLEMENT = new UnicodeBlock("LATIN_1_SUPPLEMENT");
+        public static final UnicodeBlock LATIN_1_SUPPLEMENT = new UnicodeBlock("LATIN_1_SUPPLEMENT", 0x80, 0xff);
         /**
-         * The &quot;Latin Extended-A&quot; Unicode Block. 
+         * The &quot;Latin Extended-A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LATIN_EXTENDED_A = new UnicodeBlock("LATIN_EXTENDED_A");
+        public static final UnicodeBlock LATIN_EXTENDED_A = new UnicodeBlock("LATIN_EXTENDED_A", 0x100, 0x17f);
         /**
-         * The &quot;Latin Extended-B&quot; Unicode Block. 
+         * The &quot;Latin Extended-B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LATIN_EXTENDED_B = new UnicodeBlock("LATIN_EXTENDED_B");
+        public static final UnicodeBlock LATIN_EXTENDED_B = new UnicodeBlock("LATIN_EXTENDED_B", 0x180, 0x24f);
         /**
-         * The &quot;IPA Extensions&quot; Unicode Block. 
+         * The &quot;IPA Extensions&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock IPA_EXTENSIONS = new UnicodeBlock("IPA_EXTENSIONS");
+        public static final UnicodeBlock IPA_EXTENSIONS = new UnicodeBlock("IPA_EXTENSIONS", 0x250, 0x2af);
         /**
-         * The &quot;Spacing Modifier Letters&quot; Unicode Block. 
+         * The &quot;Spacing Modifier Letters&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SPACING_MODIFIER_LETTERS = new UnicodeBlock("SPACING_MODIFIER_LETTERS");
+        public static final UnicodeBlock SPACING_MODIFIER_LETTERS = new UnicodeBlock("SPACING_MODIFIER_LETTERS", 0x2b0, 0x2ff);
         /**
-         * The &quot;Combining Diacritical Marks&quot; Unicode Block. 
+         * The &quot;Combining Diacritical Marks&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS");
+        public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS", 0x300, 0x36f);
         /**
          * The &quot;Greek and Coptic&quot; Unicode Block. Previously referred
          * to as &quot;Greek&quot;.
-         * 
-         * @since Android 1.0
-         */
-        public static final UnicodeBlock GREEK = new UnicodeBlock("GREEK");
-        /**
-         * The &quot;Cyrillic&quot; Unicode Block. 
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CYRILLIC = new UnicodeBlock("CYRILLIC");
+        public static final UnicodeBlock GREEK = new UnicodeBlock("GREEK", 0x370, 0x3ff);
+        /**
+         * The &quot;Cyrillic&quot; Unicode Block.
+         *
+         * @since 1.2
+         */
+        public static final UnicodeBlock CYRILLIC = new UnicodeBlock("CYRILLIC", 0x400, 0x4ff);
         /**
          * The &quot;Cyrillic Supplement&quot; Unicode Block. Previously
          * referred to as &quot;Cyrillic Supplementary&quot;.
-         * 
-         * @since Android 1.0
-         */
-        public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY");
-        /**
-         * The &quot;Armenian&quot; Unicode Block. 
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock ARMENIAN = new UnicodeBlock("ARMENIAN");
+        public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY", 0x500, 0x52f);
         /**
-         * The &quot;Hebrew&quot; Unicode Block. 
+         * The &quot;Armenian&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock HEBREW = new UnicodeBlock("HEBREW");
+        public static final UnicodeBlock ARMENIAN = new UnicodeBlock("ARMENIAN", 0x530, 0x58f);
         /**
-         * The &quot;Arabic&quot; Unicode Block. 
+         * The &quot;Hebrew&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ARABIC = new UnicodeBlock("ARABIC");
+        public static final UnicodeBlock HEBREW = new UnicodeBlock("HEBREW", 0x590, 0x5ff);
         /**
-         * The &quot;Syriac&quot; Unicode Block. 
+         * The &quot;Arabic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SYRIAC = new UnicodeBlock("SYRIAC");
+        public static final UnicodeBlock ARABIC = new UnicodeBlock("ARABIC", 0x600, 0x6ff);
         /**
-         * The &quot;Thaana&quot; Unicode Block. 
+         * The &quot;Syriac&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock THAANA = new UnicodeBlock("THAANA");
+        public static final UnicodeBlock SYRIAC = new UnicodeBlock("SYRIAC", 0x700, 0x74f);
         /**
-         * The &quot;Devanagari&quot; Unicode Block. 
+         * The &quot;Thaana&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock DEVANAGARI = new UnicodeBlock("DEVANAGARI");
+        public static final UnicodeBlock THAANA = new UnicodeBlock("THAANA", 0x780, 0x7bf);
         /**
-         * The &quot;Bengali&quot; Unicode Block. 
+         * The &quot;Devanagari&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BENGALI = new UnicodeBlock("BENGALI");
+        public static final UnicodeBlock DEVANAGARI = new UnicodeBlock("DEVANAGARI", 0x900, 0x97f);
         /**
-         * The &quot;Gurmukhi&quot; Unicode Block. 
+         * The &quot;Bengali&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock GURMUKHI = new UnicodeBlock("GURMUKHI");
+        public static final UnicodeBlock BENGALI = new UnicodeBlock("BENGALI", 0x980, 0x9ff);
         /**
-         * The &quot;Gujarati&quot; Unicode Block. 
+         * The &quot;Gurmukhi&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock GUJARATI = new UnicodeBlock("GUJARATI");
+        public static final UnicodeBlock GURMUKHI = new UnicodeBlock("GURMUKHI", 0xa00, 0xa7f);
         /**
-         * The &quot;Oriya&quot; Unicode Block. 
+         * The &quot;Gujarati&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ORIYA = new UnicodeBlock("ORIYA");
+        public static final UnicodeBlock GUJARATI = new UnicodeBlock("GUJARATI", 0xa80, 0xaff);
         /**
-         * The &quot;Tamil&quot; Unicode Block. 
+         * The &quot;Oriya&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock TAMIL = new UnicodeBlock("TAMIL");
+        public static final UnicodeBlock ORIYA = new UnicodeBlock("ORIYA", 0xb00, 0xb7f);
         /**
-         * The &quot;Telugu&quot; Unicode Block. 
+         * The &quot;Tamil&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock TELUGU = new UnicodeBlock("TELUGU");
+        public static final UnicodeBlock TAMIL = new UnicodeBlock("TAMIL", 0xb80, 0xbff);
         /**
-         * The &quot;Kannada&quot; Unicode Block. 
+         * The &quot;Telugu&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock KANNADA = new UnicodeBlock("KANNADA");
+        public static final UnicodeBlock TELUGU = new UnicodeBlock("TELUGU", 0xc00, 0xc7f);
         /**
-         * The &quot;Malayalam&quot; Unicode Block. 
+         * The &quot;Kannada&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MALAYALAM = new UnicodeBlock("MALAYALAM");
+        public static final UnicodeBlock KANNADA = new UnicodeBlock("KANNADA", 0xc80, 0xcff);
         /**
-         * The &quot;Sinhala&quot; Unicode Block. 
+         * The &quot;Malayalam&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SINHALA = new UnicodeBlock("SINHALA");
+        public static final UnicodeBlock MALAYALAM = new UnicodeBlock("MALAYALAM", 0xd00, 0xd7f);
         /**
-         * The &quot;Thai&quot; Unicode Block. 
+         * The &quot;Sinhala&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock THAI = new UnicodeBlock("THAI");
+        public static final UnicodeBlock SINHALA = new UnicodeBlock("SINHALA", 0xd80, 0xdff);
         /**
-         * The &quot;Lao&quot; Unicode Block. 
+         * The &quot;Thai&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LAO = new UnicodeBlock("LAO");
+        public static final UnicodeBlock THAI = new UnicodeBlock("THAI", 0xe00, 0xe7f);
         /**
-         * The &quot;Tibetan&quot; Unicode Block. 
+         * The &quot;Lao&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock TIBETAN = new UnicodeBlock("TIBETAN");
+        public static final UnicodeBlock LAO = new UnicodeBlock("LAO", 0xe80, 0xeff);
         /**
-         * The &quot;Myanmar&quot; Unicode Block. 
+         * The &quot;Tibetan&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MYANMAR = new UnicodeBlock("MYANMAR");
+        public static final UnicodeBlock TIBETAN = new UnicodeBlock("TIBETAN", 0xf00, 0xfff);
         /**
-         * The &quot;Georgian&quot; Unicode Block. 
+         * The &quot;Myanmar&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock GEORGIAN = new UnicodeBlock("GEORGIAN");
+        public static final UnicodeBlock MYANMAR = new UnicodeBlock("MYANMAR", 0x1000, 0x109f);
         /**
-         * The &quot;Hangul Jamo&quot; Unicode Block. 
+         * The &quot;Georgian&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock HANGUL_JAMO = new UnicodeBlock("HANGUL_JAMO");
+        public static final UnicodeBlock GEORGIAN = new UnicodeBlock("GEORGIAN", 0x10a0, 0x10ff);
         /**
-         * The &quot;Ethiopic&quot; Unicode Block. 
+         * The &quot;Hangul Jamo&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ETHIOPIC = new UnicodeBlock("ETHIOPIC");
+        public static final UnicodeBlock HANGUL_JAMO = new UnicodeBlock("HANGUL_JAMO", 0x1100, 0x11ff);
         /**
-         * The &quot;Cherokee&quot; Unicode Block. 
+         * The &quot;Ethiopic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock CHEROKEE = new UnicodeBlock("CHEROKEE");
+        public static final UnicodeBlock ETHIOPIC = new UnicodeBlock("ETHIOPIC", 0x1200, 0x137f);
         /**
-         * The &quot;Unified Canadian Aboriginal Syllabics&quot; Unicode Block. 
+         * The &quot;Cherokee&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS");
+        public static final UnicodeBlock CHEROKEE = new UnicodeBlock("CHEROKEE", 0x13a0, 0x13ff);
         /**
-         * The &quot;Ogham&quot; Unicode Block. 
+         * The &quot;Unified Canadian Aboriginal Syllabics&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock OGHAM = new UnicodeBlock("OGHAM");
+        public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS", 0x1400, 0x167f);
         /**
-         * The &quot;Runic&quot; Unicode Block. 
+         * The &quot;Ogham&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock RUNIC = new UnicodeBlock("RUNIC");
+        public static final UnicodeBlock OGHAM = new UnicodeBlock("OGHAM", 0x1680, 0x169f);
         /**
-         * The &quot;Tagalog&quot; Unicode Block. 
+         * The &quot;Runic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock TAGALOG = new UnicodeBlock("TAGALOG");
+        public static final UnicodeBlock RUNIC = new UnicodeBlock("RUNIC", 0x16a0, 0x16ff);
         /**
-         * The &quot;Hanunoo&quot; Unicode Block. 
+         * The &quot;Tagalog&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock HANUNOO = new UnicodeBlock("HANUNOO");
+        public static final UnicodeBlock TAGALOG = new UnicodeBlock("TAGALOG", 0x1700, 0x171f);
         /**
-         * The &quot;Buhid&quot; Unicode Block. 
+         * The &quot;Hanunoo&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock BUHID = new UnicodeBlock("BUHID");
+        public static final UnicodeBlock HANUNOO = new UnicodeBlock("HANUNOO", 0x1720, 0x173f);
         /**
-         * The &quot;Tagbanwa&quot; Unicode Block. 
+         * The &quot;Buhid&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock TAGBANWA = new UnicodeBlock("TAGBANWA");
+        public static final UnicodeBlock BUHID = new UnicodeBlock("BUHID", 0x1740, 0x175f);
         /**
-         * The &quot;Khmer&quot; Unicode Block. 
+         * The &quot;Tagbanwa&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock KHMER = new UnicodeBlock("KHMER");
+        public static final UnicodeBlock TAGBANWA = new UnicodeBlock("TAGBANWA", 0x1760, 0x177f);
         /**
-         * The &quot;Mongolian&quot; Unicode Block. 
+         * The &quot;Khmer&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock MONGOLIAN = new UnicodeBlock("MONGOLIAN");
+        public static final UnicodeBlock KHMER = new UnicodeBlock("KHMER", 0x1780, 0x17ff);
         /**
-         * The &quot;Limbu&quot; Unicode Block. 
+         * The &quot;Mongolian&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock LIMBU = new UnicodeBlock("LIMBU");
+        public static final UnicodeBlock MONGOLIAN = new UnicodeBlock("MONGOLIAN", 0x1800, 0x18af);
         /**
-         * The &quot;Tai Le&quot; Unicode Block. 
+         * The &quot;Limbu&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock TAI_LE = new UnicodeBlock("TAI_LE");
+        public static final UnicodeBlock LIMBU = new UnicodeBlock("LIMBU", 0x1900, 0x194f);
         /**
-         * The &quot;Khmer Symbols&quot; Unicode Block. 
+         * The &quot;Tai Le&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock KHMER_SYMBOLS = new UnicodeBlock("KHMER_SYMBOLS");
+        public static final UnicodeBlock TAI_LE = new UnicodeBlock("TAI_LE", 0x1950, 0x197f);
         /**
-         * The &quot;Phonetic Extensions&quot; Unicode Block. 
+         * The &quot;Khmer Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock PHONETIC_EXTENSIONS = new UnicodeBlock("PHONETIC_EXTENSIONS");
+        public static final UnicodeBlock KHMER_SYMBOLS = new UnicodeBlock("KHMER_SYMBOLS", 0x19e0, 0x19ff);
         /**
-         * The &quot;Latin Extended Additional&quot; Unicode Block. 
+         * The &quot;Phonetic Extensions&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL");
+        public static final UnicodeBlock PHONETIC_EXTENSIONS = new UnicodeBlock("PHONETIC_EXTENSIONS", 0x1d00, 0x1d7f);
         /**
-         * The &quot;Greek Extended&quot; Unicode Block. 
+         * The &quot;Latin Extended Additional&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock GREEK_EXTENDED = new UnicodeBlock("GREEK_EXTENDED");
+        public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL", 0x1e00, 0x1eff);
         /**
-         * The &quot;General Punctuation&quot; Unicode Block. 
+         * The &quot;Greek Extended&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock GENERAL_PUNCTUATION = new UnicodeBlock("GENERAL_PUNCTUATION");
+        public static final UnicodeBlock GREEK_EXTENDED = new UnicodeBlock("GREEK_EXTENDED", 0x1f00, 0x1fff);
         /**
-         * The &quot;Superscripts and Subscripts&quot; Unicode Block. 
+         * The &quot;General Punctuation&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS");
+        public static final UnicodeBlock GENERAL_PUNCTUATION = new UnicodeBlock("GENERAL_PUNCTUATION", 0x2000, 0x206f);
         /**
-         * The &quot;Currency Symbols&quot; Unicode Block. 
+         * The &quot;Superscripts and Subscripts&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CURRENCY_SYMBOLS = new UnicodeBlock("CURRENCY_SYMBOLS");
+        public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS", 0x2070, 0x209f);
+        /**
+         * The &quot;Currency Symbols&quot; Unicode Block.
+         *
+         * @since 1.2
+         */
+        public static final UnicodeBlock CURRENCY_SYMBOLS = new UnicodeBlock("CURRENCY_SYMBOLS", 0x20a0, 0x20cf);
         /**
          * The &quot;Combining Diacritical Marks for Symbols&quot; Unicode
          * Block. Previously referred to as &quot;Combining Marks for
          * Symbols&quot;.
-         * 
-         * @since Android 1.0
-         */
-        public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS");
-        /**
-         * The &quot;Letterlike Symbols&quot; Unicode Block. 
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LETTERLIKE_SYMBOLS = new UnicodeBlock("LETTERLIKE_SYMBOLS");
+        public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS", 0x20d0, 0x20ff);
         /**
-         * The &quot;Number Forms&quot; Unicode Block. 
+         * The &quot;Letterlike Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock NUMBER_FORMS = new UnicodeBlock("NUMBER_FORMS");
+        public static final UnicodeBlock LETTERLIKE_SYMBOLS = new UnicodeBlock("LETTERLIKE_SYMBOLS", 0x2100, 0x214f);
         /**
-         * The &quot;Arrows&quot; Unicode Block. 
+         * The &quot;Number Forms&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ARROWS = new UnicodeBlock("ARROWS");
+        public static final UnicodeBlock NUMBER_FORMS = new UnicodeBlock("NUMBER_FORMS", 0x2150, 0x218f);
         /**
-         * The &quot;Mathematical Operators&quot; Unicode Block. 
+         * The &quot;Arrows&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MATHEMATICAL_OPERATORS = new UnicodeBlock("MATHEMATICAL_OPERATORS");
+        public static final UnicodeBlock ARROWS = new UnicodeBlock("ARROWS", 0x2190, 0x21ff);
         /**
-         * The &quot;Miscellaneous Technical&quot; Unicode Block. 
+         * The &quot;Mathematical Operators&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = new UnicodeBlock("MISCELLANEOUS_TECHNICAL");
+        public static final UnicodeBlock MATHEMATICAL_OPERATORS = new UnicodeBlock("MATHEMATICAL_OPERATORS", 0x2200, 0x22ff);
         /**
-         * The &quot;Control Pictures&quot; Unicode Block. 
+         * The &quot;Miscellaneous Technical&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CONTROL_PICTURES = new UnicodeBlock("CONTROL_PICTURES");
+        public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = new UnicodeBlock("MISCELLANEOUS_TECHNICAL", 0x2300, 0x23ff);
         /**
-         * The &quot;Optical Character Recognition&quot; Unicode Block. 
+         * The &quot;Control Pictures&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION");
+        public static final UnicodeBlock CONTROL_PICTURES = new UnicodeBlock("CONTROL_PICTURES", 0x2400, 0x243f);
         /**
-         * The &quot;Enclosed Alphanumerics&quot; Unicode Block. 
+         * The &quot;Optical Character Recognition&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = new UnicodeBlock("ENCLOSED_ALPHANUMERICS");
+        public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION", 0x2440, 0x245f);
         /**
-         * The &quot;Box Drawing&quot; Unicode Block. 
+         * The &quot;Enclosed Alphanumerics&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BOX_DRAWING = new UnicodeBlock("BOX_DRAWING");
+        public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = new UnicodeBlock("ENCLOSED_ALPHANUMERICS", 0x2460, 0x24ff);
         /**
-         * The &quot;Block Elements&quot; Unicode Block. 
+         * The &quot;Box Drawing&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BLOCK_ELEMENTS = new UnicodeBlock("BLOCK_ELEMENTS");
+        public static final UnicodeBlock BOX_DRAWING = new UnicodeBlock("BOX_DRAWING", 0x2500, 0x257f);
         /**
-         * The &quot;Geometric Shapes&quot; Unicode Block. 
+         * The &quot;Block Elements&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock GEOMETRIC_SHAPES = new UnicodeBlock("GEOMETRIC_SHAPES");
+        public static final UnicodeBlock BLOCK_ELEMENTS = new UnicodeBlock("BLOCK_ELEMENTS", 0x2580, 0x259f);
         /**
-         * The &quot;Miscellaneous Symbols&quot; Unicode Block. 
+         * The &quot;Geometric Shapes&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS");
+        public static final UnicodeBlock GEOMETRIC_SHAPES = new UnicodeBlock("GEOMETRIC_SHAPES", 0x25a0, 0x25ff);
         /**
-         * The &quot;Dingbats&quot; Unicode Block. 
+         * The &quot;Miscellaneous Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock DINGBATS = new UnicodeBlock("DINGBATS");
+        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS", 0x2600, 0x26ff);
         /**
-         * The &quot;Miscellaneous Mathematical Symbols-A&quot; Unicode Block. 
+         * The &quot;Dingbats&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A");
+        public static final UnicodeBlock DINGBATS = new UnicodeBlock("DINGBATS", 0x2700, 0x27bf);
         /**
-         * The &quot;Supplemental Arrows-A&quot; Unicode Block. 
+         * The &quot;Miscellaneous Mathematical Symbols-A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = new UnicodeBlock("SUPPLEMENTAL_ARROWS_A");
+        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A", 0x27c0, 0x27ef);
         /**
-         * The &quot;Braille Patterns&quot; Unicode Block. 
+         * The &quot;Supplemental Arrows-A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock BRAILLE_PATTERNS = new UnicodeBlock("BRAILLE_PATTERNS");
+        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = new UnicodeBlock("SUPPLEMENTAL_ARROWS_A", 0x27f0, 0x27ff);
         /**
-         * The &quot;Supplemental Arrows-B&quot; Unicode Block. 
+         * The &quot;Braille Patterns&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = new UnicodeBlock("SUPPLEMENTAL_ARROWS_B");
+        public static final UnicodeBlock BRAILLE_PATTERNS = new UnicodeBlock("BRAILLE_PATTERNS", 0x2800, 0x28ff);
         /**
-         * The &quot;Miscellaneous Mathematical Symbols-B&quot; Unicode Block. 
+         * The &quot;Supplemental Arrows-B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B");
+        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = new UnicodeBlock("SUPPLEMENTAL_ARROWS_B", 0x2900, 0x297f);
         /**
-         * The &quot;Supplemental Mathematical Operators&quot; Unicode Block. 
+         * The &quot;Miscellaneous Mathematical Symbols-B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS");
+        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B", 0x2980, 0x29ff);
         /**
-         * The &quot;Miscellaneous Symbols and Arrows&quot; Unicode Block. 
+         * The &quot;Supplemental Mathematical Operators&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS");
+        public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS", 0x2a00, 0x2aff);
         /**
-         * The &quot;CJK Radicals Supplement&quot; Unicode Block. 
+         * The &quot;Miscellaneous Symbols and Arrows&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = new UnicodeBlock("CJK_RADICALS_SUPPLEMENT");
+        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS", 0x2b00, 0x2bff);
         /**
-         * The &quot;Kangxi Radicals&quot; Unicode Block. 
+         * The &quot;CJK Radicals Supplement&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock KANGXI_RADICALS = new UnicodeBlock("KANGXI_RADICALS");
+        public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = new UnicodeBlock("CJK_RADICALS_SUPPLEMENT", 0x2e80, 0x2eff);
         /**
-         * The &quot;Ideographic Description Characters&quot; Unicode Block. 
+         * The &quot;Kangxi Radicals&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS");
+        public static final UnicodeBlock KANGXI_RADICALS = new UnicodeBlock("KANGXI_RADICALS", 0x2f00, 0x2fdf);
         /**
-         * The &quot;CJK Symbols and Punctuation&quot; Unicode Block. 
+         * The &quot;Ideographic Description Characters&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION");
+        public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS", 0x2ff0, 0x2fff);
         /**
-         * The &quot;Hiragana&quot; Unicode Block. 
+         * The &quot;CJK Symbols and Punctuation&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock HIRAGANA = new UnicodeBlock("HIRAGANA");
+        public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION", 0x3000, 0x303f);
         /**
-         * The &quot;Katakana&quot; Unicode Block. 
+         * The &quot;Hiragana&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock KATAKANA = new UnicodeBlock("KATAKANA");
+        public static final UnicodeBlock HIRAGANA = new UnicodeBlock("HIRAGANA", 0x3040, 0x309f);
         /**
-         * The &quot;Bopomofo&quot; Unicode Block. 
+         * The &quot;Katakana&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BOPOMOFO = new UnicodeBlock("BOPOMOFO");
+        public static final UnicodeBlock KATAKANA = new UnicodeBlock("KATAKANA", 0x30a0, 0x30ff);
         /**
-         * The &quot;Hangul Compatibility Jamo&quot; Unicode Block. 
+         * The &quot;Bopomofo&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO");
+        public static final UnicodeBlock BOPOMOFO = new UnicodeBlock("BOPOMOFO", 0x3100, 0x312f);
         /**
-         * The &quot;Kanbun&quot; Unicode Block. 
+         * The &quot;Hangul Compatibility Jamo&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock KANBUN = new UnicodeBlock("KANBUN");
+        public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO", 0x3130, 0x318f);
         /**
-         * The &quot;Bopomofo Extended&quot; Unicode Block. 
+         * The &quot;Kanbun&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BOPOMOFO_EXTENDED = new UnicodeBlock("BOPOMOFO_EXTENDED");
+        public static final UnicodeBlock KANBUN = new UnicodeBlock("KANBUN", 0x3190, 0x319f);
         /**
-         * The &quot;Katakana Phonetic Extensions&quot; Unicode Block. 
+         * The &quot;Bopomofo Extended&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS");
+        public static final UnicodeBlock BOPOMOFO_EXTENDED = new UnicodeBlock("BOPOMOFO_EXTENDED", 0x31a0, 0x31bf);
         /**
-         * The &quot;Enclosed CJK Letters and Months&quot; Unicode Block. 
+         * The &quot;Katakana Phonetic Extensions&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS");
+        public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS", 0x31f0, 0x31ff);
         /**
-         * The &quot;CJK Compatibility&quot; Unicode Block. 
+         * The &quot;Enclosed CJK Letters and Months&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CJK_COMPATIBILITY = new UnicodeBlock("CJK_COMPATIBILITY");
+        public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS", 0x3200, 0x32ff);
         /**
-         * The &quot;CJK Unified Ideographs Extension A&quot; Unicode Block. 
+         * The &quot;CJK Compatibility&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A");
+        public static final UnicodeBlock CJK_COMPATIBILITY = new UnicodeBlock("CJK_COMPATIBILITY", 0x3300, 0x33ff);
         /**
-         * The &quot;Yijing Hexagram Symbols&quot; Unicode Block. 
+         * The &quot;CJK Unified Ideographs Extension A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS");
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", 0x3400, 0x4dbf);
         /**
-         * The &quot;CJK Unified Ideographs&quot; Unicode Block. 
+         * The &quot;Yijing Hexagram Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS");
+        public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS", 0x4dc0, 0x4dff);
         /**
-         * The &quot;Yi Syllables&quot; Unicode Block. 
+         * The &quot;CJK Unified Ideographs&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock YI_SYLLABLES = new UnicodeBlock("YI_SYLLABLES");
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS", 0x4e00, 0x9fff);
         /**
-         * The &quot;Yi Radicals&quot; Unicode Block. 
+         * The &quot;Yi Syllables&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock YI_RADICALS = new UnicodeBlock("YI_RADICALS");
+        public static final UnicodeBlock YI_SYLLABLES = new UnicodeBlock("YI_SYLLABLES", 0xa000, 0xa48f);
         /**
-         * The &quot;Hangul Syllables&quot; Unicode Block. 
+         * The &quot;Yi Radicals&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock HANGUL_SYLLABLES = new UnicodeBlock("HANGUL_SYLLABLES");
+        public static final UnicodeBlock YI_RADICALS = new UnicodeBlock("YI_RADICALS", 0xa490, 0xa4cf);
+        /**
+         * The &quot;Hangul Syllables&quot; Unicode Block.
+         *
+         * @since 1.2
+         */
+        public static final UnicodeBlock HANGUL_SYLLABLES = new UnicodeBlock("HANGUL_SYLLABLES", 0xac00, 0xd7af);
         /**
          * The &quot;High Surrogates&quot; Unicode Block. This block represents
          * code point values in the high surrogate range 0xD800 to 0xDB7F
-         * 
-         * @since Android 1.0
          */
-        public static final UnicodeBlock HIGH_SURROGATES = new UnicodeBlock("HIGH_SURROGATES");
+        public static final UnicodeBlock HIGH_SURROGATES = new UnicodeBlock("HIGH_SURROGATES", 0xd800, 0xdb7f);
         /**
          * The &quot;High Private Use Surrogates&quot; Unicode Block. This block
          * represents code point values in the high surrogate range 0xDB80 to
          * 0xDBFF
-         * 
-         * @since Android 1.0
          */
-        public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES");
+        public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES", 0xdb80, 0xdbff);
         /**
          * The &quot;Low Surrogates&quot; Unicode Block. This block represents
          * code point values in the low surrogate range 0xDC00 to 0xDFFF
-         * 
-         * @since Android 1.0
          */
-        public static final UnicodeBlock LOW_SURROGATES = new UnicodeBlock("LOW_SURROGATES");
+        public static final UnicodeBlock LOW_SURROGATES = new UnicodeBlock("LOW_SURROGATES", 0xdc00, 0xdfff);
         /**
-         * The &quot;Private Use Area&quot; Unicode Block. 
+         * The &quot;Private Use Area&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock PRIVATE_USE_AREA = new UnicodeBlock("PRIVATE_USE_AREA");
+        public static final UnicodeBlock PRIVATE_USE_AREA = new UnicodeBlock("PRIVATE_USE_AREA", 0xe000, 0xf8ff);
         /**
-         * The &quot;CJK Compatibility Ideographs&quot; Unicode Block. 
+         * The &quot;CJK Compatibility Ideographs&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS");
+        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS", 0xf900, 0xfaff);
         /**
-         * The &quot;Alphabetic Presentation Forms&quot; Unicode Block. 
+         * The &quot;Alphabetic Presentation Forms&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS");
+        public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS", 0xfb00, 0xfb4f);
         /**
-         * The &quot;Arabic Presentation Forms-A&quot; Unicode Block. 
+         * The &quot;Arabic Presentation Forms-A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A");
+        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A", 0xfb50, 0xfdff);
         /**
-         * The &quot;Variation Selectors&quot; Unicode Block. 
+         * The &quot;Variation Selectors&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock VARIATION_SELECTORS = new UnicodeBlock("VARIATION_SELECTORS");
+        public static final UnicodeBlock VARIATION_SELECTORS = new UnicodeBlock("VARIATION_SELECTORS", 0xfe00, 0xfe0f);
         /**
-         * The &quot;Combining Half Marks&quot; Unicode Block. 
+         * The &quot;Combining Half Marks&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock COMBINING_HALF_MARKS = new UnicodeBlock("COMBINING_HALF_MARKS");
+        public static final UnicodeBlock COMBINING_HALF_MARKS = new UnicodeBlock("COMBINING_HALF_MARKS", 0xfe20, 0xfe2f);
         /**
-         * The &quot;CJK Compatibility Forms&quot; Unicode Block. 
+         * The &quot;CJK Compatibility Forms&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = new UnicodeBlock("CJK_COMPATIBILITY_FORMS");
+        public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = new UnicodeBlock("CJK_COMPATIBILITY_FORMS", 0xfe30, 0xfe4f);
         /**
-         * The &quot;Small Form Variants&quot; Unicode Block. 
+         * The &quot;Small Form Variants&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SMALL_FORM_VARIANTS = new UnicodeBlock("SMALL_FORM_VARIANTS");
+        public static final UnicodeBlock SMALL_FORM_VARIANTS = new UnicodeBlock("SMALL_FORM_VARIANTS", 0xfe50, 0xfe6f);
         /**
-         * The &quot;Arabic Presentation Forms-B&quot; Unicode Block. 
+         * The &quot;Arabic Presentation Forms-B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B");
+        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B", 0xfe70, 0xfeff);
         /**
-         * The &quot;Halfwidth and Fullwidth Forms&quot; Unicode Block. 
+         * The &quot;Halfwidth and Fullwidth Forms&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS");
+        public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS", 0xff00, 0xffef);
         /**
-         * The &quot;Specials&quot; Unicode Block. 
+         * The &quot;Specials&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SPECIALS = new UnicodeBlock("SPECIALS");
+        public static final UnicodeBlock SPECIALS = new UnicodeBlock("SPECIALS", 0xfff0, 0xffff);
         /**
-         * The &quot;Linear B Syllabary&quot; Unicode Block. 
+         * The &quot;Linear B Syllabary&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LINEAR_B_SYLLABARY = new UnicodeBlock("LINEAR_B_SYLLABARY");
+        public static final UnicodeBlock LINEAR_B_SYLLABARY = new UnicodeBlock("LINEAR_B_SYLLABARY", 0x10000, 0x1007f);
         /**
-         * The &quot;Linear B Ideograms&quot; Unicode Block. 
+         * The &quot;Linear B Ideograms&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock LINEAR_B_IDEOGRAMS = new UnicodeBlock("LINEAR_B_IDEOGRAMS");
+        public static final UnicodeBlock LINEAR_B_IDEOGRAMS = new UnicodeBlock("LINEAR_B_IDEOGRAMS", 0x10080, 0x100ff);
         /**
-         * The &quot;Aegean Numbers&quot; Unicode Block. 
+         * The &quot;Aegean Numbers&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock AEGEAN_NUMBERS = new UnicodeBlock("AEGEAN_NUMBERS");
+        public static final UnicodeBlock AEGEAN_NUMBERS = new UnicodeBlock("AEGEAN_NUMBERS", 0x10100, 0x1013f);
         /**
-         * The &quot;Old Italic&quot; Unicode Block. 
+         * The &quot;Old Italic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock OLD_ITALIC = new UnicodeBlock("OLD_ITALIC");
+        public static final UnicodeBlock OLD_ITALIC = new UnicodeBlock("OLD_ITALIC", 0x10300, 0x1032f);
         /**
-         * The &quot;Gothic&quot; Unicode Block. 
+         * The &quot;Gothic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC");
+        public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC", 0x10330, 0x1034f);
         /**
-         * The &quot;Ugaritic&quot; Unicode Block. 
+         * The &quot;Ugaritic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC");
+        public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC", 0x10380, 0x1039f);
         /**
-         * The &quot;Deseret&quot; Unicode Block. 
+         * The &quot;Deseret&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET");
+        public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET", 0x10400, 0x1044f);
         /**
-         * The &quot;Shavian&quot; Unicode Block. 
+         * The &quot;Shavian&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN");
+        public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN", 0x10450, 0x1047f);
         /**
-         * The &quot;Osmanya&quot; Unicode Block. 
+         * The &quot;Osmanya&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA");
+        public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA", 0x10480, 0x104af);
         /**
-         * The &quot;Cypriot Syllabary&quot; Unicode Block. 
+         * The &quot;Cypriot Syllabary&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock CYPRIOT_SYLLABARY = new UnicodeBlock("CYPRIOT_SYLLABARY");
+        public static final UnicodeBlock CYPRIOT_SYLLABARY = new UnicodeBlock("CYPRIOT_SYLLABARY", 0x10800, 0x1083f);
         /**
-         * The &quot;Byzantine Musical Symbols&quot; Unicode Block. 
+         * The &quot;Byzantine Musical Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS");
+        public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS", 0x1d000, 0x1d0ff);
         /**
-         * The &quot;Musical Symbols&quot; Unicode Block. 
+         * The &quot;Musical Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock MUSICAL_SYMBOLS = new UnicodeBlock("MUSICAL_SYMBOLS");
+        public static final UnicodeBlock MUSICAL_SYMBOLS = new UnicodeBlock("MUSICAL_SYMBOLS", 0x1d100, 0x1d1ff);
         /**
-         * The &quot;Tai Xuan Jing Symbols&quot; Unicode Block. 
+         * The &quot;Tai Xuan Jing Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = new UnicodeBlock("TAI_XUAN_JING_SYMBOLS");
+        public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = new UnicodeBlock("TAI_XUAN_JING_SYMBOLS", 0x1d300, 0x1d35f);
         /**
-         * The &quot;Mathematical Alphanumeric Symbols&quot; Unicode Block. 
+         * The &quot;Mathematical Alphanumeric Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS");
+        public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS", 0x1d400, 0x1d7ff);
         /**
-         * The &quot;CJK Unified Ideographs Extension B&quot; Unicode Block. 
+         * The &quot;CJK Unified Ideographs Extension B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B");
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B", 0x20000, 0x2a6df);
         /**
-         * The &quot;CJK Compatibility Ideographs Supplement&quot; Unicode Block. 
+         * The &quot;CJK Compatibility Ideographs Supplement&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT");
+        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT", 0x2f800, 0x2fa1f);
         /**
-         * The &quot;Tags&quot; Unicode Block. 
+         * The &quot;Tags&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS");
+        public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS", 0xe0000, 0xe007f);
         /**
-         * The &quot;Variation Selectors Supplement&quot; Unicode Block. 
+         * The &quot;Variation Selectors Supplement&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT");
+        public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT", 0xe0100, 0xe01ef);
         /**
-         * The &quot;Supplementary Private Use Area-A&quot; Unicode Block. 
+         * The &quot;Supplementary Private Use Area-A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A");
+        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A", 0xf0000, 0xfffff);
         /**
-         * The &quot;Supplementary Private Use Area-B&quot; Unicode Block. 
+         * The &quot;Supplementary Private Use Area-B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B");
+        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B", 0x100000, 0x10ffff);
 
         /*
          * All of the UnicodeBlocks with valid ranges in ascending order.
          */
         private static UnicodeBlock[] BLOCKS;
 
+        // BEGIN android-changed
+        // /*
+        //  * A SortedMap (String.CASE_INSENSITIVE_ORDER) with keys that represents
+        //  * valid block names and values of the UnicodeBlock constant they map
+        //  * to.
+        //  */
+        // private static final SortedMap<String, UnicodeBlock> BLOCKS_BY_NAME = ...;
         // END android-changed
-        
+
         /**
          * Retrieves the constant that corresponds to the specified block name.
          * The block names are defined by the Unicode 4.0.1 specification in the
          * {@code Blocks-4.0.1.txt} file.
          * <p>
          * Block names may be one of the following:
-         * </p>
          * <ul>
          * <li>Canonical block name, as defined by the Unicode specification;
          * case-insensitive.</li>
@@ -1424,13 +1387,15 @@
          * uppercasing the canonical name and replacing all spaces and hyphens
          * with underscores.</li>
          * </ul>
-         * 
+         *
          * @param blockName
          *            the name of the block to retrieve.
          * @return the UnicodeBlock constant corresponding to {@code blockName}.
+         * @throws NullPointerException
+         *             if {@code blockName} is {@code null}.
          * @throws IllegalArgumentException
          *             if {@code blockName} is not a valid block name.
-         * @since Android 1.0
+         * @since 1.5
          */
         public static final UnicodeBlock forName(String blockName) {
             // BEGIN android-note
@@ -1449,7 +1414,7 @@
                     return SURROGATES_AREA;
                 } else if(blockName.equalsIgnoreCase("greek")) {
                     return GREEK;
-                } else if(blockName.equals("COMBINING_MARKS_FOR_SYMBOLS") || 
+                } else if(blockName.equals("COMBINING_MARKS_FOR_SYMBOLS") ||
                         blockName.equals("Combining Marks for Symbols") ||
                         blockName.equals("CombiningMarksforSymbols")) {
                     return COMBINING_MARKS_FOR_SYMBOLS;
@@ -1459,27 +1424,26 @@
             return BLOCKS[block];
             // END android-changed
         }
-        
+
         /**
          * Gets the constant for the Unicode block that contains the specified
          * character.
-         * 
+         *
          * @param c
          *            the character for which to get the {@code UnicodeBlock}
          *            constant.
          * @return the {@code UnicodeBlock} constant for the block that contains
          *         {@code c}, or {@code null} if {@code c} does not belong to
          *         any defined block.
-         * @since Android 1.0
          */
         public static UnicodeBlock of(char c) {
             return of((int) c);
         }
-        
+
         /**
          * Gets the constant for the Unicode block that contains the specified
          * Unicode code point.
-         * 
+         *
          * @param codePoint
          *            the Unicode code point for which to get the
          *            {@code UnicodeBlock} constant.
@@ -1488,7 +1452,7 @@
          *         not belong to any defined block.
          * @throws IllegalArgumentException
          *             if {@code codePoint} is not a valid Unicode code point.
-         * @since Android 1.0
+         * @since 1.5
          */
         public static UnicodeBlock of(int codePoint) {
             if (!isValidCodePoint(codePoint)) {
@@ -1505,9 +1469,9 @@
             return BLOCKS[block];
             // END android-changed
         }
-        
+
         // BEGIN android-changed
-        private UnicodeBlock(String blockName) {
+        private UnicodeBlock(String blockName, int start, int end) {
             super(blockName);
         }
         // END android-changed
@@ -1516,10 +1480,9 @@
     /**
      * Constructs a new {@code Character} with the specified primitive char
      * value.
-     * 
+     *
      * @param value
      *            the primitive char value to store in the new instance.
-     * @since Android 1.0
      */
     public Character(char value) {
         this.value = value;
@@ -1527,9 +1490,8 @@
 
     /**
      * Gets the primitive value of this character.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     public char charValue() {
         return value;
@@ -1538,7 +1500,7 @@
     /**
      * Compares this object to the specified character object to determine their
      * relative order.
-     * 
+     *
      * @param c
      *            the character object to compare this object to.
      * @return {@code 0} if the value of this character and the value of
@@ -1547,22 +1509,22 @@
      *         value if the value of this character is less than the value of
      *         {@code c}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Character c) {
         return value - c.value;
     }
-    
+
     /**
      * Returns a {@code Character} instance for the {@code char} value passed.
      * For ASCII/Latin-1 characters (and generally all characters with a Unicode
      * value up to 512), this method should be used instead of the constructor,
      * as it maintains a cache of corresponding {@code Character} instances.
-     * 
+     *
      * @param c
      *            the char value for which to get a {@code Character} instance.
      * @return the {@code Character} instance for {@code c}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Character valueOf(char c) {
         if (c >= CACHE_LEN ) {
@@ -1589,12 +1551,12 @@
     }
     /**
      * Indicates whether {@code codePoint} is a valid Unicode code point.
-     * 
+     *
      * @param codePoint
      *            the code point to test.
      * @return {@code true} if {@code codePoint} is a valid Unicode code point;
      *         {@code false} otherwise.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static boolean isValidCodePoint(int codePoint) {
         return (MIN_CODE_POINT <= codePoint && MAX_CODE_POINT >= codePoint);
@@ -1603,12 +1565,12 @@
     /**
      * Indicates whether {@code codePoint} is within the supplementary code
      * point range.
-     * 
+     *
      * @param codePoint
      *            the code point to test.
      * @return {@code true} if {@code codePoint} is within the supplementary
      *         code point range; {@code false} otherwise.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static boolean isSupplementaryCodePoint(int codePoint) {
         return (MIN_SUPPLEMENTARY_CODE_POINT <= codePoint && MAX_CODE_POINT >= codePoint);
@@ -1618,13 +1580,13 @@
      * Indicates whether {@code ch} is a high- (or leading-) surrogate code unit
      * that is used for representing supplementary characters in UTF-16
      * encoding.
-     * 
+     *
      * @param ch
      *            the character to test.
      * @return {@code true} if {@code ch} is a high-surrogate code unit;
      *         {@code false} otherwise.
      * @see #isLowSurrogate(char)
-     * @since Android 1.0
+     * @since 1.5
      */
     public static boolean isHighSurrogate(char ch) {
         return (MIN_HIGH_SURROGATE <= ch && MAX_HIGH_SURROGATE >= ch);
@@ -1634,21 +1596,21 @@
      * Indicates whether {@code ch} is a low- (or trailing-) surrogate code unit
      * that is used for representing supplementary characters in UTF-16
      * encoding.
-     * 
+     *
      * @param ch
      *            the character to test.
      * @return {@code true} if {@code ch} is a low-surrogate code unit;
      *         {@code false} otherwise.
      * @see #isHighSurrogate(char)
-     * @since Android 1.0
-     */    
+     * @since 1.5
+     */
     public static boolean isLowSurrogate(char ch) {
         return (MIN_LOW_SURROGATE <= ch && MAX_LOW_SURROGATE >= ch);
     }
 
     /**
      * Indicates whether the specified character pair is a valid surrogate pair.
-     * 
+     *
      * @param high
      *            the high surrogate unit to test.
      * @param low
@@ -1658,7 +1620,7 @@
      *         otherwise.
      * @see #isHighSurrogate(char)
      * @see #isLowSurrogate(char)
-     * @since Android 1.0
+     * @since 1.5
      */
     public static boolean isSurrogatePair(char high, char low) {
         return (isHighSurrogate(high) && isLowSurrogate(low));
@@ -1670,12 +1632,14 @@
      * is greater than or equal to {@code 0x10000}, in which case {@code 2} is
      * returned, otherwise {@code 1}. To test if the code point is valid, use
      * the {@link #isValidCodePoint(int)} method.
-     * 
+     *
      * @param codePoint
      *            the code point for which to calculate the number of required
      *            chars.
      * @return {@code 2} if {@code codePoint >= 0x10000}; {@code 1} otherwise.
-     * @since Android 1.0
+     * @see #isValidCodePoint(int)
+     * @see #isSupplementaryCodePoint(int)
+     * @since 1.5
      */
     public static int charCount(int codePoint) {
         return (codePoint >= 0x10000 ? 2 : 1);
@@ -1687,14 +1651,14 @@
      * surrogates, then the result is indeterminate. The
      * {@link #isSurrogatePair(char, char)} method should be used prior to this
      * method to validate the pair.
-     * 
+     *
      * @param high
      *            the high surrogate unit.
      * @param low
      *            the low surrogate unit.
      * @return the Unicode code point corresponding to the surrogate unit pair.
      * @see #isSurrogatePair(char, char)
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int toCodePoint(char high, char low) {
         // See RFC 2781, Section 2.2
@@ -1711,7 +1675,7 @@
      * {@code index + 1} is a low-surrogate unit, then the supplementary code
      * point represented by the pair is returned; otherwise the {@code char}
      * value at {@code index} is returned.
-     * 
+     *
      * @param seq
      *            the source sequence of {@code char} units.
      * @param index
@@ -1719,10 +1683,12 @@
      *            point.
      * @return the Unicode code point or {@code char} value at {@code index} in
      *         {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if the {@code index} is negative or greater than or equal to
      *             the length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointAt(CharSequence seq, int index) {
         if (seq == null) {
@@ -1751,7 +1717,7 @@
      * {@code index + 1} is a low-surrogate unit, then the supplementary code
      * point represented by the pair is returned; otherwise the {@code char}
      * value at {@code index} is returned.
-     * 
+     *
      * @param seq
      *            the source array of {@code char} units.
      * @param index
@@ -1759,10 +1725,12 @@
      *            point.
      * @return the Unicode code point or {@code char} value at {@code index} in
      *         {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if the {@code index} is negative or greater than or equal to
      *             the length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointAt(char[] seq, int index) {
         if (seq == null) {
@@ -1792,7 +1760,7 @@
      * low-surrogate unit, then the supplementary code point represented by the
      * pair is returned; otherwise the {@code char} value at {@code index} is
      * returned.
-     * 
+     *
      * @param seq
      *            the source array of {@code char} units.
      * @param index
@@ -1801,16 +1769,18 @@
      *            the index after the last unit in {@code seq} that can be used.
      * @return the Unicode code point or {@code char} value at {@code index} in
      *         {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0}, {@code index >= limit},
      *             {@code limit < 0} or if {@code limit} is greater than the
      *             length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointAt(char[] seq, int index, int limit) {
         if (index < 0 || index >= limit || limit < 0 || limit > seq.length) {
             throw new IndexOutOfBoundsException();
-        }       
+        }
 
         char high = seq[index++];
         if (index >= limit) {
@@ -1830,7 +1800,7 @@
      * {@code index - 2} is a high-surrogate unit, then the supplementary code
      * point represented by the pair is returned; otherwise the {@code char}
      * value at {@code index - 1} is returned.
-     * 
+     *
      * @param seq
      *            the source sequence of {@code char} units.
      * @param index
@@ -1838,10 +1808,12 @@
      *            point that should be returned.
      * @return the Unicode code point or {@code char} value before {@code index}
      *         in {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if the {@code index} is less than 1 or greater than the
      *             length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointBefore(CharSequence seq, int index) {
         if (seq == null) {
@@ -1870,7 +1842,7 @@
      * {@code index - 2} is a high-surrogate unit, then the supplementary code
      * point represented by the pair is returned; otherwise the {@code char}
      * value at {@code index - 1} is returned.
-     * 
+     *
      * @param seq
      *            the source array of {@code char} units.
      * @param index
@@ -1878,10 +1850,12 @@
      *            point that should be returned.
      * @return the Unicode code point or {@code char} value before {@code index}
      *         in {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if the {@code index} is less than 1 or greater than the
      *             length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointBefore(char[] seq, int index) {
         if (seq == null) {
@@ -1911,7 +1885,7 @@
      * high-surrogate unit, then the supplementary code point represented by the
      * pair is returned; otherwise the {@code char} value at {@code index - 1}
      * is returned.
-     * 
+     *
      * @param seq
      *            the source array of {@code char} units.
      * @param index
@@ -1921,12 +1895,14 @@
      *            the index of the first element in {@code seq}.
      * @return the Unicode code point or {@code char} value before {@code index}
      *         in {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if the {@code index <= start}, {@code start < 0},
      *             {@code index} is greater than the length of {@code seq}, or
      *             if {@code start} is equal or greater than the length of
      *             {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointBefore(char[] seq, int index, int start) {
         if (seq == null) {
@@ -1952,7 +1928,7 @@
      * Converts the specified Unicode code point into a UTF-16 encoded sequence
      * and copies the value(s) into the char array {@code dst}, starting at
      * index {@code dstIndex}.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to encode.
      * @param dst
@@ -1962,12 +1938,14 @@
      * @return the number of {@code char} value units copied into {@code dst}.
      * @throws IllegalArgumentException
      *             if {@code codePoint} is not a valid Unicode code point.
+     * @throws NullPointerException
+     *             if {@code dst} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code dstIndex} is negative, greater than or equal to
      *             {@code dst.length} or equals {@code dst.length - 1} when
      *             {@code codePoint} is a
      *             {@link #isSupplementaryCodePoint(int) supplementary code point}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int toChars(int codePoint, char[] dst, int dstIndex) {
         if (!isValidCodePoint(codePoint)) {
@@ -2001,7 +1979,7 @@
     /**
      * Converts the specified Unicode code point into a UTF-16 encoded sequence
      * and returns it as a char array.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to encode.
      * @return the UTF-16 encoded char sequence. If {@code codePoint} is a
@@ -2010,7 +1988,7 @@
      *         contains just one character.
      * @throws IllegalArgumentException
      *             if {@code codePoint} is not a valid Unicode code point.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static char[] toChars(int codePoint) {
         if (!isValidCodePoint(codePoint)) {
@@ -2031,7 +2009,7 @@
      * specified character sequence, as delineated by {@code beginIndex} and
      * {@code endIndex}. Any surrogate values with missing pair values will be
      * counted as one code point.
-     * 
+     *
      * @param seq
      *            the {@code CharSequence} to look through.
      * @param beginIndex
@@ -2039,10 +2017,12 @@
      * @param endIndex
      *            the exclusive index to stop counting at.
      * @return the number of Unicode code points.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code beginIndex < 0}, {@code beginIndex > endIndex} or
      *             if {@code endIndex} is greater than the length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointCount(CharSequence seq, int beginIndex,
             int endIndex) {
@@ -2075,7 +2055,7 @@
      * specified char array, as delineated by {@code offset} and {@code count}.
      * Any surrogate values with missing pair values will be counted as one code
      * point.
-     * 
+     *
      * @param seq
      *            the char array to look through
      * @param offset
@@ -2084,11 +2064,13 @@
      *            the number of {@code char} values to look through in
      *            {@code seq}.
      * @return the number of Unicode code points.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0}, {@code count < 0} or if
      *             {@code offset + count} is greater than the length of
      *             {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointCount(char[] seq, int offset, int count) {
         if (seq == null) {
@@ -2119,7 +2101,7 @@
     /**
      * Determines the index in the specified character sequence that is offset
      * {@code codePointOffset} code points from {@code index}.
-     * 
+     *
      * @param seq
      *            the character sequence to find the index in.
      * @param index
@@ -2129,13 +2111,15 @@
      *            be a negative or positive value.
      * @return the index in {@code seq} that is {@code codePointOffset} code
      *         points away from {@code index}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0}, {@code index} is greater than the
      *             length of {@code seq}, or if there are not enough values in
      *             {@code seq} to skip {@code codePointOffset} code points
      *             forwards or backwards (if {@code codePointOffset} is
      *             negative) from {@code index}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int offsetByCodePoints(CharSequence seq, int index,
             int codePointOffset) {
@@ -2193,7 +2177,7 @@
      * Determines the index in a subsequence of the specified character array
      * that is offset {@code codePointOffset} code points from {@code index}.
      * The subsequence is delineated by {@code start} and {@code count}.
-     * 
+     *
      * @param seq
      *            the character array to find the index in.
      * @param start
@@ -2209,6 +2193,8 @@
      *            be a negative or positive value.
      * @return the index in {@code seq} that is {@code codePointOffset} code
      *         points away from {@code index}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0}, {@code count < 0},
      *             {@code index < start}, {@code index > start + count},
@@ -2217,7 +2203,7 @@
      *             {@code seq} to skip {@code codePointOffset} code points
      *             forward or backward (if {@code codePointOffset} is
      *             negative) from {@code index}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int offsetByCodePoints(char[] seq, int start, int count,
             int index, int codePointOffset) {
@@ -2276,14 +2262,13 @@
      * Convenience method to determine the value of the specified character
      * {@code c} in the supplied radix. The value of {@code radix} must be
      * between MIN_RADIX and MAX_RADIX.
-     * 
+     *
      * @param c
      *            the character to determine the value of.
      * @param radix
      *            the radix.
      * @return the value of {@code c} in {@code radix} if {@code radix} lies
      *         between {@link #MIN_RADIX} and {@link #MAX_RADIX}; -1 otherwise.
-     * @since Android 1.0
      */
     public static int digit(char c, int radix) {
         // BEGIN android-changed
@@ -2313,12 +2298,12 @@
         return UCharacter.digit(c, radix);
         // ENd android-changed
     }
-    
+
     /**
      * Convenience method to determine the value of the character
      * {@code codePoint} in the supplied radix. The value of {@code radix} must
      * be between MIN_RADIX and MAX_RADIX.
-     * 
+     *
      * @param codePoint
      *            the character, including supplementary characters.
      * @param radix
@@ -2326,7 +2311,6 @@
      * @return if {@code radix} lies between {@link #MIN_RADIX} and
      *         {@link #MAX_RADIX} then the value of the character in the radix;
      *         -1 otherwise.
-     * @since Android 1.0
      */
     public static int digit(int codePoint, int radix) {
         return UCharacter.digit(codePoint, radix);
@@ -2336,12 +2320,11 @@
      * Compares this object with the specified object and indicates if they are
      * equal. In order to be equal, {@code object} must be an instance of
      * {@code Character} and have the same char value as this object.
-     * 
+     *
      * @param object
      *            the object to compare this double with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Character}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -2355,14 +2338,13 @@
      * {@code MAX_RADIX} inclusive; {@code digit} must not be negative and
      * smaller than {@code radix}. If any of these conditions does not hold, 0
      * is returned.
-     * 
+     *
      * @param digit
      *            the integer value.
      * @param radix
      *            the radix.
      * @return the character which represents the {@code digit} in the
      *         {@code radix}.
-     * @since Android 1.0
      */
     public static char forDigit(int digit, int radix) {
         if (MIN_RADIX <= radix && radix <= MAX_RADIX) {
@@ -2375,13 +2357,12 @@
 
     /**
      * Gets the numeric value of the specified Unicode character.
-     * 
+     *
      * @param c
      *            the Unicode character to get the numeric value of.
      * @return a non-negative numeric integer value if a numeric value for
      *         {@code c} exists, -1 if there is no numeric value for {@code c},
      *         -2 if the numeric value can not be represented with an integer.
-     * @since Android 1.0
      */
     public static int getNumericValue(char c) {
         // BEGIN android-changed
@@ -2414,19 +2395,18 @@
         return UCharacter.getNumericValue(c);
         // END android-changed
     }
-    
+
     /**
      * Gets the numeric value of the specified Unicode code point. For example,
      * the code point '\u216B' stands for the Roman number XII, which has the
      * numeric value 12.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to get the numeric value of.
      * @return a non-negative numeric integer value if a numeric value for
      *         {@code codePoint} exists, -1 if there is no numeric value for
      *         {@code codePoint}, -2 if the numeric value can not be
      *         represented with an integer.
-     * @since Android 1.0
      */
     public static int getNumericValue(int codePoint) {
         return UCharacter.getNumericValue(codePoint);
@@ -2434,14 +2414,16 @@
 
     /**
      * Gets the general Unicode category of the specified character.
-     * 
+     *
      * @param c
      *            the character to get the category of.
      * @return the Unicode category of {@code c}.
-     * @since Android 1.0
      */
     public static int getType(char c) {
         // BEGIN android-changed
+        // if(c < 1000) {
+        //     return typeValuesCache[(int)c];
+        // }
         // int result = BinarySearch.binarySearchRange(typeKeys, c);
         // int high = typeValues[result * 2];
         // if (c <= high) {
@@ -2452,19 +2434,23 @@
         //     return (c & 1) == 1 ? code >> 8 : code & 0xff;
         // }
         // return UNASSIGNED;
-        return getType((int)c);
+        return getType((int) c);
         // END android-changed
     }
-    
+
     /**
      * Gets the general Unicode category of the specified code point.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to get the category of.
      * @return the Unicode category of {@code codePoint}.
-     * @since Android 1.0
      */
     public static int getType(int codePoint) {
+        // BEGIN android-changed
+    	// if (codePoint < 1000 && codePoint > 0) {
+    	//     return typeValuesCache[codePoint];
+    	// }
+        // END android-changed
         int type = UCharacter.getType(codePoint);
 
         // the type values returned by UCharacter are not compatible with what
@@ -2477,11 +2463,10 @@
 
     /**
      * Gets the Unicode directionality of the specified character.
-     * 
+     *
      * @param c
      *            the character to get the directionality of.
      * @return the Unicode directionality of {@code c}.
-     * @since Android 1.0
      */
     public static byte getDirectionality(char c) {
         // BEGIN android-changed
@@ -2498,21 +2483,20 @@
         return getDirectionality((int)c);
         // END android-changed
     }
-    
+
     /**
      * Gets the Unicode directionality of the specified character.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to get the directionality of.
      * @return the Unicode directionality of {@code codePoint}.
-     * @since Android 1.0
      */
     public static byte getDirectionality(int codePoint) {
         if (getType(codePoint) == Character.UNASSIGNED) {
             return Character.DIRECTIONALITY_UNDEFINED;
         }
-        
-        byte UCDirectionality = UCharacter.getDirectionality(codePoint);       
+
+        byte UCDirectionality = UCharacter.getDirectionality(codePoint);
         if (UCDirectionality == -1) {
             return -1;
         }
@@ -2521,12 +2505,11 @@
 
     /**
      * Indicates whether the specified character is mirrored.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is mirrored; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isMirrored(char c) {
         // BEGIN android-changed
@@ -2539,15 +2522,14 @@
         return isMirrored((int)c);
         // ENd android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is mirrored.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is mirrored, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isMirrored(int codePoint) {
         return UCharacter.isMirrored(codePoint);
@@ -2561,12 +2543,11 @@
     /**
      * Indicates whether the specified character is defined in the Unicode
      * specification.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if the general Unicode category of the character is
      *         not {@code UNASSIGNED}; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isDefined(char c) {
         // BEGIN android-changed
@@ -2574,16 +2555,15 @@
         return UCharacter.isDefined(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is defined in the Unicode
      * specification.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if the general Unicode category of the code point is
      *         not {@code UNASSIGNED}; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isDefined(int codePoint) {
         return UCharacter.isDefined(codePoint);
@@ -2591,12 +2571,11 @@
 
     /**
      * Indicates whether the specified character is a digit.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a digit; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isDigit(char c) {
         // BEGIN android-changed
@@ -2611,15 +2590,14 @@
         return UCharacter.isDigit(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a digit.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a digit; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isDigit(int codePoint) {
         return UCharacter.isDigit(codePoint);
@@ -2628,11 +2606,10 @@
     /**
      * Indicates whether the specified character is ignorable in a Java or
      * Unicode identifier.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is ignorable; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isIdentifierIgnorable(char c) {
         // BEGIN android-changed
@@ -2641,16 +2618,15 @@
         return UCharacter.isIdentifierIgnorable(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is ignorable in a Java or
      * Unicode identifier.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is ignorable; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isIdentifierIgnorable(int codePoint) {
         return UCharacter.isIdentifierIgnorable(codePoint);
@@ -2658,12 +2634,11 @@
 
     /**
      * Indicates whether the specified character is an ISO control character.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is an ISO control character;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isISOControl(char c) {
         return isISOControl((int)c);
@@ -2671,12 +2646,11 @@
 
     /**
      * Indicates whether the specified code point is an ISO control character.
-     * 
+     *
      * @param c
      *            the code point to check.
      * @return {@code true} if {@code c} is an ISO control character;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isISOControl(int c) {
         return (c >= 0 && c <= 0x1f) || (c >= 0x7f && c <= 0x9f);
@@ -2685,12 +2659,11 @@
     /**
      * Indicates whether the specified character is a valid part of a Java
      * identifier other than the first character.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is valid as part of a Java identifier;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isJavaIdentifierPart(char c) {
         // Optimized case for ASCII
@@ -2709,31 +2682,29 @@
     /**
      * Indicates whether the specified code point is a valid part of a Java
      * identifier other than the first character.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code c} is valid as part of a Java identifier;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isJavaIdentifierPart(int codePoint) {
         int type = getType(codePoint);
         return (type >= UPPERCASE_LETTER && type <= OTHER_LETTER)
                 || type == CURRENCY_SYMBOL || type == CONNECTOR_PUNCTUATION
                 || (type >= DECIMAL_DIGIT_NUMBER && type <= LETTER_NUMBER)
-                || type == COMBINING_SPACING_MARK || type == NON_SPACING_MARK 
+                || type == COMBINING_SPACING_MARK || type == NON_SPACING_MARK
                 || isIdentifierIgnorable(codePoint);
     }
 
     /**
      * Indicates whether the specified character is a valid first character for
      * a Java identifier.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a valid first character of a Java
      *         identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isJavaIdentifierStart(char c) {
         // Optimized case for ASCII
@@ -2746,16 +2717,15 @@
                 || type == CURRENCY_SYMBOL || type == CONNECTOR_PUNCTUATION
                 || type == LETTER_NUMBER;
     }
-    
+
     /**
      * Indicates whether the specified code point is a valid start for a Java
      * identifier.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a valid start of a Java
      *         identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isJavaIdentifierStart(int codePoint) {
         int type = getType(codePoint);
@@ -2765,13 +2735,12 @@
 
     /**
      * Indicates whether the specified character is a Java letter.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a Java letter; {@code false}
      *         otherwise.
      * @deprecated Use {@link #isJavaIdentifierStart(char)}
-     * @since Android 1.0
      */
     @Deprecated
     public static boolean isJavaLetter(char c) {
@@ -2781,13 +2750,12 @@
     /**
      * Indicates whether the specified character is a Java letter or digit
      * character.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a Java letter or digit;
      *         {@code false} otherwise.
      * @deprecated Use {@link #isJavaIdentifierPart(char)}
-     * @since Android 1.0
      */
     @Deprecated
     public static boolean isJavaLetterOrDigit(char c) {
@@ -2796,11 +2764,10 @@
 
     /**
      * Indicates whether the specified character is a letter.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a letter; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isLetter(char c) {
         // BEGIN android-changed
@@ -2815,15 +2782,14 @@
         return UCharacter.isLetter(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a letter.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a letter; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isLetter(int codePoint) {
         return UCharacter.isLetter(codePoint);
@@ -2831,12 +2797,11 @@
 
     /**
      * Indicates whether the specified character is a letter or a digit.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a letter or a digit; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isLetterOrDigit(char c) {
         // BEGIN android-changed
@@ -2846,15 +2811,14 @@
         return UCharacter.isLetterOrDigit(c);
         // END andorid-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a letter or a digit.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a letter or a digit;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isLetterOrDigit(int codePoint) {
         return UCharacter.isLetterOrDigit(codePoint);
@@ -2862,12 +2826,11 @@
 
     /**
      * Indicates whether the specified character is a lower case letter.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a lower case letter; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isLowerCase(char c) {
         // BEGIN android-changed
@@ -2878,20 +2841,19 @@
         // if (c < 128) {
         //     return false;
         // }
-        // 
+        //
         // return getType(c) == LOWERCASE_LETTER;
         return UCharacter.isLowerCase(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a lower case letter.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a lower case letter;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isLowerCase(int codePoint) {
         return UCharacter.isLowerCase(codePoint);
@@ -2899,13 +2861,12 @@
 
     /**
      * Indicates whether the specified character is a Java space.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a Java space; {@code false}
      *         otherwise.
      * @deprecated Use {@link #isWhitespace(char)}
-     * @since Android 1.0
      */
     @Deprecated
     public static boolean isSpace(char c) {
@@ -2916,12 +2877,11 @@
      * Indicates whether the specified character is a Unicode space character.
      * That is, if it is a member of one of the Unicode categories Space
      * Separator, Line Separator, or Paragraph Separator.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a Unicode space character,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isSpaceChar(char c) {
         // BEGIN android-changed
@@ -2936,17 +2896,16 @@
         return UCharacter.isSpaceChar(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a Unicode space character.
      * That is, if it is a member of one of the Unicode categories Space
      * Separator, Line Separator, or Paragraph Separator.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a Unicode space character,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isSpaceChar(int codePoint) {
         return UCharacter.isSpaceChar(codePoint);
@@ -2954,12 +2913,11 @@
 
     /**
      * Indicates whether the specified character is a titlecase character.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a titlecase character, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isTitleCase(char c) {
         // BEGIN android-changed
@@ -2978,15 +2936,14 @@
         return UCharacter.isTitleCase(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a titlecase character.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a titlecase character,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isTitleCase(int codePoint) {
         return UCharacter.isTitleCase(codePoint);
@@ -2995,12 +2952,11 @@
     /**
      * Indicates whether the specified character is valid as part of a Unicode
      * identifier other than the first character.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is valid as part of a Unicode
      *         identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isUnicodeIdentifierPart(char c) {
         // BEGIN android-changed
@@ -3013,16 +2969,15 @@
         return UCharacter.isUnicodeIdentifierPart(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is valid as part of a Unicode
      * identifier other than the first character.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is valid as part of a Unicode
      *         identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isUnicodeIdentifierPart(int codePoint) {
         return UCharacter.isUnicodeIdentifierPart(codePoint);
@@ -3031,12 +2986,11 @@
     /**
      * Indicates whether the specified character is a valid initial character
      * for a Unicode identifier.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a valid first character for a
      *         Unicode identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isUnicodeIdentifierStart(char c) {
         // BEGIN android-changed
@@ -3046,16 +3000,15 @@
         return UCharacter.isUnicodeIdentifierStart(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a valid initial character
      * for a Unicode identifier.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a valid first character for
      *         a Unicode identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isUnicodeIdentifierStart(int codePoint) {
         return UCharacter.isUnicodeIdentifierStart(codePoint);
@@ -3063,12 +3016,11 @@
 
     /**
      * Indicates whether the specified character is an upper case letter.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a upper case letter; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isUpperCase(char c) {
         // BEGIN android-changed
@@ -3079,20 +3031,19 @@
         // if (c < 128) {
         //     return false;
         // }
-        // 
+        //
         // return getType(c) == UPPERCASE_LETTER;
         return UCharacter.isUpperCase(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is an upper case letter.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a upper case letter;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isUpperCase(int codePoint) {
         return UCharacter.isUpperCase(codePoint);
@@ -3101,12 +3052,11 @@
     /**
      * Indicates whether the specified character is a whitespace character in
      * Java.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if the supplied {@code c} is a whitespace character
      *         in Java; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isWhitespace(char c) {
         // BEGIN android-changed
@@ -3124,30 +3074,29 @@
         return UCharacter.isWhitespace(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a whitespace character in
      * Java.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if the supplied {@code c} is a whitespace character
      *         in Java; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isWhitespace(int codePoint) {
         //FIXME depends on ICU when the codePoint is '\u2007'
         return UCharacter.isWhitespace(codePoint);
+
     }
 
     /**
      * Reverses the order of the first and second byte in the specified
      * character.
-     * 
+     *
      * @param c
      *            the character to reverse.
      * @return the character with reordered bytes.
-     * @since Android 1.0
      */
     public static char reverseBytes(char c) {
         return (char)((c<<8) | (c>>8));
@@ -3157,12 +3106,11 @@
      * Returns the lower case equivalent for the specified character if the
      * character is an upper case letter. Otherwise, the specified character is
      * returned unchanged.
-     * 
+     *
      * @param c
      *            the character
      * @return if {@code c} is an upper case character then its lower case
      *         counterpart, otherwise just {@code c}.
-     * @since Android 1.0
      */
     public static char toLowerCase(char c) {
         // BEGIN android-changed
@@ -3170,10 +3118,13 @@
         // if ('A' <= c && c <= 'Z') {
         //     return (char) (c + ('a' - 'A'));
         // }
-        // if (c < 128) {
+        // if (c < 192) {// || c == 215 || (c > 222 && c < 256)) {
         //     return c;
         // }
-        // 
+        // if (c<1000) {
+        //     return (char)lowercaseValuesCache[c-192];
+        // }
+        //
         // int result = BinarySearch.binarySearchRange(lowercaseKeys, c);
         // if (result >= 0) {
         //     boolean by2 = false;
@@ -3195,17 +3146,16 @@
         return (char)UCharacter.toLowerCase(c);
         // END android-changed
     }
-    
+
     /**
      * Returns the lower case equivalent for the specified code point if it is
      * an upper case letter. Otherwise, the specified code point is returned
      * unchanged.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return if {@code codePoint} is an upper case character then its lower
      *         case counterpart, otherwise just {@code codePoint}.
-     * @since Android 1.0
      */
     public static int toLowerCase(int codePoint) {
         return UCharacter.toLowerCase(codePoint);
@@ -3218,11 +3168,10 @@
 
     /**
      * Converts the specified character to its string representation.
-     * 
+     *
      * @param value
      *            the character to convert.
      * @return the character converted to a string.
-     * @since Android 1.0
      */
     public static String toString(char value) {
         return String.valueOf(value);
@@ -3231,12 +3180,11 @@
     /**
      * Returns the title case equivalent for the specified character if it
      * exists. Otherwise, the specified character is returned unchanged.
-     * 
+     *
      * @param c
      *            the character to convert.
      * @return the title case equivalent of {@code c} if it exists, otherwise
      *         {@code c}.
-     * @since Android 1.0
      */
     public static char toTitleCase(char c) {
         // BEGIN android-changed
@@ -3251,16 +3199,15 @@
         return (char)UCharacter.toTitleCase(c);
         // ENd android-changed
     }
-    
+
     /**
      * Returns the title case equivalent for the specified code point if it
      * exists. Otherwise, the specified code point is returned unchanged.
-     * 
+     *
      * @param codePoint
      *            the code point to convert.
      * @return the title case equivalent of {@code codePoint} if it exists,
      *         otherwise {@code codePoint}.
-     * @since Android 1.0
      */
     public static int toTitleCase(int codePoint) {
         return UCharacter.toTitleCase(codePoint);
@@ -3270,12 +3217,11 @@
      * Returns the upper case equivalent for the specified character if the
      * character is a lower case letter. Otherwise, the specified character is
      * returned unchanged.
-     * 
+     *
      * @param c
      *            the character to convert.
      * @return if {@code c} is a lower case character then its upper case
      *         counterpart, otherwise just {@code c}.
-     * @since Android 1.0
      */
     public static char toUpperCase(char c) {
         // BEGIN android-changed
@@ -3283,10 +3229,12 @@
         // if ('a' <= c && c <= 'z') {
         //     return (char) (c - ('a' - 'A'));
         // }
-        // if (c < 128) {
+        // if (c < 181) {
         //     return c;
         // }
-        // 
+        // if (c<1000) {
+        //     return (char)uppercaseValuesCache[(int)c-181];
+        // }
         // int result = BinarySearch.binarySearchRange(uppercaseKeys, c);
         // if (result >= 0) {
         //     boolean by2 = false;
@@ -3308,17 +3256,16 @@
         return (char)UCharacter.toUpperCase(c);
         // END android-changed
     }
-    
+
     /**
      * Returns the upper case equivalent for the specified code point if the
      * code point is a lower case letter. Otherwise, the specified code point is
      * returned unchanged.
-     * 
+     *
      * @param codePoint
      *            the code point to convert.
      * @return if {@code codePoint} is a lower case character then its upper
      *         case counterpart, otherwise just {@code codePoint}.
-     * @since Android 1.0
      */
     public static int toUpperCase(int codePoint) {
         return UCharacter.toUpperCase(codePoint);
diff --git a/luni/src/main/java/java/lang/ClassCastException.java b/luni/src/main/java/java/lang/ClassCastException.java
index 1482b21..b33efcf 100644
--- a/luni/src/main/java/java/lang/ClassCastException.java
+++ b/luni/src/main/java/java/lang/ClassCastException.java
@@ -22,8 +22,6 @@
 /**
  * Thrown when a program attempts to cast a an object to a type with which it is
  * not compatible.
- * 
- * @since Android 1.0
  */
 public class ClassCastException extends RuntimeException {
     private static final long serialVersionUID = -9223365651070458532L;
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code ClassCastException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public ClassCastException() {
         super();
@@ -41,10 +37,9 @@
     /**
      * Constructs a new {@code ClassCastException} with the current stack trace
      * and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ClassCastException(String detailMessage) {
         super(detailMessage);
@@ -53,12 +48,11 @@
     /**
      * Constructs a new {@code ClassCastException} with the current stack trace
      * and a detail message based on the source and target class.
-     * 
+     *
      * @param instanceClass
      *            the class being cast from.
      * @param castClass
      *            the class being cast to.
-     * @since Android 1.0
      */
     ClassCastException(Class<?> instanceClass, Class<?> castClass) {
         super(Msg.getString("K0340", instanceClass.getName(), castClass //$NON-NLS-1$
diff --git a/luni/src/main/java/java/lang/ClassCircularityError.java b/luni/src/main/java/java/lang/ClassCircularityError.java
index 6dd1c8e..07bf339 100644
--- a/luni/src/main/java/java/lang/ClassCircularityError.java
+++ b/luni/src/main/java/java/lang/ClassCircularityError.java
@@ -24,9 +24,6 @@
  * <p>
  * Note that this error can only occur when inconsistent class files are loaded,
  * since it would normally be detected at compile time.
- * </p>
- * 
- * @since Android 1.0
  */
 public class ClassCircularityError extends LinkageError {
 
@@ -35,8 +32,6 @@
     /**
      * Constructs a new {@code ClassCircularityError} that include the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public ClassCircularityError() {
         super();
@@ -45,10 +40,9 @@
     /**
      * Constructs a new {@code ClassCircularityError} with the current stack
      * trace and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public ClassCircularityError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/ClassFormatError.java b/luni/src/main/java/java/lang/ClassFormatError.java
index 282ed70..009f44a 100644
--- a/luni/src/main/java/java/lang/ClassFormatError.java
+++ b/luni/src/main/java/java/lang/ClassFormatError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown by a class loader when a class file has an illegal format or if the
  * data that it contains can not be interpreted as a class.
- * 
- * @since Android 1.0
  */
 public class ClassFormatError extends LinkageError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code ClassFormatError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public ClassFormatError() {
         super();
@@ -40,10 +36,9 @@
     /**
      * Constructs a new {@code ClassFormatError} with the current stack trace
      * and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public ClassFormatError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/ClassNotFoundException.java b/luni/src/main/java/java/lang/ClassNotFoundException.java
index 26bdbf7..2ac3b49 100644
--- a/luni/src/main/java/java/lang/ClassNotFoundException.java
+++ b/luni/src/main/java/java/lang/ClassNotFoundException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when a class loader is unable to find a class.
- * 
- * @since Android 1.0
  */
 public class ClassNotFoundException extends Exception {
 
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code ClassNotFoundException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public ClassNotFoundException() {
         super((Throwable) null);
@@ -41,10 +37,9 @@
     /**
      * Constructs a new {@code ClassNotFoundException} with the current stack
      * trace and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ClassNotFoundException(String detailMessage) {
         super(detailMessage, null);
@@ -54,12 +49,11 @@
      * Constructs a new {@code ClassNotFoundException} with the current stack
      * trace, the specified detail message and the exception that occurred when
      * loading the class.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
      * @param exception
      *            the exception which occurred while loading the class.
-     * @since Android 1.0
      */
     public ClassNotFoundException(String detailMessage, Throwable exception) {
         super(detailMessage);
@@ -68,7 +62,7 @@
 
     /**
      * Returns the exception which occurred when loading the class.
-     * 
+     *
      * @return Throwable the exception which occurred while loading the class.
      */
     public Throwable getException() {
@@ -78,7 +72,7 @@
     /**
      * Returns the cause of this Throwable, or {@code null} if there is no
      * cause.
-     * 
+     *
      * @return Throwable the receiver's cause.
      */
     @Override
diff --git a/luni/src/main/java/java/lang/CloneNotSupportedException.java b/luni/src/main/java/java/lang/CloneNotSupportedException.java
index b484e08..2f4f11c 100644
--- a/luni/src/main/java/java/lang/CloneNotSupportedException.java
+++ b/luni/src/main/java/java/lang/CloneNotSupportedException.java
@@ -20,9 +20,8 @@
 /**
  * Thrown when a program attempts to clone an object which does not support the
  * {@link Cloneable} interface.
- * 
+ *
  * @see Cloneable
- * @since Android 1.0
  */
 public class CloneNotSupportedException extends Exception {
 
@@ -31,8 +30,6 @@
     /**
      * Constructs a new {@code CloneNotSupportedException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public CloneNotSupportedException() {
         super();
@@ -41,10 +38,9 @@
     /**
      * Constructs a new {@code CloneNotSupportedException} with the current
      * stack trace and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public CloneNotSupportedException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/Comparable.java b/luni/src/main/java/java/lang/Comparable.java
index c50f112..df10416 100644
--- a/luni/src/main/java/java/lang/Comparable.java
+++ b/luni/src/main/java/java/lang/Comparable.java
@@ -28,21 +28,17 @@
  * invertible (the sign of the result of x.compareTo(y) must be equal to the
  * negation of the sign of the result of y.compareTo(x) for all combinations of
  * x and y).
- * </p>
  * <p>
  * In addition, it is recommended (but not required) that if and only if the
  * result of x.compareTo(y) is zero, then the result of x.equals(y) should be
  * {@code true}.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface Comparable<T> {
-    
+
     /**
      * Compares this object to the specified object to determine their relative
      * order.
-     * 
+     *
      * @param another
      *            the object to compare to this instance.
      * @return a negative integer if this instance is less than {@code another};
@@ -52,7 +48,6 @@
      * @throws ClassCastException
      *             if {@code another} cannot be converted into something
      *             comparable to {@code this} instance.
-     * @since Android 1.0
      */
     int compareTo(T another);
 }
diff --git a/luni/src/main/java/java/lang/Deprecated.java b/luni/src/main/java/java/lang/Deprecated.java
index eb356c2..047a6be 100644
--- a/luni/src/main/java/java/lang/Deprecated.java
+++ b/luni/src/main/java/java/lang/Deprecated.java
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
- * 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
+ *     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,
@@ -18,17 +18,16 @@
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * Annotation type used to mark program elements that should no longer be used
  * by programmers. Compilers produce a warning if a deprecated program element
  * is used.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 @Documented
-@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
-public @interface Deprecated
-{
-
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Deprecated {
 }
diff --git a/luni/src/main/java/java/lang/Double.java b/luni/src/main/java/java/lang/Double.java
index c50b27d..bc0c380 100644
--- a/luni/src/main/java/java/lang/Double.java
+++ b/luni/src/main/java/java/lang/Double.java
@@ -19,9 +19,9 @@
 
 /**
  * The wrapper for the primitive type {@code double}.
- * 
+ *
  * @see java.lang.Number
- * @since Android 1.0
+ * @since 1.0
  */
 public final class Double extends Number implements Comparable<Double> {
 
@@ -35,15 +35,11 @@
     /**
      * Constant for the maximum {@code double} value, (2 - 2<sup>-52</sup>) *
      * 2<sup>1023</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final double MAX_VALUE = 1.79769313486231570e+308;
 
     /**
      * Constant for the minimum {@code double} value, 2<sup>-1074</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final double MIN_VALUE = 5e-324;
 
@@ -51,30 +47,24 @@
 
     /**
      * Constant for the Not-a-Number (NaN) value of the {@code double} type.
-     * 
-     * @since Android 1.0
      */
     public static final double NaN = 0.0 / 0.0;
 
     /**
      * Constant for the Positive Infinity value of the {@code double} type.
-     * 
-     * @since Android 1.0
      */
     public static final double POSITIVE_INFINITY = 1.0 / 0.0;
 
     /**
      * Constant for the Negative Infinity value of the {@code double} type.
-     * 
-     * @since Android 1.0
      */
     public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
 
     /**
      * The {@link Class} object that represents the primitive type {@code
      * double}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.1
      */
     @SuppressWarnings("unchecked")
     public static final Class<Double> TYPE = (Class<Double>) new double[0]
@@ -86,18 +76,17 @@
     /**
      * Constant for the number of bits needed to represent a {@code double} in
      * two's complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 64;
 
     /**
      * Constructs a new {@code Double} with the specified primitive double
      * value.
-     * 
+     *
      * @param value
      *            the primitive double value to store in the new instance.
-     * @since Android 1.0
      */
     public Double(double value) {
         this.value = value;
@@ -105,13 +94,12 @@
 
     /**
      * Constructs a new {@code Double} from the specified string.
-     * 
+     *
      * @param string
      *            the string representation of a double value.
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into a double value.
      * @see #parseDouble(String)
-     * @since Android 1.0
      */
     public Double(String string) throws NumberFormatException {
         this(parseDouble(string));
@@ -125,36 +113,20 @@
      * than any other double value, including {@code Double.POSITIVE_INFINITY};</li>
      * <li>+0.0d is greater than -0.0d</li>
      * </ul>
-     * 
+     *
      * @param object
      *            the double object to compare this object to.
      * @return a negative value if the value of this double is less than the
      *         value of {@code object}; 0 if the value of this double and the
      *         value of {@code object} are equal; a positive value if the value
      *         of this double is greater than the value of {@code object}.
+     * @throws NullPointerException
+     *             if {@code object} is {@code null}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Double object) {
-        long d1, d2;
-        long NaNbits = Double.doubleToLongBits(Double.NaN);
-        if ((d1 = Double.doubleToLongBits(value)) == NaNbits) {
-            if (Double.doubleToLongBits(object.value) == NaNbits) {
-                return 0;
-            }
-            return 1;
-        }
-        if ((d2 = Double.doubleToLongBits(object.value)) == NaNbits) {
-            return -1;
-        }
-        if (value == object.value) {
-            if (d1 == d2) {
-                return 0;
-            }
-            // check for -0
-            return d1 > d2 ? 1 : -1;
-        }
-        return value > object.value ? 1 : -1;
+        return compare(value, object.value);
     }
 
     @Override
@@ -167,14 +139,13 @@
      * to the IEEE 754 floating-point double precision bit layout. All
      * <em>Not-a-Number (NaN)</em> values are converted to a single NaN
      * representation ({@code 0x7ff8000000000000L}).
-     * 
+     *
      * @param value
      *            the double value to convert.
      * @return the IEEE 754 floating-point double precision representation of
      *         {@code value}.
      * @see #doubleToRawLongBits(double)
      * @see #longBitsToDouble(long)
-     * @since Android 1.0
      */
     public static native long doubleToLongBits(double value);
 
@@ -182,22 +153,20 @@
      * Converts the specified double value to a binary representation conforming
      * to the IEEE 754 floating-point double precision bit layout.
      * <em>Not-a-Number (NaN)</em> values are preserved.
-     * 
+     *
      * @param value
      *            the double value to convert.
      * @return the IEEE 754 floating-point double precision representation of
      *         {@code value}.
      * @see #doubleToLongBits(double)
      * @see #longBitsToDouble(long)
-     * @since Android 1.0
      */
     public static native long doubleToRawLongBits(double value);
 
     /**
      * Gets the primitive value of this double.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public double doubleValue() {
@@ -209,12 +178,11 @@
      * equal. In order to be equal, {@code object} must be an instance of
      * {@code Double} and the bit pattern of its double value is the same as
      * this object's.
-     * 
+     *
      * @param object
      *            the object to compare this double with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Double}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -241,10 +209,9 @@
 
     /**
      * Indicates whether this object represents an infinite value.
-     * 
+     *
      * @return {@code true} if the value of this double is positive or negative
      *         infinity; {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isInfinite() {
         return isInfinite(value);
@@ -252,12 +219,11 @@
 
     /**
      * Indicates whether the specified double represents an infinite value.
-     * 
+     *
      * @param d
      *            the double to check.
      * @return {@code true} if the value of {@code d} is positive or negative
      *         infinity; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isInfinite(double d) {
         return (d == POSITIVE_INFINITY) || (d == NEGATIVE_INFINITY);
@@ -265,10 +231,9 @@
 
     /**
      * Indicates whether this object is a <em>Not-a-Number (NaN)</em> value.
-     * 
+     *
      * @return {@code true} if this double is <em>Not-a-Number</em>;
      *         {@code false} if it is a (potentially infinite) double number.
-     * @since Android 1.0
      */
     public boolean isNaN() {
         return isNaN(value);
@@ -277,12 +242,11 @@
     /**
      * Indicates whether the specified double is a <em>Not-a-Number (NaN)</em>
      * value.
-     * 
+     *
      * @param d
      *            the double value to check.
      * @return {@code true} if {@code d} is <em>Not-a-Number</em>;
      *         {@code false} if it is a (potentially infinite) double number.
-     * @since Android 1.0
      */
     public static boolean isNaN(double d) {
         return d != d;
@@ -291,14 +255,13 @@
     /**
      * Converts the specified IEEE 754 floating-point double precision bit
      * pattern to a Java double value.
-     * 
+     *
      * @param bits
      *            the IEEE 754 floating-point double precision representation of
      *            a double value.
      * @return the double value converted from {@code bits}.
      * @see #doubleToLongBits(double)
      * @see #doubleToRawLongBits(double)
-     * @since Android 1.0
      */
     public static native double longBitsToDouble(long bits);
 
@@ -309,14 +272,13 @@
 
     /**
      * Parses the specified string as a double value.
-     * 
+     *
      * @param string
      *            the string representation of a double value.
      * @return the primitive double value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a double value.
-     * @since Android 1.0
      */
     public static double parseDouble(String string)
             throws NumberFormatException {
@@ -337,11 +299,10 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * specified double value.
-     * 
+     *
      * @param d
      *             the double to convert to a string.
      * @return a printable representation of {@code d}.
-     * @since Android 1.0
      */
     public static String toString(double d) {
         return org.apache.harmony.luni.util.NumberConverter.convert(d);
@@ -349,7 +310,7 @@
 
     /**
      * Parses the specified string as a double value.
-     * 
+     *
      * @param string
      *            the string representation of a double value.
      * @return a {@code Double} instance containing the double value represented
@@ -358,7 +319,6 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a double value.
      * @see #parseDouble(String)
-     * @since Android 1.0
      */
     public static Double valueOf(String string) throws NumberFormatException {
         return new Double(parseDouble(string));
@@ -371,7 +331,7 @@
      * than any other double value, including {@code Double.POSITIVE_INFINITY};</li>
      * <li>+0.0d is greater than -0.0d</li>
      * </ul>
-     * 
+     *
      * @param double1
      *            the first value to compare.
      * @param double2
@@ -379,37 +339,44 @@
      * @return a negative value if {@code double1} is less than {@code double2};
      *         0 if {@code double1} and {@code double2} are equal; a positive
      *         value if {@code double1} is greater than {@code double2}.
-     * @since Android 1.0         
      */
     public static int compare(double double1, double double2) {
-        long d1, d2;
-        long NaNbits = Double.doubleToLongBits(Double.NaN);
-        if ((d1 = Double.doubleToLongBits(double1)) == NaNbits) {
-            if (Double.doubleToLongBits(double2) == NaNbits) {
+        // Non-zero, non-NaN checking.
+        if (double1 > double2) {
+            return 1;
+        }
+        if (double2 > double1) {
+            return -1;
+        }
+        if (double1 == double2 && 0.0d != double1) {
+            return 0;
+        }
+
+        // NaNs are equal to other NaNs and larger than any other double
+        if (isNaN(double1)) {
+            if (isNaN(double2)) {
                 return 0;
             }
             return 1;
-        }
-        if ((d2 = Double.doubleToLongBits(double2)) == NaNbits) {
+        } else if (isNaN(double2)) {
             return -1;
         }
-        if (double1 == double2) {
-            if (d1 == d2) {
-                return 0;
-            }
-            // check for -0
-            return d1 > d2 ? 1 : -1;
-        }
-        return double1 > double2 ? 1 : -1;
+
+        // Deal with +0.0 and -0.0
+        long d1 = doubleToRawLongBits(double1);
+        long d2 = doubleToRawLongBits(double2);
+        // The below expression is equivalent to:
+        // (d1 == d2) ? 0 : (d1 < d2) ? -1 : 1
+        return (int) ((d1 >> 63) - (d2 >> 63));
     }
 
     /**
      * Returns a {@code Double} instance for the specified double value.
-     * 
+     *
      * @param d
      *            the double value to store in the instance.
      * @return a {@code Double} instance containing {@code d}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Double valueOf(double d) {
         return new Double(d);
@@ -417,11 +384,11 @@
 
     /**
      * Converts the specified double into its hexadecimal string representation.
-     * 
+     *
      * @param d
      *            the double to convert.
      * @return the hexadecimal string representation of {@code d}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toHexString(double d) {
         /*
diff --git a/luni/src/main/java/java/lang/Enum.java b/luni/src/main/java/java/lang/Enum.java
index 0aa15dd..395c825 100644
--- a/luni/src/main/java/java/lang/Enum.java
+++ b/luni/src/main/java/java/lang/Enum.java
@@ -27,8 +27,6 @@
  * The superclass of all enumerated types. Actual enumeration types inherit from
  * this class, but extending this class does not make a class an enumration
  * type, since the compiler needs to generate special information for it.
- * 
- * @since Android 1.0
  */
 public abstract class Enum<E extends Enum<E>> implements Serializable,
         Comparable<E> {
@@ -41,13 +39,12 @@
 
     /**
      * Constructor for constants of enum subtypes.
-     * 
+     *
      * @param name
      *            the enum constant's declared name.
      * @param ordinal
      *            the enum constant's ordinal, which corresponds to its position
      *            in the enum declaration, starting at zero.
-     * @since Android 1.0
      */
     protected Enum(String name, int ordinal) {
         this.name = name;
@@ -57,10 +54,9 @@
     /**
      * Returns the name of this enum constant. The name is the field as it
      * appears in the {@code enum} declaration.
-     * 
+     *
      * @return the name of this enum constant.
      * @see #toString()
-     * @since Android 1.0
      */
     public final String name() {
         return name;
@@ -69,9 +65,8 @@
     /**
      * Returns the position of the enum constant in the declaration. The first
      * constant has an ordinal value of zero.
-     * 
+     *
      * @return the ordinal value of this enum constant.
-     * @since Android 1.0
      */
     public final int ordinal() {
         return ordinal;
@@ -80,9 +75,8 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * object. In this case, the enum constant's name is returned.
-     * 
+     *
      * @return a printable representation of this object.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -93,12 +87,11 @@
      * Compares this object with the specified object and indicates if they are
      * equal. In order to be equal, {@code object} must be identical to this
      * enum constant.
-     * 
+     *
      * @param other
      *            the object to compare this enum constant with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Enum}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public final boolean equals(Object other) {
@@ -113,11 +106,10 @@
     /**
      * {@code Enum} objects are singletons, they may not be cloned. This method
      * always throws a {@code CloneNotSupportedException}.
-     * 
+     *
      * @return does not return.
      * @throws CloneNotSupportedException
      *             is always thrown.
-     * @since Android 1.0
      */
     @Override
     protected final Object clone() throws CloneNotSupportedException {
@@ -129,7 +121,7 @@
      * Compares this object to the specified enum object to determine their
      * relative order. This method compares the object's ordinal values, that
      * is, their position in the enum declaration.
-     * 
+     *
      * @param o
      *            the enum object to compare this object to.
      * @return a negative value if the ordinal value of this enum constant is
@@ -138,7 +130,6 @@
      *         value if the ordinal value of this enum constant is greater than
      *         the ordinal value of {@code o}.
      * @see java.lang.Comparable
-     * @since Android 1.0
      */
     public final int compareTo(E o) {
         return ordinal - o.ordinal;
@@ -146,9 +137,8 @@
 
     /**
      * Returns the enum constant's declaring class.
-     * 
+     *
      * @return the class object representing the constant's enum type.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public final Class<E> getDeclaringClass() {
@@ -162,7 +152,7 @@
 
     /**
      * Returns the constant with the specified name of the specified enum type.
-     * 
+     *
      * @param enumType
      *            the class of the enumerated type to search for the constant
      *            value.
@@ -174,7 +164,6 @@
      * @throws IllegalArgumentException
      *             if {@code enumType} is not an enumerated type or does not
      *             have a constant value called {@code name}.
-     * @since Android 1.0
      */
     public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
         if ((enumType == null) || (name == null)) {
diff --git a/luni/src/main/java/java/lang/EnumConstantNotPresentException.java b/luni/src/main/java/java/lang/EnumConstantNotPresentException.java
index 0416703..aec32d0 100644
--- a/luni/src/main/java/java/lang/EnumConstantNotPresentException.java
+++ b/luni/src/main/java/java/lang/EnumConstantNotPresentException.java
@@ -20,8 +20,8 @@
 
 /**
  * Thrown if an {@code enum} constant does not exist for a particular name.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public class EnumConstantNotPresentException extends RuntimeException {
 
@@ -36,12 +36,11 @@
      * Constructs a new {@code EnumConstantNotPresentException} with the current
      * stack trace and a detail message based on the specified enum type and
      * missing constant name.
-     * 
+     *
      * @param enumType
      *            the enum type.
      * @param constantName
      *            the missing constant name.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public EnumConstantNotPresentException(Class<? extends Enum> enumType,
@@ -54,9 +53,8 @@
 
     /**
      * Gets the enum type for which the constant name is missing.
-     * 
+     *
      * @return the enum type for which a constant name has not been found.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public Class<? extends Enum> enumType() {
@@ -68,7 +66,6 @@
      * 
      * @return the name of the constant that has not been found in the enum
      *         type.
-     * @since Android 1.0
      */
     public String constantName() {
         return constantName;
diff --git a/luni/src/main/java/java/lang/Error.java b/luni/src/main/java/java/lang/Error.java
index 3bce72c..dd284ae 100644
--- a/luni/src/main/java/java/lang/Error.java
+++ b/luni/src/main/java/java/lang/Error.java
@@ -26,7 +26,6 @@
  * @see Throwable
  * @see Exception
  * @see RuntimeException
- * @since Android 1.0
  */
 public class Error extends Throwable {
 
@@ -34,8 +33,6 @@
 
     /**
      * Constructs a new {@code Error} that includes the current stack trace.
-     * 
-     * @since Android 1.0
      */
     public Error() {
         super();
@@ -47,7 +44,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public Error(String detailMessage) {
         super(detailMessage);
@@ -61,7 +57,6 @@
      *            the detail message for this error.
      * @param throwable
      *            the cause of this error.
-     * @since Android 1.0
      */
     public Error(String detailMessage, Throwable throwable) {
         super(detailMessage, throwable);
@@ -73,7 +68,6 @@
      * 
      * @param throwable
      *            the cause of this error.
-     * @since Android 1.0
      */
     public Error(Throwable throwable) {
         super(throwable);
diff --git a/luni/src/main/java/java/lang/Exception.java b/luni/src/main/java/java/lang/Exception.java
index 010cea4..7921edd 100644
--- a/luni/src/main/java/java/lang/Exception.java
+++ b/luni/src/main/java/java/lang/Exception.java
@@ -26,15 +26,12 @@
  * @see Throwable
  * @see Error
  * @see RuntimeException
- * @since Android 1.0
  */
 public class Exception extends Throwable {
     private static final long serialVersionUID = -3387516993124229948L;
 
     /**
      * Constructs a new {@code Exception} that includes the current stack trace.
-     * 
-     * @since Android 1.0
      */
     public Exception() {
         super();
@@ -46,7 +43,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public Exception(String detailMessage) {
         super(detailMessage);
@@ -60,7 +56,6 @@
      *            the detail message for this exception.
      * @param throwable
      *            the cause of this exception.
-     * @since Android 1.0
      */
     public Exception(String detailMessage, Throwable throwable) {
         super(detailMessage, throwable);
@@ -72,7 +67,6 @@
      * 
      * @param throwable
      *            the cause of this exception.
-     * @since Android 1.0
      */
     public Exception(Throwable throwable) {
         super(throwable);
diff --git a/luni/src/main/java/java/lang/ExceptionInInitializerError.java b/luni/src/main/java/java/lang/ExceptionInInitializerError.java
index 6096f08..3767488 100644
--- a/luni/src/main/java/java/lang/ExceptionInInitializerError.java
+++ b/luni/src/main/java/java/lang/ExceptionInInitializerError.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when an exception occurs during class initialization.
- * 
- * @since Android 1.0
  */
 public class ExceptionInInitializerError extends LinkageError {
 
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code ExceptionInInitializerError} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public ExceptionInInitializerError() {
         super();
@@ -45,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public ExceptionInInitializerError(String detailMessage) {
         super(detailMessage);
@@ -70,7 +65,6 @@
      * Returns the exception that is the cause of this error.
      * 
      * @return the exception that caused this error.
-     * @since Android 1.0
      */
     public Throwable getException() {
         return exception;
@@ -80,7 +74,6 @@
      * Returns the cause of this error, or {@code null} if there is no cause.
      * 
      * @return the exception that caused this error.
-     * @since Android 1.0
      */
     @Override
     public Throwable getCause() {
diff --git a/luni/src/main/java/java/lang/Float.java b/luni/src/main/java/java/lang/Float.java
index 69f91c5..067149d 100644
--- a/luni/src/main/java/java/lang/Float.java
+++ b/luni/src/main/java/java/lang/Float.java
@@ -19,9 +19,9 @@
 
 /**
  * The wrapper for the primitive type {@code float}.
- * 
+ *
  * @see java.lang.Number
- * @since Android 1.0
+ * @since 1.0
  */
 public final class Float extends Number implements Comparable<Float> {
 
@@ -34,44 +34,34 @@
 
     /**
      * Constant for the maximum {@code float} value, (2 - 2<sup>-23</sup>) * 2<sup>127</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final float MAX_VALUE = 3.40282346638528860e+38f;
 
     /**
      * Constant for the minimum {@code float} value, 2<sup>-149</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final float MIN_VALUE = 1.40129846432481707e-45f;
 
     /**
      * Constant for the Not-a-Number (NaN) value of the {@code float} type.
-     * 
-     * @since Android 1.0
      */
     public static final float NaN = 0.0f / 0.0f;
 
     /**
      * Constant for the Positive Infinity value of the {@code float} type.
-     * 
-     * @since Android 1.0
      */
     public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
 
     /**
      * Constant for the Negative Infinity value of the {@code float} type.
-     * 
-     * @since Android 1.0
      */
     public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
 
     /**
-     * The {@link Class} object that represents the primitive type {@code 
+     * The {@link Class} object that represents the primitive type {@code
      * float}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.1
      */
     @SuppressWarnings("unchecked")
     public static final Class<Float> TYPE = (Class<Float>) new float[0]
@@ -83,17 +73,16 @@
     /**
      * Constant for the number of bits needed to represent a {@code float} in
      * two's complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 32;
 
     /**
      * Constructs a new {@code Float} with the specified primitive float value.
-     * 
+     *
      * @param value
      *            the primitive float value to store in the new instance.
-     * @since Android 1.0
      */
     public Float(float value) {
         this.value = value;
@@ -101,10 +90,9 @@
 
     /**
      * Constructs a new {@code Float} with the specified primitive double value.
-     * 
+     *
      * @param value
      *            the primitive double value to store in the new instance.
-     * @since Android 1.0
      */
     public Float(double value) {
         this.value = (float) value;
@@ -112,13 +100,12 @@
 
     /**
      * Constructs a new {@code Float} from the specified string.
-     * 
+     *
      * @param string
      *            the string representation of a float value.
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into a float value.
      * @see #parseFloat(String)
-     * @since Android 1.0
      */
     public Float(String string) throws NumberFormatException {
         this(parseFloat(string));
@@ -132,7 +119,7 @@
      * than any other float value, including {@code Float.POSITIVE_INFINITY};</li>
      * <li>+0.0f is greater than -0.0f</li>
      * </ul>
-     * 
+     *
      * @param object
      *            the float object to compare this object to.
      * @return a negative value if the value of this float is less than the
@@ -140,28 +127,10 @@
      *         value of {@code object} are equal; a positive value if the value
      *         of this float is greater than the value of {@code object}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Float object) {
-        int f1, f2;
-        int NaNbits = Float.floatToIntBits(Float.NaN);
-        if ((f1 = Float.floatToIntBits(value)) == NaNbits) {
-            if (Float.floatToIntBits(object.value) == NaNbits) {
-                return 0;
-            }
-            return 1;
-        }
-        if ((f2 = Float.floatToIntBits(object.value)) == NaNbits) {
-            return -1;
-        }
-        if (value == object.value) {
-            if (f1 == f2) {
-                return 0;
-            }
-            // check for -0
-            return f1 > f2 ? 1 : -1;
-        }
-        return value > object.value ? 1 : -1;
+        return compare(value, object.value);
     }
 
     @Override
@@ -178,12 +147,11 @@
      * Compares this instance with the specified object and indicates if they
      * are equal. In order to be equal, {@code object} must be an instance of
      * {@code Float} and have the same float value as this object.
-     * 
+     *
      * @param object
      *            the object to compare this float with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Float}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -197,14 +165,13 @@
      * to the IEEE 754 floating-point single precision bit layout. All
      * <em>Not-a-Number (NaN)</em> values are converted to a single NaN
      * representation ({@code 0x7ff8000000000000L}).
-     * 
+     *
      * @param value
      *            the float value to convert.
      * @return the IEEE 754 floating-point single precision representation of
      *         {@code value}.
      * @see #floatToRawIntBits(float)
      * @see #intBitsToFloat(int)
-     * @since Android 1.0
      */
     public static native int floatToIntBits(float value);
 
@@ -212,22 +179,20 @@
      * Converts the specified float value to a binary representation conforming
      * to the IEEE 754 floating-point single precision bit layout.
      * <em>Not-a-Number (NaN)</em> values are preserved.
-     * 
+     *
      * @param value
      *            the float value to convert.
      * @return the IEEE 754 floating-point single precision representation of
      *         {@code value}.
      * @see #floatToIntBits(float)
      * @see #intBitsToFloat(int)
-     * @since Android 1.0
      */
     public static native int floatToRawIntBits(float value);
 
     /**
      * Gets the primitive value of this float.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public float floatValue() {
@@ -242,14 +207,13 @@
     /**
      * Converts the specified IEEE 754 floating-point single precision bit
      * pattern to a Java float value.
-     * 
+     *
      * @param bits
      *            the IEEE 754 floating-point single precision representation of
      *            a float value.
      * @return the float value converted from {@code bits}.
      * @see #floatToIntBits(float)
      * @see #floatToRawIntBits(float)
-     * @since Android 1.0
      */
     public static native float intBitsToFloat(int bits);
 
@@ -260,10 +224,9 @@
 
     /**
      * Indicates whether this object represents an infinite value.
-     * 
+     *
      * @return {@code true} if the value of this float is positive or negative
      *         infinity; {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isInfinite() {
         return isInfinite(value);
@@ -271,12 +234,11 @@
 
     /**
      * Indicates whether the specified float represents an infinite value.
-     * 
+     *
      * @param f
      *            the float to check.
      * @return {@code true} if the value of {@code f} is positive or negative
      *         infinity; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isInfinite(float f) {
         return (f == POSITIVE_INFINITY) || (f == NEGATIVE_INFINITY);
@@ -284,10 +246,9 @@
 
     /**
      * Indicates whether this object is a <em>Not-a-Number (NaN)</em> value.
-     * 
+     *
      * @return {@code true} if this float is <em>Not-a-Number</em>;
      *         {@code false} if it is a (potentially infinite) float number.
-     * @since Android 1.0
      */
     public boolean isNaN() {
         return isNaN(value);
@@ -296,12 +257,11 @@
     /**
      * Indicates whether the specified float is a <em>Not-a-Number (NaN)</em>
      * value.
-     * 
+     *
      * @param f
      *            the float value to check.
      * @return {@code true} if {@code f} is <em>Not-a-Number</em>;
      *         {@code false} if it is a (potentially infinite) float number.
-     * @since Android 1.0
      */
     public static boolean isNaN(float f) {
         return f != f;
@@ -314,14 +274,15 @@
 
     /**
      * Parses the specified string as a float value.
-     * 
+     *
      * @param string
      *            the string representation of a float value.
      * @return the primitive float value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a float value.
-     * @since Android 1.0
+     * @see #valueOf(String)
+     * @since 1.2
      */
     public static float parseFloat(String string) throws NumberFormatException {
         return org.apache.harmony.luni.util.FloatingPointParser
@@ -341,11 +302,10 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * specified float value.
-     * 
+     *
      * @param f
      *             the float to convert to a string.
      * @return a printable representation of {@code f}.
-     * @since Android 1.0
      */
     public static String toString(float f) {
         return org.apache.harmony.luni.util.NumberConverter.convert(f);
@@ -353,7 +313,7 @@
 
     /**
      * Parses the specified string as a float value.
-     * 
+     *
      * @param string
      *            the string representation of a float value.
      * @return a {@code Float} instance containing the float value represented
@@ -362,7 +322,6 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a float value.
      * @see #parseFloat(String)
-     * @since Android 1.0
      */
     public static Float valueOf(String string) throws NumberFormatException {
         return valueOf(parseFloat(string));
@@ -375,7 +334,7 @@
      * than any other float value, including {@code Float.POSITIVE_INFINITY};</li>
      * <li>+0.0f is greater than -0.0f</li>
      * </ul>
-     * 
+     *
      * @param float1
      *            the first value to compare.
      * @param float2
@@ -383,37 +342,46 @@
      * @return a negative value if {@code float1} is less than {@code float2};
      *         0 if {@code float1} and {@code float2} are equal; a positive
      *         value if {@code float1} is greater than {@code float2}.
-     * @since Android 1.0
+     * @since 1.4
      */
     public static int compare(float float1, float float2) {
-        int f1, f2;
-        int NaNbits = Float.floatToIntBits(Float.NaN);
-        if ((f1 = Float.floatToIntBits(float1)) == NaNbits) {
-            if (Float.floatToIntBits(float2) == NaNbits) {
+        // Non-zero, non-NaN checking.
+        if (float1 > float2) {
+            return 1;
+        }
+        if (float2 > float1) {
+            return -1;
+        }
+        if (float1 == float2 && 0.0f != float1) {
+            return 0;
+        }
+
+        // NaNs are equal to other NaNs and larger than any other float
+        if (isNaN(float1)) {
+            if (isNaN(float2)) {
                 return 0;
             }
             return 1;
-        }
-        if ((f2 = Float.floatToIntBits(float2)) == NaNbits) {
+        } else if (isNaN(float2)) {
             return -1;
         }
-        if (float1 == float2) {
-            if (f1 == f2) {
-                return 0;
-            }
-            // check for -0
-            return f1 > f2 ? 1 : -1;
-        }
-        return float1 > float2 ? 1 : -1;
+
+        // Deal with +0.0 and -0.0
+        int f1 = floatToRawIntBits(float1);
+        int f2 = floatToRawIntBits(float2);
+        // The below expression is equivalent to:
+        // (f1 == f2) ? 0 : (f1 < f2) ? -1 : 1
+        // because f1 and f2 are either 0 or Integer.MIN_VALUE
+        return (f1 >> 31) - (f2 >> 31);
     }
 
     /**
      * Returns a {@code Float} instance for the specified float value.
-     * 
+     *
      * @param f
      *            the float value to store in the instance.
      * @return a {@code Float} instance containing {@code f}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Float valueOf(float f) {
         return new Float(f);
@@ -421,11 +389,11 @@
 
     /**
      * Converts the specified float into its hexadecimal string representation.
-     * 
+     *
      * @param f
      *            the float to convert.
      * @return the hexadecimal string representation of {@code f}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toHexString(float f) {
         /*
diff --git a/luni/src/main/java/java/lang/IllegalAccessError.java b/luni/src/main/java/java/lang/IllegalAccessError.java
index 7f87afd..7fcef85 100644
--- a/luni/src/main/java/java/lang/IllegalAccessError.java
+++ b/luni/src/main/java/java/lang/IllegalAccessError.java
@@ -22,9 +22,6 @@
  * which is not accessible from where it is referenced.
  * <p>
  * Note that this can only occur when inconsistent class files have been loaded.
- * </p>
- * 
- * @since Android 1.0
  */
 public class IllegalAccessError extends IncompatibleClassChangeError {
 
@@ -33,8 +30,6 @@
     /**
      * Constructs a new {@code IllegalAccessError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalAccessError() {
         super();
@@ -46,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public IllegalAccessError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/IllegalAccessException.java b/luni/src/main/java/java/lang/IllegalAccessException.java
index b9d2d69..d96fd56 100644
--- a/luni/src/main/java/java/lang/IllegalAccessException.java
+++ b/luni/src/main/java/java/lang/IllegalAccessException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a program attempts to access a field or method which is not
  * accessible from the location where the reference is made.
- * 
- * @since Android 1.0
  */
 public class IllegalAccessException extends Exception {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code IllegalAccessException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalAccessException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IllegalAccessException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/IllegalArgumentException.java b/luni/src/main/java/java/lang/IllegalArgumentException.java
index 6f8dcf6..eb2ad91 100644
--- a/luni/src/main/java/java/lang/IllegalArgumentException.java
+++ b/luni/src/main/java/java/lang/IllegalArgumentException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a method is invoked with an argument which it can not reasonably
  * deal with.
- * 
- * @since Android 1.0
  */
 public class IllegalArgumentException extends RuntimeException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code IllegalArgumentException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalArgumentException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IllegalArgumentException(String detailMessage) {
         super(detailMessage);
@@ -57,7 +52,7 @@
      *            the detail message for this exception.
      * @param cause
      *            the cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public IllegalArgumentException(String message, Throwable cause) {
         super(message, cause);
@@ -69,8 +64,8 @@
      * 
      * @param cause
      *            the cause of this exception, may be {@code null}.
-     * @since Android 1.0
-     */    
+     * @since 1.5
+     */
     public IllegalArgumentException(Throwable cause) {
         super((cause == null ? null : cause.toString()), cause);
     }
diff --git a/luni/src/main/java/java/lang/IllegalMonitorStateException.java b/luni/src/main/java/java/lang/IllegalMonitorStateException.java
index e570bfd..a0b8a75 100644
--- a/luni/src/main/java/java/lang/IllegalMonitorStateException.java
+++ b/luni/src/main/java/java/lang/IllegalMonitorStateException.java
@@ -21,8 +21,6 @@
  * Thrown when a monitor operation is attempted when the monitor is not in the
  * correct state, for example when a thread attempts to exit a monitor which it
  * does not own.
- * 
- * @since Android 1.0
  */
 public class IllegalMonitorStateException extends RuntimeException {
 
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code IllegalMonitorStateException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalMonitorStateException() {
         super();
@@ -44,7 +40,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IllegalMonitorStateException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/IllegalStateException.java b/luni/src/main/java/java/lang/IllegalStateException.java
index 427aaf4..28db2de 100644
--- a/luni/src/main/java/java/lang/IllegalStateException.java
+++ b/luni/src/main/java/java/lang/IllegalStateException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an action is attempted at a time when the virtual machine is not
  * in the correct state.
- * 
- * @since Android 1.0
  */
 public class IllegalStateException extends RuntimeException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code IllegalStateException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalStateException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IllegalStateException(String detailMessage) {
         super(detailMessage);
@@ -57,7 +52,7 @@
      *            the detail message for this exception.
      * @param cause
      *            the cause of this exception.
-     * @since Android 1.0
+     * @since 1.5
      */
     public IllegalStateException(String message, Throwable cause) {
         super(message, cause);
@@ -69,7 +64,7 @@
      * 
      * @param cause
      *            the cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public IllegalStateException(Throwable cause) {
         super((cause == null ? null : cause.toString()), cause);
diff --git a/luni/src/main/java/java/lang/IllegalThreadStateException.java b/luni/src/main/java/java/lang/IllegalThreadStateException.java
index 82eccbb..f1e99a8 100644
--- a/luni/src/main/java/java/lang/IllegalThreadStateException.java
+++ b/luni/src/main/java/java/lang/IllegalThreadStateException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an operation is attempted which is not possible given the state
  * that the executing thread is in.
- * 
- * @since Android 1.0
  */
 public class IllegalThreadStateException extends IllegalArgumentException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code IllegalThreadStateException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalThreadStateException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IllegalThreadStateException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/IncompatibleClassChangeError.java b/luni/src/main/java/java/lang/IncompatibleClassChangeError.java
index 83950fd..2155a28 100644
--- a/luni/src/main/java/java/lang/IncompatibleClassChangeError.java
+++ b/luni/src/main/java/java/lang/IncompatibleClassChangeError.java
@@ -24,7 +24,6 @@
  * the same running image.
  * 
  * @see Error
- * @since Android 1.0
  */
 public class IncompatibleClassChangeError extends LinkageError {
 
@@ -33,8 +32,6 @@
     /**
      * Constructs a new {@code IncompatibleClassChangeError} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public IncompatibleClassChangeError() {
         super();
@@ -46,7 +43,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public IncompatibleClassChangeError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/IndexOutOfBoundsException.java b/luni/src/main/java/java/lang/IndexOutOfBoundsException.java
index a4dc282..f26fcbf 100644
--- a/luni/src/main/java/java/lang/IndexOutOfBoundsException.java
+++ b/luni/src/main/java/java/lang/IndexOutOfBoundsException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a program attempts to access a value in an indexable collection
  * using a value which is outside of the range of valid indices.
- * 
- * @since Android 1.0
  */
 public class IndexOutOfBoundsException extends RuntimeException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code IndexOutOfBoundsException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public IndexOutOfBoundsException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IndexOutOfBoundsException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/InheritableThreadLocal.java b/luni/src/main/java/java/lang/InheritableThreadLocal.java
index 41e0d82..7e12ac2 100644
--- a/luni/src/main/java/java/lang/InheritableThreadLocal.java
+++ b/luni/src/main/java/java/lang/InheritableThreadLocal.java
@@ -1,17 +1,18 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
  *
- * 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
  *
- *      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.
+ *  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.lang;
@@ -24,36 +25,33 @@
  * creation time. However, subclasses may override {code #childValue(Object)}
  * to provide an arbitrary function for passing the value of a parent's
  * thread-local variable to the child's thread-local variable.
- * 
+ *
  * @see java.lang.Thread
  * @see java.lang.ThreadLocal
- * 
- * @since Android 1.0
  */
 public class InheritableThreadLocal<T> extends ThreadLocal<T> {
 
     /**
      * Creates a new inheritable thread-local variable.
-     * 
-     * @since Android 1.0
      */
-    public InheritableThreadLocal() {}
+    public InheritableThreadLocal() {
+        super();
+    }
 
     /**
      * Computes the initial value of this thread-local variable for the child
-     * thread given the parent thread's value. Called from the parent thread
-     * when creating a child thread. The default implementation returns the
-     * parent thread's value.
-     * 
-     * @param parentValue
-     *            the value of the variable in the parent thread.
+     * thread given the parent thread's value. Called from the parent thread when
+     * creating a child thread. The default implementation returns the parent
+     * thread's value.
+     *
+     * @param parentValue the value of the variable in the parent thread.
      * @return the initial value of the variable for the child thread.
-     * @since Android 1.0
      */
     protected T childValue(T parentValue) {
         return parentValue;
     }
 
+    // BEGIN android-added
     @Override
     Values values(Thread current) {
         return current.inheritableValues;
@@ -63,4 +61,5 @@
     Values initializeValues(Thread current) {
         return current.inheritableValues = new Values();
     }
+    // END android-added
 }
diff --git a/luni/src/main/java/java/lang/InstantiationError.java b/luni/src/main/java/java/lang/InstantiationError.java
index 0d387c6..9ad1ed6 100644
--- a/luni/src/main/java/java/lang/InstantiationError.java
+++ b/luni/src/main/java/java/lang/InstantiationError.java
@@ -23,9 +23,6 @@
  * {@code new} is invoked.
  * <p>
  * Note that this can only occur when inconsistent class files are being loaded.
- * </p>
- * 
- * @since Android 1.0
  */
 public class InstantiationError extends IncompatibleClassChangeError {
     private static final long serialVersionUID = -4885810657349421204L;
@@ -33,8 +30,6 @@
     /**
      * Constructs a new {@code InstantiationError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public InstantiationError() {
         super();
@@ -46,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public InstantiationError(String detailMessage) {
         super(detailMessage);
@@ -58,7 +52,6 @@
      * 
      * @param clazz
      *            the class that can not be instantiated.
-     * @since Android 1.0
      */
     InstantiationError(Class<?> clazz) {
         super(clazz.getName());
diff --git a/luni/src/main/java/java/lang/InstantiationException.java b/luni/src/main/java/java/lang/InstantiationException.java
index cc8b556..fe68345 100644
--- a/luni/src/main/java/java/lang/InstantiationException.java
+++ b/luni/src/main/java/java/lang/InstantiationException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a program attempts to access a constructor which is not
  * accessible from the location where the reference is made.
- * 
- * @since Android 1.0
  */
 public class InstantiationException extends Exception {
     private static final long serialVersionUID = -8441929162975509110L;
@@ -29,8 +27,6 @@
     /**
      * Constructs a new {@code InstantiationException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public InstantiationException() {
         super();
@@ -42,7 +38,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InstantiationException(String detailMessage) {
         super(detailMessage);
@@ -54,7 +49,6 @@
      * 
      * @param clazz
      *            the class that can not be instantiated.
-     * @since Android 1.0
      */
     InstantiationException(Class<?> clazz) {
         super(clazz.getName());
diff --git a/luni/src/main/java/java/lang/Integer.java b/luni/src/main/java/java/lang/Integer.java
index 3a98872..570120b 100644
--- a/luni/src/main/java/java/lang/Integer.java
+++ b/luni/src/main/java/java/lang/Integer.java
@@ -24,10 +24,9 @@
  * href="http://www.hackersdelight.org/">Henry S. Warren, Jr.'s Hacker's
  * Delight, (Addison Wesley, 2002)</a> as well as <a
  * href="http://aggregate.org/MAGIC/">The Aggregate's Magic Algorithms</a>.
- * </p>
- * 
+ *
  * @see java.lang.Number
- * @since Android 1.0
+ * @since 1.1
  */
 public final class Integer extends Number implements Comparable<Integer> {
 
@@ -40,30 +39,32 @@
 
     /**
      * Constant for the maximum {@code int} value, 2<sup>31</sup>-1.
-     * 
-     * @since Android 1.0
      */
     public static final int MAX_VALUE = 0x7FFFFFFF;
 
     /**
      * Constant for the minimum {@code int} value, -2<sup>31</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final int MIN_VALUE = 0x80000000;
 
     /**
      * Constant for the number of bits needed to represent an {@code int} in
      * two's complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 32;
 
+    /*
+     * Progressively smaller decimal order of magnitude that can be represented
+     * by an instance of Integer. Used to help compute the String
+     * representation.
+     */
+    private static final int[] decimalScale = new int[] { 1000000000, 100000000,
+            10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 };
+
     /**
      * The {@link Class} object that represents the primitive type {@code int}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Integer> TYPE = (Class<Integer>) new int[0]
@@ -75,10 +76,9 @@
     /**
      * Constructs a new {@code Integer} with the specified primitive integer
      * value.
-     * 
+     *
      * @param value
      *            the primitive integer value to store in the new instance.
-     * @since Android 1.0
      */
     public Integer(int value) {
         this.value = value;
@@ -86,13 +86,12 @@
 
     /**
      * Constructs a new {@code Integer} from the specified string.
-     * 
+     *
      * @param string
      *            the string representation of an integer value.
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into an integer value.
      * @see #parseInt(String)
-     * @since Android 1.0
      */
     public Integer(String string) throws NumberFormatException {
         this(parseInt(string));
@@ -106,7 +105,7 @@
     /**
      * Compares this object to the specified integer object to determine their
      * relative order.
-     * 
+     *
      * @param object
      *            the integer object to compare this object to.
      * @return a negative value if the value of this integer is less than the
@@ -114,7 +113,7 @@
      *         value of {@code object} are equal; a positive value if the value
      *         of this integer is greater than the value of {@code object}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Integer object) {
         return value > object.value ? 1 : (value < object.value ? -1 : 0);
@@ -125,14 +124,13 @@
      * string can be decoded into an integer value. The string may be an
      * optional minus sign "-" followed by a hexadecimal ("0x..." or "#..."),
      * octal ("0..."), or decimal ("...") representation of an integer.
-     * 
+     *
      * @param string
      *            a string representation of an integer value.
      * @return an {@code Integer} containing the value represented by
      *         {@code string}.
      * @throws NumberFormatException
      *             if {@code string} can not be parsed as an integer value.
-     * @since Android 1.0
      */
     public static Integer decode(String string) throws NumberFormatException {
         int length = string.length(), i = 0;
@@ -158,23 +156,21 @@
                 return valueOf(0);
             }
             if ((firstDigit = string.charAt(i)) == 'x' || firstDigit == 'X') {
-                if (i == length) {
+                if (++i == length) {
                     // BEGIN android-changed
                     throw new NumberFormatException("unable to parse '"+string+"' as integer");
                     // END android-changed
                 }
-                i++;
                 base = 16;
             } else {
                 base = 8;
             }
         } else if (firstDigit == '#') {
-            if (i == length) {
+            if (++i == length) {
                 // BEGIN android-changed
                 throw new NumberFormatException("unable to parse '"+string+"' as integer");
                 // END android-changed
             }
-            i++;
             base = 16;
         }
 
@@ -191,12 +187,11 @@
      * Compares this instance with the specified object and indicates if they
      * are equal. In order to be equal, {@code o} must be an instance of
      * {@code Integer} and have the same integer value as this object.
-     * 
+     *
      * @param o
      *            the object to compare this integer with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Integer}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -214,12 +209,11 @@
      * {@code string}. Returns {@code null} if {@code string} is {@code null}
      * or empty, if the property can not be found or if its value can not be
      * parsed as an integer.
-     * 
+     *
      * @param string
      *            the name of the requested system property.
      * @return the requested property's value as an {@code Integer} or
      *         {@code null}.
-     * @since Android 1.0        
      */
     public static Integer getInteger(String string) {
         if (string == null || string.length() == 0) {
@@ -241,7 +235,7 @@
      * {@code string}. Returns the specified default value if {@code string} is
      * {@code null} or empty, if the property can not be found or if its value
      * can not be parsed as an integer.
-     * 
+     *
      * @param string
      *            the name of the requested system property.
      * @param defaultValue
@@ -249,7 +243,6 @@
      *            system property with the requested name.
      * @return the requested property's value as an {@code Integer} or the
      *         default value.
-     * @since Android 1.0        
      */
     public static Integer getInteger(String string, int defaultValue) {
         if (string == null || string.length() == 0) {
@@ -271,7 +264,7 @@
      * {@code string}. Returns the specified default value if {@code string} is
      * {@code null} or empty, if the property can not be found or if its value
      * can not be parsed as an integer.
-     * 
+     *
      * @param string
      *            the name of the requested system property.
      * @param defaultValue
@@ -279,7 +272,6 @@
      *            system property with the requested name.
      * @return the requested property's value as an {@code Integer} or the
      *         default value.
-     * @since Android 1.0        
      */
     public static Integer getInteger(String string, Integer defaultValue) {
         if (string == null || string.length() == 0) {
@@ -303,9 +295,8 @@
 
     /**
      * Gets the primitive value of this int.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public int intValue() {
@@ -320,14 +311,13 @@
     /**
      * Parses the specified string as a signed decimal integer value. The ASCII
      * character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of an integer value.
      * @return the primitive integer value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as an integer value.
-     * @since Android 1.0
      */
     public static int parseInt(String string) throws NumberFormatException {
         return parseInt(string, 10);
@@ -336,7 +326,7 @@
     /**
      * Parses the specified string as a signed integer value using the specified
      * radix. The ASCII character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of an integer value.
      * @param radix
@@ -348,7 +338,6 @@
      *             {@code radix < Character.MIN_RADIX},
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as an integer value.
-     * @since Android 1.0
      */
     public static int parseInt(String string, int radix)
             throws NumberFormatException {
@@ -417,11 +406,10 @@
     /**
      * Converts the specified integer into its binary string representation. The
      * returned string is a concatenation of '0' and '1' characters.
-     * 
+     *
      * @param i
      *            the integer to convert.
      * @return the binary string representation of {@code i}.
-     * @since Android 1.0
      */
     public static String toBinaryString(int i) {
         int count = 1, j = i;
@@ -446,12 +434,11 @@
      * Converts the specified integer into its hexadecimal string
      * representation. The returned string is a concatenation of characters from
      * '0' to '9' and 'a' to 'f'.
-     * 
+     *
      * @param i
      *            the integer to convert.
      * @return the hexadecimal string representation of {@code i}.
-     * @since Android 1.0
-     */    
+     */
     public static String toHexString(int i) {
         int count = 1, j = i;
 
@@ -480,12 +467,11 @@
     /**
      * Converts the specified integer into its octal string representation. The
      * returned string is a concatenation of characters from '0' to '7'.
-     * 
+     *
      * @param i
      *            the integer to convert.
      * @return the octal string representation of {@code i}.
-     * @since Android 1.0
-     */    
+     */
     public static String toOctalString(int i) {
         int count = 1, j = i;
 
@@ -514,14 +500,102 @@
      * Converts the specified integer into its decimal string representation.
      * The returned string is a concatenation of a minus sign if the number is
      * negative and characters from '0' to '9'.
-     * 
-     * @param i
+     *
+     * @param value
      *            the integer to convert.
-     * @return the decimal string representation of {@code i}.
-     * @since Android 1.0
-     */    
-    public static String toString(int i) {
-        return toString(i, 10);
+     * @return the decimal string representation of {@code value}.
+     */
+    public static String toString(int value) {
+        // BEGIN android-note
+        // cache the strings in the range 0..99 to save allocations?
+        // END android-note
+        if (value == 0) {
+            return "0"; //$NON-NLS-1$
+        }
+
+        // Faster algorithm for smaller Integers
+        if (value < 1000 && value > -1000) {
+            char[] buffer = new char[4];
+            int positive_value = value < 0 ? -value : value;
+            int first_digit = 0;
+            if (value < 0) {
+                buffer[0] = '-';
+                first_digit++;
+            }
+            int last_digit = first_digit;
+            int quot = positive_value;
+            do {
+                int res = quot / 10;
+                int digit_value = quot - (res * 10);
+                digit_value += '0';
+                buffer[last_digit++] = (char) digit_value;
+                quot = res;
+            } while (quot != 0);
+
+            int count = last_digit--;
+            do {
+                char tmp = buffer[last_digit];
+                buffer[last_digit--] = buffer[first_digit];
+                buffer[first_digit++] = tmp;
+            } while (first_digit < last_digit);
+            return new String(0, count, buffer);
+        }
+        if (value == MIN_VALUE) {
+            return "-2147483648";//$NON-NLS-1$
+        }
+
+        char[] buffer = new char[11];
+        int positive_value = value < 0 ? -value : value;
+        byte first_digit = 0;
+        if (value < 0) {
+            buffer[0] = '-';
+            first_digit++;
+        }
+        byte last_digit = first_digit;
+        byte count;
+        int number;
+        boolean start = false;
+        for (int i = 0; i < 9; i++) {
+            count = 0;
+            if (positive_value < (number = decimalScale[i])) {
+                if (start) {
+                    buffer[last_digit++] = '0';
+                }
+                continue;
+            }
+
+            if (i > 0) {
+                number = (decimalScale[i] << 3);
+                if (positive_value >= number) {
+                    positive_value -= number;
+                    count += 8;
+                }
+                number = (decimalScale[i] << 2);
+                if (positive_value >= number) {
+                    positive_value -= number;
+                    count += 4;
+                }
+            }
+            number = (decimalScale[i] << 1);
+            if (positive_value >= number) {
+                positive_value -= number;
+                count += 2;
+            }
+            if (positive_value >= decimalScale[i]) {
+                positive_value -= decimalScale[i];
+                count++;
+            }
+            if (count > 0 && !start) {
+                start = true;
+            }
+            if (start) {
+                buffer[last_digit++] = (char) (count + '0');
+            }
+        }
+
+        buffer[last_digit++] = (char) (positive_value + '0');
+        count = last_digit--;
+        return new String(0, count, buffer);
     }
 
     /**
@@ -531,15 +605,18 @@
      * depending on the radix. If {@code radix} is not in the interval defined
      * by {@code Character.MIN_RADIX} and {@code Character.MAX_RADIX} then 10 is
      * used as the base for the conversion.
-     * 
+     *
      * @param i
      *            the integer to convert.
      * @param radix
      *            the base to use for the conversion.
      * @return the string representation of {@code i}.
-     * @since Android 1.0
-     */    
+     */
     public static String toString(int i, int radix) {
+        // BEGIN android-note
+        // if radix==10, call thru to faster Integer.toString(int) ?
+        // only worthwhile if 10 is a popular parameter
+        // END android-note
         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
             radix = 10;
         }
@@ -575,7 +652,7 @@
 
     /**
      * Parses the specified string as a signed decimal integer value.
-     * 
+     *
      * @param string
      *            the string representation of an integer value.
      * @return an {@code Integer} instance containing the integer value
@@ -584,7 +661,6 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as an integer value.
      * @see #parseInt(String)
-     * @since Android 1.0
      */
     public static Integer valueOf(String string) throws NumberFormatException {
         return valueOf(parseInt(string));
@@ -593,7 +669,7 @@
     /**
      * Parses the specified string as a signed integer value using the specified
      * radix.
-     * 
+     *
      * @param string
      *            the string representation of an integer value.
      * @param radix
@@ -606,7 +682,6 @@
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as an integer value.
      * @see #parseInt(String, int)
-     * @since Android 1.0
      */
     public static Integer valueOf(String string, int radix)
             throws NumberFormatException {
@@ -618,11 +693,11 @@
      * and returns the bit mask value for that bit. This is also referred to as
      * the Most Significant 1 Bit. Returns zero if the specified integer is
      * zero.
-     * 
+     *
      * @param i
      *            the integer to examine.
      * @return the bit mask indicating the highest 1 bit in {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int highestOneBit(int i) {
         i |= (i >> 1);
@@ -638,11 +713,11 @@
      * and returns the bit mask value for that bit. This is also referred
      * to as the Least Significant 1 Bit. Returns zero if the specified integer
      * is zero.
-     * 
+     *
      * @param i
      *            the integer to examine.
      * @return the bit mask indicating the lowest 1 bit in {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int lowestOneBit(int i) {
         return (i & (-i));
@@ -651,11 +726,11 @@
     /**
      * Determines the number of leading zeros in the specified integer prior to
      * the {@link #highestOneBit(int) highest one bit}.
-     * 
+     *
      * @param i
      *            the integer to examine.
      * @return the number of leading zeros in {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int numberOfLeadingZeros(int i) {
         i |= i >> 1;
@@ -669,11 +744,11 @@
     /**
      * Determines the number of trailing zeros in the specified integer after
      * the {@link #lowestOneBit(int) lowest one bit}.
-     * 
+     *
      * @param i
      *            the integer to examine.
      * @return the number of trailing zeros in {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int numberOfTrailingZeros(int i) {
         return bitCount((i & -i) - 1);
@@ -682,11 +757,11 @@
     /**
      * Counts the number of 1 bits in the specified integer; this is also
      * referred to as population count.
-     * 
+     *
      * @param i
      *            the integer to examine.
      * @return the number of 1 bits in {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int bitCount(int i) {
         i -= ((i >> 1) & 0x55555555);
@@ -700,13 +775,13 @@
     /**
      * Rotates the bits of the specified integer to the left by the specified
      * number of bits.
-     * 
+     *
      * @param i
      *            the integer value to rotate left.
      * @param distance
      *            the number of bits to rotate.
      * @return the rotated value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int rotateLeft(int i, int distance) {
         if (distance == 0) {
@@ -723,13 +798,13 @@
     /**
      * Rotates the bits of the specified integer to the right by the specified
      * number of bits.
-     * 
+     *
      * @param i
      *            the integer value to rotate right.
      * @param distance
      *            the number of bits to rotate.
      * @return the rotated value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int rotateRight(int i, int distance) {
         if (distance == 0) {
@@ -745,11 +820,11 @@
 
     /**
      * Reverses the order of the bytes of the specified integer.
-     * 
+     *
      * @param i
      *            the integer value for which to reverse the byte order.
      * @return the reversed value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int reverseBytes(int i) {
         int b3 = i >>> 24;
@@ -761,11 +836,11 @@
 
     /**
      * Reverses the order of the bits of the specified integer.
-     * 
+     *
      * @param i
      *            the integer value for which to reverse the bit order.
      * @return the reversed value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int reverse(int i) {
         // From Hacker's Delight, 7-1, Figure 7-1
@@ -778,12 +853,12 @@
     /**
      * Returns the value of the {@code signum} function for the specified
      * integer.
-     * 
+     *
      * @param i
      *            the integer value to check.
      * @return -1 if {@code i} is negative, 1 if {@code i} is positive, 0 if
      *         {@code i} is zero.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int signum(int i) {
         return (i == 0 ? 0 : (i < 0 ? -1 : 1));
@@ -795,12 +870,11 @@
      * If it is not necessary to get a new {@code Integer} instance, it is
      * recommended to use this method instead of the constructor, since it
      * maintains a cache of instances which may result in better performance.
-     * </p>
-     * 
+     *
      * @param i
      *            the integer value to store in the instance.
      * @return a {@code Integer} instance containing {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Integer valueOf(int i) {
         if (i < -128 || i > 127) {
@@ -814,7 +888,6 @@
         /**
          * <p>
          * A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing.
-         * </p>
          */
         static final Integer[] CACHE = new Integer[256];
 
diff --git a/luni/src/main/java/java/lang/InternalError.java b/luni/src/main/java/java/lang/InternalError.java
index 9082cd8..d4748af 100644
--- a/luni/src/main/java/java/lang/InternalError.java
+++ b/luni/src/main/java/java/lang/InternalError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine notices that it has gotten into an undefined
  * state.
- * 
- * @since Android 1.0
  */
 public class InternalError extends VirtualMachineError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code InternalError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public InternalError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public InternalError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/InterruptedException.java b/luni/src/main/java/java/lang/InterruptedException.java
index b014559..0e099c3 100644
--- a/luni/src/main/java/java/lang/InterruptedException.java
+++ b/luni/src/main/java/java/lang/InterruptedException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a waiting thread is activated before the condition it was waiting
  * for has been satisfied.
- * 
- * @since Android 1.0
  */
 public class InterruptedException extends Exception {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code InterruptedException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public InterruptedException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InterruptedException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/Iterable.java b/luni/src/main/java/java/lang/Iterable.java
index d12f0a6..31883fb 100644
--- a/luni/src/main/java/java/lang/Iterable.java
+++ b/luni/src/main/java/java/lang/Iterable.java
@@ -21,8 +21,8 @@
 /**
  * Objects of classes that implement this interface can be used within a
  * {@code foreach} statement.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface Iterable<T> {
 
@@ -30,7 +30,6 @@
      * Returns an {@link Iterator} for the elements in this object.
      * 
      * @return An {@code Iterator} instance.
-     * @since Android 1.0
      */
     Iterator<T> iterator();
 }
diff --git a/luni/src/main/java/java/lang/LinkageError.java b/luni/src/main/java/java/lang/LinkageError.java
index 9bba54b..061f3dc 100644
--- a/luni/src/main/java/java/lang/LinkageError.java
+++ b/luni/src/main/java/java/lang/LinkageError.java
@@ -23,7 +23,6 @@
  * loading and linking class files.
  * 
  * @see Error
- * @since Android 1.0
  */
 public class LinkageError extends Error {
 
@@ -32,8 +31,6 @@
     /**
      * Constructs a new {@code LinkageError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public LinkageError() {
         super();
@@ -45,7 +42,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public LinkageError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/Long.java b/luni/src/main/java/java/lang/Long.java
index 00b56ae..2746424 100644
--- a/luni/src/main/java/java/lang/Long.java
+++ b/luni/src/main/java/java/lang/Long.java
@@ -24,10 +24,9 @@
  * href="http://www.hackersdelight.org/">Henry S. Warren, Jr.'s Hacker's
  * Delight, (Addison Wesley, 2002)</a> as well as <a
  * href="http://aggregate.org/MAGIC/">The Aggregate's Magic Algorithms</a>.
- * </p>
- * 
+ *
  * @see java.lang.Number
- * @since Android 1.0
+ * @since 1.0
  */
 public final class Long extends Number implements Comparable<Long> {
 
@@ -40,22 +39,16 @@
 
     /**
      * Constant for the maximum {@code long} value, 2<sup>63</sup>-1.
-     * 
-     * @since Android 1.0
      */
     public static final long MAX_VALUE = 0x7FFFFFFFFFFFFFFFL;
 
     /**
      * Constant for the minimum {@code long} value, -2<sup>63</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final long MIN_VALUE = 0x8000000000000000L;
 
     /**
      * The {@link Class} object that represents the primitive type {@code long}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Long> TYPE = (Class<Long>) new long[0].getClass()
@@ -67,8 +60,8 @@
     /**
      * Constant for the number of bits needed to represent a {@code long} in
      * two's complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 64;
 
@@ -78,7 +71,6 @@
      * 
      * @param value
      *            the primitive long value to store in the new instance.
-     * @since Android 1.0
      */
     public Long(long value) {
         this.value = value;
@@ -92,7 +84,6 @@
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into a long value.
      * @see #parseLong(String)
-     * @since Android 1.0
      */
     public Long(String string) throws NumberFormatException {
         this(parseLong(string));
@@ -114,7 +105,7 @@
      *         {@code object} are equal; a positive value if the value of this
      *         long is greater than the value of {@code object}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Long object) {
         return value > object.value ? 1 : (value < object.value ? -1 : 0);
@@ -131,7 +122,6 @@
      * @return a {@code Long} containing the value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} can not be parsed as a long value.
-     * @since Android 1.0
      */
     public static Long decode(String string) throws NumberFormatException {
         int length = string.length(), i = 0;
@@ -187,7 +177,6 @@
      *            the object to compare this long with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Long}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -209,7 +198,6 @@
      * @param string
      *            the name of the requested system property.
      * @return the requested property's value as a {@code Long} or {@code null}.
-     * @since Android 1.0
      */
     public static Long getLong(String string) {
         if (string == null || string.length() == 0) {
@@ -239,7 +227,6 @@
      *            property with the requested name.
      * @return the requested property's value as a {@code Long} or the default
      *         value.
-     * @since Android 1.0
      */
     public static Long getLong(String string, long defaultValue) {
         if (string == null || string.length() == 0) {
@@ -269,7 +256,6 @@
      *            property with the requested name.
      * @return the requested property's value as a {@code Long} or the default
      *         value.
-     * @since Android 1.0
      */
     public static Long getLong(String string, Long defaultValue) {
         if (string == null || string.length() == 0) {
@@ -300,7 +286,6 @@
      * Gets the primitive value of this long.
      * 
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public long longValue() {
@@ -317,7 +302,6 @@
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a long value.
-     * @since Android 1.0
      */
     public static long parseLong(String string) throws NumberFormatException {
         return parseLong(string, 10);
@@ -338,7 +322,6 @@
      *             {@code radix < Character.MIN_RADIX},
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a long value.
-     * @since Android 1.0
      */
     public static long parseLong(String string, int radix)
             throws NumberFormatException {
@@ -397,7 +380,6 @@
      * @param l
      *            the long value to convert.
      * @return the binary string representation of {@code l}.
-     * @since Android 1.0
      */
     public static String toBinaryString(long l) {
         int count = 1;
@@ -427,7 +409,6 @@
      * @param l
      *            the long value to convert.
      * @return the hexadecimal string representation of {@code l}.
-     * @since Android 1.0
      */
     public static String toHexString(long l) {
         int count = 1;
@@ -462,7 +443,6 @@
      * @param l
      *            the long value to convert.
      * @return the octal string representation of {@code l}.
-     * @since Android 1.0
      */
     public static String toOctalString(long l) {
         int count = 1;
@@ -497,8 +477,7 @@
      * @param l
      *            the long to convert.
      * @return the decimal string representation of {@code l}.
-     * @since Android 1.0
-     */    
+     */
     public static String toString(long l) {
         return toString(l, 10);
     }
@@ -516,7 +495,6 @@
      * @param radix
      *            the base to use for the conversion.
      * @return the string representation of {@code l}.
-     * @since Android 1.0
      */
     public static String toString(long l, int radix) {
         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
@@ -564,7 +542,6 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a long value.
      * @see #parseLong(String)
-     * @since Android 1.0
      */
     public static Long valueOf(String string) throws NumberFormatException {
         return valueOf(parseLong(string));
@@ -586,7 +563,6 @@
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a long value.
      * @see #parseLong(String, int)
-     * @since Android 1.0
      */
     public static Long valueOf(String string, int radix)
             throws NumberFormatException {
@@ -602,7 +578,7 @@
      * @param lng
      *            the long to examine.
      * @return the bit mask indicating the highest 1 bit in {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long highestOneBit(long lng) {
         lng |= (lng >> 1);
@@ -623,7 +599,7 @@
      * @param lng
      *            the long to examine.
      * @return the bit mask indicating the lowest 1 bit in {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long lowestOneBit(long lng) {
         return (lng & (-lng));
@@ -632,11 +608,11 @@
     /**
      * Determines the number of leading zeros in the specified long value prior
      * to the {@link #highestOneBit(long) highest one bit}.
-     * 
+     *
      * @param lng
      *            the long to examine.
      * @return the number of leading zeros in {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int numberOfLeadingZeros(long lng) {
         lng |= lng >> 1;
@@ -651,11 +627,11 @@
     /**
      * Determines the number of trailing zeros in the specified long value after
      * the {@link #lowestOneBit(long) lowest one bit}.
-     * 
+     *
      * @param lng
      *            the long to examine.
      * @return the number of trailing zeros in {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int numberOfTrailingZeros(long lng) {
         return bitCount((lng & -lng) - 1);
@@ -664,11 +640,11 @@
     /**
      * Counts the number of 1 bits in the specified long value; this is also
      * referred to as population count.
-     * 
+     *
      * @param lng
      *            the long to examine.
      * @return the number of 1 bits in {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int bitCount(long lng) {
         lng = (lng & 0x5555555555555555L) + ((lng >> 1) & 0x5555555555555555L);
@@ -684,13 +660,13 @@
     /**
      * Rotates the bits of the specified long value to the left by the specified
      * number of bits.
-     * 
+     *
      * @param lng
      *            the long value to rotate left.
      * @param distance
      *            the number of bits to rotate.
      * @return the rotated value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long rotateLeft(long lng, int distance) {
         if (distance == 0) {
@@ -705,15 +681,16 @@
     }
 
     /**
+     * <p>
      * Rotates the bits of the specified long value to the right by the
      * specified number of bits.
-     * 
+     *
      * @param lng
      *            the long value to rotate right.
      * @param distance
      *            the number of bits to rotate.
      * @return the rotated value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long rotateRight(long lng, int distance) {
         if (distance == 0) {
@@ -733,7 +710,7 @@
      * @param lng
      *            the long value for which to reverse the byte order.
      * @return the reversed value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long reverseBytes(long lng) {
         long b7 = lng >>> 56;
@@ -753,7 +730,7 @@
      * @param lng
      *            the long value for which to reverse the bit order.
      * @return the reversed value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long reverse(long lng) {
         // From Hacker's Delight, 7-1, Figure 7-1
@@ -774,7 +751,7 @@
      *            the long value to check.
      * @return -1 if {@code lng} is negative, 1 if {@code lng} is positive, 0 if
      *         {@code lng} is zero.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int signum(long lng) {
         return (lng == 0 ? 0 : (lng < 0 ? -1 : 1));
@@ -786,12 +763,11 @@
      * If it is not necessary to get a new {@code Long} instance, it is
      * recommended to use this method instead of the constructor, since it
      * maintains a cache of instances which may result in better performance.
-     * </p>
-     * 
+     *
      * @param lng
      *            the long value to store in the instance.
      * @return a {@code Long} instance containing {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Long valueOf(long lng) {
         if (lng < -128 || lng > 127) {
@@ -804,7 +780,6 @@
         /**
          * <p>
          * A cache of instances used by {@link Long#valueOf(long)} and auto-boxing.
-         * </p>
          */
         static final Long[] CACHE = new Long[256];
 
diff --git a/luni/src/main/java/java/lang/Math.java b/luni/src/main/java/java/lang/Math.java
index f18f40f..998856a 100644
--- a/luni/src/main/java/java/lang/Math.java
+++ b/luni/src/main/java/java/lang/Math.java
@@ -17,26 +17,21 @@
 
 package java.lang;
 
+
 /**
  * Class Math provides basic math constants and operations such as trigonometric
  * functions, hyperbolic functions, exponential, logarithms, etc.
- * 
- * @since Android 1.0
  */
 public final class Math {
 
     /**
      * The double value closest to e, the base of the natural logarithm.
-     * 
-     * @since Android 1.0
      */
     public static final double E = 2.718281828459045;
 
     /**
      * The double value closest to pi, the ratio of a circle's circumference to
      * its diameter.
-     * 
-     * @since Android 1.0
      */
     public static final double PI = 3.141592653589793;
 
@@ -58,18 +53,16 @@
      * <li>{@code abs(-infinity) = +infinity}</li>
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose absolute value has to be computed.
      * @return the absolute value of the argument.
-     * @since Android 1.0
      */
-    public static double abs(double d) {
-        long bits = Double.doubleToLongBits(d);
-        bits &= 0x7fffffffffffffffL;
-        return Double.longBitsToDouble(bits);
-    }
+	public static double abs(double d) {
+		long bits = Double.doubleToLongBits(d);
+		bits &= 0x7fffffffffffffffL;
+		return Double.longBitsToDouble(bits);
+	}
 
     /**
      * Returns the absolute value of the argument.
@@ -81,50 +74,45 @@
      * <li>{@code abs(-infinity) = +infinity}</li>
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
-    public static float abs(float f) {
-        int bits = Float.floatToIntBits(f);
-        bits &= 0x7fffffff;
-        return Float.intBitsToFloat(bits);
-    }
+	public static float abs(float f) {
+		int bits = Float.floatToIntBits(f);
+		bits &= 0x7fffffff;
+		return Float.intBitsToFloat(bits);
+	}
 
     /**
      * Returns the absolute value of the argument.
      * <p>
      * If the argument is {@code Integer.MIN_VALUE}, {@code Integer.MIN_VALUE}
      * is returned.
-     * </p>
-     * 
+     *
      * @param i
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
-    public static int abs(int i) {
-        return i >= 0 ? i : -i;
-    }
+	public static int abs(int i) {
+		return i >= 0 ? i : -i;
+	}
 
     /**
      * Returns the absolute value of the argument. If the argument is {@code
      * Long.MIN_VALUE}, {@code Long.MIN_VALUE} is returned.
-     * 
+     *
      * @param l
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
-    public static long abs(long l) {
-        return l >= 0 ? l : -l;
-    }
+	public static long abs(long l) {
+		return l >= 0 ? l : -l;
+	}
 
     /**
      * Returns the closest double approximation of the arc cosine of the
@@ -137,14 +125,12 @@
      * <li>{@code acos((anything < -1) = NaN}</li>
      * <li>{@code acos(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to compute arc cosine of.
      * @return the arc cosine of the argument.
-     * @since Android 1.0
      */
-    public static native double acos(double d);
+	public static native double acos(double d);
 
     /**
      * Returns the closest double approximation of the arc sine of the argument
@@ -157,14 +143,12 @@
      * <li>{@code asin((anything < -1)) = NaN}</li>
      * <li>{@code asin(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose arc sine has to be computed.
      * @return the arc sine of the argument.
-     * @since Android 1.0
      */
-    public static native double asin(double d);
+	public static native double asin(double d);
 
     /**
      * Returns the closest double approximation of the arc tangent of the
@@ -179,12 +163,10 @@
      * <li>{@code atan(-infinity) = -pi/2}</li>
      * <li>{@code atan(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose arc tangent has to be computed.
      * @return the arc tangent of the argument.
-     * @since Android 1.0
      */
     public static native double atan(double d);
 
@@ -219,19 +201,14 @@
      * <li>{@code atan2(-infinity, (anything but,0, NaN, and infinity))}
      * {@code =} {@code -pi/2}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param y
      *            the numerator of the value whose atan has to be computed.
      * @param x
      *            the denominator of the value whose atan has to be computed.
      * @return the arc tangent of {@code y/x}.
-     * @since Android 1.0
      */
-    public static native double atan2(double y, double x);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
+    public static native double atan2(double x, double y);
 
     /**
      * Returns the closest double approximation of the cube root of the
@@ -245,12 +222,10 @@
      * <li>{@code cbrt(-infinity) = -infinity}</li>
      * <li>{@code cbrt(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose cube root has to be computed.
      * @return the cube root of the argument.
-     * @since Android 1.0
      */
     public static native double cbrt(double d);
 
@@ -267,16 +242,14 @@
      * <li>{@code ceil(-infinity) = -infinity}</li>
      * <li>{@code ceil(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose closest integer value has to be computed.
      * @return the ceiling of the argument.
-     * @since Android 1.0
      */
     public static native double ceil(double d);
 
-    /**
+	/**
      * Returns the closest double approximation of the cosine of the argument.
      * The returned result is within 1 ulp (unit in the last place) of the real
      * result.
@@ -287,15 +260,13 @@
      * <li>{@code cos(-infinity) = NaN}</li>
      * <li>{@code cos(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the angle whose cosine has to be computed, in radians.
      * @return the cosine of the argument.
-     * @since Android 1.0
      */
     public static native double cos(double d);
-    
+
     /**
      * Returns the closest double approximation of the hyperbolic cosine of the
      * argument. The returned result is within 2.5 ulps (units in the last
@@ -307,12 +278,10 @@
      * <li>{@code cosh(-infinity) = +infinity}</li>
      * <li>{@code cosh(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose hyperbolic cosine has to be computed.
      * @return the hyperbolic cosine of the argument.
-     * @since Android 1.0
      */
     public static native double cosh(double d);
 
@@ -327,15 +296,13 @@
      * <li>{@code exp(-infinity) = +0.0}</li>
      * <li>{@code exp(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose exponential has to be computed.
      * @return the exponential of the argument.
-     * @since Android 1.0
      */
     public static native double exp(double d);
-    
+
     /**
      * Returns the closest double approximation of <i>{@code e}</i><sup>
      * {@code d}</sup>{@code - 1}. If the argument is very close to 0, it is
@@ -354,14 +321,12 @@
      * <li>{@code expm1(-infinity) = -1.0}</li>
      * <li>{@code expm1(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to compute the <i>{@code e}</i><sup>{@code d}
      *            </sup>{@code - 1} of.
      * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value
      *         of the argument.
-     * @since Android 1.0
      */
     public static native double expm1(double d);
 
@@ -377,20 +342,19 @@
      * <li>{@code floor(-infinity) = -infinity}</li>
      * <li>{@code floor(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose closest integer value has to be computed.
      * @return the floor of the argument.
-     * @since Android 1.0
      */
     public static native double floor(double d);
-    
+
     /**
      * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +}
      * <i> {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is
      * without medium underflow or overflow. The returned result is within 1 ulp
-     * (unit in the last place) of the real result.
+     * (unit in the last place) of the real result. If one parameter remains
+     * constant, the result should be semi-monotonic.
      * <p>
      * Special cases:
      * <ul>
@@ -400,8 +364,7 @@
      * <li>{@code hypot((anything including NaN), -infinity) = +infinity}</li>
      * <li>{@code hypot(NaN, NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param x
      *            a double number.
      * @param y
@@ -409,7 +372,6 @@
      * @return the {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +}
      *         <i> {@code y}</i><sup>{@code 2}</sup>{@code )} value of the
      *         arguments.
-     * @since Android 1.0
      */
     public static native double hypot(double x, double y);
 
@@ -431,19 +393,14 @@
      * <li>{@code IEEEremainder(x, -infinity) = x } where x is anything but
      * +/-infinity</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param x
      *            the numerator of the operation.
      * @param y
      *            the denominator of the operation.
      * @return the IEEE754 floating point reminder of of {@code x/y}.
-     * @since Android 1.0
      */
     public static native double IEEEremainder(double x, double y);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
 
     /**
      * Returns the closest double approximation of the natural logarithm of the
@@ -459,12 +416,10 @@
      * <li>{@code log(-infinity) = NaN}</li>
      * <li>{@code log(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose log has to be computed.
      * @return the natural logarithm of the argument.
-     * @since Android 1.0
      */
     public static native double log(double d);
 
@@ -482,21 +437,19 @@
      * <li>{@code log10(-infinity) = NaN}</li>
      * <li>{@code log10(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose base 10 log has to be computed.
      * @return the natural logarithm of the argument.
-     * @since Android 1.0
      */
     public static native double log10(double d);
-    
+
     /**
      * Returns the closest double approximation of the natural logarithm of the
      * sum of the argument and 1. If the argument is very close to 0, it is much
      * more accurate to use {@code log1p(d)} than {@code log(1.0+d)} (due to
      * numerical cancellation). The returned result is within 1 ulp (unit in the
-     * last place) of the real result.
+     * last place) of the real result and is semi-monotonic.
      * <p>
      * Special cases:
      * <ul>
@@ -508,12 +461,10 @@
      * <li>{@code log1p(-infinity) = NaN}</li>
      * <li>{@code log1p(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to compute the {@code ln(1+d)} of.
      * @return the natural logarithm of the sum of the argument and 1.
-     * @since Android 1.0
      */
     public static native double log1p(double d);
 
@@ -528,29 +479,34 @@
      * <li>{@code max(+0.0, -0.0) = +0.0}</li>
      * <li>{@code max(-0.0, +0.0) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d1
      *            the first argument.
      * @param d2
      *            the second argument.
      * @return the larger of {@code d1} and {@code d2}.
-     * @since Android 1.0
      */
-    public static double max(double d1, double d2) {
-        if (d1 > d2)
+	public static double max(double d1, double d2) {
+        // BEGIN android-changed
+        // copied from a newer version of Harmony
+        if (d1 > d2) {
             return d1;
-        if (d1 < d2)
+        }
+        if (d1 < d2) {
             return d2;
+        }
         /* if either arg is NaN, return NaN */
-        if (d1 != d2)
+        if (d1 != d2) {
             return Double.NaN;
-        /* max( +0.0,-0.0) == +0.0 */
-        if (d1 == 0.0
-                && ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0)
-            return 0.0;
-        return d1;
-    }
+        }
+        /* max(+0.0,-0.0) == +0.0 */
+        /* 0 == Double.doubleToRawLongBits(0.0d) */
+        if (Double.doubleToRawLongBits(d1) != 0) {
+            return d2;
+        }
+        return 0.0d;
+        // END android-changed
+	}
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
@@ -563,59 +519,62 @@
      * <li>{@code max(+0.0, -0.0) = +0.0}</li>
      * <li>{@code max(-0.0, +0.0) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f1
      *            the first argument.
      * @param f2
      *            the second argument.
      * @return the larger of {@code f1} and {@code f2}.
-     * @since Android 1.0
      */
-    public static float max(float f1, float f2) {
-        if (f1 > f2)
+	public static float max(float f1, float f2) {
+        // BEGIN android-changed
+        // copied from a newer version of Harmony
+        if (f1 > f2) {
             return f1;
-        if (f1 < f2)
+        }
+        if (f1 < f2) {
             return f2;
+        }
         /* if either arg is NaN, return NaN */
-        if (f1 != f2)
+        if (f1 != f2) {
             return Float.NaN;
-        /* max( +0.0,-0.0) == +0.0 */
-        if (f1 == 0.0f
-                && ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0)
-            return 0.0f;
-        return f1;
-    }
+        }
+        /* max(+0.0,-0.0) == +0.0 */
+        /* 0 == Float.floatToRawIntBits(0.0f) */
+        if (Float.floatToRawIntBits(f1) != 0) {
+            return f2;
+        }
+        return 0.0f;
+        // END android-changed
+	}
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
      * arguments.
-     * 
+     *
      * @param i1
      *            the first argument.
      * @param i2
      *            the second argument.
      * @return the larger of {@code i1} and {@code i2}.
-     * @since Android 1.0
      */
-    public static int max(int i1, int i2) {
-        return i1 > i2 ? i1 : i2;
-    }
+	public static int max(int i1, int i2) {
+		return i1 > i2 ? i1 : i2;
+	}
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
      * arguments.
-     * 
+     *
      * @param l1
      *            the first argument.
      * @param l2
      *            the second argument.
      * @return the larger of {@code l1} and {@code l2}.
-     * @since Android 1.0
      */
-    public static long max(long l1, long l2) {
-        return l1 > l2 ? l1 : l2;
-    }
+	public static long max(long l1, long l2) {
+		return l1 > l2 ? l1 : l2;
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
@@ -628,29 +587,34 @@
      * <li>{@code min(+0.0, -0.0) = -0.0}</li>
      * <li>{@code min(-0.0, +0.0) = -0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d1
      *            the first argument.
      * @param d2
      *            the second argument.
      * @return the smaller of {@code d1} and {@code d2}.
-     * @since Android 1.0
      */
-    public static double min(double d1, double d2) {
-        if (d1 > d2)
+	public static double min(double d1, double d2) {
+        // BEGIN android-changed
+        // copied from a newer version of Harmony
+        if (d1 > d2) {
             return d2;
-        if (d1 < d2)
+        }
+        if (d1 < d2) {
             return d1;
+        }
         /* if either arg is NaN, return NaN */
-        if (d1 != d2)
+        if (d1 != d2) {
             return Double.NaN;
-        /* min( +0.0,-0.0) == -0.0 */
-        if (d1 == 0.0
-                && ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0)
-            return 0.0 * (-1.0);
-        return d1;
-    }
+        }
+        /* min(+0.0,-0.0) == -0.0 */
+        /* 0x8000000000000000L == Double.doubleToRawLongBits(-0.0d) */
+        if (Double.doubleToRawLongBits(d1) == 0x8000000000000000L) {
+            return -0.0d;
+        }
+        return d2;
+        // END android-changed
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
@@ -663,59 +627,62 @@
      * <li>{@code min(+0.0, -0.0) = -0.0}</li>
      * <li>{@code min(-0.0, +0.0) = -0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f1
      *            the first argument.
      * @param f2
      *            the second argument.
      * @return the smaller of {@code f1} and {@code f2}.
-     * @since Android 1.0
      */
-    public static float min(float f1, float f2) {
-        if (f1 > f2)
+	public static float min(float f1, float f2) {
+        // BEGIN android-changed
+        // copied from a newer version of Harmony
+        if (f1 > f2) {
             return f2;
-        if (f1 < f2)
+        }
+        if (f1 < f2) {
             return f1;
+        }
         /* if either arg is NaN, return NaN */
-        if (f1 != f2)
+        if (f1 != f2) {
             return Float.NaN;
-        /* min( +0.0,-0.0) == -0.0 */
-        if (f1 == 0.0f
-                && ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0)
-            return 0.0f * (-1.0f);
-        return f1;
-    }
+        }
+        /* min(+0.0,-0.0) == -0.0 */
+        /* 0x80000000 == Float.floatToRawIntBits(-0.0f) */
+        if (Float.floatToRawIntBits(f1) == 0x80000000) {
+            return -0.0f;
+        }
+        return f2;
+        // END android-changed
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
      * arguments.
-     * 
+     *
      * @param i1
      *            the first argument.
      * @param i2
      *            the second argument.
      * @return the smaller of {@code i1} and {@code i2}.
-     * @since Android 1.0
      */
-    public static int min(int i1, int i2) {
-        return i1 < i2 ? i1 : i2;
-    }
+	public static int min(int i1, int i2) {
+		return i1 < i2 ? i1 : i2;
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
      * arguments.
-     * 
+     *
      * @param l1
      *            the first argument.
      * @param l2
      *            the second argument.
      * @return the smaller of {@code l1} and {@code l2}.
-     * @since Android 1.0
      */
-    public static long min(long l1, long l2) {
-        return l1 < l2 ? l1 : l2;
-    }
+	public static long min(long l1, long l2) {
+		return l1 < l2 ? l1 : l2;
+	}
 
     /**
      * Returns the closest double approximation of the result of raising
@@ -747,19 +714,14 @@
      * {@code pow(-1,(integer))*pow(+anything,integer) }</li>
      * <li>{@code pow((-anything except 0 and inf), (non-integer)) = NAN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param x
      *            the base of the operation.
      * @param y
      *            the exponent of the operation.
      * @return {@code x} to the power of {@code y}.
-     * @since Android 1.0
      */
     public static native double pow(double x, double y);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
 
     /**
      * Returns the double conversion of the result of rounding the argument to
@@ -773,16 +735,14 @@
      * <li>{@code rint(-infinity) = -infinity}</li>
      * <li>{@code rint(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to be rounded.
      * @return the closest integer to the argument (as a double).
-     * @since Android 1.0
      */
     public static native double rint(double d);
 
-    /**
+	/**
      * Returns the result of rounding the argument to an integer. The result is
      * equivalent to {@code (long) Math.floor(d+0.5)}.
      * <p>
@@ -796,19 +756,17 @@
      * <li>{@code round(-infintiy) = Long.MIN_VALUE}</li>
      * <li>{@code round(NaN) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to be rounded.
      * @return the closest integer to the argument.
-     * @since Android 1.0
      */
-    public static long round(double d) {
-        // check for NaN
-        if (d != d)
-            return 0L;
-        return (long) floor(d + 0.5d);
-    }
+	public static long round(double d) {
+		// check for NaN
+		if (d != d)
+			return 0L;
+		return (long) floor(d + 0.5d);
+	}
 
     /**
      * Returns the result of rounding the argument to an integer. The result is
@@ -824,18 +782,39 @@
      * <li>{@code round(-infintiy) = Integer.MIN_VALUE}</li>
      * <li>{@code round(NaN) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the value to be rounded.
      * @return the closest integer to the argument.
-     * @since Android 1.0
      */
-    public static int round(float f) {
-        // check for NaN
-        if (f != f)
-            return 0;
-        return (int) floor(f + 0.5f);
+	public static int round(float f) {
+		// check for NaN
+		if (f != f)
+			return 0;
+		return (int) floor(f + 0.5f);
+	}
+
+    /**
+     * Returns the signum function of the argument. If the argument is less than
+     * zero, it returns -1.0. If the argument is greater than zero, 1.0 is
+     * returned. If the argument is either positive or negative zero, the
+     * argument is returned as result.
+     * <p>
+     * Special cases:
+     * <ul>
+     * <li>{@code signum(+0.0) = +0.0}</li>
+     * <li>{@code signum(-0.0) = -0.0}</li>
+     * <li>{@code signum(+infinity) = +1.0}</li>
+     * <li>{@code signum(-infinity) = -1.0}</li>
+     * <li>{@code signum(NaN) = NaN}</li>
+     * </ul>
+     *
+     * @param d
+     *            the value whose signum has to be computed.
+     * @return the value of the signum function.
+     */
+    public static double signum(double d) {
+        return StrictMath.signum(d);
     }
 
     /**
@@ -852,37 +831,10 @@
      * <li>{@code signum(-infinity) = -1.0}</li>
      * <li>{@code signum(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
-     * @param d
-     *            the value whose signum has to be computed.
-     * @return the value of the signum function.
-     * @since Android 1.0
-     */
-    public static double signum(double d) {
-        return StrictMath.signum(d);
-    }
-    
-    /**
-     * Returns the signum function of the argument. If the argument is less than
-     * zero, it returns -1.0. If the argument is greater than zero, 1.0 is
-     * returned. If the argument is either positive or negative zero, the
-     * argument is returned as result.
-     * <p>
-     * Special cases:
-     * <ul>
-     * <li>{@code signum(+0.0) = +0.0}</li>
-     * <li>{@code signum(-0.0) = -0.0}</li>
-     * <li>{@code signum(+infinity) = +1.0}</li>
-     * <li>{@code signum(-infinity) = -1.0}</li>
-     * <li>{@code signum(NaN) = NaN}</li>
-     * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
-     * @since Android 1.0
      */
     public static float signum(float f) {
         return StrictMath.signum(f);
@@ -901,15 +853,13 @@
      * <li>{@code sin(-infinity) = NaN}</li>
      * <li>{@code sin(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the angle whose sin has to be computed, in radians.
      * @return the sine of the argument.
-     * @since Android 1.0
      */
     public static native double sin(double d);
-    
+
     /**
      * Returns the closest double approximation of the hyperbolic sine of the
      * argument. The returned result is within 2.5 ulps (units in the last
@@ -923,12 +873,10 @@
      * <li>{@code sinh(-infinity) = -infinity}</li>
      * <li>{@code sinh(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose hyperbolic sine has to be computed.
      * @return the hyperbolic sine of the argument.
-     * @since Android 1.0
      */
     public static native double sinh(double d);
 
@@ -944,12 +892,10 @@
      * <li>{@code sqrt(+infinity) = +infinity}</li>
      * <li>{@code sqrt(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose square root has to be computed.
      * @return the square root of the argument.
-     * @since Android 1.0
      */
     public static native double sqrt(double d);
 
@@ -966,15 +912,13 @@
      * <li>{@code tan(-infinity) = NaN}</li>
      * <li>{@code tan(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the angle whose tangens has to be computed, in radians.
      * @return the tangent of the argument.
-     * @since Android 1.0
      */
     public static native double tan(double d);
-    
+
     /**
      * Returns the closest double approximation of the hyperbolic tangent of the
      * argument. The absolute value is always less than 1. The returned result
@@ -990,28 +934,25 @@
      * <li>{@code tanh(-infinity) = -1.0}</li>
      * <li>{@code tanh(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose hyperbolic tangent has to be computed.
      * @return the hyperbolic tangent of the argument.
-     * @since Android 1.0
      */
     public static native double tanh(double d);
 
     /**
      * Returns a pseudo-random number between 0.0 (inclusive) and 1.0
      * (exclusive).
-     * 
+     *
      * @return a pseudo-random number.
-     * @since Android 1.0
      */
-    public static double random() {
-        if (random == null) {
-            random = new java.util.Random();
-        }
-        return random.nextDouble();
-    }
+	public static double random() {
+		if (random == null) {
+			random = new java.util.Random();
+		}
+		return random.nextDouble();
+	}
 
     /**
      * Returns the measure in radians of the supplied degree angle. The result
@@ -1025,16 +966,14 @@
      * <li>{@code toRadians(-infinity) = -infinity}</li>
      * <li>{@code toRadians(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param angdeg
      *            an angle in degrees.
      * @return the radian measure of the angle.
-     * @since Android 1.0
      */
-    public static double toRadians(double angdeg) {
-        return angdeg / 180d * PI;
-    }
+	public static double toRadians(double angdeg) {
+		return angdeg / 180d * PI;
+	}
 
     /**
      * Returns the measure in degrees of the supplied radian angle. The result
@@ -1048,18 +987,16 @@
      * <li>{@code toDegrees(-infinity) = -infinity}</li>
      * <li>{@code toDegrees(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param angrad
      *            an angle in radians.
      * @return the degree measure of the angle.
-     * @since Android 1.0
      */
-    public static double toDegrees(double angrad) {
-        return angrad * 180d / PI;
-    }
-    
-    /**
+	public static double toDegrees(double angrad) {
+		return angrad * 180d / PI;
+	}
+
+	/**
      * Returns the argument's ulp (unit in the last place). The size of a ulp of
      * a double value is the positive distance between this value and the double
      * value next larger in magnitude. For non-NaN {@code x},
@@ -1073,12 +1010,10 @@
      * <li>{@code ulp(-infintiy) = infinity}</li>
      * <li>{@code ulp(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the floating-point value to compute ulp of.
      * @return the size of a ulp of the argument.
-     * @since Android 1.0
      */
     public static double ulp(double d) {
         // special cases
@@ -1105,12 +1040,10 @@
      * <li>{@code ulp(-infintiy) = infinity}</li>
      * <li>{@code ulp(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the floating-point value to compute ulp of.
      * @return the size of a ulp of the argument.
-     * @since Android 1.0
      */
     public static float ulp(float f) {
         // special cases
diff --git a/luni/src/main/java/java/lang/NegativeArraySizeException.java b/luni/src/main/java/java/lang/NegativeArraySizeException.java
index 1ca7855..50b6929 100644
--- a/luni/src/main/java/java/lang/NegativeArraySizeException.java
+++ b/luni/src/main/java/java/lang/NegativeArraySizeException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an attempt is made to create an array with a size of less than
  * zero.
- * 
- * @since Android 1.0
  */
 public class NegativeArraySizeException extends RuntimeException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NegativeArraySizeException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public NegativeArraySizeException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NegativeArraySizeException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/NoClassDefFoundError.java b/luni/src/main/java/java/lang/NoClassDefFoundError.java
index e23ecc6..9fae360 100644
--- a/luni/src/main/java/java/lang/NoClassDefFoundError.java
+++ b/luni/src/main/java/java/lang/NoClassDefFoundError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine is unable to locate a class which it has been
  * asked to load.
- * 
- * @since Android 1.0
  */
 public class NoClassDefFoundError extends LinkageError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NoClassDefFoundError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public NoClassDefFoundError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public NoClassDefFoundError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/NoSuchFieldError.java b/luni/src/main/java/java/lang/NoSuchFieldError.java
index 667d6a5..9b479f6 100644
--- a/luni/src/main/java/java/lang/NoSuchFieldError.java
+++ b/luni/src/main/java/java/lang/NoSuchFieldError.java
@@ -22,9 +22,6 @@
  * on a class or object, a field that does not exist.
  * <p>
  * Note that this can only occur when inconsistent class files are being loaded.
- * </p>
- * 
- * @since Android 1.0
  */
 public class NoSuchFieldError extends IncompatibleClassChangeError {
 
@@ -33,8 +30,6 @@
     /**
      * Constructs a new {@code NoSuchFieldError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public NoSuchFieldError() {
         super();
@@ -46,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public NoSuchFieldError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/NoSuchFieldException.java b/luni/src/main/java/java/lang/NoSuchFieldException.java
index 31a566d..283bfab 100644
--- a/luni/src/main/java/java/lang/NoSuchFieldException.java
+++ b/luni/src/main/java/java/lang/NoSuchFieldException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine notices that a program tries to reference,
  * on a class or object, a field that does not exist.
- * 
- * @since Android 1.0
  */
 public class NoSuchFieldException extends java.lang.Exception {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NoSuchFieldException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public NoSuchFieldException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NoSuchFieldException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/NoSuchMethodError.java b/luni/src/main/java/java/lang/NoSuchMethodError.java
index a72f76b..91ed06c 100644
--- a/luni/src/main/java/java/lang/NoSuchMethodError.java
+++ b/luni/src/main/java/java/lang/NoSuchMethodError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine notices that a program tries to reference,
  * on a class or object, a method that does not exist.
- * 
- * @since Android 1.0
  */
 public class NoSuchMethodError extends IncompatibleClassChangeError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NoSuchMethodError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public NoSuchMethodError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NoSuchMethodError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/NoSuchMethodException.java b/luni/src/main/java/java/lang/NoSuchMethodException.java
index bd3cf01..cf4dbe0 100644
--- a/luni/src/main/java/java/lang/NoSuchMethodException.java
+++ b/luni/src/main/java/java/lang/NoSuchMethodException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine notices that a program tries to reference,
  * on a class or object, a method that does not exist.
- * 
- * @since Android 1.0
  */
 public class NoSuchMethodException extends java.lang.Exception {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NoSuchMethodException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
    public NoSuchMethodException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NoSuchMethodException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/NullPointerException.java b/luni/src/main/java/java/lang/NullPointerException.java
index d11b282..90e9e50 100644
--- a/luni/src/main/java/java/lang/NullPointerException.java
+++ b/luni/src/main/java/java/lang/NullPointerException.java
@@ -23,8 +23,6 @@
  * object or array points to {@code null}. It also occurs in some other, less
  * obvious circumstances, like a {@code throw e} statement where the {@link
  * Throwable} reference is {@code null}.
- * 
- * @since Android 1.0
  */
 public class NullPointerException extends RuntimeException {
 
@@ -33,8 +31,6 @@
     /**
      * Constructs a new {@code NullPointerException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public NullPointerException() {
         super();
@@ -46,7 +42,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NullPointerException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/Number.java b/luni/src/main/java/java/lang/Number.java
index dc868cb..4fb5596 100644
--- a/luni/src/main/java/java/lang/Number.java
+++ b/luni/src/main/java/java/lang/Number.java
@@ -22,8 +22,6 @@
  * The abstract superclass of the classes which represent numeric base types
  * (that is {@link Byte}, {@link Short}, {@link Integer}, {@link Long},
  * {@link Float}, and {@link Double}. 
- * 
- * @since Android 1.0
  */
 public abstract class Number implements java.io.Serializable {
 
@@ -31,8 +29,6 @@
 
     /**
      * Empty default constructor.
-     * 
-     * @since Android 1.0
      */
     public Number() {
     }
@@ -42,7 +38,6 @@
      * truncating the value, so it fits into a byte.  
      * 
      * @return the primitive byte value of this object.
-     * @since Android 1.0
      */
     public byte byteValue() {
         return (byte) intValue();
@@ -52,7 +47,6 @@
      * Returns this object's value as a double. Might involve rounding.
      * 
      * @return the primitive double value of this object.
-     * @since Android 1.0
      */
     public abstract double doubleValue();
 
@@ -60,7 +54,6 @@
      * Returns this object's value as a float. Might involve rounding.
      * 
      * @return the primitive float value of this object.
-     * @since Android 1.0
      */
     public abstract float floatValue();
 
@@ -69,7 +62,6 @@
      * truncating the value, so it fits into an int.
      * 
      * @return the primitive int value of this object.
-     * @since Android 1.0
      */
     public abstract int intValue();
 
@@ -78,7 +70,6 @@
      * truncating the value, so it fits into a long.
      * 
      * @return the primitive long value of this object.
-     * @since Android 1.0
      */
     public abstract long longValue();
 
@@ -87,7 +78,6 @@
      * truncating the value, so it fits into a short.
      * 
      * @return the primitive short value of this object.
-     * @since Android 1.0
      */
     public short shortValue() {
         return (short) intValue();
diff --git a/luni/src/main/java/java/lang/NumberFormatException.java b/luni/src/main/java/java/lang/NumberFormatException.java
index ed5433d..9d2f0c7 100644
--- a/luni/src/main/java/java/lang/NumberFormatException.java
+++ b/luni/src/main/java/java/lang/NumberFormatException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an invalid value is passed to a string-to-number conversion
  * method.
- * 
- * @since Android 1.0
  */
 public class NumberFormatException extends java.lang.IllegalArgumentException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NumberFormatException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public NumberFormatException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NumberFormatException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/OutOfMemoryError.java b/luni/src/main/java/java/lang/OutOfMemoryError.java
index 2c54ad1..a8f8a2c 100644
--- a/luni/src/main/java/java/lang/OutOfMemoryError.java
+++ b/luni/src/main/java/java/lang/OutOfMemoryError.java
@@ -21,8 +21,6 @@
  * Thrown when a request for memory is made that can not be satisfied using the
  * available platform resources. Such a request may be made by both the running
  * application or by an internal function of the virtual machine.
- * 
- * @since Android 1.0
  */
 public class OutOfMemoryError extends java.lang.VirtualMachineError {
 
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code OutOfMemoryError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public OutOfMemoryError() {
         super();
@@ -44,7 +40,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public OutOfMemoryError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/Override.java b/luni/src/main/java/java/lang/Override.java
index 864357d..c4049cb 100644
--- a/luni/src/main/java/java/lang/Override.java
+++ b/luni/src/main/java/java/lang/Override.java
@@ -1,12 +1,12 @@
-/*
- * Copyright (C) 2007 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
- *
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -16,19 +16,19 @@
 
 package java.lang;
 
-import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
- * Annotation type used to mark methods that override a method declaration in a superclass.
- * Compilers produce an error if a method annotated with @Override does not actually override
- * a method in a superclass.
- * 
- * @since Android 1.0
+ * Annotation type used to mark methods that override a method declaration in a
+ * superclass. Compilers produce an error if a method annotated with @Override
+ * does not actually override a method in a superclass.
+ *
+ * @since 1.5
  */
-@Retention(value=java.lang.annotation.RetentionPolicy.SOURCE)
-@Target(value=java.lang.annotation.ElementType.METHOD)
-public @interface Override
-{
-
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.SOURCE)
+public @interface Override {
 }
diff --git a/luni/src/main/java/java/lang/Process.java b/luni/src/main/java/java/lang/Process.java
index 5fe8be7..c030fcc 100644
--- a/luni/src/main/java/java/lang/Process.java
+++ b/luni/src/main/java/java/lang/Process.java
@@ -17,25 +17,20 @@
 
 package java.lang;
 
-
 import java.io.InputStream;
 import java.io.OutputStream;
 
 /**
  * Represents an external process. Enables writing to, reading from, destroying,
  * and waiting for the external process, as well as querying its exit value.
- * 
+ *
  * @see Runtime#exec
  * @see ProcessBuilder#start()
- * 
- * @since Android 1.0
  */
 public abstract class Process {
 
     /**
      * Terminates this process and closes any associated streams.
-     * 
-     * @since Android 1.0
      */
     abstract public void destroy();
 
@@ -46,7 +41,6 @@
      * @return the exit value of this process.
      * @throws IllegalThreadStateException
      *             if this process has not terminated.
-     * @since Android 1.0
      */
     abstract public int exitValue();
 
@@ -56,7 +50,6 @@
      * 
      * @return the input stream to read from the error stream associated with
      *         the native process.
-     * @since Android 1.0
      */
     abstract public InputStream getErrorStream();
 
@@ -66,7 +59,6 @@
      * 
      * @return the input stream to read from the output stream associated with
      *         the native process.
-     * @since Android 1.0
      */
     abstract public InputStream getInputStream();
 
@@ -76,7 +68,6 @@
      * 
      * @return the output stream to write to the input stream associated with
      *         the native process.
-     * @since Android 1.0
      */
     abstract public OutputStream getOutputStream();
 
@@ -87,7 +78,6 @@
      * @return the exit value of the native process being waited on.
      * @throws InterruptedException
      *             if the calling thread is interrupted.
-     * @since Android 1.0
      */
     abstract public int waitFor() throws InterruptedException;
 }
diff --git a/luni/src/main/java/java/lang/ProcessBuilder.java b/luni/src/main/java/java/lang/ProcessBuilder.java
index 9d6b90b..f649fec 100644
--- a/luni/src/main/java/java/lang/ProcessBuilder.java
+++ b/luni/src/main/java/java/lang/ProcessBuilder.java
@@ -24,8 +24,8 @@
 
 /**
  * Creates operating system processes.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public final class ProcessBuilder {
 
@@ -40,10 +40,9 @@
     /**
      * Constructs a new {@code ProcessBuilder} instance with the specified
      * operating system program and its arguments.
-     * 
+     *
      * @param command
      *            the requested operating system program and its arguments.
-     * @since Android 1.0
      */
     public ProcessBuilder(String... command) {
         this(toList(command));
@@ -54,12 +53,11 @@
      * operating system program and its arguments. Note that the list passed to
      * this constructor is not copied, so any subsequent updates to it are
      * reflected in this instance's state.
-     * 
+     *
      * @param command
      *            the requested operating system program and its arguments.
      * @throws NullPointerException
      *             if {@code command} is {@code null}.
-     * @since Android 1.0
      */
     public ProcessBuilder(List<String> command) {
         super();
@@ -76,9 +74,8 @@
      * Returns this process builder's current program and arguments. Note that
      * the returned list is not a copy and modifications to it will change the
      * state of this instance.
-     * 
+     *
      * @return this process builder's program and arguments.
-     * @since Android 1.0
      */
     public List<String> command() {
         return command;
@@ -86,11 +83,10 @@
 
     /**
      * Changes the program and arguments of this process builder.
-     * 
+     *
      * @param command
      *            the new operating system program and its arguments.
      * @return this process builder instance.
-     * @since Android 1.0
      */
     public ProcessBuilder command(String... command) {
         return command(toList(command));
@@ -100,13 +96,12 @@
      * Changes the program and arguments of this process builder. Note that the
      * list passed to this method is not copied, so any subsequent updates to it
      * are reflected in this instance's state.
-     * 
+     *
      * @param command
      *            the new operating system program and its arguments.
      * @return this process builder instance.
      * @throws NullPointerException
      *             if {@code command} is {@code null}.
-     * @since Android 1.0
      */
     public ProcessBuilder command(List<String> command) {
         if (command == null) {
@@ -120,9 +115,8 @@
      * Returns the working directory of this process builder. If {@code null} is
      * returned, then the working directory of the Java process is used when a
      * process is started.
-     * 
+     *
      * @return the current working directory, may be {@code null}.
-     * @since Android 1.0
      */
     public File directory() {
         return directory;
@@ -132,11 +126,10 @@
      * Changes the working directory of this process builder. If the specified
      * directory is {@code null}, then the working directory of the Java
      * process is used when a process is started.
-     * 
+     *
      * @param directory
      *            the new working directory for this process builder.
      * @return this process builder instance.
-     * @since Android 1.0
      */
     public ProcessBuilder directory(File directory) {
         this.directory = directory;
@@ -149,9 +142,8 @@
      * the environment, as returned by {@link System#getenv()}. Note that the
      * map returned by this method is not a copy and any changes made to it are
      * reflected in this instance's state.
-     * 
+     *
      * @return the map containing this process builder's environment variables.
-     * @since Android 1.0
      */
     public Map<String, String> environment() {
         return environment;
@@ -162,10 +154,9 @@
      * output. If redirected, the {@link Process#getErrorStream()} will always
      * return end of stream and standard error is written to
      * {@link Process#getInputStream()}.
-     * 
+     *
      * @return {@code true} if the standard error is redirected; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean redirectErrorStream() {
         return redirectErrorStream;
@@ -174,12 +165,11 @@
     /**
      * Changes the state of whether or not standard error is redirected to
      * standard output.
-     * 
+     *
      * @param redirectErrorStream
      *            {@code true} to redirect standard error, {@code false}
      *            otherwise.
      * @return this process builder instance.
-     * @since Android 1.0
      */
     public ProcessBuilder redirectErrorStream(boolean redirectErrorStream) {
         this.redirectErrorStream = redirectErrorStream;
@@ -188,7 +178,7 @@
 
     /**
      * Starts a new process based on the current state of this process builder.
-     * 
+     *
      * @return the new {@code Process} instance.
      * @throws NullPointerException
      *             if any of the elements of {@link #command()} is {@code null}.
@@ -199,7 +189,6 @@
      *             process creation.
      * @throws IOException
      *             if an I/O error happens.
-     * @since Android 1.0
      */
     public Process start() throws IOException {
         if (command.isEmpty()) {
diff --git a/luni/src/main/java/java/lang/Readable.java b/luni/src/main/java/java/lang/Readable.java
index 1eca6cc..b536f59 100644
--- a/luni/src/main/java/java/lang/Readable.java
+++ b/luni/src/main/java/java/lang/Readable.java
@@ -22,8 +22,6 @@
 /**
  * Represents a sequence of characters that can be incrementally read (copied)
  * into a {@link CharBuffer}.
- * 
- * @since Android 1.0
  */
 public interface Readable {
 
@@ -37,7 +35,6 @@
      *         {@code Readable} reaches its end
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     int read(CharBuffer cb) throws IOException;
 }
diff --git a/luni/src/main/java/java/lang/Runnable.java b/luni/src/main/java/java/lang/Runnable.java
index 2cca717..b09d914 100644
--- a/luni/src/main/java/java/lang/Runnable.java
+++ b/luni/src/main/java/java/lang/Runnable.java
@@ -21,8 +21,6 @@
 /**
  * Represents a command that can be executed. Often used to run code in a
  * different {@link Thread}.
- * 
- * @since Android 1.0
  */
 public interface Runnable {
 
@@ -30,8 +28,6 @@
      * Starts executing the active part of the class' code. This method is
      * called when a thread is started that has been created with a class which
      * implements {@code Runnable}.
-     * 
-     * @since Android 1.0
      */
     public void run();
 }
diff --git a/luni/src/main/java/java/lang/RuntimeException.java b/luni/src/main/java/java/lang/RuntimeException.java
index e519bf1..9229b0c 100644
--- a/luni/src/main/java/java/lang/RuntimeException.java
+++ b/luni/src/main/java/java/lang/RuntimeException.java
@@ -23,8 +23,6 @@
  * the virtual machine. Unlike checked exceptions (exceptions where the type
  * doesn't extend {@code RuntimeException} or {@link Error}), the compiler does
  * not require code to handle runtime exceptions.
- * 
- * @since Android 1.0
  */
 public class RuntimeException extends Exception {
     
@@ -33,8 +31,6 @@
     /**
      * Constructs a new {@code RuntimeException} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public RuntimeException() {
         super();
@@ -46,7 +42,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public RuntimeException(String detailMessage) {
         super(detailMessage);
@@ -60,7 +55,6 @@
      *            the detail message for this exception.
      * @param throwable
      *            the cause of this exception.
-     * @since Android 1.0
      */
     public RuntimeException(String detailMessage, Throwable throwable) {
         super(detailMessage, throwable);
@@ -72,7 +66,6 @@
      * 
      * @param throwable
      *            the cause of this exception.
-     * @since Android 1.0
      */
     public RuntimeException(Throwable throwable) {
         super(throwable);
diff --git a/luni/src/main/java/java/lang/RuntimePermission.java b/luni/src/main/java/java/lang/RuntimePermission.java
index 0f856a0..ba7e665 100644
--- a/luni/src/main/java/java/lang/RuntimePermission.java
+++ b/luni/src/main/java/java/lang/RuntimePermission.java
@@ -23,8 +23,6 @@
  * Represents the permission to execute a runtime-related function. There is no
  * action list associated with a {@code RuntimePermission}; the user either has
  * the permission or he doesn't.
- * 
- * @since Android 1.0
  */
 public final class RuntimePermission extends BasicPermission {
 
@@ -83,7 +81,6 @@
      * 
      * @param permissionName
      *            the name of the new permission.
-     * @since Android 1.0
      */
     public RuntimePermission(String permissionName) {
         super(permissionName);
@@ -97,7 +94,6 @@
      *            the name of the new permission.
      * @param actions
      *            ignored.
-     * @since Android 1.0
      */
     public RuntimePermission(String name, String actions) {
         super(name, actions);
diff --git a/luni/src/main/java/java/lang/SecurityException.java b/luni/src/main/java/java/lang/SecurityException.java
index 7387088..c977be0 100644
--- a/luni/src/main/java/java/lang/SecurityException.java
+++ b/luni/src/main/java/java/lang/SecurityException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when a security manager check fails.
- * 
- * @since Android 1.0
  */
 public class SecurityException extends java.lang.RuntimeException {
 
@@ -29,8 +27,6 @@
     /**
      * Constructs a new {@code SecurityException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public SecurityException() {
         super();
@@ -42,7 +38,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public SecurityException(String detailMessage) {
         super(detailMessage);
@@ -56,7 +51,7 @@
      *            the detail message for this exception.
      * @param cause
      *            the optional cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public SecurityException(String message, Throwable cause) {
         super(message, cause);
@@ -68,7 +63,7 @@
      * 
      * @param cause
      *            the optional cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public SecurityException(Throwable cause) {
         super((cause == null ? null : cause.toString()), cause);
diff --git a/luni/src/main/java/java/lang/SecurityManager.java b/luni/src/main/java/java/lang/SecurityManager.java
index dc624e3..9125850 100644
--- a/luni/src/main/java/java/lang/SecurityManager.java
+++ b/luni/src/main/java/java/lang/SecurityManager.java
@@ -49,8 +49,6 @@
  * operation is not allowed, then they throw a {@link SecurityException}. The
  * only exception is {@link #checkTopLevelWindow(Object)}, which returns a
  * boolean to indicate permission.
- * 
- * @since Android 1.0
  */
 public class SecurityManager {
 
@@ -63,9 +61,8 @@
 
     /**
      * Flag to indicate whether a security check is in progress.
-     * 
+     *
      * @deprecated Use {@link #checkPermission}
-     * @since Android 1.0
      */
     @Deprecated
     protected boolean inCheck;
@@ -75,9 +72,6 @@
      * <p>
      * The {@code RuntimePermission("createSecurityManager")} is checked if a
      * security manager is installed.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     public SecurityManager() {
         SecurityManager security = System.getSecurityManager();
@@ -94,7 +88,7 @@
     /**
      * Checks whether the calling thread is allowed to accept socket
      * connections.
-     * 
+     *
      * @param host
      *            the address of the host that attempts to connect.
      * @param port
@@ -104,7 +98,6 @@
      * @throws SecurityException
      *             if the calling thread is not allowed to accept socket
      *             connections from {@code host} through {@code port}.
-     * @since Android 1.0
      */
     public void checkAccept(String host, int port) {
         if (host == null) {
@@ -116,12 +109,11 @@
     /**
      * Checks whether the calling thread is allowed to modify the specified
      * thread.
-     * 
+     *
      * @param thread
      *            the thread to access.
      * @throws SecurityException
      *             if the calling thread is not allowed to access {@code thread}.
-     * @since Android 1.0
      */
     public void checkAccess(Thread thread) {
         // Only worry about system threads. Dead threads have a null group.
@@ -134,14 +126,13 @@
     /**
      * Checks whether the calling thread is allowed to modify the specified
      * thread group.
-     * 
+     *
      * @param group
      *            the thread group to access.
      * @throws NullPointerException
      *             if {@code group} is {@code null}.
      * @throws SecurityException
      *             if the calling thread is not allowed to access {@code group}.
-     * @since Android 1.0
      */
     public void checkAccess(ThreadGroup group) {
         // Only worry about system threads.
@@ -157,7 +148,7 @@
      * Checks whether the calling thread is allowed to establish socket
      * connections. A -1 port indicates the caller is trying to resolve the
      * hostname.
-     * 
+     *
      * @param host
      *            the address of the host to connect to.
      * @param port
@@ -167,7 +158,6 @@
      * @throws SecurityException
      *             if the calling thread is not allowed to connect to {@code
      *             host} through {@code port}.
-     * @since Android 1.0
      */
     public void checkConnect(String host, int port) {
         if (host == null) {
@@ -184,7 +174,7 @@
      * Checks whether the specified security context is allowed to establish
      * socket connections. A -1 port indicates the caller is trying to resolve
      * the hostname.
-     * 
+     *
      * @param host
      *            the address of the host to connect to.
      * @param port
@@ -196,7 +186,6 @@
      * @throws SecurityException
      *             if {@code context} is not allowed to connect to {@code host}
      *             through {@code port}.
-     * @since Android 1.0
      */
     public void checkConnect(String host, int port, Object context) {
         // BEGIN android-added
@@ -214,11 +203,10 @@
 
     /**
      * Checks whether the calling thread is allowed to create a class loader.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to create a class
      *             loader.
-     * @since Android 1.0
      */
     public void checkCreateClassLoader() {
         checkPermission(RuntimePermission.permissionToCreateClassLoader);
@@ -227,12 +215,11 @@
     /**
      * Checks whether the calling thread is allowed to delete the file with the
      * specified name, which should be passed in canonical form.
-     * 
+     *
      * @param file
      *            the name of the file to delete.
      * @throws SecurityException
      *             if the calling thread is not allowed to delete {@code file}.
-     * @since Android 1.0
      */
     public void checkDelete(String file) {
         checkPermission(new FilePermission(file, "delete")); //$NON-NLS-1$
@@ -241,12 +228,11 @@
     /**
      * Checks whether the calling thread is allowed to execute the specified
      * platform specific command.
-     * 
+     *
      * @param cmd
      *            the command line to execute.
      * @throws SecurityException
      *             if the calling thread is not allowed to execute {@code cmd}.
-     * @since Android 1.0
      */
     public void checkExec(String cmd) {
         checkPermission(new FilePermission(new File(cmd).isAbsolute() ? cmd
@@ -256,14 +242,13 @@
     /**
      * Checks whether the calling thread is allowed to terminate the virtual
      * machine.
-     * 
+     *
      * @param status
      *            the status that the virtual machine returns when it is
      *            terminated.
      * @throws SecurityException
      *             if the calling thread is not allowed to terminate the virtual
      *             machine with {@code status}.
-     * @since Android 1.0
      */
     public void checkExit(int status) {
         checkPermission(RuntimePermission.permissionToExitVM);
@@ -272,12 +257,11 @@
     /**
      * Checks whether the calling thread is allowed to load the specified native
      * library.
-     * 
+     *
      * @param libName
      *            the name of the library to load.
      * @throws SecurityException
      *             if the calling thread is not allowed to load {@code libName}.
-     * @since Android 1.0
      */
     public void checkLink(String libName) {
         if (libName == null) {
@@ -289,12 +273,11 @@
     /**
      * Checks whether the calling thread is allowed to listen on the specified
      * port.
-     * 
+     *
      * @param port
      *            the port number to check.
      * @throws SecurityException
      *             if the calling thread is not allowed listen on {@code port}.
-     * @since Android 1.0
      */
     public void checkListen(int port) {
         if (port == 0) {
@@ -312,7 +295,7 @@
      * reflect API). Due to the nature of the check, overriding implementations
      * cannot call {@code super.checkMemberAccess()} since the stack would no
      * longer be of the expected shape.
-     * 
+     *
      * @param cls
      *            the class of which members are accessed.
      * @param type
@@ -322,7 +305,6 @@
      * @throws SecurityException
      *             if the calling thread is not allowed to access members of
      *             {@code cls}.
-     * @since Android 1.0
      */
     public void checkMemberAccess(Class<?> cls, int type) {
         if (cls == null) {
@@ -352,12 +334,11 @@
     /**
      * Checks whether the calling thread is allowed to use the specified IP
      * multicast group address.
-     * 
+     *
      * @param maddr
      *            the internet group address to use.
      * @throws SecurityException
      *             if the calling thread is not allowed to use {@code maddr}.
-     * @since Android 1.0
      */
     public void checkMulticast(InetAddress maddr) {
         checkPermission(new SocketPermission(maddr.getHostAddress(),
@@ -367,7 +348,7 @@
     /**
      * Checks whether the calling thread is allowed to use the specified IP
      * multicast group address.
-     * 
+     *
      * @param maddr
      *            the internet group address to use.
      * @param ttl
@@ -376,7 +357,6 @@
      * @throws SecurityException
      *             if the calling thread is not allowed to use {@code maddr}.
      * @deprecated use {@link #checkMulticast(java.net.InetAddress)}
-     * @since Android 1.0
      */
     @Deprecated
     public void checkMulticast(InetAddress maddr, byte ttl) {
@@ -387,13 +367,12 @@
     /**
      * Checks whether the calling thread is allowed to access the specified
      * package.
-     * 
+     *
      * @param packageName
      *            the name of the package to access.
      * @throws SecurityException
      *             if the calling thread is not allowed to access {@code
      *             packageName}.
-     * @since Android 1.0
      */
     public void checkPackageAccess(String packageName) {
         if (packageName == null) {
@@ -408,13 +387,12 @@
     /**
      * Checks whether the calling thread is allowed to define new classes in the
      * specified package.
-     * 
+     *
      * @param packageName
      *            the name of the package to add a class to.
      * @throws SecurityException
      *             if the calling thread is not allowed to add classes to
      *             {@code packageName}.
-     * @since Android 1.0
      */
     public void checkPackageDefinition(String packageName) {
         if (packageName == null) {
@@ -459,11 +437,10 @@
     /**
      * Checks whether the calling thread is allowed to access the system
      * properties.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to access system
      *             properties.
-     * @since Android 1.0
      */
     public void checkPropertiesAccess() {
         checkPermission(READ_WRITE_ALL_PROPERTIES_PERMISSION);
@@ -472,13 +449,12 @@
     /**
      * Checks whether the calling thread is allowed to access a particular
      * system property.
-     * 
+     *
      * @param key
      *            the name of the property to access.
      * @throws SecurityException
      *             if the calling thread is not allowed to access the {@code
      *             key} system property.
-     * @since Android 1.0
      */
     public void checkPropertyAccess(String key) {
         checkPermission(new PropertyPermission(key, "read")); //$NON-NLS-1$
@@ -487,12 +463,11 @@
     /**
      * Checks whether the calling thread is allowed to read from the file with
      * the specified file descriptor.
-     * 
+     *
      * @param fd
      *            the file descriptor of the file to read from.
      * @throws SecurityException
      *             if the calling thread is not allowed to read from {@code fd}.
-     * @since Android 1.0
      */
     public void checkRead(FileDescriptor fd) {
         if (fd == null) {
@@ -504,13 +479,12 @@
     /**
      * Checks whether the calling thread is allowed to read from the file with
      * the specified name, which should be passed in canonical form.
-     * 
+     *
      * @param file
      *            the name of the file or directory to read from.
      * @throws SecurityException
      *             if the calling thread is not allowed to read from {@code
      *             file}.
-     * @since Android 1.0
      */
     public void checkRead(String file) {
         checkPermission(new FilePermission(file, "read")); //$NON-NLS-1$
@@ -519,14 +493,13 @@
     /**
      * Checks whether the given security context is allowed to read from the
      * file named by the argument, which should be passed in canonical form.
-     * 
+     *
      * @param file
      *            the name of the file or directory to check.
      * @param context
      *            the security context to use for the check.
      * @throws SecurityException
      *             if {@code context} is not allowed to read from {@code file}.
-     * @since Android 1.0
      */
     public void checkRead(String file, Object context) {
         checkPermission(new FilePermission(file, "read"), context); //$NON-NLS-1$
@@ -535,13 +508,12 @@
     /**
      * Checks whether the calling thread is allowed to perform the security
      * operation named by the target.
-     * 
+     *
      * @param target
      *            the name of the operation to perform.
      * @throws SecurityException
      *             if the calling thread is not allowed to perform
      *             {@code target}.
-     * @since Android 1.0
      */
     public void checkSecurityAccess(String target) {
         checkPermission(new SecurityPermission(target));
@@ -550,11 +522,10 @@
     /**
      * Checks whether the calling thread is allowed to set the net object
      * factories.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to set the net object
      *             factories.
-     * @since Android 1.0
      */
     public void checkSetFactory() {
         checkPermission(RuntimePermission.permissionToSetFactory);
@@ -563,14 +534,13 @@
     /**
      * Checks whether the calling thread is trusted to show the specified top
      * level window.
-     * 
+     *
      * @param window
      *            the window to show.
      * @return {@code true} if the calling thread is allowed to show {@code
      *         window}; {@code false} otherwise.
      * @throws NullPointerException
      *             if {@code window} is {@code null}.
-     * @since Android 1.0
      */
     public boolean checkTopLevelWindow(Object window) {
         if (window == null) {
@@ -597,11 +567,10 @@
     /**
      * Checks whether the calling thread is allowed to access the system
      * clipboard.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to access the system
      *             clipboard.
-     * @since Android 1.0
      */
     public void checkSystemClipboardAccess() {
         try {
@@ -623,11 +592,10 @@
     /**
      * Checks whether the calling thread is allowed to access the AWT event
      * queue.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to access the AWT event
      *             queue.
-     * @since Android 1.0
      */
     public void checkAwtEventQueueAccess() {
         try {
@@ -648,11 +616,10 @@
 
     /**
      * Checks whether the calling thread is allowed to start a new print job.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to start a new print
      *             job.
-     * @since Android 1.0
      */
     public void checkPrintJobAccess() {
         checkPermission(RuntimePermission.permissionToQueuePrintJob);
@@ -661,12 +628,11 @@
     /**
      * Checks whether the calling thread is allowed to write to the file with
      * the specified file descriptor.
-     * 
+     *
      * @param fd
      *            the file descriptor of the file to write to.
      * @throws SecurityException
      *             if the calling thread is not allowed to write to {@code fd}.
-     * @since Android 1.0
      */
     public void checkWrite(FileDescriptor fd) {
         if (fd == null) {
@@ -678,13 +644,12 @@
     /**
      * Checks whether the calling thread is allowed to write to the file with
      * the specified name, which should be passed in canonical form.
-     * 
+     *
      * @param file
      *            the name of the file or directory to write to.
      * @throws SecurityException
-     *             if the calling thread is not allowed to write to 
+     *             if the calling thread is not allowed to write to
      *             {@code file}.
-     * @since Android 1.0
      */
     public void checkWrite(String file) {
         checkPermission(new FilePermission(file, "write")); //$NON-NLS-1$
@@ -692,11 +657,10 @@
 
     /**
      * Indicates if this security manager is currently checking something.
-     * 
+     *
      * @return {@code true} if this security manager is executing a security
      *         check method; {@code false} otherwise.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     public boolean getInCheck() {
@@ -707,9 +671,8 @@
      * Returns an array containing one entry for each method in the current
      * execution stack. Each entry is the {@code java.lang.Class} which
      * represents the class in which the method is defined.
-     * 
+     *
      * @return all classes in the execution stack.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     protected Class[] getClassContext() {
@@ -719,10 +682,9 @@
     /**
      * Returns the class loader of the first class in the execution stack whose
      * class loader is not a system class loader.
-     * 
+     *
      * @return the most recent non-system class loader.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     protected ClassLoader currentClassLoader() {
@@ -755,11 +717,10 @@
     /**
      * Returns the index in the call stack of the first class whose class loader
      * is not a system class loader.
-     * 
+     *
      * @return the frame index of the first method whose class was loaded by a
      *         non-system class loader.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     protected int classLoaderDepth() {
@@ -791,10 +752,9 @@
     /**
      * Returns the first class in the call stack that was loaded by a class
      * loader which is not a system class loader.
-     * 
+     *
      * @return the most recent class loaded by a non-system class loader.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     protected Class<?> currentLoadedClass() {
@@ -827,13 +787,12 @@
      * Returns the index in the call stack of the first method which is
      * contained in the class with the specified name. Returns -1 if no methods
      * from this class are in the stack.
-     * 
+     *
      * @param name
      *            the name of the class to look for.
      * @return the frame index of the first method found is contained in the
      *         class identified by {@code name}.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     protected int classDepth(String name) {
@@ -849,13 +808,12 @@
     /**
      * Indicates whether there is a method in the call stack from the class with
      * the specified name.
-     * 
+     *
      * @param name
      *            the name of the class to look for.
      * @return {@code true} if a method from the class identified by {@code
      *         name} is executing; {@code false} otherwise.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     protected boolean inClass(String name) {
@@ -865,11 +823,10 @@
     /**
      * Indicates whether there is a method in the call stack from a class which
      * was defined by a non-system class loader.
-     * 
+     *
      * @return {@code true} if a method from a class that was defined by a
      *         non-system class loader is executing; {@code false} otherwise.
      * @deprecated Use {@link #checkPermission}
-     * @since Android 1.0
      */
     @Deprecated
     protected boolean inClassLoader() {
@@ -880,9 +837,8 @@
      * Returns the thread group which should be used to instantiate new threads.
      * By default, this is the same as the thread group of the thread running
      * this method.
-     * 
+     *
      * @return ThreadGroup the thread group to create new threads in.
-     * @since Android 1.0
      */
     public ThreadGroup getThreadGroup() {
         return Thread.currentThread().getThreadGroup();
@@ -890,12 +846,11 @@
 
     /**
      * Returns an object which encapsulates the security state of the current
-     * point in the execution. In the Android reference implementation, this is
-     * an {@link java.security.AccessControlContext}.
-     * 
+     * point in the execution. In our case, this is an {@link
+     * java.security.AccessControlContext}.
+     *
      * @return an object that encapsulates information about the current
      *         execution environment.
-     * @since Android 1.0
      */
     public Object getSecurityContext() {
         return AccessController.getContext();
@@ -904,13 +859,12 @@
     /**
      * Checks whether the calling thread is allowed to access the resource being
      * guarded by the specified permission object.
-     * 
+     *
      * @param permission
      *            the permission to check.
      * @throws SecurityException
      *             if the requested {@code permission} is denied according to
      *             the current security policy.
-     * @since Android 1.0
      */
     public void checkPermission(Permission permission) {
         try {
@@ -924,7 +878,7 @@
     /**
      * Checks whether the specified security context is allowed to access the
      * resource being guarded by the specified permission object.
-     * 
+     *
      * @param permission
      *            the permission to check.
      * @param context
@@ -934,7 +888,6 @@
      *             AccessControlContext} or if the requested {@code permission}
      *             is denied for {@code context} according to the current
      *             security policy.
-     * @since Android 1.0
      */
     public void checkPermission(Permission permission, Object context) {
         try {
diff --git a/luni/src/main/java/java/lang/Short.java b/luni/src/main/java/java/lang/Short.java
index cf95d22..9baf3a8 100644
--- a/luni/src/main/java/java/lang/Short.java
+++ b/luni/src/main/java/java/lang/Short.java
@@ -21,11 +21,11 @@
  * The wrapper for the primitive type {@code short}.
  * 
  * @see java.lang.Number
- * @since Android 1.0
+ * @since 1.1
  */
 public final class Short extends Number implements Comparable<Short> {
 
-    private static final long serialVersionUID = 7515723908773894738L;
+	private static final long serialVersionUID = 7515723908773894738L;
 
     /**
      * The value which the receiver represents.
@@ -34,69 +34,61 @@
 
     /**
      * Constant for the maximum {@code short} value, 2<sup>15</sup>-1.
-     * 
-     * @since Android 1.0
      */
     public static final short MAX_VALUE = (short) 0x7FFF;
 
     /**
      * Constant for the minimum {@code short} value, -2<sup>15</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final short MIN_VALUE = (short) 0x8000;
 
     /**
      * Constant for the number of bits needed to represent a {@code short} in
      * two's complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 16;
 
     /**
-     * The {@link Class} object that represents the primitive type {@code 
+     * The {@link Class} object that represents the primitive type {@code
      * short}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Short> TYPE = (Class<Short>) new short[0]
             .getClass().getComponentType();
 
-    // Note: This can't be set to "short.class", since *that* is
-    // defined to be "java.lang.Short.TYPE";
+	// Note: This can't be set to "short.class", since *that* is
+	// defined to be "java.lang.Short.TYPE";
 
     
     /**
      * Constructs a new {@code Short} from the specified string.
-     * 
+     *
      * @param string
      *            the string representation of a short value.
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into a short value.
      * @see #parseShort(String)
-     * @since Android 1.0
      */
-    public Short(String string) throws NumberFormatException {
-        this(parseShort(string));
-    }
+	public Short(String string) throws NumberFormatException {
+		this(parseShort(string));
+	}
 
     /**
      * Constructs a new {@code Short} with the specified primitive short value.
-     * 
+     *
      * @param value
      *            the primitive short value to store in the new instance.
-     * @since Android 1.0
      */
-    public Short(short value) {
-        this.value = value;
-    }
+	public Short(short value) {
+		this.value = value;
+	}
 
-    @Override
+	@Override
     public byte byteValue() {
-        return (byte) value;
-    }
+		return (byte) value;
+	}
 
     /**
      * Compares this object to the specified short object to determine their
@@ -108,98 +100,97 @@
      *         value of {@code object}; 0 if the value of this short and the
      *         value of {@code object} are equal; a positive value if the value
      *         of this short is greater than the value of {@code object}.
+     * @throws NullPointerException
+     *             if {@code object} is null.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
-    public int compareTo(Short object) {
-        return value > object.value ? 1 : (value < object.value ? -1 : 0);
-    }
+	public int compareTo(Short object) {
+		return value > object.value ? 1 : (value < object.value ? -1 : 0);
+	}
 
     /**
      * Parses the specified string and returns a {@code Short} instance if the
      * string can be decoded into a short value. The string may be an optional
      * minus sign "-" followed by a hexadecimal ("0x..." or "#..."), octal
      * ("0..."), or decimal ("...") representation of a short.
-     * 
+     *
      * @param string
      *            a string representation of a short value.
      * @return a {@code Short} containing the value represented by
      *         {@code string}.
      * @throws NumberFormatException
      *             if {@code string} can not be parsed as a short value.
-     * @since Android 1.0
      */
-    public static Short decode(String string) throws NumberFormatException {
-        int intValue = Integer.decode(string).intValue();
-        short result = (short) intValue;
-        if (result == intValue) {
+	public static Short decode(String string) throws NumberFormatException {
+		int intValue = Integer.decode(string).intValue();
+		short result = (short) intValue;
+		if (result == intValue) {
             return valueOf(result);
         }
-        throw new NumberFormatException();
-    }
+		throw new NumberFormatException();
+	}
 
-    @Override
+	@Override
     public double doubleValue() {
-        return value;
-    }
+		return value;
+	}
 
     /**
      * Compares this instance with the specified object and indicates if they
      * are equal. In order to be equal, {@code object} must be an instance of
      * {@code Short} and have the same short value as this object.
-     * 
+     *
      * @param object
      *            the object to compare this short with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Short}; {@code false} otherwise.
-     * @since Android 1.0
      */
-    @Override
+	@Override
     public boolean equals(Object object) {
-        return (object instanceof Short)
-                && (value == ((Short) object).value);
-    }
+		return (object instanceof Short)
+				&& (value == ((Short) object).value);
+	}
 
-    @Override
+	@Override
     public float floatValue() {
-        return value;
-    }
+		return value;
+	}
 
-    @Override
+	@Override
     public int hashCode() {
-        return value;
-    }
+		return value;
+	}
 
-    @Override
+	@Override
     public int intValue() {
-        return value;
-    }
+		return value;
+	}
 
-    @Override
+	@Override
     public long longValue() {
-        return value;
-    }
+		return value;
+	}
 
     /**
      * Parses the specified string as a signed decimal short value. The ASCII
      * character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of a short value.
      * @return the primitive short value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a short value.
-     * @since Android 1.0
      */
-    public static short parseShort(String string) throws NumberFormatException {
-        return parseShort(string, 10);
-    }
+	public static short parseShort(String string) throws NumberFormatException {
+		return parseShort(string, 10);
+	}
 
     /**
      * Parses the specified string as a signed short value using the specified
      * radix. The ASCII character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of a short value.
      * @param radix
@@ -211,50 +202,47 @@
      *             {@code radix < Character.MIN_RADIX},
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a short value.
-     * @since Android 1.0
      */
-    public static short parseShort(String string, int radix)
-            throws NumberFormatException {
-        int intValue = Integer.parseInt(string, radix);
-        short result = (short) intValue;
-        if (result == intValue) {
+	public static short parseShort(String string, int radix)
+			throws NumberFormatException {
+		int intValue = Integer.parseInt(string, radix);
+		short result = (short) intValue;
+		if (result == intValue) {
             return result;
         }
-        throw new NumberFormatException();
-    }
+		throw new NumberFormatException();
+	}
 
     /**
      * Gets the primitive value of this short.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public short shortValue() {
-        return value;
-    }
+		return value;
+	}
 
-    @Override
+	@Override
     public String toString() {
-        return Integer.toString(value);
-    }
+		return Integer.toString(value);
+	}
 
     /**
      * Returns a string containing a concise, human-readable description of the
      * specified short value with radix 10.
-     * 
+     *
      * @param value
      *             the short to convert to a string.
      * @return a printable representation of {@code value}.
-     * @since Android 1.0
      */
-    public static String toString(short value) {
-        return Integer.toString(value);
-    }
+	public static String toString(short value) {
+		return Integer.toString(value);
+	}
 
     /**
      * Parses the specified string as a signed decimal short value.
-     * 
+     *
      * @param string
      *            the string representation of a short value.
      * @return a {@code Short} instance containing the short value represented
@@ -263,16 +251,15 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a short value.
      * @see #parseShort(String)
-     * @since Android 1.0
      */
-    public static Short valueOf(String string) throws NumberFormatException {
-        return valueOf(parseShort(string));
-    }
+	public static Short valueOf(String string) throws NumberFormatException {
+		return valueOf(parseShort(string));
+	}
 
     /**
      * Parses the specified string as a signed short value using the specified
      * radix.
-     * 
+     *
      * @param string
      *            the string representation of a short value.
      * @param radix
@@ -285,12 +272,11 @@
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a short value.
      * @see #parseShort(String, int)
-     * @since Android 1.0
      */
-    public static Short valueOf(String string, int radix)
-            throws NumberFormatException {
-        return valueOf(parseShort(string, radix));
-    }
+	public static Short valueOf(String string, int radix)
+			throws NumberFormatException {
+		return valueOf(parseShort(string, radix));
+	}
     
     /**
      * Reverses the bytes of the specified short.
@@ -298,7 +284,7 @@
      * @param s
      *            the short value for which to reverse bytes.
      * @return the reversed value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static short reverseBytes(short s) {
         int high = (s >> 8) & 0xFF;
@@ -312,12 +298,11 @@
      * If it is not necessary to get a new {@code Short} instance, it is
      * recommended to use this method instead of the constructor, since it
      * maintains a cache of instances which may result in better performance.
-     * </p>
-     * 
+     *
      * @param s
      *            the short value to store in the instance.
      * @return a {@code Short} instance containing {@code s}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Short valueOf(short s) {
         if (s < -128 || s > 127) {
@@ -328,9 +313,7 @@
 
     static class valueOfCache {
         /**
-         * <p>
          * A cache of instances used by {@link Short#valueOf(short)} and auto-boxing.
-         * </p>
          */
         private static final Short[] CACHE = new Short[256];
 
diff --git a/luni/src/main/java/java/lang/StackOverflowError.java b/luni/src/main/java/java/lang/StackOverflowError.java
index dd63b6b..3cbc0c7 100644
--- a/luni/src/main/java/java/lang/StackOverflowError.java
+++ b/luni/src/main/java/java/lang/StackOverflowError.java
@@ -22,8 +22,6 @@
  * platform or virtual machine specific limit. Typically, this will occur only
  * when a program becomes infinitely recursive, but it can also occur in
  * correctly written (but deeply recursive) programs.
- * 
- * @since Android 1.0
  */
 public class StackOverflowError extends java.lang.VirtualMachineError {
 
@@ -32,8 +30,6 @@
     /**
      * Constructs a new {@code StackOverflowError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public StackOverflowError() {
         super();
@@ -45,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public StackOverflowError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/StrictMath.java b/luni/src/main/java/java/lang/StrictMath.java
index 66e4771..7a2da8e 100644
--- a/luni/src/main/java/java/lang/StrictMath.java
+++ b/luni/src/main/java/java/lang/StrictMath.java
@@ -37,25 +37,19 @@
  * Library" (fdlibm), version 5.3.
  * <p>
  * <a href="http://www.netlib.org/fdlibm/">http://www.netlib.org/fdlibm/</a>
- * 
- * @since Android 1.0
  */
 public final class StrictMath {
 
-    /**
+	/**
      * The double value closest to e, the base of the natural logarithm.
-     * 
-     * @since Android 1.0
-     */
-    public final static double E = Math.E;
+	 */
+	public final static double E = Math.E;
 
-    /**
+	/**
      * The double value closest to pi, the ratio of a circle's circumference to
      * its diameter.
-     * 
-     * @since Android 1.0
-     */
-    public final static double PI = Math.PI;
+	 */
+	public final static double PI = Math.PI;
 
     private static java.util.Random random;
 
@@ -65,7 +59,7 @@
     private StrictMath() {
     }
 
-    /**
+	/**
      * Returns the absolute value of the argument.
      * <p>
      * Special cases:
@@ -75,18 +69,16 @@
      * <li>{@code abs(-infinity) = +infinity}</li>
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose absolute value has to be computed.
      * @return the absolute value of the argument.
-     * @since Android 1.0
      */
-    public static double abs(double d) {
-        long bits = Double.doubleToLongBits(d);
-        bits &= 0x7fffffffffffffffL;
-        return Double.longBitsToDouble(bits);
-    }
+	public static double abs(double d) {
+		long bits = Double.doubleToLongBits(d);
+		bits &= 0x7fffffffffffffffL;
+		return Double.longBitsToDouble(bits);
+	}
 
     /**
      * Returns the absolute value of the argument.
@@ -98,52 +90,47 @@
      * <li>{@code abs(-infinity) = +infinity}</li>
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
-    public static float abs(float f) {
-        int bits = Float.floatToIntBits(f);
-        bits &= 0x7fffffff;
-        return Float.intBitsToFloat(bits);
-    }
+	public static float abs(float f) {
+		int bits = Float.floatToIntBits(f);
+		bits &= 0x7fffffff;
+		return Float.intBitsToFloat(bits);
+	}
 
     /**
      * Returns the absolute value of the argument.
      * <p>
      * If the argument is {@code Integer.MIN_VALUE}, {@code Integer.MIN_VALUE}
      * is returned.
-     * 
+     *
      * @param i
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
-    public static int abs(int i) {
-        return i >= 0 ? i : -i;
-    }
+	public static int abs(int i) {
+		return i >= 0 ? i : -i;
+	}
 
     /**
      * Returns the absolute value of the argument.
      * <p>
      * If the argument is {@code Long.MIN_VALUE}, {@code Long.MIN_VALUE} is
      * returned.
-     * </p>
-     * 
+     *
      * @param l
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
-    public static long abs(long l) {
-        return l >= 0 ? l : -l;
-    }
+	public static long abs(long l) {
+		return l >= 0 ? l : -l;
+	}
 
     /**
      * Returns the closest double approximation of the arc cosine of the
@@ -155,14 +142,12 @@
      * <li>{@code acos((anything < -1) = NaN}</li>
      * <li>{@code acos(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to compute arc cosine of.
      * @return the arc cosine of the argument.
-     * @since Android 1.0
      */
-    public static native double acos(double d);
+	public static native double acos(double d);
 
     /**
      * Returns the closest double approximation of the arc sine of the argument
@@ -174,14 +159,12 @@
      * <li>{@code asin((anything < -1)) = NaN}</li>
      * <li>{@code asin(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose arc sine has to be computed.
      * @return the arc sine of the argument.
-     * @since Android 1.0
      */
-    public static native double asin(double d);
+	public static native double asin(double d);
 
     /**
      * Returns the closest double approximation of the arc tangent of the
@@ -195,14 +178,12 @@
      * <li>{@code atan(-infinity) = -pi/2}</li>
      * <li>{@code atan(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose arc tangent has to be computed.
      * @return the arc tangent of the argument.
-     * @since Android 1.0
      */
-    public static native double atan(double d);
+	public static native double atan(double d);
 
     /**
      * Returns the closest double approximation of the arc tangent of
@@ -234,20 +215,15 @@
      * <li>{@code atan2(-infinity, (anything but,0, NaN, and infinity))}
      * {@code =} {@code -pi/2}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param y
      *            the numerator of the value whose atan has to be computed.
      * @param x
      *            the denominator of the value whose atan has to be computed.
      * @return the arc tangent of {@code y/x}.
-     * @since Android 1.0
      */
-    public static native double atan2(double y, double x);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
-    
+	public static native double atan2(double y, double x);
+
     /**
      * Returns the closest double approximation of the cube root of the
      * argument.
@@ -260,12 +236,10 @@
      * <li>{@code cbrt(-infinity) = -infinity}</li>
      * <li>{@code cbrt(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose cube root has to be computed.
      * @return the cube root of the argument.
-     * @since Android 1.0
      */
     public static native double cbrt(double d);
 
@@ -282,15 +256,14 @@
      * <li>{@code ceil(-infinity) = -infinity}</li>
      * <li>{@code ceil(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose closest integer value has to be computed.
      * @return the ceiling of the argument.
-     * @since Android 1.0
      */
-    public static native double ceil(double d);
-    
+	public static native double ceil(double d);
+
+
     /**
      * Returns the closest double approximation of the hyperbolic cosine of the
      * argument.
@@ -301,12 +274,10 @@
      * <li>{@code cosh(-infinity) = +infinity}</li>
      * <li>{@code cosh(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose hyperbolic cosine has to be computed.
      * @return the hyperbolic cosine of the argument.
-     * @since Android 1.0
      */
     public static native double cosh(double d);
 
@@ -319,12 +290,10 @@
      * <li>{@code cos(-infinity) = NaN}</li>
      * <li>{@code cos(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the angle whose cosine has to be computed, in radians.
      * @return the cosine of the argument.
-     * @since Android 1.0
      */
     public static native double cos(double d);
 
@@ -338,15 +307,13 @@
      * <li>{@code exp(-infinity) = +0.0}</li>
      * <li>{@code exp(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose exponential has to be computed.
      * @return the exponential of the argument.
-     * @since Android 1.0
      */
     public static native double exp(double d);
-    
+
     /**
      * Returns the closest double approximation of <i>{@code e}</i><sup>
      * {@code d}</sup>{@code - 1}. If the argument is very close to 0, it is
@@ -361,14 +328,12 @@
      * <li>{@code expm1(-infinity) = -1.0}</li>
      * <li>{@code expm1(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to compute the <i>{@code e}</i><sup>{@code d}</sup>
      *            {@code - 1} of.
      * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value
      *         of the argument.
-     * @since Android 1.0
      */
     public static native double expm1(double d);
 
@@ -384,14 +349,12 @@
      * <li>{@code floor(-infinity) = -infinity}</li>
      * <li>{@code floor(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d the value whose closest integer value has to be computed.
      * @return the floor of the argument.
-     * @since Android 1.0
      */
     public static native double floor(double d);
-    
+
     /**
      * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +}
      * <i> {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is
@@ -405,8 +368,7 @@
      * <li>{@code hypot((anything including NaN), -infinity) = +infinity}</li>
      * <li>{@code hypot(NaN, NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param x
      *            a double number.
      * @param y
@@ -414,7 +376,6 @@
      * @return the {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +}
      *         <i> {@code y}</i><sup>{@code 2}</sup>{@code )} value of the
      *         arguments.
-     * @since Android 1.0
      */
     public static native double hypot(double x, double y);
 
@@ -436,19 +397,14 @@
      * <li>{@code IEEEremainder(x, -infinity) = x } where x is anything but
      * +/-infinity</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param x
      *            the numerator of the operation.
      * @param y
      *            the denominator of the operation.
      * @return the IEEE754 floating point reminder of of {@code x/y}.
-     * @since Android 1.0
      */
-    public static native double IEEEremainder(double x, double y);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
+	public static native double IEEEremainder(double x, double y);
 
     /**
      * Returns the closest double approximation of the natural logarithm of the
@@ -463,15 +419,13 @@
      * <li>{@code log(-infinity) = NaN}</li>
      * <li>{@code log(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose log has to be computed.
      * @return the natural logarithm of the argument.
-     * @since Android 1.0
      */
     public static native double log(double d);
-    
+
     /**
      * Returns the closest double approximation of the base 10 logarithm of the
      * argument.
@@ -485,15 +439,13 @@
      * <li>{@code log10(-infinity) = NaN}</li>
      * <li>{@code log10(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose base 10 log has to be computed.
      * @return the natural logarithm of the argument.
-     * @since Android 1.0
      */
     public static native double log10(double d);
-    
+
     /**
      * Returns the closest double approximation of the natural logarithm of the
      * sum of the argument and 1. If the argument is very close to 0, it is much
@@ -510,12 +462,10 @@
      * <li>{@code log1p(-infinity) = NaN}</li>
      * <li>{@code log1p(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to compute the {@code ln(1+d)} of.
      * @return the natural logarithm of the sum of the argument and 1.
-     * @since Android 1.0
      */
     public static native double log1p(double d);
 
@@ -530,29 +480,27 @@
      * <li>{@code max(+0.0, -0.0) = +0.0}</li>
      * <li>{@code max(-0.0, +0.0) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d1
      *            the first argument.
      * @param d2
      *            the second argument.
      * @return the larger of {@code d1} and {@code d2}.
-     * @since Android 1.0
      */
-    public static double max(double d1, double d2) {
-        if (d1 > d2)
-            return d1;
-        if (d1 < d2)
-            return d2;
-        /* if either arg is NaN, return NaN */
-        if (d1 != d2)
-            return Double.NaN;
-        /* max( +0.0,-0.0) == +0.0 */
-        if (d1 == 0.0
-                && ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0)
-            return 0.0;
-        return d1;
-    }
+	public static double max(double d1, double d2) {
+		if (d1 > d2)
+			return d1;
+		if (d1 < d2)
+			return d2;
+		/* if either arg is NaN, return NaN */
+		if (d1 != d2)
+			return Double.NaN;
+		/* max( +0.0,-0.0) == +0.0 */
+		if (d1 == 0.0
+				&& ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0)
+			return 0.0;
+		return d1;
+	}
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
@@ -565,59 +513,55 @@
      * <li>{@code max(+0.0, -0.0) = +0.0}</li>
      * <li>{@code max(-0.0, +0.0) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f1
      *            the first argument.
      * @param f2
      *            the second argument.
      * @return the larger of {@code f1} and {@code f2}.
-     * @since Android 1.0
      */
-    public static float max(float f1, float f2) {
-        if (f1 > f2)
-            return f1;
-        if (f1 < f2)
-            return f2;
-        /* if either arg is NaN, return NaN */
-        if (f1 != f2)
-            return Float.NaN;
-        /* max( +0.0,-0.0) == +0.0 */
-        if (f1 == 0.0f
-                && ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0)
-            return 0.0f;
-        return f1;
-    }
+	public static float max(float f1, float f2) {
+		if (f1 > f2)
+			return f1;
+		if (f1 < f2)
+			return f2;
+		/* if either arg is NaN, return NaN */
+		if (f1 != f2)
+			return Float.NaN;
+		/* max( +0.0,-0.0) == +0.0 */
+		if (f1 == 0.0f
+				&& ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0)
+			return 0.0f;
+		return f1;
+	}
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
      * arguments.
-     * 
+     *
      * @param i1
      *            the first argument.
      * @param i2
      *            the second argument.
      * @return the larger of {@code i1} and {@code i2}.
-     * @since Android 1.0
      */
-    public static int max(int i1, int i2) {
-        return i1 > i2 ? i1 : i2;
-    }
+	public static int max(int i1, int i2) {
+		return i1 > i2 ? i1 : i2;
+	}
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
      * arguments.
-     * 
+     *
      * @param l1
      *            the first argument.
      * @param l2
      *            the second argument.
      * @return the larger of {@code l1} and {@code l2}.
-     * @since Android 1.0
      */
-    public static long max(long l1, long l2) {
-        return l1 > l2 ? l1 : l2;
-    }
+	public static long max(long l1, long l2) {
+		return l1 > l2 ? l1 : l2;
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
@@ -630,29 +574,27 @@
      * <li>{@code min(+0.0, -0.0) = -0.0}</li>
      * <li>{@code min(-0.0, +0.0) = -0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d1
      *            the first argument.
      * @param d2
      *            the second argument.
      * @return the smaller of {@code d1} and {@code d2}.
-     * @since Android 1.0
      */
-    public static double min(double d1, double d2) {
-        if (d1 > d2)
-            return d2;
-        if (d1 < d2)
-            return d1;
-        /* if either arg is NaN, return NaN */
-        if (d1 != d2)
-            return Double.NaN;
-        /* min( +0.0,-0.0) == -0.0 */
-        if (d1 == 0.0
-                && ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0)
-            return 0.0 * (-1.0);
-        return d1;
-    }
+	public static double min(double d1, double d2) {
+		if (d1 > d2)
+			return d2;
+		if (d1 < d2)
+			return d1;
+		/* if either arg is NaN, return NaN */
+		if (d1 != d2)
+			return Double.NaN;
+		/* min( +0.0,-0.0) == -0.0 */
+		if (d1 == 0.0
+				&& ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0)
+			return 0.0 * (-1.0);
+		return d1;
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
@@ -665,59 +607,55 @@
      * <li>{@code min(+0.0, -0.0) = -0.0}</li>
      * <li>{@code min(-0.0, +0.0) = -0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f1
      *            the first argument.
      * @param f2
      *            the second argument.
      * @return the smaller of {@code f1} and {@code f2}.
-     * @since Android 1.0
      */
-    public static float min(float f1, float f2) {
-        if (f1 > f2)
-            return f2;
-        if (f1 < f2)
-            return f1;
-        /* if either arg is NaN, return NaN */
-        if (f1 != f2)
-            return Float.NaN;
-        /* min( +0.0,-0.0) == -0.0 */
-        if (f1 == 0.0f
-                && ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0)
-            return 0.0f * (-1.0f);
-        return f1;
-    }
+	public static float min(float f1, float f2) {
+		if (f1 > f2)
+			return f2;
+		if (f1 < f2)
+			return f1;
+		/* if either arg is NaN, return NaN */
+		if (f1 != f2)
+			return Float.NaN;
+		/* min( +0.0,-0.0) == -0.0 */
+		if (f1 == 0.0f
+				&& ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0)
+			return 0.0f * (-1.0f);
+		return f1;
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
      * arguments.
-     * 
+     *
      * @param i1
      *            the first argument.
      * @param i2
      *            the second argument.
      * @return the smaller of {@code i1} and {@code i2}.
-     * @since Android 1.0
      */
-    public static int min(int i1, int i2) {
-        return i1 < i2 ? i1 : i2;
-    }
+	public static int min(int i1, int i2) {
+		return i1 < i2 ? i1 : i2;
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
      * arguments.
-     * 
+     *
      * @param l1
      *            the first argument.
      * @param l2
      *            the second argument.
      * @return the smaller of {@code l1} and {@code l2}.
-     * @since Android 1.0
      */
-    public static long min(long l1, long l2) {
-        return l1 < l2 ? l1 : l2;
-    }
+	public static long min(long l1, long l2) {
+		return l1 < l2 ? l1 : l2;
+	}
 
     /**
      * Returns the closest double approximation of the result of raising
@@ -750,26 +688,20 @@
      * <li>{@code pow((-anything except 0 and infinity), (non-integer))}
      * {@code =} {@code NAN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param x
      *            the base of the operation.
      * @param y
      *            the exponent of the operation.
      * @return {@code x} to the power of {@code y}.
-     * @since Android 1.0
      */
-    public static native double pow(double x, double y);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
+	public static native double pow(double x, double y);
 
     /**
      * Returns a pseudo-random number between 0.0 (inclusive) and 1.0
      * (exclusive).
-     * 
+     *
      * @return a pseudo-random number.
-     * @since Android 1.0
      */
     public static double random() {
         // BEGIN android-changed
@@ -777,8 +709,8 @@
             random = new java.util.Random();
         }
         // END android-changed
-        return random.nextDouble();
-    }
+		return random.nextDouble();
+	}
 
     /**
      * Returns the double conversion of the result of rounding the argument to
@@ -792,12 +724,10 @@
      * <li>{@code rint(-infinity) = -infinity}</li>
      * <li>{@code rint(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to be rounded.
      * @return the closest integer to the argument (as a double).
-     * @since Android 1.0
      */
     public static native double rint(double d);
 
@@ -815,19 +745,17 @@
      * <li>{@code round(-infinity) = Long.MIN_VALUE}</li>
      * <li>{@code round(NaN) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to be rounded.
      * @return the closest integer to the argument.
-     * @since Android 1.0
      */
-    public static long round(double d) {
-        // check for NaN
-        if (d != d)
-            return 0L;
-        return (long) Math.floor(d + 0.5d);
-    }
+	public static long round(double d) {
+		// check for NaN
+		if (d != d)
+			return 0L;
+		return (long) Math.floor(d + 0.5d);
+	}
 
     /**
      * Returns the result of rounding the argument to an integer. The result is
@@ -843,19 +771,17 @@
      * <li>{@code round(-infinity) = Integer.MIN_VALUE}</li>
      * <li>{@code round(NaN) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the value to be rounded.
      * @return the closest integer to the argument.
-     * @since Android 1.0
      */
-    public static int round(float f) {
-        // check for NaN
-        if (f != f)
-            return 0;
-        return (int) Math.floor(f + 0.5f);
-    }
+	public static int round(float f) {
+		// check for NaN
+		if (f != f)
+			return 0;
+		return (int) Math.floor(f + 0.5f);
+	}
 
     /**
      * Returns the signum function of the argument. If the argument is less than
@@ -871,12 +797,10 @@
      * <li>{@code signum(-infinity) = -1.0}</li>
      * <li>{@code signum(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
-     * @since Android 1.0
      */
     public static double signum(double d){
         if(Double.isNaN(d)){
@@ -905,12 +829,10 @@
      * <li>{@code signum(-infinity) = -1.0}</li>
      * <li>{@code signum(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
-     * @since Android 1.0
      */
     public static float signum(float f){
         if(Float.isNaN(f)){
@@ -937,15 +859,13 @@
      * <li>{@code sinh(-infinity) = -infinity}</li>
      * <li>{@code sinh(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose hyperbolic sine has to be computed.
      * @return the hyperbolic sine of the argument.
-     * @since Android 1.0
      */
     public static native double sinh(double d);
-    
+
     /**
      * Returns the closest double approximation of the sine of the argument.
      * <p>
@@ -957,12 +877,10 @@
      * <li>{@code sin(-infinity) = NaN}</li>
      * <li>{@code sin(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the angle whose sin has to be computed, in radians.
      * @return the sine of the argument.
-     * @since Android 1.0
      */
     public static native double sin(double d);
 
@@ -978,12 +896,10 @@
      * <li>{@code sqrt(+infinity) = +infinity}</li>
      * <li>{@code sqrt(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose square root has to be computed.
      * @return the square root of the argument.
-     * @since Android 1.0
      */
     public static native double sqrt(double d);
 
@@ -998,12 +914,10 @@
      * <li>{@code tan(-infinity) = NaN}</li>
      * <li>{@code tan(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the angle whose tangens has to be computed, in radians.
      * @return the tangent of the argument.
-     * @since Android 1.0
      */
     public static native double tan(double d);
 
@@ -1019,15 +933,13 @@
      * <li>{@code tanh(-infinity) = -1.0}</li>
      * <li>{@code tanh(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose hyperbolic tangent has to be computed.
      * @return the hyperbolic tangent of the argument
-     * @since Android 1.0
      */
     public static native double tanh(double d);
-    
+
     /**
      * Returns the measure in degrees of the supplied radian angle. The result
      * is {@code angrad * 180 / pi}.
@@ -1040,16 +952,14 @@
      * <li>{@code toDegrees(-infinity) = -infinity}</li>
      * <li>{@code toDegrees(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param angrad
      *            an angle in radians.
      * @return the degree measure of the angle.
-     * @since Android 1.0
      */
-    public static double toDegrees(double angrad) {
-        return angrad * 180d / PI;
-    }
+	public static double toDegrees(double angrad) {
+		return angrad * 180d / PI;
+	}
 
     /**
      * Returns the measure in radians of the supplied degree angle. The result
@@ -1063,18 +973,16 @@
      * <li>{@code toRadians(-infinity) = -infinity}</li>
      * <li>{@code toRadians(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param angdeg
      *            an angle in degrees.
      * @return the radian measure of the angle.
-     * @since Android 1.0
      */
-    public static double toRadians(double angdeg) {
-        return angdeg / 180d * PI;
-    }
-    
-    /**
+	public static double toRadians(double angdeg) {
+		return angdeg / 180d * PI;
+	}
+
+	/**
      * Returns the argument's ulp (unit in the last place). The size of a ulp of
      * a double value is the positive distance between this value and the double
      * value next larger in magnitude. For non-NaN {@code x},
@@ -1088,12 +996,10 @@
      * <li>{@code ulp(-infintiy) = infinity}</li>
      * <li>{@code ulp(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the floating-point value to compute ulp of.
      * @return the size of a ulp of the argument.
-     * @since Android 1.0
      */
     public static double ulp(double d) {
         // special cases
@@ -1120,12 +1026,10 @@
      * <li>{@code ulp(-infintiy) = infinity}</li>
      * <li>{@code ulp(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the floating-point value to compute ulp of.
      * @return the size of a ulp of the argument.
-     * @since Android 1.0
      */
     public static float ulp(float f) {
         // special cases
diff --git a/luni/src/main/java/java/lang/String.java b/luni/src/main/java/java/lang/String.java
index b257a36..22f72cb 100644
--- a/luni/src/main/java/java/lang/String.java
+++ b/luni/src/main/java/java/lang/String.java
@@ -21,9 +21,6 @@
 import java.io.UnsupportedEncodingException;
 import java.util.Comparator;
 import java.util.Formatter;
-// BEGIN android-added
-import java.util.IllegalFormatException;
-// END android-added
 import java.util.Locale;
 
 import java.util.regex.Pattern;
@@ -50,7 +47,7 @@
  * @see StringBuffer
  * @see StringBuilder
  * @see Charset
- * @since Android 1.0
+ * @since 1.0
  */
 public final class String implements Serializable, Comparable<String>,
         CharSequence {
@@ -80,7 +77,7 @@
         /**
          * Create a ConsolePrintStream on the specified OutputStream, usually
          * System.out.
-         * 
+         *
          * @param out
          *            the console OutputStream
          */
@@ -138,8 +135,6 @@
 
     /**
      * A comparator ignoring the case of the characters.
-     * 
-     * @since Android 1.0
      */
     public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
 
@@ -166,8 +161,6 @@
 
     /**
      * Creates an empty string.
-     * 
-     * @since Android 1.0
      */
     public String() {
         value = new char[0];
@@ -189,10 +182,9 @@
      * specified by the file.encoding system property. If the system property is
      * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1
      * is not available, an ASCII encoding is used.
-     * 
+     *
      * @param data
      *            the byte array to convert to a string.
-     * @since Android 1.0
      */
     public String(byte[] data) {
         this(data, 0, data.length);
@@ -201,14 +193,15 @@
     /**
      * Converts the byte array to a string, setting the high byte of every
      * character to the specified value.
-     * 
+     *
      * @param data
      *            the byte array to convert to a string.
      * @param high
      *            the high byte to use.
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @deprecated Use {@link #String(byte[])} or
      *             {@link #String(byte[], String)} instead.
-     * @since Android 1.0
      */
     @Deprecated
     public String(byte[] data, int high) {
@@ -220,17 +213,18 @@
      * specified by the file.encoding system property. If the system property is
      * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1
      * is not available, an ASCII encoding is used.
-     * 
+     *
      * @param data
      *            the byte array to convert to a string.
      * @param start
      *            the starting offset in the byte array.
      * @param length
      *            the number of bytes to convert.
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0, start < 0} or {@code start + length >
      *             data.length}.
-     * @since Android 1.0
      */
     public String(byte[] data, int start, int length) {
         // start + length could overflow, start/length maybe MaxInt
@@ -264,13 +258,13 @@
      *            the starting offset in the byte array.
      * @param length
      *            the number of bytes to convert.
-     *
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0, start < 0} or
      *             {@code start + length > data.length}
      *
      * @deprecated Use {@link #String(byte[], int, int)} instead.
-     * @since Android 1.0
      */
     @Deprecated
     public String(byte[] data, int high, int start, int length) {
@@ -294,7 +288,7 @@
 
     /**
      * Converts the byte array to a string using the specified encoding.
-     * 
+     *
      * @param data
      *            the byte array to convert to a string.
      * @param start
@@ -303,12 +297,13 @@
      *            the number of bytes to convert.
      * @param encoding
      *            the encoding.
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0, start < 0} or {@code start + length >
      *             data.length}.
      * @throws UnsupportedEncodingException
      *             if {@code encoding} is not supported.
-     * @since Android 1.0
      */
     public String(byte[] data, int start, int length, final String encoding)
             throws UnsupportedEncodingException {
@@ -444,7 +439,7 @@
             try {
                 cb = charset.decode(ByteBuffer.wrap(data, start, length));
             } catch (Exception e) {
-                // do nothing. according to spec: 
+                // do nothing. according to spec:
                 // behavior is unspecified for invalid array
                 cb = CharBuffer.wrap("\u003f".toCharArray()); //$NON-NLS-1$
             }
@@ -462,14 +457,15 @@
 
     /**
      * Converts the byte array to a string using the specified encoding.
-     * 
+     *
      * @param data
      *            the byte array to convert to a string.
      * @param encoding
      *            the encoding.
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @throws UnsupportedEncodingException
      *             if {@code encoding} is not supported.
-     * @since Android 1.0
      */
     public String(byte[] data, String encoding) throws UnsupportedEncodingException {
         this(data, 0, data.length, encoding);
@@ -479,10 +475,11 @@
      * Initializes this string to contain the characters in the specified
      * character array. Modifying the character array after creating the string
      * has no effect on the string.
-     * 
+     *
      * @param data
      *            the array of characters.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      */
     public String(char[] data) {
         this(data, 0, data.length);
@@ -492,17 +489,18 @@
      * Initializes this string to contain the specified characters in the
      * character array. Modifying the character array after creating the string
      * has no effect on the string.
-     * 
+     *
      * @param data
      *            the array of characters.
      * @param start
      *            the starting offset in the character array.
      * @param length
      *            the number of characters to use.
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0, start < 0} or {@code start + length >
      *             data.length}
-     * @since Android 1.0
      */
     public String(char[] data, int start, int length) {
         // range check everything so a new char[] is not created
@@ -529,10 +527,9 @@
 
     /**
      * Creates a {@code String} that is a copy of the specified string.
-     * 
+     *
      * @param string
      *            the string to copy.
-     * @since Android 1.0
      */
     public String(String string) {
         value = string.value;
@@ -543,10 +540,9 @@
     /**
      * Creates a {@code String} from the contents of the specified
      * {@code StringBuffer}.
-     * 
+     *
      * @param stringbuffer
      *            the buffer to get the contents from.
-     * @since Android 1.0
      */
     public String(StringBuffer stringbuffer) {
         offset = 0;
@@ -558,7 +554,7 @@
 
     /**
      * Creates a {@code String} from the sub-array of Unicode code points.
-     * 
+     *
      * @param codePoints
      *            the array of Unicode code points to convert.
      * @param offset
@@ -566,13 +562,15 @@
      *            converting from.
      * @param count
      *            the number of elements in {@code codePoints} to copy.
+     * @throws NullPointerException
+     *             if {@code codePoints} is {@code null}.
      * @throws IllegalArgumentException
      *             if any of the elements of {@code codePoints} are not valid
      *             Unicode code points.
      * @throws IndexOutOfBoundsException
      *             if {@code offset} or {@code count} are not within the bounds
      *             of {@code codePoints}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public String(int[] codePoints, int offset, int count) {
         super();
@@ -596,10 +594,12 @@
     /**
      * Creates a {@code String} from the contents of the specified {@code
      * StringBuilder}.
-     * 
+     *
      * @param sb
      *            the {@code StringBuilder} to copy the contents from.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code sb} is {@code null}.
+     * @since 1.5
      */
     public String(StringBuilder sb) {
         if (sb == null) {
@@ -630,13 +630,12 @@
 
     /**
      * Returns the character at the specified offset in this string.
-     * 
+     *
      * @param index
      *            the zero-based index in this string.
      * @return the character at the index.
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0} or {@code index >= length()}.
-     * @since Android 1.0
      */
     public char charAt(int index) {
         if (0 <= index && index < count) {
@@ -645,6 +644,39 @@
         throw new StringIndexOutOfBoundsException();
     }
 
+    // Optimized for ASCII
+    private char compareValue(char ch) {
+        if (ch < 128) {
+            if ('A' <= ch && ch <= 'Z') {
+                return (char) (ch + ('a' - 'A'));
+            }
+            return ch;
+        }
+        return Character.toLowerCase(Character.toUpperCase(ch));
+    }
+
+    // Optimized for ASCII
+    private char toLowerCase(char ch) {
+        if (ch < 128) {
+            if ('A' <= ch && ch <= 'Z') {
+                return (char) (ch + ('a' - 'A'));
+            }
+            return ch;
+        }
+        return Character.toLowerCase(ch);
+    }
+
+    // Optimized for ASCII
+    private char toUpperCase(char ch) {
+        if (ch < 128) {
+            if ('a' <= ch && ch <= 'z') {
+                return (char) (ch - ('a' - 'A'));
+            }
+            return ch;
+        }
+        return Character.toUpperCase(ch);
+    }
+
     /**
      * Compares the specified string to this string using the Unicode values of
      * the characters. Returns 0 if the strings contain the same characters in
@@ -656,13 +688,14 @@
      * Unicode value which is greater than the Unicode value of the character at
      * the same position in the specified string, or if the specified string is
      * a prefix of this string.
-     * 
+     *
      * @param string
      *            the string to compare.
      * @return 0 if the strings are equal, a negative integer if this string is
      *         before the specified string, or a positive integer if this string
      *         is after the specified string.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public int compareTo(String string) {
         // Code adapted from K&R, pg 101
@@ -688,13 +721,14 @@
      * this string has a Unicode value which is greater than the Unicode value
      * of the character at the same position in the specified string, or if the
      * specified string is a prefix of this string.
-     * 
+     *
      * @param string
      *            the string to compare.
      * @return 0 if the strings are equal, a negative integer if this string is
      *         before the specified string, or a positive integer if this string
      *         is after the specified string.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public int compareToIgnoreCase(String string) {
         int o1 = offset, o2 = string.offset, result;
@@ -705,8 +739,8 @@
             if ((c1 = value[o1++]) == (c2 = target[o2++])) {
                 continue;
             }
-            c1 = Character.toLowerCase(Character.toUpperCase(c1));
-            c2 = Character.toLowerCase(Character.toUpperCase(c2));
+            c1 = compareValue(c1);
+            c2 = compareValue(c2);
             if ((result = c1 - c2) != 0) {
                 return result;
             }
@@ -716,12 +750,11 @@
 
     /**
      * Concatenates this string and the specified string.
-     * 
+     *
      * @param string
      *            the string to concatenate
      * @return a new string which is the concatenation of this string and the
      *         specified string.
-     * @since Android 1.0
      */
     public String concat(String string) {
         if (string.count > 0 && count > 0) {
@@ -738,11 +771,12 @@
      * Creates a new string containing the characters in the specified character
      * array. Modifying the character array after creating the string has no
      * effect on the string.
-     * 
+     *
      * @param data
      *            the array of characters.
      * @return the new string.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code data} is {@code null}.
      */
     public static String copyValueOf(char[] data) {
         return new String(data, 0, data.length);
@@ -752,7 +786,7 @@
      * Creates a new string containing the specified characters in the character
      * array. Modifying the character array after creating the string has no
      * effect on the string.
-     * 
+     *
      * @param data
      *            the array of characters.
      * @param start
@@ -760,10 +794,11 @@
      * @param length
      *            the number of characters to use.
      * @return the new string.
+     * @throws NullPointerException
+     *             if {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0, start < 0} or {@code start + length >
      *             data.length}.
-     * @since Android 1.0
      */
     public static String copyValueOf(char[] data, int start, int length) {
         return new String(data, start, length);
@@ -794,12 +829,13 @@
     /**
      * Compares the specified string to this string to determine if the
      * specified string is a suffix.
-     * 
+     *
      * @param suffix
      *            the suffix to look for.
      * @return {@code true} if the specified string is a suffix of this string,
      *         {@code false} otherwise.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code suffix} is {@code null}.
      */
     public boolean endsWith(String suffix) {
         return regionMatches(count - suffix.count, suffix, 0, suffix.count);
@@ -809,13 +845,12 @@
      * Compares the specified object to this string and returns true if they are
      * equal. The object must be an instance of string with the same characters
      * in the same order.
-     * 
+     *
      * @param object
      *            the object to compare.
      * @return {@code true} if the specified object is equal to this string,
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -850,12 +885,11 @@
     /**
      * Compares the specified string to this string ignoring the case of the
      * characters and returns true if they are equal.
-     * 
+     *
      * @param string
      *            the string to compare.
      * @return {@code true} if the specified string is equal to this string,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean equalsIgnoreCase(String string) {
         if (string == this) {
@@ -871,9 +905,9 @@
         char[] target = string.value;
         while (o1 < end) {
             if ((c1 = value[o1++]) != (c2 = target[o2++])
-                    && Character.toUpperCase(c1) != Character.toUpperCase(c2)
+                    && toUpperCase(c1) != toUpperCase(c2)
                     // Required for unicode that we test both cases
-                    && Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
+                    && toLowerCase(c1) != toLowerCase(c2)) {
                 return false;
             }
         }
@@ -885,9 +919,8 @@
      * specified by the file.encoding system property. If the system property is
      * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1
      * is not available, an ASCII encoding is used.
-     * 
+     *
      * @return the byte array encoding of this string.
-     * @since Android 1.0
      */
     public byte[] getBytes() {
         ByteBuffer buffer = defaultCharset().encode(
@@ -900,7 +933,7 @@
     /**
      * Converts this string to a byte array, ignoring the high order bits of
      * each character.
-     * 
+     *
      * @param start
      *            the starting offset of characters to copy.
      * @param end
@@ -909,11 +942,12 @@
      *            the destination byte array.
      * @param index
      *            the starting offset in the destination byte array.
+     * @throws NullPointerException
+     *             if {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0}, {@code end > length()}, {@code index <
      *             0} or {@code end - start > data.length - index}.
      * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)}
-     * @since Android 1.0
      */
     @Deprecated
     public void getBytes(int start, int end, byte[] data, int index) {
@@ -933,13 +967,12 @@
 
     /**
      * Converts this string to a byte array using the specified encoding.
-     * 
+     *
      * @param encoding
      *            the encoding to use.
      * @return the encoded byte array of this string.
      * @throws UnsupportedEncodingException
      *             if the encoding is not supported.
-     * @since Android 1.0
      */
     public byte[] getBytes(String encoding) throws UnsupportedEncodingException {
         ByteBuffer buffer = getCharset(encoding).encode(
@@ -970,7 +1003,7 @@
     /**
      * Copies the specified characters in this string to the character array
      * starting at the specified offset in the character array.
-     * 
+     *
      * @param start
      *            the starting offset of characters to copy.
      * @param end
@@ -979,11 +1012,12 @@
      *            the destination character array.
      * @param index
      *            the starting offset in the character array.
+     * @throws NullPointerException
+     *             if {@code buffer} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0}, {@code end > length()}, {@code start >
      *             end}, {@code index < 0}, {@code end - start > buffer.length -
      *             index}
-     * @since Android 1.0
      */
     public void getChars(int start, int end, char[] buffer, int index) {
         // NOTE last character not copied!
@@ -1031,12 +1065,11 @@
      * Searches in this string for the first index of the specified character.
      * The search for the character starts at the beginning and moves towards
      * the end of this string.
-     * 
+     *
      * @param c
      *            the character to find.
      * @return the index in this string of the specified character, -1 if the
      *         character isn't found.
-     * @since Android 1.0
      */
     public int indexOf(int c) {
         // BEGIN android-changed
@@ -1059,14 +1092,13 @@
      * Searches in this string for the index of the specified character. The
      * search for the character starts at the specified offset and moves towards
      * the end of this string.
-     * 
+     *
      * @param c
      *            the character to find.
      * @param start
      *            the starting offset.
      * @return the index in this string of the specified character, -1 if the
      *         character isn't found.
-     * @since Android 1.0
      */
     public int indexOf(int c, int start) {
         // BEGIN android-changed
@@ -1092,12 +1124,13 @@
      * Searches in this string for the first index of the specified string. The
      * search for the string starts at the beginning and moves towards the end
      * of this string.
-     * 
+     *
      * @param string
      *            the string to find.
      * @return the index of the first character of the specified string in this
      *         string, -1 if the specified string is not a substring.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public int indexOf(String string) {
         // BEGIN android-changed
@@ -1136,14 +1169,15 @@
      * Searches in this string for the index of the specified string. The search
      * for the string starts at the specified offset and moves towards the end
      * of this string.
-     * 
+     *
      * @param subString
      *            the string to find.
      * @param start
      *            the starting offset.
      * @return the index of the first character of the specified string in this
      *         string, -1 if the specified string is not a substring.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code subString} is {@code null}.
      */
     public int indexOf(String subString, int start) {
         // BEGIN android-changed
@@ -1185,9 +1219,8 @@
      * If the string is not in the table, it is added. Returns the string
      * contained in the table which is equal to this string. The same string
      * object is always returned for strings which are equal.
-     * 
+     *
      * @return the interned string equal to this string.
-     * @since Android 1.0
      */
     native public String intern();
 
@@ -1196,12 +1229,11 @@
      * Searches in this string for the last index of the specified character.
      * The search for the character starts at the end and moves towards the
      * beginning of this string.
-     * 
+     *
      * @param c
      *            the character to find.
      * @return the index in this string of the specified character, -1 if the
      *         character isn't found.
-     * @since Android 1.0
      */
     public int lastIndexOf(int c) {
         // BEGIN android-changed
@@ -1221,14 +1253,13 @@
      * Searches in this string for the index of the specified character. The
      * search for the character starts at the specified offset and moves towards
      * the beginning of this string.
-     * 
+     *
      * @param c
      *            the character to find.
      * @param start
      *            the starting offset.
      * @return the index in this string of the specified character, -1 if the
      *         character isn't found.
-     * @since Android 1.0
      */
     public int lastIndexOf(int c, int start) {
         // BEGIN android-changed
@@ -1253,12 +1284,13 @@
      * Searches in this string for the last index of the specified string. The
      * search for the string starts at the end and moves towards the beginning
      * of this string.
-     * 
+     *
      * @param string
      *            the string to find.
      * @return the index of the first character of the specified string in this
      *         string, -1 if the specified string is not a substring.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public int lastIndexOf(String string) {
         // Use count instead of count - 1 so lastIndexOf("") returns count
@@ -1269,14 +1301,15 @@
      * Searches in this string for the index of the specified string. The search
      * for the string starts at the specified offset and moves towards the
      * beginning of this string.
-     * 
+     *
      * @param subString
      *            the string to find.
      * @param start
      *            the starting offset.
      * @return the index of the first character of the specified string in this
      *         string , -1 if the specified string is not a substring.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code subString} is {@code null}.
      */
     public int lastIndexOf(String subString, int start) {
         int subCount = subString.count;
@@ -1312,9 +1345,8 @@
 
     /**
      * Returns the size of this string.
-     * 
+     *
      * @return the number of characters in this string.
-     * @since Android 1.0
      */
     public int length() {
         return count;
@@ -1323,7 +1355,7 @@
     /**
      * Compares the specified string to this string and compares the specified
      * range of characters to determine if they are the same.
-     * 
+     *
      * @param thisStart
      *            the starting offset in this string.
      * @param string
@@ -1334,7 +1366,8 @@
      *            the number of characters to compare.
      * @return {@code true} if the ranges of characters are equal, {@code false}
      *         otherwise
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public boolean regionMatches(int thisStart, String string, int start,
             int length) {
@@ -1367,7 +1400,7 @@
      * Compares the specified string to this string and compares the specified
      * range of characters to determine if they are the same. When ignoreCase is
      * true, the case of the characters is ignored during the comparison.
-     * 
+     *
      * @param ignoreCase
      *            specifies if case should be ignored.
      * @param thisStart
@@ -1380,7 +1413,8 @@
      *            the number of characters to compare.
      * @return {@code true} if the ranges of characters are equal, {@code false}
      *         otherwise.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public boolean regionMatches(boolean ignoreCase, int thisStart,
             String string, int start, int length) {
@@ -1403,11 +1437,9 @@
             char[] target = string.value;
             while (thisStart < end) {
                 if ((c1 = value[thisStart++]) != (c2 = target[start++])
-                        && Character.toUpperCase(c1) != Character
-                                .toUpperCase(c2)
+                        && toUpperCase(c1) != toUpperCase(c2)
                         // Required for unicode that we test both cases
-                        && Character.toLowerCase(c1) != Character
-                                .toLowerCase(c2)) {
+                        && toLowerCase(c1) != toLowerCase(c2)) {
                     return false;
                 }
             }
@@ -1419,13 +1451,12 @@
     /**
      * Copies this string replacing occurrences of the specified character with
      * another character.
-     * 
+     *
      * @param oldChar
      *            the character to replace.
      * @param newChar
      *            the replacement character.
      * @return a new string with occurrences of oldChar replaced by newChar.
-     * @since Android 1.0
      */
     public String replace(char oldChar, char newChar) {
         // BEGIN endroid-changed
@@ -1454,18 +1485,19 @@
         return copied ? new String(0, count, buffer) : this;
         // END android-changed
     }
-    
+
     /**
      * Copies this string replacing occurrences of the specified target sequence
      * with another sequence. The string is processed from the beginning to the
      * end.
-     * 
+     *
      * @param target
      *            the sequence to replace.
      * @param replacement
      *            the replacement sequence.
      * @return the resulting string.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code target} or {@code replacement} is {@code null}.
      */
     public String replace(CharSequence target, CharSequence replacement) {
         if (target == null) {
@@ -1489,7 +1521,7 @@
             buffer.append(rs);
             tail = index + tl;
         } while ((index = indexOf(ts, tail)) != -1);
-        //append trailing chars 
+        //append trailing chars
         buffer.append(value, offset + tail, count - tail);
 
         return buffer.toString();
@@ -1498,12 +1530,13 @@
     /**
      * Compares the specified string to this string to determine if the
      * specified string is a prefix.
-     * 
+     *
      * @param prefix
      *            the string to look for.
      * @return {@code true} if the specified string is a prefix of this string,
      *         {@code false} otherwise
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code prefix} is {@code null}.
      */
     public boolean startsWith(String prefix) {
         return startsWith(prefix, 0);
@@ -1512,14 +1545,15 @@
     /**
      * Compares the specified string to this string, starting at the specified
      * offset, to determine if the specified string is a prefix.
-     * 
+     *
      * @param prefix
      *            the string to look for.
      * @param start
      *            the starting offset.
      * @return {@code true} if the specified string occurs in this string at the
      *         specified offset, {@code false} otherwise.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code prefix} is {@code null}.
      */
     public boolean startsWith(String prefix, int start) {
         return regionMatches(start, prefix, 0, prefix.count);
@@ -1527,14 +1561,13 @@
 
     /**
      * Copies a range of characters into a new string.
-     * 
+     *
      * @param start
      *            the offset of the first character.
      * @return a new string containing the characters from start to the end of
      *         the string.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0} or {@code start > length()}.
-     * @since Android 1.0
      */
     public String substring(int start) {
         if (start == 0) {
@@ -1548,7 +1581,7 @@
 
     /**
      * Copies a range of characters into a new string.
-     * 
+     *
      * @param start
      *            the offset of the first character.
      * @param end
@@ -1557,7 +1590,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0}, {@code start > end} or {@code end >
      *             length()}.
-     * @since Android 1.0
      */
     public String substring(int start, int end) {
         if (start == 0 && end == count) {
@@ -1573,9 +1605,8 @@
 
     /**
      * Copies the characters in this string to a character array.
-     * 
+     *
      * @return a character array containing the characters of this string.
-     * @since Android 1.0
      */
     public char[] toCharArray() {
         char[] buffer = new char[count];
@@ -1586,10 +1617,9 @@
     /**
      * Converts the characters in this string to lowercase, using the default
      * Locale.
-     * 
+     *
      * @return a new string containing the lowercase characters equivalent to
      *         the characters in this string.
-     * @since Android 1.0
      */
     public String toLowerCase() {
         return toLowerCase(Locale.getDefault());
@@ -1598,17 +1628,16 @@
     /**
      * Converts the characters in this string to lowercase, using the specified
      * Locale.
-     * 
+     *
      * @param locale
      *            the Locale to use.
      * @return a new string containing the lowercase characters equivalent to
      *         the characters in this string.
-     * @since Android 1.0
      */
     public String toLowerCase(Locale locale) {
         for (int o = offset, end = offset + count; o < end; o++) {
             char ch = value[o];
-            if (ch != Character.toLowerCase(ch)) {
+            if (ch != toLowerCase(ch)) {
                 char[] buffer = new char[count];
                 int i = o - offset;
                 // Not worth checking for i == 0 case
@@ -1616,12 +1645,12 @@
                 // Turkish
                 if (!"tr".equals(locale.getLanguage())) { //$NON-NLS-1$
                     while (i < count) {
-                        buffer[i++] = Character.toLowerCase(value[o++]);
+                        buffer[i++] = toLowerCase(value[o++]);
                     }
                 } else {
                     while (i < count) {
-                        buffer[i++] = (ch = value[o++]) != 0x49 ? Character
-                                .toLowerCase(ch) : (char) 0x131;
+                        buffer[i++] = (ch = value[o++]) != 0x49 ? toLowerCase(ch)
+                                : (char) 0x131;
                     }
                 }
                 return new String(0, count, buffer);
@@ -1634,7 +1663,6 @@
      * Returns this string.
      *
      * @return this string.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -1644,15 +1672,17 @@
     /**
      * Converts the characters in this string to uppercase, using the default
      * Locale.
-     * 
+     *
      * @return a new string containing the uppercase characters equivalent to
      *         the characters in this string.
-     * @since Android 1.0
      */
     public String toUpperCase() {
         return toUpperCase(Locale.getDefault());
     }
 
+    // BEGIN android-note
+    // put this in a helper class so that it's only initialized on demand?
+    // END android-note
     private static final char[] upperValues = "SS\u0000\u02bcN\u0000J\u030c\u0000\u0399\u0308\u0301\u03a5\u0308\u0301\u0535\u0552\u0000H\u0331\u0000T\u0308\u0000W\u030a\u0000Y\u030a\u0000A\u02be\u0000\u03a5\u0313\u0000\u03a5\u0313\u0300\u03a5\u0313\u0301\u03a5\u0313\u0342\u1f08\u0399\u0000\u1f09\u0399\u0000\u1f0a\u0399\u0000\u1f0b\u0399\u0000\u1f0c\u0399\u0000\u1f0d\u0399\u0000\u1f0e\u0399\u0000\u1f0f\u0399\u0000\u1f08\u0399\u0000\u1f09\u0399\u0000\u1f0a\u0399\u0000\u1f0b\u0399\u0000\u1f0c\u0399\u0000\u1f0d\u0399\u0000\u1f0e\u0399\u0000\u1f0f\u0399\u0000\u1f28\u0399\u0000\u1f29\u0399\u0000\u1f2a\u0399\u0000\u1f2b\u0399\u0000\u1f2c\u0399\u0000\u1f2d\u0399\u0000\u1f2e\u0399\u0000\u1f2f\u0399\u0000\u1f28\u0399\u0000\u1f29\u0399\u0000\u1f2a\u0399\u0000\u1f2b\u0399\u0000\u1f2c\u0399\u0000\u1f2d\u0399\u0000\u1f2e\u0399\u0000\u1f2f\u0399\u0000\u1f68\u0399\u0000\u1f69\u0399\u0000\u1f6a\u0399\u0000\u1f6b\u0399\u0000\u1f6c\u0399\u0000\u1f6d\u0399\u0000\u1f6e\u0399\u0000\u1f6f\u0399\u0000\u1f68\u0399\u0000\u1f69\u0399\u0000\u1f6a\u0399\u0000\u1f6b\u0399\u0000\u1f6c\u0399\u0000\u1f6d\u0399\u0000\u1f6e\u0399\u0000\u1f6f\u0399\u0000\u1fba\u0399\u0000\u0391\u0399\u0000\u0386\u0399\u0000\u0391\u0342\u0000\u0391\u0342\u0399\u0391\u0399\u0000\u1fca\u0399\u0000\u0397\u0399\u0000\u0389\u0399\u0000\u0397\u0342\u0000\u0397\u0342\u0399\u0397\u0399\u0000\u0399\u0308\u0300\u0399\u0308\u0301\u0399\u0342\u0000\u0399\u0308\u0342\u03a5\u0308\u0300\u03a5\u0308\u0301\u03a1\u0313\u0000\u03a5\u0342\u0000\u03a5\u0308\u0342\u1ffa\u0399\u0000\u03a9\u0399\u0000\u038f\u0399\u0000\u03a9\u0342\u0000\u03a9\u0342\u0399\u03a9\u0399\u0000FF\u0000FI\u0000FL\u0000FFIFFLST\u0000ST\u0000\u0544\u0546\u0000\u0544\u0535\u0000\u0544\u053b\u0000\u054e\u0546\u0000\u0544\u053d\u0000".value; //$NON-NLS-1$
 
     /**
@@ -1716,12 +1746,11 @@
     /**
      * Converts the characters in this string to uppercase, using the specified
      * Locale.
-     * 
+     *
      * @param locale
      *            the Locale to use.
      * @return a new string containing the uppercase characters equivalent to
      *         the characters in this string.
-     * @since Android 1.0
      */
     public String toUpperCase(Locale locale) {
         boolean turkish = "tr".equals(locale.getLanguage()); //$NON-NLS-1$
@@ -1736,8 +1765,8 @@
                     System.arraycopy(output, 0, newoutput, 0, output.length);
                     output = newoutput;
                 }
-                char upch = !turkish ? Character.toUpperCase(ch)
-                        : (ch != 0x69 ? Character.toUpperCase(ch)
+                char upch = !turkish ? toUpperCase(ch)
+                        : (ch != 0x69 ? toUpperCase(ch)
                                 : (char) 0x130);
                 if (ch != upch) {
                     if (output == null) {
@@ -1782,10 +1811,9 @@
     /**
      * Copies this string removing white space characters from the beginning and
      * end of the string.
-     * 
+     *
      * @return a new string with characters <code><= \\u0020</code> removed from
      *         the beginning and the end.
-     * @since Android 1.0
      */
     public String trim() {
         int start = offset, last = offset + count - 1;
@@ -1806,11 +1834,12 @@
      * Creates a new string containing the characters in the specified character
      * array. Modifying the character array after creating the string has no
      * effect on the string.
-     * 
+     *
      * @param data
      *            the array of characters.
      * @return the new string.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code data} is {@code null}.
      */
     public static String valueOf(char[] data) {
         return new String(data, 0, data.length);
@@ -1820,7 +1849,7 @@
      * Creates a new string containing the specified characters in the character
      * array. Modifying the character array after creating the string has no
      * effect on the string.
-     * 
+     *
      * @param data
      *            the array of characters.
      * @param start
@@ -1831,7 +1860,8 @@
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0}, {@code start < 0} or {@code start +
      *             length > data.length}
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code data} is {@code null}.
      */
     public static String valueOf(char[] data, int start, int length) {
         return new String(data, start, length);
@@ -1839,11 +1869,10 @@
 
     /**
      * Converts the specified character to its string representation.
-     * 
+     *
      * @param value
      *            the character.
      * @return the character converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(char value) {
         String s;
@@ -1858,11 +1887,10 @@
 
     /**
      * Converts the specified double to its string representation.
-     * 
+     *
      * @param value
      *            the double.
      * @return the double converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(double value) {
         return Double.toString(value);
@@ -1870,11 +1898,10 @@
 
     /**
      * Converts the specified float to its string representation.
-     * 
+     *
      * @param value
      *            the float.
      * @return the float converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(float value) {
         return Float.toString(value);
@@ -1882,11 +1909,10 @@
 
     /**
      * Converts the specified integer to its string representation.
-     * 
+     *
      * @param value
      *            the integer.
      * @return the integer converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(int value) {
         return Integer.toString(value);
@@ -1894,11 +1920,10 @@
 
     /**
      * Converts the specified long to its string representation.
-     * 
+     *
      * @param value
      *            the long.
      * @return the long converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(long value) {
         return Long.toString(value);
@@ -1908,11 +1933,10 @@
      * Converts the specified object to its string representation. If the object
      * is null return the string {@code "null"}, otherwise use {@code
      * toString()} to get the string representation.
-     * 
+     *
      * @param value
      *            the object.
      * @return the object converted to a string, or the string {@code "null"}.
-     * @since Android 1.0
      */
     public static String valueOf(Object value) {
         return value != null ? value.toString() : "null"; //$NON-NLS-1$
@@ -1922,11 +1946,10 @@
      * Converts the specified boolean to its string representation. When the
      * boolean is {@code true} return {@code "true"}, otherwise return {@code
      * "false"}.
-     * 
+     *
      * @param value
      *            the boolean.
      * @return the boolean converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(boolean value) {
         return value ? "true" : "false"; //$NON-NLS-1$ //$NON-NLS-2$
@@ -1935,13 +1958,15 @@
     /**
      * Returns whether the characters in the StringBuffer {@code strbuf} are the
      * same as those in this string.
-     * 
+     *
      * @param strbuf
      *            the StringBuffer to compare this string to.
      * @return {@code true} if the characters in {@code strbuf} are identical to
      *         those in this string. If they are not, {@code false} will be
      *         returned.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code strbuf} is {@code null}.
+     * @since 1.4
      */
     public boolean contentEquals(StringBuffer strbuf) {
         synchronized (strbuf) {
@@ -1957,11 +1982,11 @@
     /**
      * Compares a {@code CharSequence} to this {@code String} to determine if
      * their contents are equal.
-     * 
+     *
      * @param cs
      *            the character sequence to compare to.
      * @return {@code true} if equal, otherwise {@code false}
-     * @since Android 1.0
+     * @since 1.5
      */
     public boolean contentEquals(CharSequence cs) {
         if (cs == null) {
@@ -1983,14 +2008,16 @@
 
     /**
      * Determines whether this string matches a given regular expression.
-     * 
+     *
      * @param expr
      *            the regular expression to be matched.
      * @return {@code true} if the expression matches, otherwise {@code false}.
      * @throws PatternSyntaxException
      *             if the syntax of the supplied regular expression is not
      *             valid.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code expr} is {@code null}.
+     * @since 1.4
      */
     public boolean matches(String expr) {
         return Pattern.matches(expr, this);
@@ -1999,7 +2026,7 @@
     /**
      * Replace any substrings within this string that match the supplied regular
      * expression {@code expr}, with the string {@code substitute}.
-     * 
+     *
      * @param expr
      *            the regular expression to match.
      * @param substitute
@@ -2009,7 +2036,7 @@
      *             if the syntax of the supplied regular expression is not
      *             valid.
      * @see Pattern
-     * @since Android 1.0
+     * @since 1.4
      */
     public String replaceAll(String expr, String substitute) {
         return Pattern.compile(expr).matcher(this).replaceAll(substitute);
@@ -2018,7 +2045,7 @@
     /**
      * Replace the first substring within this string that matches the supplied
      * regular expression {@code expr}, with the string {@code substitute}.
-     * 
+     *
      * @param expr
      *            the regular expression to match.
      * @param substitute
@@ -2027,8 +2054,10 @@
      * @throws PatternSyntaxException
      *             if the syntax of the supplied regular expression is not
      *             valid.
+     * @throws NullPointerException
+     *             if {@code strbuf} is {@code null}.
      * @see Pattern
-     * @since Android 1.0
+     * @since 1.4
      */
     public String replaceFirst(String expr, String substitute) {
         return Pattern.compile(expr).matcher(this).replaceFirst(substitute);
@@ -2036,16 +2065,18 @@
 
     /**
      * Splits this string using the supplied regular expression {@code expr}.
-     * 
+     *
      * @param expr
      *            the regular expression used to divide the string.
      * @return an array of Strings created by separating the string along
      *         matches of the regular expression.
+     * @throws NullPointerException
+     *             if {@code expr} is {@code null}.
      * @throws PatternSyntaxException
      *             if the syntax of the supplied regular expression is not
      *             valid.
      * @see Pattern
-     * @since Android 1.0
+     * @since 1.4
      */
     public String[] split(String expr) {
         return Pattern.compile(expr).split(this);
@@ -2055,18 +2086,20 @@
      * Splits this string using the supplied regular expression {@code expr}.
      * The parameter {@code max} controls the behavior how many times the
      * pattern is applied to the string.
-     * 
+     *
      * @param expr
      *            the regular expression used to divide the string.
      * @param max
      *            the number of entries in the resulting array.
      * @return an array of Strings created by separating the string along
      *         matches of the regular expression.
+     * @throws NullPointerException
+     *             if {@code expr} is {@code null}.
      * @throws PatternSyntaxException
      *             if the syntax of the supplied regular expression is not
      *             valid.
      * @see Pattern#split(CharSequence, int)
-     * @since Android 1.0
+     * @since 1.4
      */
     public String[] split(String expr, int max) {
         return Pattern.compile(expr).split(this, max);
@@ -2075,7 +2108,7 @@
     /**
      * Has the same result as the substring function, but is present so that
      * string may implement the CharSequence interface.
-     * 
+     *
      * @param start
      *            the offset the first character.
      * @param end
@@ -2085,7 +2118,7 @@
      *             if {@code start < 0}, {@code end < 0}, {@code start > end} or
      *             {@code end > length()}.
      * @see java.lang.CharSequence#subSequence(int, int)
-     * @since Android 1.0
+     * @since 1.4
      */
     public CharSequence subSequence(int start, int end) {
         return substring(start, end);
@@ -2094,7 +2127,7 @@
     /**
      * Retrieves the Unicode code point (character) value at the specified
      * {@code index}.
-     * 
+     *
      * @param index
      *            the index to the {@code char} code unit within this string.
      * @return the Unicode code point value.
@@ -2102,7 +2135,7 @@
      *             if {@code index} is negative or greater than or equal to
      *             {@code length()}.
      * @see Character#codePointAt(char[], int, int)
-     * @since Android 1.0
+     * @since 1.5
      */
     public int codePointAt(int index) {
         if (index < 0 || index >= count) {
@@ -2115,7 +2148,7 @@
     /**
      * Retrieves the Unicode code point value that precedes the specified
      * {@code index}.
-     * 
+     *
      * @param index
      *            the index to the {@code char} code unit within this string.
      * @return the Unicode code point value.
@@ -2123,7 +2156,7 @@
      *             if {@code index} is less than 1 or greater than
      *             {@code length()}.
      * @see Character#codePointBefore(char[], int, int)
-     * @since Android 1.0
+     * @since 1.5
      */
     public int codePointBefore(int index) {
         if (index < 1 || index > count) {
@@ -2136,7 +2169,7 @@
     /**
      * Calculates the number of Unicode code points between {@code beginIndex}
      * and {@code endIndex}.
-     * 
+     *
      * @param beginIndex
      *            the inclusive beginning index of the subsequence.
      * @param endIndex
@@ -2147,7 +2180,7 @@
      *             endIndex} or {@code endIndex} is greater than {@code
      *             length()}.
      * @see Character#codePointCount(CharSequence, int, int)
-     * @since Android 1.0
+     * @since 1.5
      */
     public int codePointCount(int beginIndex, int endIndex) {
         if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
@@ -2160,12 +2193,12 @@
     /**
      * Determines if this {@code String} contains the sequence of characters in
      * the {@code CharSequence} passed.
-     * 
+     *
      * @param cs
      *            the character sequence to search for.
      * @return {@code true} if the sequence of characters are contained in this
      *         string, otherwise {@code false}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public boolean contains(CharSequence cs) {
         if (cs == null) {
@@ -2177,7 +2210,7 @@
     /**
      * Returns the index within this object that is offset from {@code index} by
      * {@code codePointOffset} code points.
-     * 
+     *
      * @param index
      *            the index within this object to calculate the offset from.
      * @param codePointOffset
@@ -2187,7 +2220,7 @@
      *             if {@code index} is negative or greater than {@code length()}
      *             or if there aren't enough code points before or after {@code
      *             index} to match {@code codePointOffset}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public int offsetByCodePoints(int index, int codePointOffset) {
         int s = index + offset;
@@ -2199,16 +2232,18 @@
     /**
      * Returns a formatted string, using the supplied format and arguments,
      * using the default locale.
-     * 
+     *
      * @param format
      *            a format string.
      * @param args
      *            arguments to replace format specifiers (may be none).
      * @return the formatted string.
-     * @throws IllegalFormatException
+     * @throws NullPointerException
+     *             if {@code format} is {@code null}.
+     * @throws java.util.IllegalFormatException
      *             if the format is invalid.
      * @see java.util.Formatter
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String format(String format, Object... args) {
         return format(Locale.getDefault(), format, args);
@@ -2224,7 +2259,7 @@
      * if you use the method only rarely, but if you rely on it for formatting a
      * large number of strings, consider creating and reusing your own
      * {@link java.util.Formatter} instance instead.
-     * 
+     *
      * @param loc
      *            the locale to apply; {@code null} value means no localization.
      * @param format
@@ -2232,10 +2267,12 @@
      * @param args
      *            arguments to replace format specifiers (may be none).
      * @return the formatted string.
-     * @throws IllegalFormatException
+     * @throws NullPointerException
+     *             if {@code format} is {@code null}.
+     * @throws java.util.IllegalFormatException
      *             if the format is invalid.
      * @see java.util.Formatter
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String format(Locale loc, String format, Object... args) {
         if (format == null) {
diff --git a/luni/src/main/java/java/lang/StringBuffer.java b/luni/src/main/java/java/lang/StringBuffer.java
index 5cb5c24..3ec43dc 100644
--- a/luni/src/main/java/java/lang/StringBuffer.java
+++ b/luni/src/main/java/java/lang/StringBuffer.java
@@ -39,7 +39,7 @@
  * 
  * @see String
  * @see StringBuilder
- * @since Android 1.0
+ * @since 1.0
  */
 public final class StringBuffer extends AbstractStringBuilder implements
         Appendable, Serializable, CharSequence {
@@ -53,8 +53,6 @@
 
     /**
      * Constructs a new StringBuffer using the default capacity which is 16.
-     * 
-     * @since Android 1.0
      */
     public StringBuffer() {
         super();
@@ -65,7 +63,6 @@
      * 
      * @param capacity
      *            the initial capacity.
-     * @since Android 1.0
      */
     public StringBuffer(int capacity) {
         super(capacity);
@@ -73,12 +70,13 @@
 
     /**
      * Constructs a new StringBuffer containing the characters in the specified
-     * stringy. The capacity of the new buffer will be the length of the
+     * string. The capacity of the new buffer will be the length of the
      * {@code String} plus the default capacity.
      * 
      * @param string
      *            the string content with which to initialize the new instance.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code string} is {@code null}.
      */
     public StringBuffer(String string) {
         super(string);
@@ -91,7 +89,9 @@
      * 
      * @param cs
      *            the content to initialize the instance.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code cs} is {@code null}.
+     * @since 1.5
      */
     public StringBuffer(CharSequence cs) {
         super(cs.toString());
@@ -103,13 +103,11 @@
      * <p>
      * If the argument is {@code true} the string {@code "true"} is appended,
      * otherwise the string {@code "false"} is appended.
-     * </p>
-     * 
+     *
      * @param b
      *            the boolean to append.
      * @return this StringBuffer.
      * @see String#valueOf(boolean)
-     * @since Android 1.0
      */
     public StringBuffer append(boolean b) {
         return append(b ? "true" : "false"); //$NON-NLS-1$//$NON-NLS-2$
@@ -122,7 +120,6 @@
      *            the character to append.
      * @return this StringBuffer.
      * @see String#valueOf(char)
-     * @since Android 1.0
      */
     public synchronized StringBuffer append(char ch) {
         append0(ch);
@@ -137,7 +134,6 @@
      *            the double to append.
      * @return this StringBuffer.
      * @see String#valueOf(double)
-     * @since Android 1.0
      */
     public StringBuffer append(double d) {
         return append(Double.toString(d));
@@ -151,7 +147,6 @@
      *            the float to append.
      * @return this StringBuffer.
      * @see String#valueOf(float)
-     * @since Android 1.0
      */
     public StringBuffer append(float f) {
         return append(Float.toString(f));
@@ -165,7 +160,6 @@
      *            the integer to append.
      * @return this StringBuffer.
      * @see String#valueOf(int)
-     * @since Android 1.0
      */
     public StringBuffer append(int i) {
         return append(Integer.toString(i));
@@ -179,7 +173,6 @@
      *            the long to append.
      * @return this StringBuffer.
      * @see String#valueOf(long)
-     * @since Android 1.0
      */
     public StringBuffer append(long l) {
         return append(Long.toString(l));
@@ -192,13 +185,11 @@
      * If the specified object is {@code null} the string {@code "null"} is
      * appended, otherwise the objects {@code toString} is used to get its
      * string representation.
-     * </p>
-     * 
+     *
      * @param obj
      *            the object to append (may be null).
      * @return this StringBuffer.
      * @see String#valueOf(Object)
-     * @since Android 1.0
      */
     public synchronized StringBuffer append(Object obj) {
         if (obj == null) {
@@ -214,12 +205,10 @@
      * <p>
      * If the specified string is {@code null} the string {@code "null"} is
      * appended, otherwise the contents of the specified string is appended.
-     * </p>
-     * 
+     *
      * @param string
      *            the string to append (may be null).
      * @return this StringBuffer.
-     * @since Android 1.0
      */
     public synchronized StringBuffer append(String string) {
         append0(string);
@@ -232,12 +221,12 @@
      * If the specified StringBuffer is {@code null} the string {@code "null"}
      * is appended, otherwise the contents of the specified StringBuffer is
      * appended.
-     * </p>
-     * 
+     *
      * @param sb
      *            the StringBuffer to append (may be null).
      * @return this StringBuffer.
-     * @since Android 1.0
+     * 
+     * @since 1.4
      */
     public synchronized StringBuffer append(StringBuffer sb) {
         if (sb == null) {
@@ -256,7 +245,8 @@
      * @param chars
      *            the character array to append.
      * @return this StringBuffer.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code chars} is {@code null}.
      */
     public synchronized StringBuffer append(char chars[]) {
         append0(chars);
@@ -276,7 +266,8 @@
      * @throws ArrayIndexOutOfBoundsException
      *             if {@code length < 0} , {@code start < 0} or {@code start +
      *             length > chars.length}.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code chars} is {@code null}.
      */
     public synchronized StringBuffer append(char chars[], int start, int length) {
         append0(chars, start, length);
@@ -289,12 +280,11 @@
      * If the specified CharSequence is {@code null} the string {@code "null"}
      * is appended, otherwise the contents of the specified CharSequence is
      * appended.
-     * </p>
-     * 
+     *
      * @param s
      *            the CharSequence to append.
      * @return this StringBuffer.
-     * @since Android 1.0
+     * @since 1.5
      */
     public synchronized StringBuffer append(CharSequence s) {
         if (s == null) {
@@ -310,8 +300,7 @@
      * <p>
      * If the specified CharSequence is {@code null}, then the string {@code
      * "null"} is used to extract a subsequence.
-     * </p>
-     * 
+     *
      * @param s
      *            the CharSequence to append.
      * @param start
@@ -323,7 +312,7 @@
      *             if {@code start} or {@code end} are negative, {@code start}
      *             is greater than {@code end} or {@code end} is greater than
      *             the length of {@code s}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public synchronized StringBuffer append(CharSequence s, int start, int end) {
         append0(s, start, end);
@@ -336,13 +325,12 @@
      * <p>
      * The code point is converted to a {@code char[]} as defined by
      * {@link Character#toChars(int)}.
-     * </p>
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to encode and append.
      * @return this StringBuffer.
      * @see Character#toChars(int)
-     * @since Android 1.0
+     * @since 1.5
      */
     public StringBuffer appendCodePoint(int codePoint) {
         return append(Character.toChars(codePoint));
@@ -379,7 +367,6 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code start < 0}, {@code start > end} or {@code end >
      *             length()}.
-     * @since Android 1.0
      */
     public synchronized StringBuffer delete(int start, int end) {
         delete0(start, end);
@@ -394,7 +381,6 @@
      * @return this StringBuffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code location < 0} or {@code location >= length()}
-     * @since Android 1.0
      */
     public synchronized StringBuffer deleteCharAt(int location) {
         deleteCharAt0(location);
@@ -405,6 +391,7 @@
     public synchronized void ensureCapacity(int min) {
         super.ensureCapacity(min);
     }
+
     /**
      * Copies the requested sequence of characters to the {@code char[]} passed
      * starting at {@code idx}.
@@ -421,7 +408,6 @@
      *             if {@code start < 0}, {@code end > length()}, {@code start >
      *             end}, {@code index < 0}, {@code end - start > buffer.length -
      *             index}
-     * @since Android 1.0
      */
     @Override
     public synchronized void getChars(int start, int end, char[] buffer, int idx) {
@@ -443,7 +429,6 @@
      * @return this buffer.
      * @throws ArrayIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public synchronized StringBuffer insert(int index, char ch) {
         insert0(index, ch);
@@ -461,7 +446,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, boolean b) {
         return insert(index, b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -478,7 +462,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, int i) {
         return insert(index, Integer.toString(i));
@@ -495,7 +478,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, long l) {
         return insert(index, Long.toString(l));
@@ -512,7 +494,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, double d) {
         return insert(index, Double.toString(d));
@@ -529,7 +510,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, float f) {
         return insert(index, Float.toString(f));
@@ -542,8 +522,7 @@
      * If the specified object is {@code null}, the string {@code "null"} is
      * inserted, otherwise the objects {@code toString} method is used to get
      * its string representation.
-     * </p>
-     * 
+     *
      * @param index
      *            the index at which to insert.
      * @param obj
@@ -551,7 +530,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, Object obj) {
         return insert(index, obj == null ? "null" : obj.toString()); //$NON-NLS-1$
@@ -562,8 +540,7 @@
      * <p>
      * If the specified string is {@code null}, the string {@code "null"} is
      * inserted, otherwise the contents of the string is inserted.
-     * </p>
-     * 
+     *
      * @param index
      *            the index at which to insert.
      * @param string
@@ -571,7 +548,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public synchronized StringBuffer insert(int index, String string) {
         insert0(index, string);
@@ -588,7 +564,8 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code chars} is {@code null}.
      */
     public synchronized StringBuffer insert(int index, char[] chars) {
         insert0(index, chars);
@@ -608,11 +585,12 @@
      * @param length
      *            the number of characters.
      * @return this buffer.
+     * @throws NullPointerException
+     *             if {@code chars} is {@code null}.
      * @throws StringIndexOutOfBoundsException
      *             if {@code length < 0}, {@code start < 0}, {@code start +
      *             length > chars.length}, {@code index < 0} or {@code index >
      *             length()}
-     * @since Android 1.0
      */
     public synchronized StringBuffer insert(int index, char chars[], int start,
             int length) {
@@ -626,8 +604,7 @@
      * <p>
      * If the specified CharSequence is {@code null}, the string {@code "null"}
      * is inserted, otherwise the contents of the CharSequence.
-     * </p>
-     * 
+     *
      * @param index
      *            The index at which to insert.
      * @param s
@@ -635,7 +612,7 @@
      * @return this buffer.
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public synchronized StringBuffer insert(int index, CharSequence s) {
         insert0(index, s == null ? "null" : s.toString()); //$NON-NLS-1$
@@ -648,7 +625,6 @@
      * <p>
      * If the specified CharSequence is {@code null}, the string {@code "null"}
      * is inserted, otherwise the contents of the CharSequence.
-     * </p>
      * 
      * @param index
      *            The index at which to insert.
@@ -664,7 +640,7 @@
      *             length, {@code start} or {@code end} are negative, {@code
      *             start} is greater than {@code end} or {@code end} is greater
      *             than the length of {@code s}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public synchronized StringBuffer insert(int index, CharSequence s,
             int start, int end) {
@@ -697,7 +673,6 @@
      *             if {@code start} or {@code end} are negative, {@code start}
      *             is greater than {@code end} or {@code end} is greater than
      *             the length of {@code s}.
-     * @since Android 1.0
      */
     public synchronized StringBuffer replace(int start, int end, String string) {
         replace0(start, end, string);
@@ -708,7 +683,6 @@
      * Reverses the order of characters in this buffer.
      * 
      * @return this buffer.
-     * @since Android 1.0
      */
     public synchronized StringBuffer reverse() {
         reverse0();
diff --git a/luni/src/main/java/java/lang/StringBuilder.java b/luni/src/main/java/java/lang/StringBuilder.java
index d62f900..12d401f 100644
--- a/luni/src/main/java/java/lang/StringBuilder.java
+++ b/luni/src/main/java/java/lang/StringBuilder.java
@@ -32,13 +32,13 @@
  * StringBuilder}, so that, like {@code StringBuffer}s, they can be used in
  * chaining method calls together. For example, {@code new StringBuilder("One
  * should ").append("always strive ").append("to achieve Harmony")}.
- * </p>
  * 
  * @see CharSequence
  * @see Appendable
  * @see StringBuffer
  * @see String
- * @since Android 1.0
+ * 
+ * @since 1.5
  */
 public final class StringBuilder extends AbstractStringBuilder implements
         Appendable, CharSequence, Serializable {
@@ -49,7 +49,6 @@
      * Constructs an instance with an initial capacity of {@code 16}.
      * 
      * @see #capacity()
-     * @since Android 1.0
      */
     public StringBuilder() {
         super();
@@ -57,13 +56,12 @@
 
     /**
      * Constructs an instance with the specified capacity.
-     * 
+     *
      * @param capacity
      *            the initial capacity to use.
      * @throws NegativeArraySizeException
      *             if the specified {@code capacity} is negative.
      * @see #capacity()
-     * @since Android 1.0
      */
     public StringBuilder(int capacity) {
         super(capacity);
@@ -73,10 +71,11 @@
      * Constructs an instance that's initialized with the contents of the
      * specified {@code CharSequence}. The capacity of the new builder will be
      * the length of the {@code CharSequence} plus 16.
-     * 
+     *
      * @param seq
      *            the {@code CharSequence} to copy into the builder.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code seq} is {@code null}.
      */
     public StringBuilder(CharSequence seq) {
         super(seq.toString());
@@ -86,10 +85,11 @@
      * Constructs an instance that's initialized with the contents of the
      * specified {@code String}. The capacity of the new builder will be the
      * length of the {@code String} plus 16.
-     * 
+     *
      * @param str
      *            the {@code String} to copy into the builder.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code str} is {@code null}.
      */
     public StringBuilder(String str) {
         super(str);
@@ -99,12 +99,11 @@
      * Appends the string representation of the specified {@code boolean} value.
      * The {@code boolean} value is converted to a String according to the rule
      * defined by {@link String#valueOf(boolean)}.
-     * 
+     *
      * @param b
      *            the {@code boolean} value to append.
      * @return this builder.
      * @see String#valueOf(boolean)
-     * @since Android 1.0
      */
     public StringBuilder append(boolean b) {
         append0(b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -115,12 +114,11 @@
      * Appends the string representation of the specified {@code char} value.
      * The {@code char} value is converted to a string according to the rule
      * defined by {@link String#valueOf(char)}.
-     * 
+     *
      * @param c
      *            the {@code char} value to append.
      * @return this builder.
      * @see String#valueOf(char)
-     * @since Android 1.0
      */
     public StringBuilder append(char c) {
         append0(c);
@@ -131,12 +129,11 @@
      * Appends the string representation of the specified {@code int} value. The
      * {@code int} value is converted to a string according to the rule defined
      * by {@link String#valueOf(int)}.
-     * 
+     *
      * @param i
      *            the {@code int} value to append.
      * @return this builder.
      * @see String#valueOf(int)
-     * @since Android 1.0
      */
     public StringBuilder append(int i) {
         append0(Integer.toString(i));
@@ -147,12 +144,11 @@
      * Appends the string representation of the specified {@code long} value.
      * The {@code long} value is converted to a string according to the rule
      * defined by {@link String#valueOf(long)}.
-     * 
+     *
      * @param lng
      *            the {@code long} value.
      * @return this builder.
      * @see String#valueOf(long)
-     * @since Android 1.0
      */
     public StringBuilder append(long lng) {
         append0(Long.toString(lng));
@@ -163,12 +159,11 @@
      * Appends the string representation of the specified {@code float} value.
      * The {@code float} value is converted to a string according to the rule
      * defined by {@link String#valueOf(float)}.
-     * 
+     *
      * @param f
      *            the {@code float} value to append.
      * @return this builder.
      * @see String#valueOf(float)
-     * @since Android 1.0
      */
     public StringBuilder append(float f) {
         append0(Float.toString(f));
@@ -179,12 +174,11 @@
      * Appends the string representation of the specified {@code double} value.
      * The {@code double} value is converted to a string according to the rule
      * defined by {@link String#valueOf(double)}.
-     * 
+     *
      * @param d
      *            the {@code double} value to append.
      * @return this builder.
      * @see String#valueOf(double)
-     * @since Android 1.0
      */
     public StringBuilder append(double d) {
         append0(Double.toString(d));
@@ -195,12 +189,11 @@
      * Appends the string representation of the specified {@code Object}.
      * The {@code Object} value is converted to a string according to the rule
      * defined by {@link String#valueOf(Object)}.
-     * 
+     *
      * @param obj
      *            the {@code Object} to append.
      * @return this builder.
      * @see String#valueOf(Object)
-     * @since Android 1.0
      */
     public StringBuilder append(Object obj) {
         if (obj == null) {
@@ -214,11 +207,10 @@
     /**
      * Appends the contents of the specified string. If the string is {@code
      * null}, then the string {@code "null"} is appended.
-     * 
+     *
      * @param str
      *            the string to append.
      * @return this builder.
-     * @since Android 1.0
      */
     public StringBuilder append(String str) {
         append0(str);
@@ -229,11 +221,10 @@
      * Appends the contents of the specified {@code StringBuffer}. If the
      * StringBuffer is {@code null}, then the string {@code "null"} is
      * appended.
-     * 
+     *
      * @param sb
      *            the {@code StringBuffer} to append.
      * @return this builder.
-     * @since Android 1.0
      */
     public StringBuilder append(StringBuffer sb) {
         if (sb == null) {
@@ -248,12 +239,11 @@
      * Appends the string representation of the specified {@code char[]}.
      * The {@code char[]} is converted to a string according to the rule
      * defined by {@link String#valueOf(char[])}.
-     * 
+     *
      * @param ch
      *            the {@code char[]} to append..
      * @return this builder.
      * @see String#valueOf(char[])
-     * @since Android 1.0
      */
     public StringBuilder append(char[] ch) {
         append0(ch);
@@ -264,7 +254,7 @@
      * Appends the string representation of the specified subset of the {@code
      * char[]}. The {@code char[]} value is converted to a String according to
      * the rule defined by {@link String#valueOf(char[],int,int)}.
-     * 
+     *
      * @param str
      *            the {@code char[]} to append.
      * @param offset
@@ -276,7 +266,6 @@
      *             if {@code offset} and {@code len} do not specify a valid
      *             subsequence.
      * @see String#valueOf(char[],int,int)
-     * @since Android 1.0
      */
     public StringBuilder append(char[] str, int offset, int len) {
         append0(str, offset, len);
@@ -287,11 +276,10 @@
      * Appends the string representation of the specified {@code CharSequence}.
      * If the {@code CharSequence} is {@code null}, then the string {@code
      * "null"} is appended.
-     * 
+     *
      * @param csq
      *            the {@code CharSequence} to append.
      * @return this builder.
-     * @since Android 1.0
      */
     public StringBuilder append(CharSequence csq) {
         if (csq == null) {
@@ -306,7 +294,7 @@
      * Appends the string representation of the specified subsequence of the
      * {@code CharSequence}. If the {@code CharSequence} is {@code null}, then
      * the string {@code "null"} is used to extract the subsequence from.
-     * 
+     *
      * @param csq
      *            the {@code CharSequence} to append.
      * @param start
@@ -318,7 +306,6 @@
      *             if {@code start} or {@code end} are negative, {@code start}
      *             is greater than {@code end} or {@code end} is greater than
      *             the length of {@code csq}.
-     * @since Android 1.0
      */
     public StringBuilder append(CharSequence csq, int start, int end) {
         append0(csq, start, end);
@@ -328,12 +315,11 @@
     /**
      * Appends the encoded Unicode code point. The code point is converted to a
      * {@code char[]} as defined by {@link Character#toChars(int)}.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to encode and append.
      * @return this builder.
      * @see Character#toChars(int)
-     * @since Android 1.0
      */
     public StringBuilder appendCodePoint(int codePoint) {
         append0(Character.toChars(codePoint));
@@ -352,7 +338,6 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code start} is less than zero, greater than the current
      *             length or greater than {@code end}.
-     * @since Android 1.0
      */
     public StringBuilder delete(int start, int end) {
         delete0(start, end);
@@ -369,7 +354,6 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code index} is less than zero or is greater than or
      *             equal to the current length.
-     * @since Android 1.0
      */
     public StringBuilder deleteCharAt(int index) {
         deleteCharAt0(index);
@@ -381,7 +365,7 @@
      * at the specified {@code offset}. The {@code boolean} value is converted
      * to a string according to the rule defined by
      * {@link String#valueOf(boolean)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param b
@@ -391,7 +375,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length}.
      * @see String#valueOf(boolean)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, boolean b) {
         insert0(offset, b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -402,7 +385,7 @@
      * Inserts the string representation of the specified {@code char} value at
      * the specified {@code offset}. The {@code char} value is converted to a
      * string according to the rule defined by {@link String#valueOf(char)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param c
@@ -412,7 +395,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(char)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, char c) {
         insert0(offset, c);
@@ -423,7 +405,7 @@
      * Inserts the string representation of the specified {@code int} value at
      * the specified {@code offset}. The {@code int} value is converted to a
      * String according to the rule defined by {@link String#valueOf(int)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param i
@@ -433,7 +415,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(int)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, int i) {
         insert0(offset, Integer.toString(i));
@@ -444,7 +425,7 @@
      * Inserts the string representation of the specified {@code long} value at
      * the specified {@code offset}. The {@code long} value is converted to a
      * String according to the rule defined by {@link String#valueOf(long)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param l
@@ -454,7 +435,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {code length()}.
      * @see String#valueOf(long)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, long l) {
         insert0(offset, Long.toString(l));
@@ -465,7 +445,7 @@
      * Inserts the string representation of the specified {@code float} value at
      * the specified {@code offset}. The {@code float} value is converted to a
      * string according to the rule defined by {@link String#valueOf(float)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param f
@@ -475,7 +455,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(float)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, float f) {
         insert0(offset, Float.toString(f));
@@ -487,7 +466,7 @@
      * at the specified {@code offset}. The {@code double} value is converted
      * to a String according to the rule defined by
      * {@link String#valueOf(double)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param d
@@ -497,7 +476,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(double)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, double d) {
         insert0(offset, Double.toString(d));
@@ -508,7 +486,7 @@
      * Inserts the string representation of the specified {@code Object} at the
      * specified {@code offset}. The {@code Object} value is converted to a
      * String according to the rule defined by {@link String#valueOf(Object)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param obj
@@ -518,7 +496,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(Object)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, Object obj) {
         insert0(offset, obj == null ? "null" : obj.toString()); //$NON-NLS-1$
@@ -528,7 +505,7 @@
     /**
      * Inserts the specified string at the specified {@code offset}. If the
      * specified string is null, then the String {@code "null"} is inserted.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param str
@@ -537,7 +514,6 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, String str) {
         insert0(offset, str);
@@ -548,7 +524,7 @@
      * Inserts the string representation of the specified {@code char[]} at the
      * specified {@code offset}. The {@code char[]} value is converted to a
      * String according to the rule defined by {@link String#valueOf(char[])}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param ch
@@ -558,7 +534,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(char[])
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, char[] ch) {
         insert0(offset, ch);
@@ -570,7 +545,7 @@
      * {@code char[]} at the specified {@code offset}. The {@code char[]} value
      * is converted to a String according to the rule defined by
      * {@link String#valueOf(char[],int,int)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param str
@@ -585,7 +560,6 @@
      *             {@code length()}, or {@code strOffset} and {@code strLen} do
      *             not specify a valid subsequence.
      * @see String#valueOf(char[],int,int)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, char[] str, int strOffset,
             int strLen) {
@@ -598,7 +572,7 @@
      * at the specified {@code offset}. The {@code CharSequence} is converted
      * to a String as defined by {@link CharSequence#toString()}. If {@code s}
      * is {@code null}, then the String {@code "null"} is inserted.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param s
@@ -608,7 +582,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see CharSequence#toString()
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, CharSequence s) {
         insert0(offset, s == null ? "null" : s.toString()); //$NON-NLS-1$
@@ -622,7 +595,7 @@
      * {@link CharSequence#subSequence(int, int)}. If the {@code CharSequence}
      * is {@code null}, then the string {@code "null"} is used to determine the
      * subsequence.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param s
@@ -637,7 +610,6 @@
      *             {@code length()}, or {@code start} and {@code end} do not
      *             specify a valid subsequence.
      * @see CharSequence#subSequence(int, int)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, CharSequence s, int start, int end) {
         insert0(offset, s, start, end);
@@ -658,7 +630,8 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code start} is negative, greater than the current
      *             {@code length()} or greater than {@code end}.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code str} is {@code null}.
      */
     public StringBuilder replace(int start, int end, String str) {
         replace0(start, end, str);
@@ -669,7 +642,6 @@
      * Reverses the order of characters in this builder.
      * 
      * @return this buffer.
-     * @since Android 1.0
      */
     public StringBuilder reverse() {
         reverse0();
@@ -680,7 +652,6 @@
      * Returns the contents of this builder.
      * 
      * @return the string representation of the data in this builder.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -695,7 +666,7 @@
     /**
      * Reads the state of a {@code StringBuilder} from the passed stream and
      * restores it to this instance.
-     * 
+     *
      * @param in
      *            the stream to read the state from.
      * @throws IOException
@@ -713,7 +684,7 @@
 
     /**
      * Writes the state of this object to the stream passed.
-     * 
+     *
      * @param out
      *            the stream to write the state to.
      * @throws IOException
diff --git a/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java b/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java
index a2fca9a..b3fbf7e 100644
--- a/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java
+++ b/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java
@@ -23,8 +23,6 @@
 /**
  * Thrown when the a string is indexed with a value less than zero, or greater
  * than or equal to the size of the array.
- * 
- * @since Android 1.0
  */
 public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException {
 
@@ -33,8 +31,6 @@
     /**
      * Constructs a new {@code StringIndexOutOfBoundsException} that includes
      * the current stack trace.
-     * 
-     * @since Android 1.0
      */
     public StringIndexOutOfBoundsException() {
         super();
@@ -47,7 +43,6 @@
      * 
      * @param index
      *            the index which is out of bounds.
-     * @since Android 1.0
      */    
     public StringIndexOutOfBoundsException(int index) {
         super(Msg.getString("K0055", index)); //$NON-NLS-1$
@@ -59,7 +54,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public StringIndexOutOfBoundsException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/SuppressWarnings.java b/luni/src/main/java/java/lang/SuppressWarnings.java
index d3b4289..1ff0e42 100644
--- a/luni/src/main/java/java/lang/SuppressWarnings.java
+++ b/luni/src/main/java/java/lang/SuppressWarnings.java
@@ -1,12 +1,12 @@
-/*
- * Copyright (C) 2007 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
- *
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -16,15 +16,9 @@
 
 package java.lang;
 
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
+import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 /**
@@ -35,18 +29,17 @@
  * <p>
  * It is recommended that programmers always use this annotation on the most
  * deeply nested element where it is actually needed.
- * </p>
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
-@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
-@Retention(value=SOURCE)
-public @interface SuppressWarnings
-{
+@Target( { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD,
+        ElementType.PARAMETER, ElementType.CONSTRUCTOR,
+        ElementType.LOCAL_VARIABLE })
+@Retention(RetentionPolicy.SOURCE)
+public @interface SuppressWarnings {
+
     /**
      * The list of warnings a compiler should not issue.
-     * 
-     * @since Android 1.0
      */
-    String[] value();
+    public String[] value();
 }
diff --git a/luni/src/main/java/java/lang/ThreadDeath.java b/luni/src/main/java/java/lang/ThreadDeath.java
index e4f2cc2..3006865 100644
--- a/luni/src/main/java/java/lang/ThreadDeath.java
+++ b/luni/src/main/java/java/lang/ThreadDeath.java
@@ -20,8 +20,6 @@
 /**
  * ThreadDeath is thrown when a thread stops executing. It is used to aid in the
  * orderly unrolling of the thread's stack (eg. cleanup of monitors).
- * 
- * @since Android 1.0
  */
 public class ThreadDeath extends Error {
 
@@ -31,8 +29,6 @@
      * Constructs a new instance of this class. Note that in the case of
      * ThreadDeath, the stacktrace may <em>not</em> be filled in a way which
      * allows a stack trace to be printed.
-     * 
-     * @since Android 1.0
      */
     public ThreadDeath() {
     }
diff --git a/luni/src/main/java/java/lang/ThreadLocal.java b/luni/src/main/java/java/lang/ThreadLocal.java
index 58e85be..90250b3 100644
--- a/luni/src/main/java/java/lang/ThreadLocal.java
+++ b/luni/src/main/java/java/lang/ThreadLocal.java
@@ -16,6 +16,12 @@
 
 package java.lang;
 
+/*
+ * Android's thread local is not derived from Harmony's classlib. It is used in
+ * Harmony's DRLVM, however, whose source is here:
+ * http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/
+ */
+
 import java.lang.ref.WeakReference;
 import java.lang.ref.Reference;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -29,7 +35,6 @@
  * 
  * @see java.lang.Thread
  * @author Bob Lee
- * @since Android 1.0
  */
 public class ThreadLocal<T> {
 
@@ -97,6 +102,8 @@
      * is followed by a {@link #get()} before a {@link #set},
      * {@code #get()} will call {@link #initialValue()} and create a new
      * entry with the resulting value.
+     *
+     * @since 1.5
      */
     public void remove() {
         Thread currentThread = Thread.currentThread();
diff --git a/luni/src/main/java/java/lang/TypeNotPresentException.java b/luni/src/main/java/java/lang/TypeNotPresentException.java
index 11ef4c1..d96f766 100644
--- a/luni/src/main/java/java/lang/TypeNotPresentException.java
+++ b/luni/src/main/java/java/lang/TypeNotPresentException.java
@@ -21,8 +21,8 @@
  * type through a string that contains the type's name and the type cannot be
  * found. This exception is an unchecked alternative to
  * {@link java.lang.ClassNotFoundException}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public class TypeNotPresentException extends RuntimeException {
     private static final long serialVersionUID = -5101214195716534496L;
@@ -38,7 +38,6 @@
      *            the fully qualified name of the type that could not be found.
      * @param cause
      *            the optional cause of this exception, may be {@code null}.
-     * @since Android 1.0
      */
     public TypeNotPresentException(String typeName, Throwable cause) {
         super("Type " + typeName + " not present", cause);
diff --git a/luni/src/main/java/java/lang/UnknownError.java b/luni/src/main/java/java/lang/UnknownError.java
index a98a5d4..ecdb008 100644
--- a/luni/src/main/java/java/lang/UnknownError.java
+++ b/luni/src/main/java/java/lang/UnknownError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine must throw an error which does not match any
  * known exceptional condition.
- * 
- * @since Android 1.0
  */
 public class UnknownError extends VirtualMachineError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code UnknownError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public UnknownError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnknownError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/UnsatisfiedLinkError.java b/luni/src/main/java/java/lang/UnsatisfiedLinkError.java
index 489601f..12429a0 100644
--- a/luni/src/main/java/java/lang/UnsatisfiedLinkError.java
+++ b/luni/src/main/java/java/lang/UnsatisfiedLinkError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an attempt is made to invoke a native for which an implementation
  * could not be found.
- * 
- * @since Android 1.0
  */
 public class UnsatisfiedLinkError extends LinkageError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code UnsatisfiedLinkError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public UnsatisfiedLinkError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnsatisfiedLinkError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/UnsupportedClassVersionError.java b/luni/src/main/java/java/lang/UnsupportedClassVersionError.java
index 3ee8f8c..7670f70 100644
--- a/luni/src/main/java/java/lang/UnsupportedClassVersionError.java
+++ b/luni/src/main/java/java/lang/UnsupportedClassVersionError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an attempt is made to load a class with a format version that is
  * not supported by the virtual machine.
- * 
- * @since Android 1.0
  */
 public class UnsupportedClassVersionError extends ClassFormatError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code UnsupportedClassVersionError} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public UnsupportedClassVersionError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnsupportedClassVersionError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/UnsupportedOperationException.java b/luni/src/main/java/java/lang/UnsupportedOperationException.java
index 8b78226..ac27518 100644
--- a/luni/src/main/java/java/lang/UnsupportedOperationException.java
+++ b/luni/src/main/java/java/lang/UnsupportedOperationException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when an unsupported operation is attempted.
- * 
- * @since Android 1.0
  */
 public class UnsupportedOperationException extends RuntimeException {
 
@@ -29,13 +27,8 @@
     /**
      * Constructs a new {@code UnsupportedOperationException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public UnsupportedOperationException() {
-        // BEGIN android-added
-        super();
-        // END android-added
     }
 
     /**
@@ -44,7 +37,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnsupportedOperationException(String detailMessage) {
         super(detailMessage);
@@ -58,7 +50,7 @@
      *            the detail message for this exception.
      * @param cause
      *            the optional cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public UnsupportedOperationException(String message, Throwable cause) {
         super(message, cause);
@@ -70,7 +62,7 @@
      * 
      * @param cause
      *            the optional cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public UnsupportedOperationException(Throwable cause) {
         super((cause == null ? null : cause.toString()), cause);
diff --git a/luni/src/main/java/java/lang/VerifyError.java b/luni/src/main/java/java/lang/VerifyError.java
index ddf4de7..35cf34b 100644
--- a/luni/src/main/java/java/lang/VerifyError.java
+++ b/luni/src/main/java/java/lang/VerifyError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine notices that an attempt is made to load a
  * class which does not pass the class verification phase.
- * 
- * @since Android 1.0
  */
 public class VerifyError extends LinkageError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code VerifyError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public VerifyError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public VerifyError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/VirtualMachineError.java b/luni/src/main/java/java/lang/VirtualMachineError.java
index 107f562..87a6342 100644
--- a/luni/src/main/java/java/lang/VirtualMachineError.java
+++ b/luni/src/main/java/java/lang/VirtualMachineError.java
@@ -23,7 +23,6 @@
  * during the operation of the virtual machine.
  * 
  * @see Error
- * @since Android 1.0
  */
 public abstract class VirtualMachineError extends Error {
 
@@ -32,8 +31,6 @@
     /**
      * Constructs a new {@code VirtualMachineError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public VirtualMachineError() {
         super();
@@ -45,7 +42,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public VirtualMachineError(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/lang/Void.java b/luni/src/main/java/java/lang/Void.java
index 8d06b64..4132e41 100644
--- a/luni/src/main/java/java/lang/Void.java
+++ b/luni/src/main/java/java/lang/Void.java
@@ -21,15 +21,13 @@
 
 /**
  * Placeholder class for the Java keyword {@code void}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.1
  */
 public final class Void extends Object {
     
     /**
      * The {@link Class} object that represents the primitive type {@code void}.
-     * 
-     * @since Android 1.0
      */
     public static final Class<Void> TYPE = lookupType();
 
@@ -48,6 +46,6 @@
         return (Class<Void>) voidType;
     }
 
-    private Void() {
-    }
+	private Void() {
+	}
 }
diff --git a/luni/src/main/java/java/lang/ref/ReferenceQueue.java b/luni/src/main/java/java/lang/ref/ReferenceQueue.java
index eb6280b..ac6d695 100644
--- a/luni/src/main/java/java/lang/ref/ReferenceQueue.java
+++ b/luni/src/main/java/java/lang/ref/ReferenceQueue.java
@@ -16,25 +16,24 @@
  */
 
 // BEGIN android-note
-// This implementation was changed significantly. Changes where not marked.
+// This implementation is quite different from Harmony. Changes are not marked.
 // END android-note
+
 package java.lang.ref;
 
 /**
  * The {@code ReferenceQueue} is the container on which reference objects are
  * enqueued when the garbage collector detects the reachability type specified
  * for the referent.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public class ReferenceQueue<T> {
-    
+
     private Reference<? extends T> head;
 
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public ReferenceQueue() {
         super();
@@ -43,11 +42,9 @@
     /**
      * Returns the next available reference from the queue, removing it in the
      * process. Does not wait for a reference to become available.
-     * 
+     *
      * @return the next available reference, or {@code null} if no reference is
      *         immediately available
-     *            
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public synchronized Reference<? extends T> poll() {
@@ -73,37 +70,31 @@
     /**
      * Returns the next available reference from the queue, removing it in the
      * process. Waits indefinitely for a reference to become available.
-     * 
+     *
      * @return the next available reference
-     * 
+     *
      * @throws InterruptedException
-     *             if the blocking call was interrupted for some reason  
-     *            
-     * @since Android 1.0
+     *             if the blocking call was interrupted for some reason
      */
     public Reference<? extends T> remove() throws InterruptedException {
         return remove(0L);
     }
-    
+
     /**
      * Returns the next available reference from the queue, removing it in the
      * process. Waits for a reference to become available or the given timeout
      * period to elapse, whichever happens first.
-     * 
+     *
      * @param timeout
      *            maximum time (in ms) to spend waiting for a reference object
      *            to become available. A value of zero results in the method
      *            waiting indefinitely.
-     *            
      * @return the next available reference, or {@code null} if no reference
      *         becomes available within the timeout period
-     * 
      * @throws IllegalArgumentException
      *             if the wait period is negative.
      * @throws InterruptedException
-     *             if the blocking call was interrupted for some reason  
-     *            
-     * @since Android 1.0
+     *             if the blocking call was interrupted for some reason
      */
     public synchronized Reference<? extends T> remove(long timeout) throws IllegalArgumentException,
             InterruptedException {
@@ -128,20 +119,20 @@
     }
 
     /**
-     * Enqueues the reference object on the receiver.
-     * 
-     * @param toQueue
+     * Enqueue the reference object on the receiver.
+     *
+     * @param reference
      *            reference object to be enqueued.
-     *            
-     * @since Android 1.0
+     * @return boolean true if reference is enqueued. false if reference failed
+     *         to enqueue.
      */
-    synchronized void enqueue(Reference<? extends T> toQueue) {
+    synchronized void enqueue(Reference<? extends T> reference) {
         if (head == null) {
-            toQueue.queueNext = toQueue;
+            reference.queueNext = reference;
         } else {
-            toQueue.queueNext = head;
+            reference.queueNext = head;
         }
-        head = toQueue;
+        head = reference;
         notify();
     }
 }
diff --git a/luni/src/main/java/java/lang/reflect/AnnotatedElement.java b/luni/src/main/java/java/lang/reflect/AnnotatedElement.java
index 1f081b9..426daba 100644
--- a/luni/src/main/java/java/lang/reflect/AnnotatedElement.java
+++ b/luni/src/main/java/java/lang/reflect/AnnotatedElement.java
@@ -21,8 +21,8 @@
 
 /**
  * This interface provides reflective access to annotation information.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface AnnotatedElement {
 
@@ -33,13 +33,9 @@
      * 
      * @param annotationType
      *            the type of the annotation to search for
-     *            
      * @return the annotation with the specified type or {@code null}
-     * 
      * @throws NullPointerException
      *             if {@code annotationType} is {@code null}
-     * 
-     * @since Android 1.0
      */
     <T extends Annotation> T getAnnotation(Class<T> annotationType);
 
@@ -49,8 +45,6 @@
      * returns a zero length array.
      * 
      * @return an array of all annotations for this element
-     * 
-     * @since Android 1.0
      */
     Annotation[] getAnnotations();
 
@@ -60,8 +54,6 @@
      * method returns a zero length array.
      * 
      * @return an array of annotations declared for this element
-     * 
-     * @since Android 1.0
      */
     Annotation[] getDeclaredAnnotations();
 
@@ -71,13 +63,9 @@
      * 
      * @param annotationType
      *            the type of the annotation to search for
-     *            
      * @return {@code true} if the annotation exists, {@code false} otherwise
-     * 
      * @throws NullPointerException
      *             if {@code annotationType} is {@code null}
-     * 
-     * @since Android 1.0
      */
     boolean isAnnotationPresent(Class<? extends Annotation> annotationType);
 }
diff --git a/luni/src/main/java/java/lang/reflect/GenericArrayType.java b/luni/src/main/java/java/lang/reflect/GenericArrayType.java
index 81fb39f..56f873d 100644
--- a/luni/src/main/java/java/lang/reflect/GenericArrayType.java
+++ b/luni/src/main/java/java/lang/reflect/GenericArrayType.java
@@ -21,22 +21,19 @@
  * This interface represents an array type with a component type that is either
  * a parameterized type or a type variable.
  * 
- * @since Android 1.0
+ * @since 1.5
  */
 public interface GenericArrayType extends Type {
-
     /**
      * Returns the component type of this array.
      *
      * @return the component type of this array
-     * 
+     *
      * @throws TypeNotPresentException
      *             if the component type points to a missing type
      * @throws MalformedParameterizedTypeException
      *             if the component type points to a type that cannot be
      *             instantiated for some reason
-     * 
-     * @since Android 1.0
      */
     Type getGenericComponentType();
-}
+}
\ No newline at end of file
diff --git a/luni/src/main/java/java/lang/reflect/GenericDeclaration.java b/luni/src/main/java/java/lang/reflect/GenericDeclaration.java
index c7cedcf..880350b 100644
--- a/luni/src/main/java/java/lang/reflect/GenericDeclaration.java
+++ b/luni/src/main/java/java/lang/reflect/GenericDeclaration.java
@@ -18,8 +18,8 @@
 
 /**
  * Common interface for language constructs that declare type parameters.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface GenericDeclaration {
 
@@ -28,11 +28,8 @@
      * no type parameters, this method returns a zero length array.
      * 
      * @return the declared type parameters in declaration order
-     * 
      * @throws GenericSignatureFormatError
      *             if the signature is malformed
-     * 
-     * @since Android 1.0
      */
     TypeVariable<?>[] getTypeParameters();
 }
diff --git a/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java b/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java
index bb901fd..c113006 100644
--- a/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java
+++ b/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java
@@ -20,8 +20,8 @@
 /**
  * Indicates that a malformed signature has been encountered via a reflective
  * method.
- *
- * @since Android 1.0
+ * 
+ * @since 1.5
  */
 public class GenericSignatureFormatError extends ClassFormatError {
 
@@ -29,8 +29,6 @@
 
     /**
      * Constructs a new {@code GenericSignatureFormatError} instance.
-     *
-     * @since Android 1.0
      */
     public GenericSignatureFormatError() {
         super();
diff --git a/luni/src/main/java/java/lang/reflect/InvocationHandler.java b/luni/src/main/java/java/lang/reflect/InvocationHandler.java
index b28d535..fe3eaba 100644
--- a/luni/src/main/java/java/lang/reflect/InvocationHandler.java
+++ b/luni/src/main/java/java/lang/reflect/InvocationHandler.java
@@ -21,8 +21,6 @@
  * Implementors of this interface dispatch methods invoked on proxy instances.
  * 
  * @see Proxy
- * 
- * @since Android 1.0
  */
 public interface InvocationHandler {
 
@@ -58,8 +56,6 @@
      *             The exception must match one of the declared exception types
      *             of the invoked method or any unchecked exception type. If not
      *             then an {@code UndeclaredThrowableException} is thrown
-     * 
-     * @since Android 1.0
      */
     public Object invoke(Object proxy, Method method, Object[] args)
             throws Throwable;
diff --git a/luni/src/main/java/java/lang/reflect/InvocationTargetException.java b/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
index 2d69135..6dc44e7 100644
--- a/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
+++ b/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
@@ -23,8 +23,6 @@
  * 
  * @see Method#invoke
  * @see Constructor#newInstance
- * 
- * @since Android 1.0
  */
 public class InvocationTargetException extends Exception {
 
@@ -35,8 +33,6 @@
     /**
      * Constructs a new {@code InvocationTargetException} instance with a
      * {@code null} cause / target exception.
-     * 
-     * @since Android 1.0
      */
     protected InvocationTargetException() {
         super((Throwable) null);
@@ -49,8 +45,6 @@
      * @param exception
      *            the exception which occurred while running the Method or
      *            Constructor
-     *            
-     * @since Android 1.0
      */
     public InvocationTargetException(Throwable exception) {
         super(null, exception);
@@ -66,8 +60,6 @@
      * @param exception
      *            the exception which occurred while running the Method or
      *            Constructor
-     *            
-     * @since Android 1.0
      */
     public InvocationTargetException(Throwable exception, String detailMessage) {
         super(detailMessage, exception);
@@ -78,8 +70,6 @@
      * Returns the target exception, which may be {@code null}.
      * 
      * @return the target exception
-     * 
-     * @since Android 1.0
      */
     public Throwable getTargetException() {
         return target;
@@ -89,8 +79,6 @@
      * Returns the cause of this exception, which may be {@code null}.
      * 
      * @return the cause of this exception
-     * 
-     * @since Android 1.0
      */
     @Override
     public Throwable getCause() {
diff --git a/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java b/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java
index 7dfbc6f..71f2819 100644
--- a/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java
+++ b/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java
@@ -21,7 +21,7 @@
  * Indicates that a malformed parameterized type has been encountered by a
  * reflective method.
  * 
- * @since Android 1.0
+ * @since 1.5
  */
 public class MalformedParameterizedTypeException extends RuntimeException {
 
@@ -29,8 +29,6 @@
 
     /**
      * Constructs a new {@code MalformedParameterizedTypeException} instance.
-     * 
-     * @since Android 1.0
      */
     public MalformedParameterizedTypeException() {
         super();
diff --git a/luni/src/main/java/java/lang/reflect/Member.java b/luni/src/main/java/java/lang/reflect/Member.java
index fb0739f..a91e108 100644
--- a/luni/src/main/java/java/lang/reflect/Member.java
+++ b/luni/src/main/java/java/lang/reflect/Member.java
@@ -8,11 +8,11 @@
  *
  *     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.
+ *  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.lang.reflect;
@@ -23,28 +23,22 @@
  * @see Field
  * @see Constructor
  * @see Method
- * 
- * @since Android 1.0
  */
 public interface Member {
 
     /**
      * Designates all public members of a class or interface (including
      * inherited members).
-     * 
+     *
      * @see java.lang.SecurityManager#checkMemberAccess
-     * 
-     * @since Android 1.0
      */
     public static final int PUBLIC = 0;
 
     /**
      * Designates all declared members of a class or interface (without
      * inherited members).
-     * 
+     *
      * @see java.lang.SecurityManager#checkMemberAccess
-     * 
-     * @since Android 1.0
      */
     public static final int DECLARED = 1;
 
@@ -52,8 +46,6 @@
      * Returns the class that declares this member.
      *
      * @return the declaring class
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     Class getDeclaringClass();
@@ -63,10 +55,8 @@
      * be used to decode the result.
      *
      * @return the modifiers for this member
-     * 
+     *
      * @see Modifier
-     * 
-     * @since Android 1.0
      */
     int getModifiers();
 
@@ -74,8 +64,6 @@
      * Returns the name of this member.
      *
      * @return the name of this member
-     * 
-     * @since Android 1.0
      */
     String getName();
 
@@ -84,8 +72,6 @@
      * introduced by the compiler).
      * 
      * @return {@code true} if this member is synthetic, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     boolean isSynthetic();
 }
diff --git a/luni/src/main/java/java/lang/reflect/Modifier.java b/luni/src/main/java/java/lang/reflect/Modifier.java
index ed201aa..0f9dc98 100644
--- a/luni/src/main/java/java/lang/reflect/Modifier.java
+++ b/luni/src/main/java/java/lang/reflect/Modifier.java
@@ -22,100 +22,74 @@
  *
  * @see Class#getModifiers()
  * @see Member#getModifiers()
- * 
- * @since Android 1.0
  */
 public class Modifier {
 
     /**
      * The {@code int} value representing the {@code public}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int PUBLIC = 0x1;
 
     /**
      * The {@code int} value representing the {@code private}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int PRIVATE = 0x2;
 
     /**
      * The {@code int} value representing the {@code protected}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int PROTECTED = 0x4;
 
     /**
      * The {@code int} value representing the {@code static} modifier.
-     *
-     * @since Android 1.0
      */
     public static final int STATIC = 0x8;
 
     /**
      * The {@code int} value representing the {@code final} modifier.
-     *
-     * @since Android 1.0
      */
     public static final int FINAL = 0x10;
 
     /**
      * The {@code int} value representing the {@code synchronized}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int SYNCHRONIZED = 0x20;
 
     /**
      * The {@code int} value representing the {@code volatile}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int VOLATILE = 0x40;
 
     /**
      * The {@code int} value representing the {@code transient}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int TRANSIENT = 0x80;
 
     /**
      * The {@code int} value representing the {@code native} modifier.
-     *
-     * @since Android 1.0
      */
     public static final int NATIVE = 0x100;
 
     /**
      * The {@code int} value representing the {@code interface}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int INTERFACE = 0x200;
 
     /**
      * The {@code int} value representing the {@code abstract}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int ABSTRACT = 0x400;
 
     /**
      * The {@code int} value representing the {@code strict} modifier.
-     *
-     * @since Android 1.0
      */
     public static final int STRICT = 0x800;
 
@@ -132,8 +106,6 @@
 
     /**
      * Constructs a new {@code Modifier} instance.
-     *
-     * @since Android 1.0
      */
     public Modifier() {
     }
@@ -144,11 +116,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     *            
      * @return {@code true} if the specified modifiers contain the {@code
      *         abstract} modifier, {@code false} otherwise
-     *         
-     * @since Android 1.0
      */
     public static boolean isAbstract(int modifiers) {
         return ((modifiers & ABSTRACT) != 0);
@@ -160,11 +129,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     *            
      * @return {@code true} if the specified modifiers contain the {@code
      *         final} modifier, {@code false} otherwise
-     *         
-     * @since Android 1.0
      */
     public static boolean isFinal(int modifiers) {
         return ((modifiers & FINAL) != 0);
@@ -176,11 +142,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     *
      * @return {@code true} if the specified modifiers contain the {@code
      *         interface} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isInterface(int modifiers) {
         return ((modifiers & INTERFACE) != 0);
@@ -192,11 +155,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         native} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isNative(int modifiers) {
         return ((modifiers & NATIVE) != 0);
@@ -208,11 +168,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         private} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isPrivate(int modifiers) {
         return ((modifiers & PRIVATE) != 0);
@@ -224,11 +181,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         protected} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isProtected(int modifiers) {
         return ((modifiers & PROTECTED) != 0);
@@ -240,11 +194,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         public} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isPublic(int modifiers) {
         return ((modifiers & PUBLIC) != 0);
@@ -256,11 +207,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         static} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isStatic(int modifiers) {
         return ((modifiers & STATIC) != 0);
@@ -272,11 +220,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         strict} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isStrict(int modifiers) {
         return ((modifiers & STRICT) != 0);
@@ -288,11 +233,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         synchronized} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isSynchronized(int modifiers) {
         return ((modifiers & SYNCHRONIZED) != 0);
@@ -304,11 +246,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         transient} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isTransient(int modifiers) {
         return ((modifiers & TRANSIENT) != 0);
@@ -320,11 +259,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         volatile} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isVolatile(int modifiers) {
         return ((modifiers & VOLATILE) != 0);
@@ -339,10 +275,7 @@
      *
      * @param modifiers
      *            the modifiers to print
-     * 
      * @return a printable representation of the modifiers
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("nls")
     public static java.lang.String toString(int modifiers) {
diff --git a/luni/src/main/java/java/lang/reflect/ParameterizedType.java b/luni/src/main/java/java/lang/reflect/ParameterizedType.java
index 3d03921..91f2520 100644
--- a/luni/src/main/java/java/lang/reflect/ParameterizedType.java
+++ b/luni/src/main/java/java/lang/reflect/ParameterizedType.java
@@ -18,10 +18,10 @@
 package java.lang.reflect;
 
 /**
- * This interface represents a parameterized type such as {@code 
+ * This interface represents a parameterized type such as {@code
  * 'Set&lt;String&gt;'}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface ParameterizedType extends Type {
 
@@ -32,25 +32,23 @@
      * parameterized type, this method returns a zero length array. The generic
      * type of the following {@code field} declaration is an example for a
      * parameterized type without type arguments.
-     * 
+     *
      * <pre>
      * A&lt;String&gt;.B field;
-     * 
+     *
      * class A&lt;T&gt; {
      *     class B {
      *     }
      * }</pre>
-     * 
-     * 
+     *
+     *
      * @return the actual type arguments
-     * 
+     *
      * @throws TypeNotPresentException
      *             if one of the type arguments cannot be found
      * @throws MalformedParameterizedTypeException
      *             if one of the type arguments cannot be instantiated for some
      *             reason
-     * 
-     * @since Android 1.0
      */
     Type[] getActualTypeArguments();
 
@@ -59,13 +57,11 @@
      * {@code null} is returned if this is a top-level type.
      * 
      * @return the owner type or {@code null} if this is a top-level type
-     * 
+     *
      * @throws TypeNotPresentException
      *             if one of the type arguments cannot be found
      * @throws MalformedParameterizedTypeException
      *             if the owner type cannot be instantiated for some reason
-     * 
-     * @since Android 1.0
      */
     Type getOwnerType();
 
@@ -73,10 +69,8 @@
      * Returns the declaring type of this parameterized type.
      * <p>
      * The raw type of {@code Set&lt;String&gt; field;} is {@code Set}.
-     * 
+     *
      * @return the raw type of this parameterized type
-     * 
-     * @since Android 1.0
      */
     Type getRawType();
 }
diff --git a/luni/src/main/java/java/lang/reflect/Proxy.java b/luni/src/main/java/java/lang/reflect/Proxy.java
index 29d15c5..cc0c956 100644
--- a/luni/src/main/java/java/lang/reflect/Proxy.java
+++ b/luni/src/main/java/java/lang/reflect/Proxy.java
@@ -35,8 +35,7 @@
  * invocations to an {@code InvocationHandler}.
  *
  * @see InvocationHandler
- * 
- * @since Android 1.0
+ * @since 1.3
  */
 public class Proxy implements Serializable {
 
@@ -52,8 +51,6 @@
 
     /**
      * The invocation handler on which the method calls are dispatched.
-     *
-     * @since Android 1.0
      */
     protected InvocationHandler h;
 
@@ -64,11 +61,9 @@
     /**
      * Constructs a new {@code Proxy} instance with the specified invocation
      * handler.
-     * 
+     *
      * @param h
      *            the invocation handler for the newly created proxy
-     *            
-     * @since Android 1.0
      */
     protected Proxy(InvocationHandler h) {
         this.h = h;
@@ -81,24 +76,20 @@
      * different order result in different generated classes. The interfaces
      * must be visible from the supplied class loader; no duplicates are
      * permitted. All non-public interfaces must be defined in the same package.
-     * 
+     *
      * @param loader
      *            the class loader that will define the proxy class
      * @param interfaces
      *            an array of {@code Class} objects, each one identifying an
      *            interface that will be implemented by the returned proxy
      *            class
-     * 
      * @return a proxy class that implements all of the interfaces referred to
      *         in the contents of {@code interfaces}
-     * 
      * @throws IllegalArgumentException
      *                if any of the interface restrictions are violated
      * @throws NullPointerException
      *                if either {@code interfaces} or any of its elements are
      *                {@code null}
-     * 
-     * @since Android 1.0
      */
     public static Class<?> getProxyClass(ClassLoader loader,
             Class<?>... interfaces) throws IllegalArgumentException {
@@ -174,19 +165,17 @@
             WeakReference<Class<?>> ref = interfaceCache.get(interfaceKey);
             if (ref == null) {
                 String nextClassName = "$Proxy" + NextClassNameIndex++; //$NON-NLS-1$
-                if (commonPackageName != null) {
+                if (commonPackageName != null && commonPackageName.length() > 0) {
                     nextClassName = commonPackageName + "." + nextClassName; //$NON-NLS-1$
                 }
                 // BEGIN android-changed
-                //byte[] classFileBytes = ProxyClassFile.generateBytes(
-                //        nextClassName, interfaces);
-                // END android-changed
+                // byte[] classFileBytes = ProxyClassFile.generateBytes(
+                //         nextClassName, interfaces);
+                // newClass = defineClassImpl(loader, nextClassName.replace('.',
+                //         '/'), classFileBytes);
                 if (loader == null) {
                     loader = ClassLoader.getSystemClassLoader();
                 }
-                // BEGIN android-changed
-                //newClass = defineClassImpl(loader, nextClassName.replace('.',
-                //        '/'), classFileBytes);
                 newClass = generateProxy(nextClassName.replace('.', '/'),
                         interfaces, loader);
                 // END android-changed
@@ -200,6 +189,10 @@
                 }
             } else {
                 newClass = ref.get();
+                assert newClass != null : "\ninterfaceKey=\"" + interfaceKey + "\""
+                                        + "\nloaderCache=\"" + loaderCache + "\""
+                                        + "\nintfCache=\"" + interfaceCache + "\""
+                                        + "\nproxyCache=\"" + proxyCache + "\"";
             }
             return newClass;
         }
@@ -211,7 +204,7 @@
      * the specified invocation handler. The interfaces must be visible from the
      * supplied class loader; no duplicates are permitted. All non-public
      * interfaces must be defined in the same package.
-     * 
+     *
      * @param loader
      *            the class loader that will define the proxy class
      * @param interfaces
@@ -221,15 +214,11 @@
      * @param h
      *            the invocation handler that handles the dispatched method
      *            invocations
-     * 
      * @return a new proxy object that delegates to the handler {@code h}
-     * 
      * @throws IllegalArgumentException
      *                if any of the interface restrictions are violated
      * @throws NullPointerException
      *                if the interfaces or any of its elements are null
-     * 
-     * @since Android 1.0
      */
     public static Object newProxyInstance(ClassLoader loader,
             Class<?>[] interfaces, InvocationHandler h)
@@ -260,17 +249,13 @@
     /**
      * Indicates whether or not the specified class is a dynamically generated
      * proxy class.
-     * 
+     *
      * @param cl
      *            the class
-     * 
      * @return {@code true} if the class is a proxy class, {@code false}
      *         otherwise
-     * 
      * @throws NullPointerException
      *                if the class is {@code null}
-     * 
-     * @since Android 1.0
      */
     public static boolean isProxyClass(Class<?> cl) {
         if (cl == null) {
@@ -283,16 +268,12 @@
 
     /**
      * Returns the invocation handler of the specified proxy instance.
-     * 
+     *
      * @param proxy
      *            the proxy instance
-     * 
      * @return the invocation handler of the specified proxy instance
-     * 
      * @throws IllegalArgumentException
      *                if the supplied {@code proxy} is not a proxy object
-     * 
-     * @since Android 1.0
      */
     public static InvocationHandler getInvocationHandler(Object proxy)
             throws IllegalArgumentException {
diff --git a/luni/src/main/java/java/lang/reflect/ReflectPermission.java b/luni/src/main/java/java/lang/reflect/ReflectPermission.java
index b568663..93eef39 100644
--- a/luni/src/main/java/java/lang/reflect/ReflectPermission.java
+++ b/luni/src/main/java/java/lang/reflect/ReflectPermission.java
@@ -22,8 +22,6 @@
 /**
  * A {@code ReflectPermission} object represents a permission to access
  * operations in the reflection layer.
- * 
- * @since Android 1.0
  */
 public final class ReflectPermission extends BasicPermission {
 
@@ -35,13 +33,10 @@
      * 
      * @param permissionName
      *            the name of the new permission
-     *            
      * @throws IllegalArgumentException
      *             if {@code name} is empty
      * @throws NullPointerException
      *             if {@code name} is {@code null}
-     * 
-     * @since Android 1.0
      */
     public ReflectPermission(String permissionName) {
         super(permissionName);
@@ -55,13 +50,10 @@
      *            the name of the new permission
      * @param actions
      *            this parameter will be ignored
-     * 
      * @throws IllegalArgumentException
      *             if {@code name} is empty
      * @throws NullPointerException
      *             if {@code name} is {@code null}
-     * 
-     * @since Android 1.0
      */
     public ReflectPermission(String name, String actions) {
         super(name, actions);
diff --git a/luni/src/main/java/java/lang/reflect/Type.java b/luni/src/main/java/java/lang/reflect/Type.java
index abd4978..a057088 100644
--- a/luni/src/main/java/java/lang/reflect/Type.java
+++ b/luni/src/main/java/java/lang/reflect/Type.java
@@ -18,8 +18,8 @@
 
 /**
  * Common interface implemented by all Java types.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface Type {
     // Empty
diff --git a/luni/src/main/java/java/lang/reflect/TypeVariable.java b/luni/src/main/java/java/lang/reflect/TypeVariable.java
index 99aca77..e3f8c1d 100644
--- a/luni/src/main/java/java/lang/reflect/TypeVariable.java
+++ b/luni/src/main/java/java/lang/reflect/TypeVariable.java
@@ -17,15 +17,14 @@
 package java.lang.reflect;
 
 /**
- * This interface represents a type variables such as {@code 'T'} in {@code 
- * 'public interface Comparable&lt;T&gt;'}, the bounded {@code 'T'} in {@code 
+ * This interface represents a type variables such as {@code 'T'} in {@code
+ * 'public interface Comparable&lt;T&gt;'}, the bounded {@code 'T'} in {@code
  * 'public interface A&lt;T extends Number&gt;'} or the multiple bounded {@code
  * 'T'} in {@code 'public interface B&lt;T extends Number & Cloneable&gt;'}.
- * 
+ *
  * @param <D>
  *            the generic declaration that declares this type variable
- * 
- * @since Android 1.0
+ * @since 1.5
  */
 public interface TypeVariable<D extends GenericDeclaration> extends Type {
 
@@ -33,15 +32,13 @@
      * Returns the upper bounds of this type variable. {@code Object} is the
      * implicit upper bound if no other bounds are declared.
      *
-     * @return the upper bounds of this type variable 
-     * 
+     * @return the upper bounds of this type variable
+     *
      * @throws TypeNotPresentException
      *             if any of the bounds points to a missing type
      * @throws MalformedParameterizedTypeException
      *             if any of the bounds points to a type that cannot be
      *             instantiated for some reason
-     * 
-     * @since Android 1.0
      */
     Type[] getBounds();
 
@@ -49,8 +46,6 @@
      * Returns the language construct that declares this type variable.
      *
      * @return the generic declaration
-     * 
-     * @since Android 1.0
      */
     D getGenericDeclaration();
 
@@ -59,8 +54,6 @@
      * code.
      *
      * @return the name of this type variable
-     * 
-     * @since Android 1.0
      */
     String getName();
 }
diff --git a/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java b/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java
index 108f98a..bd5adfa 100644
--- a/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java
+++ b/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java
@@ -22,8 +22,6 @@
  * an InvocationHandler.
  *
  * @see java.lang.reflect.InvocationHandler#invoke
- *
- * @since Android 1.0
  */
 public class UndeclaredThrowableException extends RuntimeException {
 
@@ -37,8 +35,6 @@
      * 
      * @param exception
      *            the undeclared, checked exception that occurred
-     * 
-     * @since Android 1.0
      */
     public UndeclaredThrowableException(Throwable exception) {
         super();
@@ -54,8 +50,6 @@
      *            the detail message for the exception
      * @param exception
      *            the undeclared, checked exception that occurred
-     * 
-     * @since Android 1.0
      */
     public UndeclaredThrowableException(Throwable exception,
             String detailMessage) {
@@ -69,8 +63,6 @@
      * {@code null}.
      *
      * @return the undeclared, checked exception that occurred
-     * 
-     * @since Android 1.0
      */
     public Throwable getUndeclaredThrowable() {
         return undeclaredThrowable;
@@ -81,8 +73,6 @@
      * {@code null}.
      *
      * @return the undeclared, checked exception that occurred
-     * 
-     * @since Android 1.0
      */
     @Override
     public Throwable getCause() {
diff --git a/luni/src/main/java/java/lang/reflect/WildcardType.java b/luni/src/main/java/java/lang/reflect/WildcardType.java
index 72a022d..affd526 100644
--- a/luni/src/main/java/java/lang/reflect/WildcardType.java
+++ b/luni/src/main/java/java/lang/reflect/WildcardType.java
@@ -22,24 +22,21 @@
  * {@code '?'}, the upper bounded wildcard {@code '? extends Closeable'}, the
  * multiple upper bounded wildcard {@code '? extends Closeable & Flushable'} or
  * the lower bounded wildcard {@code '? super OutputStream'}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface WildcardType extends Type {
-    
     /**
      * Returns the array of types that represent the upper bounds of this type.
      * The default upper bound is {@code Object}.
      *
      * @return an array containing the upper bounds types
-     * 
+     *
      * @throws TypeNotPresentException
      *             if any of the bounds points to a missing type
      * @throws MalformedParameterizedTypeException
      *             if any bound points to a type that cannot be instantiated for
      *             some reason
-     * 
-     * @since Android 1.0
      */
     Type[] getUpperBounds();
 
@@ -48,16 +45,14 @@
      * The default lower bound is {@code null}, in which case an empty array is
      * returned. Since only one lower bound is allowed, the returned array's
      * length will never exceed one.
-     * 
+     *
      * @return an array containing the lower bounds types
-     * 
+     *
      * @throws TypeNotPresentException
      *             if any of the bounds points to a missing type
      * @throws MalformedParameterizedTypeException
      *             if any of the bounds points to a type that cannot be
      *             instantiated for some reason
-     * 
-     * @since Android 1.0
      */
     Type[] getLowerBounds();
 }
diff --git a/luni/src/main/java/java/net/Authenticator.java b/luni/src/main/java/java/net/Authenticator.java
index 1eea8d8..75d68fa 100644
--- a/luni/src/main/java/java/net/Authenticator.java
+++ b/luni/src/main/java/java/net/Authenticator.java
@@ -27,7 +27,6 @@
  * 
  * @see #setDefault
  * @see #getPasswordAuthentication
- * @since Android 1.0
  */
 public abstract class Authenticator {
 
@@ -63,10 +62,8 @@
      * default which is {@code null}.
      * <p>
      * Returns {@code null} by default.
-     * </p>
-     * 
+     *
      * @return collected password authentication data.
-     * @since Android 1.0
      */
     protected PasswordAuthentication getPasswordAuthentication() {
         return null;
@@ -76,7 +73,6 @@
      * Returns the port of the connection that requests authorization.
      * 
      * @return port of the connection.
-     * @since Android 1.0
      */
     protected final int getRequestingPort() {
         return this.port;
@@ -87,7 +83,6 @@
      * {@code null} if unknown.
      * 
      * @return address of the connection.
-     * @since Android 1.0
      */
     protected final InetAddress getRequestingSite() {
         return this.addr;
@@ -98,7 +93,6 @@
      * authorization.
      * 
      * @return prompt string of the connection.
-     * @since Android 1.0
      */
     protected final String getRequestingPrompt() {
         return this.prompt;
@@ -108,7 +102,6 @@
      * Returns the protocol of the connection that requests authorization.
      * 
      * @return protocol of the connection.
-     * @since Android 1.0
      */
     protected final String getRequestingProtocol() {
         return this.protocol;
@@ -119,7 +112,6 @@
      * example HTTP Basic Authentication.
      * 
      * @return scheme of the connection.
-     * @since Android 1.0
      */
     protected final String getRequestingScheme() {
         return this.scheme;
@@ -145,7 +137,6 @@
      * @throws SecurityException
      *             if a security manager denies the password authentication
      *             permission.
-     * @since Android 1.0
      */
     public static synchronized PasswordAuthentication requestPasswordAuthentication(
             InetAddress rAddr, int rPort, String rProtocol, String rPrompt,
@@ -182,7 +173,6 @@
      * @throws SecurityException
      *             if a security manager denies the password authentication
      *             permission.
-     * @since Android 1.0
      */
     public static void setDefault(Authenticator a) {
         SecurityManager sm = System.getSecurityManager();
@@ -214,7 +204,6 @@
      * @throws SecurityException
      *             if a security manager denies the password authentication
      *             permission.
-     * @since Android 1.0
      */
     public static synchronized PasswordAuthentication requestPasswordAuthentication(
             String rHost, InetAddress rAddr, int rPort, String rProtocol,
@@ -244,9 +233,8 @@
     /**
      * Returns the host name of the connection that requests authentication or
      * {@code null} if unknown.
-     * 
+     *
      * @return name of the requesting host or {@code null}.
-     * @since Android 1.0
      */
     protected final String getRequestingHost() {
         return host;
@@ -278,7 +266,6 @@
      * @throws SecurityException
      *             if a security manager denies the password authentication
      *             permission.
-     * @since Android 1.0
      */
     public static PasswordAuthentication requestPasswordAuthentication(
             String rHost, InetAddress rAddr, int rPort, String rProtocol,
@@ -312,7 +299,6 @@
      * Returns the URL of the authentication request.
      * 
      * @return authentication request url.
-     * @since Android 1.0
      */
     protected URL getRequestingURL() {
         return url;
@@ -322,7 +308,6 @@
      * Returns the type of this request, it can be {@code PROXY} or {@code SERVER}.
      * 
      * @return RequestorType of the authentication request.
-     * @since Android 1.0
      */
     protected Authenticator.RequestorType getRequestorType() {
         return rt;
@@ -330,8 +315,6 @@
 
     /**
      * Enumeration class for the origin of the authentication request.
-     * 
-     * @since Android 1.0
      */
     public enum RequestorType {
 
diff --git a/luni/src/main/java/java/net/BindException.java b/luni/src/main/java/java/net/BindException.java
index 69be315..48f1cf6 100644
--- a/luni/src/main/java/java/net/BindException.java
+++ b/luni/src/main/java/java/net/BindException.java
@@ -20,8 +20,6 @@
 /**
  * A {@code BindException} is thrown when a process cannot bind a local
  * address/port, either because it is already bound or reserved by the OS.
- * 
- * @since Android 1.0
  */
 public class BindException extends SocketException {
 
@@ -29,8 +27,6 @@
 
     /**
      * Constructs a new instance with its walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public BindException() {
         super();
@@ -41,7 +37,6 @@
      * 
      * @param detailMessage
      *            detail message of the exception.
-     * @since Android 1.0
      */
     public BindException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/net/CacheRequest.java b/luni/src/main/java/java/net/CacheRequest.java
index 8c67a44..778cb13 100644
--- a/luni/src/main/java/java/net/CacheRequest.java
+++ b/luni/src/main/java/java/net/CacheRequest.java
@@ -29,14 +29,11 @@
  * the current cache store operation is abandoned.
  * 
  * @see ResponseCache
- * @since Android 1.0
  */
 public abstract class CacheRequest {
 
     /**
      * This implementation does nothing.
-     * 
-     * @since Android 1.0
      */
     public CacheRequest() {
         super();
@@ -46,8 +43,6 @@
      * Aborts the current cache operation. If an {@code IOException} occurs
      * while reading the response or writing resource data to the cache, the
      * current cache store operation is aborted.
-     * 
-     * @since Android 1.0
      */
     public abstract void abort();
 
@@ -58,7 +53,6 @@
      * @throws IOException
      *             if an I/O error is encountered during writing response body
      *             operation.
-     * @since Android 1.0
      */
     public abstract OutputStream getBody() throws IOException;
 }
diff --git a/luni/src/main/java/java/net/CacheResponse.java b/luni/src/main/java/java/net/CacheResponse.java
index ae5be44..b0ad094 100644
--- a/luni/src/main/java/java/net/CacheResponse.java
+++ b/luni/src/main/java/java/net/CacheResponse.java
@@ -28,13 +28,10 @@
  * getHeaders()} to fetch the response headers.
  * 
  * @see ResponseCache
- * @since Android 1.0
  */
 public abstract class CacheResponse {
     /**
      * This implementation does nothing.
-     * 
-     * @since Android 1.0
      */
     public CacheResponse() {
         super();
@@ -48,7 +45,6 @@
      * @throws IOException
      *             if an I/O error is encountered while retrieving the response
      *             body.
-     * @since Android 1.0
      */
     public abstract InputStream getBody() throws IOException;
 
@@ -62,7 +58,6 @@
      * @throws IOException
      *             if an I/O error is encountered while retrieving the response
      *             headers.
-     * @since Android 1.0
      */
     public abstract Map<String, List<String>> getHeaders() throws IOException;
 }
diff --git a/luni/src/main/java/java/net/ConnectException.java b/luni/src/main/java/java/net/ConnectException.java
index 42389c7..84cd2bb 100644
--- a/luni/src/main/java/java/net/ConnectException.java
+++ b/luni/src/main/java/java/net/ConnectException.java
@@ -20,8 +20,6 @@
 /**
  * A {@code ConnectException} is thrown if a connection cannot be established to
  * a remote host on a specific port.
- * 
- * @since Android 1.0
  */
 public class ConnectException extends SocketException {
 
@@ -29,8 +27,6 @@
 
     /**
      * This implementation does nothing.
-     * 
-     * @since Android 1.0
      */
     public ConnectException() {
         super();
@@ -38,10 +34,9 @@
 
     /**
      * This implementation does nothing.
-     * 
+     *
      * @param detailMessage
      *            detail message of the exception.
-     * @since Android 1.0
      */
     public ConnectException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/net/ContentHandler.java b/luni/src/main/java/java/net/ContentHandler.java
index 05c6acf..8e0bbb7 100644
--- a/luni/src/main/java/java/net/ContentHandler.java
+++ b/luni/src/main/java/java/net/ContentHandler.java
@@ -23,28 +23,26 @@
  * This class converts the content of a certain format (i.e. a MIME type) into a
  * Java type object. It is created by {@code ContentHandlerFactory}. The data
  * values should be accessed via {@code URL} or {@code URLConnection}.
- * 
+ *
  * @see ContentHandlerFactory
  * @see URL#getContent()
  * @see URLConnection#getContent()
- * @since Android 1.0
  */
 public abstract class ContentHandler {
     /**
      * Returns the object pointed by the specified URL connection {@code uConn}.
-     * 
+     *
      * @param uConn
      *            URL connection that points to the desired object.
      * @return object referred by {@code uConn}.
      * @throws IOException
      *             if an IO error occurs during the retrieval of the object
-     * @since Android 1.0
      */
     public abstract Object getContent(URLConnection uConn) throws IOException;
 
     /**
      * Returns the object pointed by the specified URL connection {@code uConn}.
-     * 
+     *
      * @param uConn
      *            URL connection that points to the desired object.
      * @param types
@@ -53,7 +51,6 @@
      *         content doesn't match one of the specified content types.
      * @throws IOException
      *             if an error occurred while obtaining the content.
-     * @since Android 1.0
      */
     // Class arg not generified in the spec.
     @SuppressWarnings("unchecked")
diff --git a/luni/src/main/java/java/net/ContentHandlerFactory.java b/luni/src/main/java/java/net/ContentHandlerFactory.java
index 1a564ee..3089c04 100644
--- a/luni/src/main/java/java/net/ContentHandlerFactory.java
+++ b/luni/src/main/java/java/net/ContentHandlerFactory.java
@@ -21,7 +21,6 @@
  * Defines a factory which is responsible for creating a {@code ContentHandler}.
  * 
  * @see ContentHandler
- * @since Android 1.0
  */
 public interface ContentHandlerFactory {
     /**
@@ -31,7 +30,6 @@
      *            specifies the content type which is handled by the returned
      *            {@code ContentHandler}.
      * @return content handler object for a specific content type.
-     * @since Android 1.0
      */
     ContentHandler createContentHandler(String contentType);
 }
diff --git a/luni/src/main/java/java/net/CookieHandler.java b/luni/src/main/java/java/net/CookieHandler.java
index 29428ec..05eddde 100644
--- a/luni/src/main/java/java/net/CookieHandler.java
+++ b/luni/src/main/java/java/net/CookieHandler.java
@@ -22,8 +22,6 @@
 
 /**
  * This class provides a way to manage cookies with a HTTP protocol handler.
- * 
- * @since Android 1.0
  */
 public abstract class CookieHandler {
 
@@ -37,9 +35,8 @@
 
     /**
      * Returns the system-wide cookie handler or {@code null} if not set.
-     * 
+     *
      * @return the system-wide cookie handler.
-     * @since Android 1.0
      */
     public static CookieHandler getDefault() {
         SecurityManager sm = System.getSecurityManager();
@@ -51,10 +48,9 @@
 
     /**
      * Sets the system-wide cookie handler.
-     * 
+     *
      * @param cHandler
      *            a cookie handler to set as the system-wide default handler.
-     * @since Android 1.0
      */
     public static void setDefault(CookieHandler cHandler) {
         SecurityManager sm = System.getSecurityManager();
@@ -66,7 +62,7 @@
 
     /**
      * Gets all cookies for a specific URI from the cookie cache.
-     * 
+     *
      * @param uri
      *            a URI to search for applicable cookies.
      * @param requestHeaders
@@ -74,7 +70,6 @@
      * @return an unchangeable map of all appropriate cookies.
      * @throws IOException
      *             if an error occurs during the I/O operation.
-     * @since Android 1.0
      */
     public abstract Map<String, List<String>> get(URI uri,
             Map<String, List<String>> requestHeaders) throws IOException;
@@ -82,14 +77,13 @@
     /**
      * Sets all cookies of a specific URI in the {@code responseHeaders} into
      * the cookie cache.
-     * 
+     *
      * @param uri
      *            the origin URI of the cookies.
      * @param responseHeaders
      *            a list of request headers.
      * @throws IOException
      *             if an error occurs during the I/O operation.
-     * @since Android 1.0
      */
     public abstract void put(URI uri, Map<String, List<String>> responseHeaders)
             throws IOException;
diff --git a/luni/src/main/java/java/net/DatagramPacket.java b/luni/src/main/java/java/net/DatagramPacket.java
index bcc531e..7bbf553 100644
--- a/luni/src/main/java/java/net/DatagramPacket.java
+++ b/luni/src/main/java/java/net/DatagramPacket.java
@@ -25,20 +25,30 @@
  * such as its source or destination host.
  * 
  * @see DatagramSocket
- * @since Android 1.0
  */
 public final class DatagramPacket {
 
     byte[] data;
 
+    /**
+     * Length of the data to be sent or size of data that was received via
+     * DatagramSocket#receive() method call. 
+     */
     int length;
 
+    /**
+     * Size of internal buffer that is used to store received data. Should be
+     * greater or equal to "length" field.
+     */
+    int capacity;
+
     InetAddress address;
 
     int port = -1; // The default port number is -1
 
     int offset = 0;
 
+
     /**
      * Constructs a new {@code DatagramPacket} object to receive data up to
      * {@code length} bytes.
@@ -47,7 +57,6 @@
      *            a byte array to store the read characters.
      * @param length
      *            the length of the data buffer.
-     * @since Android 1.0
      */
     public DatagramPacket(byte[] data, int length) {
         this(data, 0, length);
@@ -63,7 +72,6 @@
      *            the offset of the byte array where the bytes is written.
      * @param length
      *            the length of the data.
-     * @since Android 1.0
      */
     public DatagramPacket(byte[] data, int offset, int length) {
         super();
@@ -75,7 +83,7 @@
      * {@code aPort} of the address {@code host}. The {@code length} must be
      * lesser than or equal to the size of {@code data}. The first {@code
      * length} bytes from the byte array position {@code offset} are sent.
-     * 
+     *
      * @param data
      *            a byte array which stores the characters to be sent.
      * @param offset
@@ -86,7 +94,6 @@
      *            the address of the target host.
      * @param aPort
      *            the port of the target host.
-     * @since Android 1.0
      */
     public DatagramPacket(byte[] data, int offset, int length,
             InetAddress host, int aPort) {
@@ -100,7 +107,7 @@
      * {@code aPort} of the address {@code host}. The {@code length} must be
      * lesser than or equal to the size of {@code data}. The first {@code
      * length} bytes are sent.
-     * 
+     *
      * @param data
      *            a byte array which stores the characters to be sent.
      * @param length
@@ -109,7 +116,6 @@
      *            the address of the target host.
      * @param port
      *            the port of the target host.
-     * @since Android 1.0
      */
     public DatagramPacket(byte[] data, int length, InetAddress host, int port) {
         this(data, 0, length, host, port);
@@ -120,7 +126,6 @@
      * 
      * @return the address from where the datagram was received or to which it
      *         is sent.
-     * @since Android 1.0
      */
     public synchronized InetAddress getAddress() {
         return address;
@@ -130,7 +135,6 @@
      * Gets the data of this datagram packet.
      * 
      * @return the received data or the data to be sent.
-     * @since Android 1.0
      */
     public synchronized byte[] getData() {
         return data;
@@ -140,7 +144,6 @@
      * Gets the length of the data stored in this datagram packet.
      * 
      * @return the length of the received data or the data to be sent.
-     * @since Android 1.0
      */
     public synchronized int getLength() {
         return length;
@@ -150,7 +153,6 @@
      * Gets the offset of the data stored in this datagram packet.
      * 
      * @return the position of the received data or the data to be sent.
-     * @since Android 1.0
      */
     public synchronized int getOffset() {
         return offset;
@@ -159,9 +161,8 @@
     /**
      * Gets the port number of the target or sender host of this datagram
      * packet.
-     * 
+     *
      * @return the port number of the origin or target host.
-     * @since Android 1.0
      */
     public synchronized int getPort() {
         return port;
@@ -172,7 +173,6 @@
      * 
      * @param addr
      *            the target host address.
-     * @since Android 1.0
      */
     public synchronized void setAddress(InetAddress addr) {
         address = addr;
@@ -188,7 +188,6 @@
      * @param aLength
      *            the length of the data to be sent or the length of buffer to
      *            store the received data.
-     * @since Android 1.0
      */
     public synchronized void setData(byte[] buf, int anOffset, int aLength) {
         if (0 > anOffset || anOffset > buf.length || 0 > aLength
@@ -198,6 +197,7 @@
         data = buf;
         offset = anOffset;
         length = aLength;
+        capacity = aLength;
     }
 
     /**
@@ -206,10 +206,10 @@
      * 
      * @param buf
      *            the buffer to store the data.
-     * @since Android 1.0
      */
     public synchronized void setData(byte[] buf) {
         length = buf.length; // This will check for null
+        capacity = buf.length;
         data = buf;
         offset = 0;
     }
@@ -220,13 +220,13 @@
      * 
      * @param len
      *            the length of this datagram packet.
-     * @since Android 1.0
      */
     public synchronized void setLength(int len) {
         if (0 > len || offset + len > data.length) {
             throw new IllegalArgumentException(Msg.getString("K002f")); //$NON-NLS-1$
         }
         length = len;
+        capacity = len;
     }
 
     /**
@@ -234,7 +234,6 @@
      * 
      * @param aPort
      *            the target host port number.
-     * @since Android 1.0
      */
     public synchronized void setPort(int aPort) {
         if (aPort < 0 || aPort > 65535) {
@@ -257,9 +256,9 @@
      *            the target host address and port.
      * @throws SocketException
      *             if an error in the underlying protocol occurs.
-     * @since Android 1.0
      */
-    public DatagramPacket(byte[] data, int length, SocketAddress sockAddr) throws SocketException {
+    public DatagramPacket(byte[] data, int length, SocketAddress sockAddr)
+            throws SocketException {
         this(data, 0, length);
         setSocketAddress(sockAddr);
     }
@@ -280,7 +279,6 @@
      *            the target host address and port.
      * @throws SocketException
      *             if an error in the underlying protocol occurs.
-     * @since Android 1.0
      */
     public DatagramPacket(byte[] data, int offset, int length,
             SocketAddress sockAddr) throws SocketException {
@@ -291,9 +289,8 @@
     /**
      * Gets the host address and the port to which this datagram packet is sent
      * as a {@code SocketAddress} object.
-     * 
+     *
      * @return the SocketAddress of the target host.
-     * @since Android 1.0
      */
     public synchronized SocketAddress getSocketAddress() {
         return new InetSocketAddress(getAddress(), getPort());
@@ -304,7 +301,6 @@
      * 
      * @param sockAddr
      *            the SocketAddress of the target host.
-     * @since Android 1.0
      */
     public synchronized void setSocketAddress(SocketAddress sockAddr) {
         if (!(sockAddr instanceof InetSocketAddress)) {
diff --git a/luni/src/main/java/java/net/DatagramSocket.java b/luni/src/main/java/java/net/DatagramSocket.java
index 0c7745f..6b3b6cc 100644
--- a/luni/src/main/java/java/net/DatagramSocket.java
+++ b/luni/src/main/java/java/net/DatagramSocket.java
@@ -20,19 +20,17 @@
 import java.io.IOException;
 import java.nio.channels.DatagramChannel;
 
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainDatagramSocketImpl;
 import org.apache.harmony.luni.platform.Platform;
-
 import org.apache.harmony.luni.util.Msg;
 
 /**
  * This class implements a UDP socket for sending and receiving {@code
  * DatagramPacket}. A {@code DatagramSocket} object can be used for both
  * endpoints of a connection for a packet delivery service.
- * 
+ *
  * @see DatagramPacket
  * @see DatagramSocketImplFactory
- * @since Android 1.0
  */
 public class DatagramSocket {
 
@@ -56,16 +54,15 @@
     static {
         Platform.getNetworkSystem().oneTimeInitialization(true);
     }
-    
+
     private Object lock = new Lock();
 
     /**
      * Constructs a UDP datagram socket which is bound to any available port on
      * the localhost.
-     * 
+     *
      * @throws SocketException
      *             if an error occurs while creating or binding the socket.
-     * @since Android 1.0
      */
     public DatagramSocket() throws SocketException {
         this(0);
@@ -75,12 +72,11 @@
      * Constructs a UDP datagram socket which is bound to the specific port
      * {@code aPort} on the localhost. Valid values for {@code aPort} are
      * between 0 and 65535 inclusive.
-     * 
+     *
      * @param aPort
      *            the port to bind on the localhost.
      * @throws SocketException
      *             if an error occurs while creating or binding the socket.
-     * @since Android 1.0
      */
     public DatagramSocket(int aPort) throws SocketException {
         super();
@@ -92,14 +88,13 @@
      * Constructs a UDP datagram socket which is bound to the specific local
      * address {@code addr} on port {@code aPort}. Valid values for {@code
      * aPort} are between 0 and 65535 inclusive.
-     * 
+     *
      * @param aPort
      *            the port to bind on the localhost.
      * @param addr
      *            the address to bind on the localhost.
      * @throws SocketException
      *             if an error occurs while creating or binding the socket.
-     * @since Android 1.0
      */
     public DatagramSocket(int aPort, InetAddress addr) throws SocketException {
         super();
@@ -111,10 +106,9 @@
      * Sends prior to attempting to bind the socket, checks whether the port is
      * within the valid port range and verifies with the security manager that
      * the port may be bound by the current context.
-     * 
+     *
      * @param aPort
      *            the port on the localhost that is to be bound.
-     * @since Android 1.0
      */
     void checkListen(int aPort) {
         if (aPort < 0 || aPort > 65535) {
@@ -128,8 +122,6 @@
 
     /**
      * Closes this UDP datagram socket and all possibly associated channels.
-     * 
-     * @since Android 1.0
      */
     // In the documentation jdk1.1.7a/guide/net/miscNet.html, this method is
     // noted as not being synchronized.
@@ -144,12 +136,11 @@
      * validated, thereafter the only validation on {@code send()} and {@code
      * receive()} is to check whether the packet address/port matches the
      * connected target.
-     * 
+     *
      * @param anAddress
      *            the target address of this socket.
      * @param aPort
      *            the target port of this socket.
-     * @since Android 1.0
      */
     public void connect(InetAddress anAddress, int aPort) {
         if (anAddress == null || aPort < 0 || aPort > 65535) {
@@ -189,8 +180,6 @@
     /**
      * Disconnects this UDP datagram socket from the remote host. This method
      * called on an unconnected socket does nothing.
-     * 
-     * @since Android 1.0
      */
     public void disconnect() {
         if (isClosed() || !isConnected()) {
@@ -205,7 +194,7 @@
     synchronized void createSocket(int aPort, InetAddress addr)
             throws SocketException {
         impl = factory != null ? factory.createDatagramSocketImpl()
-                : SocketImplProvider.getDatagramSocketImpl();
+                : new PlainDatagramSocketImpl();
         impl.create();
         try {
             impl.bind(aPort, addr);
@@ -219,10 +208,9 @@
     /**
      * Gets the {@code InetAddress} instance representing the remote address to
      * which this UDP datagram socket is connected.
-     * 
+     *
      * @return the remote address this socket is connected to or {@code null} if
      *         this socket is not connected.
-     * @since Android 1.0
      */
     public InetAddress getInetAddress() {
         return address;
@@ -231,10 +219,9 @@
     /**
      * Gets the {@code InetAddress} instance representing the bound local
      * address of this UDP datagram socket.
-     * 
+     *
      * @return the local address to which this socket is bound to or {@code
      *         null} if this socket is closed.
-     * @since Android 1.0
      */
     public InetAddress getLocalAddress() {
         if (isClosed()) {
@@ -257,10 +244,9 @@
 
     /**
      * Gets the local port which this socket is bound to.
-     * 
+     *
      * @return the local port of this socket or {@code -1} if this socket is
      *         closed and {@code 0} if it is unbound.
-     * @since Android 1.0
      */
     public int getLocalPort() {
         if (isClosed()) {
@@ -274,10 +260,9 @@
 
     /**
      * Gets the remote port which this socket is connected to.
-     * 
+     *
      * @return the remote port of this socket. The return value {@code -1}
      *         indicates that this socket is not connected.
-     * @since Android 1.0
      */
     public int getPort() {
         return port;
@@ -285,9 +270,8 @@
 
     /**
      * Indicates whether this socket is multicast or not.
-     * 
+     *
      * @return the return value is always {@code false}.
-     * @since Android 1.0
      */
     boolean isMulticastSocket() {
         return false;
@@ -295,11 +279,10 @@
 
     /**
      * Gets the socket receive buffer size. ( {@code SocketOptions.SO_RCVBUF} )
-     * 
+     *
      * @return the input buffer size.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while getting the option value.
-     * @since Android 1.0
      */
     public synchronized int getReceiveBufferSize() throws SocketException {
         checkClosedAndBind(false);
@@ -308,11 +291,10 @@
 
     /**
      * Gets the socket send buffer size. ( {@code SocketOptions.SO_SNDBUF} )
-     * 
+     *
      * @return the output buffer size.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while getting the option value.
-     * @since Android 1.0
      */
     public synchronized int getSendBufferSize() throws SocketException {
         checkClosedAndBind(false);
@@ -323,11 +305,10 @@
      * Gets the socket receive timeout in milliseconds. The return value {@code
      * 0} implies the timeout is disabled/infinitive. ( {@code
      * SocketOptions.SO_TIMEOUT} )
-     * 
+     *
      * @return the socket receive timeout.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while getting the option value.
-     * @since Android 1.0
      */
     public synchronized int getSoTimeout() throws SocketException {
         checkClosedAndBind(false);
@@ -342,42 +323,49 @@
      * has expired. If a security manager exists, its {@code checkAccept} method
      * determines whether or not a packet is discarded. Any packets from
      * unacceptable origins are silently discarded.
-     * 
+     *
      * @param pack
      *            the {@code DatagramPacket} to store the received data.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while receiving the packet.
-     * @since Android 1.0
      */
     public synchronized void receive(DatagramPacket pack) throws IOException {
         checkClosedAndBind(true);
 
-        boolean secure = true;
-
-        InetAddress senderAddr = null;
-
-        int senderPort = 0;
+        InetAddress senderAddr;
+        int senderPort;
         DatagramPacket tempPack = new DatagramPacket(new byte[1], 1);
+
+        // means that we have received the packet into the temporary buffer
         boolean copy = false;
 
         SecurityManager security = System.getSecurityManager();
-        if (address != null || security != null) { // The socket is connected
+
+        if (address != null || security != null) {
+            // The socket is connected or we need to check security permissions
+
             // Check pack before peeking
             if (pack == null) {
                 throw new NullPointerException();
             }
-            secure = false;
-            while (!secure) {
+
+            // iterate over incoming packets
+            while (true) {
                 copy = false;
+
+                // let's get sender's address and port
                 try {
                     senderPort = impl.peekData(tempPack);
                     senderAddr = tempPack.getAddress();
                 } catch (SocketException e) {
                     if (e.getMessage().equals(
                             "The socket does not support the operation")) { //$NON-NLS-1$
-                        tempPack = new DatagramPacket(new byte[pack.length],
-                                pack.getLength());
+                        // receive packet to temporary buffer
+                        tempPack = new DatagramPacket(new byte[pack.capacity],
+                                pack.capacity);
                         impl.receive(tempPack);
+                        // tempPack's length field is now updated, capacity is unchanged
+                        // let's extract address & port
                         senderAddr = tempPack.getAddress();
                         senderPort = tempPack.getPort();
                         copy = true;
@@ -385,46 +373,45 @@
                         throw e;
                     }
                 }
+
                 if (address == null) {
+                    // if we are not connected let's check if we are allowed to
+                    // receive packets from sender's address and port
                     try {
                         security.checkAccept(senderAddr.getHostName(),
                                 senderPort);
-                        if (!copy) {
-                            secure = true;
-                        }
+                        // address & port are valid
                         break;
                     } catch (SecurityException e) {
                         if (!copy) {
-                            if (tempPack == null) {
-                                tempPack = new DatagramPacket(
-                                        new byte[pack.length], pack.length);
-                            }
+                            // drop this packet and continue
                             impl.receive(tempPack);
                         }
                     }
                 } else if (port == senderPort && address.equals(senderAddr)) {
-                    if (!copy) {
-                        secure = true;
-                    }
+                    // we are connected and the packet came
+                    // from the address & port we are connected to
                     break;
                 } else if (!copy) {
-                    if (tempPack == null) {
-                        tempPack = new DatagramPacket(new byte[pack.length],
-                                pack.length);
-                    }
+                    // drop packet and continue
                     impl.receive(tempPack);
                 }
             }
         }
+
         if (copy) {
             System.arraycopy(tempPack.getData(), 0, pack.getData(), pack
                     .getOffset(), tempPack.getLength());
-            pack.setLength(tempPack.getLength());
+            // we shouldn't update the pack's capacity field in order to be
+            // compatible with RI
+            pack.length = tempPack.length;
             pack.setAddress(tempPack.getAddress());
             pack.setPort(tempPack.getPort());
-        }
-        if (secure) {
+        } else {
+            pack.setLength(pack.capacity);
             impl.receive(pack);
+            // pack's length field is now updated by native code call;
+            // pack's capacity field is unchanged
         }
     }
 
@@ -433,12 +420,11 @@
      * policy before it may be sent. If a security manager is installed, this
      * method checks whether it is allowed to send this packet to the specified
      * address.
-     * 
+     *
      * @param pack
      *            the {@code DatagramPacket} which has to be sent.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while sending the packet.
-     * @since Android 1.0
      */
     public void send(DatagramPacket pack) throws IOException {
         checkClosedAndBind(true);
@@ -480,12 +466,11 @@
      * maximum packet size is that can be sent over this socket. It depends on
      * the network implementation what will happen if the packet is bigger than
      * the buffer size. ( {@code SocketOptions.SO_SNDBUF} )
-     * 
+     *
      * @param size
      *            the buffer size in bytes. The size must be at least one byte.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public synchronized void setSendBufferSize(int size) throws SocketException {
         if (size < 1) {
@@ -500,12 +485,11 @@
      * the maximum packet size is that can be received over this socket. It
      * depends on the network implementation what will happen if the packet is
      * bigger than the buffer size. ( {@code SocketOptions.SO_RCVBUF} )
-     * 
+     *
      * @param size
      *            the buffer size in bytes. The size must be at least one byte.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public synchronized void setReceiveBufferSize(int size)
             throws SocketException {
@@ -523,12 +507,11 @@
      * {@code 0} (default) is used to set an infinite timeout. To have effect
      * this option must be set before the blocking method was called. ( {@code
      * SocketOptions.SO_TIMEOUT} )
-     * 
+     *
      * @param timeout
      *            the timeout period in milliseconds or {@code 0} for infinite.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException {
         if (timeout < 0) {
@@ -545,13 +528,12 @@
      * method {@code checkSetFactory()} is called to check if the operation is
      * allowed. A {@code SecurityException} is thrown if the operation is not
      * allowed.
-     * 
+     *
      * @param fac
      *            the socket factory to use.
-     * @exception IOException
+     * @throws IOException
      *                if the factory has already been set.
      * @see DatagramSocketImplFactory
-     * @since Android 1.0
      */
     public static synchronized void setDatagramSocketImplFactory(
             DatagramSocketImplFactory fac) throws IOException {
@@ -569,10 +551,9 @@
      * Constructs a new {@code DatagramSocket} using the specific datagram
      * socket implementation {@code socketImpl}. The created {@code
      * DatagramSocket} will not be bound.
-     * 
+     *
      * @param socketImpl
      *            the DatagramSocketImpl to use.
-     * @since Android 1.0
      */
     protected DatagramSocket(DatagramSocketImpl socketImpl) {
         if (socketImpl == null) {
@@ -585,12 +566,13 @@
      * Constructs a new {@code DatagramSocket} bound to the host/port specified
      * by the {@code SocketAddress} {@code localAddr} or an unbound {@code
      * DatagramSocket} if the {@code SocketAddress} is {@code null}.
-     * 
+     *
      * @param localAddr
      *            the local machine address and port to bind to.
+     * @throws IllegalArgumentException
+     *             if the SocketAddress is not supported
      * @throws SocketException
      *             if a problem occurs creating or binding the socket.
-     * @since Android 1.0
      */
     public DatagramSocket(SocketAddress localAddr) throws SocketException {
         if (localAddr != null) {
@@ -601,7 +583,7 @@
             checkListen(((InetSocketAddress) localAddr).getPort());
         }
         impl = factory != null ? factory.createDatagramSocketImpl()
-                : SocketImplProvider.getDatagramSocketImpl();
+                : new PlainDatagramSocketImpl();
         impl.create();
         if (localAddr != null) {
             try {
@@ -630,13 +612,14 @@
      * Binds this socket to the local address and port specified by {@code
      * localAddr}. If this value is {@code null} any free port on a valid local
      * address is used.
-     * 
+     *
      * @param localAddr
      *            the local machine address and port to bind on.
+     * @throws IllegalArgumentException
+     *             if the SocketAddress is not supported
      * @throws SocketException
      *             if the socket is already bound or a problem occurs during
      *             binding.
-     * @since Android 1.0
      */
     public void bind(SocketAddress localAddr) throws SocketException {
         checkClosedAndBind(false);
@@ -665,12 +648,11 @@
      * {@code remoteAddr}. The host and port are validated, thereafter the only
      * validation on {@code send()} and {@code receive()} is that the packet
      * address/port matches the connected target.
-     * 
+     *
      * @param remoteAddr
      *            the address and port of the target host.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs during connecting.
-     * @since Android 1.0
      */
     public void connect(SocketAddress remoteAddr) throws SocketException {
         if (remoteAddr == null) {
@@ -720,9 +702,8 @@
 
     /**
      * Determines whether the socket is bound to an address or not.
-     * 
+     *
      * @return {@code true} if the socket is bound, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isBound() {
         return isBound;
@@ -730,9 +711,8 @@
 
     /**
      * Determines whether the socket is connected to a target host.
-     * 
+     *
      * @return {@code true} if the socket is connected, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isConnected() {
         return isConnected;
@@ -741,9 +721,8 @@
     /**
      * Gets the address and port of the connected remote host. If this socket is
      * not connected yet, {@code null} is returned.
-     * 
+     *
      * @return the remote socket address.
-     * @since Android 1.0
      */
     public SocketAddress getRemoteSocketAddress() {
         if (!isConnected()) {
@@ -755,9 +734,8 @@
     /**
      * Gets the bound local address and port of this socket. If the socket is
      * unbound, {@code null} is returned.
-     * 
+     *
      * @return the local socket address.
-     * @since Android 1.0
      */
     public SocketAddress getLocalSocketAddress() {
         if (!isBound()) {
@@ -773,13 +751,11 @@
      * <p>
      * There is an undefined behavior if this option is set after the socket is
      * already bound.
-     * </p>
-     * 
+     *
      * @param reuse
      *            the socket option value to enable or disable this option.
      * @throws SocketException
      *             if the socket is closed or the option could not be set.
-     * @since Android 1.0
      */
     public void setReuseAddress(boolean reuse) throws SocketException {
         checkClosedAndBind(false);
@@ -789,11 +765,10 @@
 
     /**
      * Gets the state of the socket option {@code SocketOptions.SO_REUSEADDR}.
-     * 
+     *
      * @return {@code true} if the option is enabled, {@code false} otherwise.
      * @throws SocketException
      *             if the socket is closed or the option is invalid.
-     * @since Android 1.0
      */
     public boolean getReuseAddress() throws SocketException {
         checkClosedAndBind(false);
@@ -804,12 +779,11 @@
     /**
      * Sets the socket option {@code SocketOptions.SO_BROADCAST}. This option
      * must be enabled to send broadcast messages.
-     * 
+     *
      * @param broadcast
      *            the socket option value to enable or disable this option.
      * @throws SocketException
      *             if the socket is closed or the option could not be set.
-     * @since Android 1.0
      */
     public void setBroadcast(boolean broadcast) throws SocketException {
         checkClosedAndBind(false);
@@ -819,11 +793,10 @@
 
     /**
      * Gets the state of the socket option {@code SocketOptions.SO_BROADCAST}.
-     * 
+     *
      * @return {@code true} if the option is enabled, {@code false} otherwise.
      * @throws SocketException
      *             if the socket is closed or the option is invalid.
-     * @since Android 1.0
      */
     public boolean getBroadcast() throws SocketException {
         checkClosedAndBind(false);
@@ -839,13 +812,11 @@
      * <p>
      * Values between {@code 0} and {@code 255} inclusive are valid for this
      * option.
-     * </p>
-     * 
+     *
      * @param value
      *            the socket option value to be set as type-of-service.
      * @throws SocketException
      *             if the socket is closed or the option could not be set.
-     * @since Android 1.0
      */
     public void setTrafficClass(int value) throws SocketException {
         checkClosedAndBind(false);
@@ -858,11 +829,10 @@
     /**
      * Gets the value of the type-of-service socket option {@code
      * SocketOptions.IP_TOS}.
-     * 
+     *
      * @return the type-of-service socket option value.
      * @throws SocketException
      *             if the socket is closed or the option is invalid.
-     * @since Android 1.0
      */
     public int getTrafficClass() throws SocketException {
         checkClosedAndBind(false);
@@ -871,9 +841,8 @@
 
     /**
      * Gets the state of this socket.
-     * 
+     *
      * @return {@code true} if the socket is closed, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isClosed() {
         return isClosed;
@@ -882,10 +851,9 @@
     /**
      * Gets the related DatagramChannel of this socket. This implementation
      * returns always {@code null}.
-     * 
+     *
      * @return the related DatagramChannel or {@code null} if this socket was
      *         not created by a {@code DatagramChannel} object.
-     * @since Android 1.0
      */
     public DatagramChannel getChannel() {
         return null;
diff --git a/luni/src/main/java/java/net/DatagramSocketImpl.java b/luni/src/main/java/java/net/DatagramSocketImpl.java
index 7915156..db3b9ec 100644
--- a/luni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/luni/src/main/java/java/net/DatagramSocketImpl.java
@@ -25,29 +25,21 @@
 
 /**
  * The abstract superclass for datagram and multicast socket implementations.
- * 
- * @since Android 1.0
  */
 public abstract class DatagramSocketImpl implements SocketOptions {
 
     /**
      * File descriptor that is used to address this socket.
-     * 
-     * @since Android 1.0
      */
     protected FileDescriptor fd;
 
     /**
      * The number of the local port to which this socket is bound.
-     * 
-     * @since Android 1.0
      */
     protected int localPort;
 
     /**
      * Constructs an unbound datagram socket implementation.
-     * 
-     * @since Android 1.0
      */
     public DatagramSocketImpl() {
         localPort = -1;
@@ -61,28 +53,24 @@
      *            the port on the localhost to bind.
      * @param addr
      *            the address on the multihomed localhost to bind.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while binding, for example, if the port
      *                has been already bound.
-     * @since Android 1.0
      */
     protected abstract void bind(int port, InetAddress addr)
             throws SocketException;
 
     /**
      * Closes this socket.
-     * 
-     * @since Android 1.0
      */
     protected abstract void close();
 
     /**
      * This method allocates the socket descriptor in the underlying operating
      * system.
-     * 
+     *
      * @throws SocketException
      *             if an error occurs while creating the socket.
-     * @since Android 1.0
      */
     protected abstract void create() throws SocketException;
 
@@ -91,7 +79,6 @@
      * if the socket is closed or not bound.
      * 
      * @return the current file descriptor of this socket.
-     * @since Android 1.0
      */
     protected FileDescriptor getFileDescriptor() {
         return fd;
@@ -101,7 +88,6 @@
      * Gets the local address to which the socket is bound.
      * 
      * @return the local address to which the socket is bound.
-     * @since Android 1.0
      */
     InetAddress getLocalAddress() {
         return Platform.getNetworkSystem().getSocketLocalAddress(fd,
@@ -112,7 +98,6 @@
      * Gets the local port of this socket.
      * 
      * @return the local port to which this socket is bound.
-     * @since Android 1.0
      */
     protected int getLocalPort() {
         return localPort;
@@ -124,9 +109,8 @@
      * @param optID
      *            the ID of the socket option to be retrieved.
      * @return the requested option value.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while accessing the option.
-     * @since Android 1.0
      */
     public abstract Object getOption(int optID) throws SocketException;
 
@@ -139,7 +123,6 @@
      *             value.
      * @deprecated Replaced by {@link #getTimeToLive}
      * @see #getTimeToLive()
-     * @since Android 1.0
      */
     @Deprecated
     protected abstract byte getTTL() throws IOException;
@@ -148,12 +131,11 @@
      * Gets the time-to-live (TTL) for multicast packets sent on this socket.
      * The TTL option defines how many routers a packet may be pass before it is
      * discarded.
-     * 
+     *
      * @return the time-to-live option as an integer value.
      * @throws IOException
      *             if an error occurs while getting the time-to-live option
      *             value.
-     * @since Android 1.0
      */
     protected abstract int getTimeToLive() throws IOException;
 
@@ -167,7 +149,6 @@
      * @throws IOException
      *             if an error occurs while joining the specified multicast
      *             group.
-     * @since Android 1.0
      */
     protected abstract void join(InetAddress addr) throws IOException;
 
@@ -184,7 +165,6 @@
      * @throws IOException
      *             if an error occurs while joining the specified multicast
      *             group.
-     * @since Android 1.0
      */
     protected abstract void joinGroup(SocketAddress addr,
             NetworkInterface netInterface) throws IOException;
@@ -197,7 +177,6 @@
      * @throws IOException
      *             if an error occurs while leaving the group or no multicast
      *             address was assigned.
-     * @since Android 1.0
      */
     protected abstract void leave(InetAddress addr) throws IOException;
 
@@ -211,7 +190,6 @@
      *            removed.
      * @throws IOException
      *             if an error occurs while leaving the group.
-     * @since Android 1.0
      */
     protected abstract void leaveGroup(SocketAddress addr,
             NetworkInterface netInterface) throws IOException;
@@ -224,9 +202,8 @@
      * @param sender
      *            the origin address of a packet.
      * @return the address of {@code sender} as an integer value.
-     * @exception IOException
+     * @throws IOException
      *                if an error or a timeout occurs while reading the address.
-     * @since Android 1.0
      */
     protected abstract int peek(InetAddress sender) throws IOException;
 
@@ -238,9 +215,8 @@
      * 
      * @param pack
      *            the datagram packet container to fill in the received data.
-     * @exception IOException
+     * @throws IOException
      *                if an error or timeout occurs while receiving data.
-     * @since Android 1.0
      */
     protected abstract void receive(DatagramPacket pack) throws IOException;
 
@@ -250,9 +226,8 @@
      * 
      * @param pack
      *            the datagram packet to be sent.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while sending the packet.
-     * @since Android 1.0
      */
     protected abstract void send(DatagramPacket pack) throws IOException;
 
@@ -263,9 +238,8 @@
      *            the ID of the socket option to be set.
      * @param val
      *            the value of the option.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public abstract void setOption(int optID, Object val)
             throws SocketException;
@@ -279,7 +253,6 @@
      *            &lt;= 255.
      * @throws IOException
      *             if an error occurs while setting the option.
-     * @since Android 1.0
      */
     protected abstract void setTimeToLive(int ttl) throws IOException;
 
@@ -294,7 +267,6 @@
      *             if an error occurs while setting the option.
      * @deprecated Replaced by {@link #setTimeToLive}
      * @see #setTimeToLive(int)
-     * @since Android 1.0
      */
     @Deprecated
     protected abstract void setTTL(byte ttl) throws IOException;
@@ -306,10 +278,9 @@
      *            the address of the target host which has to be connected.
      * @param port
      *            the port on the target host which has to be connected.
-     * @exception SocketException
+     * @throws SocketException
      *                if the datagram socket cannot be connected to the
      *                specified remote address and port.
-     * @since Android 1.0
      */
     protected void connect(InetAddress inetAddr, int port)
             throws SocketException {
@@ -318,8 +289,6 @@
 
     /**
      * Disconnects this socket from the remote host.
-     * 
-     * @since Android 1.0
      */
     protected void disconnect() {
         // do nothing
@@ -335,9 +304,8 @@
      * @param pack
      *            the datagram packet used to store the data.
      * @return the port the packet was received from.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while peeking at the data.
-     * @since Android 1.0
      */
     protected abstract int peekData(DatagramPacket pack) throws IOException;
 }
diff --git a/luni/src/main/java/java/net/DatagramSocketImplFactory.java b/luni/src/main/java/java/net/DatagramSocketImplFactory.java
index b97146e..ce91738 100644
--- a/luni/src/main/java/java/net/DatagramSocketImplFactory.java
+++ b/luni/src/main/java/java/net/DatagramSocketImplFactory.java
@@ -23,7 +23,6 @@
  * implementation.
  * 
  * @see DatagramSocket
- * @since Android 1.0
  */
 public interface DatagramSocketImplFactory {
     
@@ -31,7 +30,6 @@
      * Creates a new {@code DatagramSocketImpl} instance.
      * 
      * @return the new datagram socket implementation.
-     * @since Android 1.0
      */
     DatagramSocketImpl createDatagramSocketImpl();
 }
diff --git a/luni/src/main/java/java/net/FileNameMap.java b/luni/src/main/java/java/net/FileNameMap.java
index e8ac35f..16fa0e0 100644
--- a/luni/src/main/java/java/net/FileNameMap.java
+++ b/luni/src/main/java/java/net/FileNameMap.java
@@ -26,7 +26,6 @@
  * @see URLConnection#getFileNameMap()
  * @see URLConnection#guessContentTypeFromName(String)
  * @see URLStreamHandler
- * @since Android 1.0
  */
 public interface FileNameMap {
 
@@ -36,7 +35,6 @@
      * @param fileName
      *            the name of the file to consider.
      * @return the appropriate MIME type of the given file.
-     * @since Android 1.0
      */
     public String getContentTypeFor(String fileName);
 }
diff --git a/luni/src/main/java/java/net/HttpRetryException.java b/luni/src/main/java/java/net/HttpRetryException.java
index 5f613ab..4ad14bd 100644
--- a/luni/src/main/java/java/net/HttpRetryException.java
+++ b/luni/src/main/java/java/net/HttpRetryException.java
@@ -21,8 +21,6 @@
 /**
  * If a HTTP request has to be retried, this exception will be thrown if the
  * request cannot be retried automatically.
- * 
- * @since Android 1.0
  */
 public class HttpRetryException extends IOException {
 
@@ -40,7 +38,6 @@
      *            the detail message for this exception.
      * @param code
      *            the HTTP response code from target host.
-     * @since Android 1.0
      */
     public HttpRetryException(String detail, int code) {
         super(detail);
@@ -58,7 +55,6 @@
      *            the HTTP response code from target host.
      * @param location
      *            the destination URL of the redirection.
-     * @since Android 1.0
      */
     public HttpRetryException(String detail, int code, String location) {
         super(detail);
@@ -68,9 +64,8 @@
 
     /**
      * Gets the location value.
-     * 
+     *
      * @return the stored location from the HTTP header.
-     * @since Android 1.0
      */
     public String getLocation() {
         return location;
@@ -78,9 +73,8 @@
 
     /**
      * Gets the detail message.
-     * 
+     *
      * @return the detail message.
-     * @since Android 1.0
      */
     public String getReason() {
         return getMessage();
@@ -88,9 +82,8 @@
 
     /**
      * Gets the response code.
-     * 
+     *
      * @return the HTTP response code.
-     * @since Android 1.0
      */
     public int responseCode() {
         return responseCode;
diff --git a/luni/src/main/java/java/net/HttpURLConnection.java b/luni/src/main/java/java/net/HttpURLConnection.java
index 55cc363..6be891f 100644
--- a/luni/src/main/java/java/net/HttpURLConnection.java
+++ b/luni/src/main/java/java/net/HttpURLConnection.java
@@ -29,7 +29,6 @@
  * @see URL
  * @see URLConnection
  * @see URLStreamHandler
- * @since Android 1.0
  */
 public abstract class HttpURLConnection extends URLConnection {
     @SuppressWarnings("nls")
@@ -39,8 +38,6 @@
    /**
      * The HTTP request method of this {@code HttpURLConnection}. The default
      * value is {@code "GET"}.
-     * 
-     * @since Android 1.0
      */
     protected String method = "GET"; //$NON-NLS-1$
 
@@ -53,24 +50,17 @@
      * <li>3xx: Relocation/Redirection</li>
      * <li>4xx: Client Error</li>
      * <li>5xx: Server Error</li>
-     * </p>
-     * 
-     * @since Android 1.0
      */
     protected int responseCode = -1;
 
     /**
      * The HTTP response message which corresponds to the response code.
-     * 
-     * @since Android 1.0
      */
     protected String responseMessage;
 
     /**
      * Flag to define whether the protocol will automatically follow redirects
      * or not. The default value is {@code true}.
-     * 
-     * @since Android 1.0
      */
     protected boolean instanceFollowRedirects = followRedirects;
 
@@ -80,8 +70,6 @@
      * If the HTTP chunked encoding is enabled this parameter defines the
      * chunk-length. Default value is {@code -1} that means the chunked encoding
      * mode is disabled.
-     * 
-     * @since Android 1.0
      */
     protected int chunkLength = -1;
 
@@ -89,8 +77,6 @@
      * If using HTTP fixed-length streaming mode this parameter defines the
      * fixed length of content. Default value is {@code -1} that means the
      * fixed-length streaming mode is disabled.
-     * 
-     * @since Android 1.0
      */
     protected int fixedContentLength = -1;
 
@@ -102,255 +88,184 @@
     // 5XX: server error
     /**
      * Numeric status code, 202: Accepted
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_ACCEPTED = 202;
 
     /**
      * Numeric status code, 502: Bad Gateway
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_BAD_GATEWAY = 502;
 
     /**
      * Numeric status code, 405: Bad Method
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_BAD_METHOD = 405;
 
     /**
      * Numeric status code, 400: Bad Request
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_BAD_REQUEST = 400;
 
     /**
      * Numeric status code, 408: Client Timeout
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_CLIENT_TIMEOUT = 408;
 
     /**
      * Numeric status code, 409: Conflict
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_CONFLICT = 409;
 
     /**
      * Numeric status code, 201: Created
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_CREATED = 201;
 
     /**
      * Numeric status code, 413: Entity too large
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_ENTITY_TOO_LARGE = 413;
 
     /**
      * Numeric status code, 403: Forbidden
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_FORBIDDEN = 403;
 
     /**
      * Numeric status code, 504: Gateway timeout
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_GATEWAY_TIMEOUT = 504;
 
     /**
      * Numeric status code, 410: Gone
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_GONE = 410;
 
     /**
      * Numeric status code, 500: Internal error
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_INTERNAL_ERROR = 500;
 
     /**
      * Numeric status code, 411: Length required
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_LENGTH_REQUIRED = 411;
 
     /**
      * Numeric status code, 301 Moved permanently
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_MOVED_PERM = 301;
 
     /**
      * Numeric status code, 302: Moved temporarily
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_MOVED_TEMP = 302;
 
     /**
      * Numeric status code, 300: Multiple choices
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_MULT_CHOICE = 300;
 
     /**
      * Numeric status code, 204: No content
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NO_CONTENT = 204;
 
     /**
      * Numeric status code, 406: Not acceptable
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NOT_ACCEPTABLE = 406;
 
     /**
      * Numeric status code, 203: Not authoritative
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NOT_AUTHORITATIVE = 203;
 
     /**
      * Numeric status code, 404: Not found
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NOT_FOUND = 404;
 
     /**
      * Numeric status code, 501: Not implemented
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NOT_IMPLEMENTED = 501;
 
     /**
      * Numeric status code, 304: Not modified
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NOT_MODIFIED = 304;
 
     /**
      * Numeric status code, 200: OK
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_OK = 200;
 
     /**
      * Numeric status code, 206: Partial
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_PARTIAL = 206;
 
     /**
      * Numeric status code, 402: Payment required
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_PAYMENT_REQUIRED = 402;
 
     /**
      * Numeric status code, 412: Precondition failed
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_PRECON_FAILED = 412;
 
     /**
      * Numeric status code, 407: Proxy authentication required
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_PROXY_AUTH = 407;
 
     /**
      * Numeric status code, 414: Request too long
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_REQ_TOO_LONG = 414;
 
     /**
      * Numeric status code, 205: Reset
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_RESET = 205;
 
     /**
      * Numeric status code, 303: See other
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_SEE_OTHER = 303;
 
     /**
      * Numeric status code, 500: Internal error
-     * 
+     *
      * @deprecated Use {@link #HTTP_INTERNAL_ERROR}
-     * @since Android 1.0
      */
     @Deprecated
     public final static int HTTP_SERVER_ERROR = 500;
 
     /**
      * Numeric status code, 305: Use proxy
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_USE_PROXY = 305;
 
     /**
      * Numeric status code, 401: Unauthorized
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_UNAUTHORIZED = 401;
 
     /**
      * Numeric status code, 415: Unsupported type
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_UNSUPPORTED_TYPE = 415;
 
     /**
      * Numeric status code, 503: Unavailable
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_UNAVAILABLE = 503;
 
     /**
      * Numeric status code, 505: Version not supported
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_VERSION = 505;
 
@@ -362,7 +277,6 @@
      *            the URL of this connection.
      * @see URL
      * @see URLConnection
-     * @since Android 1.0
      */
     protected HttpURLConnection(URL url) {
         super(url);
@@ -373,7 +287,6 @@
      * 
      * @see URLConnection#connect()
      * @see URLConnection#connected
-     * @since Android 1.0
      */
     public abstract void disconnect();
 
@@ -383,7 +296,6 @@
      * can be used to read the data the server will send back.
      * 
      * @return the error input stream returned by the server.
-     * @since Android 1.0
      */
     public java.io.InputStream getErrorStream() {
         return null;
@@ -396,7 +308,6 @@
      * 
      * @return the value of the flag.
      * @see #setFollowRedirects
-     * @since Android 1.0
      */
     public static boolean getFollowRedirects() {
         return followRedirects;
@@ -412,7 +323,6 @@
      * @throws IOException
      *             if an IO exception occurs during the creation of the
      *             permission object.
-     * @since Android 1.0
      */
     @Override
     public java.security.Permission getPermission() throws IOException {
@@ -432,7 +342,6 @@
      * @return the request method string.
      * @see #method
      * @see #setRequestMethod
-     * @since Android 1.0
      */
     public String getRequestMethod() {
         return method;
@@ -445,7 +354,6 @@
      * @throws IOException
      *             if there is an IO error during the retrieval.
      * @see #getResponseMessage
-     * @since Android 1.0
      */
     public int getResponseCode() throws IOException {
         // Call getInputStream() first since getHeaderField() doesn't return
@@ -478,7 +386,6 @@
      * @throws IOException
      *             if there is an error during the retrieval.
      * @see #getResponseCode()
-     * @since Android 1.0
      */
     public String getResponseMessage() throws IOException {
         if (responseMessage != null) {
@@ -496,7 +403,6 @@
      * @param auto
      *            the value to enable or disable this option.
      * @see SecurityManager#checkSetFactory()
-     * @since Android 1.0
      */
     public static void setFollowRedirects(boolean auto) {
         SecurityManager security = System.getSecurityManager();
@@ -517,7 +423,6 @@
      *             supported by this HTTP implementation.
      * @see #getRequestMethod()
      * @see #method
-     * @since Android 1.0
      */
     public void setRequestMethod(String method) throws ProtocolException {
         if (connected) {
@@ -540,7 +445,6 @@
      * 
      * @return {@code true} if this connection passes a proxy server, false
      *         otherwise.
-     * @since Android 1.0
      */
     public abstract boolean usingProxy();
 
@@ -549,7 +453,6 @@
      * 
      * @return {@code true} if this connection follows redirects, false
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean getInstanceFollowRedirects() {
         return instanceFollowRedirects;
@@ -561,7 +464,6 @@
      * @param followRedirects
      *            {@code true} if this connection will follows redirects, false
      *            otherwise.
-     * @since Android 1.0
      */
     public void setInstanceFollowRedirects(boolean followRedirects) {
         instanceFollowRedirects = followRedirects;
@@ -579,7 +481,6 @@
      *            found.
      * @return the header field represented in milliseconds since January 1,
      *         1970 GMT.
-     * @since Android 1.0
      */
     @Override
     public long getHeaderFieldDate(String field, long defaultValue) {
@@ -598,7 +499,6 @@
      *             if already connected or an other mode already set.
      * @throws IllegalArgumentException
      *             if {@code contentLength} is less than zero.
-     * @since Android 1.0
      */
     public void setFixedLengthStreamingMode(int contentLength) {
         if (super.connected) {
@@ -624,7 +524,6 @@
      *            the length of a chunk.
      * @throws IllegalStateException
      *             if already connected or an other mode already set.
-     * @since Android 1.0
      */
     public void setChunkedStreamingMode(int chunklen) {
         if (super.connected) {
diff --git a/luni/src/main/java/java/net/Inet4Address.java b/luni/src/main/java/java/net/Inet4Address.java
index dd6b088..23efa5e 100644
--- a/luni/src/main/java/java/net/Inet4Address.java
+++ b/luni/src/main/java/java/net/Inet4Address.java
@@ -28,8 +28,6 @@
  * address ({@code b.bbb} ) allows to represent a class A network address as
  * <i>net.host</i>. If there is only one part ({@code bbbb} ) the address is
  * represented without any byte rearrangement.
- * 
- * @since Android 1.0
  */
 public final class Inet4Address extends InetAddress {
 
@@ -50,7 +48,6 @@
      * 
      * @return {@code true} if this instance represents a multicast address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMulticastAddress() {
@@ -63,7 +60,6 @@
      * 
      * @return {@code true} if this instance represents the wildcard ANY
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isAnyLocalAddress() {
@@ -81,7 +77,6 @@
      * 
      * @return {@code true} if this instance represents a lookback address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLoopbackAddress() {
@@ -95,11 +90,9 @@
      * Default Address Selection for Internet Protocol Version 6 (IPv6) states
      * IPv4 auto-configuration addresses, prefix 169.254/16, IPv4 loopback
      * addresses, prefix 127/8, are assigned link-local scope.
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a link-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLinkLocalAddress() {
@@ -115,11 +108,9 @@
      * Default Address Selection for Internet Protocol Version 6 (IPv6) states
      * IPv4 private addresses, prefixes 10/8, 172.16/12, and 192.168/16, are
      * assigned site-local scope.
-     * </p>
      * 
      * @return {@code true} if this instance represents a site-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isSiteLocalAddress() {
@@ -135,7 +126,6 @@
      * 
      * @return {@code true} if the address is in the global multicast group,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCGlobal() {
@@ -174,7 +164,6 @@
      * addresses.
      * 
      * @return {@code false} for all IPv4 addresses.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCNodeLocal() {
@@ -188,7 +177,6 @@
      * 
      * @return {@code true} if this instance represents a link-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCLinkLocal() {
@@ -202,7 +190,6 @@
      * 
      * @return {@code true} if this instance represents a site-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCSiteLocal() {
@@ -217,7 +204,6 @@
      * 
      * @return {@code true} if this instance represents a organization-local
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCOrgLocal() {
@@ -229,7 +215,6 @@
      * Returns a textual representation of this IP address.
      * 
      * @return the textual representation of this host address.
-     * @since Android 1.0
      */
     @Override
     public String getHostAddress() {
@@ -247,7 +232,6 @@
      * Gets the hashcode of the represented IP address.
      * 
      * @return the appropriate hashcode value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -262,7 +246,6 @@
      * @param obj
      *            the object to be tested for equality.
      * @return {@code true} if the addresses are equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
diff --git a/luni/src/main/java/java/net/Inet6Address.java b/luni/src/main/java/java/net/Inet6Address.java
index 4c10faa..0569829 100644
--- a/luni/src/main/java/java/net/Inet6Address.java
+++ b/luni/src/main/java/java/net/Inet6Address.java
@@ -28,8 +28,6 @@
 
 /**
  * This class represents a 128 bit long IPv6 address.
- * 
- * @since Android 1.0
  */
 public final class Inet6Address extends InetAddress {
 
@@ -80,7 +78,6 @@
      *            the name associated with the address.
      * @param scope_id
      *            the scope id for link- or site-local addresses.
-     * @since Android 1.0
      */
     Inet6Address(byte address[], String name, int scope_id) {
         hostName = name;
@@ -104,7 +101,6 @@
      * @return the Inet6Address instance representing the IP address.
      * @throws UnknownHostException
      *             if the address is null or has an invalid length.
-     * @since Android 1.0
      */
     public static Inet6Address getByAddress(String host, byte[] addr,
             int scope_id) throws UnknownHostException {
@@ -135,7 +131,6 @@
      *             if the address is {@code null} or has an invalid length or
      *             the interface doesn't have a numeric scope id for the given
      *             address type.
-     * @since Android 1.0
      */
     public static Inet6Address getByAddress(String host, byte[] addr,
             NetworkInterface nif) throws UnknownHostException {
@@ -177,10 +172,11 @@
     /**
      * Returns {@code true} if one of following cases applies:
      * <p>
-     * <li>1. both addresses are site local</li>
-     * <li>2. both addresses are link local</li>
-     * <li>3. {@code ia} is neither site local nor link local</li>
-     * </p>
+     * <ol>
+     *  <li>both addresses are site local</li>
+     *  <li>both addresses are link local</li>
+     *  <li>{@code ia} is neither site local nor link local</li>
+     * </ol>
      */
     private boolean compareLocalType(Inet6Address ia) {
         if (ia.isSiteLocalAddress() && isSiteLocalAddress()) {
@@ -203,7 +199,6 @@
      *            the network address.
      * @param scope_id
      *            the scope id for link- or site-local addresses.
-     * @since Android 1.0
      */
     Inet6Address(byte address[], int scope_id) {
         ipaddress = address;
@@ -219,7 +214,6 @@
      * 
      * @return {@code true} if this address is in the multicast group, {@code
      *         false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMulticastAddress() {
@@ -233,7 +227,6 @@
      * 
      * @return {@code true} if this instance represents a wildcard address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isAnyLocalAddress() {
@@ -251,7 +244,6 @@
      * 
      * @return {@code true} if this instance represents the loopback address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLoopbackAddress() {
@@ -277,7 +269,6 @@
      * 
      * @return {@code true} if this instance represents a link-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLinkLocalAddress() {
@@ -292,7 +283,6 @@
      * 
      * @return {@code true} if this instance represents a site-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isSiteLocalAddress() {
@@ -307,7 +297,6 @@
      * 
      * @return {@code true} if this instance represents a global multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCGlobal() {
@@ -323,7 +312,6 @@
      * 
      * @return {@code true} if this instance represents a node-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCNodeLocal() {
@@ -339,7 +327,6 @@
      * 
      * @return {@code true} if this instance represents a link-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCLinkLocal() {
@@ -355,7 +342,6 @@
      * 
      * @return {@code true} if this instance represents a site-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCSiteLocal() {
@@ -371,7 +357,6 @@
      * 
      * @return {@code true} if this instance represents a org-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCOrgLocal() {
@@ -384,7 +369,6 @@
      * Gets the textual representation of this IP address.
      * 
      * @return the as a dotted string formatted IP address.
-     * @since Android 1.0
      */
     @Override
     public String getHostAddress() {
@@ -397,7 +381,6 @@
      * 
      * @return the scope_id of this address or 0 when not linked with an
      *         interface.
-     * @since Android 1.0
      */
     public int getScopeId() {
         if (scope_id_set) {
@@ -411,7 +394,6 @@
      * network interface. Otherwise returns {@code null}.
      * 
      * @return the scoped network interface of this address.
-     * @since Android 1.0
      */
     public NetworkInterface getScopedInterface() {
         if (scope_ifname_set) {
@@ -424,7 +406,6 @@
      * Gets the hashcode of the represented IP address.
      * 
      * @return the appropriate hashcode value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -441,7 +422,6 @@
      * @param obj
      *            the object to be tested for equality.
      * @return {@code true} if the addresses are equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -455,7 +435,6 @@
      * 
      * @return {@code true} if this instance represents an IPv4 compatible
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isIPv4CompatibleAddress() {
         for (int i = 0; i < 12; i++) {
@@ -506,7 +485,6 @@
      * IP address.
      * 
      * @return the description, as host/address.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java
index 72c7669..fa3859b 100644
--- a/luni/src/main/java/java/net/InetAddress.java
+++ b/luni/src/main/java/java/net/InetAddress.java
@@ -41,8 +41,6 @@
  * encapsulates an IP address and provides name and reverse name resolution
  * functions. The address is stored in network order, but as a signed (rather
  * than unsigned) integer.
- * 
- * @since Android 1.0
  */
 public class InetAddress extends Object implements Serializable {
 
@@ -59,7 +57,7 @@
 
     private static final String ERRMSG_CONNECTION_REFUSED = "Connection refused"; //$NON-NLS-1$
 
-    private static final long serialVersionUID = 3286316764910316507L;
+    private static final long serialVersionUID = 3286316764910316507L; 
 
     // BEGIN android-added
     /**
@@ -86,7 +84,7 @@
     // BEGIN android-removed
     // // Fill in the JNI id caches
     // private static native void oneTimeInitialization(boolean supportsIPv6);
-    // 
+    //
     // static {
     //     oneTimeInitialization(true);
     // }
@@ -102,7 +100,7 @@
     /**
      * Constructs an {@code InetAddress}, representing the {@code address} and
      * {@code hostName}.
-     * 
+     *
      * @param address
      *            the network address.
      */
@@ -114,7 +112,7 @@
     /**
      * Constructs an {@code InetAddress}, representing the {@code address} and
      * {@code hostName}.
-     * 
+     *
      * @param address
      *            the network address.
      */
@@ -124,26 +122,6 @@
         this.hostName = hostName;
     }
 
-    // BEGIN android-removed
-    // Removed in newer version of harmony
-    // /**
-    //  * Returns the IP address of the argument {@code addr} as a byte array. The
-    //  * elements are in network order (the highest order address byte is in the
-    //  * zeroth element).
-    //  * 
-    //  * @return the network address as a byte array.
-    //  */
-    // static byte[] addressOf(int addr) {
-    //     int temp = addr;
-    //     byte array[] = new byte[4];
-    //     array[3] = (byte) (temp & 0xFF);
-    //     array[2] = (byte) ((temp >>>= 8) & 0xFF);
-    //     array[1] = (byte) ((temp >>>= 8) & 0xFF);
-    //     array[0] = (byte) ((temp >>>= 8) & 0xFF);
-    //     return array;
-    // }
-    // BEGIN android-removed
-
     CacheElement cacheElement() {
         return new CacheElement();
     }
@@ -152,11 +130,10 @@
      * Compares this {@code InetAddress} instance against the specified address
      * in {@code obj}. Two addresses are equal if their address byte arrays have
      * the same length and if the bytes in the arrays are equal.
-     * 
+     *
      * @param obj
      *            the object to be tested for equality.
      * @return {@code true} if both objects are equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -185,9 +162,8 @@
      * Returns the IP address represented by this {@code InetAddress} instance
      * as a byte array. The elements are in network order (the highest order
      * address byte is in the zeroth element).
-     * 
+     *
      * @return the address in form of a byte array.
-     * @since Android 1.0
      */
     public byte[] getAddress() {
         return ipaddress.clone();
@@ -200,25 +176,21 @@
      * {@code UnknownHostException} is thrown. If the host name is a dotted IP
      * address string an array with the corresponding single {@code InetAddress}
      * is returned.
-     * 
+     *
      * @param host
      *            the host's name or IP to be resolved to an address.
      * @return the array of addresses associated with the specified host.
      * @throws UnknownHostException
      *             if the address lookup fails.
-     * @since Android 1.0
      */
     public static InetAddress[] getAllByName(String host)
             throws UnknownHostException {
         // BEGIN android-changed
-        // Added change taken from newer harmony concerning zero length hostname.
-        // Added special handling for localhost, since it doesn't work properly.
+        // Added special handling for "localhost", since it doesn't work properly.
         // TODO Get rid of this later...
-        if (host == null || 0 == host.length() ||
-                "localhost".equalsIgnoreCase(host)) {
-            return new InetAddress[] { preferIPv6Addresses()
-                                       ? Inet6Address.LOOPBACK
-                                       : LOOPBACK };
+        if (host == null || 0 == host.length() || "localhost".equalsIgnoreCase(host)) {
+            return new InetAddress[] { preferIPv6Addresses() ? Inet6Address.LOOPBACK
+                    : LOOPBACK };
         }
         // END android-changed
 
@@ -241,7 +213,7 @@
                 } else {
                   // Cannot happen, because the underlying code only returns
                   // addresses that are 4 or 16 bytes long.
-                  throw new AssertionError("Impossible address length " + 
+                  throw new AssertionError("Impossible address length " +
                                            rawAddress.length);
                 }
             }
@@ -289,14 +261,12 @@
         }
 
         byte[] hBytes = Inet6Util.createByteArrayFromIPAddressString(host);
-        // BEGIN android-added
-        // Copied from a newer version of harmony
         if (hBytes.length == 4) {
             return (new InetAddress[] { new Inet4Address(hBytes) });
         } else if (hBytes.length == 16) {
             return (new InetAddress[] { new Inet6Address(hBytes) });
         }
-        // END android-added
+
         return (new InetAddress[] { new InetAddress(hBytes) });
     }
 
@@ -306,20 +276,19 @@
      * string IP address. If the latter, the {@code hostName} field is
      * determined upon demand. {@code host} can be {@code null} which means that
      * an address of the loopback interface is returned.
-     * 
+     *
      * @param host
      *            the hostName to be resolved to an address or {@code null}.
      * @return the {@code InetAddress} instance representing the host.
      * @throws UnknownHostException
      *             if the address lookup fails.
-     * @since Android 1.0
      */
     public static InetAddress getByName(String host)
             throws UnknownHostException {
         // BEGIN android-changed
         // Added special handling for localhost, since it doesn't work properly.
         // TODO Get rid of this later...
-        if (host == null || 0 == host.length() || 
+        if (host == null || 0 == host.length() ||
                 "localhost".equalsIgnoreCase(host)) {
             return InetAddress.LOOPBACK;
         }
@@ -341,10 +310,9 @@
 
     /**
      * Gets the textual representation of this IP address.
-     * 
+     *
      * @return the textual representation of this host address in form of a
      *         dotted string.
-     * @since Android 1.0
      */
     public String getHostAddress() {
         return inetNtoaImpl(bytesToInt(ipaddress, 0));
@@ -354,9 +322,8 @@
      * Gets the host name of this IP address. If the IP address could not be
      * resolved, the textual representation in a dotted-quad-notation is
      * returned.
-     * 
+     *
      * @return the corresponding string name of this IP address.
-     * @since Android 1.0
      */
     public String getHostName() {
         try {
@@ -395,9 +362,8 @@
      * address. If a security manager is set, it is checked if the method caller
      * is allowed to get the hostname. Otherwise, the textual representation in
      * a dotted-quad-notation is returned.
-     * 
+     *
      * @return the fully qualified domain name of this IP address.
-     * @since Android 1.0
      */
     public String getCanonicalHostName() {
         String canonicalName;
@@ -429,14 +395,10 @@
      * Gets the local host address if the security policy allows this.
      * Otherwise, gets the loopback address which allows this machine to be
      * contacted.
-     * <p>
-     * The current implementation returns always the loopback address.
-     * </p>
-     * 
+     *
      * @return the {@code InetAddress} representing the local host.
      * @throws UnknownHostException
      *             if the address lookup fails.
-     * @since Android 1.0
      */
     public static InetAddress getLocalHost() throws UnknownHostException {
         String host = getHostNameImpl();
@@ -453,9 +415,8 @@
 
     /**
      * Gets the hashcode of the represented IP address.
-     * 
+     *
      * @return the appropriate hashcode value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -464,10 +425,9 @@
 
     /**
      * Returns whether this address is an IP multicast address or not.
-     * 
+     *
      * @return {@code true} if this address is in the multicast group, {@code
      *         false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMulticastAddress() {
         return ((ipaddress[0] & 255) >>> 4) == 0xE;
@@ -507,10 +467,12 @@
             return element.inetAddress();
         }
 
+        // TODO Clean up NegativeCache; there's no need to maintain the failure message
+
         // now try the negative cache
         String failedMessage = NegativeCache.getFailedMessage(host);
         if (failedMessage != null) {
-            throw new UnknownHostException(host + " - " + failedMessage); //$NON-NLS-1$
+            throw new UnknownHostException(host);
         }
 
         InetAddress anInetAddress;
@@ -519,7 +481,8 @@
         } catch (UnknownHostException e) {
             // put the entry in the negative cache
             NegativeCache.put(host, e.getMessage());
-            throw new UnknownHostException(host + " - " + e.getMessage()); //$NON-NLS-1$
+            // use host for message to match RI, save the cause for giggles
+            throw (UnknownHostException)new UnknownHostException(host).initCause(e);
         }
 
         Cache.add(anInetAddress);
@@ -540,17 +503,17 @@
     //     throws UnknownHostException;
     // END android-deleted
 
-    // BEGIN android-changed
+    // BEGIN android-added
     /**
      * Resolves a host name to its IP addresses. Thread safe.
      */
     private static native byte[][] getallbyname(String name,
                                                 boolean preferIPv4Stack);
-    // END android-changed
+    // END android-added
 
     /**
      * Query the IP stack for the host address. The host is in address form.
-     * 
+     *
      * @param addr
      *            the host address to lookup.
      * @throws UnknownHostException
@@ -587,12 +550,12 @@
         // TODO Probably not exactly what we want, and also inefficient. Provide native later.
         try {
             String[] args = host.split("\\.");
-            
+
             int a = Integer.parseInt(args[0]) << 24;
             int b = Integer.parseInt(args[1]) << 16;
             int c = Integer.parseInt(args[2]) <<  8;
             int d = Integer.parseInt(args[3])      ;
-            
+
             return a | b | c | d;
         } catch (Exception ex) {
             throw new UnknownHostException(host);
@@ -612,17 +575,17 @@
         int b = (hipAddr >> 16) & 0xFF;
         int c = (hipAddr >>  8) & 0xFF;
         int d = (hipAddr      ) & 0xFF;
-        
+
         return "" + a + "." + b + "." + c + "." + d;
     }
     // END android-changed
 
     /**
      * Query the IP stack for the host address. The host is in string name form.
-     * 
+     *
      * @param name
      *            the host name to lookup
-     * @param preferIPv6Addresses
+     * @param preferIPv6Address
      *            address preference if underlying platform is V4/V6
      * @return InetAddress the host address
      * @throws UnknownHostException
@@ -640,7 +603,7 @@
 
     /**
      * Gets the host name of the system.
-     * 
+     *
      * @return String the system hostname
      */
     // BEGIN android-changed
@@ -665,9 +628,8 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * IP address.
-     * 
+     *
      * @return the description, as host/address.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -695,8 +657,6 @@
         }
     }
 
-    // BEGIN android-changed
-    // Copied from a newer version of harmony
     static class Cache {
         private static int maxSize = 5;
 
@@ -764,7 +724,6 @@
             }
         }
     }
-    // END android-changed
 
     /**
      * Returns true if the string is a host name, false if it is an IP Address.
@@ -778,10 +737,9 @@
      * Returns whether this address is a loopback address or not. This
      * implementation returns always {@code false}. Valid IPv4 loopback
      * addresses are 127.d.d.d The only valid IPv6 loopback address is ::1.
-     * 
+     *
      * @return {@code true} if this instance represents a loopback address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isLoopbackAddress() {
         return false;
@@ -793,14 +751,11 @@
      * <p>
      * Valid IPv6 link-local addresses are FE80::0 through to
      * FEBF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF.
-     * </p>
      * <p>
      * There are no valid IPv4 link-local addresses.
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a link-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isLinkLocalAddress() {
         return false;
@@ -812,14 +767,11 @@
      * <p>
      * Valid IPv6 site-local addresses are FEC0::0 through to
      * FEFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF.
-     * </p>
      * <p>
      * There are no valid IPv4 site-local addresses.
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a site-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isSiteLocalAddress() {
         return false;
@@ -832,15 +784,12 @@
      * Valid IPv6 link-global multicast addresses are FFxE:/112 where x is a set
      * of flags, and the additional 112 bits make up the global multicast
      * address space.
-     * </p>
      * <p>
      * Valid IPv4 global multicast addresses are between: 224.0.1.0 to
      * 238.255.255.255.
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a global multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMCGlobal() {
         return false;
@@ -853,14 +802,11 @@
      * Valid IPv6 node-local multicast addresses are FFx1:/112 where x is a set
      * of flags, and the additional 112 bits make up the node-local multicast
      * address space.
-     * </p>
      * <p>
      * There are no valid IPv4 node-local multicast addresses.
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a node-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMCNodeLocal() {
         return false;
@@ -873,14 +819,11 @@
      * Valid IPv6 link-local multicast addresses are FFx2:/112 where x is a set
      * of flags, and the additional 112 bits make up the link-local multicast
      * address space.
-     * </p>
      * <p>
      * Valid IPv4 link-local addresses are between: 224.0.0.0 to 224.0.0.255
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a link-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMCLinkLocal() {
         return false;
@@ -893,15 +836,12 @@
      * Valid IPv6 site-local multicast addresses are FFx5:/112 where x is a set
      * of flags, and the additional 112 bits make up the site-local multicast
      * address space.
-     * </p>
      * <p>
      * Valid IPv4 site-local addresses are between: 239.252.0.0 to
      * 239.255.255.255
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a site-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMCSiteLocal() {
         return false;
@@ -914,15 +854,12 @@
      * Valid IPv6 organization-local multicast addresses are FFx8:/112 where x
      * is a set of flags, and the additional 112 bits make up the
      * organization-local multicast address space.
-     * </p>
      * <p>
      * Valid IPv4 organization-local addresses are between: 239.192.0.0 to
      * 239.251.255.255
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a organization-local
      *         multicast address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMCOrgLocal() {
         return false;
@@ -931,10 +868,9 @@
     /**
      * Returns whether this is a wildcard address or not. This implementation
      * returns always {@code false}.
-     * 
+     *
      * @return {@code true} if this instance represents a wildcard address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isAnyLocalAddress() {
         return false;
@@ -944,7 +880,7 @@
      * Tries to reach this {@code InetAddress}. This method first tries to use
      * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection
      * on port 7 (Echo) of the remote host is established.
-     * 
+     *
      * @param timeout
      *            timeout in milliseconds before the test fails if no connection
      *            could be established.
@@ -954,7 +890,6 @@
      *             if an error occurs during an I/O operation.
      * @throws IllegalArgumentException
      *             if timeout is less than zero.
-     * @since Android 1.0
      */
     public boolean isReachable(int timeout) throws IOException {
         return isReachable(null, 0, timeout);
@@ -964,7 +899,7 @@
      * Tries to reach this {@code InetAddress}. This method first tries to use
      * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection
      * on port 7 (Echo) of the remote host is established.
-     * 
+     *
      * @param netif
      *            the network interface on which to connection should be
      *            established.
@@ -979,7 +914,6 @@
      *             if an error occurs during an I/O operation.
      * @throws IllegalArgumentException
      *             if ttl or timeout is less than zero.
-     * @since Android 1.0
      */
     public boolean isReachable(NetworkInterface netif, final int ttl,
             final int timeout) throws IOException {
@@ -1073,8 +1007,8 @@
                     //             InetAddress.this, addr, ttl, timeout);
                     // } else {
                         try {
-                            threadReached = isReachableByTCP(InetAddress.this,
-                                    addr, timeout);
+                            threadReached = isReachableByTCP(addr,
+                                    InetAddress.this, timeout);
                         } catch (IOException e) {
                             // do nothing
                         }
@@ -1122,7 +1056,7 @@
     //         int ttl, int timeout) throws IOException {
     //     return isReachableByMultiThread(netif, ttl, timeout, true);
     // }
-    // 
+    //
     // private boolean isReachableByTCPUseMultiThread(NetworkInterface netif,
     //         int ttl, int timeout) throws IOException {
     //     return isReachableByMultiThread(netif, ttl, timeout, false);
@@ -1135,10 +1069,10 @@
         // define traffic only for parameter
         int traffic = 0;
         boolean reached = false;
-        NETIMPL.createSocket(fd, NetUtil.preferIPv4Stack());
+        NETIMPL.createStreamSocket(fd, NetUtil.preferIPv4Stack());
         try {
             if (null != source) {
-                NETIMPL.bind(fd, 0, source);
+                NETIMPL.bind(fd, source, 0);
             }
             NETIMPL.connectStreamWithTimeoutSocket(fd, 7, timeout, traffic,
                     dest);
@@ -1161,18 +1095,15 @@
      * exactly 16 bytes. If not, an {@code UnknownHostException} is thrown.
      * <p>
      * The IP address is not validated by a name service.
-     * </p>
      * <p>
      * The high order byte is {@code ipAddress[0]}.
-     * </p>
-     * 
+     *
      * @param ipAddress
      *            is either a 4 (IPv4) or 16 (IPv6) byte long array.
      * @return an {@code InetAddress} instance representing the given IP address
      *         {@code ipAddress}.
      * @throws UnknownHostException
      *             if the given byte array has no valid length.
-     * @since Android 1.0
      */
     public static InetAddress getByAddress(byte[] ipAddress)
             throws UnknownHostException {
@@ -1187,7 +1118,7 @@
      * exactly 16 bytes. If not, an {@code UnknownHostException} is thrown. The
      * IP address is not validated by a name service. The high order byte is
      * {@code ipAddress[0]}.
-     * 
+     *
      * @param ipAddress
      *            either a 4 (IPv4) or 16 (IPv6) byte array.
      * @param scope_id
@@ -1204,10 +1135,7 @@
             for (int i = 0; i < 4; i++) {
                 copy_address[i] = ipAddress[i];
             }
-            // BEGIN adnroid-changed
-            // Copied from a newer version of harmony
             return new Inet4Address(copy_address);
-            // END android-changed
         }
 
         if (ipAddress != null && ipAddress.length == 16) {
@@ -1224,6 +1152,8 @@
             copy_address = ipAddress.clone();
             return new Inet6Address(copy_address, scope_id);
         }
+
+        // K0339=Invalid IP Address is neither 4 or 16 bytes
         throw new UnknownHostException(Msg.getString("K0339")); //$NON-NLS-1$
     }
 
@@ -1251,15 +1181,12 @@
      * UnknownHostException} will be thrown.
      * <p>
      * The host name and IP address are not validated.
-     * </p>
      * <p>
      * The hostname either be a machine alias or a valid IPv6 or IPv4 address
      * format.
-     * </p>
      * <p>
      * The high order byte is {@code ipAddress[0]}.
-     * </p>
-     * 
+     *
      * @param hostName
      *            the string representation of hostname or IP address.
      * @param ipAddress
@@ -1268,7 +1195,6 @@
      *         and hostname.
      * @throws UnknownHostException
      *             if the given byte array has no valid length.
-     * @since Android 1.0
      */
     public static InetAddress getByAddress(String hostName, byte[] ipAddress)
             throws UnknownHostException {
@@ -1284,7 +1210,7 @@
      * UnknownHostException} is thrown. The host name and IP address are not
      * validated. The hostname either be a machine alias or a valid IPv6 or IPv4
      * address format. The high order byte is {@code ipAddress[0]}.
-     * 
+     *
      * @param hostName
      *            string representation of hostname or IP address.
      * @param ipAddress
diff --git a/luni/src/main/java/java/net/InetSocketAddress.java b/luni/src/main/java/java/net/InetSocketAddress.java
index 6901053..13c10f2 100644
--- a/luni/src/main/java/java/net/InetSocketAddress.java
+++ b/luni/src/main/java/java/net/InetSocketAddress.java
@@ -23,8 +23,6 @@
 /**
  * This class represents a socket endpoint described by a IP address and a port
  * number. It is a concrete implementation of {@code SocketAddress} for IP.
- * 
- * @since Android 1.0
  */
 public class InetSocketAddress extends SocketAddress {
 
@@ -40,10 +38,9 @@
      * Creates a socket endpoint with the given port number {@code port} and the
      * wildcard address {@code InetAddress.ANY}. The range for valid port numbers
      * is between 0 and 65535 inclusive.
-     * 
+     *
      * @param port
      *            the specified port number to which this socket is bound.
-     * @since Android 1.0
      */
     public InetSocketAddress(int port) {
         this((InetAddress) null, port);
@@ -54,12 +51,11 @@
      * {@code address}. The range for valid port numbers is between 0 and 65535
      * inclusive. If {@code address} is {@code null} this socket is bound to the
      * wildcard address {@code InetAddress.ANY}.
-     * 
+     *
      * @param port
      *            the specified port number to which this socket is bound.
      * @param address
      *            the specified address to which this socket is bound.
-     * @since Android 1.0
      */
     public InetSocketAddress(InetAddress address, int port) {
         if (port < 0 || port > 65535) {
@@ -79,7 +75,7 @@
      * hostname {@code host}. The hostname is tried to be resolved and cannot be
      * {@code null}. The range for valid port numbers is between 0 and 65535
      * inclusive.
-     * 
+     *
      * @param port
      *            the specified port number to which this socket is bound.
      * @param host
@@ -88,14 +84,13 @@
      *             if a {@link SecurityManager} is installed and its {@code
      *             checkConnect()} method does not allow the resolving of the
      *             host name.
-     * @since Android 1.0
      */
     public InetSocketAddress(String host, int port) {
         this(host, port, true);
     }
 
     /*
-     * Internal contructor for InetSocketAddress(String, int) and
+     * Internal constructor for InetSocketAddress(String, int) and
      * createUnresolved(String, int);
      */
     InetSocketAddress(String host, int port, boolean needResolved) {
@@ -126,7 +121,7 @@
      * Creates an {@code InetSocketAddress} without trying to resolve the
      * hostname into an {@code InetAddress}. The address field is marked as
      * unresolved.
-     * 
+     *
      * @param host
      *            the specified hostname to which this socket is bound.
      * @param port
@@ -135,7 +130,6 @@
      * @throws IllegalArgumentException
      *             if the hostname {@code host} is {@code null} or the port is
      *             not in the range between 0 and 65535.
-     * @since Android 1.0
      */
     public static InetSocketAddress createUnresolved(String host, int port) {
         return new InetSocketAddress(host, port, false);
@@ -143,9 +137,8 @@
 
     /**
      * Gets the port number of this socket.
-     * 
+     *
      * @return the socket endpoint port number.
-     * @since Android 1.0
      */
     public final int getPort() {
         return port;
@@ -153,9 +146,8 @@
 
     /**
      * Gets the address of this socket.
-     * 
+     *
      * @return the socket endpoint address.
-     * @since Android 1.0
      */
     public final InetAddress getAddress() {
         return addr;
@@ -163,9 +155,8 @@
 
     /**
      * Gets the hostname of this socket.
-     * 
+     *
      * @return the socket endpoint hostname.
-     * @since Android 1.0
      */
     public final String getHostName() {
         return (null != addr) ? addr.getHostName() : hostname;
@@ -173,10 +164,9 @@
 
     /**
      * Returns whether this socket address is unresolved or not.
-     * 
+     *
      * @return {@code true} if this socket address is unresolved, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public final boolean isUnresolved() {
         return addr == null;
@@ -185,9 +175,8 @@
     /**
      * Gets a string representation of this socket included the address and the
      * port number.
-     * 
+     *
      * @return the address and port number as a textual representation.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -204,12 +193,11 @@
      * Compares two socket endpoints and returns true if they are equal. Two
      * socket endpoints are equal if the IP address or the hostname of both are
      * equal and they are bound to the same port.
-     * 
+     *
      * @param socketAddr
      *            the object to be tested for equality.
      * @return {@code true} if this socket and the given socket object {@code
      *         socketAddr} are equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public final boolean equals(Object socketAddr) {
@@ -243,9 +231,8 @@
 
     /**
      * Gets the hashcode of this socket.
-     * 
+     *
      * @return the appropriate hashcode.
-     * @since Android 1.0
      */
     @Override
     public final int hashCode() {
diff --git a/luni/src/main/java/java/net/JarURLConnection.java b/luni/src/main/java/java/net/JarURLConnection.java
index 11545fa..da39d9c 100644
--- a/luni/src/main/java/java/net/JarURLConnection.java
+++ b/luni/src/main/java/java/net/JarURLConnection.java
@@ -38,15 +38,11 @@
  * jar:http://www.example.com/applets/archive.jar!/test.class}</li>
  * <li>Directory Entry: {@code
  * jar:http://www.example.com/applets/archive.jar!/applets/}</li>
- * 
- * @since Android 1.0
  */
 public abstract class JarURLConnection extends URLConnection {
 
     /**
      * The location part of the represented URL.
-     * 
-     * @since Android 1.0
      */
     protected URLConnection jarFileURLConnection;
 
@@ -60,12 +56,11 @@
     /**
      * Constructs an instance of {@code JarURLConnection} that refers to the
      * specified URL.
-     * 
+     *
      * @param url
      *            the URL that contains the location to connect to.
      * @throws MalformedURLException
      *             if an invalid URL has been entered.
-     * @since Android 1.0
      */
     protected JarURLConnection(URL url) throws MalformedURLException {
         super(url);
@@ -74,10 +69,12 @@
         if ((sepIdx = file.indexOf("!/")) < 0) { //$NON-NLS-1$
             throw new MalformedURLException();
         }
-        if (file.length() == sepIdx + 2) {
+        fileURL = new URL(url.getFile().substring(0,sepIdx)); //$NON-NLS-1$
+        sepIdx += 2;
+        if (file.length() == sepIdx) {
             return;
         }
-        entryName = file.substring(sepIdx + 2, file.length());
+        entryName = file.substring(sepIdx, file.length());
         if (null != url.getRef()) {
             entryName += "#" + url.getRef(); //$NON-NLS-1$
         }
@@ -86,12 +83,11 @@
     /**
      * Returns all attributes of the {@code JarEntry} referenced by this {@code
      * JarURLConnection}.
-     * 
+     *
      * @return the attributes of the referenced {@code JarEntry}.
-     * @exception IOException
+     * @throws IOException
      *                if an I/O exception occurs while retrieving the
      *                JAR-entries.
-     * @since Android 1.0
      */
     public Attributes getAttributes() throws java.io.IOException {
         JarEntry jEntry = getJarEntry();
@@ -102,12 +98,11 @@
      * Returns all certificates of the {@code JarEntry} referenced by this
      * {@code JarURLConnection} instance. This method will return {@code null}
      * until the {@code InputStream} has been completely verified.
-     * 
+     *
      * @return the certificates of the {@code JarEntry} as an array.
-     * @exception IOException
+     * @throws IOException
      *                if there is an I/O exception occurs while getting the
      *                {@code JarEntry}.
-     * @since Android 1.0
      */
     public Certificate[] getCertificates() throws java.io.IOException {
         JarEntry jEntry = getJarEntry();
@@ -122,9 +117,8 @@
      * Gets the name of the entry referenced by this {@code JarURLConnection}.
      * The return value will be {@code null} if this instance refers to a JAR
      * file rather than an JAR file entry.
-     * 
+     *
      * @return the {@code JarEntry} name this instance refers to.
-     * @since Android 1.0
      */
     public String getEntryName() {
         return entryName;
@@ -133,12 +127,11 @@
     /**
      * Gets the {@code JarEntry} object of the entry referenced by this {@code
      * JarURLConnection}.
-     * 
+     *
      * @return the referenced {@code JarEntry} object or {@code null} if no
      *         entry name is specified.
      * @throws IOException
      *             if an error occurs while getting the file or file-entry.
-     * @since Android 1.0
      */
     public JarEntry getJarEntry() throws IOException {
         if (!connected) {
@@ -153,56 +146,44 @@
 
     /**
      * Gets the manifest file associated with this JAR-URL.
-     * 
+     *
      * @return the manifest of the referenced JAR-file.
      * @throws IOException
      *             if an error occurs while getting the manifest file.
-     * @since Android 1.0
      */
     public Manifest getManifest() throws java.io.IOException {
-        return getJarFile().getManifest();
+        return (Manifest)getJarFile().getManifest().clone();
     }
 
     /**
      * Gets the {@code JarFile} object referenced by this {@code
      * JarURLConnection}.
-     * 
+     *
      * @return the referenced JarFile object.
-     * @exception IOException
+     * @throws IOException
      *                if an I/O exception occurs while retrieving the JAR-file.
-     * @since Android 1.0
      */
     public abstract JarFile getJarFile() throws java.io.IOException;
 
     /**
      * Gets the URL to the JAR-file referenced by this {@code JarURLConnection}.
-     * 
+     *
      * @return the URL to the JAR-file or {@code null} if there was an error
      *         retrieving the URL.
-     * @since Android 1.0
      */
     public URL getJarFileURL() {
-        if (fileURL != null) {
-            return fileURL;
-        }
-        try {
-            return fileURL = new URL(url.getFile().substring(0,
-                    url.getFile().indexOf("!/"))); //$NON-NLS-1$
-        } catch (MalformedURLException e) {
-            return null;
-        }
+        return fileURL;
     }
 
     /**
      * Gets all attributes of the manifest file referenced by this {@code
      * JarURLConnection}. If this instance refers to a JAR-file rather than a
      * JAR-file entry, {@code null} will be returned.
-     * 
+     *
      * @return the attributes of the manifest file or {@code null}.
-     * @exception IOException
+     * @throws IOException
      *                if an I/O exception occurs while retrieving the {@code
      *                JarFile}.
-     * @since Android 1.0
      */
     public Attributes getMainAttributes() throws java.io.IOException {
         Manifest m = getJarFile().getManifest();
diff --git a/luni/src/main/java/java/net/MalformedURLException.java b/luni/src/main/java/java/net/MalformedURLException.java
index 386228b..cf8aa46 100644
--- a/luni/src/main/java/java/net/MalformedURLException.java
+++ b/luni/src/main/java/java/net/MalformedURLException.java
@@ -24,7 +24,6 @@
  * incorrect specification.
  * 
  * @see URL
- * @since Android 1.0
  */
 public class MalformedURLException extends IOException {
 
@@ -32,8 +31,6 @@
 
     /**
      * Constructs a new instance of this class with its walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public MalformedURLException() {
         super();
@@ -45,7 +42,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception instance.
-     * @since Android 1.0
      */
     public MalformedURLException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/net/MulticastSocket.java b/luni/src/main/java/java/net/MulticastSocket.java
index cf20890..0b1c99b 100644
--- a/luni/src/main/java/java/net/MulticastSocket.java
+++ b/luni/src/main/java/java/net/MulticastSocket.java
@@ -20,15 +20,14 @@
 import java.io.IOException;
 import java.util.Enumeration;
 
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainDatagramSocketImpl;
 import org.apache.harmony.luni.util.Msg;
 
 /**
  * This class implements a multicast socket for sending and receiving IP
  * multicast datagram packets.
- * 
+ *
  * @see DatagramSocket
- * @since Android 1.0
  */
 public class MulticastSocket extends DatagramSocket {
 
@@ -39,10 +38,9 @@
     /**
      * Constructs a multicast socket, bound to any available port on the
      * localhost.
-     * 
+     *
      * @throws IOException
      *             if an error occurs creating or binding the socket.
-     * @since Android 1.0
      */
     public MulticastSocket() throws IOException {
         super();
@@ -52,12 +50,11 @@
     /**
      * Constructs a multicast socket, bound to the specified port on the
      * localhost.
-     * 
+     *
      * @param aPort
      *            the port to bind on the localhost.
      * @throws IOException
      *             if an error occurs creating or binding the socket.
-     * @since Android 1.0
      */
     public MulticastSocket(int aPort) throws IOException {
         super(aPort);
@@ -67,12 +64,11 @@
     /**
      * Gets the network address used by this socket. This is useful on
      * multihomed machines.
-     * 
+     *
      * @return the address of the network interface through which the datagram
      *         packets are sent or received.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while getting the interface address.
-     * @since Android 1.0
      */
     public InetAddress getInterface() throws SocketException {
         checkClosedAndBind(false);
@@ -104,12 +100,12 @@
     /**
      * Gets the network interface used by this socket. This is useful on
      * multihomed machines.
-     * 
+     *
      * @return the network interface used by this socket or {@code null} if no
      *         interface is set.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while getting the interface.
-     * @since Android 1.0
+     * @since 1.4
      */
     public NetworkInterface getNetworkInterface() throws SocketException {
         checkClosedAndBind(false);
@@ -162,11 +158,10 @@
 
     /**
      * Gets the time-to-live (TTL) for multicast packets sent on this socket.
-     * 
+     *
      * @return the default value for the time-to-life field.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs reading the default value.
-     * @since Android 1.0
      */
     public int getTimeToLive() throws IOException {
         checkClosedAndBind(false);
@@ -175,13 +170,12 @@
 
     /**
      * Gets the time-to-live (TTL) for multicast packets sent on this socket.
-     * 
+     *
      * @return the default value for the time-to-life field.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs reading the default value.
      * @deprecated Replaced by {@link #getTimeToLive}
      * @see #getTimeToLive()
-     * @since Android 1.0
      */
     @Deprecated
     public byte getTTL() throws IOException {
@@ -189,21 +183,15 @@
         return impl.getTTL();
     }
 
-    @Override
-    boolean isMulticastSocket() {
-        return true;
-    }
-
     /**
      * Adds this socket to the specified multicast group. A socket must join a
      * group before data may be received. A socket may be a member of multiple
      * groups but may join any group only once.
-     * 
+     *
      * @param groupAddr
      *            the multicast group to be joined.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while joining a group.
-     * @since Android 1.0
      */
     public void joinGroup(InetAddress groupAddr) throws IOException {
         checkClosedAndBind(false);
@@ -221,19 +209,19 @@
      * Adds this socket to the specified multicast group. A socket must join a
      * group before data may be received. A socket may be a member of multiple
      * groups but may join any group only once.
-     * 
+     *
      * @param groupAddress
      *            the multicast group to be joined.
      * @param netInterface
      *            the network interface on which the datagram packets will be
      *            received.
-     * @exception IOException
+     * @throws IOException
      *                if the specified address is not a multicast address.
-     * @exception SecurityException
+     * @throws SecurityException
      *                if the caller is not authorized to join the group.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if no multicast group is specified.
-     * @since Android 1.0
+     * @since 1.4
      */
     public void joinGroup(SocketAddress groupAddress,
             NetworkInterface netInterface) throws IOException {
@@ -271,14 +259,15 @@
 
     /**
      * Removes this socket from the specified multicast group.
-     * 
+     *
      * @param groupAddr
      *            the multicast group to be left.
-     * @exception IOException
+     * @throws NullPointerException
+     *                if {@code groupAddr} is {@code null}.
+     * @throws IOException
      *                if the specified group address is not a multicast address.
-     * @exception SecurityException
+     * @throws SecurityException
      *                if the caller is not authorized to leave the group.
-     * @since Android 1.0
      */
     public void leaveGroup(InetAddress groupAddr) throws IOException {
         checkClosedAndBind(false);
@@ -294,19 +283,19 @@
 
     /**
      * Removes this socket from the specified multicast group.
-     * 
+     *
      * @param groupAddress
      *            the multicast group to be left.
      * @param netInterface
      *            the network interface on which the addresses should be
      *            dropped.
-     * @exception IOException
+     * @throws IOException
      *                if the specified group address is not a multicast address.
-     * @exception SecurityException
+     * @throws SecurityException
      *                if the caller is not authorized to leave the group.
-     * @exception IllegalArgumentException
-     *                if no multicast group is specified.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if {@code groupAddress} is {@code null}.
+     * @since 1.4
      */
     public void leaveGroup(SocketAddress groupAddress,
             NetworkInterface netInterface) throws IOException {
@@ -344,16 +333,15 @@
     /**
      * Send the packet on this socket. The packet must satisfy the security
      * policy before it may be sent.
-     * 
+     *
      * @param pack
      *            the {@code DatagramPacket} to send
      * @param ttl
      *            the TTL setting for this transmission, overriding the socket
      *            default
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while sending data or setting options.
      * @deprecated use {@link #setTimeToLive}.
-     * @since Android 1.0
      */
     @Deprecated
     public void send(DatagramPacket pack, byte ttl) throws IOException {
@@ -384,13 +372,12 @@
      * Sets the interface address used by this socket. This allows to send
      * multicast packets on a different interface than the default interface of
      * the local system. This is useful on multihomed machines.
-     * 
+     *
      * @param addr
      *            the multicast interface network address to set.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the network interface
      *                address option.
-     * @since Android 1.0
      */
     public void setInterface(InetAddress addr) throws SocketException {
         checkClosedAndBind(false);
@@ -435,13 +422,13 @@
     /**
      * Sets the network interface used by this socket. This is useful for
      * multihomed machines.
-     * 
+     *
      * @param netInterface
      *            the multicast network interface to set.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the network interface
      *                option.
-     * @since Android 1.0
+     * @since 1.4
      */
     public void setNetworkInterface(NetworkInterface netInterface)
             throws SocketException {
@@ -529,13 +516,12 @@
     /**
      * Sets the time-to-live (TTL) for multicast packets sent on this socket.
      * Valid TTL values are between 0 and 255 inclusive.
-     * 
+     *
      * @param ttl
      *            the default time-to-live field value for packets sent on this
      *            socket. {@code 0 <= ttl <= 255}.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while setting the TTL option value.
-     * @since Android 1.0
      */
     public void setTimeToLive(int ttl) throws IOException {
         checkClosedAndBind(false);
@@ -548,15 +534,14 @@
     /**
      * Sets the time-to-live (TTL) for multicast packets sent on this socket.
      * Valid TTL values are between 0 and 255 inclusive.
-     * 
+     *
      * @param ttl
      *            the default time-to-live field value for packets sent on this
      *            socket: {@code 0 <= ttl <= 255}.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while setting the TTL option value.
      * @deprecated Replaced by {@link #setTimeToLive}
      * @see #setTimeToLive(int)
-     * @since Android 1.0
      */
     @Deprecated
     public void setTTL(byte ttl) throws IOException {
@@ -568,11 +553,10 @@
     synchronized void createSocket(int aPort, InetAddress addr)
             throws SocketException {
         impl = factory != null ? factory.createDatagramSocketImpl()
-                : SocketImplProvider.getMulticastSocketImpl();
+                : new PlainDatagramSocketImpl();
         impl.create();
         try {
-            // the required default options are now set in the VM where they
-            // should be
+            impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.TRUE);
             impl.bind(aPort, addr);
             isBound = true;
         } catch (SocketException e) {
@@ -585,14 +569,14 @@
      * Constructs a {@code MulticastSocket} bound to the host/port specified by
      * the {@code SocketAddress}, or an unbound {@code DatagramSocket} if the
      * {@code SocketAddress} is {@code null}.
-     * 
+     *
      * @param localAddr
      *            the local machine address and port to bind to.
      * @throws IllegalArgumentException
      *             if the {@code SocketAddress} is not supported.
      * @throws IOException
      *             if an error occurs creating or binding the socket.
-     * @since Android 1.0
+     * @since 1.4
      */
     public MulticastSocket(SocketAddress localAddr) throws IOException {
         super(localAddr);
@@ -601,12 +585,12 @@
 
     /**
      * Gets the state of the {@code SocketOptions.IP_MULTICAST_LOOP}.
-     * 
+     *
      * @return {@code true} if the IP multicast loop is enabled, {@code false}
      *         otherwise.
      * @throws SocketException
      *             if the socket is closed or the option is invalid.
-     * @since Android 1.0
+     * @since 1.4
      */
     public boolean getLoopbackMode() throws SocketException {
         checkClosedAndBind(false);
@@ -616,13 +600,13 @@
 
     /**
      * Sets the {@code SocketOptions.IP_MULTICAST_LOOP}.
-     * 
+     *
      * @param loop
      *            the value for the socket option socket {@code
      *            SocketOptions.IP_MULTICAST_LOOP}.
      * @throws SocketException
      *             if the socket is closed or the option is invalid.
-     * @since Android 1.0
+     * @since 1.4
      */
     public void setLoopbackMode(boolean loop) throws SocketException {
         checkClosedAndBind(false);
diff --git a/luni/src/main/java/java/net/NegCacheElement.java b/luni/src/main/java/java/net/NegCacheElement.java
index 7285a14..e166db4 100644
--- a/luni/src/main/java/java/net/NegCacheElement.java
+++ b/luni/src/main/java/java/net/NegCacheElement.java
@@ -18,28 +18,27 @@
 
 /**
  * This class is used to hold information about failed host name lookups.
- * 
+ *
  * @see NegativeCache
- * @since Android 1.0
  */
 class NegCacheElement {
 
     // we need the time to figure out when the entry is stale
     // BEGIN android-changed
     final long nanoTimeAdded = System.nanoTime();
+    // END android-changed
 
     // holds the name of the host for which the lookup failed
     final String hostName;
-    
+
     /**
      * Constructor used to set the hostname for the entry for which the lookup
      * failed.
-     * 
+     *
      * @param hostName
      *            name of the host for which the lookup failed.
      */
     NegCacheElement(String hostName) {
         this.hostName = hostName;
     }
-    // END android-changed
 }
diff --git a/luni/src/main/java/java/net/NegativeCache.java b/luni/src/main/java/java/net/NegativeCache.java
index 58078fc..e66d3f3 100644
--- a/luni/src/main/java/java/net/NegativeCache.java
+++ b/luni/src/main/java/java/net/NegativeCache.java
@@ -25,16 +25,13 @@
 /**
  * This class is used to maintain the negative name lookup cache, which caches
  * host names which could not be resolved, as a security feature.
- * 
+ *
  * @see NegCacheElement
- * @since Android 1.0
  */
 class NegativeCache<K, V> extends LinkedHashMap<K, V> {
 
     private static final long serialVersionUID = 1L;
 
-    // BEGIN android-changed
-    // Copied from a newer version of harmony
     private static NegativeCache<String, NegCacheElement> negCache;
 
     // maximum number of entries in the cache
@@ -42,13 +39,17 @@
 
     // the loading for the cache
     private static final float LOADING = 0.75F;
-    // END android-changed
 
     /**
-     * Returns the hostname for the cache element.
-     * 
-     * @return hostName name of the host for which the lookup failed.
-     * @since Android 1.0
+     * Constructs a negative cache for name lookups.
+     *
+     * @param initialCapacity
+     *            the initial size of the cache.
+     * @param loadFactor
+     *            the load factor of the backing map.
+     * @param accessOrder
+     *            if {@code true} indicates that traversal order should begin
+     *            with most recently accessed element.
      */
     NegativeCache(int initialCapacity, float loadFactor, boolean accessOrder) {
         super(initialCapacity, loadFactor, accessOrder);
@@ -59,10 +60,9 @@
      * size has grown beyond the maximum size allowed for the cache. A {@code
      * LinkedHashMap} is created such that the least recently used entry is
      * deleted.
-     * 
+     *
      * @param eldest
      *            the map entry which will be deleted if we return {@code true}.
-     * @since Android 1.0
      */
     @Override
     protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
@@ -72,17 +72,13 @@
     /**
      * Adds the host name and the corresponding name lookup fail message to the
      * cache.
-     * 
+     *
      * @param hostName
      *            the name of the host for which the lookup failed.
      * @param failedMessage
      *            the message returned when the lookup fails.
-     * @since Android 1.0
      */
     static synchronized void put(String hostName, String failedMessage) {
-        // BEGIN android-note
-        // Made synchronized. copied from a newer version of harmony
-        // END android-note
         checkCacheExists();
         negCache.put(hostName, new NegCacheElement(failedMessage));
     }
@@ -90,17 +86,13 @@
     /**
      * Returns the message of the negative cache if the entry has not yet
      * expired.
-     * 
+     *
      * @param hostName
      *            the name of the host for which we look up the entry.
      * @return the message which was returned when the host lookup failed if the
      *         entry has not yet expired.
-     * @since Android 1.0
      */
     static synchronized String getFailedMessage(String hostName) {
-        // BEGIN android-note
-        // Made synchronized. copied from a newer version of harmony
-        // END android-note
         checkCacheExists();
         NegCacheElement element = negCache.get(hostName);
         if (element != null) {
@@ -130,10 +122,7 @@
             }
         }
         if (element != null) {
-            // BEGIN android-changed
-            // Copied from a newer version of harmony
             return element.hostName;
-            // END android-changed
         }
         return null;
     }
@@ -148,13 +137,9 @@
     // END android-added
 
     /**
-     * This method checks whether the cache was already created and if not
-     * creates it.
+     * This method checks if we have created the cache and if not creates it
      */
     static synchronized void checkCacheExists() {
-        // BEGIN android-note
-        // Made synchronized. copied from a newer version of harmony
-        // END android-note
         if (negCache == null) {
             /*
              * Create with the access order set so ordering is based on when the
diff --git a/luni/src/main/java/java/net/NetPermission.java b/luni/src/main/java/java/net/NetPermission.java
index e7cca8b..bac9d89 100644
--- a/luni/src/main/java/java/net/NetPermission.java
+++ b/luni/src/main/java/java/net/NetPermission.java
@@ -31,11 +31,9 @@
  * <dd>Allows a stream (protocol) handler to be set when constructing an URL
  * object</dd>
  * </dl>
- * </p>
  * 
  * @see java.security.BasicPermission
  * @see SecurityManager
- * @since Android 1.0
  */
 public final class NetPermission extends java.security.BasicPermission {
 
@@ -46,7 +44,6 @@
      * 
      * @param name
      *            the name of the new NetPermission instance.
-     * @since Android 1.0
      */
     public NetPermission(String name) {
         super(name);
@@ -60,7 +57,6 @@
      *            the name of the new {@code NetPermission} instance.
      * @param actions
      *            the ignored action string.
-     * @since Android 1.0
      */
     public NetPermission(String name, String actions) {
         super(name, actions);
diff --git a/luni/src/main/java/java/net/NetworkInterface.java b/luni/src/main/java/java/net/NetworkInterface.java
index 68452e6b..091eb9f 100644
--- a/luni/src/main/java/java/net/NetworkInterface.java
+++ b/luni/src/main/java/java/net/NetworkInterface.java
@@ -28,8 +28,6 @@
  * interface is defined by its address and a platform dependent name. The class
  * provides methods to get all information about the available interfaces of the
  * system or to identify the local interface of a joined multicast group.
- * 
- * @since Android 1.0
  */
 public final class NetworkInterface extends Object {
 
@@ -115,7 +113,6 @@
      * Gets the name associated with this network interface.
      * 
      * @return the name of this {@code NetworkInterface} instance.
-     * @since Android 1.0
      */
     public String getName() {
         return name;
@@ -125,7 +122,6 @@
      * Gets a list of addresses bound to this network interface.
      * 
      * @return the address list of the represented network interface.
-     * @since Android 1.0
      */
     public Enumeration<InetAddress> getInetAddresses() {
         /*
@@ -192,7 +188,6 @@
      * 
      * @return the display name of this network interface or the name if the
      *         display name is not available.
-     * @since Android 1.0
      */
     public String getDisplayName() {
         /*
@@ -217,7 +212,6 @@
      *             information.
      * @throws NullPointerException
      *             if the given interface's name is {@code null}.
-     * @since Android 1.0
      */
     public static NetworkInterface getByName(String interfaceName)
             throws SocketException {
@@ -244,7 +238,7 @@
 
     /**
      * Gets the specific network interface according to the given address.
-     * 
+     *
      * @param address
      *            the address to identify the searched network interface.
      * @return the network interface with the specified address if one exists or
@@ -254,7 +248,6 @@
      *             information.
      * @throws NullPointerException
      *             if the given interface address is invalid.
-     * @since Android 1.0
      */
     public static NetworkInterface getByInetAddress(InetAddress address)
             throws SocketException {
@@ -302,7 +295,6 @@
      * @throws SocketException
      *             if an error occurs while getting the network interface
      *             information.
-     * @since Android 1.0
      */
     public static Enumeration<NetworkInterface> getNetworkInterfaces()
             throws SocketException {
@@ -343,7 +335,6 @@
      * @return {@code true} if the specified object is equal to this {@code
      *         NetworkInterface}, {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -412,7 +403,6 @@
      * generated using this name.
      * 
      * @return the hashcode value for this {@code NetworkInterface} instance.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -427,7 +417,6 @@
      * network interface.
      * 
      * @return the textual representation for this network interface.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/luni/src/main/java/java/net/NoRouteToHostException.java b/luni/src/main/java/java/net/NoRouteToHostException.java
index 042ccd4..f2e2c36 100644
--- a/luni/src/main/java/java/net/NoRouteToHostException.java
+++ b/luni/src/main/java/java/net/NoRouteToHostException.java
@@ -21,8 +21,6 @@
  * The {@code NoRouteToHostException} will be thrown while attempting to connect
  * to a remote host but the host cannot be reached for instance because of a
  * badly configured router or a blocking firewall.
- * 
- * @since Android 1.0
  */
 public class NoRouteToHostException extends SocketException {
 
@@ -30,8 +28,6 @@
 
     /**
      * Constructs a new instance of this exception with its walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public NoRouteToHostException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NoRouteToHostException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/net/PasswordAuthentication.java b/luni/src/main/java/java/net/PasswordAuthentication.java
index 324f878..735810d 100644
--- a/luni/src/main/java/java/net/PasswordAuthentication.java
+++ b/luni/src/main/java/java/net/PasswordAuthentication.java
@@ -20,9 +20,8 @@
 /**
  * This immutable class is a data structure that encapsulates username and
  * password which is used by the {@code Authenticator} class.
- * 
+ *
  * @see Authenticator
- * @since Android 1.0
  */
 public final class PasswordAuthentication {
 
@@ -38,7 +37,6 @@
      *            the username to store.
      * @param password
      *            the associated password to store.
-     * @since Android 1.0
      */
     public PasswordAuthentication(String userName, char[] password) {
         this.userName = userName;
@@ -51,7 +49,6 @@
      * longer needed.
      * 
      * @return the copied password.
-     * @since Android 1.0
      */
     public char[] getPassword() {
         return password.clone();
@@ -61,7 +58,6 @@
      * Gets the username stored by this instance.
      * 
      * @return the stored username.
-     * @since Android 1.0
      */
     public String getUserName() {
         return userName;
diff --git a/luni/src/main/java/java/net/PortUnreachableException.java b/luni/src/main/java/java/net/PortUnreachableException.java
index 973a978..2b5b25b 100644
--- a/luni/src/main/java/java/net/PortUnreachableException.java
+++ b/luni/src/main/java/java/net/PortUnreachableException.java
@@ -27,8 +27,6 @@
 
     /**
      * Constructs a new instance of this class with its walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public PortUnreachableException() {
     }
@@ -39,7 +37,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public PortUnreachableException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/net/ProtocolException.java b/luni/src/main/java/java/net/ProtocolException.java
index f32dedc..ebbdc44 100644
--- a/luni/src/main/java/java/net/ProtocolException.java
+++ b/luni/src/main/java/java/net/ProtocolException.java
@@ -21,8 +21,6 @@
  * Signals that either a connection attempt to a socket of the wrong type, the
  * application of an unsupported operation or that a general error in the
  * underlying protocol has occurred.
- * 
- * @since Android 1.0
  */
 public class ProtocolException extends java.io.IOException {
 
@@ -30,8 +28,6 @@
 
     /**
      * Constructs a new instance of this class with its walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public ProtocolException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ProtocolException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/net/Proxy.java b/luni/src/main/java/java/net/Proxy.java
index df0383d..3442339 100644
--- a/luni/src/main/java/java/net/Proxy.java
+++ b/luni/src/main/java/java/net/Proxy.java
@@ -25,8 +25,6 @@
  * <li>DIRECT</li>
  * <li>HTTP</li>
  * <li>SOCKS</li></ul
- * 
- * @since Android 1.0
  */
 public class Proxy {
 
@@ -34,8 +32,6 @@
      * Represents the proxy type setting {@code Proxy.Type.DIRECT}. It tells
      * protocol handlers that there is no proxy to be used. The address is set
      * to {@code null}.
-     * 
-     * @since Android 1.0
      */
     public static final Proxy NO_PROXY = new Proxy();
 
@@ -58,7 +54,6 @@
      *             if the parameter {@code type} is set to {@code
      *             Proxy.Type.DIRECT} or the value for {@code SocketAddress} is
      *             {@code null}.
-     * @since Android 1.0
      */
     public Proxy(Proxy.Type type, SocketAddress sa) {
         /*
@@ -86,7 +81,6 @@
      * Gets the type of this {@code Proxy} instance.
      * 
      * @return the stored proxy type.
-     * @since Android 1.0
      */
     public Proxy.Type type() {
         return type;
@@ -97,7 +91,6 @@
      * 
      * @return the stored proxy address or {@code null} if the proxy type is
      *         {@code DIRECT}.
-     * @since Android 1.0
      */
     public SocketAddress address() {
         return address;
@@ -107,9 +100,8 @@
      * Gets a textual representation of this {@code Proxy} instance. The string
      * includes the two parts {@code type.toString()} and {@code
      * address.toString()} if {@code address} is not {@code null}.
-     * 
+     *
      * @return the representing string of this proxy.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -131,7 +123,6 @@
      * @return {@code true} if the given object represents the same {@code
      *         Proxy} as this instance, {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public final boolean equals(Object obj) {
@@ -150,7 +141,6 @@
      * Gets the hashcode for this {@code Proxy} instance.
      * 
      * @return the hashcode value for this Proxy instance.
-     * @since Android 1.0
      */
     @Override
     public final int hashCode() {
@@ -165,8 +155,6 @@
     /**
      * {@code Enum} class for the proxy type. Possible options are {@code
      * DIRECT}, {@code HTTP} and {@code SOCKS}.
-     * 
-     * @since Android 1.0
      */
     public enum Type {
         /**
diff --git a/luni/src/main/java/java/net/ProxySelector.java b/luni/src/main/java/java/net/ProxySelector.java
index aad4bcc..334ea1e 100644
--- a/luni/src/main/java/java/net/ProxySelector.java
+++ b/luni/src/main/java/java/net/ProxySelector.java
@@ -24,8 +24,6 @@
  * can be set as default by calling the {@code setDefault()} method. If a
  * connection can't be established, the caller should notify the proxy selector
  * by invoking the {@code connectFailed()} method.
- * 
- * @since Android 1.0
  */
 public abstract class ProxySelector {
 
@@ -47,8 +45,6 @@
 
     /**
      * Creates a new {@code ProxySelector} instance.
-     * 
-     * @since Android 1.0
      */
     public ProxySelector() {
         super();
@@ -61,7 +57,6 @@
      * @throws SecurityException
      *             if a security manager is installed but it doesn't have the
      *             NetPermission("getProxySelector").
-     * @since Android 1.0
      */
     public static ProxySelector getDefault() {
         SecurityManager sm = System.getSecurityManager();
@@ -83,7 +78,6 @@
      * @throws SecurityException
      *             if a security manager is installed but it doesn't have the
      *             NetPermission("setProxySelector").
-     * @since Android 1.0
      */
     public static void setDefault(ProxySelector selector) {
         SecurityManager sm = System.getSecurityManager();
@@ -101,14 +95,14 @@
      * <li>https URI stands for https connection.</li>
      * <li>ftp URI stands for ftp connection.</li>
      * <li>socket:://ip:port URI stands for tcp client sockets connection.</li>
-     * </p>
-     * 
+     *
      * @param uri
      *            the target URI object.
      * @return a list containing all applicable proxies. If no proxy is
      *         available, the list contains only the {@code Proxy.NO_PROXY}
      *         element.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *             if {@code uri} is {@code null}.
      */
     public abstract List<Proxy> select(URI uri);
 
@@ -125,8 +119,9 @@
      * @param ioe
      *            the exception which was thrown during connection
      *            establishment.
+     * @throws IllegalArgumentException
+     *             if any argument is {@code null}.
      * @see #select(URI)
-     * @since Android 1.0
      */
     public abstract void connectFailed(URI uri, SocketAddress sa,
             IOException ioe);
diff --git a/luni/src/main/java/java/net/ProxySelectorImpl.java b/luni/src/main/java/java/net/ProxySelectorImpl.java
index 79ce0cf..fa8d049 100644
--- a/luni/src/main/java/java/net/ProxySelectorImpl.java
+++ b/luni/src/main/java/java/net/ProxySelectorImpl.java
@@ -30,9 +30,8 @@
 
 /**
  * Default implementation for {@code ProxySelector}.
- * 
- * @since Android 1.0
  */
+@SuppressWarnings("unchecked")
 class ProxySelectorImpl extends ProxySelector {
 
     private static final int HTTP_PROXY_PORT = 80;
@@ -239,7 +238,7 @@
      */
     private boolean isNonProxyHost(String host, String nonProxyHosts) {
         // nonProxyHosts is not set
-        if (null == nonProxyHosts) {
+        if (null == host || null == nonProxyHosts) {
             return false;
         }
         // Construct regex expression of nonProxyHosts
diff --git a/luni/src/main/java/java/net/ResponseCache.java b/luni/src/main/java/java/net/ResponseCache.java
index e7a0aca..427b63d 100644
--- a/luni/src/main/java/java/net/ResponseCache.java
+++ b/luni/src/main/java/java/net/ResponseCache.java
@@ -28,24 +28,20 @@
  * getDefault()}. If {@code URLConnection#useCaches} is set, {@code
  * URLConnection} class will use {@code ResponseCache} to store and get
  * resources.
- * </p>
  * <p>
  * Whether the resource is cached depends on the implementation of {@code
  * ResponseCache}. If so, a {@code CacheResponse} is returned from which the
  * stream handler reads. If the stream handler fails to get a resource from the
  * cache, it must get the resource from its original location.
- * </p>
  * <p>
  * To write to the cache, the protocol handlers call {@code put()}, upon which a
  * {@code CacheRequest} is supplied to which the resources are written.
- * </p>
- * 
+ *
  * @see #put(URI, URLConnection)
  * @see CacheRequest
  * @see CacheResponse
  * @see URLConnection
  * @see URLStreamHandler
- * @since Android 1.0
  */
 public abstract class ResponseCache {
 
@@ -92,8 +88,6 @@
 
     /**
      * Creates a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public ResponseCache() {
         super();
@@ -106,7 +100,6 @@
      * @throws SecurityException
      *             if a security manager is installed but it doesn't have the
      *             {@code NetPermission("getResponseCache")}.
-     * @since Android 1.0
      */
     public static ResponseCache getDefault() {
         checkGetResponseCachePermission();
@@ -126,7 +119,6 @@
      * @throws SecurityException
      *             if a security manager is installed but it doesn't have the
      *             {@code NetPermission("setResponseCache")}.
-     * @since Android 1.0
      */
     public static void setDefault(ResponseCache responseCache) {
         checkSetResponseCachePermission();
@@ -149,7 +141,6 @@
      *             if an I/O error occurs while getting the cached data.
      * @throws IllegalArgumentException
      *             if any one of the parameters is set to {@code null}.
-     * @since Android 1.0
      */
     public abstract CacheResponse get(URI uri, String rqstMethod,
             Map<String, List<String>> rqstHeaders) throws IOException;
@@ -171,7 +162,6 @@
      *             if an I/O error occurs while adding the resource.
      * @throws IllegalArgumentException
      *             if any one of the parameters is set to {@code null}.
-     * @since Android 1.0
      */
     public abstract CacheRequest put(URI uri, URLConnection conn)
             throws IOException;
diff --git a/luni/src/main/java/java/net/SecureCacheResponse.java b/luni/src/main/java/java/net/SecureCacheResponse.java
index fff6b82..0031b3a 100644
--- a/luni/src/main/java/java/net/SecureCacheResponse.java
+++ b/luni/src/main/java/java/net/SecureCacheResponse.java
@@ -27,14 +27,11 @@
  * protocol like TLS or SSL.
  * 
  * @see ResponseCache
- * @since Android 1.0
  */
 public abstract class SecureCacheResponse extends CacheResponse {
 
     /**
      * Creates a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public SecureCacheResponse() {
         super();
@@ -45,7 +42,6 @@
      * to retrieve the network resource.
      * 
      * @return the cipher suite string.
-     * @since Android 1.0
      */
     public abstract String getCipherSuite();
 
@@ -57,7 +53,6 @@
      * 
      * @return the certificate chain that was sent to the server. If no
      *         certificate chain was sent, the method returns {@code null}.
-     * @since Android 1.0
      */
     public abstract List<Certificate> getLocalCertificateChain();
 
@@ -71,7 +66,6 @@
      * @return the server's certificate chain.
      * @throws SSLPeerUnverifiedException
      *             if the peer is unverified.
-     * @since Android 1.0
      */
     public abstract List<Certificate> getServerCertificateChain()
             throws SSLPeerUnverifiedException;
@@ -84,7 +78,6 @@
      * @return a principal object representing the server's principal.
      * @throws SSLPeerUnverifiedException
      *             if the peer is unverified.
-     * @since Android 1.0
      */
     public abstract Principal getPeerPrincipal()
             throws SSLPeerUnverifiedException;
@@ -97,7 +90,6 @@
      * @return the local principal object being sent to the server. Returns an
      *         {@code X500Principal} object for X509-based cipher suites. If no
      *         principal was sent, it returns {@code null}.
-     * @since Android 1.0
      */
     public abstract Principal getLocalPrincipal();
 }
diff --git a/luni/src/main/java/java/net/ServerSocket.java b/luni/src/main/java/java/net/ServerSocket.java
index 5f7e079..fc3ad10 100644
--- a/luni/src/main/java/java/net/ServerSocket.java
+++ b/luni/src/main/java/java/net/ServerSocket.java
@@ -20,9 +20,8 @@
 import java.io.IOException;
 import java.nio.channels.ServerSocketChannel;
 
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainServerSocketImpl;
 import org.apache.harmony.luni.platform.Platform;
-
 import org.apache.harmony.luni.util.Msg;
 
 /**
@@ -30,8 +29,6 @@
  * connections. A {@code ServerSocket} handles the requests and sends back an
  * appropriate reply. The actual tasks that a server socket must accomplish are
  * implemented by an internal {@code SocketImpl} instance.
- * 
- * @since Android 1.0
  */
 public class ServerSocket {
 
@@ -44,7 +41,7 @@
     private boolean isBound;
 
     private boolean isClosed;
-    
+
     static {
         Platform.getNetworkSystem().oneTimeInitialization(true);
     }
@@ -52,14 +49,13 @@
     /**
      * Constructs a new {@code ServerSocket} instance which is not bound to any
      * port. The default number of pending connections may be backlogged.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while creating the server socket.
-     * @since Android 1.0
      */
     public ServerSocket() throws IOException {
         impl = factory != null ? factory.createSocketImpl()
-                : SocketImplProvider.getServerSocketImpl();
+                : new PlainServerSocketImpl();
     }
 
     /**
@@ -81,12 +77,11 @@
      * Constructs a new {@code ServerSocket} instance bound to the nominated
      * port on the localhost. The default number of pending connections may be
      * backlogged. If {@code aport} is 0 a free port is assigned to the socket.
-     * 
+     *
      * @param aport
      *            the port number to listen for connection requests on.
      * @throws IOException
      *             if an error occurs while creating the server socket.
-     * @since Android 1.0
      */
     public ServerSocket(int aport) throws IOException {
         this(aport, defaultBacklog(), InetAddress.ANY);
@@ -97,7 +92,7 @@
      * port on the localhost. The number of pending connections that may be
      * backlogged is specified by {@code backlog}. If {@code aport} is 0 a free
      * port is assigned to the socket.
-     * 
+     *
      * @param aport
      *            the port number to listen for connection requests on.
      * @param backlog
@@ -105,7 +100,6 @@
      *            will be rejected.
      * @throws IOException
      *             if an error occurs while creating the server socket.
-     * @since Android 1.0
      */
     public ServerSocket(int aport, int backlog) throws IOException {
         this(aport, backlog, InetAddress.ANY);
@@ -116,7 +110,7 @@
      * local host address and port. The number of pending connections that may
      * be backlogged is specified by {@code backlog}. If {@code aport} is 0 a
      * free port is assigned to the socket.
-     * 
+     *
      * @param aport
      *            the port number to listen for connection requests on.
      * @param localAddr
@@ -126,14 +120,13 @@
      *            will be rejected.
      * @throws IOException
      *             if an error occurs while creating the server socket.
-     * @since Android 1.0
      */
     public ServerSocket(int aport, int backlog, InetAddress localAddr)
             throws IOException {
         super();
         checkListen(aport);
         impl = factory != null ? factory.createSocketImpl()
-                : SocketImplProvider.getServerSocketImpl();
+                : new PlainServerSocketImpl();
         InetAddress addr = localAddr == null ? InetAddress.ANY : localAddr;
 
         synchronized (this) {
@@ -154,11 +147,10 @@
      * Waits for an incoming request and blocks until the connection is opened.
      * This method returns a socket object representing the just opened
      * connection.
-     * 
+     *
      * @return the connection representing socket.
      * @throws IOException
      *             if an error occurs while accepting a new connection.
-     * @since Android 1.0
      */
     public Socket accept() throws IOException {
         checkClosedAndCreate(false);
@@ -190,10 +182,9 @@
      * Checks whether the server may listen for connection requests on {@code
      * aport}. Throws an exception if the port is outside the valid range
      * {@code 0 <= aport <= 65535 }or does not satisfy the security policy.
-     * 
+     *
      * @param aPort
      *            the candidate port to listen on.
-     * @since Android 1.0
      */
     void checkListen(int aPort) {
         if (aPort < 0 || aPort > 65535) {
@@ -208,10 +199,9 @@
     /**
      * Closes this server socket and its implementation. Any attempt to connect
      * to this socket thereafter will fail.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this socket.
-     * @since Android 1.0
      */
     public void close() throws IOException {
         isClosed = true;
@@ -222,7 +212,7 @@
      * Answer the default number of pending connections on a server socket. If
      * the backlog value maximum is reached, any subsequent incoming request is
      * rejected.
-     * 
+     *
      * @return int the default number of pending connection requests
      */
     static int defaultBacklog() {
@@ -232,9 +222,8 @@
     /**
      * Gets the local IP address of this server socket or {@code null} if the
      * socket is unbound. This is useful for multihomed hosts.
-     * 
+     *
      * @return the local address of this server socket.
-     * @since Android 1.0
      */
     public InetAddress getInetAddress() {
         if (!isBound()) {
@@ -246,9 +235,8 @@
     /**
      * Gets the local port of this server socket or {@code -1} if the socket is
      * unbound.
-     * 
+     *
      * @return the local port this server is listening on.
-     * @since Android 1.0
      */
     public int getLocalPort() {
         if (!isBound()) {
@@ -260,11 +248,10 @@
     /**
      * Gets the timeout period of this server socket. This is the time the
      * server will wait listening for accepted connections before exiting.
-     * 
+     *
      * @return the listening timeout value of this server socket.
      * @throws IOException
      *             if the option cannot be retrieved.
-     * @since Android 1.0
      */
     public synchronized int getSoTimeout() throws IOException {
         if (!isCreated) {
@@ -287,13 +274,12 @@
     /**
      * Invokes the server socket implementation to accept a connection on the
      * given socket {@code aSocket}.
-     * 
+     *
      * @param aSocket
      *            the concrete {@code SocketImpl} to accept the connection
      *            request on.
      * @throws IOException
      *             if the connection cannot be accepted.
-     * @since Android 1.0
      */
     protected final void implAccept(Socket aSocket) throws IOException {
         impl.accept(aSocket.impl);
@@ -304,13 +290,12 @@
      * Sets the server socket implementation factory of this instance. This
      * method may only be invoked with sufficient security privilege and only
      * once during the application lifetime.
-     * 
+     *
      * @param aFactory
      *            the streaming socket factory to be used for further socket
      *            instantiations.
      * @throws IOException
      *             if the factory could not be set or is already set.
-     * @since Android 1.0
      */
     public static synchronized void setSocketFactory(SocketImplFactory aFactory)
             throws IOException {
@@ -328,12 +313,11 @@
      * Sets the timeout period of this server socket. This is the time the
      * server will wait listening for accepted connections before exiting. This
      * value must be a positive number.
-     * 
+     *
      * @param timeout
      *            the listening timeout value of this server socket.
      * @throws SocketException
      *             if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException {
         checkClosedAndCreate(true);
@@ -347,9 +331,8 @@
      * Returns a textual representation of this server socket including the
      * address, port and the state. The port field is set to {@code 0} if there
      * is no connection to the server socket.
-     * 
+     *
      * @return the textual socket representation.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -371,7 +354,7 @@
      * number of pending connections may be backlogged. If the {@code localAddr}
      * is set to {@code null} the socket will be bound to an available local
      * address on any free port of the system.
-     * 
+     *
      * @param localAddr
      *            the local address and port to bind on.
      * @throws IllegalArgumentException
@@ -379,7 +362,6 @@
      * @throws IOException
      *             if the socket is already bound or a problem occurs during
      *             binding.
-     * @since Android 1.0
      */
     public void bind(SocketAddress localAddr) throws IOException {
         bind(localAddr, defaultBacklog());
@@ -391,7 +373,7 @@
      * available local address on any free port of the system. The value for
      * {@code backlog} must e greater than {@code 0} otherwise the default value
      * will be used.
-     * 
+     *
      * @param localAddr
      *            the local machine address and port to bind on.
      * @param backlog
@@ -402,7 +384,6 @@
      * @throws IOException
      *             if the socket is already bound or a problem occurs during
      *             binding.
-     * @since Android 1.0
      */
     public void bind(SocketAddress localAddr, int backlog) throws IOException {
         checkClosedAndCreate(true);
@@ -443,9 +424,8 @@
     /**
      * Gets the local socket address of this server socket or {@code null} if
      * the socket is unbound. This is useful on multihomed hosts.
-     * 
+     *
      * @return the local socket address and port this socket is bound to.
-     * @since Android 1.0
      */
     public SocketAddress getLocalSocketAddress() {
         if (!isBound()) {
@@ -457,9 +437,8 @@
     /**
      * Returns whether this server socket is bound to a local address and port
      * or not.
-     * 
+     *
      * @return {@code true} if this socket is bound, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isBound() {
         return isBound;
@@ -467,9 +446,8 @@
 
     /**
      * Returns whether this server socket is closed or not.
-     * 
+     *
      * @return {@code true} if this socket is closed, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isClosed() {
         return isClosed;
@@ -504,12 +482,11 @@
 
     /**
      * Sets the value for the socket option {@code SocketOptions.SO_REUSEADDR}.
-     * 
+     *
      * @param reuse
      *            the socket option setting.
      * @throws SocketException
      *             if an error occurs while setting the option value.
-     * @since Android 1.0
      */
     public void setReuseAddress(boolean reuse) throws SocketException {
         checkClosedAndCreate(true);
@@ -519,11 +496,10 @@
 
     /**
      * Gets the value of the socket option {@code SocketOptions.SO_REUSEADDR}.
-     * 
+     *
      * @return {@code true} if the option is enabled, {@code false} otherwise.
      * @throws SocketException
      *             if an error occurs while reading the option value.
-     * @since Android 1.0
      */
     public boolean getReuseAddress() throws SocketException {
         checkClosedAndCreate(true);
@@ -534,13 +510,12 @@
     /**
      * Sets the server socket receive buffer size {@code
      * SocketOptions.SO_RCVBUF}.
-     * 
+     *
      * @param size
      *            the buffer size in bytes.
      * @throws SocketException
      *             if an error occurs while setting the size or the size is
      *             invalid.
-     * @since Android 1.0
      */
     public void setReceiveBufferSize(int size) throws SocketException {
         checkClosedAndCreate(true);
@@ -553,11 +528,10 @@
     /**
      * Gets the value for the receive buffer size socket option {@code
      * SocketOptions.SO_RCVBUF}.
-     * 
+     *
      * @return the receive buffer size of this socket.
      * @throws SocketException
      *             if an error occurs while reading the option value.
-     * @since Android 1.0
      */
     public int getReceiveBufferSize() throws SocketException {
         checkClosedAndCreate(true);
@@ -568,9 +542,8 @@
      * Gets the related channel if this instance was created by a
      * {@code ServerSocketChannel}. The current implementation returns always {@code
      * null}.
-     * 
+     *
      * @return the related {@code ServerSocketChannel} if any.
-     * @since Android 1.0
      */
     public ServerSocketChannel getChannel() {
         return null;
@@ -580,8 +553,7 @@
      * Sets performance preferences for connection time, latency and bandwidth.
      * <p>
      * This method does currently nothing.
-     * </p>
-     * 
+     *
      * @param connectionTime
      *            the value representing the importance of a short connecting
      *            time.
@@ -589,7 +561,6 @@
      *            the value representing the importance of low latency.
      * @param bandwidth
      *            the value representing the importance of high bandwidth.
-     * @since Android 1.0
      */
     public void setPerformancePreferences(int connectionTime, int latency,
             int bandwidth) {
diff --git a/luni/src/main/java/java/net/Socket.java b/luni/src/main/java/java/net/Socket.java
index b29b965..97bfc2e 100644
--- a/luni/src/main/java/java/net/Socket.java
+++ b/luni/src/main/java/java/net/Socket.java
@@ -24,15 +24,13 @@
 import java.security.AccessController;
 
 import org.apache.harmony.luni.net.NetUtil;
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainSocketImpl;
 import org.apache.harmony.luni.platform.Platform;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 
 /**
  * Provides a client-side TCP socket.
- * 
- * @since Android 1.0
  */
 public class Socket {
 
@@ -66,7 +64,7 @@
     static final int TCP_NODELAY = 4;
 
     static final int FLAG_SHUTDOWN = 8;
-   
+
     static {
         Platform.getNetworkSystem().oneTimeInitialization(true);
     }
@@ -75,14 +73,13 @@
      * Creates a new unconnected socket. When a SocketImplFactory is defined it
      * creates the internal socket implementation, otherwise the default socket
      * implementation will be used for this socket.
-     * 
+     *
      * @see SocketImplFactory
      * @see SocketImpl
-     * @since Android 1.0
      */
     public Socket() {
         impl = factory != null ? factory.createSocketImpl()
-                : SocketImplProvider.getSocketImpl();
+                : new PlainSocketImpl();
     }
 
     /**
@@ -95,8 +92,7 @@
      * proxy server: <br>
      * {@code Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new
      * InetSocketAddress("test.domain.org", 2130)));}
-     * </p>
-     * 
+     *
      * @param proxy
      *            the specified proxy for this socket.
      * @throws IllegalArgumentException
@@ -107,7 +103,6 @@
      *             connect to the given proxy.
      * @see SocketImplFactory
      * @see SocketImpl
-     * @since Android 1.0
      */
     public Socket(Proxy proxy) {
         if (null == proxy || Proxy.Type.HTTP == proxy.type()) {
@@ -127,7 +122,7 @@
             checkConnectPermission(host, port);
         }
         impl = factory != null ? factory.createSocketImpl()
-                : SocketImplProvider.getSocketImpl(proxy);
+                : new PlainSocketImpl(proxy);
         this.proxy = proxy;
     }
 
@@ -135,7 +130,7 @@
      * Creates a new streaming socket connected to the target host specified by
      * the parameters {@code dstName} and {@code dstPort}. The socket is bound
      * to any available port on the local host.
-     * 
+     *
      * @param dstName
      *            the target host name or IP address to connect to.
      * @param dstPort
@@ -147,7 +142,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies the permission to
      *             connect to the given address and port.
-     * @since Android 1.0
      */
     public Socket(String dstName, int dstPort) throws UnknownHostException,
             IOException {
@@ -162,9 +156,9 @@
      * the parameters {@code dstName} and {@code dstPort}. On the local endpoint
      * the socket is bound to the given address {@code localAddress} on port
      * {@code localPort}.
-     * 
+     *
      * If {@code host} is {@code null} a loopback address is used to connect to.
-     * 
+     *
      * @param dstName
      *            the target host name or IP address to connect to.
      * @param dstPort
@@ -180,7 +174,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies the permission to
      *             connect to the given address and port.
-     * @since Android 1.0
      */
     public Socket(String dstName, int dstPort, InetAddress localAddress,
             int localPort) throws IOException {
@@ -194,7 +187,7 @@
      * Creates a new streaming or datagram socket connected to the target host
      * specified by the parameters {@code hostName} and {@code port}. The socket
      * is bound to any available port on the local host.
-     * 
+     *
      * @param hostName
      *            the target host name or IP address to connect to.
      * @param port
@@ -212,7 +205,6 @@
      * @deprecated Use {@code Socket(String, int)} instead of this for streaming
      *             sockets or an appropriate constructor of {@code
      *             DatagramSocket} for UDP transport.
-     * @since Android 1.0
      */
     @Deprecated
     public Socket(String hostName, int port, boolean streaming)
@@ -227,7 +219,7 @@
      * Creates a new streaming socket connected to the target host specified by
      * the parameters {@code dstAddress} and {@code dstPort}. The socket is
      * bound to any available port on the local host.
-     * 
+     *
      * @param dstAddress
      *            the target host address to connect to.
      * @param dstPort
@@ -237,7 +229,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies the permission to
      *             connect to the given address and port.
-     * @since Android 1.0
      */
     public Socket(InetAddress dstAddress, int dstPort) throws IOException {
         this();
@@ -250,7 +241,7 @@
      * the parameters {@code dstAddress} and {@code dstPort}. On the local
      * endpoint the socket is bound to the given address {@code localAddress} on
      * port {@code localPort}.
-     * 
+     *
      * @param dstAddress
      *            the target host address to connect to.
      * @param dstPort
@@ -264,7 +255,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies the permission to
      *             connect to the given address and port.
-     * @since Android 1.0
      */
     public Socket(InetAddress dstAddress, int dstPort,
             InetAddress localAddress, int localPort) throws IOException {
@@ -277,7 +267,7 @@
      * Creates a new streaming or datagram socket connected to the target host
      * specified by the parameters {@code addr} and {@code port}. The socket is
      * bound to any available port on the local host.
-     * 
+     *
      * @param addr
      *            the Internet address to connect to.
      * @param port
@@ -293,7 +283,6 @@
      * @deprecated Use {@code Socket(InetAddress, int)} instead of this for
      *             streaming sockets or an appropriate constructor of {@code
      *             DatagramSocket} for UDP transport.
-     * @since Android 1.0
      */
     @Deprecated
     public Socket(InetAddress addr, int port, boolean streaming)
@@ -305,12 +294,11 @@
 
     /**
      * Creates an unconnected socket with the given socket implementation.
-     * 
+     *
      * @param anImpl
      *            the socket implementation to be used.
      * @throws SocketException
      *             if an error occurs while creating the socket.
-     * @since Android 1.0
      */
     protected Socket(SocketImpl anImpl) throws SocketException {
         impl = anImpl;
@@ -319,7 +307,7 @@
     /**
      * Checks whether the connection destination satisfies the security policy
      * and the validity of the port range.
-     * 
+     *
      * @param destAddr
      *            the destination host address.
      * @param dstPort
@@ -336,7 +324,7 @@
 
     /**
      * Checks whether the connection destination satisfies the security policy.
-     * 
+     *
      * @param hostname
      *            the destination hostname.
      * @param dstPort
@@ -352,10 +340,9 @@
     /**
      * Closes the socket. It is not possible to reconnect or rebind to this
      * socket thereafter which means a new socket instance has to be created.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing the socket.
-     * @since Android 1.0
      */
     public synchronized void close() throws IOException {
         isClosed = true;
@@ -364,10 +351,9 @@
 
     /**
      * Gets the IP address of the target host this socket is connected to.
-     * 
+     *
      * @return the IP address of the connected target host or {@code null} if
      *         this socket is not yet connected.
-     * @since Android 1.0
      */
     public InetAddress getInetAddress() {
         if (!isConnected()) {
@@ -378,12 +364,11 @@
 
     /**
      * Gets an input stream to read data from this socket.
-     * 
+     *
      * @return the byte-oriented input stream.
      * @throws IOException
      *             if an error occurs while creating the input stream or the
      *             socket is in an invalid state.
-     * @since Android 1.0
      */
     public InputStream getInputStream() throws IOException {
         checkClosedAndCreate(false);
@@ -395,13 +380,12 @@
 
     /**
      * Gets the setting of the socket option {@code SocketOptions.SO_KEEPALIVE}.
-     * 
+     *
      * @return {@code true} if the {@code SocketOptions.SO_KEEPALIVE} is
      *         enabled, {@code false} otherwise.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_KEEPALIVE
-     * @since Android 1.0
      */
     public boolean getKeepAlive() throws SocketException {
         checkClosedAndCreate(true);
@@ -411,10 +395,9 @@
 
     /**
      * Gets the local IP address this socket is bound to.
-     * 
+     *
      * @return the local IP address of this socket or {@code InetAddress.ANY} if
      *         the socket is unbound.
-     * @since Android 1.0
      */
     public InetAddress getLocalAddress() {
         if (!isBound()) {
@@ -426,10 +409,9 @@
 
     /**
      * Gets the local port this socket is bound to.
-     * 
+     *
      * @return the local port of this socket or {@code -1} if the socket is
      *         unbound.
-     * @since Android 1.0
      */
     public int getLocalPort() {
         if (!isBound()) {
@@ -440,12 +422,11 @@
 
     /**
      * Gets an output stream to write data into this socket.
-     * 
+     *
      * @return the byte-oriented output stream.
      * @throws IOException
      *             if an error occurs while creating the output stream or the
      *             socket is in an invalid state.
-     * @since Android 1.0
      */
     public OutputStream getOutputStream() throws IOException {
         checkClosedAndCreate(false);
@@ -457,10 +438,9 @@
 
     /**
      * Gets the port number of the target host this socket is connected to.
-     * 
+     *
      * @return the port number of the connected target host or {@code 0} if this
      *         socket is not yet connected.
-     * @since Android 1.0
      */
     public int getPort() {
         if (!isConnected()) {
@@ -471,13 +451,12 @@
 
     /**
      * Gets the value of the socket option {@code SocketOptions.SO_LINGER}.
-     * 
+     *
      * @return the current value of the option {@code SocketOptions.SO_LINGER}
      *         or {@code -1} if this option is disabled.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_LINGER
-     * @since Android 1.0
      */
     public int getSoLinger() throws SocketException {
         checkClosedAndCreate(true);
@@ -486,12 +465,11 @@
 
     /**
      * Gets the receive buffer size of this socket.
-     * 
+     *
      * @return the current value of the option {@code SocketOptions.SO_RCVBUF}.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_RCVBUF
-     * @since Android 1.0
      */
     public synchronized int getReceiveBufferSize() throws SocketException {
         checkClosedAndCreate(true);
@@ -500,12 +478,11 @@
 
     /**
      * Gets the send buffer size of this socket.
-     * 
+     *
      * @return the current value of the option {@code SocketOptions.SO_SNDBUF}.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_SNDBUF
-     * @since Android 1.0
      */
     public synchronized int getSendBufferSize() throws SocketException {
         checkClosedAndCreate(true);
@@ -515,13 +492,12 @@
     /**
      * Gets the timeout for this socket during which a reading operation shall
      * block while waiting for data.
-     * 
+     *
      * @return the current value of the option {@code SocketOptions.SO_TIMEOUT}
      *         or {@code 0} which represents an infinite timeout.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_TIMEOUT
-     * @since Android 1.0
      */
     public synchronized int getSoTimeout() throws SocketException {
         checkClosedAndCreate(true);
@@ -530,13 +506,12 @@
 
     /**
      * Gets the setting of the socket option {@code SocketOptions.TCP_NODELAY}.
-     * 
+     *
      * @return {@code true} if the {@code SocketOptions.TCP_NODELAY} is enabled,
      *         {@code false} otherwise.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#TCP_NODELAY
-     * @since Android 1.0
      */
     public boolean getTcpNoDelay() throws SocketException {
         checkClosedAndCreate(true);
@@ -546,13 +521,12 @@
 
     /**
      * Sets the state of the {@code SocketOptions.SO_KEEPALIVE} for this socket.
-     * 
+     *
      * @param value
      *            the state whether this option is enabled or not.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#SO_KEEPALIVE
-     * @since Android 1.0
      */
     public void setKeepAlive(boolean value) throws SocketException {
         if (impl != null) {
@@ -565,12 +539,11 @@
     /**
      * Sets the internal factory for creating socket implementations. This may
      * only be executed once during the lifetime of the application.
-     * 
+     *
      * @param fac
      *            the socket implementation factory to be set.
      * @throws IOException
      *             if the factory has been already set.
-     * @since Android 1.0
      */
     public static synchronized void setSocketImplFactory(SocketImplFactory fac)
             throws IOException {
@@ -586,7 +559,7 @@
 
     /**
      * Sets the send buffer size of this socket.
-     * 
+     *
      * @param size
      *            the buffer size in bytes. This value must be a positive number
      *            greater than {@code 0}.
@@ -594,7 +567,6 @@
      *             if an error occurs while setting the size or the given value
      *             is an invalid size.
      * @see SocketOptions#SO_SNDBUF
-     * @since Android 1.0
      */
     public synchronized void setSendBufferSize(int size) throws SocketException {
         checkClosedAndCreate(true);
@@ -606,7 +578,7 @@
 
     /**
      * Sets the receive buffer size of this socket.
-     * 
+     *
      * @param size
      *            the buffer size in bytes. This value must be a positive number
      *            greater than {@code 0}.
@@ -614,7 +586,6 @@
      *             if an error occurs while setting the size or the given value
      *             is an invalid size.
      * @see SocketOptions#SO_RCVBUF
-     * @since Android 1.0
      */
     public synchronized void setReceiveBufferSize(int size)
             throws SocketException {
@@ -629,7 +600,7 @@
      * Sets the state of the {@code SocketOptions.SO_LINGER} with the given
      * timeout in seconds. The timeout value for this option is silently limited
      * to the maximum of {@code 65535}.
-     * 
+     *
      * @param on
      *            the state whether this option is enabled or not.
      * @param timeout
@@ -637,7 +608,6 @@
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#SO_LINGER
-     * @since Android 1.0
      */
     public void setSoLinger(boolean on, int timeout) throws SocketException {
         checkClosedAndCreate(true);
@@ -665,14 +635,13 @@
      * operation will block indefinitely if this option value is set to {@code
      * 0}. The timeout must be set before calling the read operation. A
      * {@code SocketTimeoutException} is thrown when this timeout expires.
-     * 
+     *
      * @param timeout
      *            the reading timeout value as number greater than {@code 0} or
      *            {@code 0} for an infinite timeout.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#SO_TIMEOUT
-     * @since Android 1.0
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException {
         checkClosedAndCreate(true);
@@ -684,13 +653,12 @@
 
     /**
      * Sets the state of the {@code SocketOptions.TCP_NODELAY} for this socket.
-     * 
+     *
      * @param on
      *            the state whether this option is enabled or not.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#TCP_NODELAY
-     * @since Android 1.0
      */
     public void setTcpNoDelay(boolean on) throws SocketException {
         checkClosedAndCreate(true);
@@ -700,7 +668,7 @@
     /**
      * Creates a stream socket, binds it to the nominated local address/port,
      * then connects it to the nominated destination address/port.
-     * 
+     *
      * @param dstAddress
      *            the destination host address.
      * @param dstPort
@@ -743,9 +711,8 @@
     /**
      * Returns a {@code String} containing a concise, human-readable description of the
      * socket.
-     * 
+     *
      * @return the textual representation of this socket.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -759,12 +726,11 @@
      * Closes the input stream of this socket. Any further data sent to this
      * socket will be discarded. Reading from this socket after this method has
      * been called will return the value {@code EOF}.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing the socket input stream.
      * @throws SocketException
      *             if the input stream is already closed.
-     * @since Android 1.0
      */
     public void shutdownInput() throws IOException {
         if (isInputShutdown()) {
@@ -779,12 +745,11 @@
      * Closes the output stream of this socket. All buffered data will be sent
      * followed by the termination sequence. Writing to the closed output stream
      * will cause an {@code IOException}.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing the socket output stream.
      * @throws SocketException
      *             if the output stream is already closed.
-     * @since Android 1.0
      */
     public void shutdownOutput() throws IOException {
         if (isOutputShutdown()) {
@@ -798,7 +763,7 @@
     /**
      * Checks whether the socket is closed, and throws an exception. Otherwise
      * creates the underlying SocketImpl.
-     * 
+     *
      * @throws SocketException
      *             if the socket is closed.
      */
@@ -840,9 +805,8 @@
      * Gets the local address and port of this socket as a SocketAddress or
      * {@code null} if the socket is unbound. This is useful on multihomed
      * hosts.
-     * 
+     *
      * @return the bound local socket address and port.
-     * @since Android 1.0
      */
     public SocketAddress getLocalSocketAddress() {
         if (!isBound()) {
@@ -854,9 +818,8 @@
     /**
      * Gets the remote address and port of this socket as a {@code
      * SocketAddress} or {@code null} if the socket is not connected.
-     * 
+     *
      * @return the remote socket address and port.
-     * @since Android 1.0
      */
     public SocketAddress getRemoteSocketAddress() {
         if (!isConnected()) {
@@ -867,10 +830,9 @@
 
     /**
      * Returns whether this socket is bound to a local address and port.
-     * 
+     *
      * @return {@code true} if the socket is bound to a local address, {@code
      *         false} otherwise.
-     * @since Android 1.0
      */
     public boolean isBound() {
         return isBound;
@@ -878,9 +840,8 @@
 
     /**
      * Returns whether this socket is connected to a remote host.
-     * 
+     *
      * @return {@code true} if the socket is connected, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isConnected() {
         return isConnected;
@@ -888,9 +849,8 @@
 
     /**
      * Returns whether this socket is closed.
-     * 
+     *
      * @return {@code true} if the socket is closed, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isClosed() {
         return isClosed;
@@ -901,7 +861,7 @@
      * the SocketAddress {@code localAddr}. If {@code localAddr} is set to
      * {@code null}, this socket will be bound to an available local address on
      * any free port.
-     * 
+     *
      * @param localAddr
      *            the specific address and port on the local machine to bind to.
      * @throws IllegalArgumentException
@@ -909,7 +869,6 @@
      * @throws IOException
      *             if the socket is already bound or an error occurs while
      *             binding.
-     * @since Android 1.0
      */
     public void bind(SocketAddress localAddr) throws IOException {
         checkClosedAndCreate(true);
@@ -946,7 +905,7 @@
     /**
      * Connects this socket to the given remote host address and port specified
      * by the SocketAddress {@code remoteAddr}.
-     * 
+     *
      * @param remoteAddr
      *            the address and port of the remote host to connect to.
      * @throws IllegalArgumentException
@@ -954,7 +913,6 @@
      * @throws IOException
      *             if the socket is already connected or an error occurs while
      *             connecting.
-     * @since Android 1.0
      */
     public void connect(SocketAddress remoteAddr) throws IOException {
         connect(remoteAddr, 0);
@@ -965,7 +923,7 @@
      * by the SocketAddress {@code remoteAddr} with the specified timeout. The
      * connecting method will block until the connection is established or an
      * error occurred.
-     * 
+     *
      * @param remoteAddr
      *            the address and port of the remote host to connect to.
      * @param timeout
@@ -977,7 +935,6 @@
      * @throws IOException
      *             if the socket is already connected or an error occurs while
      *             connecting.
-     * @since Android 1.0
      */
     public void connect(SocketAddress remoteAddr, int timeout)
             throws IOException {
@@ -1028,22 +985,20 @@
     /**
      * Returns whether the incoming channel of the socket has already been
      * closed.
-     * 
+     *
      * @return {@code true} if reading from this socket is not possible anymore,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isInputShutdown() {
         return isInputShutdown;
     }
 
     /**
-     * Returns whether the outgoing channel of the socket has already been 
+     * Returns whether the outgoing channel of the socket has already been
      * closed.
-     * 
+     *
      * @return {@code true} if writing to this socket is not possible anymore,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isOutputShutdown() {
         return isOutputShutdown;
@@ -1051,13 +1006,12 @@
 
     /**
      * Sets the state of the {@code SocketOptions.SO_REUSEADDR} for this socket.
-     * 
+     *
      * @param reuse
      *            the state whether this option is enabled or not.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#SO_REUSEADDR
-     * @since Android 1.0
      */
     public void setReuseAddress(boolean reuse) throws SocketException {
         checkClosedAndCreate(true);
@@ -1067,13 +1021,12 @@
 
     /**
      * Gets the setting of the socket option {@code SocketOptions.SO_REUSEADDR}.
-     * 
+     *
      * @return {@code true} if the {@code SocketOptions.SO_REUSEADDR} is
      *         enabled, {@code false} otherwise.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_REUSEADDR
-     * @since Android 1.0
      */
     public boolean getReuseAddress() throws SocketException {
         checkClosedAndCreate(true);
@@ -1085,13 +1038,12 @@
      * Sets the state of the {@code SocketOptions.SO_OOBINLINE} for this socket.
      * When this option is enabled urgent data can be received in-line with
      * normal data.
-     * 
+     *
      * @param oobinline
      *            whether this option is enabled or not.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#SO_OOBINLINE
-     * @since Android 1.0
      */
     public void setOOBInline(boolean oobinline) throws SocketException {
         checkClosedAndCreate(true);
@@ -1101,13 +1053,12 @@
 
     /**
      * Gets the setting of the socket option {@code SocketOptions.SO_OOBINLINE}.
-     * 
+     *
      * @return {@code true} if the {@code SocketOptions.SO_OOBINLINE} is
      *         enabled, {@code false} otherwise.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_OOBINLINE
-     * @since Android 1.0
      */
     public boolean getOOBInline() throws SocketException {
         checkClosedAndCreate(true);
@@ -1119,14 +1070,13 @@
      * Sets the value of the {@code SocketOptions.IP_TOS} for this socket. See
      * the specification RFC 1349 for more information about the type of service
      * field.
-     * 
+     *
      * @param value
      *            the value to be set for this option with a valid range of
      *            {@code 0-255}.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#IP_TOS
-     * @since Android 1.0
      */
     public void setTrafficClass(int value) throws SocketException {
         checkClosedAndCreate(true);
@@ -1138,12 +1088,11 @@
 
     /**
      * Gets the value of the socket option {@code SocketOptions.IP_TOS}.
-     * 
+     *
      * @return the value which represents the type of service.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#IP_TOS
-     * @since Android 1.0
      */
     public int getTrafficClass() throws SocketException {
         checkClosedAndCreate(true);
@@ -1153,12 +1102,11 @@
     /**
      * Sends the given single byte data which is represented by the lowest octet
      * of {@code value} as "TCP urgent data".
-     * 
+     *
      * @param value
      *            the byte of urgent data to be sent.
      * @throws IOException
      *             if an error occurs while sending urgent data.
-     * @since Android 1.0
      */
     public void sendUrgentData(int value) throws IOException {
         if (!impl.supportsUrgentData()) {
@@ -1170,7 +1118,7 @@
     /**
      * Set the appropriate flags for a socket created by {@code
      * ServerSocket.accept()}.
-     * 
+     *
      * @see ServerSocket#implAccept
      */
     void accepted() {
@@ -1186,9 +1134,8 @@
     /**
      * Gets the SocketChannel of this socket, if one is available. The current
      * implementation of this method returns always {@code null}.
-     * 
+     *
      * @return the related SocketChannel or {@code null} if no channel exists.
-     * @since Android 1.0
      */
     public SocketChannel getChannel() {
         return null;
@@ -1198,8 +1145,7 @@
      * Sets performance preferences for connectionTime, latency and bandwidth.
      * <p>
      * This method does currently nothing.
-     * </p>
-     * 
+     *
      * @param connectionTime
      *            the value representing the importance of a short connecting
      *            time.
@@ -1207,7 +1153,6 @@
      *            the value representing the importance of low latency.
      * @param bandwidth
      *            the value representing the importance of high bandwidth.
-     * @since Android 1.0
      */
     public void setPerformancePreferences(int connectionTime, int latency,
             int bandwidth) {
diff --git a/luni/src/main/java/java/net/SocketAddress.java b/luni/src/main/java/java/net/SocketAddress.java
index 756b5fd..32a4c36 100644
--- a/luni/src/main/java/java/net/SocketAddress.java
+++ b/luni/src/main/java/java/net/SocketAddress.java
@@ -23,15 +23,11 @@
  * This abstract class represents a protocol-independent base for
  * socket-endpoint representing classes. The class has to be implemented
  * according to a specific protocol.
- * 
- * @since Android 1.0
  */
 public abstract class SocketAddress implements Serializable {
 
     /**
      * Creates a new {@code SocketAddress} instance.
-     * 
-     * @since Android 1.0
      */
     public SocketAddress() {
         super();
diff --git a/luni/src/main/java/java/net/SocketException.java b/luni/src/main/java/java/net/SocketException.java
index b9b3a14..23d3744 100644
--- a/luni/src/main/java/java/net/SocketException.java
+++ b/luni/src/main/java/java/net/SocketException.java
@@ -22,8 +22,6 @@
 /**
  * This {@code SocketException} may be thrown during socket creation or setting
  * options, and is the superclass of all other socket related exceptions.
- * 
- * @since Android 1.0
  */
 public class SocketException extends IOException {
 
@@ -32,8 +30,6 @@
     /**
      * Constructs a new {@code SocketException} instance with its walkback
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public SocketException() {
         super();
@@ -45,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message of this exception.
-     * @since Android 1.0
      */
     public SocketException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/net/SocketImpl.java b/luni/src/main/java/java/net/SocketImpl.java
index f011e63..be13eca 100644
--- a/luni/src/main/java/java/net/SocketImpl.java
+++ b/luni/src/main/java/java/net/SocketImpl.java
@@ -20,7 +20,6 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InterruptedIOException;
 import java.io.OutputStream;
 
 import org.apache.harmony.luni.platform.INetworkSystem;
@@ -35,36 +34,26 @@
  * ServerSocket} on a well known port (referred to as listener) used to
  * establish a connection and the resulting {@code Socket} (referred to as
  * host).
- * 
- * @since Android 1.0
  */
 public abstract class SocketImpl implements SocketOptions {
 
     /**
      * The remote address this socket is connected to.
-     * 
-     * @since Android 1.0
      */
     protected InetAddress address;
 
     /**
      * The remote port this socket is connected to.
-     * 
-     * @since Android 1.0
      */
     protected int port;
 
     /**
      * The file descriptor of this socket.
-     * 
-     * @since Android 1.0
      */
     protected FileDescriptor fd;
 
     /**
      * The local port this socket is connected to.
-     * 
-     * @since Android 1.0
      */
     protected int localport;
 
@@ -80,9 +69,8 @@
 
     /**
      * Creates a new connection-oriented socket implementation.
-     * 
+     *
      * @see SocketImplFactory
-     * @since Android 1.0
      */
     public SocketImpl() {
         this.netImpl = Platform.getNetworkSystem();
@@ -91,73 +79,67 @@
     /**
      * Waits for an incoming request and blocks until the connection is opened
      * on the given socket.
-     * 
+     *
      * @param newSocket
      *            the socket to accept connections on.
      * @throws IOException
      *             if an error occurs while accepting a new connection.
-     * @since Android 1.0
      */
     protected abstract void accept(SocketImpl newSocket) throws IOException;
 
     /**
      * Returns the available number of bytes which are readable from this socket
      * without blocking.
-     * 
+     *
      * @return the number of bytes that may be read without blocking.
      * @throws IOException
      *             if an error occurs while reading the number of bytes.
-     * @since Android 1.0
      */
     protected abstract int available() throws IOException;
 
     /**
      * Binds this socket to the specified local host address and port number.
-     * 
+     *
      * @param address
      *            the local machine address to bind this socket to.
      * @param port
      *            the port on the local machine to bind this socket to.
      * @throws IOException
      *             if an error occurs while binding this socket.
-     * @since Android 1.0
      */
     protected abstract void bind(InetAddress address, int port)
             throws IOException;
 
     /**
      * Closes this socket. This makes later access invalid.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this socket.
-     * @since Android 1.0
      */
     protected abstract void close() throws IOException;
 
     /**
      * Connects this socket to the specified remote host and port number.
-     * 
+     *
      * @param host
      *            the remote host this socket has to be connected to.
      * @param port
      *            the remote port on which this socket has to be connected.
      * @throws IOException
      *             if an error occurs while connecting to the remote host.
-     * @since Android 1.0
      */
     protected abstract void connect(String host, int port) throws IOException;
 
     /**
      * Connects this socket to the specified remote host address and port
      * number.
-     * 
+     *
      * @param address
      *            the remote host address this socket has to be connected to.
      * @param port
      *            the remote port on which this socket has to be connected.
      * @throws IOException
      *             if an error occurs while connecting to the remote host.
-     * @since Android 1.0
      */
     protected abstract void connect(InetAddress address, int port)
             throws IOException;
@@ -165,21 +147,19 @@
     /**
      * Creates a new unconnected socket. The argument {@code isStreaming}
      * defines whether the new socket is a streaming or a datagram socket.
-     * 
+     *
      * @param isStreaming
      *            defines whether the type of the new socket is streaming or
      *            datagram.
      * @throws IOException
      *             if an error occurs while creating the socket.
-     * @since Android 1.0
      */
     protected abstract void create(boolean isStreaming) throws IOException;
 
     /**
      * Gets the file descriptor of this socket.
-     * 
+     *
      * @return the file descriptor of this socket.
-     * @since Android 1.0
      */
     protected FileDescriptor getFileDescriptor() {
         return fd;
@@ -187,9 +167,8 @@
 
     /**
      * Gets the remote address this socket is connected to.
-     * 
+     *
      * @return the remote address of this socket.
-     * @since Android 1.0
      */
     protected InetAddress getInetAddress() {
         return address;
@@ -197,11 +176,10 @@
 
     /**
      * Gets the input stream of this socket.
-     * 
+     *
      * @return the input stream of this socket.
      * @throws IOException
      *             if an error occurs while accessing the input stream.
-     * @since Android 1.0
      */
     protected abstract InputStream getInputStream() throws IOException;
 
@@ -209,9 +187,8 @@
      * Gets the local port number of this socket. The field is initialized to
      * {@code -1} and upon demand will go to the IP stack to get the bound
      * value. See the class comment for the context of the local port.
-     * 
+     *
      * @return the local port number this socket is bound to.
-     * @since Android 1.0
      */
     protected int getLocalPort() {
         return localport;
@@ -219,32 +196,29 @@
 
     /**
      * Gets the value of the given socket option.
-     * 
+     *
      * @param optID
      *            the socket option to retrieve.
      * @return the option value.
      * @throws SocketException
      *             if an error occurs while accessing the option.
-     * @since Android 1.0
      */
     public abstract Object getOption(int optID) throws SocketException;
 
     /**
      * Gets the output stream of this socket.
-     * 
+     *
      * @return the output stream of this socket.
      * @throws IOException
      *             if an error occurs while accessing the output stream.
-     * @since Android 1.0
      */
     protected abstract OutputStream getOutputStream() throws IOException;
 
     /**
      * Gets the remote port number of this socket. This value is not meaningful
      * when this instance is wrapped by a {@code ServerSocket}.
-     * 
+     *
      * @return the remote port this socket is connected to.
-     * @since Android 1.0
      */
     protected int getPort() {
         return port;
@@ -255,60 +229,23 @@
      * connection requests are queued up to the limit specified by {@code
      * backlog}. Additional requests are rejected. The method {@code listen()}
      * may only be invoked on streaming sockets.
-     * 
+     *
      * @param backlog
      *            the maximum number of outstanding connection requests.
      * @throws IOException
      *             if an error occurs while listening.
-     * @since Android 1.0
      */
     protected abstract void listen(int backlog) throws IOException;
 
     /**
-     * In the IP stack, read at most {@code count} bytes off the socket
-     * into the {@code buffer}, at the {@code offset}. If the timeout
-     * is zero, block indefinitely waiting for data, otherwise wait the
-     * specified period (in milliseconds).
-     * 
-     * @param buffer
-     *            the buffer to read into
-     * @param offset
-     *            the offset into the buffer
-     * @param count
-     *            the max number of bytes to read
-     * @return int the actual number of bytes read
-     * @exception IOException
-     *                thrown if an error occurs while reading
-     */
-    int read(byte[] buffer, int offset, int count) throws IOException {
-        if (shutdownInput) {
-            return -1;
-        }
-        try {
-            // BEGIN android-added
-            int receiveTimeout = (Integer)getOption(SocketOptions.SO_TIMEOUT);
-            // END android-added
-            int read = this.netImpl.receiveStream(fd, buffer, offset, count,
-                    receiveTimeout);
-            if (read == -1) {
-                shutdownInput = true;
-            }
-            return read;
-        } catch (InterruptedIOException e) {
-            throw new SocketTimeoutException(e.getMessage());
-        }
-    }
-
-    /**
      * Sets the value for the specified socket option.
-     * 
+     *
      * @param optID
      *            the socket option to be set.
      * @param val
      *            the option value.
      * @throws SocketException
      *             if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public abstract void setOption(int optID, Object val)
             throws SocketException;
@@ -316,9 +253,8 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * socket.
-     * 
+     *
      * @return the textual representation of this socket.
-     * @since Android 1.0
      */
     @SuppressWarnings("nls")
     @Override
@@ -331,7 +267,7 @@
     /**
      * In the IP stack, write at most {@code count} bytes on the socket
      * from the {@code buffer}, from the {@code offset}.
-     * 
+     *
      * @param buffer
      *            the buffer to read into
      * @param offset
@@ -339,18 +275,15 @@
      * @param count
      *            the number of bytes to write
      * @return int the actual number of bytes written
-     * @exception IOException
+     * @throws IOException
      *                thrown if an error occurs while writing
      */
     int write(byte[] buffer, int offset, int count) throws IOException {
         if (!streaming) {
-            // BEGIN android-changed
-            // copied from newer harmony version
-            return this.netImpl
-                    .sendDatagram2(fd, buffer, offset, count, port, address);
-            // END android-changed
+            return this.netImpl.sendDatagram2(fd, buffer, offset, count, port,
+                    address);
         }
-        return this.netImpl.sendStream(fd, buffer, offset, count);
+        return this.netImpl.write(fd, buffer, offset, count);
     }
 
     /**
@@ -358,11 +291,9 @@
      * <p>
      * This default implementation always throws an {@link IOException} to
      * indicate that the subclass should have overridden this method.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             always because this method should be overridden.
-     * @since Android 1.0
      */
     protected void shutdownInput() throws IOException {
         // KA025=Method has not been implemented
@@ -374,11 +305,9 @@
      * <p>
      * This default implementation always throws an {@link IOException} to
      * indicate that the subclass should have overridden this method.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             always because this method should be overridden.
-     * @since Android 1.0
      */
     protected void shutdownOutput() throws IOException {
         // KA025=Method has not been implemented
@@ -389,14 +318,13 @@
      * Connects this socket to the remote host address and port number specified
      * by the {@code SocketAddress} object with the given timeout. This method
      * will block indefinitely if the timeout is set to zero.
-     * 
+     *
      * @param remoteAddr
      *            the remote host address and port number to connect to.
      * @param timeout
      *            the timeout value in milliseconds.
      * @throws IOException
      *             if an error occurs while connecting.
-     * @since Android 1.0
      */
     protected abstract void connect(SocketAddress remoteAddr, int timeout)
             throws IOException;
@@ -404,9 +332,8 @@
     /**
      * Returns whether the socket supports urgent data or not. Subclasses should
      * override this method.
-     * 
+     *
      * @return {@code false} because subclasses must override this method.
-     * @since Android 1.0
      */
     protected boolean supportsUrgentData() {
         return false;
@@ -414,26 +341,24 @@
 
     /**
      * Sends the single byte of urgent data on the socket.
-     * 
+     *
      * @param value
      *            the byte of urgent data.
      * @throws IOException
      *             if an error occurs sending urgent data.
-     * @since Android 1.0
      */
     protected abstract void sendUrgentData(int value) throws IOException;
 
     /**
      * Sets performance preference for connection time, latency and bandwidth.
      * Does nothing by default.
-     * 
+     *
      * @param connectionTime
      *            the importance of connect time.
      * @param latency
      *            the importance of latency.
      * @param bandwidth
      *            the importance of bandwidth.
-     * @since Android 1.0
      */
     protected void setPerformancePreferences(int connectionTime, int latency,
             int bandwidth) {
diff --git a/luni/src/main/java/java/net/SocketImplFactory.java b/luni/src/main/java/java/net/SocketImplFactory.java
index 3cc42b0..57b0bc3 100644
--- a/luni/src/main/java/java/net/SocketImplFactory.java
+++ b/luni/src/main/java/java/net/SocketImplFactory.java
@@ -19,16 +19,13 @@
 
 /**
  * This interface defines a factory for socket implementations.
- * 
- * @since Android 1.0
  */
 public interface SocketImplFactory {
-    
+
     /**
      * Creates a new {@code SocketImpl} instance.
      * 
      * @return the created {@code SocketImpl} instance.
-     * @since Android 1.0
      */
     SocketImpl createSocketImpl();
 }
diff --git a/luni/src/main/java/java/net/SocketOptions.java b/luni/src/main/java/java/net/SocketOptions.java
index 6e1753f..38c9301 100644
--- a/luni/src/main/java/java/net/SocketOptions.java
+++ b/luni/src/main/java/java/net/SocketOptions.java
@@ -25,7 +25,6 @@
  * 
  * @see SocketImpl
  * @see DatagramSocketImpl
- * @since Android 1.0
  */
 public interface SocketOptions {
 
@@ -38,8 +37,6 @@
      * during this timeout the socket is closed normally otherwise forcefully.
      * Valid values for this option are in the range {@code 0 <= SO_LINGER <=
      * 65535}.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_LINGER = 128;
 
@@ -47,8 +44,6 @@
      * Timeout for blocking operations. The argument value is specified in
      * milliseconds. An {@code InterruptedIOException} is thrown if this timeout
      * expires.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_TIMEOUT = 4102;
 
@@ -57,8 +52,6 @@
      * a side-effect though, this could lead to a low packet efficiency. The
      * socket implementation uses the Nagle's algorithm to try to reach a higher
      * packet efficiency if this option is disabled.
-     * 
-     * @since Android 1.0
      */
     public static final int TCP_NODELAY = 1;
 
@@ -69,8 +62,6 @@
     /**
      * This option specifies the interface which is used to send multicast
      * packets. It's only available on a {@code MulticastSocket}.
-     * 
-     * @since Android 1.0
      */
     public static final int IP_MULTICAST_IF = 16;
 
@@ -78,8 +69,6 @@
      * This option can be used to set one specific interface on a multihomed
      * host on which incoming connections are accepted. It's only available on
      * server-side sockets.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_BINDADDR = 15;
 
@@ -87,8 +76,6 @@
      * This option specifies whether a reuse of a local address is allowed even
      * if an other socket is not yet removed by the operating system. It's only
      * available on a {@code MulticastSocket}.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_REUSEADDR = 4;
 
@@ -96,15 +83,11 @@
     
     /**
      * Buffer size of the outgoing channel.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_SNDBUF = 4097;
 
     /**
      * Buffer size of the incoming channel.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_RCVBUF = 4098;
 
@@ -113,16 +96,12 @@
     /**
      * This option specifies whether socket implementations can send keepalive
      * messages if no data has been sent for a longer time.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_KEEPALIVE = 8;
     
     /**
      * This option specifies the value for the Type-of-Service (TOS) field of
      * the IP header.
-     * 
-     * @since Android 1.0
      */
     public static final int IP_TOS = 3;
     
@@ -130,23 +109,17 @@
      * This option specifies whether the local loopback of multicast packets is
      * enabled or disabled. This option is enabled by default on multicast
      * sockets.
-     * 
-     * @since Android 1.0
      */
     public static final int IP_MULTICAST_LOOP = 18;
     
     /**
      * This option can be used to enable broadcasting on datagram sockets.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_BROADCAST = 32;
     
     /**
      * This option specifies whether sending TCP urgent data is supported on
      * this socket or not.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_OOBINLINE = 4099;
     
@@ -155,8 +128,6 @@
      * host on which incoming connections are accepted. It's only available on
      * server-side sockets. This option supports setting outgoing interfaces
      * with either IPv4 or IPv6 addresses.
-     * 
-     * @since Android 1.0
      */
     public static final int IP_MULTICAST_IF2 = 31;
 
@@ -168,7 +139,6 @@
      *            the option identifier.
      * @throws SocketException
      *             if an error occurs reading the option value.
-     * @since Android 1.0
      */
     public Object getOption(int optID) throws SocketException;
 
@@ -181,7 +151,6 @@
      *            the value to be set for the option.
      * @throws SocketException
      *             if an error occurs setting the option value.
-     * @since Android 1.0
      */
     public void setOption(int optID, Object val) throws SocketException;
 }
diff --git a/luni/src/main/java/java/net/SocketPermission.java b/luni/src/main/java/java/net/SocketPermission.java
index 72d77e7..25cc43f 100644
--- a/luni/src/main/java/java/net/SocketPermission.java
+++ b/luni/src/main/java/java/net/SocketPermission.java
@@ -14,9 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-// BEGIN andorid-note
-// This class was copied from a newer version of harmony
-// END andorid-note
 
 package java.net;
 
@@ -57,16 +54,13 @@
  * <i>LOW-HIGH</i> where <i>LOW</i> and <i>HIGH</i> are valid port numbers. If
  * either <i>LOW</i> or <i>HIGH</i> is omitted it is equivalent to entering the
  * lowest or highest possible value respectively. For example:
- * 
+ *
  * <pre>
  * {@code SocketPermission(&quot;www.company.com:7000-&quot;, &quot;connect,accept&quot;)}
  * </pre>
- * 
+ *
  * represents the permission to connect to and accept connections from {@code
  * www.company.com} on ports in the range {@code 7000} to {@code 65535}.
- * </p>
- * 
- * @since Android 1.0
  */
 public final class SocketPermission extends Permission implements Serializable {
 
@@ -122,13 +116,11 @@
      * possible operations {@code "connect"}, {@code "listen"}, {@code "accept"}
      * , and {@code "resolve"}. They are case-insensitive and can be put
      * together in any order. {@code "resolve"} is implied per default.
-     * </p>
-     * 
+     *
      * @param host
      *            the hostname this permission is valid for.
      * @param action
      *            the action string of this permission.
-     * @since Android 1.0
      */
     public SocketPermission(String host, String action) {
         super(host.equals("") ? "localhost" : host); //$NON-NLS-1$ //$NON-NLS-2$
@@ -149,14 +141,13 @@
     /**
      * Compares the argument {@code o} to this instance and returns {@code true}
      * if they represent the same permission using a class specific comparison.
-     * 
+     *
      * @param o
      *            the object to compare with this {@code SocketPermission}
      *            instance.
      * @return {@code true} if they represent the same permission, {@code false}
      *         otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -187,10 +178,9 @@
      * Returns the hash value for this {@code SocketPermission} instance. Any
      * two objects which returns {@code true} when passed to {@code equals()}
      * must return the same value as a result of this method.
-     * 
+     *
      * @return the hashcode value for this instance.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -201,9 +191,8 @@
      * Gets a comma-separated list of all actions allowed by this permission. If
      * more than one action is returned they follow this order: {@code connect},
      * {@code listen}, {@code accept}, {@code resolve}.
-     * 
+     *
      * @return the comma-separated action list.
-     * @since Android 1.0
      */
     @Override
     public String getActions() {
@@ -212,7 +201,7 @@
 
     /**
      * Stores the actions for this permission as a bit field.
-     * 
+     *
      * @param actions
      *            java.lang.String the action list
      */
@@ -255,13 +244,12 @@
      * permission actions, hosts and ports must be implied by this permission
      * instance in order to return {@code true}. This permission may imply
      * additional actions not present in the argument permission.
-     * 
+     *
      * @param p
      *            the socket permission which has to be implied by this
      *            instance.
      * @return {@code true} if this permission instance implies all permissions
      *         represented by {@code p}, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean implies(Permission p) {
@@ -293,15 +281,14 @@
     /**
      * Creates a new {@code PermissionCollection} to store {@code
      * SocketPermission} objects.
-     * 
+     *
      * @return the new permission collection.
-     * @since Android 1.0
      */
     @Override
     public PermissionCollection newPermissionCollection() {
         return new SocketPermissionCollection();
     }
-    
+
     /**
      * Parse the port, including the minPort, maxPort
      * @param hostPort the host[:port] one
@@ -319,14 +306,14 @@
            portMax = 80;
            return;
        }
-       
+
        if (":*".equals(port)) {
            // The port range should be 0-65535
            portMin = 0;
            portMax = 65535;
            return;
        }
-       
+
        // Omit ':'
        port = port.substring(1);
        int negIdx = port.indexOf('-');
@@ -349,21 +336,23 @@
        try {
            portMin = Integer.valueOf(strPortMin).intValue();
            portMax = Integer.valueOf(strPortMax).intValue();
-           
+
            if (portMin > portMax) {
-               throw new IllegalArgumentException(Msg.getString("K0049") + " " + port); //$NON-NLS-1$
+               // K0049=MinPort is greater than MaxPort\: {0}
+               throw new IllegalArgumentException(Msg.getString("K0049", port)); //$NON-NLS-1$
            }
        } catch (NumberFormatException e) {
-           throw new IllegalArgumentException(Msg.getString("K004a") + " " + port); //$NON-NLS-1$
+           // K004a=Invalid port number specified\: {0}
+           throw new IllegalArgumentException(Msg.getString("K004a", port)); //$NON-NLS-1$
        }
     }
 
     /**
      * Creates a canonical action list.
-     * 
+     *
      * @param action
      *            java.lang.String
-     * 
+     *
      * @return java.lang.String
      */
     private String toCanonicalActionString(String action) {
@@ -403,15 +392,20 @@
     }
 
     /**
-     * Get the host part from the host[:port] one.
-     * The host should be
+     * Get the host part from the host[:port] one. The host should be
+     *
+     * <pre>
      *      host = (hostname | IPv4address | IPv6reference | IPv6 in full uncompressed form)
-     * The wildcard "*" may be included once in a DNS name host specification. If it is included, 
-     * it must be in the leftmost position
-     * 
+     * </pre>
+     *
+     * The wildcard "*" may be included once in a DNS name host specification.
+     * If it is included, it must be in the leftmost position
+     *
      * @param host
-     * @return
-     * @throws IllegalArgumentException   if the host is invalid.
+     *            the {@code host[:port]} string.
+     * @return the host name.
+     * @throws IllegalArgumentException
+     *             if the host is invalid.
      */
     private String getHostString(String host) throws IllegalArgumentException {
         host = host.trim();
@@ -431,7 +425,7 @@
         }
 
         int lastIdx = host.lastIndexOf(':');
-        
+
         if (idx == lastIdx) {
             if (-1 != idx) {
                 // only one colon, should be port
@@ -456,21 +450,22 @@
             if (Inet6Util.isIP6AddressInFullForm(host)) {
                 return host.toLowerCase();
             }
-            throw new IllegalArgumentException(Msg.getString("K004a") + " "
-                    + host);
+            // K004a=Invalid port number specified\: {0}
+            throw new IllegalArgumentException(Msg.getString("K004a", host));
         }
         // forward bracket found
         int bbracketIdx = host.indexOf(']');
         if (-1 == bbracketIdx) {
             // no back bracket found, wrong
-            throw new IllegalArgumentException(Msg.getString("K004a") + " "
-                    + host);
+            // K004a=Invalid port number specified\: {0}
+            throw new IllegalArgumentException(Msg.getString("K004a", host));
         }
         host = host.substring(0, bbracketIdx + 1);
         if (Inet6Util.isValidIP6Address(host)) {
             return host.toLowerCase();
         }
-        throw new IllegalArgumentException(Msg.getString("K004a") + " " + host);
+        // K004a=Invalid port number specified\: {0}
+        throw new IllegalArgumentException(Msg.getString("K004a", host));
     }
 
     /**
diff --git a/luni/src/main/java/java/net/SocketPermissionCollection.java b/luni/src/main/java/java/net/SocketPermissionCollection.java
index 777f9a7..60bb831 100644
--- a/luni/src/main/java/java/net/SocketPermissionCollection.java
+++ b/luni/src/main/java/java/net/SocketPermissionCollection.java
@@ -26,8 +26,6 @@
  * This class represents a list of {@code SocketPermission} objects and provides
  * a method to check whether or not a specific permission is implied by this
  * {@code SocketPermissionCollection}.
- * 
- * @since Android 1.0
  */
 final class SocketPermissionCollection extends PermissionCollection {
 
@@ -62,8 +60,6 @@
      * Returns whether this permission collection implies {@code permission}.
      * Basically it tests whether {@code permission} is the subset of this
      * collection.
-     * 
-     * @since Android 1.0
      */
     @Override
     public boolean implies(Permission permission) {
diff --git a/luni/src/main/java/java/net/SocketTimeoutException.java b/luni/src/main/java/java/net/SocketTimeoutException.java
index 32ba183..c1c762e 100644
--- a/luni/src/main/java/java/net/SocketTimeoutException.java
+++ b/luni/src/main/java/java/net/SocketTimeoutException.java
@@ -22,8 +22,6 @@
 /**
  * This exception is thrown when a timeout expired on a socket {@code read} or
  * {@code accept} operation.
- * 
- * @since Android 1.0
  */
 public class SocketTimeoutException extends InterruptedIOException {
 
@@ -32,8 +30,6 @@
     /**
      * Creates a new {@code SocketTimeoutException} instance with its walkback
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public SocketTimeoutException() {
         super();
@@ -45,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message of this exception.
-     * @since Android 1.0
      */
     public SocketTimeoutException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/net/URI.java b/luni/src/main/java/java/net/URI.java
index 4b1f4df..7fd08a5 100644
--- a/luni/src/main/java/java/net/URI.java
+++ b/luni/src/main/java/java/net/URI.java
@@ -28,8 +28,6 @@
 
 /**
  * This class represents an instance of a URI as defined by RFC 2396.
- * 
- * @since Android 1.0
  */
 public final class URI implements Comparable<URI>, Serializable {
 
@@ -78,13 +76,12 @@
 
     /**
      * Creates a new URI instance according to the given string {@code uri}.
-     * 
+     *
      * @param uri
      *            the textual URI representation to be parsed into a URI object.
      * @throws URISyntaxException
      *             if the given string {@code uri} doesn't fit to the
      *             specification RFC2396 or could not be parsed correctly.
-     * @since Android 1.0
      */
     public URI(String uri) throws URISyntaxException {
         new Helper().parseURI(uri, false);
@@ -96,8 +93,7 @@
      * string will be parsed later on to create the URI instance.
      * <p>
      * {@code [scheme:]scheme-specific-part[#fragment]}
-     * </p>
-     * 
+     *
      * @param scheme
      *            the scheme part of the URI.
      * @param ssp
@@ -107,7 +103,6 @@
      * @throws URISyntaxException
      *             if the temporary created string doesn't fit to the
      *             specification RFC2396 or could not be parsed correctly.
-     * @since Android 1.0
      */
     public URI(String scheme, String ssp, String frag)
             throws URISyntaxException {
@@ -135,8 +130,7 @@
      * string will be parsed later on to create the URI instance.
      * <p>
      * {@code [scheme:][user-info@]host[:port][path][?query][#fragment]}
-     * </p>
-     * 
+     *
      * @param scheme
      *            the scheme part of the URI.
      * @param userinfo
@@ -156,7 +150,6 @@
      * @throws URISyntaxException
      *             if the temporary created string doesn't fit to the
      *             specification RFC2396 or could not be parsed correctly.
-     * @since Android 1.0
      */
     public URI(String scheme, String userinfo, String host, int port,
             String path, String query, String fragment)
@@ -230,8 +223,7 @@
      * string will be parsed later on to create the URI instance.
      * <p>
      * {@code [scheme:]host[path][#fragment]}
-     * </p>
-     * 
+     *
      * @param scheme
      *            the scheme part of the URI.
      * @param host
@@ -243,7 +235,6 @@
      * @throws URISyntaxException
      *             if the temporary created string doesn't fit to the
      *             specification RFC2396 or could not be parsed correctly.
-     * @since Android 1.0
      */
     public URI(String scheme, String host, String path, String fragment)
             throws URISyntaxException {
@@ -256,8 +247,7 @@
      * string will be parsed later on to create the URI instance.
      * <p>
      * {@code [scheme:][//authority][path][?query][#fragment]}
-     * </p>
-     * 
+     *
      * @param scheme
      *            the scheme part of the URI.
      * @param authority
@@ -272,7 +262,6 @@
      * @throws URISyntaxException
      *             if the temporary created string doesn't fit to the
      *             specification RFC2396 or could not be parsed correctly.
-     * @since Android 1.0
      */
     public URI(String scheme, String authority, String path, String query,
             String fragment) throws URISyntaxException {
@@ -718,7 +707,7 @@
                     // case for a closed bracket at end of IP [x:x:x:...x]
                     case ']':
                         if (i != length - 1) {
-                            return false; // must be last charcter
+                            return false; // must be last character
                         }
                         if (ipAddress.charAt(0) != '[') {
                             return false; // must have a open [
@@ -856,11 +845,10 @@
      * in the natural case-sensitive way. A hierarchical URI is less than an
      * opaque URI and if one part is {@code null} the URI with the undefined
      * part is less than the other one.
-     * 
+     *
      * @param uri
      *            the URI this instance has to compare with.
      * @return the value representing the order of the two instances.
-     * @since Android 1.0
      */
     public int compareTo(URI uri) {
         int ret = 0;
@@ -969,11 +957,10 @@
     /**
      * Parses the given argument {@code uri} and creates an appropriate URI
      * instance.
-     * 
+     *
      * @param uri
      *            the string which has to be parsed to create the URI instance.
      * @return the created instance representing the given URI.
-     * @since Android 1.0
      */
     public static URI create(String uri) {
         URI result = null;
@@ -1057,12 +1044,11 @@
      * Compares this URI instance with the given argument {@code o} and
      * determines if both are equal. Two URI instances are equal if all single
      * parts are identical in their meaning.
-     * 
+     *
      * @param o
      *            the URI this instance has to be compared with.
      * @return {@code true} if both URI instances point to the same resource,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -1147,9 +1133,8 @@
 
     /**
      * Gets the decoded authority part of this URI.
-     * 
+     *
      * @return the decoded authority part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getAuthority() {
         return decode(authority);
@@ -1159,7 +1144,6 @@
      * Gets the decoded fragment part of this URI.
      * 
      * @return the decoded fragment part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getFragment() {
         return decode(fragment);
@@ -1169,7 +1153,6 @@
      * Gets the host part of this URI.
      * 
      * @return the host part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getHost() {
         return host;
@@ -1179,7 +1162,6 @@
      * Gets the decoded path part of this URI.
      * 
      * @return the decoded path part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getPath() {
         return decode(path);
@@ -1189,7 +1171,6 @@
      * Gets the port number of this URI.
      * 
      * @return the port number or {@code -1} if undefined.
-     * @since Android 1.0
      */
     public int getPort() {
         return port;
@@ -1199,7 +1180,6 @@
      * Gets the decoded query part of this URI.
      * 
      * @return the decoded query part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getQuery() {
         return decode(query);
@@ -1209,7 +1189,6 @@
      * Gets the authority part of this URI in raw form.
      * 
      * @return the encoded authority part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawAuthority() {
         return authority;
@@ -1219,7 +1198,6 @@
      * Gets the fragment part of this URI in raw form.
      * 
      * @return the encoded fragment part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawFragment() {
         return fragment;
@@ -1229,7 +1207,6 @@
      * Gets the path part of this URI in raw form.
      * 
      * @return the encoded path part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawPath() {
         return path;
@@ -1239,7 +1216,6 @@
      * Gets the query part of this URI in raw form.
      * 
      * @return the encoded query part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawQuery() {
         return query;
@@ -1249,17 +1225,15 @@
      * Gets the scheme-specific part of this URI in raw form.
      * 
      * @return the encoded scheme-specific part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawSchemeSpecificPart() {
         return schemespecificpart;
     }
-    
+
     /**
      * Gets the user-info part of this URI in raw form.
      * 
      * @return the encoded user-info part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawUserInfo() {
         return userinfo;
@@ -1269,17 +1243,15 @@
      * Gets the scheme part of this URI.
      * 
      * @return the scheme part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getScheme() {
         return scheme;
     }
-    
+
     /**
      * Gets the decoded scheme-specific part of this URI.
      * 
      * @return the decoded scheme-specific part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getSchemeSpecificPart() {
         return decode(schemespecificpart);
@@ -1289,7 +1261,6 @@
      * Gets the decoded user-info part of this URI.
      * 
      * @return the decoded user-info part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getUserInfo() {
         return decode(userinfo);
@@ -1297,9 +1268,8 @@
 
     /**
      * Gets the hashcode value of this URI instance.
-     * 
+     *
      * @return the appropriate hashcode value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -1314,7 +1284,6 @@
      * defined in this URI.
      * 
      * @return {@code true} if this URI is absolute, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isAbsolute() {
         return absolute;
@@ -1327,7 +1296,6 @@
      * undefined.
      * 
      * @return {@code true} if the URI is opaque, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isOpaque() {
         return opaque;
@@ -1424,10 +1392,9 @@
 
     /**
      * Normalizes the path part of this URI.
-     * 
+     *
      * @return an URI object which represents this instance with a normalized
      *         path.
-     * @since Android 1.0
      */
     public URI normalize() {
         if (opaque) {
@@ -1450,12 +1417,11 @@
      * Tries to parse the authority component of this URI to divide it into the
      * host, port, and user-info. If this URI is already determined as a
      * ServerAuthority this instance will be returned without changes.
-     * 
+     *
      * @return this instance with the components of the parsed server authority.
      * @throws URISyntaxException
      *             if the authority part could not be parsed as a server-based
      *             authority.
-     * @since Android 1.0
      */
     public URI parseServerAuthority() throws URISyntaxException {
         if (!serverAuthority) {
@@ -1467,11 +1433,10 @@
     /**
      * Makes the given URI {@code relative} to a relative URI against the URI
      * represented by this instance.
-     * 
+     *
      * @param relative
      *            the URI which has to be relativized against this URI.
      * @return the relative URI.
-     * @since Android 1.0
      */
     public URI relativize(URI relative) {
         if (relative.opaque || opaque) {
@@ -1516,17 +1481,17 @@
         result.query = relative.query;
         // the result URI is the remainder of the relative URI's path
         result.path = relativePath.substring(thisPath.length());
+        result.setSchemeSpecificPart();
         return result;
     }
 
     /**
      * Resolves the given URI {@code relative} against the URI represented by
      * this instance.
-     * 
+     *
      * @param relative
      *            the URI which has to be resolved against this URI.
      * @return the resolved URI.
-     * @since Android 1.0
      */
     public URI resolve(URI relative) {
         if (relative.absolute || opaque) {
@@ -1602,12 +1567,11 @@
      * Creates a new URI instance by parsing the given string {@code relative}
      * and resolves the created URI against the URI represented by this
      * instance.
-     * 
+     *
      * @param relative
      *            the given string to create the new URI instance which has to
      *            be resolved later on.
      * @return the created and resolved URI.
-     * @since Android 1.0
      */
     public URI resolve(String relative) {
         return resolve(create(relative));
@@ -1652,9 +1616,8 @@
     /**
      * Returns the textual string representation of this URI instance using the
      * US-ASCII encoding.
-     * 
+     *
      * @return the US-ASCII string representation of this URI.
-     * @since Android 1.0
      */
     public String toASCIIString() {
         return encodeOthers(toString());
@@ -1662,9 +1625,8 @@
 
     /**
      * Returns the textual string representation of this URI instance.
-     * 
+     *
      * @return the textual string representation of this URI.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -1751,12 +1713,11 @@
 
     /**
      * Converts this URI instance to a URL.
-     * 
+     *
      * @return the created URL representing the same resource as this URI.
      * @throws MalformedURLException
      *             if an error occurs while creating the URL or no protocol
      *             handler could be found.
-     * @since Android 1.0
      */
     public URL toURL() throws MalformedURLException {
         if (!absolute) {
diff --git a/luni/src/main/java/java/net/URIEncoderDecoder.java b/luni/src/main/java/java/net/URIEncoderDecoder.java
index a9ef3c1..4bf95ab 100644
--- a/luni/src/main/java/java/net/URIEncoderDecoder.java
+++ b/luni/src/main/java/java/net/URIEncoderDecoder.java
@@ -27,8 +27,6 @@
  * application/x-www-form-urlencoded} MIME content type. It contains helper
  * methods used by the URI class, and performs encoding and decoding in a
  * slightly different way than {@code URLEncoder} and {@code URLDecoder}.
- * 
- * @since Android 1.0
  */
 class URIEncoderDecoder {
 
@@ -43,8 +41,7 @@
      * US-ASCII set, and are not ISO Control or are not ISO Space characters)
      * <p>
      * called from {@code URI.Helper.parseURI()} to validate each component
-     * </p>
-     * 
+     *
      * @param s
      *            {@code java.lang.String} the string to be validated
      * @param legal
@@ -100,14 +97,12 @@
      * by '%'.
      * <p>
      * For example: '#' -> %23
-     * </p>
      * Other characters, which are unicode chars that are not US-ASCII, and are
      * not ISO Control or are not ISO Space chars, are preserved.
      * <p>
      * Called from {@code URI.quoteComponent()} (for multiple argument
      * constructors)
-     * </p>
-     * 
+     *
      * @param s
      *            java.lang.String the string to be converted
      * @param legal
@@ -145,10 +140,9 @@
      * converted into their hexidecimal value prepended by '%'.
      * <p>
      * For example: Euro currency symbol -> "%E2%82%AC".
-     * </p>
+     * <p>
      * Called from URI.toASCIIString()
-     * </p>
-     * 
+     *
      * @param s
      *            java.lang.String the string to be converted
      * @return java.lang.String the converted string
@@ -178,11 +172,10 @@
      *'%' and two following hex digit characters are converted to the
      * equivalent byte value. All other characters are passed through
      * unmodified.
-     * </p>
+     * <p>
      * e.g. "A%20B%20C %24%25" -> "A B C $%"
      * <p>
      * Called from URI.getXYZ() methods
-     * </p>
      * 
      * @param s
      *            java.lang.String The encoded string.
diff --git a/luni/src/main/java/java/net/URISyntaxException.java b/luni/src/main/java/java/net/URISyntaxException.java
index e7e332e..2daf35f 100644
--- a/luni/src/main/java/java/net/URISyntaxException.java
+++ b/luni/src/main/java/java/net/URISyntaxException.java
@@ -22,8 +22,6 @@
 /**
  * A {@code URISyntaxException} will be thrown if some information could not be parsed
  * while creating a URI.
- * 
- * @since Android 1.0
  */
 public class URISyntaxException extends Exception {
 
@@ -49,7 +47,6 @@
      *             {@code null}.
      * @throws IllegalArgumentException
      *             if the value for {@code index} is lesser than {@code -1}.
-     * @since Android 1.0
      */
     public URISyntaxException(String input, String reason, int index) {
         super(reason);
@@ -77,7 +74,6 @@
      * @throws NullPointerException
      *             if one of the arguments {@code input} or {@code reason} is
      *             {@code null}.
-     * @since Android 1.0
      */
     public URISyntaxException(String input, String reason) {
         super(reason);
@@ -95,7 +91,6 @@
      * index is unknown/unavailable.
      * 
      * @return the index of the syntax error.
-     * @since Android 1.0
      */
     public int getIndex() {
         return index;
@@ -105,7 +100,6 @@
      * Gets a description of the syntax error.
      * 
      * @return the string describing the syntax error.
-     * @since Android 1.0
      */
     public String getReason() {
         return super.getMessage();
@@ -115,7 +109,6 @@
      * Gets the initial string that contains an invalid syntax.
      * 
      * @return the string that caused the exception.
-     * @since Android 1.0
      */
     public String getInput() {
         return input;
@@ -128,7 +121,6 @@
      * 
      * @return a sting containing information about the exception.
      * @see java.lang.Throwable#getMessage()
-     * @since Android 1.0
      */
     @Override
     public String getMessage() {
diff --git a/luni/src/main/java/java/net/URL.java b/luni/src/main/java/java/net/URL.java
index 2bc8c6c..9b0fdc4 100644
--- a/luni/src/main/java/java/net/URL.java
+++ b/luni/src/main/java/java/net/URL.java
@@ -34,8 +34,6 @@
  * which generates the output dynamically. A URL is divided in its parts
  * protocol, host name, port, path, file, user-info, query, reference and
  * authority. However, not each of this parts has to be defined.
- * 
- * @since Android 1.0
  */
 public final class URL implements java.io.Serializable {
     private static final long serialVersionUID = -7627629688361524110L;
@@ -131,11 +129,9 @@
      * <p>
      * A security check is performed to verify whether the current policy allows
      * to set the stream handler factory.
-     * </p>
-     * 
+     *
      * @param streamFactory
      *            the factory to be used for creating stream protocol handlers.
-     * @since Android 1.0
      */
     public static synchronized void setURLStreamHandlerFactory(
             URLStreamHandlerFactory streamFactory) {
@@ -158,7 +154,6 @@
      * @throws MalformedURLException
      *             if the given string {@code spec} could not be parsed as a
      *             URL.
-     * @since Android 1.0
      */
     public URL(String spec) throws MalformedURLException {
         this((URL) null, spec, (URLStreamHandler) null);
@@ -178,7 +173,6 @@
      * @throws MalformedURLException
      *             if the given string {@code spec} could not be parsed as a URL
      *             or an invalid protocol has been found.
-     * @since Android 1.0
      */
     public URL(URL context, String spec) throws MalformedURLException {
         this(context, spec, (URLStreamHandler) null);
@@ -202,7 +196,6 @@
      * @throws MalformedURLException
      *             if the given string {@code spec} could not be parsed as a URL
      *             or an invalid protocol has been found.
-     * @since Android 1.0
      */
     public URL(URL context, String spec, URLStreamHandler handler)
             throws MalformedURLException {
@@ -235,8 +228,6 @@
                 // According to RFC 2396 scheme part should match
                 // the following expression:
                 // alpha *( alpha | digit | "+" | "-" | "." )
-                // BEGIN android-changed
-                // copied from newer version of harmony
                 char c = protocol.charAt(0);
                 boolean valid = ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
                 for (int i = 1; valid && (i < protocol.length()); i++) {
@@ -253,10 +244,9 @@
                     index = -1;
                 } else {
                     // Ignore case in protocol names.
-                    // Scheme is defined by ASCII characters.
+                	// Scheme is defined by ASCII characters.
                     protocol = Util.toASCIILowerCase(protocol);
                 }
-                // END android-changed
             }
         }
 
@@ -338,7 +328,6 @@
      * @throws MalformedURLException
      *             if the combination of all arguments do not represent a valid
      *             URL or the protocol is invalid.
-     * @since Android 1.0
      */
     public URL(String protocol, String host, String file)
             throws MalformedURLException {
@@ -361,7 +350,6 @@
      * @throws MalformedURLException
      *             if the combination of all arguments do not represent a valid
      *             URL or the protocol is invalid.
-     * @since Android 1.0
      */
     public URL(String protocol, String host, int port, String file)
             throws MalformedURLException {
@@ -371,7 +359,7 @@
     /**
      * Creates a new URL instance using the given arguments. The URL uses the
      * specified port instead of the default port for the given protocol.
-     * 
+     *
      * @param protocol
      *            the protocol of the new URL.
      * @param host
@@ -386,25 +374,26 @@
      * @throws MalformedURLException
      *             if the combination of all arguments do not represent a valid
      *             URL or the protocol is invalid.
-     * @since Android 1.0
+     * @throws SecurityException
+     *             if {@code handler} is non-{@code null}, and a security
+     *             manager is installed that disallows user-defined protocol
+     *             handlers.
      */
     public URL(String protocol, String host, int port, String file,
             URLStreamHandler handler) throws MalformedURLException {
         if (port < -1) {
-            throw new MalformedURLException(org.apache.harmony.luni.util.Msg
-                    .getString("K0325", port)); //$NON-NLS-1$
+            throw new MalformedURLException(Msg.getString("K0325", port)); //$NON-NLS-1$
         }
 
         if (host != null && host.indexOf(":") != -1 && host.charAt(0) != '[') { //$NON-NLS-1$
             host = "[" + host + "]"; //$NON-NLS-1$ //$NON-NLS-2$
         }
 
-        if (protocol != null) {
-            this.protocol = protocol;
-        } else {
-            throw new NullPointerException(Msg.getString("K00b3", protocol)); //$NON-NLS-1$
+        if (protocol == null) {
+            throw new NullPointerException(Msg.getString("K00b3", "null")); //$NON-NLS-1$ //$NON-NLS-2$
         }
 
+        this.protocol = protocol;
         this.host = host;
         this.port = port;
 
@@ -427,8 +416,7 @@
             setupStreamHandler();
             if (strmHandler == null) {
                 throw new MalformedURLException(
-                        org.apache.harmony.luni.util.Msg.getString(
-                                "K00b3", protocol)); //$NON-NLS-1$
+                        Msg.getString("K00b3", protocol)); //$NON-NLS-1$
             }
         } else {
             SecurityManager sm = System.getSecurityManager();
@@ -479,7 +467,6 @@
      *            the file to be set.
      * @param ref
      *            the reference to be set.
-     * @since Android 1.0
      */
     protected void set(String protocol, String host, int port, String file,
             String ref) {
@@ -506,8 +493,7 @@
      *            the URL this instance has to be compared with.
      * @return {@code true} if both instances represents the same URL, {@code
      *         false} otherwise.
-     * @see #hashCode
-     * @since Android 1.0
+     * @see #hashCode()
      */
     @Override
     public boolean equals(Object o) {
@@ -532,7 +518,6 @@
      *            the URL to compare against.
      * @return {@code true} if both instances refer to the same resource,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean sameFile(URL otherURL) {
         return strmHandler.sameFile(this, otherURL);
@@ -542,7 +527,6 @@
      * Gets the hashcode value of this URL instance.
      * 
      * @return the appropriate hashcode value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -560,7 +544,6 @@
      * Note that this will overwrite any existing stream handler with the new
      * one. Senders must check if the strmHandler is null before calling the
      * method if they do not want this behavior (a speed optimization).
-     * </p>
      */
     void setupStreamHandler() {
         // Check for a cached (previously looked up) handler for
@@ -629,12 +612,10 @@
      * <li>Image for pictures</li>
      * <li>AudioClip for audio sequences</li>
      * <li>{@link InputStream} for all other data</li>
-     * </p>
      * 
      * @return the content of the referred resource.
      * @throws IOException
      *             if an error occurs obtaining the content.
-     * @since Android 1.0
      */
     public final Object getContent() throws IOException {
         return openConnection().getContent();
@@ -654,7 +635,6 @@
      *         type.
      * @throws IOException
      *             if an error occurs obtaining the content.
-     * @since Android 1.0
      */
     // Param not generic in spec
     @SuppressWarnings("unchecked")
@@ -668,7 +648,6 @@
      * @return the stream which allows to read the resource.
      * @throws IOException
      *             if an error occurs while opening the InputStream.
-     * @since Android 1.0
      */
     public final InputStream openStream() throws java.io.IOException {
         return openConnection().getInputStream();
@@ -681,7 +660,6 @@
      * @return the connection to this URL.
      * @throws IOException
      *             if an error occurs while opening the connection.
-     * @since Android 1.0
      */
     public URLConnection openConnection() throws IOException {
         return strmHandler.openConnection(this);
@@ -693,7 +671,6 @@
      * @return the URI instance that represents this URL.
      * @throws URISyntaxException
      *             if this URL cannot be converted into a URI.
-     * @since Android 1.0
      */
     public URI toURI() throws URISyntaxException {
         return new URI(toExternalForm());
@@ -718,7 +695,6 @@
      * @throws UnsupportedOperationException
      *             if the protocol handler does not support opening connections
      *             through proxies.
-     * @since Android 1.0
      */
     public URLConnection openConnection(Proxy proxy) throws IOException {
         if (null == proxy) {
@@ -733,7 +709,6 @@
      * {@code toExternalForm()}.
      * 
      * @return the string representation of this URL.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -745,7 +720,6 @@
      * this URL.
      * 
      * @return the string representation of this URL.
-     * @since Android 1.0
      */
     public String toExternalForm() {
         if (strmHandler == null) {
@@ -798,8 +772,7 @@
      * <p>
      * Note that, we really only need the readObject method but the spec that
      * says readObject will be ignored if no writeObject is present.
-     * </p>
-     * 
+     *
      * @param s
      *            the stream to write on.
      * @throws IOException
@@ -814,7 +787,6 @@
      * 
      * @return the file name this URL refers to or an empty string if the file
      *         part is not set.
-     * @since Android 1.0
      */
     public String getFile() {
         return file;
@@ -824,7 +796,6 @@
      * Gets the value of the host part of this URL.
      * 
      * @return the host name or IP address of this URL.
-     * @since Android 1.0
      */
     public String getHost() {
         return host;
@@ -834,7 +805,6 @@
      * Gets the port number of this URL or {@code -1} if the port is not set.
      * 
      * @return the port number of this URL.
-     * @since Android 1.0
      */
     public int getPort() {
         return port;
@@ -844,7 +814,6 @@
      * Gets the protocol of this URL.
      * 
      * @return the protocol type of this URL.
-     * @since Android 1.0
      */
     public String getProtocol() {
         return protocol;
@@ -854,7 +823,6 @@
      * Gets the value of the reference part of this URL.
      * 
      * @return the reference part of this URL.
-     * @since Android 1.0
      */
     public String getRef() {
         return ref;
@@ -864,7 +832,6 @@
      * Gets the value of the query part of this URL.
      * 
      * @return the query part of this URL.
-     * @since Android 1.0
      */
     public String getQuery() {
         return query;
@@ -874,7 +841,6 @@
      * Gets the value of the path part of this URL.
      * 
      * @return the path part of this URL.
-     * @since Android 1.0
      */
     public String getPath() {
         return path;
@@ -884,7 +850,6 @@
      * Gets the value of the user-info part of this URL.
      * 
      * @return the user-info part of this URL.
-     * @since Android 1.0
      */
     public String getUserInfo() {
         return userInfo;
@@ -894,7 +859,6 @@
      * Gets the value of the authority part of this URL.
      * 
      * @return the authority part of this URL.
-     * @since Android 1.0
      */
     public String getAuthority() {
         return authority;
@@ -921,7 +885,6 @@
      *            the query to be set.
      * @param ref
      *            the reference to be set.
-     * @since Android 1.0
      */
     protected void set(String protocol, String host, int port,
             String authority, String userInfo, String path, String query,
@@ -941,21 +904,13 @@
         this.query = query;
     }
 
-    // BEGIN android-removed
-    // copied from newer version of harmony
-    // URLStreamHandler getStreamHandler() {
-    //     return strmHandler;
-    // }
-    // END android-removed
-
     /**
      * Gets the default port number of the protocol used by this URL. If no
      * default port is defined by the protocol or the {@code URLStreamHandler},
      * {@code -1} will be returned.
-     * 
+     *
      * @return the default port number according to the protocol of this URL.
      * @see URLStreamHandler#getDefaultPort
-     * @since Android 1.0
      */
     public int getDefaultPort() {
         return strmHandler.getDefaultPort();
diff --git a/luni/src/main/java/java/net/URLClassLoader.java b/luni/src/main/java/java/net/URLClassLoader.java
index c70ed45..dd3c9bf 100644
--- a/luni/src/main/java/java/net/URLClassLoader.java
+++ b/luni/src/main/java/java/net/URLClassLoader.java
@@ -17,12 +17,15 @@
 
 package java.net;
 
+import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FilePermission;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
 import java.security.AccessControlContext;
 import java.security.AccessController;
@@ -35,22 +38,14 @@
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.IdentityHashMap;
 import java.util.List;
-import java.util.ListIterator;
 import java.util.Map;
-import java.util.Set;
 import java.util.StringTokenizer;
-import java.util.Vector;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
-import java.util.zip.ZipEntry;
 
-import org.apache.harmony.luni.util.InvalidJarIndexException;
 import org.apache.harmony.luni.util.Msg;
 
 /**
@@ -58,33 +53,17 @@
  * list of URLs which can refer to either directories or JAR files. Classes
  * loaded by this {@code URLClassLoader} are granted permission to access the
  * URLs contained in the URL search list.
- * 
- * @since Android 1.0
  */
 public class URLClassLoader extends SecureClassLoader {
 
-    private static URL[] NO_PATH = new URL[0];
+    ArrayList<URL> originalUrls;
 
-    @SuppressWarnings("unchecked")
-    private static <K, V> Hashtable<K, V>[] newHashtableArray(int size) {
-        return new Hashtable[size];
-    }
-
-    URL[] urls, orgUrls;
-
-    Set<URL> invalidUrls = Collections.synchronizedSet(new HashSet<URL>());
-
-    private Map<URL, JarFile> resCache = 
-            Collections.synchronizedMap(new IdentityHashMap<URL, JarFile>(32));
-
-    private Object lock = new Object();
+    List<URL> searchList;
+    ArrayList<URLHandler> handlerList;
+    Map<URL, URLHandler> handlerMap = new HashMap<URL, URLHandler>();
 
     private URLStreamHandlerFactory factory;
 
-    HashMap<URL, URL[]> extensions;
-
-    Hashtable<String, URL[]>[] indexes;
-
     private AccessControlContext currentContext;
 
     static class SubURLClassLoader extends URLClassLoader {
@@ -103,7 +82,7 @@
          * Overrides the {@code loadClass()} of {@code ClassLoader}. It calls
          * the security manager's {@code checkPackageAccess()} before
          * attempting to load the class.
-         * 
+         *
          * @return the Class object.
          * @param className
          *            String the name of the class to search for.
@@ -115,7 +94,7 @@
          */
         @Override
         protected synchronized Class<?> loadClass(String className,
-                boolean resolveClass) throws ClassNotFoundException {
+                                                  boolean resolveClass) throws ClassNotFoundException {
             SecurityManager sm = System.getSecurityManager();
             if (sm != null && !checkingPackageAccess) {
                 int index = className.lastIndexOf('.');
@@ -132,12 +111,503 @@
         }
     }
 
+    static class IndexFile {
+
+        private HashMap<String, ArrayList<URL>> map;
+        //private URLClassLoader host;
+
+
+        static IndexFile readIndexFile(JarFile jf, JarEntry indexEntry, URL url) {
+            BufferedReader in = null;
+            InputStream is = null;
+            try {
+                // Add mappings from resource to jar file
+                String parentURLString = getParentURL(url).toExternalForm();
+                String prefix = "jar:" //$NON-NLS-1$
+                        + parentURLString + "/"; //$NON-NLS-1$
+                is = jf.getInputStream(indexEntry);
+                in = new BufferedReader(new InputStreamReader(is, "UTF8"));
+                HashMap<String, ArrayList<URL>> pre_map = new HashMap<String, ArrayList<URL>>();
+                // Ignore the 2 first lines (index version)
+                if (in.readLine() == null) return null;
+                if (in.readLine() == null) return null;
+                TOP_CYCLE:
+                while (true) {
+                    String line = in.readLine();
+                    if (line == null) {
+                        break;
+                    }
+                    URL jar = new URL(prefix + line + "!/"); //$NON-NLS-1$
+                    while (true) {
+                        line = in.readLine();
+                        if (line == null) {
+                            break TOP_CYCLE;
+                        }
+                        if ("".equals(line)) {
+                            break;
+                        }
+                        ArrayList<URL> list;
+                        if (pre_map.containsKey(line)) {
+                            list = pre_map.get(line);
+                        } else {
+                            list = new ArrayList<URL>();
+                            pre_map.put(line, list);
+                        }
+                        list.add(jar);
+                    }
+                }
+                if (!pre_map.isEmpty()) {
+                    return new IndexFile(pre_map);
+                }
+            } catch (MalformedURLException e) {
+                // Ignore this jar's index
+            } catch (IOException e) {
+                // Ignore this jar's index
+            }
+            finally {
+                if (in != null) {
+                    try {
+                        in.close();
+                    } catch (IOException e) {
+                    }
+                }
+                if (is != null) {
+                    try {
+                        is.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+            return null;
+        }
+
+        private static URL getParentURL(URL url) throws IOException {
+            URL fileURL = ((JarURLConnection) url.openConnection()).getJarFileURL();
+            String file = fileURL.getFile();
+            String parentFile = new File(file).getParent();
+            parentFile = parentFile.replace(File.separatorChar, '/');
+            if (parentFile.charAt(0) != '/') {
+                parentFile = "/" + parentFile; //$NON-NLS-1$
+            }
+            URL parentURL = new URL(fileURL.getProtocol(), fileURL
+                    .getHost(), fileURL.getPort(), parentFile);
+            return parentURL;
+        }
+
+        public IndexFile(HashMap<String, ArrayList<URL>> map) {
+            this.map = map;
+        }
+
+        ArrayList<URL> get(String name) {
+            return map.get(name);
+        }
+    }
+
+    class URLHandler {
+        URL url;
+        URL codeSourceUrl;
+
+        public URLHandler(URL url) {
+            this.url = url;
+            this.codeSourceUrl = url;
+        }
+
+        void findResources(String name, ArrayList<URL> resources) {
+            URL res = findResource(name);
+            if (res != null && !resources.contains(res)) {
+                resources.add(res);
+            }
+        }
+
+        Class<?> findClass(String packageName, String name, String origName) {
+            URL resURL = targetURL(url, name);
+            if (resURL != null) {
+                try {
+                    InputStream is = resURL.openStream();
+                    return createClass(is, packageName, origName);
+                } catch (IOException e) {
+                }
+            }
+            return null;
+        }
+
+
+        Class<?> createClass(InputStream is, String packageName, String origName) {
+            if (is == null) {
+                return null;
+            }
+            byte[] clBuf = null;
+            try {
+                clBuf = getBytes(is);
+            } catch (IOException e) {
+                return null;
+            } finally {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                }
+            }
+            if (packageName != null) {
+                String packageDotName = packageName.replace('/', '.');
+                Package packageObj = getPackage(packageDotName);
+                if (packageObj == null) {
+                    definePackage(packageDotName, null, null,
+                            null, null, null, null, null);
+                } else {
+                    if (packageObj.isSealed()) {
+                        throw new SecurityException(Msg
+                                .getString("K004c")); //$NON-NLS-1$
+                    }
+                }
+            }
+            return defineClass(origName, clBuf, 0, clBuf.length, new CodeSource(codeSourceUrl, (Certificate[]) null));
+        }
+
+        URL findResource(String name) {
+            URL resURL = targetURL(url, name);
+            if (resURL != null) {
+                try {
+                    URLConnection uc = resURL.openConnection();
+                    uc.getInputStream().close();
+                    // HTTP can return a stream on a non-existent file
+                    // So check for the return code;
+                    if (!resURL.getProtocol().equals("http")) { //$NON-NLS-1$
+                        return resURL;
+                    }
+                    int code;
+                    if ((code = ((HttpURLConnection) uc).getResponseCode()) >= 200
+                            && code < 300) {
+                        return resURL;
+                    }
+                } catch (SecurityException e) {
+                    return null;
+                } catch (IOException e) {
+                    return null;
+                }
+            }
+            return null;
+        }
+
+        URL targetURL(URL base, String name) {
+            try {
+                String file = base.getFile() + URIEncoderDecoder.quoteIllegal(name,
+                        "/@" + URI.someLegal);
+
+                return new URL(base.getProtocol(), base.getHost(), base.getPort(),
+                        file, null);
+            } catch (UnsupportedEncodingException e) {
+                return null;
+            } catch (MalformedURLException e) {
+                return null;
+            }
+        }
+
+    }
+
+    class URLJarHandler extends URLHandler {
+        final JarFile jf;
+        final String prefixName;
+        final IndexFile index;
+        final Map<URL, URLHandler> subHandlers = new HashMap<URL, URLHandler>();
+
+        public URLJarHandler(URL url, URL jarURL, JarFile jf, String prefixName) {
+            super(url);
+            this.jf = jf;
+            this.prefixName = prefixName;
+            this.codeSourceUrl = jarURL;
+            final JarEntry je = jf.getJarEntry("META-INF/INDEX.LIST"); //$NON-NLS-1$
+            this.index = (je == null ? null : IndexFile.readIndexFile(jf, je, url));
+        }
+
+        public URLJarHandler(URL url, URL jarURL, JarFile jf, String prefixName, IndexFile index) {
+            super(url);
+            this.jf = jf;
+            this.prefixName = prefixName;
+            this.index = index;
+            this.codeSourceUrl = jarURL;
+        }
+
+        IndexFile getIndex() {
+            return index;
+        }
+
+        @Override
+        void findResources(String name, ArrayList<URL> resources) {
+            URL res = findResourceInOwn(name);
+            if (res != null && !resources.contains(res)) {
+                resources.add(res);
+            }
+            if (index != null) {
+                int pos = name.lastIndexOf("/"); //$NON-NLS-1$
+                // only keep the directory part of the resource
+                // as index.list only keeps track of directories and root files
+                String indexedName = (pos > 0) ? name.substring(0, pos) : name;
+                ArrayList<URL> urls = index.get(indexedName);
+                if (urls != null) {
+                    urls.remove(url);
+                    for (URL url : urls) {
+                        URLHandler h = getSubHandler(url);
+                        if (h != null) {
+                            h.findResources(name, resources);
+                        }
+                    }
+                }
+            }
+
+        }
+
+        @Override
+        Class<?> findClass(String packageName, String name, String origName) {
+            String entryName = prefixName + name;
+            JarEntry entry = jf.getJarEntry(entryName);
+            if (entry != null) {
+                /**
+                 * Avoid recursive load class, especially the class
+                 * is an implementation class of security provider
+                 * and the jar is signed.
+                 */
+                try {
+                    Manifest manifest = jf.getManifest();
+                    return createClass(entry, manifest, packageName, origName);
+                } catch (IOException e) {
+                }
+            }
+            if (index != null) {
+                ArrayList<URL> urls;
+                if (packageName == null) {
+                    urls = index.get(name);
+                } else {
+                    urls = index.get(packageName);
+                }
+                if (urls != null) {
+                    urls.remove(url);
+                    for (URL url : urls) {
+                        URLHandler h = getSubHandler(url);
+                        if (h != null) {
+                            Class<?> res = h.findClass(packageName, name, origName);
+                            if (res != null) {
+                                return res;
+                            }
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+
+        private Class<?> createClass(JarEntry entry, Manifest manifest, String packageName, String origName) {
+            InputStream is = null;
+            byte[] clBuf = null;
+            try {
+                is = jf.getInputStream(entry);
+                clBuf = getBytes(is);
+            } catch (IOException e) {
+                return null;
+            } finally {
+                if (is != null) {
+                    try {
+                        is.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+            if (packageName != null) {
+                String packageDotName = packageName.replace('/', '.');
+                Package packageObj = getPackage(packageDotName);
+                if (packageObj == null) {
+                    if (manifest != null) {
+                        definePackage(packageDotName, manifest,
+                                codeSourceUrl);
+                    } else {
+                        definePackage(packageDotName, null, null,
+                                null, null, null, null, null);
+                    }
+                } else {
+                    boolean exception = packageObj.isSealed();
+                    if (manifest != null) {
+                        if (isSealed(manifest, packageName + "/")) {
+                            exception = !packageObj
+                                    .isSealed(codeSourceUrl);
+                        }
+                    }
+                    if (exception) {
+                        throw new SecurityException(Msg
+                                .getString("K0352", packageName)); //$NON-NLS-1$
+                    }
+                }
+            }
+            CodeSource codeS = new CodeSource(codeSourceUrl, entry.getCertificates());
+            return defineClass(origName, clBuf, 0, clBuf.length, codeS);
+        }
+
+        URL findResourceInOwn(String name) {
+            String entryName = prefixName + name;
+            if (jf.getEntry(entryName) != null) {
+                return targetURL(url, name);
+            }
+            return null;
+        }
+
+        @Override
+        URL findResource(String name) {
+            URL res = findResourceInOwn(name);
+            if (res != null) {
+                return res;
+            }
+            if (index != null) {
+                int pos = name.lastIndexOf("/"); //$NON-NLS-1$
+                // only keep the directory part of the resource
+                // as index.list only keeps track of directories and root files
+                String indexedName = (pos > 0) ? name.substring(0, pos) : name;
+                ArrayList<URL> urls = index.get(indexedName);
+                if (urls != null) {
+                    urls.remove(url);
+                    for (URL url : urls) {
+                        URLHandler h = getSubHandler(url);
+                        if (h != null) {
+                            res = h.findResource(name);
+                            if (res != null) {
+                                return res;
+                            }
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+
+        private synchronized URLHandler getSubHandler(URL url) {
+            URLHandler sub = subHandlers.get(url);
+            if (sub != null) {
+                return sub;
+            }
+            String protocol = url.getProtocol();
+            if (protocol.equals("jar")) { //$NON-NLS-1$
+                sub = createURLJarHandler(url);
+            } else if (protocol.equals("file")) { //$NON-NLS-1$
+                sub = createURLSubJarHandler(url);
+            } else {
+                sub = createURLHandler(url);
+            }
+            if (sub != null) {
+                subHandlers.put(url, sub);
+            }
+            return sub;
+        }
+
+        private URLHandler createURLSubJarHandler(URL url) {
+            String prefixName;
+            String file = url.getFile();
+            if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
+                prefixName = "";
+            } else {
+                int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$
+                if (sepIdx == -1) {
+                    // Invalid URL, don't look here again
+                    return null;
+                }
+                sepIdx += 2;
+                prefixName = file.substring(sepIdx);
+            }
+            try {
+                URL jarURL = ((JarURLConnection) url
+                        .openConnection()).getJarFileURL();
+                JarURLConnection juc = (JarURLConnection) new URL(
+                        "jar", "", //$NON-NLS-1$ //$NON-NLS-2$
+                        jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$
+                JarFile jf = juc.getJarFile();
+                URLJarHandler jarH = new URLJarHandler(url, jarURL, jf, prefixName, null);
+                // TODO : to think what we should do with indexes & manifest.class file here
+                return jarH;
+            } catch (IOException e) {
+            }
+            return null;
+        }
+
+    }
+
+    class URLFileHandler extends URLHandler {
+        private String prefix;
+
+        public URLFileHandler(URL url) {
+            super(url);
+            String baseFile = url.getFile();
+            String host = url.getHost();
+            int hostLength = 0;
+            if (host != null) {
+                hostLength = host.length();
+            }
+            StringBuilder buf = new StringBuilder(2 + hostLength
+                    + baseFile.length());
+            if (hostLength > 0) {
+                buf.append("//").append(host); //$NON-NLS-1$
+            }
+            // baseFile always ends with '/'
+            buf.append(baseFile);
+            prefix = buf.toString();
+        }
+
+        @Override
+        Class<?> findClass(String packageName, String name, String origName) {
+            String filename = prefix + name;
+            try {
+                filename = URLDecoder.decode(filename, "UTF-8"); //$NON-NLS-1$
+            } catch (IllegalArgumentException e) {
+                return null;
+            } catch (UnsupportedEncodingException e) {
+                return null;
+            }
+
+            File file = new File(filename);
+            if (file.exists()) {
+                try {
+                    InputStream is = new FileInputStream(file);
+                    return createClass(is, packageName, origName);
+                } catch (FileNotFoundException e) {
+                }
+            }
+            return null;
+        }
+
+        @Override
+        URL findResource(String name) {
+            int idx = 0;
+            String filename;
+
+            // Do not create a UNC path, i.e. \\host
+            while (idx < name.length() &&
+                   ((name.charAt(idx) == '/') || (name.charAt(idx) == '\\'))) {
+                idx++;
+            }
+
+            if (idx > 0) {
+                name = name.substring(idx);
+            }
+
+            try {
+                filename = URLDecoder.decode(prefix, "UTF-8") + name; //$NON-NLS-1$
+
+                if (new File(filename).exists()) {
+                    return targetURL(url, name);
+                }
+                return null;
+            } catch (IllegalArgumentException e) {
+                return null;
+            } catch (UnsupportedEncodingException e) {
+                // must not happen
+                throw new AssertionError(e);
+            }
+        }
+
+    }
+
+
     /**
      * Constructs a new {@code URLClassLoader} instance. The newly created
      * instance will have the system ClassLoader as its parent. URLs that end
      * with "/" are assumed to be directories, otherwise they are assumed to be
      * JAR files.
-     * 
+     *
      * @param urls
      *            the list of URLs where a specific class or file could be
      *            found.
@@ -145,7 +615,6 @@
      *             if a security manager exists and its {@code
      *             checkCreateClassLoader()} method doesn't allow creation of
      *             new ClassLoaders.
-     * @since Android 1.0
      */
     public URLClassLoader(URL[] urls) {
         this(urls, ClassLoader.getSystemClassLoader(), null);
@@ -155,7 +624,7 @@
      * Constructs a new URLClassLoader instance. The newly created instance will
      * have the system ClassLoader as its parent. URLs that end with "/" are
      * assumed to be directories, otherwise they are assumed to be JAR files.
-     * 
+     *
      * @param urls
      *            the list of URLs where a specific class or file could be
      *            found.
@@ -165,7 +634,6 @@
      *             if a security manager exists and its {@code
      *             checkCreateClassLoader()} method doesn't allow creation of
      *             new class loaders.
-     * @since Android 1.0
      */
     public URLClassLoader(URL[] urls, ClassLoader parent) {
         this(urls, parent, null);
@@ -173,267 +641,81 @@
 
     /**
      * Adds the specified URL to the search list.
-     * 
+     *
      * @param url
      *            the URL which is to add.
-     * @since Android 1.0
      */
     protected void addURL(URL url) {
         try {
-            URL search = createSearchURL(url);
-            urls = addURL(urls, search);
-            orgUrls = addURL(orgUrls, url);
-            synchronized (extensions) {
-                extensions.put(search, null);
-            }
+            originalUrls.add(url);
+            searchList.add(createSearchURL(url));
         } catch (MalformedURLException e) {
         }
     }
 
     /**
-     * Returns an array with the given URL added to the given array.
-     * 
-     * @param urlArray
-     *            {@code java.net.URL[]} the source array
-     * @param url
-     *            {@code java.net.URL} the URL to be added
-     * @return java.net.URL[] an array made of the given array and the new URL
-     */
-    URL[] addURL(URL[] urlArray, URL url) {
-        URL[] newPath = new URL[urlArray.length + 1];
-        System.arraycopy(urlArray, 0, newPath, 0, urlArray.length);
-        newPath[urlArray.length] = url;
-        Hashtable<String, URL[]>[] newIndexes = newHashtableArray(indexes.length + 1);
-        System.arraycopy(indexes, 0, newIndexes, 0, indexes.length);
-        indexes = newIndexes;
-        return newPath;
-    }
-
-    /**
      * Returns all known URLs which point to the specified resource.
-     * 
+     *
      * @param name
      *            the name of the requested resource.
      * @return the enumeration of URLs which point to the specified resource.
      * @throws IOException
      *             if an I/O error occurs while attempting to connect.
-     * @since Android 1.0
      */
     @Override
     public Enumeration<URL> findResources(final String name) throws IOException {
         if (name == null) {
             return null;
         }
-        Vector<URL> result = AccessController.doPrivileged(
-                new PrivilegedAction<Vector<URL>>() {
-                    public Vector<URL> run() {
-                        return findResources(urls, name, new Vector<URL>());
+        ArrayList<URL> result = AccessController.doPrivileged(
+                new PrivilegedAction<ArrayList<URL>>() {
+                    public ArrayList<URL> run() {
+                        ArrayList<URL> results = new ArrayList<URL>();
+                        findResourcesImpl(name, results);
+                        return results;
                     }
                 }, currentContext);
         SecurityManager sm;
         int length = result.size();
         if (length > 0 && (sm = System.getSecurityManager()) != null) {
-            Vector<URL> reduced = new Vector<URL>(length);
+            ArrayList<URL> reduced = new ArrayList<URL>(length);
             for (int i = 0; i < length; i++) {
-                URL url = result.elementAt(i);
+                URL url = result.get(i);
                 try {
                     sm.checkPermission(url.openConnection().getPermission());
-                    reduced.addElement(url);
+                    reduced.add(url);
                 } catch (IOException e) {
                 } catch (SecurityException e) {
                 }
             }
             result = reduced;
         }
-        return result.elements();
+        return Collections.enumeration(result);
     }
 
-    /**
-     * Returns a Vector of URLs among the given ones that contain the specified
-     * resource.
-     * 
-     * @return Vector the enumeration of URLs that contain the specified
-     *         resource.
-     * @param searchURLs
-     *            {@code java.net.URL[]} the array to be searched.
-     * @param name
-     *            {@code java.lang.String} the name of the requested resource.
-     */
-    Vector<URL> findResources(URL[] searchURLs, String name, Vector<URL> result) {
-        boolean findInExtensions = searchURLs == urls;
-        for (int i = 0; i < searchURLs.length; i++) {
-            if (!invalidUrls.contains(searchURLs[i])) {
-                URL[] search = new URL[] { searchURLs[i] };
-                URL res = findResourceImpl(search, name);
-                if (!invalidUrls.contains(search[0])) {
-                    if (res != null && !result.contains(res)) {
-                        result.addElement(res);
-                    }
-                    if (findInExtensions) {
-                        findInExtensions(explore(searchURLs[i], i), name, i,
-                                result, false);
-                    }
-                }
+    void findResourcesImpl(String name, ArrayList<URL> result) {
+        int n = 0;
+        while (true) {
+            URLHandler handler = getHandler(n++);
+            if (handler == null) {
+                break;
             }
+            handler.findResources(name, result);
         }
-        return result;
     }
 
-    /**
-     * Returns an {@code Object[]} containing a class, a URL, and a vector of
-     * URLs, two of which are {@code null}, according to the caller, which is
-     * identified by the {@code int} type.
-     * 
-     * @return Object[] a 3-element array : {Class, URL, Vector}. The non-null
-     *         element contains the resource(s) found, which are searched in in
-     *         {@code indexes[i]}.
-     * @param i
-     *            the index of 'indexes' array to use.
-     * @param name
-     *            the resource to look for : either a resource or a class.
-     * @param resources
-     *            {@code boolean} indicates that a vector of URL should be
-     *            returned as the non {@code null} element in {@code Object[]}.
-     * @param url
-     *            if {@code true} a URL should be returned as the non-null
-     *            element, if {@code false} a class should be returned.
-     */
-    Object findInIndex(int i, String name, Vector<URL> resources, boolean url) {
-        Hashtable<String, URL[]> index = indexes[i];
-        if (index != null) {
-            int pos = name.lastIndexOf("/"); //$NON-NLS-1$
-            // only keep the directory part of the resource
-            // as index.list only keeps track of directories and root files
-            String indexedName = (pos > 0) ? name.substring(0, pos) : name;
-            URL[] jarURLs;
-            if (resources != null) {
-                jarURLs = index.get(indexedName);
-                if (jarURLs != null) {
-                    findResources(jarURLs, name, resources);
-                }
-            } else if (url) {
-                jarURLs = index.get(indexedName);
-                if (jarURLs != null) {
-                    return findResourceImpl(jarURLs, name);
-                }
-            } else {
-                String clsName = name;
-                String partialName = clsName.replace('.', '/');
-                int position;
-                if ((position = partialName.lastIndexOf('/')) != -1) {
-                    String packageName = partialName.substring(0, position);
-                    jarURLs = index.get(packageName);
-                } else {
-                    String className = partialName.substring(0, partialName
-                            .length())
-                            + ".class"; //$NON-NLS-1$
-                    jarURLs = index.get(className);
-                }
-                if (jarURLs != null) {
-                    Class<?> c = findClassImpl(jarURLs, clsName);
-                    // InvalidJarException is thrown when a mapping for a class
-                    // is not valid, i.e. we can't find the class by following
-                    // the mapping.
-                    if (c == null) {
-                        throw new InvalidJarIndexException();
-                    }
-                    return c;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns an {@code Object[]} containing a Class, a URL, and a Vector of
-     * URLs, two of which are {@code null}, according to the caller, which is
-     * identified by the {@code int} type.
-     * 
-     * @return Object[] a 3-element array : {Class, URL, Vector}. The non-null
-     *         element contains the resource(s) found, which are searched in
-     *         newExtensions.
-     * @param newExtensions
-     *            URL[] the URLs to look in for.
-     * @param name
-     *            the resource to look for : either a resource or a class.
-     * @param i
-     *            the index of 'indexes' array to use.
-     * @param resources
-     *            indicates that a Vector of URL should be returned as the
-     *            non-null element in {@code Object[]}.
-     * @param url
-     *            if {@code true} a URL should be returned as the non-null
-     *            element, if {@code false} a class should be returned.
-     */
-    Object findInExtensions(URL[] newExtensions, String name, int i,
-            Vector<URL> resources, boolean url) {
-        if (newExtensions != null) {
-            for (int k = 0; k < newExtensions.length; k++) {
-                if (newExtensions[k] != null) {
-                    URL[] search = new URL[] { newExtensions[k] };
-                    if (resources != null) {
-                        URL res = findResourceImpl(search, name);
-                        if (!invalidUrls.contains(search[0])) { // the URL does
-                            // not exist
-                            if (res != null && !resources.contains(res)) {
-                                resources.addElement(res);
-                            }
-                            findInExtensions(explore(newExtensions[k], i),
-                                    name, i, resources, url);
-                        }
-                    } else {
-                        Object result;
-                        if (url) {
-                            result = findResourceImpl(search, name);
-                        } else {
-                            result = findClassImpl(search, name);
-                        }
-                        if (result != null) {
-                            return result;
-                        }
-                        if (!invalidUrls.contains(search[0])) { // the URL
-                            // exists
-                            result = findInExtensions(explore(newExtensions[k],
-                                    i), name, i, null, url);
-                            if (result != null) {
-                                return result;
-                            }
-                        }
-                    }
-                }
-            }
-        } else {
-            try {
-                return findInIndex(i, name, resources, url);
-            } catch (InvalidJarIndexException ex) {
-                // Ignore misleading/wrong jar index
-                return null;
-            }
-        }
-        return null;
-    }
 
     /**
      * Converts an input stream into a byte array.
-     * 
-     * @return byte[] the byte array
+     *
      * @param is
      *            the input stream
+     * @return byte[] the byte array
      */
-    private static byte[] getBytes(InputStream is, boolean readAvailable)
+    private static byte[] getBytes(InputStream is)
             throws IOException {
-        if (readAvailable) {
-            byte[] buf = new byte[is.available()];
-            is.read(buf, 0, buf.length);
-            is.close();
-            return buf;
-        }
         byte[] buf = new byte[4096];
-        int size = is.available();
-        if (size < 1024) {
-            size = 1024;
-        }
-        ByteArrayOutputStream bos = new ByteArrayOutputStream(size);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream(4096);
         int count;
         while ((count = is.read(buf)) > 0) {
             bos.write(buf, 0, count);
@@ -448,11 +730,10 @@
      * read permission to the file is added to the permission collection.
      * Otherwise, connecting to and accepting connections from the URL is
      * granted.
-     * 
+     *
      * @param codesource
      *            the code source object whose permissions have to be known.
      * @return the list of permissions according to the code source object.
-     * @since Android 1.0
      */
     @Override
     protected PermissionCollection getPermissions(final CodeSource codesource) {
@@ -494,12 +775,11 @@
 
     /**
      * Returns the search list of this {@code URLClassLoader}.
-     * 
+     *
      * @return the list of all known URLs of this instance.
-     * @since Android 1.0
      */
     public URL[] getURLs() {
-        return orgUrls.clone();
+        return originalUrls.toArray(new URL[originalUrls.size()]);
     }
 
     /**
@@ -515,12 +795,11 @@
      * system {@code ClassLoader} as its parent. The method {@code loadClass()}
      * of the new instance will call {@code
      * SecurityManager.checkPackageAccess()} before loading a class.
-     * 
+     *
      * @param urls
      *            the list of URLs that is passed to the new {@code
      *            URLClassloader}.
      * @return the created {@code URLClassLoader} instance.
-     * @since Android 1.0
      */
     public static URLClassLoader newInstance(final URL[] urls) {
         URLClassLoader sub = AccessController
@@ -538,17 +817,16 @@
      * specified {@code ClassLoader} as its parent. The method {@code
      * loadClass()} of the new instance will call the SecurityManager's {@code
      * checkPackageAccess()} before loading a class.
-     * 
+     *
      * @param urls
      *            the list of URLs that is passed to the new URLClassloader.
      * @param parentCl
      *            the parent class loader that is passed to the new
      *            URLClassloader.
      * @return the created {@code URLClassLoader} instance.
-     * @since Android 1.0
      */
     public static URLClassLoader newInstance(final URL[] urls,
-            final ClassLoader parentCl) {
+                                             final ClassLoader parentCl) {
         URLClassLoader sub = AccessController
                 .doPrivileged(new PrivilegedAction<URLClassLoader>() {
                     public URLClassLoader run() {
@@ -565,7 +843,7 @@
      * use the specified factory to create stream handlers. URLs that end with
      * "/" are assumed to be directories, otherwise they are assumed to be JAR
      * files.
-     * 
+     *
      * @param searchUrls
      *            the list of URLs where a specific class or file could be
      *            found.
@@ -578,10 +856,9 @@
      *             if a security manager exists and its {@code
      *             checkCreateClassLoader()} method doesn't allow creation of
      *             new {@code ClassLoader}s.
-     * @since Android 1.0
      */
     public URLClassLoader(URL[] searchUrls, ClassLoader parent,
-            URLStreamHandlerFactory factory) {
+                          URLStreamHandlerFactory factory) {
         super(parent);
         // Required for pre-v1.2 security managers to work
         SecurityManager security = System.getSecurityManager();
@@ -592,33 +869,28 @@
         // capture the context of the thread that creates this URLClassLoader
         currentContext = AccessController.getContext();
         int nbUrls = searchUrls.length;
-        urls = new URL[nbUrls];
-        orgUrls = new URL[nbUrls];
-        // Search each jar for CLASS-PATH attribute in manifest
-        extensions = new HashMap<URL, URL[]>(nbUrls * 2);
+        originalUrls = new ArrayList<URL>(nbUrls);
+        handlerList = new ArrayList<URLHandler>(nbUrls);
+        searchList = Collections.synchronizedList(new ArrayList<URL>(nbUrls));
         for (int i = 0; i < nbUrls; i++) {
+            originalUrls.add(searchUrls[i]);
             try {
-                urls[i] = createSearchURL(searchUrls[i]);
-                extensions.put(urls[i], null);
+                searchList.add(createSearchURL(searchUrls[i]));
             } catch (MalformedURLException e) {
             }
-            orgUrls[i] = searchUrls[i];
         }
-        // Search each jar for META-INF/INDEX.LIST
-        indexes = newHashtableArray(nbUrls);
     }
 
     /**
      * Tries to locate and load the specified class using the known URLs. If the
      * class could be found, a class object representing the loaded class will
      * be returned.
-     * 
-     * @return the class that has been loaded.
+     *
      * @param clsName
      *            the name of the class which has to be found.
+     * @return the class that has been loaded.
      * @throws ClassNotFoundException
      *             if the specified class cannot be loaded.
-     * @since Android 1.0
      */
     @Override
     protected Class<?> findClass(final String clsName)
@@ -626,7 +898,7 @@
         Class<?> cls = AccessController.doPrivileged(
                 new PrivilegedAction<Class<?>>() {
                     public Class<?> run() {
-                        return findClassImpl(urls, clsName);
+                        return findClassImpl(clsName);
                     }
                 }, currentContext);
         if (cls != null) {
@@ -639,7 +911,7 @@
      * Returns an URL that will be checked if it contains the class or resource.
      * If the file component of the URL is not a directory, a Jar URL will be
      * created.
-     * 
+     *
      * @return java.net.URL a test URL
      */
     private URL createSearchURL(URL url) throws MalformedURLException {
@@ -656,19 +928,19 @@
             return new URL("jar", "", //$NON-NLS-1$ //$NON-NLS-2$
                     -1, url.toString() + "!/"); //$NON-NLS-1$
         }
+        // use jar protocol as the stream handler protocol
         return new URL("jar", "", //$NON-NLS-1$ //$NON-NLS-2$
                 -1, url.toString() + "!/", //$NON-NLS-1$
-                factory.createURLStreamHandler(protocol));
+                factory.createURLStreamHandler("jar"));//$NON-NLS-1$
     }
 
     /**
      * Returns an URL referencing the specified resource or {@code null} if the
      * resource could not be found.
-     * 
+     *
      * @param name
      *            the name of the requested resource.
      * @return the URL which points to the given resource.
-     * @since Android 1.0
      */
     @Override
     public URL findResource(final String name) {
@@ -677,7 +949,7 @@
         }
         URL result = AccessController.doPrivileged(new PrivilegedAction<URL>() {
             public URL run() {
-                return findResourceImpl(urls, name);
+                return findResourceImpl(name);
             }
         }, currentContext);
         SecurityManager sm;
@@ -696,161 +968,108 @@
     /**
      * Returns a URL among the given ones referencing the specified resource or
      * null if no resource could be found.
-     * 
+     *
+     * @param resName java.lang.String the name of the requested resource
      * @return URL URL for the resource.
-     * @param searchList
-     *            java.net.URL[] the array to be searched
-     * @param resName
-     *            java.lang.String the name of the requested resource
      */
-    URL findResourceImpl(URL[] searchList, String resName) {
-        boolean findInExtensions = searchList == urls;
-        int i = 0;
-        while (i < searchList.length) {
-            if (searchList[i] == null) {
-                // KA024=One of urls is null
+    URL findResourceImpl(String resName) {
+        int n = 0;
+
+        while (true) {
+            URLHandler handler = getHandler(n++);
+            if (handler == null) {
+                break;
+            }
+            URL res = handler.findResource(resName);
+            if (res != null) {
+                return res;
+            }
+        }
+        return null;
+    }
+
+    URLHandler getHandler(int num) {
+        if (num < handlerList.size()) {
+            return handlerList.get(num);
+        }
+        makeNewHandler();
+        if (num < handlerList.size()) {
+            return handlerList.get(num);
+        }
+        return null;
+    }
+
+    private synchronized void makeNewHandler() {
+        while (!searchList.isEmpty()) {
+            URL nextCandidate = searchList.remove(0);
+            if (nextCandidate == null) {  // KA024=One of urls is null
                 throw new NullPointerException(Msg.getString("KA024")); //$NON-NLS-1$
-            } else if (!invalidUrls.contains(searchList[i])) {
-                JarFile jf = null;
-                try {
-                    URL currentUrl = searchList[i];
-                    String protocol = currentUrl.getProtocol();
-                    
-                    if (protocol.equals("jar")) { //$NON-NLS-1$
-                        jf = resCache.get(currentUrl);
-                        if (jf == null) {
-                            if (invalidUrls.contains(currentUrl)) {
-                                continue;
-                            }
-                            // each jf should be found only once 
-                            // so we do this job in the synchronized block
-                            synchronized (lock) {
-                                // Check the cache again in case another thread 
-                                // updated it while we're waiting on lock
-                                jf = resCache.get(currentUrl);
-                                if (jf == null) {
-                                    if (invalidUrls.contains(currentUrl)) {
-                                        continue;
-                                    }
-                                    /*
-                                     * If the connection for currentUrl or resURL is
-                                     * used, getJarFile() will throw an exception if the
-                                     * entry doesn't exist.
-                                     */
-                                    URL jarURL = ((JarURLConnection) currentUrl
-                                              .openConnection()).getJarFileURL();
-                                    try {
-                                        JarURLConnection juc = (JarURLConnection) new URL(
-                                                "jar", "", //$NON-NLS-1$ //$NON-NLS-2$
-                                                jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$
-                                        jf = juc.getJarFile();
-                                        resCache.put(currentUrl, jf);
-                                    } catch (IOException e) {
-                                        // Don't look for this jar file again
-                                        invalidUrls.add(searchList[i]);
-                                        throw e;
-                                    }
-                                }
-                            }
-                        }
-                        String entryName;
-                        if (currentUrl.getFile().endsWith("!/")) { //$NON-NLS-1$
-                            entryName = resName;
-                        } else {
-                            String file = currentUrl.getFile();
-                            int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$
-                            if (sepIdx == -1) {
-                                // Invalid URL, don't look here again
-                                invalidUrls.add(searchList[i]);
-                                continue;
-                            }
-                            sepIdx += 2;
-                            entryName = new StringBuffer(file.length() - sepIdx
-                                    + resName.length()).append(
-                                    file.substring(sepIdx)).append(resName)
-                                    .toString();
-                        }
-                        if (jf.getEntry(entryName) != null) {
-                            return targetURL(currentUrl, resName);
-                        }
-                    } else if (protocol.equals("file")) { //$NON-NLS-1$
-                        String baseFile = currentUrl.getFile();
-                        String host = currentUrl.getHost();
-                        int hostLength = 0;
-                        if (host != null) {
-                            hostLength = host.length();
-                        }
-                        StringBuffer buf = new StringBuffer(2 + hostLength
-                                + baseFile.length() + resName.length());
-                        if (hostLength > 0) {
-                            buf.append("//").append(host); //$NON-NLS-1$
-                        }
-                        // baseFile always ends with '/'
-                        buf.append(baseFile);
-                        String fixedResName = resName;
-                        // Do not create a UNC path, i.e. \\host
-                        while (fixedResName.startsWith("/") //$NON-NLS-1$
-                                || fixedResName.startsWith("\\")) { //$NON-NLS-1$
-                            fixedResName = fixedResName.substring(1);
-                        }
-                        buf.append(fixedResName);
-
-                        String filename = buf.toString();
-                        
-                        try {
-                            filename = URLDecoder.decode(filename, "UTF-8"); //$NON-NLS-1$
-                        } catch (IllegalArgumentException e) {
-                            return null;
-                        }
-
-                        if (new File(filename).exists()) {
-                            return targetURL(currentUrl, fixedResName);
-                        }
-                    } else {
-                        URL resURL = targetURL(currentUrl, resName);
-                        URLConnection uc = resURL.openConnection();
-                        try {
-                            uc.getInputStream().close();
-                        } catch (SecurityException e) {
-                            return null;
-                        }
-                        // HTTP can return a stream on a non-existent file
-                        // So check for the return code;
-                        if (!resURL.getProtocol().equals("http")) { //$NON-NLS-1$
-                            return resURL;
-                        }
-                        int code;
-                        if ((code = ((HttpURLConnection) uc).getResponseCode()) >= 200
-                                && code < 300) {
-                            return resURL;
-                        }
-                    }
-                } catch (MalformedURLException e) {
-                    // Keep iterating through the URL list
-                } catch (IOException e) {
-                } catch (SecurityException e) {
+            }
+            if (!handlerMap.containsKey(nextCandidate)) {
+                URLHandler result;
+                String protocol = nextCandidate.getProtocol();
+                if (protocol.equals("jar")) { //$NON-NLS-1$
+                    result = createURLJarHandler(nextCandidate);
+                } else if (protocol.equals("file")) { //$NON-NLS-1$
+                    result = createURLFileHandler(nextCandidate);
+                } else {
+                    result = createURLHandler(nextCandidate);
                 }
-                if ((jf != null) && findInExtensions) {
-                    if (indexes[i] != null) {
-                        try {
-                            URL result = (URL) findInIndex(i, resName, null,
-                                    true);
-                            if (result != null) {
-                                return result;
-                            }
-                        } catch (InvalidJarIndexException ex) {
-                            // Ignore invalid/misleading JAR index file
-                        }
-                    } else {
-                        URL result = (URL) findInExtensions(explore(
-                                searchList[i], i), resName, i, null, true);
-                        if (result != null) {
-                            return result;
-                        }
-                    }
+                if (result != null) {
+                    handlerMap.put(nextCandidate, result);
+                    handlerList.add(result);
+                    return;
                 }
             }
-            ++i;
+        }
+    }
+
+    private URLHandler createURLHandler(URL url) {
+        return new URLHandler(url);
+    }
+
+    private URLHandler createURLFileHandler(URL url) {
+        return new URLFileHandler(url);
+    }
+
+    private URLHandler createURLJarHandler(URL url) {
+        String prefixName;
+        String file = url.getFile();
+        if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
+            prefixName = "";
+        } else {
+            int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$
+            if (sepIdx == -1) {
+                // Invalid URL, don't look here again
+                return null;
+            }
+            sepIdx += 2;
+            prefixName = file.substring(sepIdx);
+        }
+        try {
+            URL jarURL = ((JarURLConnection) url
+                    .openConnection()).getJarFileURL();
+            JarURLConnection juc = (JarURLConnection) new URL(
+                    "jar", "", //$NON-NLS-1$ //$NON-NLS-2$
+                    jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$
+            JarFile jf = juc.getJarFile();
+            URLJarHandler jarH = new URLJarHandler(url, jarURL, jf, prefixName);
+
+            if (jarH.getIndex() == null) {
+                try {
+                    Manifest manifest = jf.getManifest();
+                    if (manifest != null) {
+                        String classpath = manifest.getMainAttributes().getValue(
+                                Attributes.Name.CLASS_PATH);
+                        if (classpath != null) {
+                            searchList.addAll(0, getInternalURLs(url, classpath));
+                        }
+                    }
+                } catch (IOException e) {
+                }
+            }
+            return jarH;
+        } catch (IOException e) {
         }
         return null;
     }
@@ -858,7 +1077,7 @@
     /**
      * Defines a new package using the information extracted from the specified
      * manifest.
-     * 
+     *
      * @param packageName
      *            the name of the new package.
      * @param manifest
@@ -869,10 +1088,9 @@
      * @return the created package.
      * @throws IllegalArgumentException
      *             if a package with the given name already exists.
-     * @since Android 1.0
      */
     protected Package definePackage(String packageName, Manifest manifest,
-            URL url) throws IllegalArgumentException {
+                                    URL url) throws IllegalArgumentException {
         Attributes mainAttributes = manifest.getMainAttributes();
         String dirName = packageName.replace('.', '/') + "/"; //$NON-NLS-1$
         Attributes packageAttributes = manifest.getAttributes(dirName);
@@ -921,7 +1139,7 @@
         return definePackage(packageName, specificationTitle,
                 specificationVersion, specificationVendor, implementationTitle,
                 implementationVersion, implementationVendor, isSealed(manifest,
-                        dirName) ? url : null);
+                dirName) ? url : null);
     }
 
     private boolean isSealed(Manifest manifest, String dirName) {
@@ -940,19 +1158,18 @@
 
     /**
      * returns URLs referenced in the string classpath.
-     * 
+     *
      * @param root
      *            the jar URL that classpath is related to
      * @param classpath
      *            the relative URLs separated by spaces
-     * 
      * @return URL[] the URLs contained in the string classpath.
      */
-    private URL[] getInternalURLs(URL root, String classpath) {
+    private ArrayList<URL> getInternalURLs(URL root, String classpath) {
         // Class-path attribute is composed of space-separated values.
         StringTokenizer tokenizer = new java.util.StringTokenizer(classpath);
-        Vector<URL> addedURLs = new Vector<URL>();
-        String file = root.getFile();        
+        ArrayList<URL> addedURLs = new ArrayList<URL>();
+        String file = root.getFile();
         int jarIndex = file.lastIndexOf("!/") - 1; //$NON-NLS-1$
         int index = file.lastIndexOf("/", jarIndex) + 1; //$NON-NLS-1$
         if (index == 0) {
@@ -969,381 +1186,40 @@
                 try {
                     URL newURL = new URL(protocol, host, port, file + element
                             + "!/"); //$NON-NLS-1$
-                    synchronized (extensions) {
-                        if (!extensions.containsKey(newURL)) {
-                            extensions.put(newURL, null);
-                            addedURLs.add(newURL);
-                        }
-                    }
+                    addedURLs.add(newURL);
                 } catch (MalformedURLException e) {
                     // Nothing is added
                 }
             }
         }
-        URL[] newURLs = addedURLs.toArray(new URL[] {});
-        return newURLs;
+        return addedURLs;
     }
 
-    /**
-     * @param in
-     *            InputStream the stream to read lines from
-     * @return List a list of String lines
-     */
-    private List<String> readLines(InputStream in) throws IOException {
-        byte[] buff = new byte[144];
-        List<String> lines = new ArrayList<String>();
-        int pos = 0;
-        int next;
-        while ((next = in.read()) != -1) {
-            if (next == '\n') {
-                lines.add(new String(buff, 0, pos, "UTF8")); //$NON-NLS-1$
-                pos = 0;
-                continue;
-            }
-            if (next == '\r') {
-                lines.add(new String(buff, 0, pos, "UTF8")); //$NON-NLS-1$
-                pos = 0;
-                if ((next = in.read()) == '\n') {
-                    continue;
-                }
-            }
-            if (pos == buff.length) {
-                byte[] newBuf = new byte[buff.length * 2];
-                System.arraycopy(buff, 0, newBuf, 0, buff.length);
-                buff = newBuf;
-            }
-            buff[pos++] = (byte) next;
+    Class<?> findClassImpl(String className) {
+        Class<?> loadedClass = findLoadedClass(className);
+        if (null != loadedClass) {
+            return loadedClass;
         }
-        if (pos > 0) {
-            lines.add(new String(buff, 0, pos, "UTF8")); //$NON-NLS-1$
+        String partialName = className.replace('.', '/');
+        final String classFileName = new StringBuilder(partialName).append(".class").toString(); //$NON-NLS-1$
+        String packageName = null;
+        int position = partialName.lastIndexOf('/');
+        if ((position = partialName.lastIndexOf('/')) != -1) {
+            packageName = partialName.substring(0, position);
         }
-        return lines;
-    }
-
-    private URL targetURL(URL base, String name) throws MalformedURLException {
-        try {
-            String file = base.getFile() + URIEncoderDecoder.quoteIllegal(name,
-                    "/@" + URI.someLegal);
-
-            return new URL(base.getProtocol(), base.getHost(), base.getPort(),
-                    file, null);
-        } catch (UnsupportedEncodingException e) {
-            MalformedURLException e2 = new MalformedURLException(e.toString());
-            
-            e2.initCause(e);
-            throw e2;
-        }
-        
-    }
-
-    /**
-     * @param searchURLs
-     *            java.net.URL[] the URLs to search in
-     * @param clsName
-     *            java.lang.String the class name to be found
-     * @return Class the class found or null if not found
-     */
-    Class<?> findClassImpl(URL[] searchURLs, String clsName) {
-        boolean readAvailable = false;
-        boolean findInExtensions = searchURLs == urls;
-        final String name = new StringBuffer(clsName.replace('.', '/')).append(
-                ".class").toString(); //$NON-NLS-1$
-        for (int i = 0; i < searchURLs.length; i++) {
-            if (searchURLs[i] == null) {
-                // KA024=One of urls is null
-                throw new NullPointerException(Msg.getString("KA024")); //$NON-NLS-1$
-            } else if (!invalidUrls.contains(searchURLs[i])) {
-                Manifest manifest = null;
-                InputStream is = null;
-                JarEntry entry = null;
-                JarFile jf = null;
-                byte[] clBuf = null;
-                try {
-                    URL thisURL = searchURLs[i];
-                    String protocol = thisURL.getProtocol();
-                    if (protocol.equals("jar")) { //$NON-NLS-1$
-                        jf = resCache.get(thisURL);
-                        if ((jf == null) && (!invalidUrls.contains(thisURL))) {
-                            synchronized (lock) {
-                                // Check the cache again in case another thread updated it 
-                                // updated it while we're waiting on lock
-                                jf = resCache.get(thisURL);
-                                if (jf == null) {
-                                    if (invalidUrls.contains(thisURL)) {
-                                        continue;
-                                    }
-                                    // If the connection for testURL or thisURL is used,
-                                    // getJarFile() will throw an exception if the entry
-                                    // doesn't exist.
-                                    URL jarURL = ((JarURLConnection) thisURL
-                                              .openConnection()).getJarFileURL();
-                                    try {
-                                        JarURLConnection juc = (JarURLConnection) new URL(
-                                                "jar", "", jarURL.toExternalForm() + "!/") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-                                                .openConnection();
-                                        jf = juc.getJarFile();
-                                        resCache.put(thisURL, jf);
-                                    } catch (IOException e) {
-                                        // Don't look for this jar file again
-                                        invalidUrls.add(searchURLs[i]);
-                                        throw e;
-                                    }
-                                }
-                            }
-                        }
-                        if (thisURL.getFile().endsWith("!/")) { //$NON-NLS-1$
-                            entry = jf.getJarEntry(name);
-                        } else {
-                            String file = thisURL.getFile();
-                            int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$
-                            if (sepIdx == -1) {
-                                // Invalid URL, don't look here again
-                                invalidUrls.add(searchURLs[i]);
-                                continue;
-                            }
-                            sepIdx += 2;
-                            String entryName = new StringBuffer(file.length()
-                                    - sepIdx + name.length()).append(
-                                    file.substring(sepIdx)).append(name)
-                                    .toString();
-                            entry = jf.getJarEntry(entryName);
-                        }
-                        if (entry != null) {
-                            readAvailable = true;
-                            is = jf.getInputStream(entry);
-                            /**
-                             * Avoid recursive load class, especially the class
-                             * is an implementation class of security provider
-                             * and the jar is signed.
-                             */
-                            Class loadedClass = findLoadedClass(clsName);
-                            if (null != loadedClass) {
-                                is.close();
-                                return loadedClass;
-                            }
-                            manifest = jf.getManifest();
-                        }
-                    } else if (protocol.equals("file")) { //$NON-NLS-1$
-                        String filename = thisURL.getFile();
-                        String host = thisURL.getHost();
-                        if (host != null && host.length() > 0) {
-                            filename = new StringBuffer(host.length()
-                                    + filename.length() + name.length() + 2)
-                                    .append("//").append(host).append(filename) //$NON-NLS-1$
-                                    .append(name).toString();
-                        } else {
-                            filename = new StringBuffer(filename.length()
-                                    + name.length()).append(filename).append(
-                                    name).toString();
-                        }
-
-                        // Just return null for caller to throw
-                        // ClassNotFoundException.
-                        try {
-                            filename = URLDecoder.decode(filename, "UTF-8"); //$NON-NLS-1$
-                        } catch (IllegalArgumentException e) {
-                            return null;
-                        }
-
-                        File file = new File(filename);
-                        // Don't throw exceptions for speed
-                        if (file.exists()) {
-                            is = new FileInputStream(file);
-                            readAvailable = true;
-                        } else {
-                            continue;
-                        }
-                    } else {
-                        is = targetURL(thisURL, name).openStream();
-                    }
-                } catch (MalformedURLException e) {
-                    // Keep iterating through the URL list
-                } catch (IOException e) {
-                }
-                if (is != null) {
-                    URL codeSourceURL = null;
-                    Certificate[] certificates = null;
-                    CodeSource codeS = null;
-                    try {
-                        codeSourceURL = findInExtensions ? orgUrls[i]
-                                : ((JarURLConnection) searchURLs[i]
-                                        .openConnection()).getJarFileURL();
-                    } catch (IOException e) {
-                        codeSourceURL = searchURLs[i];
-                    }
-                    if (is != null) {
-                        try {
-                            clBuf = getBytes(is, readAvailable);
-                            is.close();
-                        } catch (IOException e) {
-                            return null;
-                        }
-                    }
-                    if (entry != null) {
-                        certificates = entry.getCertificates();
-                    }
-                    // Use the original URL, not the possible jar URL
-                    codeS = new CodeSource(codeSourceURL, certificates);
-                    int dotIndex = clsName.lastIndexOf("."); //$NON-NLS-1$
-                    if (dotIndex != -1) {
-                        String packageName = clsName.substring(0, dotIndex);
-                        synchronized (this) {
-                            Package packageObj = getPackage(packageName);
-                            if (packageObj == null) {
-                                if (manifest != null) {
-                                    definePackage(packageName, manifest,
-                                            codeSourceURL);
-                                } else {
-                                    definePackage(packageName, null, null,
-                                            null, null, null, null, null);
-                                }
-                            } else {
-                                boolean exception = false;
-                                if (manifest != null) {
-                                    String dirName = packageName.replace('.',
-                                            '/')
-                                            + "/"; //$NON-NLS-1$
-                                    if (isSealed(manifest, dirName)) {
-                                        exception = !packageObj
-                                                .isSealed(codeSourceURL);
-                                    }
-                                } else {
-                                    exception = packageObj.isSealed();
-                                }
-                                if (exception) {
-                                    throw new SecurityException(Msg
-                                            .getString("K004c")); //$NON-NLS-1$
-                                }
-                            }
-                        }
-                    }
-                    return defineClass(clsName, clBuf, 0, clBuf.length, codeS);
-                }
-                if ((jf != null) && findInExtensions) {
-                    if (indexes[i] != null) {
-                        try {
-                            Class<?> c = (Class<?>) findInIndex(i, clsName,
-                                    null, false);
-                            if (c != null) {
-                                return c;
-                            }
-                        } catch (InvalidJarIndexException ex) {
-                            // Ignore misleading/wrong jar index
-                        }
-                    } else {
-                        Class<?> c = (Class<?>) findInExtensions(explore(
-                                searchURLs[i], i), clsName, i, null, false);
-                        if (c != null) {
-                            return c;
-                        }
-                    }
-                }
+        int n = 0;
+        while (true) {
+            URLHandler handler = getHandler(n++);
+            if (handler == null) {
+                break;
+            }
+            Class<?> res = handler.findClass(packageName, classFileName, className);
+            if (res != null) {
+                return res;
             }
         }
         return null;
+
     }
 
-    /**
-     * @param url
-     *            URL the URL to explore
-     * @param indexNumber
-     *            int the index in extensions to consider
-     * 
-     * @return URL[] the URLs of bundled extensions that have been found (i.e.
-     *         the URL of jar files in the class-path attribute), or null if
-     *         none. if an INDEX.LIST has been found, an empty array is returned
-     */
-    URL[] explore(URL url, int indexNumber) {
-        URL[] internal;
-        synchronized (extensions) {
-            internal = extensions.get(url);
-        }
-        if (internal != null) {
-            return internal;
-        }
-        if (indexes[indexNumber] != null) {
-            return null;
-        }
-
-        if (!url.getProtocol().equals("jar")) { //$NON-NLS-1$
-            return null;
-        }
-
-        JarFile jf = resCache.get(url);
-        // Add mappings from INDEX.LIST
-        ZipEntry ze = jf.getEntry("META-INF/INDEX.LIST"); //$NON-NLS-1$
-        if (ze != null) {
-            if (url.equals(urls[indexNumber])) {
-                try {
-                    Hashtable<String, URL[]> index = new Hashtable<String, URL[]>(
-                            15);
-                    InputStream indexIS = jf.getInputStream(ze);
-                    List<String> lines = readLines(indexIS);
-                    indexIS.close();
-                    ListIterator<String> iterator = lines.listIterator();
-                    // Ignore the 2 first lines (index version)
-                    iterator.next();
-                    iterator.next();
-                    // Add mappings from resource to jar file
-                    URL fileURL = ((JarURLConnection) url.openConnection())
-                            .getJarFileURL();
-                    String file = fileURL.getFile();
-                    String parentFile = new File(file).getParent();
-                    parentFile = parentFile.replace(File.separatorChar, '/');
-                    if (parentFile.charAt(0) != '/') {
-                        parentFile = "/" + parentFile; //$NON-NLS-1$
-                    }
-                    URL parentURL = new URL(fileURL.getProtocol(), fileURL
-                            .getHost(), fileURL.getPort(), parentFile);
-                    while (iterator.hasNext()) {
-                        URL jar = new URL("jar:" //$NON-NLS-1$
-                                + parentURL.toExternalForm() + "/" //$NON-NLS-1$
-                                + iterator.next() + "!/"); //$NON-NLS-1$
-                        String resource = null;
-                        while (iterator.hasNext()
-                                && !(resource = iterator.next()).equals("")) { //$NON-NLS-1$
-                            if (index.containsKey(resource)) {
-                                URL[] jars = index.get(resource);
-                                URL[] newJars = new URL[jars.length + 1];
-                                System.arraycopy(jars, 0, newJars, 0,
-                                        jars.length);
-                                newJars[jars.length] = jar;
-                                index.put(resource, newJars);
-                            } else {
-                                URL[] jars = { jar };
-                                index.put(resource, jars);
-                            }
-                        }
-                    }
-                    indexes[indexNumber] = index;
-                } catch (MalformedURLException e) {
-                    // Ignore this jar's index
-                } catch (IOException e) {
-                    // Ignore this jar's index
-                }
-            }
-            return null;
-        }
-
-        // Returns URLs referenced by the class-path attribute.
-        Manifest manifest = null;
-        try {
-            manifest = jf.getManifest();
-        } catch (IOException e) {
-        }
-        String classpath = null;
-        if (manifest != null) {
-            classpath = manifest.getMainAttributes().getValue(
-                    Attributes.Name.CLASS_PATH);
-        }
-        synchronized (extensions) {
-            internal = extensions.get(url);
-            if (internal == null) {
-                internal = classpath != null ? getInternalURLs(url, classpath)
-                        : NO_PATH;
-                extensions.put(url, internal);
-            }
-        }
-        return internal;
-    }
 }
diff --git a/luni/src/main/java/java/net/URLConnection.java b/luni/src/main/java/java/net/URLConnection.java
index 6c1a192..b87b11a 100644
--- a/luni/src/main/java/java/net/URLConnection.java
+++ b/luni/src/main/java/java/net/URLConnection.java
@@ -23,6 +23,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Collections;
+import java.util.Date;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
@@ -31,22 +32,17 @@
 import org.apache.harmony.luni.internal.net.www.MimeTable;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
-import org.apache.harmony.luni.util.Util;
 
 /**
  * Concrete implementations of the abstract {@code URLConnection} class provide
  * a communication link to a URL for exchanging data with a specific protocol
  * type. A {@code URLConnection} can only be set up after the instantiation but
  * before connecting to the remote resource.
- * 
- * @since Android 1.0
  */
 public abstract class URLConnection {
 
     /**
      * The URL which represents the remote target of this {@code URLConnection}.
-     * 
-     * @since Android 1.0
      */
     protected URL url;
 
@@ -63,16 +59,12 @@
     /**
      * The data must be modified more recently than this time in milliseconds
      * since January 1, 1970, GMT to be transmitted.
-     * 
-     * @since Android 1.0
      */
     protected long ifModifiedSince;
 
     /**
      * Specifies whether the using of caches is enabled or the data has to be
      * recent for every request.
-     * 
-     * @since Android 1.0
      */
     protected boolean useCaches = defaultUseCaches;
 
@@ -80,30 +72,22 @@
      * Specifies whether this {@code URLConnection} is already connected to the
      * remote resource. If this field is set to {@code true} the flags for
      * setting up the connection are not changeable anymore.
-     * 
-     * @since Android 1.0
      */
     protected boolean connected;
 
     /**
      * Specifies whether this {@code URLConnection} allows sending data.
-     * 
-     * @since Android 1.0
      */
     protected boolean doOutput;
 
     /**
      * Specifies whether this {@code URLConnection} allows receiving data.
-     * 
-     * @since Android 1.0
      */
     protected boolean doInput = true;
 
     /**
      * Specifies whether this {@code URLConnection} allows user interaction as
      * it is needed for authentication purposes.
-     * 
-     * @since Android 1.0
      */
     protected boolean allowUserInteraction = defaultAllowUserInteraction;
 
@@ -127,11 +111,10 @@
     /**
      * Creates a new {@code URLConnection} instance pointing to the resource
      * specified by the given URL.
-     * 
+     *
      * @param url
      *            the URL which represents the resource this {@code
      *            URLConnection} will point to.
-     * @since Android 1.0
      */
     protected URLConnection(URL url) {
         this.url = url;
@@ -140,20 +123,18 @@
     /**
      * Establishes the connection to the earlier configured resource. The
      * connection can only be set up before this method has been called.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while connecting to the resource.
-     * @since Android 1.0
      */
     public abstract void connect() throws IOException;
 
     /**
      * Gets the option value which indicates whether user interaction is allowed
      * on this {@code URLConnection}.
-     * 
+     *
      * @return the value of the option {@code allowUserInteraction}.
      * @see #allowUserInteraction
-     * @since Android 1.0
      */
     public boolean getAllowUserInteraction() {
         return allowUserInteraction;
@@ -166,11 +147,10 @@
      * header field "Content-Type". If none is found it will guess the content
      * type from the filename extension. If that fails the stream itself will be
      * used to guess the content type.
-     * 
+     *
      * @return the content representing object.
      * @throws IOException
      *             if an error occurs obtaining the content.
-     * @since Android 1.0
      */
     public Object getContent() throws java.io.IOException {
         if (!connected) {
@@ -196,14 +176,13 @@
      * type from the filename extension. If that fails the stream itself will be
      * used to guess the content type. The content type must match with one of
      * the list {@code types}.
-     * 
+     *
      * @param types
      *            the list of acceptable content types.
      * @return the content representing object or {@code null} if the content
      *         type does not match with one of the specified types.
      * @throws IOException
      *             if an error occurs obtaining the content.
-     * @since Android 1.0
      */
     // Param is not generic in spec
     @SuppressWarnings("unchecked")
@@ -226,9 +205,8 @@
     /**
      * Gets the content encoding type specified by the response header field
      * {@code content-encoding} or {@code null} if this field is not set.
-     * 
+     *
      * @return the value of the response header field {@code content-encoding}.
-     * @since Android 1.0
      */
     public String getContentEncoding() {
         return getHeaderField("Content-Encoding"); //$NON-NLS-1$
@@ -237,7 +215,7 @@
     /**
      * Returns the specific ContentHandler that will handle the type {@code
      * contentType}.
-     * 
+     *
      * @param type
      *            The type that needs to be handled
      * @return An instance of the Content Handler
@@ -286,7 +264,8 @@
                     .doPrivileged(new PrivilegedAction<Object>() {
                         public Object run() {
                             try {
-                                String className = "org.apache.harmony.luni.internal.net.www.content." //$NON-NLS-1$
+                                // Try looking up AWT image content handlers
+                                String className = "org.apache.harmony.awt.www.content." //$NON-NLS-1$
                                         + typeString;
                                 return Class.forName(className).newInstance();
                             } catch (ClassNotFoundException e) {
@@ -312,9 +291,8 @@
     /**
      * Gets the content length in bytes specified by the response header field
      * {@code content-length} or {@code -1} if this field is not set.
-     * 
+     *
      * @return the value of the response header field {@code content-length}.
-     * @since Android 1.0
      */
     public int getContentLength() {
         return getHeaderFieldInt("Content-Length", -1); //$NON-NLS-1$
@@ -323,9 +301,8 @@
     /**
      * Gets the MIME-type of the content specified by the response header field
      * {@code content-type} or {@code null} if type is unknown.
-     * 
+     *
      * @return the value of the response header field {@code content-type}.
-     * @since Android 1.0
      */
     public String getContentType() {
         return getHeaderField("Content-Type"); //$NON-NLS-1$
@@ -335,9 +312,8 @@
      * Gets the timestamp when this response has been sent as a date in
      * milliseconds since January 1, 1970 GMT or {@code 0} if this timestamp is
      * unknown.
-     * 
+     *
      * @return the sending timestamp of the current response.
-     * @since Android 1.0
      */
     public long getDate() {
         return getHeaderFieldDate("Date", 0); //$NON-NLS-1$
@@ -345,11 +321,10 @@
 
     /**
      * Gets the default setting whether this connection allows user interaction.
-     * 
+     *
      * @return the value of the default setting {@code
      *         defaultAllowUserInteraction}.
      * @see #allowUserInteraction
-     * @since Android 1.0
      */
     public static boolean getDefaultAllowUserInteraction() {
         return defaultAllowUserInteraction;
@@ -359,12 +334,11 @@
      * Gets the default value for the specified request {@code field} or {@code
      * null} if the field could not be found. The current implementation of this
      * method returns always {@code null}.
-     * 
+     *
      * @param field
      *            the request field whose default value shall be returned.
      * @return the default value for the given field.
      * @deprecated Use {@link #getRequestProperty}
-     * @since Android 1.0
      */
     @Deprecated
     public static String getDefaultRequestProperty(String field) {
@@ -373,10 +347,9 @@
 
     /**
      * Gets the default setting whether this connection allows using caches.
-     * 
+     *
      * @return the value of the default setting {@code defaultUseCaches}.
      * @see #useCaches
-     * @since Android 1.0
      */
     public boolean getDefaultUseCaches() {
         return defaultUseCaches;
@@ -385,11 +358,10 @@
     /**
      * Gets the value of the option {@code doInput} which specifies whether this
      * connection allows to receive data.
-     * 
+     *
      * @return {@code true} if this connection allows input, {@code false}
      *         otherwise.
      * @see #doInput
-     * @since Android 1.0
      */
     public boolean getDoInput() {
         return doInput;
@@ -398,11 +370,10 @@
     /**
      * Gets the value of the option {@code doOutput} which specifies whether
      * this connection allows to send data.
-     * 
+     *
      * @return {@code true} if this connection allows output, {@code false}
      *         otherwise.
      * @see #doOutput
-     * @since Android 1.0
      */
     public boolean getDoOutput() {
         return doOutput;
@@ -411,9 +382,8 @@
     /**
      * Gets the timestamp when this response will be expired in milliseconds
      * since January 1, 1970 GMT or {@code 0} if this timestamp is unknown.
-     * 
+     *
      * @return the value of the response header field {@code expires}.
-     * @since Android 1.0
      */
     public long getExpiration() {
         return getHeaderFieldDate("Expires", 0); //$NON-NLS-1$
@@ -422,9 +392,8 @@
     /**
      * Gets the table which is used by all {@code URLConnection} instances to
      * determine the MIME-type according to a file extension.
-     * 
+     *
      * @return the file name map to determine the MIME-type.
-     * @since Android 1.0
      */
     public static FileNameMap getFileNameMap() {
         // Must use lazy initialization or there is a bootstrap problem
@@ -440,11 +409,10 @@
      * Gets the header value at the field position {@code pos} or {@code null}
      * if the header has fewer than {@code pos} fields. The current
      * implementation of this method returns always {@code null}.
-     * 
+     *
      * @param pos
      *            the field position of the response header.
      * @return the value of the field at position {@code pos}.
-     * @since Android 1.0
      */
     public String getHeaderField(int pos) {
         return null;
@@ -454,9 +422,9 @@
      * Gets an unchangeable map of the response-header fields and values. The
      * response-header field names are the key values of the map. The map values
      * are lists of header field values associated with a particular key name.
-     * 
+     *
      * @return the response-header representing generic map.
-     * @since Android 1.0
+     * @since 1.4
      */
     public Map<String, List<String>> getHeaderFields() {
         return Collections.emptyMap();
@@ -466,9 +434,9 @@
      * Gets an unchangeable map of general request properties used by this
      * connection. The request property names are the key values of the map. The
      * map values are lists of property values of the corresponding key name.
-     * 
+     *
      * @return the request-property representing generic map.
-     * @since Android 1.0
+     * @since 1.4
      */
     public Map<String, List<String>> getRequestProperties() {
         if (connected) {
@@ -480,7 +448,7 @@
     /**
      * Adds the given property to the request header. Existing properties with
      * the same name will not be overwritten by this method.
-     * 
+     *
      * @param field
      *            the request property field name to add.
      * @param newValue
@@ -489,7 +457,7 @@
      *             if the connection has been already established.
      * @throws NullPointerException
      *             if the property name is {@code null}.
-     * @since Android 1.0
+     * @since 1.4
      */
     public void addRequestProperty(String field, String newValue) {
         if (connected) {
@@ -504,11 +472,10 @@
      * Gets the value of the header field specified by {@code key} or {@code
      * null} if there is no field with this name. The current implementation of
      * this method returns always {@code null}.
-     * 
+     *
      * @param key
      *            the name of the header field.
      * @return the value of the header field.
-     * @since Android 1.0
      */
     public String getHeaderField(String key) {
         return null;
@@ -518,34 +485,37 @@
      * Gets the specified header value as a date in milliseconds since January
      * 1, 1970 GMT. Returns the {@code defaultValue} if no such header field
      * could be found.
-     * 
+     *
      * @param field
      *            the header field name whose value is needed.
      * @param defaultValue
      *            the default value if no field has been found.
      * @return the value of the specified header field as a date in
      *         milliseconds.
-     * @since Android 1.0
      */
+    @SuppressWarnings("deprecation")
     public long getHeaderFieldDate(String field, long defaultValue) {
         String date = getHeaderField(field);
         if (date == null) {
             return defaultValue;
         }
-        return Util.parseDate(date);
+        try {
+            return Date.parse(date);
+        } catch (Exception e) {
+            return defaultValue;
+        }
     }
 
     /**
      * Gets the specified header value as a number. Returns the {@code
      * defaultValue} if no such header field could be found or the value could
      * not be parsed as an {@code Integer}.
-     * 
+     *
      * @param field
      *            the header field name whose value is needed.
      * @param defaultValue
      *            the default value if no field has been found.
      * @return the value of the specified header field as a number.
-     * @since Android 1.0
      */
     public int getHeaderFieldInt(String field, int defaultValue) {
         try {
@@ -559,11 +529,10 @@
      * Gets the name of the header field at the given position {@code posn} or
      * {@code null} if there are fewer than {@code posn} fields. The current
      * implementation of this method returns always {@code null}.
-     * 
+     *
      * @param posn
      *            the position of the header field which has to be returned.
      * @return the header field name at the given position.
-     * @since Android 1.0
      */
     public String getHeaderFieldKey(int posn) {
         return null;
@@ -573,10 +542,9 @@
      * Gets the point of time since when the data must be modified to be
      * transmitted. Some protocols transmit data only if it has been modified
      * more recently than a particular time.
-     * 
+     *
      * @return the time in milliseconds since January 1, 1970 GMT.
      * @see #ifModifiedSince
-     * @since Android 1.0
      */
     public long getIfModifiedSince() {
         return ifModifiedSince;
@@ -586,11 +554,10 @@
      * Gets an {@code InputStream} for reading data from the resource pointed by
      * this {@code URLConnection}. It throws an UnknownServiceException by
      * default. This method must be overridden by its subclasses.
-     * 
+     *
      * @return the InputStream to read data from.
      * @throws IOException
      *             if no InputStream could be created.
-     * @since Android 1.0
      */
     public InputStream getInputStream() throws IOException {
         throw new UnknownServiceException(Msg.getString("K004d")); //$NON-NLS-1$
@@ -599,9 +566,8 @@
     /**
      * Gets the value of the response header field {@code last-modified} or
      * {@code 0} if this value is not set.
-     * 
+     *
      * @return the value of the {@code last-modified} header field.
-     * @since Android 1.0
      */
     public long getLastModified() {
         if (lastModified != -1) {
@@ -614,11 +580,10 @@
      * Gets an {@code OutputStream} for writing data to this {@code
      * URLConnection}. It throws an {@code UnknownServiceException} by default.
      * This method must be overridden by its subclasses.
-     * 
+     *
      * @return the OutputStream to write data.
      * @throws IOException
      *             if no OutputStream could be created.
-     * @since Android 1.0
      */
     public OutputStream getOutputStream() throws IOException {
         throw new UnknownServiceException(Msg.getString("K005f")); //$NON-NLS-1$
@@ -631,12 +596,11 @@
      * necessary. By default, this method returns {@code AllPermission}.
      * Subclasses should overwrite this method to return an appropriate
      * permission object.
-     * 
+     *
      * @return the permission object representing the needed permissions to open
      *         this connection.
      * @throws IOException
      *             if an I/O error occurs while creating the permission object.
-     * @since Android 1.0
      */
     public java.security.Permission getPermission() throws IOException {
         return new java.security.AllPermission();
@@ -646,13 +610,12 @@
      * Gets the value of the request header property specified by {code field}
      * or {@code null} if there is no field with this name. The current
      * implementation of this method returns always {@code null}.
-     * 
+     *
      * @param field
      *            the name of the request header property.
      * @return the value of the property.
      * @throws IllegalStateException
      *             if the connection has been already established.
-     * @since Android 1.0
      */
     public String getRequestProperty(String field) {
         if (connected) {
@@ -663,9 +626,8 @@
 
     /**
      * Gets the URL represented by this {@code URLConnection}.
-     * 
+     *
      * @return the URL of this connection.
-     * @since Android 1.0
      */
     public URL getURL() {
         return url;
@@ -674,9 +636,8 @@
     /**
      * Gets the value of the flag which specifies whether this {@code
      * URLConnection} allows to use caches.
-     * 
+     *
      * @return {@code true} if using caches is allowed, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean getUseCaches() {
         return useCaches;
@@ -686,12 +647,11 @@
      * Determines the MIME-type of the given resource {@code url} by resolving
      * the filename extension with the internal FileNameMap. Any fragment
      * identifier is removed before processing.
-     * 
+     *
      * @param url
      *            the URL with the filename to get the MIME type.
      * @return the guessed content type or {@code null} if the type could not be
      *         determined.
-     * @since Android 1.0
      */
     public static String guessContentTypeFromName(String url) {
         return getFileNameMap().getContentTypeFor(url);
@@ -700,7 +660,7 @@
     /**
      * Determines the MIME-type of the resource represented by the input stream
      * {@code is} by reading its first few characters.
-     * 
+     *
      * @param is
      *            the resource representing input stream to determine the
      *            content type.
@@ -708,35 +668,91 @@
      *         determined.
      * @throws IOException
      *             if an I/O error occurs while reading from the input stream.
-     * @since Android 1.0
      */
+    @SuppressWarnings("nls")
     public static String guessContentTypeFromStream(InputStream is)
             throws IOException {
+
         if (!is.markSupported()) {
             return null;
         }
-        is.mark(4);
-        char[] chars = new char[4];
-        for (int i = 0; i < chars.length; i++) {
-            chars[i] = (char) is.read();
-        }
+        // Look ahead up to 64 bytes for the longest encoded header
+        is.mark(64);
+        byte[] bytes = new byte[64];
+        int length = is.read(bytes);
         is.reset();
-        if ((chars[0] == 'P') && (chars[1] == 'K')) {
-            return "application/zip"; //$NON-NLS-1$
+
+        // Check for Unicode BOM encoding indicators
+        String encoding = "ASCII";
+        int start = 0;
+        if (length > 1) {
+            if ((bytes[0] == (byte) 0xFF) && (bytes[1] == (byte) 0xFE)) {
+                encoding = "UTF-16LE";
+                start = 2;
+                length -= length & 1;
+            }
+            if ((bytes[0] == (byte) 0xFE) && (bytes[1] == (byte) 0xFF)) {
+                encoding = "UTF-16BE";
+                start = 2;
+                length -= length & 1;
+            }
+            if (length > 2) {
+                if ((bytes[0] == (byte) 0xEF) && (bytes[1] == (byte) 0xBB)
+                        && (bytes[2] == (byte) 0xBF)) {
+                    encoding = "UTF-8";
+                    start = 3;
+                }
+                if (length > 3) {
+                    if ((bytes[0] == (byte) 0x00) && (bytes[1] == (byte) 0x00)
+                            && (bytes[2] == (byte) 0xFE)
+                            && (bytes[3] == (byte) 0xFF)) {
+                        encoding = "UTF-32BE";
+                        start = 4;
+                        length -= length & 3;
+                    }
+                    if ((bytes[0] == (byte) 0xFF) && (bytes[1] == (byte) 0xFE)
+                            && (bytes[2] == (byte) 0x00)
+                            && (bytes[3] == (byte) 0x00)) {
+                        encoding = "UTF-32LE";
+                        start = 4;
+                        length -= length & 3;
+                    }
+                }
+            }
         }
-        if ((chars[0] == 'G') && (chars[1] == 'I')) {
-            return "image/gif"; //$NON-NLS-1$
+
+        String header = new String(bytes, start, length - start, encoding);
+
+        // Check binary types
+        if (header.startsWith("PK")) {
+            return "application/zip";
         }
-        if (new String(chars).trim().startsWith("<")) { //$NON-NLS-1$
-            return "text/html"; //$NON-NLS-1$
+        if (header.startsWith("GI")) {
+            return "image/gif";
         }
+
+        // Check text types
+        String textHeader = header.trim().toUpperCase();
+        if (textHeader.startsWith("<!DOCTYPE HTML") ||
+                textHeader.startsWith("<HTML") ||
+                textHeader.startsWith("<HEAD") ||
+                textHeader.startsWith("<BODY") ||
+                textHeader.startsWith("<HEAD")) {
+            return "text/html";
+        }
+
+        if (textHeader.startsWith("<?XML")) {
+            return "application/xml";
+        }
+
+        // Give up
         return null;
     }
 
     /**
      * Performs any necessary string parsing on the input string such as
      * converting non-alphanumeric character into underscore.
-     * 
+     *
      * @param typeString
      *            the parsed string
      * @return the string to be parsed
@@ -757,14 +773,13 @@
      * Sets the flag indicating whether this connection allows user interaction
      * or not. This method can only be called prior to the connection
      * establishment.
-     * 
+     *
      * @param newValue
      *            the value of the flag to be set.
      * @throws IllegalStateException
      *             if this method attempts to change the flag after the
      *             connection has been established.
      * @see #allowUserInteraction
-     * @since Android 1.0
      */
     public void setAllowUserInteraction(boolean newValue) {
         if (connected) {
@@ -777,13 +792,12 @@
      * Sets the internally used content handler factory. The content factory can
      * only be set if it is allowed by the security manager and only once during
      * the lifetime of the application.
-     * 
+     *
      * @param contentFactory
      *            the content factory to be set.
      * @throws Error
      *             if the security manager does not allow to set the content
      *             factory or it has been already set earlier ago.
-     * @since Android 1.0
      */
     public static synchronized void setContentHandlerFactory(
             ContentHandlerFactory contentFactory) {
@@ -801,12 +815,11 @@
      * Sets the default value for the flag indicating whether this connection
      * allows user interaction or not. Existing {@code URLConnection}s are
      * unaffected.
-     * 
+     *
      * @param allows
      *            the default value of the flag to be used for new connections.
      * @see #defaultAllowUserInteraction
      * @see #allowUserInteraction
-     * @since Android 1.0
      */
     public static void setDefaultAllowUserInteraction(boolean allows) {
         defaultAllowUserInteraction = allows;
@@ -816,14 +829,13 @@
      * Sets the default value of the specified request header field. This value
      * will be used for the specific field of every newly created connection.
      * The current implementation of this method does nothing.
-     * 
+     *
      * @param field
      *            the request header field to be set.
      * @param value
      *            the default value to be used.
      * @deprecated Use {@link #setRequestProperty} of an existing {@code
      *             URLConnection} instance.
-     * @since Android 1.0
      */
     @Deprecated
     public static void setDefaultRequestProperty(String field, String value) {
@@ -832,12 +844,11 @@
     /**
      * Sets the default value for the flag indicating whether this connection
      * allows to use caches. Existing {@code URLConnection}s are unaffected.
-     * 
+     *
      * @param newValue
      *            the default value of the flag to be used for new connections.
      * @see #defaultUseCaches
      * @see #useCaches
-     * @since Android 1.0
      */
     public void setDefaultUseCaches(boolean newValue) {
         // BEGIN android-removed
@@ -852,14 +863,13 @@
     /**
      * Sets the flag indicating whether this {@code URLConnection} allows input.
      * It cannot be set after the connection is established.
-     * 
+     *
      * @param newValue
      *            the new value for the flag to be set.
      * @throws IllegalAccessError
      *             if this method attempts to change the value after the
      *             connection has been already established.
      * @see #doInput
-     * @since Android 1.0
      */
     public void setDoInput(boolean newValue) {
         if (connected) {
@@ -871,14 +881,13 @@
     /**
      * Sets the flag indicating whether this {@code URLConnection} allows
      * output. It cannot be set after the connection is established.
-     * 
+     *
      * @param newValue
      *            the new value for the flag to be set.
      * @throws IllegalAccessError
      *             if this method attempts to change the value after the
      *             connection has been already established.
      * @see #doOutput
-     * @since Android 1.0
      */
     public void setDoOutput(boolean newValue) {
         if (connected) {
@@ -890,10 +899,9 @@
     /**
      * Sets the internal map which is used by all {@code URLConnection}
      * instances to determine the MIME-type according to a filename extension.
-     * 
+     *
      * @param map
      *            the MIME table to be set.
-     * @since Android 1.0
      */
     public static void setFileNameMap(FileNameMap map) {
         SecurityManager manager = System.getSecurityManager();
@@ -908,13 +916,12 @@
      * transmitted. Some protocols transmit data only if it has been modified
      * more recently than a particular time. The data will be transmitted
      * regardless of its timestamp if this option is set to {@code 0}.
-     * 
+     *
      * @param newValue
      *            the time in milliseconds since January 1, 1970 GMT.
      * @throws IllegalStateException
      *             if this {@code URLConnection} has already been connected.
      * @see #ifModifiedSince
-     * @since Android 1.0
      */
     public void setIfModifiedSince(long newValue) {
         if (connected) {
@@ -927,7 +934,7 @@
      * Sets the value of the specified request header field. The value will only
      * be used by the current {@code URLConnection} instance. This method can
      * only be called before the connection is established.
-     * 
+     *
      * @param field
      *            the request header field to be set.
      * @param newValue
@@ -936,7 +943,6 @@
      *             if the connection has been already established.
      * @throws NullPointerException
      *             if the parameter {@code field} is {@code null}.
-     * @since Android 1.0
      */
     public void setRequestProperty(String field, String newValue) {
         if (connected) {
@@ -951,14 +957,13 @@
      * Sets the flag indicating whether this connection allows to use caches or
      * not. This method can only be called prior to the connection
      * establishment.
-     * 
+     *
      * @param newValue
      *            the value of the flag to be set.
      * @throws IllegalStateException
      *             if this method attempts to change the flag after the
      *             connection has been established.
      * @see #useCaches
-     * @since Android 1.0
      */
     public void setUseCaches(boolean newValue) {
         if (connected) {
@@ -973,12 +978,11 @@
      * SocketTimeoutException} is thrown if the connection could not be
      * established in this time. Default is {@code 0} which stands for an
      * infinite timeout.
-     * 
+     *
      * @param timeout
      *            the connecting timeout in milliseconds.
      * @throws IllegalArgumentException
      *             if the parameter {@code timeout} is less than zero.
-     * @since Android 1.0
      */
     public void setConnectTimeout(int timeout) {
         if (0 > timeout) {
@@ -989,9 +993,8 @@
 
     /**
      * Gets the configured connecting timeout.
-     * 
+     *
      * @return the connecting timeout value in milliseconds.
-     * @since Android 1.0
      */
     public int getConnectTimeout() {
         return connectTimeout;
@@ -1003,12 +1006,11 @@
      * SocketTimeoutException} is thrown if the connection could not be
      * established in this time. Default is {@code 0} which stands for an
      * infinite timeout.
-     * 
+     *
      * @param timeout
      *            the reading timeout in milliseconds.
      * @throws IllegalArgumentException
      *             if the parameter {@code timeout} is less than zero.
-     * @since Android 1.0
      */
     public void setReadTimeout(int timeout) {
         if (0 > timeout) {
@@ -1020,9 +1022,8 @@
     /**
      * Gets the configured timeout for reading from the input stream of an
      * established connection to the resource.
-     * 
+     *
      * @return the reading timeout value in milliseconds.
-     * @since Android 1.0
      */
     public int getReadTimeout() {
         return readTimeout;
@@ -1031,9 +1032,8 @@
     /**
      * Returns the string representation containing the name of this class and
      * the URL.
-     * 
+     *
      * @return the string representation of this {@code URLConnection} instance.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/luni/src/main/java/java/net/URLDecoder.java b/luni/src/main/java/java/net/URLDecoder.java
index d272aa7..fd2753c 100644
--- a/luni/src/main/java/java/net/URLDecoder.java
+++ b/luni/src/main/java/java/net/URLDecoder.java
@@ -17,20 +17,23 @@
 
 package java.net;
 
-import java.io.ByteArrayOutputStream;
 import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
 
 import org.apache.harmony.luni.util.Msg;
-import org.apache.harmony.luni.util.Util;
 
 /**
  * This class is used to decode a string which is encoded in the {@code
  * application/x-www-form-urlencoded} MIME content type.
- * 
- * @since Android 1.0
  */
 public class URLDecoder {
 
+    static Charset defaultCharset;
+
     /**
      * Decodes the argument which is assumed to be encoded in the {@code
      * x-www-form-urlencoded} MIME content type.
@@ -39,19 +42,32 @@
      * characters are converted to the equivalent byte value. All other
      * characters are passed through unmodified. For example "A+B+C %24%25" ->
      * "A B C $%".
-     * </p>
-     * 
+     *
      * @param s
      *            the encoded string.
      * @return the decoded clear-text representation of the given string.
      * @deprecated use {@link #decode(String, String)} instead.
-     * @since Android 1.0
      */
     @Deprecated
     public static String decode(String s) {
-        return Util.decode(s, true);
+
+        if (defaultCharset == null) {
+            try {
+                defaultCharset = Charset.forName(
+                        System.getProperty("file.encoding")); //$NON-NLS-1$
+            } catch (IllegalCharsetNameException e) {
+                // Ignored
+            } catch (UnsupportedCharsetException e) {
+                // Ignored
+            }
+
+            if (defaultCharset == null) {
+                defaultCharset = Charset.forName("ISO-8859-1"); //$NON-NLS-1$
+            }
+        }
+        return decode(s, defaultCharset);
     }
-    
+
     /**
      * Decodes the argument which is assumed to be encoded in the {@code
      * x-www-form-urlencoded} MIME content type using the specified encoding
@@ -61,8 +77,7 @@
      * characters are converted to the equivalent byte value. All other
      * characters are passed through unmodified. For example "A+B+C %24%25" ->
      * "A B C $%".
-     * </p>
-     * 
+     *
      * @param s
      *            the encoded string.
      * @param enc
@@ -70,7 +85,6 @@
      * @return the decoded clear-text representation of the given string.
      * @throws UnsupportedEncodingException
      *             if the specified encoding scheme is invalid.
-     * @since Android 1.0
      */
     public static String decode(String s, String enc)
             throws UnsupportedEncodingException {
@@ -81,40 +95,80 @@
 
         // If the given encoding is an empty string throw an exception.
         if (enc.length() == 0) {
-            throw new UnsupportedEncodingException(Msg
-                    .getString("K00a5", "enc")); //$NON-NLS-1$ //$NON-NLS-2$
+            throw new UnsupportedEncodingException(
+                    // K00a5=Invalid parameter - {0}
+                    Msg.getString("K00a5", "enc")); //$NON-NLS-1$ //$NON-NLS-2$
         }
 
-        StringBuffer result = new StringBuffer(s.length());
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        if (s.indexOf('%') == -1) {
+            if (s.indexOf('+') == -1)
+                return s;
+            char str[] = s.toCharArray();
+            for (int i = 0; i < str.length; i++) {
+                if (str[i] == '+')
+                    str[i] = ' ';
+            }
+            return new String(str);
+        }
+
+        Charset charset = null;
+        try {
+            charset = Charset.forName(enc);
+        } catch (IllegalCharsetNameException e) {
+            throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
+                    enc).initCause(e));
+        } catch (UnsupportedCharsetException e) {
+            throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
+                    enc).initCause(e));
+        }
+
+        return decode(s, charset);
+    }
+
+    private static String decode(String s, Charset charset) {
+
+        char str_buf[] = new char[s.length()];
+        byte buf[] = new byte[s.length() / 3];
+        int buf_len = 0;
+
         for (int i = 0; i < s.length();) {
             char c = s.charAt(i);
             if (c == '+') {
-                result.append(' ');
+                str_buf[buf_len] = ' ';
             } else if (c == '%') {
-                out.reset();
+
+                int len = 0;
                 do {
                     if (i + 2 >= s.length()) {
-                        throw new IllegalArgumentException(Msg.getString(
-                                "K01fe", i)); //$NON-NLS-1$
+                        throw new IllegalArgumentException(
+                                // K01fe=Incomplete % sequence at\: {0}
+                                Msg.getString("K01fe", i)); //$NON-NLS-1$
                     }
                     int d1 = Character.digit(s.charAt(i + 1), 16);
                     int d2 = Character.digit(s.charAt(i + 2), 16);
                     if (d1 == -1 || d2 == -1) {
-                        throw new IllegalArgumentException(Msg.getString(
-                                "K01ff", //$NON-NLS-1$
-                                s.substring(i, i + 3), String.valueOf(i)));
+                        throw new IllegalArgumentException(
+                                // K01ff=Invalid % sequence ({0}) at\: {1}
+                                Msg.getString(
+                                        "K01ff", //$NON-NLS-1$
+                                        s.substring(i, i + 3),
+                                        String.valueOf(i)));
                     }
-                    out.write((byte) ((d1 << 4) + d2));
+                    buf[len++] = (byte) ((d1 << 4) + d2);
                     i += 3;
                 } while (i < s.length() && s.charAt(i) == '%');
-                result.append(out.toString(enc));
+
+                CharBuffer cb = charset.decode(ByteBuffer.wrap(buf, 0, len));
+                len = cb.length();
+                System.arraycopy(cb.array(), 0, str_buf, buf_len, len);
+                buf_len += len;
                 continue;
             } else {
-                result.append(c);
+                str_buf[buf_len] = c;
             }
             i++;
+            buf_len++;
         }
-        return result.toString();
+        return new String(str_buf, 0, buf_len);
     }
 }
diff --git a/luni/src/main/java/java/net/URLEncoder.java b/luni/src/main/java/java/net/URLEncoder.java
index 69f2d37..2c21aa6 100644
--- a/luni/src/main/java/java/net/URLEncoder.java
+++ b/luni/src/main/java/java/net/URLEncoder.java
@@ -22,8 +22,6 @@
 /**
  * This class is used to encode a string using the format required by
  * {@code application/x-www-form-urlencoded} MIME content type.
- * 
- * @since Android 1.0
  */
 public class URLEncoder {
 
@@ -43,13 +41,11 @@
      * and characters '.', '-', '*', '_' are converted into their hexadecimal
      * value prepended by '%'. For example: '#' -> %23. In addition, spaces are
      * substituted by '+'
-     * </p>
-     * 
+     *
      * @param s
      *            the string to be encoded.
      * @return the encoded string.
      * @deprecated use {@link #encode(String, String)} instead.
-     * @since Android 1.0
      */
     @Deprecated
     public static String encode(String s) {
@@ -81,8 +77,7 @@
      * and characters '.', '-', '*', '_' are converted into their hexadecimal
      * value prepended by '%'. For example: '#' -> %23. In addition, spaces are
      * substituted by '+'
-     * </p>
-     * 
+     *
      * @param s
      *            the string to be encoded.
      * @param enc
@@ -90,10 +85,10 @@
      * @return the encoded string.
      * @throws UnsupportedEncodingException
      *             if the specified encoding scheme is invalid.
-     * @since Android 1.0
      */
     public static String encode(String s, String enc)
             throws UnsupportedEncodingException {
+
         if (s == null || enc == null) {
             throw new NullPointerException();
         }
diff --git a/luni/src/main/java/java/net/URLStreamHandler.java b/luni/src/main/java/java/net/URLStreamHandler.java
index f05c8bd..f039b00 100644
--- a/luni/src/main/java/java/net/URLStreamHandler.java
+++ b/luni/src/main/java/java/net/URLStreamHandler.java
@@ -26,11 +26,8 @@
  * The abstract class {@code URLStreamHandler} is the base for all classes which
  * can handle the communication with a URL object over a particular protocol
  * type.
- * 
- * @since Android 1.0
  */
 public abstract class URLStreamHandler {
-
     /**
      * Establishes a new connection to the resource specified by the URL {@code
      * u}. Since different protocols also have unique ways of connecting, it
@@ -41,7 +38,6 @@
      * @return the opened URLConnection to the specified resource.
      * @throws IOException
      *             if an I/O error occurs during opening the connection.
-     * @since Android 1.0
      */
     protected abstract URLConnection openConnection(URL u) throws IOException;
 
@@ -62,7 +58,6 @@
      *             wrong.
      * @throws UnsupportedOperationException
      *             if the protocol handler doesn't support this method.
-     * @since Android 1.0
      */
     protected URLConnection openConnection(URL u, Proxy proxy)
             throws IOException {
@@ -74,7 +69,7 @@
      * generally have the following format:
      * <p>
      * http://www.company.com/java/file1.java#reference
-     * </p>
+     * <p>
      * The string is parsed in HTTP format. If the protocol has a different URL
      * format this method must be overridden.
      * 
@@ -88,7 +83,6 @@
      *            the string position to stop parsing.
      * @see #toExternalForm
      * @see URL
-     * @since Android 1.0
      */
     protected void parseURL(URL u, String str, int start, int end) {
         // For compatibility, refer to Harmony-2941
@@ -259,7 +253,6 @@
      *            the reference.
      * @deprecated use setURL(URL, String String, int, String, String, String,
      *             String, String) instead.
-     * @since Android 1.0
      */
     @Deprecated
     protected void setURL(URL u, String protocol, String host, int port,
@@ -292,7 +285,6 @@
      *            the query.
      * @param ref
      *            the reference.
-     * @since Android 1.0
      */
     protected void setURL(URL u, String protocol, String host, int port,
             String authority, String userInfo, String file, String query,
@@ -311,7 +303,6 @@
      * @return the clear text representation of the specified URL.
      * @see #parseURL
      * @see URL#toExternalForm()
-     * @since Android 1.0
      */
     protected String toExternalForm(URL url) {
         StringBuffer answer = new StringBuffer(url.getProtocol().length()
@@ -346,7 +337,6 @@
      *            the second URL to compare.
      * @return {@code true} if the URLs are the same, {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     protected boolean equals(URL url1, URL url2) {
         if (!sameFile(url1, url2)) {
@@ -364,9 +354,8 @@
     /**
      * Returns the default port of the protocol used by the handled URL. The
      * current implementation returns always {@code -1}.
-     * 
+     *
      * @return the appropriate default port number of the protocol.
-     * @since Android 1.0
      */
     protected int getDefaultPort() {
         return -1;
@@ -374,11 +363,10 @@
 
     /**
      * Returns the host address of the given URL.
-     * 
+     *
      * @param url
      *            the URL object where to read the host address from.
      * @return the host address of the specified URL.
-     * @since Android 1.0
      */
     protected InetAddress getHostAddress(URL url) {
         try {
@@ -398,7 +386,6 @@
      * @param url
      *            the URL to determine the hashcode.
      * @return the hashcode of the given URL.
-     * @since Android 1.0
      */
     protected int hashCode(URL url) {
         return toExternalForm(url).hashCode();
@@ -406,14 +393,13 @@
 
     /**
      * Compares two URL objects whether they refer to the same host.
-     * 
+     *
      * @param url1
      *            the first URL to be compared.
      * @param url2
      *            the second URL to be compared.
      * @return {@code true} if both URLs refer to the same host, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     protected boolean hostsEqual(URL url1, URL url2) {
         String host1 = getHost(url1), host2 = getHost(url2);
@@ -439,7 +425,6 @@
      *            the second URL to be compared.
      * @return {@code true} if both URLs refer to the same file, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     protected boolean sameFile(URL url1, URL url2) {
         String s1 = url1.getProtocol();
diff --git a/luni/src/main/java/java/net/URLStreamHandlerFactory.java b/luni/src/main/java/java/net/URLStreamHandlerFactory.java
index e696410..4e50792 100644
--- a/luni/src/main/java/java/net/URLStreamHandlerFactory.java
+++ b/luni/src/main/java/java/net/URLStreamHandlerFactory.java
@@ -20,11 +20,9 @@
 /**
  * Defines a factory which creates an {@code URLStreamHandler} for a specified
  * protocol. It is used by the class {@code URL}.
- * 
- * @since Android 1.0
  */
 public interface URLStreamHandlerFactory {
-    
+
     /**
      * Creates a new {@code URLStreamHandler} instance for the given {@code
      * protocol}.
@@ -32,7 +30,6 @@
      * @param protocol
      *            the protocol for which a handler is needed.
      * @return the created handler.
-     * @since Android 1.0
      */
     URLStreamHandler createURLStreamHandler(String protocol);
 }
diff --git a/luni/src/main/java/java/net/UnknownHostException.java b/luni/src/main/java/java/net/UnknownHostException.java
index 9f7c63a..db05558 100644
--- a/luni/src/main/java/java/net/UnknownHostException.java
+++ b/luni/src/main/java/java/net/UnknownHostException.java
@@ -21,8 +21,6 @@
 
 /**
  * Is thrown when a hostname can not be resolved.
- * 
- * @since Android 1.0
  */
 public class UnknownHostException extends IOException {
 
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code UnknownHostException} instance with its walkback
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public UnknownHostException() {
         super();
@@ -44,7 +40,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnknownHostException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/net/UnknownServiceException.java b/luni/src/main/java/java/net/UnknownServiceException.java
index 4865d6d..6ad2a19 100644
--- a/luni/src/main/java/java/net/UnknownServiceException.java
+++ b/luni/src/main/java/java/net/UnknownServiceException.java
@@ -24,8 +24,6 @@
  * particular service requested by the URL connection. This could be happened if
  * there is an invalid MIME type or the application wants to send data over a
  * read-only connection.
- * 
- * @since Android 1.0
  */
 public class UnknownServiceException extends IOException {
 
@@ -34,8 +32,6 @@
     /**
      * Constructs a new {@code UnknownServiceException} instance with its
      * walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public UnknownServiceException() {
         super();
@@ -47,7 +43,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnknownServiceException(String detailMessage) {
         super(detailMessage);
diff --git a/luni/src/main/java/java/util/AbstractCollection.java b/luni/src/main/java/java/util/AbstractCollection.java
index 9f26445..6511b11 100644
--- a/luni/src/main/java/java/util/AbstractCollection.java
+++ b/luni/src/main/java/java/util/AbstractCollection.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.lang.reflect.Array;
 
 /**
@@ -26,23 +25,18 @@
  * iterator()} and {@code size()} to create an immutable collection. To create a
  * modifiable collection it's necessary to override the {@code add()} method that
  * currently throws an {@code UnsupportedOperationException}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public abstract class AbstractCollection<E> implements Collection<E> {
 
     /**
-     * Constructs a new instance of this {@code AbstractCollection}.
-     * 
-     * @since Android 1.0
+     * Constructs a new instance of this AbstractCollection.
      */
     protected AbstractCollection() {
         super();
     }
 
-    /**
-     * @see Collection#add
-     */         
     public boolean add(E object) {
         throw new UnsupportedOperationException();
     }
@@ -64,18 +58,17 @@
      *            the collection of objects.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code Collection} is not supported.
-     * @exception ClassCastException
-     *                when the class of an object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code Collection} is not supported.
+     * @throws ClassCastException
+     *                if the class of an object is inappropriate for this
      *                {@code Collection}.
-     * @exception IllegalArgumentException
-     *                when an object cannot be added to this {@code Collection}.
-     * @exception NullPointerException
-     *                when {@code collection} is {@code null}, or if it contains
+     * @throws IllegalArgumentException
+     *                if an object cannot be added to this {@code Collection}.
+     * @throws NullPointerException
+     *                if {@code collection} is {@code null}, or if it contains
      *                {@code null} elements and this {@code Collection} does not support
      *                such elements.
-     * @since Android 1.0
      */
     public boolean addAll(Collection<? extends E> collection) {
         boolean result = false;
@@ -97,13 +90,12 @@
      * Concrete implementations usually can clear a {@code Collection} more efficiently
      * and should therefore overwrite this method.
      * 
-     * @exception UnsupportedOperationException
-     *                when the iterator does not support removing elements from
+     * @throws UnsupportedOperationException
+     *                it the iterator does not support removing elements from
      *                this {@code Collection}
      * @see #iterator
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public void clear() {
         Iterator<E> it = iterator();
@@ -126,12 +118,11 @@
      *            the object to search for.
      * @return {@code true} if object is an element of this {@code Collection}, {@code
      *         false} otherwise.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if the object to look for isn't of the correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if the object to look for is {@code null} and this
      *                {@code Collection} doesn't support {@code null} elements.
-     * @since Android 1.0
      */
     public boolean contains(Object object) {
         Iterator<E> it = iterator();
@@ -161,16 +152,15 @@
      *            the collection of objects.
      * @return {@code true} if all objects in the specified {@code Collection} are
      *         elements of this {@code Collection}, {@code false} otherwise.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if one or more elements of {@code collection} isn't of the
      *                correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one {@code null}
      *                element and this {@code Collection} doesn't support {@code null}
      *                elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean containsAll(Collection<?> collection) {
         Iterator<?> it = collection.iterator();
@@ -188,9 +178,8 @@
      * 
      * @return {@code true} if this {@code Collection} has no elements, {@code false}
      *         otherwise.
-     * 
+     *
      * @see #size
-     * @since Android 1.0
      */
     public boolean isEmpty() {
         return size() == 0;
@@ -206,7 +195,6 @@
      * by concrete {@code Collection} implementations.
      * 
      * @return an iterator for accessing the {@code Collection} contents.
-     * @since Android 1.0
      */
     public abstract Iterator<E> iterator();
 
@@ -226,14 +214,13 @@
      *            the object to remove.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
-     *                when the object passed is not of the correct type.
-     * @exception NullPointerException
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
+     *                if the object passed is not of the correct type.
+     * @throws NullPointerException
      *                if {@code object} is {@code null} and this {@code Collection}
      *                doesn't support {@code null} elements.
-     * @since Android 1.0
      */
     public boolean remove(Object object) {
         Iterator<?> it = iterator();
@@ -272,18 +259,17 @@
      *            the collection of objects to remove.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
      *                if one or more elements of {@code collection} isn't of the
      *                correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one {@code null}
      *                element and this {@code Collection} doesn't support {@code null}
      *                elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean removeAll(Collection<?> collection) {
         boolean result = false;
@@ -314,18 +300,17 @@
      *            the collection of objects to retain.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
      *                if one or more elements of {@code collection}
      *                isn't of the correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one
      *                {@code null} element and this {@code Collection} doesn't support
      *                {@code null} elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean retainAll(Collection<?> collection) {
         boolean result = false;
@@ -348,7 +333,6 @@
      * @return how many objects this {@code Collection} contains, or {@code Integer.MAX_VALUE}
      *         if there are more than {@code Integer.MAX_VALUE} elements in this
      *         {@code Collection}.
-     * @since Android 1.0
      */
     public abstract int size();
 
@@ -367,10 +351,10 @@
         int size = size(), index = 0;
         if (size > contents.length) {
             Class<?> ct = contents.getClass().getComponentType();
-            contents = (T[])Array.newInstance(ct, size);
+            contents = (T[]) Array.newInstance(ct, size);
         }
-        for (E entry: this) {
-            contents[index++] = (T)entry;
+        for (E entry : this) {
+            contents[index++] = (T) entry;
         }
         if (index < contents.length) {
             contents[index] = null;
@@ -384,7 +368,6 @@
      * are separated by ', ' (comma and space).
      * 
      * @return the string representation of this {@code Collection}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -402,7 +385,7 @@
             } else {
                 buffer.append("(this Collection)"); //$NON-NLS-1$
             }
-            if(it.hasNext()) {
+            if (it.hasNext()) {
                 buffer.append(", "); //$NON-NLS-1$
             }
         }
diff --git a/luni/src/main/java/java/util/AbstractList.java b/luni/src/main/java/java/util/AbstractList.java
index cfd8c6f..899affd 100644
--- a/luni/src/main/java/java/util/AbstractList.java
+++ b/luni/src/main/java/java/util/AbstractList.java
@@ -24,16 +24,14 @@
  * methods {@code get()} and {@code size()}, and to create a
  * modifiable {@code List} it's necessary to override the {@code add()} method that
  * currently throws an {@code UnsupportedOperationException}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public abstract class AbstractList<E> extends AbstractCollection<E> implements
         List<E> {
 
     /**
      * A counter for changes to the list.
-     * 
-     * @since Android 1.0
      */
     protected transient int modCount;
 
@@ -67,22 +65,25 @@
         }
 
         public void remove() {
-            if (expectedModCount == modCount) {
-                try {
-                    AbstractList.this.remove(lastPosition);
-                } catch (IndexOutOfBoundsException e) {
-                    throw new IllegalStateException();
-                }
-                if (modCount != expectedModCount) {
-                    expectedModCount++;
-                }
-                if (pos == lastPosition) {
-                    pos--;
-                }
-                lastPosition = -1;
-            } else {
+            if (this.lastPosition == -1) {
+                throw new IllegalStateException();
+            }
+
+            if (expectedModCount != modCount) {
                 throw new ConcurrentModificationException();
             }
+
+            try {
+                AbstractList.this.remove(lastPosition);
+            } catch (IndexOutOfBoundsException e) {
+                throw new ConcurrentModificationException();
+            }
+
+            expectedModCount = modCount;
+            if (pos == lastPosition) {
+                pos--;
+            }
+            lastPosition = -1;
         }
     }
 
@@ -107,7 +108,7 @@
                 pos++;
                 lastPosition = -1;
                 if (modCount != expectedModCount) {
-                    expectedModCount++;
+                    expectedModCount = modCount;
                 }
             } else {
                 throw new ConcurrentModificationException();
@@ -374,8 +375,6 @@
 
     /**
      * Constructs a new instance of this AbstractList.
-     * 
-     * @since Android 1.0
      */
     protected AbstractList() {
         super();
@@ -386,15 +385,15 @@
      * The object is inserted before any previous element at the specified
      * location. If the location is equal to the size of this List, the object
      * is added at the end.
-     * 
+     * <p>
      * Concrete implementations that would like to support the add functionality
-     * must override this method.          
-     * 
+     * must override this method.
+     *
      * @param location
      *            the index at which to insert.
      * @param object
      *            the object to add.
-     * 
+     *
      * @throws UnsupportedOperationException
      *                if adding to this List is not supported.
      * @throws ClassCastException
@@ -404,7 +403,6 @@
      *                if the object cannot be added to this List
      * @throws IndexOutOfBoundsException
      *                if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     public void add(int location, E object) {
         throw new UnsupportedOperationException();
@@ -412,12 +410,12 @@
 
     /**
      * Adds the specified object at the end of this List.
-     * 
-     * 
+     *
+     *
      * @param object
      *            the object to add
      * @return true
-     * 
+     *
      * @throws UnsupportedOperationException
      *                if adding to this List is not supported
      * @throws ClassCastException
@@ -425,7 +423,6 @@
      *                List
      * @throws IllegalArgumentException
      *                if the object cannot be added to this List
-     * @since Android 1.0
      */
     @Override
     public boolean add(E object) {
@@ -437,7 +434,7 @@
      * Inserts the objects in the specified Collection at the specified location
      * in this List. The objects are added in the order they are returned from
      * the collection's iterator.
-     * 
+     *
      * @param location
      *            the index at which to insert.
      * @param collection
@@ -451,7 +448,6 @@
      *             if an object cannot be added to this list.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || > size()}
-     * @since Android 1.0
      */
     public boolean addAll(int location, Collection<? extends E> collection) {
         Iterator<? extends E> it = collection.iterator();
@@ -463,12 +459,11 @@
 
     /**
      * Removes all elements from this list, leaving it empty.
-     * 
+     *
      * @throws UnsupportedOperationException
      *             if removing from this list is not supported.
      * @see List#isEmpty
      * @see List#size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -479,13 +474,12 @@
      * Compares the specified object to this list and return true if they are
      * equal. Two lists are equal when they both contain the same objects in the
      * same order.
-     * 
+     *
      * @param object
      *            the object to compare to this object.
      * @return {@code true} if the specified object is equal to this list,
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -512,24 +506,22 @@
 
     /**
      * Returns the element at the specified location in this list.
-     * 
+     *
      * @param location
      *            the index of the element to return.
      * @return the element at the specified index.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     public abstract E get(int location);
 
     /**
      * Returns the hash code of this list. The hash code is calculated by taking
      * each element's hashcode into account.
-     * 
+     *
      * @return the hash code.
      * @see #equals
      * @see List#hashCode()
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -545,12 +537,11 @@
     /**
      * Searches this list for the specified object and returns the index of the
      * first occurrence.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return the index of the first occurrence of the object, or -1 if it was
      *         not found.
-     * @since Android 1.0
      */
     public int indexOf(Object object) {
         ListIterator<?> it = listIterator();
@@ -573,10 +564,9 @@
     /**
      * Returns an iterator on the elements of this list. The elements are
      * iterated in the same order as they occur in the list.
-     * 
+     *
      * @return an iterator on the elements of this list.
      * @see Iterator
-     * @since Android 1.0
      */
     @Override
     public Iterator<E> iterator() {
@@ -586,12 +576,11 @@
     /**
      * Searches this list for the specified object and returns the index of the
      * last occurrence.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return the index of the last occurrence of the object, or -1 if the
      *         object was not found.
-     * @since Android 1.0
      */
     public int lastIndexOf(Object object) {
         ListIterator<?> it = listIterator(size());
@@ -614,10 +603,9 @@
     /**
      * Returns a ListIterator on the elements of this list. The elements are
      * iterated in the same order that they occur in the list.
-     * 
+     *
      * @return a ListIterator on the elements of this list
      * @see ListIterator
-     * @since Android 1.0
      */
     public ListIterator<E> listIterator() {
         return listIterator(0);
@@ -627,14 +615,13 @@
      * Returns a list iterator on the elements of this list. The elements are
      * iterated in the same order as they occur in the list. The iteration
      * starts at the specified location.
-     * 
+     *
      * @param location
      *            the index at which to start the iteration.
      * @return a ListIterator on the elements of this list.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || location > size()}
      * @see ListIterator
-     * @since Android 1.0
      */
     public ListIterator<E> listIterator(int location) {
         return new FullListIterator(location);
@@ -642,7 +629,7 @@
 
     /**
      * Removes the object at the specified location from this list.
-     * 
+     *
      * @param location
      *            the index of the object to remove.
      * @return the removed object.
@@ -650,7 +637,6 @@
      *             if removing from this list is not supported.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     public E remove(int location) {
         throw new UnsupportedOperationException();
@@ -659,7 +645,7 @@
     /**
      * Removes the objects in the specified range from the start to the end
      * index minus one.
-     * 
+     *
      * @param start
      *            the index at which to start removing.
      * @param end
@@ -668,7 +654,6 @@
      *             if removing from this list is not supported.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0} or {@code start >= size()}.
-     * @since Android 1.0
      */
     protected void removeRange(int start, int end) {
         Iterator<?> it = listIterator(start);
@@ -681,7 +666,7 @@
     /**
      * Replaces the element at the specified location in this list with the
      * specified object.
-     * 
+     *
      * @param location
      *            the index at which to put the specified object.
      * @param object
@@ -695,7 +680,6 @@
      *             if an object cannot be added to this list.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     public E set(int location, E object) {
         throw new UnsupportedOperationException();
@@ -733,7 +717,7 @@
      * <p>
      * All methods will throw a ConcurrentModificationException if the modCount
      * of the original list is not equal to the expected value.
-     * 
+     *
      * @param start
      *            start index of the subList (inclusive).
      * @param end
@@ -744,7 +728,6 @@
      *             if (start < 0 || end > size())
      * @throws IllegalArgumentException
      *             if (start > end)
-     * @since Android 1.0
      */
     public List<E> subList(int start, int end) {
         if (0 <= start && end <= size()) {
diff --git a/luni/src/main/java/java/util/AbstractMap.java b/luni/src/main/java/java/util/AbstractMap.java
index 00266a7..b687e72 100644
--- a/luni/src/main/java/java/util/AbstractMap.java
+++ b/luni/src/main/java/java/util/AbstractMap.java
@@ -17,17 +17,12 @@
 
 package java.util;
 
-// BEGIN android-added
-// copied from newer harmony
-import java.util.Map.Entry;
-// END android-added
-
 /**
  * This class is an abstract implementation of the {@code Map} interface. This
  * implementation does not support adding. A subclass must implement the
  * abstract method entrySet().
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public abstract class AbstractMap<K, V> implements Map<K, V> {
 
@@ -38,8 +33,6 @@
 
     /**
      * Constructs a new instance of this {@code AbstractMap}.
-     * 
-     * @since Android 1.0
      */
     protected AbstractMap() {
         super();
@@ -47,12 +40,11 @@
 
     /**
      * Removes all elements from this map, leaving it empty.
-     * 
+     *
      * @throws UnsupportedOperationException
      *                if removing from this map is not supported.
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     public void clear() {
         entrySet().clear();
@@ -60,12 +52,11 @@
 
     /**
      * Returns whether this map contains the specified key.
-     * 
+     *
      * @param key
      *            the key to search for.
      * @return {@code true} if this map contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsKey(Object key) {
         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
@@ -87,12 +78,11 @@
 
     /**
      * Returns whether this map contains the specified value.
-     * 
+     *
      * @param value
      *            the value to search for.
      * @return {@code true} if this map contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsValue(Object value) {
         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
@@ -116,23 +106,21 @@
      * Returns a set containing all of the mappings in this map. Each mapping is
      * an instance of {@link Map.Entry}. As the set is backed by this map,
      * changes in one will be reflected in the other.
-     * 
+     *
      * @return a set of the mappings.
-     * @since Android 1.0
      */
     public abstract Set<Map.Entry<K, V>> entrySet();
 
     /**
      * Compares the specified object to this instance, and returns {@code true}
      * if the specified object is a map and both maps contain the same mappings.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return boolean {@code true} if the object is the same as this object,
      *         and {@code false} if it is different from this object.
      * @see #hashCode()
      * @see #entrySet()
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -145,19 +133,21 @@
                 return false;
             }
 
-            // BEGIN android-changed
-            // copied from newer version of harmony
             Iterator<Map.Entry<K, V>> it = entrySet().iterator();
-            while (it.hasNext()) {
-                Entry<K, V> entry = it.next();
-                K key = entry.getKey();
-                V value = entry.getValue();
-                Object obj = map.get(key);
-                if( null != obj && (!obj.equals(value)) || null == obj && obj != value) {
-                    return false;
+
+            try {
+                while (it.hasNext()) {
+                    Entry<K, V> entry = it.next();
+                    K key = entry.getKey();
+                    V value = entry.getValue();
+                    Object obj = map.get(key);
+                    if( null != obj && (!obj.equals(value)) || null == obj && obj != value) {
+                        return false;
+                    }
                 }
+            } catch (ClassCastException cce) {
+                return false;
             }
-            // END android-changed
             return true;
         }
         return false;
@@ -165,12 +155,11 @@
 
     /**
      * Returns the value of the mapping with the specified key.
-     * 
+     *
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
     public V get(Object key) {
         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
@@ -195,10 +184,9 @@
     /**
      * Returns the hash code for this object. Objects which are equal must
      * return the same value for this method.
-     * 
+     *
      * @return the hash code of this object.
      * @see #equals(Object)
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -212,11 +200,10 @@
 
     /**
      * Returns whether this map is empty.
-     * 
+     *
      * @return {@code true} if this map has no elements, {@code false}
      *         otherwise.
      * @see #size()
-     * @since Android 1.0
      */
     public boolean isEmpty() {
         return size() == 0;
@@ -226,9 +213,8 @@
      * Returns a set of the keys contained in this map. The set is backed by
      * this map so changes to one are reflected by the other. The returned set
      * does not support adding.
-     * 
+     *
      * @return a set of the keys.
-     * @since Android 1.0
      */
     public Set<K> keySet() {
         if (keySet == null) {
@@ -269,7 +255,7 @@
 
     /**
      * Maps the specified key to the specified value.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
@@ -286,7 +272,6 @@
      * @throws NullPointerException
      *                if the key or value is {@code null} and this Map does not
      *                support {@code null} keys or values.
-     * @since Android 1.0
      */
     public V put(K key, V value) {
         throw new UnsupportedOperationException();
@@ -294,7 +279,7 @@
 
     /**
      * Copies every mapping in the specified map to this map.
-     * 
+     *
      * @param map
      *            the map to copy mappings from.
      * @throws UnsupportedOperationException
@@ -307,7 +292,6 @@
      * @throws NullPointerException
      *                if a key or value is {@code null} and this map does not
      *                support {@code null} keys or values.
-     * @since Android 1.0
      */
     public void putAll(Map<? extends K, ? extends V> map) {
         for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
@@ -317,14 +301,13 @@
 
     /**
      * Removes a mapping with the specified key from this Map.
-     * 
+     *
      * @param key
      *            the key of the mapping to remove.
      * @return the value of the removed mapping or {@code null} if no mapping
      *         for the specified key was found.
      * @throws UnsupportedOperationException
      *                if removing from this map is not supported.
-     * @since Android 1.0
      */
     public V remove(Object key) {
         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
@@ -350,9 +333,8 @@
 
     /**
      * Returns the number of elements in this map.
-     * 
+     *
      * @return the number of elements in this map.
-     * @since Android 1.0
      */
     public int size() {
         return entrySet().size();
@@ -360,9 +342,8 @@
 
     /**
      * Returns the string representation of this map.
-     * 
+     *
      * @return the string representation of this map.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -407,16 +388,13 @@
      * "wrapper object" over the iterator of map's entrySet(). The {@code size}
      * method wraps the map's size method and the {@code contains} method wraps
      * the map's containsValue method.
-     * </p>
      * <p>
      * The collection is created when this method is called for the first time
      * and returned in response to all subsequent calls. This method may return
      * different collections when multiple concurrent calls occur to this
      * method, since no synchronization is performed.
-     * </p>
-     * 
+     *
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     public Collection<V> values() {
         if (valuesCollection == null) {
@@ -458,12 +436,11 @@
     /**
      * Returns a new instance of the same class as this instance, whose slots
      * have been filled in with the values of the slots of this instance.
-     * 
+     *
      * @return a shallow copy of this object.
      * @throws CloneNotSupportedException
      *                if the receiver's class does not implement the interface
      *                {@code Cloneable}.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
diff --git a/luni/src/main/java/java/util/AbstractQueue.java b/luni/src/main/java/java/util/AbstractQueue.java
index 0b9bdf1..4b4fccf 100644
--- a/luni/src/main/java/java/util/AbstractQueue.java
+++ b/luni/src/main/java/java/util/AbstractQueue.java
@@ -22,18 +22,15 @@
  * {@code element} are based on {@code offer, poll}, and {@code peek} except
  * that they throw exceptions to indicate some error instead of returning true
  * or false.
- * 
+ *
  * @param <E>
  *            the type of the element in the collection.
- * @since Android 1.0
  */
 public abstract class AbstractQueue<E> extends AbstractCollection<E> implements
         Queue<E> {
 
     /**
      * Constructor to be used by subclasses.
-     * 
-     * @since Android 1.0
      */
     protected AbstractQueue() {
         super();
@@ -47,7 +44,6 @@
      * @return {@code true} if the operation succeeds, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the element is not allowed to be added to the queue.
-     * @since Android 1.0
      */
     @Override
     public boolean add(E o) {
@@ -76,7 +72,6 @@
      * @throws IllegalArgumentException
      *             If the collection to be added to the queue is the queue
      *             itself.
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(Collection<? extends E> c) {
@@ -95,7 +90,6 @@
      * @return the element at the head of the queue.
      * @throws NoSuchElementException
      *             if the queue is empty.
-     * @since Android 1.0
      */
     public E remove() {
         E o = poll();
@@ -111,7 +105,6 @@
      * @return the element at the head of the queue.
      * @throws NoSuchElementException
      *             if the queue is empty.
-     * @since Android 1.0
      */
     public E element() {
         E o = peek();
@@ -123,8 +116,6 @@
 
     /**
      * Removes all elements of the queue, leaving it empty.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void clear() {
diff --git a/luni/src/main/java/java/util/AbstractSequentialList.java b/luni/src/main/java/java/util/AbstractSequentialList.java
index 4ca8f7b..dcdecaa 100644
--- a/luni/src/main/java/java/util/AbstractSequentialList.java
+++ b/luni/src/main/java/java/util/AbstractSequentialList.java
@@ -17,20 +17,17 @@
 
 package java.util;
 
-
 /**
  * AbstractSequentialList is an abstract implementation of the List interface.
  * This implementation does not support adding. A subclass must implement the
  * abstract method listIterator().
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public abstract class AbstractSequentialList<E> extends AbstractList<E> {
 
     /**
      * Constructs a new instance of this AbstractSequentialList.
-     * 
-     * @since Android 1.0
      */
     protected AbstractSequentialList() {
         super();
@@ -45,24 +42,11 @@
     public boolean addAll(int location, Collection<? extends E> collection) {
         ListIterator<E> it = listIterator(location);
         Iterator<? extends E> colIt = collection.iterator();
-        // BEGIN android-removed
-        // int next = it.nextIndex();
-        // while (colIt.hasNext()) {
-        //     it.add(colIt.next());
-        //     it.previous();
-        // }
-        // return next != it.nextIndex();
-        // END android-removed
-
-        // BEGIN android-added
-        // BUG: previous/next inconsistant.  We care for list
-        // modification NOT iterator modification.
-        int size = this.size();
+        int next = it.nextIndex();
         while (colIt.hasNext()) {
             it.add(colIt.next());
         }
-        return size != this.size();
-        // END android-added
+        return next != it.nextIndex();
     }
 
     @Override
@@ -97,6 +81,9 @@
     @Override
     public E set(int location, E object) {
         ListIterator<E> it = listIterator(location);
+        if (!it.hasNext()) {
+            throw new IndexOutOfBoundsException();
+        }
         E result = it.next();
         it.set(object);
         return result;
diff --git a/luni/src/main/java/java/util/AbstractSet.java b/luni/src/main/java/java/util/AbstractSet.java
index a19b1f7..e6ef0bb 100644
--- a/luni/src/main/java/java/util/AbstractSet.java
+++ b/luni/src/main/java/java/util/AbstractSet.java
@@ -22,15 +22,13 @@
  * implementation does not support adding. A subclass must implement the
  * abstract methods iterator() and size().
  * 
- * @since Android 1.0
+ * @since 1.2
  */
 public abstract class AbstractSet<E> extends AbstractCollection<E> implements
         Set<E> {
 
     /**
      * Constructs a new instance of this AbstractSet.
-     * 
-     * @since Android 1.0
      */
     protected AbstractSet() {
         super();
@@ -46,7 +44,6 @@
      * @return {@code true} if the specified object is equal to this set,
      *         {@code false} otherwise
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -55,14 +52,12 @@
         }
         if (object instanceof Set) {
             Set<?> s = (Set<?>) object;
-            // BEGIN android-changed
-            // copied from a newer version of harmony
+
             try {
                 return size() == s.size() && containsAll(s);
             } catch (ClassCastException cce) {
                 return false;
             }
-            // END android-changed
         }
         return false;
     }
@@ -74,7 +69,6 @@
      * 
      * @return the hash code of this set.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -95,9 +89,8 @@
      *            the collection of objects to remove.
      * @return {@code true} if this collection was modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this collection is not supported.
-     * @since Android 1.0
+     * @throws UnsupportedOperationException
+     *                if removing from this collection is not supported.
      */
     @Override
     public boolean removeAll(Collection<?> collection) {
diff --git a/luni/src/main/java/java/util/ArrayList.java b/luni/src/main/java/java/util/ArrayList.java
index 78f9690..ade5d27 100644
--- a/luni/src/main/java/java/util/ArrayList.java
+++ b/luni/src/main/java/java/util/ArrayList.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -29,11 +28,11 @@
  * ArrayList is an implementation of {@link List}, backed by an array. All
  * optional operations adding, removing, and replacing are supported. The
  * elements can be any objects.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
-public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable,
-        Serializable, RandomAccess {
+public class ArrayList<E> extends AbstractList<E> implements List<E>,
+        Cloneable, Serializable, RandomAccess {
 
     private static final long serialVersionUID = 8683452581122892189L;
 
@@ -43,53 +42,53 @@
     // END android-added
 
     private transient int firstIndex;
-    
+
     private transient int lastIndex;
 
     private transient E[] array;
 
     /**
      * Constructs a new instance of {@code ArrayList} with zero capacity.
-     * 
-     * @since Android 1.0
      */
     public ArrayList() {
+        // BEGIN android-changed
+        // default capacity is zero, not ten
         this(0);
+        // END android-changed
     }
 
     /**
      * Constructs a new instance of {@code ArrayList} with the specified
      * capacity.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this {@code ArrayList}.
-     * @since Android 1.0
      */
     public ArrayList(int capacity) {
-        firstIndex = lastIndex = 0;
-        try {
-            array = newElementArray(capacity);
-        } catch (NegativeArraySizeException e) {
+        if (capacity < 0) {
             throw new IllegalArgumentException();
         }
+        firstIndex = lastIndex = 0;
+        array = newElementArray(capacity);
     }
 
     /**
      * Constructs a new instance of {@code ArrayList} containing the elements of
      * the specified collection. The initial size of the {@code ArrayList} will
      * be 10% higher than the size of the specified collection.
-     * 
+     *
      * @param collection
      *            the collection of elements to add.
-     * @since Android 1.0
      */
     public ArrayList(Collection<? extends E> collection) {
         int size = collection.size();
-        firstIndex = lastIndex = 0;
+        firstIndex = 0;
         array = newElementArray(size + (size / 10));
-        addAll(collection);
+        collection.toArray(array);
+        lastIndex = size;
+        modCount = 1;
     }
-    
+
     @SuppressWarnings("unchecked")
     private E[] newElementArray(int size) {
         // BEGIN android-added
@@ -98,7 +97,7 @@
         }
         // END android-added
 
-        return (E[])new Object[size];
+        return (E[]) new Object[size];
     }
 
     /**
@@ -106,20 +105,17 @@
      * location. The object is inserted before any previous element at the
      * specified location. If the location is equal to the size of this
      * {@code ArrayList}, the object is added at the end.
-     * 
+     *
      * @param location
      *            the index at which to insert the object.
      * @param object
      *            the object to add.
      * @throws IndexOutOfBoundsException
      *             when {@code location < 0 || > size()}
-     * @since Android 1.0
      */
     @Override
     public void add(int location, E object) {
-        // BEGIN android-changed: slight performance improvement
         int size = lastIndex - firstIndex;
-        // END android-changed
         if (0 < location && location < size) {
             if (firstIndex == 0 && lastIndex == array.length) {
                 growForInsert(location, 1);
@@ -153,11 +149,10 @@
 
     /**
      * Adds the specified object at the end of this {@code ArrayList}.
-     * 
+     *
      * @param object
      *            the object to add.
      * @return always true
-     * @since Android 1.0
      */
     @Override
     public boolean add(E object) {
@@ -173,7 +168,7 @@
      * Inserts the objects in the specified collection at the specified location
      * in this List. The objects are added in the order they are returned from
      * the collection's iterator.
-     * 
+     *
      * @param location
      *            the index at which to insert.
      * @param collection
@@ -182,14 +177,16 @@
      *         otherwise.
      * @throws IndexOutOfBoundsException
      *             when {@code location < 0 || > size()}
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(int location, Collection<? extends E> collection) {
-        int size = size();
+        int size = lastIndex - firstIndex;
         if (location < 0 || location > size) {
             throw new IndexOutOfBoundsException();
         }
+        if (this == collection) {
+            collection = (ArrayList)clone();
+        }
         int growSize = collection.size();
         if (0 < location && location < size) {
             if (array.length - size < growSize) {
@@ -223,12 +220,10 @@
         }
 
         if (growSize > 0) {
-            Iterator<? extends E> it = collection.iterator();
-            int index = location + firstIndex;
-            int end = index + growSize;
-            while (index < end) {
-                array[index++] = it.next();
-            }
+            Object[] dumparray = new Object[growSize];
+            collection.toArray(dumparray);
+            System.arraycopy(dumparray, 0, this.array, location + firstIndex,
+                    growSize);
             modCount++;
             return true;
         }
@@ -237,37 +232,32 @@
 
     /**
      * Adds the objects in the specified collection to this {@code ArrayList}.
-     * 
+     *
      * @param collection
      *            the collection of objects.
      * @return {@code true} if this {@code ArrayList} is modified, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(Collection<? extends E> collection) {
-        int growSize = collection.size();
-        if (growSize > 0) {
-            if (lastIndex > array.length - growSize) {
-                growAtEnd(growSize);
-            }
-            Iterator<? extends E> it = collection.iterator();
-            int end = lastIndex + growSize;
-            while (lastIndex < end) {
-                array[lastIndex++] = it.next();
-            }
-            modCount++;
-            return true;
+        Object[] dumpArray = collection.toArray();
+        if (dumpArray.length == 0) {
+            return false;
         }
-        return false;
+        if (dumpArray.length > array.length - lastIndex) {
+            growAtEnd(dumpArray.length);
+        }
+        System.arraycopy(dumpArray, 0, this.array, lastIndex, dumpArray.length);
+        lastIndex += dumpArray.length;
+        modCount++;
+        return true;
     }
 
     /**
      * Removes all elements from this {@code ArrayList}, leaving it empty.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -281,10 +271,9 @@
     /**
      * Returns a new {@code ArrayList} with the same elements, the same size and
      * the same capacity as this {@code ArrayList}.
-     * 
+     *
      * @return a shallow copy of this {@code ArrayList}
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -300,12 +289,11 @@
 
     /**
      * Searches this {@code ArrayList} for the specified object.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return {@code true} if {@code object} is an element of this
      *         {@code ArrayList}, {@code false} otherwise
-     * @since Android 1.0
      */
     @Override
     public boolean contains(Object object) {
@@ -328,10 +316,9 @@
     /**
      * Ensures that after this operation the {@code ArrayList} can hold the
      * specified number of elements without further growing.
-     * 
+     *
      * @param minimumCapacity
      *            the minimum capacity asked for.
-     * @since Android 1.0
      */
     public void ensureCapacity(int minimumCapacity) {
         if (array.length < minimumCapacity) {
@@ -356,7 +343,7 @@
     }
 
     private void growAtEnd(int required) {
-        int size = size();
+        int size = lastIndex - firstIndex;
         if (firstIndex >= required - (array.length - lastIndex)) {
             int newLast = lastIndex - firstIndex;
             if (size > 0) {
@@ -385,8 +372,8 @@
     }
 
     private void growAtFront(int required) {
-        int size = size();
-        if (array.length - lastIndex >= required) {
+        int size = lastIndex - firstIndex;
+        if (array.length - lastIndex + firstIndex >= required) {
             int newFirst = array.length - size;
             if (size > 0) {
                 System.arraycopy(array, firstIndex, array, newFirst, size);
@@ -416,7 +403,8 @@
     }
 
     private void growForInsert(int location, int required) {
-        int size = size(), increment = size / 2;
+        int size = lastIndex - firstIndex;
+        int increment = size / 2;
         if (required > increment) {
             increment = required;
         }
@@ -480,20 +468,17 @@
 
     /**
      * Removes the object at the specified location from this list.
-     * 
+     *
      * @param location
      *            the index of the object to remove.
      * @return the removed object.
      * @throws IndexOutOfBoundsException
      *             when {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     @Override
     public E remove(int location) {
         E result;
-        // BEGIN android-changed: slight performance improvement
         int size = lastIndex - firstIndex;
-        // END android-changed
         if (0 <= location && location < size) {
             if (location == size - 1) {
                 result = array[--lastIndex];
@@ -514,6 +499,9 @@
                     array[--lastIndex] = null;
                 }
             }
+            if (firstIndex == lastIndex) {
+                firstIndex = lastIndex = 0;
+            }
         } else {
             throw new IndexOutOfBoundsException();
         }
@@ -522,41 +510,34 @@
         return result;
     }
 
-    // BEGIN android-added
-    /*
-     * The remove(Object) implementation from AbstractCollection creates
-     * a new Iterator on every remove and ends up calling remove(int).
-     */
     @Override
     public boolean remove(Object object) {
-        int index = indexOf(object);
-        if (index >= 0) {
-            remove(index);
+        int location = indexOf(object);
+        if (location >= 0) {
+            remove(location);
             return true;
         }
         return false;
     }
-    // END android-added
 
     /**
      * Removes the objects in the specified range from the start to the end, but
      * not including the end index.
-     * 
+     *
      * @param start
      *            the index at which to start removing.
      * @param end
      *            the index one after the end of the range to remove.
      * @throws IndexOutOfBoundsException
      *             when {@code start < 0, start > end} or {@code end > size()}
-     * @since Android 1.0
      */
     @Override
     protected void removeRange(int start, int end) {
-        if (start >= 0 && start <= end && end <= size()) {
+        if (start >= 0 && start <= end && end <= (lastIndex - firstIndex)) {
             if (start == end) {
                 return;
             }
-            int size = size();
+            int size = lastIndex - firstIndex;
             if (end == size) {
                 Arrays.fill(array, firstIndex + start, lastIndex, null);
                 lastIndex = firstIndex + start;
@@ -579,7 +560,7 @@
     /**
      * Replaces the element at the specified location in this {@code ArrayList}
      * with the specified object.
-     * 
+     *
      * @param location
      *            the index at which to put the specified object.
      * @param object
@@ -587,13 +568,10 @@
      * @return the previous element at the index.
      * @throws IndexOutOfBoundsException
      *             when {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     @Override
     public E set(int location, E object) {
-        // BEGIN android-changed: slight performance improvement
         if (0 <= location && location < (lastIndex - firstIndex)) {
-        // END android-changed
             E result = array[firstIndex + location];
             array[firstIndex + location] = object;
             return result;
@@ -603,9 +581,8 @@
 
     /**
      * Returns the number of elements in this {@code ArrayList}.
-     * 
+     *
      * @return the number of elements in this {@code ArrayList}.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -615,13 +592,12 @@
     /**
      * Returns a new array containing all elements contained in this
      * {@code ArrayList}.
-     * 
+     *
      * @return an array of the elements from this {@code ArrayList}
-     * @since Android 1.0
      */
     @Override
     public Object[] toArray() {
-        int size = size();
+        int size = lastIndex - firstIndex;
         Object[] result = new Object[size];
         System.arraycopy(array, firstIndex, result, 0, size);
         return result;
@@ -634,19 +610,18 @@
      * type is created. If the specified array is used and is larger than this
      * {@code ArrayList}, the array element following the collection elements
      * is set to null.
-     * 
+     *
      * @param contents
      *            the array.
      * @return an array of the elements from this {@code ArrayList}.
      * @throws ArrayStoreException
      *             when the type of an element in this {@code ArrayList} cannot
      *             be stored in the type of the specified array.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] contents) {
-        int size = size();
+        int size = lastIndex - firstIndex;
         if (size > contents.length) {
             Class<?> ct = contents.getClass().getComponentType();
             contents = (T[]) Array.newInstance(ct, size);
@@ -661,17 +636,17 @@
     /**
      * Sets the capacity of this {@code ArrayList} to be the same as the current
      * size.
-     * 
+     *
      * @see #size
-     * @since Android 1.0
      */
     public void trimToSize() {
-        int size = size();
+        int size = lastIndex - firstIndex;
         E[] newArray = newElementArray(size);
         System.arraycopy(array, firstIndex, newArray, 0, size);
         array = newArray;
         firstIndex = 0;
         lastIndex = array.length;
+        modCount = 0;
     }
 
     private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
@@ -679,7 +654,7 @@
 
     private void writeObject(ObjectOutputStream stream) throws IOException {
         ObjectOutputStream.PutField fields = stream.putFields();
-        fields.put("size", size()); //$NON-NLS-1$
+        fields.put("size", lastIndex - firstIndex); //$NON-NLS-1$
         stream.writeFields();
         stream.writeInt(array.length);
         Iterator<?> it = iterator();
@@ -695,7 +670,7 @@
         lastIndex = fields.get("size", 0); //$NON-NLS-1$
         array = newElementArray(stream.readInt());
         for (int i = 0; i < lastIndex; i++) {
-            array[i] = (E)stream.readObject();
+            array[i] = (E) stream.readObject();
         }
     }
 }
diff --git a/luni/src/main/java/java/util/Arrays.java b/luni/src/main/java/java/util/Arrays.java
index d479945..4fc1e85 100644
--- a/luni/src/main/java/java/util/Arrays.java
+++ b/luni/src/main/java/java/util/Arrays.java
@@ -22,11 +22,16 @@
 
 /**
  * {@code Arrays} contains static methods which operate on arrays.
- *  
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public class Arrays {
 
+    // BEGIN android-removed
+    /* Specifies when to switch to insertion sort */
+    // private static final int SIMPLE_LENGTH = 7;
+    // END android-removed
+
     private static class ArrayList<E> extends AbstractList<E> implements
             List<E>, Serializable, RandomAccess {
 
@@ -152,11 +157,10 @@
      * {@code List} cannot be modified, i.e. adding and removing are unsupported, but
      * the elements can be set. Setting an element modifies the underlying
      * array.
-     * 
+     *
      * @param array
      *            the array.
      * @return a {@code List} of the elements of the specified array.
-     * @since Android 1.0
      */
     public static <T> List<T> asList(T... array) {
         return new ArrayList<T>(array);
@@ -167,19 +171,18 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code byte} array to search.
      * @param value
      *            the {@code byte} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(byte[] array, byte value) {
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (value > array[mid]) {
                 low = mid + 1;
             } else if (value == array[mid]) {
@@ -200,19 +203,18 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code char} array to search.
      * @param value
      *            the {@code char} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(char[] array, char value) {
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (value > array[mid]) {
                 low = mid + 1;
             } else if (value == array[mid]) {
@@ -232,20 +234,19 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code double} array to search.
      * @param value
      *            the {@code double} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(double[] array, double value) {
         long longBits = Double.doubleToLongBits(value);
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (lessThan(array[mid], value)) {
                 low = mid + 1;
             } else if (longBits == Double.doubleToLongBits(array[mid])) {
@@ -265,20 +266,19 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code float} array to search.
      * @param value
      *            the {@code float} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(float[] array, float value) {
         int intBits = Float.floatToIntBits(value);
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (lessThan(array[mid], value)) {
                 low = mid + 1;
             } else if (intBits == Float.floatToIntBits(array[mid])) {
@@ -298,19 +298,18 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code int} array to search.
      * @param value
      *            the {@code int} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(int[] array, int value) {
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (value > array[mid]) {
                 low = mid + 1;
             } else if (value == array[mid]) {
@@ -330,19 +329,18 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code long} array to search.
      * @param value
      *            the {@code long} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(long[] array, long value) {
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (value > array[mid]) {
                 low = mid + 1;
             } else if (value == array[mid]) {
@@ -362,28 +360,27 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code Object} array to search.
      * @param object
      *            the {@code Object} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if an element in the array or the search element does not
      *                implement {@code Comparable}, or cannot be compared to each other.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static int binarySearch(Object[] array, Object object) {
         if (array.length == 0) {
             return -1;
         }
-        Comparable<Object> key = (Comparable<Object>) object;
+
         int low = 0, mid = 0, high = array.length - 1, result = 0;
         while (low <= high) {
-            mid = (low + high) >> 1;
-            if ((result = key.compareTo(array[mid])) > 0) {
+            mid = (low + high) >>> 1;
+            if ((result = ((Comparable<Object>)array[mid]).compareTo(object)) < 0){
                 low = mid + 1;
             } else if (result == 0) {
                 return mid;
@@ -391,7 +388,7 @@
                 high = mid - 1;
             }
         }
-        return -mid - (result <= 0 ? 1 : 2);
+        return -mid - (result >= 0 ? 1 : 2);
     }
 
     /**
@@ -400,7 +397,7 @@
      * Searching in an unsorted array has an undefined result. It's also
      * undefined which element is found if there are multiple occurrences of the
      * same element.
-     * 
+     *
      * @param array
      *            the sorted array to search
      * @param object
@@ -409,10 +406,9 @@
      *            the {@code Comparator} sued to compare the elements.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @exception ClassCastException
-     *                if an element in the array cannot be compared to the search element 
+     * @throws ClassCastException
+     *                if an element in the array cannot be compared to the search element
      *                using the {@code Comparator}.
-     * @since Android 1.0
      */
     public static <T> int binarySearch(T[] array, T object,
             Comparator<? super T> comparator) {
@@ -422,7 +418,7 @@
 
         int low = 0, mid = 0, high = array.length - 1, result = 0;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if ((result = comparator.compare(array[mid], object)) < 0) {
                 low = mid + 1;
             } else if (result == 0) {
@@ -439,19 +435,18 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code short} array to search.
      * @param value
      *            the {@code short} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(short[] array, short value) {
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (value > array[mid]) {
                 low = mid + 1;
             } else if (value == array[mid]) {
@@ -468,12 +463,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code byte} array to fill.
      * @param value
      *            the {@code byte} element.
-     * @since Android 1.0
      */
     public static void fill(byte[] array, byte value) {
         for (int i = 0; i < array.length; i++) {
@@ -483,7 +477,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code byte} array to fill.
      * @param start
@@ -492,11 +486,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code byte} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(byte[] array, int start, int end, byte value) {
         // Check for null first
@@ -514,12 +507,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code short} array to fill.
      * @param value
      *            the {@code short} element.
-     * @since Android 1.0
      */
     public static void fill(short[] array, short value) {
         for (int i = 0; i < array.length; i++) {
@@ -529,7 +521,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code short} array to fill.
      * @param start
@@ -538,11 +530,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code short} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(short[] array, int start, int end, short value) {
         // Check for null first
@@ -560,12 +551,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code char} array to fill.
      * @param value
      *            the {@code char} element.
-     * @since Android 1.0
      */
     public static void fill(char[] array, char value) {
         for (int i = 0; i < array.length; i++) {
@@ -575,7 +565,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code char} array to fill.
      * @param start
@@ -584,11 +574,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code char} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(char[] array, int start, int end, char value) {
         // Check for null first
@@ -606,12 +595,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code int} array to fill.
      * @param value
      *            the {@code int} element.
-     * @since Android 1.0
      */
     public static void fill(int[] array, int value) {
         for (int i = 0; i < array.length; i++) {
@@ -621,7 +609,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code int} array to fill.
      * @param start
@@ -630,11 +618,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code int} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(int[] array, int start, int end, int value) {
         // Check for null first
@@ -652,12 +639,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code long} array to fill.
      * @param value
      *            the {@code long} element.
-     * @since Android 1.0
      */
     public static void fill(long[] array, long value) {
         for (int i = 0; i < array.length; i++) {
@@ -667,7 +653,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code long} array to fill.
      * @param start
@@ -676,11 +662,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code long} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(long[] array, int start, int end, long value) {
         // Check for null first
@@ -698,12 +683,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code float} array to fill.
      * @param value
      *            the {@code float} element.
-     * @since Android 1.0
      */
     public static void fill(float[] array, float value) {
         for (int i = 0; i < array.length; i++) {
@@ -713,7 +697,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code float} array to fill.
      * @param start
@@ -722,11 +706,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code float} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(float[] array, int start, int end, float value) {
         // Check for null first
@@ -744,12 +727,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code double} array to fill.
      * @param value
      *            the {@code double} element.
-     * @since Android 1.0
      */
     public static void fill(double[] array, double value) {
         for (int i = 0; i < array.length; i++) {
@@ -759,7 +741,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code double} array to fill.
      * @param start
@@ -768,11 +750,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code double} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(double[] array, int start, int end, double value) {
         // Check for null first
@@ -790,12 +771,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code boolean} array to fill.
      * @param value
      *            the {@code boolean} element.
-     * @since Android 1.0
      */
     public static void fill(boolean[] array, boolean value) {
         for (int i = 0; i < array.length; i++) {
@@ -805,7 +785,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code boolean} array to fill.
      * @param start
@@ -814,11 +794,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code boolean} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(boolean[] array, int start, int end, boolean value) {
         // Check for null first
@@ -836,12 +815,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code Object} array to fill.
      * @param value
      *            the {@code Object} element.
-     * @since Android 1.0
      */
     public static void fill(Object[] array, Object value) {
         for (int i = 0; i < array.length; i++) {
@@ -851,7 +829,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code Object} array to fill.
      * @param start
@@ -860,11 +838,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code Object} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(Object[] array, int start, int end, Object value) {
         // Check for null first
@@ -882,7 +859,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code boolean} arrays {@code a} and {@code b}, if 
+     * {@code boolean} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -891,11 +868,10 @@
      * containing a sequence of {@link Boolean}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(boolean[] array) {
         if (array == null) {
@@ -911,7 +887,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * not-null {@code int} arrays {@code a} and {@code b}, if 
+     * not-null {@code int} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -920,11 +896,10 @@
      * containing a sequence of {@link Integer}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(int[] array) {
         if (array == null) {
@@ -940,7 +915,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code short} arrays {@code a} and {@code b}, if 
+     * {@code short} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -949,11 +924,10 @@
      * containing a sequence of {@link Short}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(short[] array) {
         if (array == null) {
@@ -969,7 +943,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code char} arrays {@code a} and {@code b}, if 
+     * {@code char} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -978,11 +952,10 @@
      * containing a sequence of {@link Character}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(char[] array) {
         if (array == null) {
@@ -998,7 +971,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code byte} arrays {@code a} and {@code b}, if 
+     * {@code byte} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -1007,11 +980,10 @@
      * containing a sequence of {@link Byte}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(byte[] array) {
         if (array == null) {
@@ -1027,7 +999,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code long} arrays {@code a} and {@code b}, if 
+     * {@code long} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -1036,11 +1008,10 @@
      * containing a sequence of {@link Long}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(long[] array) {
         if (array == null) {
@@ -1060,7 +1031,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code float} arrays {@code a} and {@code b}, if 
+     * {@code float} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -1069,11 +1040,10 @@
      * containing a sequence of {@link Float}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(float[] array) {
         if (array == null) {
@@ -1092,7 +1062,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code double} arrays {@code a} and {@code b}, if 
+     * {@code double} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -1101,11 +1071,10 @@
      * containing a sequence of {@link Double}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(double[] array) {
         if (array == null) {
@@ -1131,19 +1100,18 @@
      * method on an array that contains itself as an element, either directly or
      * indirectly.
      * <p>
-     * For any two arrays {@code a} and {@code b}, if 
+     * For any two arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
-     * that the return value of {@code Arrays.hashCode(a)} equals 
+     * that the return value of {@code Arrays.hashCode(a)} equals
      * {@code Arrays.hashCode(b)}.
      * <p>
      * The value returned by this method is the same value as the method
      * Arrays.asList(array).hashCode(). If the array is {@code null}, the return value
      * is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(Object[] array) {
         if (array == null) {
@@ -1170,7 +1138,7 @@
      * this method on an array that contains itself as an element, either
      * directly or indirectly.
      * <p>
-     * For any two arrays {@code a} and {@code b}, if 
+     * For any two arrays {@code a} and {@code b}, if
      * {@code Arrays.deepEquals(a, b)} returns {@code true}, it
      * means that the return value of {@code Arrays.deepHashCode(a)} equals
      * {@code Arrays.deepHashCode(b)}.
@@ -1185,11 +1153,10 @@
      * an array of a reference type. The value returned by this method is the
      * same value as the method {@code Arrays.asList(array).hashCode()}. If the array is
      * {@code null}, the return value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int deepHashCode(Object[] array) {
         if (array == null) {
@@ -1247,7 +1214,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code byte} array.
      * @param array2
@@ -1255,7 +1222,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(byte[] array1, byte[] array2) {
         if (array1 == array2) {
@@ -1274,7 +1240,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code short} array.
      * @param array2
@@ -1282,7 +1248,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(short[] array1, short[] array2) {
         if (array1 == array2) {
@@ -1301,7 +1266,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code char} array.
      * @param array2
@@ -1309,7 +1274,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(char[] array1, char[] array2) {
         if (array1 == array2) {
@@ -1328,7 +1292,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code int} array.
      * @param array2
@@ -1336,7 +1300,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(int[] array1, int[] array2) {
         if (array1 == array2) {
@@ -1355,7 +1318,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code long} array.
      * @param array2
@@ -1363,7 +1326,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(long[] array1, long[] array2) {
         if (array1 == array2) {
@@ -1383,7 +1345,7 @@
     /**
      * Compares the two arrays. The values are compared in the same manner as
      * {@code Float.equals()}.
-     * 
+     *
      * @param array1
      *            the first {@code float} array.
      * @param array2
@@ -1392,7 +1354,6 @@
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
      * @see Float#equals(Object)
-     * @since Android 1.0
      */
     public static boolean equals(float[] array1, float[] array2) {
         if (array1 == array2) {
@@ -1413,7 +1374,7 @@
     /**
      * Compares the two arrays. The values are compared in the same manner as
      * {@code Double.equals()}.
-     * 
+     *
      * @param array1
      *            the first {@code double} array.
      * @param array2
@@ -1422,7 +1383,6 @@
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
      * @see Double#equals(Object)
-     * @since Android 1.0
      */
     public static boolean equals(double[] array1, double[] array2) {
         if (array1 == array2) {
@@ -1442,7 +1402,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code boolean} array.
      * @param array2
@@ -1450,7 +1410,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(boolean[] array1, boolean[] array2) {
         if (array1 == array2) {
@@ -1469,7 +1428,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code Object} array.
      * @param array2
@@ -1477,7 +1436,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal according to {@code equals()}, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(Object[] array1, Object[] array2) {
         if (array1 == array2) {
@@ -1522,7 +1480,7 @@
      * <p>
      * If either of the given arrays contain themselves as elements, the
      * behavior of this method is uncertain.
-     * 
+     *
      * @param array1
      *            the first {@code Object} array.
      * @param array2
@@ -1530,7 +1488,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal according to {@code equals()}, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean deepEquals(Object[] array1, Object[] array2) {
         if (array1 == array2) {
@@ -1603,41 +1560,58 @@
     }
 
     private static boolean lessThan(double double1, double double2) {
-        long d1, d2;
-        long NaNbits = Double.doubleToLongBits(Double.NaN);
-        if ((d1 = Double.doubleToLongBits(double1)) == NaNbits) {
-            return false;
-        }
-        if ((d2 = Double.doubleToLongBits(double2)) == NaNbits) {
+        // A slightly specialized version of
+        // Double.compare(double1, double2) < 0.
+
+        // Non-zero and non-NaN checking.
+        if (double1 < double2) {
             return true;
         }
-        if (double1 == double2) {
-            if (d1 == d2) {
-                return false;
-            }
-            // check for -0
-            return d1 < d2;
+        if (double1 > double2) {
+            return false;
         }
-        return double1 < double2;
+        if (double1 == double2 && 0.0d != double1) {
+            return false;
+        }
+
+        // NaNs are equal to other NaNs and larger than any other double.
+        if (Double.isNaN(double1)) {
+            return false;
+        } else if (Double.isNaN(double2)) {
+            return true;
+        }
+
+        // Deal with +0.0 and -0.0.
+        long d1 = Double.doubleToRawLongBits(double1);
+        long d2 = Double.doubleToRawLongBits(double2);
+        return d1 < d2;
     }
 
     private static boolean lessThan(float float1, float float2) {
-        int f1, f2;
-        int NaNbits = Float.floatToIntBits(Float.NaN);
-        if ((f1 = Float.floatToIntBits(float1)) == NaNbits) {
-            return false;
-        }
-        if ((f2 = Float.floatToIntBits(float2)) == NaNbits) {
+        // A slightly specialized version of Float.compare(float1, float2) < 0.
+
+        // Non-zero and non-NaN checking.
+        if (float1 < float2) {
             return true;
         }
-        if (float1 == float2) {
-            if (f1 == f2) {
-                return false;
-            }
-            // check for -0
-            return f1 < f2;
+        if (float1 > float2) {
+            return false;
         }
-        return float1 < float2;
+        if (float1 == float2 && 0.0f != float1) {
+            return false;
+        }
+
+        // NaNs are equal to other NaNs and larger than any other float
+        if (Float.isNaN(float1)) {
+            return false;
+        } else if (Float.isNaN(float2)) {
+            return true;
+        }
+
+        // Deal with +0.0 and -0.0
+        int f1 = Float.floatToRawIntBits(float1);
+        int f2 = Float.floatToRawIntBits(float2);
+        return f1 < f2;
     }
 
     private static int med3(byte[] array, int a, int b, int c) {
@@ -1684,10 +1658,9 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code byte} array to be sorted.
-     * @since Android 1.0
      */
     public static void sort(byte[] array) {
         sort(0, array.length, array);
@@ -1695,18 +1668,17 @@
 
     /**
      * Sorts the specified range in the array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code byte} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(byte[] array, int start, int end) {
         if (array == null) {
@@ -1718,8 +1690,8 @@
 
     private static void checkBounds(int arrLength, int start, int end) {
         if (start > end) {
-            throw new IllegalArgumentException("fromIndex(" + start //$NON-NLS-1$
-                    + ") > toIndex(" + end + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+            throw new IllegalArgumentException("start(" + start //$NON-NLS-1$
+                    + ") > end(" + end + ")"); //$NON-NLS-1$ //$NON-NLS-2$
         }
         if (start < 0 || end > arrLength) {
             throw new ArrayIndexOutOfBoundsException();
@@ -1806,10 +1778,9 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code char} array to be sorted.
-     * @since Android 1.0
      */
     public static void sort(char[] array) {
         sort(0, array.length, array);
@@ -1817,18 +1788,17 @@
 
     /**
      * Sorts the specified range in the array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code char} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(char[] array, int start, int end) {
         if (array == null) {
@@ -1918,11 +1888,10 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code double} array to be sorted.
      * @see #sort(double[], int, int)
-     * @since Android 1.0
      */
     public static void sort(double[] array) {
         sort(0, array.length, array);
@@ -1931,19 +1900,18 @@
     /**
      * Sorts the specified range in the array in ascending numerical order. The
      * values are sorted according to the order imposed by {@code Double.compareTo()}.
-     * 
+     *
      * @param array
      *            the {@code double} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
      * @see Double#compareTo(Double)
-     * @since Android 1.0
      */
     public static void sort(double[] array, int start, int end) {
         if (array == null) {
@@ -2033,11 +2001,10 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code float} array to be sorted.
      * @see #sort(float[], int, int)
-     * @since Android 1.0
      */
     public static void sort(float[] array) {
         sort(0, array.length, array);
@@ -2046,19 +2013,18 @@
     /**
      * Sorts the specified range in the array in ascending numerical order. The
      * values are sorted according to the order imposed by {@code Float.compareTo()}.
-     * 
+     *
      * @param array
      *            the {@code float} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
      * @see Float#compareTo(Float)
-     * @since Android 1.0
      */
     public static void sort(float[] array, int start, int end) {
         if (array == null) {
@@ -2148,10 +2114,9 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code int} array to be sorted.
-     * @since Android 1.0
      */
     public static void sort(int[] array) {
         sort(0, array.length, array);
@@ -2159,18 +2124,17 @@
 
     /**
      * Sorts the specified range in the array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code int} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(int[] array, int start, int end) {
         if (array == null) {
@@ -2260,10 +2224,9 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code long} array to be sorted.
-     * @since Android 1.0
      */
     public static void sort(long[] array) {
         sort(0, array.length, array);
@@ -2271,18 +2234,17 @@
 
     /**
      * Sorts the specified range in the array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code long} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(long[] array, int start, int end) {
         if (array == null) {
@@ -2370,7 +2332,7 @@
         }
     }
 
-// BEGIN android-changed
+// BEGIN android-note
 
     /*
      * <p>If this platform has an optimizing VM, check whether ComparableTimSort
@@ -2405,19 +2367,22 @@
 //        sort(a, fromIndex, toIndex, NATURAL_ORDER);
 //    }
 
+// END android-note
+
     /**
      * Sorts the specified array in ascending natural order.
-     * 
+     *
      * @param array
      *            the {@code Object} array to be sorted.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if an element in the array does not implement {@code Comparable}
      *                or if some elements cannot be compared to each other.
      * @see #sort(Object[], int, int)
-     * @since Android 1.0
      */
     public static void sort(Object[] array) {
+        // BEGIN android-changed
         ComparableTimSort.sort(array);
+        // END android-changed
     }
 
     /**
@@ -2425,31 +2390,76 @@
      * elements must implement the {@code Comparable} interface and must be
      * comparable to each other without a {@code ClassCastException} being
      * thrown.
-     * 
+     *
      * @param array
      *            the {@code Object} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if an element in the array does not implement {@code Comparable}
      *                or some elements cannot be compared to each other.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(Object[] array, int start, int end) {
+        // BEGIN android-changed
         ComparableTimSort.sort(array, start, end);
+        // END android-changed
     }
 
+    // BEGIN android-removed
+    /*
+    private static void sort(int start, int end, Object[] array) {
+            ...
+    }
+    private static void swap(int a, int b, Object[] arr) {
+            ...
+    }
+    private static void mergeSort(Object[] in, Object[] out, int start,
+            int end) {
+            ...
+    }
+    private static void mergeSort(Object[] in, Object[] out, int start,
+            int end, Comparator c) {
+            ...
+    }
+    private static int find(Object[] arr, Comparable val, int bnd, int l, int r) {
+            ...
+    }
+    private static int find(Object[] arr, Object val, int bnd, int l, int r,
+            Comparator c) {
+            ...
+    }
+    private static int medChar(int a, int b, int c, String[] arr, int id) {
+            ...
+    }
+    private static int charAt(String str, int i) {
+            ...
+    }
+    private static void copySwap(Object[] src, int from, Object[] dst, int to,
+            int len) {
+            ...
+    }
+    private static void stableStringSort(String[] arr, int start,
+            int end) {
+            ...
+    }
+    private static void stableStringSort(String[] arr, String[] src,
+            String[] dst, int start, int end, int chId) {
+            ...
+    }
+    */
+    // END android-removed
+
     /**
      * Sorts the specified range in the array using the specified {@code Comparator}.
      * All elements must be comparable to each other without a
      * {@code ClassCastException} being thrown.
-     * 
+     *
      * @param array
      *            the {@code Object} array to be sorted.
      * @param start
@@ -2458,45 +2468,44 @@
      *            the last + 1 index to sort.
      * @param comparator
      *            the {@code Comparator}.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if elements in the array cannot be compared to each other
      *                using the {@code Comparator}.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static <T> void sort(T[] array, int start, int end,
             Comparator<? super T> comparator) {
+        // BEGIN android-changed
         TimSort.sort(array, start, end, comparator);
+        // END android-changed
     }
 
     /**
      * Sorts the specified array using the specified {@code Comparator}. All elements
      * must be comparable to each other without a {@code ClassCastException} being thrown.
-     * 
+     *
      * @param array
      *            the {@code Object} array to be sorted.
      * @param comparator
      *            the {@code Comparator}.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if elements in the array cannot be compared to each other
      *                using the {@code Comparator}.
-     * @since Android 1.0
      */
     public static <T> void sort(T[] array, Comparator<? super T> comparator) {
+        // BEGIN android-changed
         TimSort.sort(array, comparator);
+        // END android-changed
     }
 
-// END  android-changed
-
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code short} array to be sorted.
-     * @since Android 1.0
      */
     public static void sort(short[] array) {
         sort(0, array.length, array);
@@ -2504,18 +2513,17 @@
 
     /**
      * Sorts the specified range in the array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code short} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(short[] array, int start, int end) {
         if (array == null) {
@@ -2604,18 +2612,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code boolean[]} passed.
      * The result is surrounded by brackets ({@code &quot;[]&quot;}), each
      * element is converted to a {@code String} via the
      * {@link String#valueOf(boolean)} and separated by {@code &quot;, &quot;}.
      * If the array is {@code null}, then {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code boolean} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(boolean[] array) {
         if (array == null) {
@@ -2636,18 +2642,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code byte[]} passed. The
      * result is surrounded by brackets ({@code &quot;[]&quot;}), each element
      * is converted to a {@code String} via the {@link String#valueOf(int)} and
      * separated by {@code &quot;, &quot;}. If the array is {@code null}, then
      * {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code byte} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(byte[] array) {
         if (array == null) {
@@ -2668,18 +2672,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code char[]} passed. The
      * result is surrounded by brackets ({@code &quot;[]&quot;}), each element
      * is converted to a {@code String} via the {@link String#valueOf(char)} and
      * separated by {@code &quot;, &quot;}. If the array is {@code null}, then
      * {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code char} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(char[] array) {
         if (array == null) {
@@ -2700,18 +2702,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code double[]} passed.
      * The result is surrounded by brackets ({@code &quot;[]&quot;}), each
      * element is converted to a {@code String} via the
      * {@link String#valueOf(double)} and separated by {@code &quot;, &quot;}.
      * If the array is {@code null}, then {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code double} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(double[] array) {
         if (array == null) {
@@ -2732,18 +2732,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code float[]} passed.
      * The result is surrounded by brackets ({@code &quot;[]&quot;}), each
      * element is converted to a {@code String} via the
      * {@link String#valueOf(float)} and separated by {@code &quot;, &quot;}.
      * If the array is {@code null}, then {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code float} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(float[] array) {
         if (array == null) {
@@ -2764,18 +2762,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code int[]} passed. The
      * result is surrounded by brackets ({@code &quot;[]&quot;}), each element
      * is converted to a {@code String} via the {@link String#valueOf(int)} and
      * separated by {@code &quot;, &quot;}. If the array is {@code null}, then
      * {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code int} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(int[] array) {
         if (array == null) {
@@ -2796,18 +2792,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code long[]} passed. The
      * result is surrounded by brackets ({@code &quot;[]&quot;}), each element
      * is converted to a {@code String} via the {@link String#valueOf(long)} and
      * separated by {@code &quot;, &quot;}. If the array is {@code null}, then
      * {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code long} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(long[] array) {
         if (array == null) {
@@ -2828,18 +2822,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code short[]} passed.
      * The result is surrounded by brackets ({@code &quot;[]&quot;}), each
      * element is converted to a {@code String} via the
      * {@link String#valueOf(int)} and separated by {@code &quot;, &quot;}. If
      * the array is {@code null}, then {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code short} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(short[] array) {
         if (array == null) {
@@ -2860,18 +2852,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code Object[]} passed.
      * The result is surrounded by brackets ({@code &quot;[]&quot;}), each
      * element is converted to a {@code String} via the
      * {@link String#valueOf(Object)} and separated by {@code &quot;, &quot;}.
      * If the array is {@code null}, then {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code Object} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(Object[] array) {
         if (array == null) {
@@ -2892,11 +2882,9 @@
     }
 
     /**
-     * <p>
      * Creates a <i>"deep"</i> {@code String} representation of the
      * {@code Object[]} passed, such that if the array contains other arrays,
      * the {@code String} representation of those arrays is generated as well.
-     * </p>
      * <p>
      * If any of the elements are primitive arrays, the generation is delegated
      * to the other {@code toString} methods in this class. If any element
@@ -2904,12 +2892,11 @@
      * as {@code "[...]"}. If an element is an {@code Object[]}, then its
      * representation is generated by a recursive call to this method. All other
      * elements are converted via the {@link String#valueOf(Object)} method.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code Object} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String deepToString(Object[] array) {
         // Special case null to prevent NPE
@@ -2923,10 +2910,8 @@
     }
 
     /**
-     * <p>
      * Implementation method used by {@link #deepToString(Object[])}.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code Object[]} to dive into.
      * @param origArrays
@@ -3010,11 +2995,9 @@
     }
 
     /**
-     * <p>
      * Utility method used to assist the implementation of
      * {@link #deepToString(Object[])}.
-     * </p>
-     * 
+     *
      * @param origArrays
      *            An array of Object[] references.
      * @param array
diff --git a/luni/src/main/java/java/util/BitSet.java b/luni/src/main/java/java/util/BitSet.java
index aa60be0..d2d7c0a 100644
--- a/luni/src/main/java/java/util/BitSet.java
+++ b/luni/src/main/java/java/util/BitSet.java
@@ -17,6 +17,8 @@
 
 package java.util;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import java.io.Serializable;
 
 import org.apache.harmony.luni.util.Msg;
@@ -26,20 +28,43 @@
  * {@code BitSet} can be on(1) or off(0). A {@code BitSet} is created with a
  * given size and grows if this size is exceeded. Growth is always rounded to a
  * 64 bit boundary.
- *  
- * @since Android 1.0
  */
 public class BitSet implements Serializable, Cloneable {
     private static final long serialVersionUID = 7997698588986878753L;
 
-    // Size in bits of the data type being used in the bits array
-    private static final int ELM_SIZE = 64;
+    private static final int OFFSET = 6;
+
+    private static final int ELM_SIZE = 1 << OFFSET;
+
+    private static final int RIGHT_BITS = ELM_SIZE - 1;
+
+    private static final long[] TWO_N_ARRAY = new long[] { 0x1L, 0x2L, 0x4L,
+            0x8L, 0x10L, 0x20L, 0x40L, 0x80L, 0x100L, 0x200L, 0x400L, 0x800L,
+            0x1000L, 0x2000L, 0x4000L, 0x8000L, 0x10000L, 0x20000L, 0x40000L,
+            0x80000L, 0x100000L, 0x200000L, 0x400000L, 0x800000L, 0x1000000L,
+            0x2000000L, 0x4000000L, 0x8000000L, 0x10000000L, 0x20000000L,
+            0x40000000L, 0x80000000L, 0x100000000L, 0x200000000L, 0x400000000L,
+            0x800000000L, 0x1000000000L, 0x2000000000L, 0x4000000000L,
+            0x8000000000L, 0x10000000000L, 0x20000000000L, 0x40000000000L,
+            0x80000000000L, 0x100000000000L, 0x200000000000L, 0x400000000000L,
+            0x800000000000L, 0x1000000000000L, 0x2000000000000L,
+            0x4000000000000L, 0x8000000000000L, 0x10000000000000L,
+            0x20000000000000L, 0x40000000000000L, 0x80000000000000L,
+            0x100000000000000L, 0x200000000000000L, 0x400000000000000L,
+            0x800000000000000L, 0x1000000000000000L, 0x2000000000000000L,
+            0x4000000000000000L, 0x8000000000000000L };
 
     private long[] bits;
 
+    private transient boolean needClear;
+
+    private transient int actualArrayLength;
+
+    private transient boolean isLengthActual;
+
     /**
      * Create a new {@code BitSet} with size equal to 64 bits.
-     * 
+     *
      * @see #clear(int)
      * @see #set(int)
      * @see #clear()
@@ -47,17 +72,18 @@
      * @see #set(int, boolean)
      * @see #set(int, int)
      * @see #set(int, int, boolean)
-     * @since Android 1.0
      */
     public BitSet() {
-        this(64);
+        bits = new long[1];
+        actualArrayLength = 0;
+        isLengthActual = true;
     }
 
     /**
      * Create a new {@code BitSet} with size equal to nbits. If nbits is not a
      * multiple of 64, then create a {@code BitSet} with size nbits rounded to
      * the next closest multiple of 64.
-     * 
+     *
      * @param nbits
      *            the size of the bit set.
      * @throws NegativeArraySizeException
@@ -69,31 +95,34 @@
      * @see #set(int, boolean)
      * @see #set(int, int)
      * @see #set(int, int, boolean)
-     * @since Android 1.0
      */
     public BitSet(int nbits) {
-        if (nbits >= 0) {
-            bits = new long[(nbits / ELM_SIZE) + (nbits % ELM_SIZE > 0 ? 1 : 0)];
-        } else {
+        if (nbits < 0) {
             throw new NegativeArraySizeException();
         }
+        bits = new long[(nbits >> OFFSET) + ((nbits & RIGHT_BITS) > 0 ? 1 : 0)];
+        actualArrayLength = 0;
+        isLengthActual = true;
     }
 
     /**
      * Private constructor called from get(int, int) method
-     * 
+     *
      * @param bits
      *            the size of the bit set
      */
-    private BitSet(long[] bits) {
+    private BitSet(long[] bits, boolean needClear, int actualArrayLength,
+            boolean isLengthActual) {
         this.bits = bits;
+        this.needClear = needClear;
+        this.actualArrayLength = actualArrayLength;
+        this.isLengthActual = isLengthActual;
     }
 
     /**
      * Creates a copy of this {@code BitSet}.
-     * 
+     *
      * @return a copy of this {@code BitSet}.
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -110,13 +139,12 @@
      * Compares the argument to this {@code BitSet} and returns whether they are
      * equal. The object must be an instance of {@code BitSet} with the same
      * bits set.
-     * 
+     *
      * @param obj
      *            the {@code BitSet} object to compare.
      * @return a {@code boolean} indicating whether or not this {@code BitSet} and
      *         {@code obj} are equal.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -125,10 +153,13 @@
         }
         if (obj instanceof BitSet) {
             long[] bsBits = ((BitSet) obj).bits;
-            int length1 = bits.length, length2 = bsBits.length;
+            int length1 = this.actualArrayLength, length2 = ((BitSet) obj).actualArrayLength;
+            if (this.isLengthActual && ((BitSet) obj).isLengthActual
+                    && length1 != length2) {
+                return false;
+            }
             // If one of the BitSets is larger than the other, check to see if
-            // any of
-            // its extra bits are set. If so return false.
+            // any of its extra bits are set. If so return false.
             if (length1 <= length2) {
                 for (int i = 0; i < length1; i++) {
                     if (bits[i] != bsBits[i]) {
@@ -160,35 +191,29 @@
     /**
      * Increase the size of the internal array to accommodate {@code pos} bits.
      * The new array max index will be a multiple of 64.
-     * 
-     * @param pos
+     *
+     * @param len
      *            the index the new array needs to be able to access.
-     * @since Android 1.0
      */
-    private void growBits(int pos) {
-        pos++; // Inc to get correct bit count
-        long[] tempBits = new long[(pos / ELM_SIZE)
-                + (pos % ELM_SIZE > 0 ? 1 : 0)];
-        System.arraycopy(bits, 0, tempBits, 0, bits.length);
+    private final void growLength(int len) {
+        long[] tempBits = new long[Math.max(len, bits.length * 2)];
+        System.arraycopy(bits, 0, tempBits, 0, this.actualArrayLength);
         bits = tempBits;
     }
 
     /**
      * Computes the hash code for this {@code BitSet}. If two {@code BitSet}s are equal
      * the have to return the same result for {@code hashCode()}.
-     * 
+     *
      * @return the {@code int} representing the hash code for this bit
      *         set.
      * @see #equals
      * @see java.util.Hashtable
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
         long x = 1234;
-        // for (int i = 0, length = bits.length; i < length; i+=2)
-        // x ^= (bits[i] + ((long)bits[i+1] << 32)) * (i/2 + 1);
-        for (int i = 0, length = bits.length; i < length; i++) {
+        for (int i = 0, length = actualArrayLength; i < length; i++) {
             x ^= bits[i] * (i + 1);
         }
         return (int) ((x >> 32) ^ x);
@@ -197,7 +222,7 @@
     /**
      * Retrieves the bit at index {@code pos}. Grows the {@code BitSet} if
      * {@code pos > size}.
-     * 
+     *
      * @param pos
      *            the index of the bit to be retrieved.
      * @return {@code true} if the bit at {@code pos} is set,
@@ -211,89 +236,98 @@
      * @see #set(int, boolean)
      * @see #set(int, int)
      * @see #set(int, int, boolean)
-     * @since Android 1.0
      */
     public boolean get(int pos) {
-        if (pos >= 0) {
-            if (pos < bits.length * ELM_SIZE) {
-                return (bits[pos / ELM_SIZE] & (1L << (pos % ELM_SIZE))) != 0;
-            }
-            return false;
+        if (pos < 0) {
+            // Negative index specified
+            throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
-        // Negative index specified
-        throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+
+        int arrayPos = pos >> OFFSET;
+        if (arrayPos < actualArrayLength) {
+            return (bits[arrayPos] & TWO_N_ARRAY[pos & RIGHT_BITS]) != 0;
+        }
+        return false;
     }
 
     /**
      * Retrieves the bits starting from {@code pos1} to {@code pos2} and returns
      * back a new bitset made of these bits. Grows the {@code BitSet} if
      * {@code pos2 > size}.
-     * 
+     *
      * @param pos1
-     *            beginning position.
+     *            inclusive beginning position.
      * @param pos2
-     *            ending position.
+     *            exclusive ending position.
      * @return new bitset of the range specified.
      * @throws IndexOutOfBoundsException
      *             if {@code pos1} or {@code pos2} is negative, or if
      *             {@code pos2} is smaller than {@code pos1}.
      * @see #get(int)
-     * @since Android 1.0
      */
     public BitSet get(int pos1, int pos2) {
-        if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
-            int last = (bits.length * ELM_SIZE);
-            if (pos1 >= last || pos1 == pos2) {
+        if (pos1 < 0 || pos2 < 0 || pos2 < pos1) {
+            throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+        }
+
+        int last = actualArrayLength << OFFSET;
+        if (pos1 >= last || pos1 == pos2) {
+            return new BitSet(0);
+        }
+        if (pos2 > last) {
+            pos2 = last;
+        }
+
+        int idx1 = pos1 >> OFFSET;
+        int idx2 = (pos2 - 1) >> OFFSET;
+        long factor1 = (~0L) << (pos1 & RIGHT_BITS);
+        long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS));
+
+        if (idx1 == idx2) {
+            long result = (bits[idx1] & (factor1 & factor2)) >>> (pos1 % ELM_SIZE);
+            if (result == 0) {
                 return new BitSet(0);
             }
-            if (pos2 > last) {
-                pos2 = last;
-            }
+            return new BitSet(new long[] { result }, needClear, 1, true);
+        }
+        long[] newbits = new long[idx2 - idx1 + 1];
+        // first fill in the first and last indexes in the new bitset
+        newbits[0] = bits[idx1] & factor1;
+        newbits[newbits.length - 1] = bits[idx2] & factor2;
 
-            int idx1 = pos1 / ELM_SIZE;
-            int idx2 = (pos2 - 1) / ELM_SIZE;
-            long factor1 = (~0L) << (pos1 % ELM_SIZE);
-            long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
+        // fill in the in between elements of the new bitset
+        for (int i = 1; i < idx2 - idx1; i++) {
+            newbits[i] = bits[idx1 + i];
+        }
 
-            if (idx1 == idx2) {
-                long result = (bits[idx1] & (factor1 & factor2)) >>> (pos1 % ELM_SIZE);
-                return new BitSet(new long[] { result });
-            }
-            long[] newbits = new long[idx2 - idx1 + 1];
-            // first fill in the first and last indexes in the new bitset
-            newbits[0] = bits[idx1] & factor1;
-            newbits[newbits.length - 1] = bits[idx2] & factor2;
+        // shift all the elements in the new bitset to the right by pos1
+        // % ELM_SIZE
+        int numBitsToShift = pos1 & RIGHT_BITS;
+        int actualLen = newbits.length;
+        if (numBitsToShift != 0) {
+            for (int i = 0; i < newbits.length; i++) {
+                // shift the current element to the right regardless of
+                // sign
+                newbits[i] = newbits[i] >>> (numBitsToShift);
 
-            // fill in the in between elements of the new bitset
-            for (int i = 1; i < idx2 - idx1; i++) {
-                newbits[i] = bits[idx1 + i];
-            }
-
-            // shift all the elements in the new bitset to the right by pos1
-            // % ELM_SIZE
-            int numBitsToShift = pos1 % ELM_SIZE;
-            if (numBitsToShift != 0) {
-                for (int i = 0; i < newbits.length; i++) {
-                    // shift the current element to the right regardless of
-                    // sign
-                    newbits[i] = newbits[i] >>> (numBitsToShift);
-
-                    // apply the last x bits of newbits[i+1] to the current
-                    // element
-                    if (i != newbits.length - 1) {
-                        newbits[i] |= newbits[i + 1] << (ELM_SIZE - (numBitsToShift));
-                    }
+                // apply the last x bits of newbits[i+1] to the current
+                // element
+                if (i != newbits.length - 1) {
+                    newbits[i] |= newbits[i + 1] << (ELM_SIZE - (numBitsToShift));
+                }
+                if (newbits[i] != 0) {
+                    actualLen = i + 1;
                 }
             }
-            return new BitSet(newbits);
         }
-        throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+        return new BitSet(newbits, needClear, actualLen,
+                newbits[actualLen - 1] != 0);
     }
 
     /**
      * Sets the bit at index {@code pos} to 1. Grows the {@code BitSet} if
      * {@code pos > size}.
-     * 
+     *
      * @param pos
      *            the index of the bit to set.
      * @throws IndexOutOfBoundsException
@@ -301,23 +335,28 @@
      * @see #clear(int)
      * @see #clear()
      * @see #clear(int, int)
-     * @since Android 1.0
      */
     public void set(int pos) {
-        if (pos >= 0) {
-            if (pos >= bits.length * ELM_SIZE) {
-                growBits(pos);
-            }
-            bits[pos / ELM_SIZE] |= 1L << (pos % ELM_SIZE);
-        } else {
+        if (pos < 0) {
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        int len = (pos >> OFFSET) + 1;
+        if (len > bits.length) {
+            growLength(len);
+        }
+        bits[len - 1] |= TWO_N_ARRAY[pos & RIGHT_BITS];
+        if (len > actualArrayLength) {
+            actualArrayLength = len;
+            isLengthActual = true;
+        }
+        needClear();
     }
 
     /**
      * Sets the bit at index {@code pos} to {@code val}. Grows the
      * {@code BitSet} if {@code pos > size}.
-     * 
+     *
      * @param pos
      *            the index of the bit to set.
      * @param val
@@ -325,7 +364,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code pos} is negative.
      * @see #set(int)
-     * @since Android 1.0
      */
     public void set(int pos, boolean val) {
         if (val) {
@@ -338,60 +376,68 @@
     /**
      * Sets the bits starting from {@code pos1} to {@code pos2}. Grows the
      * {@code BitSet} if {@code pos2 > size}.
-     * 
+     *
      * @param pos1
-     *            beginning position.
+     *            inclusive beginning position.
      * @param pos2
-     *            ending position.
+     *            exclusive ending position.
      * @throws IndexOutOfBoundsException
      *             if {@code pos1} or {@code pos2} is negative, or if
      *             {@code pos2} is smaller than {@code pos1}.
      * @see #set(int)
-     * @since Android 1.0
      */
     public void set(int pos1, int pos2) {
-        if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
-            if (pos1 == pos2) {
-                return;
-            }
-            if (pos2 >= bits.length * ELM_SIZE) {
-                growBits(pos2);
-            }
-
-            int idx1 = pos1 / ELM_SIZE;
-            int idx2 = (pos2 - 1) / ELM_SIZE;
-            long factor1 = (~0L) << (pos1 % ELM_SIZE);
-            long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
-
-            if (idx1 == idx2) {
-                bits[idx1] |= (factor1 & factor2);
-            } else {
-                bits[idx1] |= factor1;
-                bits[idx2] |= factor2;
-                for (int i = idx1 + 1; i < idx2; i++) {
-                    bits[i] |= (~0L);
-                }
-            }
-        } else {
+        if (pos1 < 0 || pos2 < 0 || pos2 < pos1) {
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        if (pos1 == pos2) {
+            return;
+        }
+        int len2 = ((pos2 - 1) >> OFFSET) + 1;
+        if (len2 > bits.length) {
+            growLength(len2);
+        }
+
+        int idx1 = pos1 >> OFFSET;
+        int idx2 = (pos2 - 1) >> OFFSET;
+        long factor1 = (~0L) << (pos1 & RIGHT_BITS);
+        long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS));
+
+        if (idx1 == idx2) {
+            bits[idx1] |= (factor1 & factor2);
+        } else {
+            bits[idx1] |= factor1;
+            bits[idx2] |= factor2;
+            for (int i = idx1 + 1; i < idx2; i++) {
+                bits[i] |= (~0L);
+            }
+        }
+        if (idx2 + 1 > actualArrayLength) {
+            actualArrayLength = idx2 + 1;
+            isLengthActual = true;
+        }
+        needClear();
+    }
+
+    private void needClear() {
+        this.needClear = true;
     }
 
     /**
      * Sets the bits starting from {@code pos1} to {@code pos2} to the given
      * {@code val}. Grows the {@code BitSet} if {@code pos2 > size}.
-     * 
+     *
      * @param pos1
-     *            beginning position.
+     *            inclusive beginning position.
      * @param pos2
-     *            ending position.
+     *            exclusive ending position.
      * @param val
      *            value to set these bits.
      * @throws IndexOutOfBoundsException
      *             if {@code pos1} or {@code pos2} is negative, or if
      *             {@code pos2} is smaller than {@code pos1}.
      * @see #set(int,int)
-     * @since Android 1.0
      */
     public void set(int pos1, int pos2, boolean val) {
         if (val) {
@@ -403,159 +449,183 @@
 
     /**
      * Clears all the bits in this {@code BitSet}.
-     * 
+     *
      * @see #clear(int)
      * @see #clear(int, int)
-     * @since Android 1.0
      */
     public void clear() {
-        for (int i = 0; i < bits.length; i++) {
-            bits[i] = 0L;
+        if (needClear) {
+            for (int i = 0; i < bits.length; i++) {
+                bits[i] = 0L;
+            }
+            actualArrayLength = 0;
+            isLengthActual = true;
+            needClear = false;
         }
     }
 
     /**
      * Clears the bit at index {@code pos}. Grows the {@code BitSet} if
      * {@code pos > size}.
-     * 
+     *
      * @param pos
      *            the index of the bit to clear.
      * @throws IndexOutOfBoundsException
      *             if {@code pos} is negative.
      * @see #clear(int, int)
-     * @since Android 1.0
      */
     public void clear(int pos) {
-        if (pos >= 0) {
-            if (pos < bits.length * ELM_SIZE) {
-                bits[pos / ELM_SIZE] &= ~(1L << (pos % ELM_SIZE));
-            }
-        } else {
+        if (pos < 0) {
             // Negative index specified
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        if (!needClear) {
+            return;
+        }
+        int arrayPos = pos >> OFFSET;
+        if (arrayPos < actualArrayLength) {
+            bits[arrayPos] &= ~(TWO_N_ARRAY[pos & RIGHT_BITS]);
+            if (bits[actualArrayLength - 1] == 0) {
+                isLengthActual = false;
+            }
+        }
     }
 
     /**
      * Clears the bits starting from {@code pos1} to {@code pos2}. Grows the
      * {@code BitSet} if {@code pos2 > size}.
-     * 
+     *
      * @param pos1
-     *            beginning position.
+     *            inclusive beginning position.
      * @param pos2
-     *            ending position.
+     *            exclusive ending position.
      * @throws IndexOutOfBoundsException
      *             if {@code pos1} or {@code pos2} is negative, or if
      *             {@code pos2} is smaller than {@code pos1}.
      * @see #clear(int)
-     * @since Android 1.0
      */
     public void clear(int pos1, int pos2) {
-        if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
-            int last = (bits.length * ELM_SIZE);
-            if (pos1 >= last || pos1 == pos2) {
-                return;
-            }
-            if (pos2 > last) {
-                pos2 = last;
-            }
-
-            int idx1 = pos1 / ELM_SIZE;
-            int idx2 = (pos2 - 1) / ELM_SIZE;
-            long factor1 = (~0L) << (pos1 % ELM_SIZE);
-            long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
-
-            if (idx1 == idx2) {
-                bits[idx1] &= ~(factor1 & factor2);
-            } else {
-                bits[idx1] &= ~factor1;
-                bits[idx2] &= ~factor2;
-                for (int i = idx1 + 1; i < idx2; i++) {
-                    bits[i] = 0L;
-                }
-            }
-        } else {
+        if (pos1 < 0 || pos2 < 0 || pos2 < pos1) {
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        if (!needClear) {
+            return;
+        }
+        int last = (actualArrayLength << OFFSET);
+        if (pos1 >= last || pos1 == pos2) {
+            return;
+        }
+        if (pos2 > last) {
+            pos2 = last;
+        }
+
+        int idx1 = pos1 >> OFFSET;
+        int idx2 = (pos2 - 1) >> OFFSET;
+        long factor1 = (~0L) << (pos1 & RIGHT_BITS);
+        long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS));
+
+        if (idx1 == idx2) {
+            bits[idx1] &= ~(factor1 & factor2);
+        } else {
+            bits[idx1] &= ~factor1;
+            bits[idx2] &= ~factor2;
+            for (int i = idx1 + 1; i < idx2; i++) {
+                bits[i] = 0L;
+            }
+        }
+        if ((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0)) {
+            isLengthActual = false;
+        }
     }
 
     /**
      * Flips the bit at index {@code pos}. Grows the {@code BitSet} if
      * {@code pos > size}.
-     * 
+     *
      * @param pos
      *            the index of the bit to flip.
      * @throws IndexOutOfBoundsException
      *             if {@code pos} is negative.
      * @see #flip(int, int)
-     * @since Android 1.0
      */
     public void flip(int pos) {
-        if (pos >= 0) {
-            if (pos >= bits.length * ELM_SIZE) {
-                growBits(pos);
-            }
-            bits[pos / ELM_SIZE] ^= 1L << (pos % ELM_SIZE);
-        } else {
+        if (pos < 0) {
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        int len = (pos >> OFFSET) + 1;
+        if (len > bits.length) {
+            growLength(len);
+        }
+        bits[len - 1] ^= TWO_N_ARRAY[pos & RIGHT_BITS];
+        if (len > actualArrayLength) {
+            actualArrayLength = len;
+        }
+        isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0));
+        needClear();
     }
 
     /**
      * Flips the bits starting from {@code pos1} to {@code pos2}. Grows the
      * {@code BitSet} if {@code pos2 > size}.
-     * 
+     *
      * @param pos1
-     *            beginning position.
+     *            inclusive beginning position.
      * @param pos2
-     *            ending position.
+     *            exclusive ending position.
      * @throws IndexOutOfBoundsException
      *             if {@code pos1} or {@code pos2} is negative, or if
      *             {@code pos2} is smaller than {@code pos1}.
      * @see #flip(int)
-     * @since Android 1.0
      */
     public void flip(int pos1, int pos2) {
-        if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
-            if (pos1 == pos2) {
-                return;
-            }
-            if (pos2 >= bits.length * ELM_SIZE) {
-                growBits(pos2);
-            }
-
-            int idx1 = pos1 / ELM_SIZE;
-            int idx2 = (pos2 - 1) / ELM_SIZE;
-            long factor1 = (~0L) << (pos1 % ELM_SIZE);
-            long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
-
-            if (idx1 == idx2) {
-                bits[idx1] ^= (factor1 & factor2);
-            } else {
-                bits[idx1] ^= factor1;
-                bits[idx2] ^= factor2;
-                for (int i = idx1 + 1; i < idx2; i++) {
-                    bits[i] ^= (~0L);
-                }
-            }
-        } else {
+        if (pos1 < 0 || pos2 < 0 || pos2 < pos1) {
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        if (pos1 == pos2) {
+            return;
+        }
+        int len2 = ((pos2 - 1) >> OFFSET) + 1;
+        if (len2 > bits.length) {
+            growLength(len2);
+        }
+
+        int idx1 = pos1 >> OFFSET;
+        int idx2 = (pos2 - 1) >> OFFSET;
+        long factor1 = (~0L) << (pos1 & RIGHT_BITS);
+        long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS));
+
+        if (idx1 == idx2) {
+            bits[idx1] ^= (factor1 & factor2);
+        } else {
+            bits[idx1] ^= factor1;
+            bits[idx2] ^= factor2;
+            for (int i = idx1 + 1; i < idx2; i++) {
+                bits[i] ^= (~0L);
+            }
+        }
+        if (len2 > actualArrayLength) {
+            actualArrayLength = len2;
+        }
+        isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0));
+        needClear();
     }
 
     /**
      * Checks if these two {@code BitSet}s have at least one bit set to true in the same
      * position.
-     * 
+     *
      * @param bs
      *            {@code BitSet} used to calculate the intersection.
      * @return {@code true} if bs intersects with this {@code BitSet},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean intersects(BitSet bs) {
         long[] bsBits = bs.bits;
-        int length1 = bits.length, length2 = bsBits.length;
+        int length1 = actualArrayLength, length2 = bs.actualArrayLength;
 
         if (length1 <= length2) {
             for (int i = 0; i < length1; i++) {
@@ -575,19 +645,20 @@
     }
 
     /**
-     * Performs the logical AND of this {@code BitSet} with another 
+     * Performs the logical AND of this {@code BitSet} with another
      * {@code BitSet}. The values of this {@code BitSet} are changed accordingly.
-     * 
+     *
      * @param bs
      *            {@code BitSet} to AND with.
      * @see #or
      * @see #xor
-     * @since Android 1.0
      */
-
     public void and(BitSet bs) {
         long[] bsBits = bs.bits;
-        int length1 = bits.length, length2 = bsBits.length;
+        if (!needClear) {
+            return;
+        }
+        int length1 = actualArrayLength, length2 = bs.actualArrayLength;
         if (length1 <= length2) {
             for (int i = 0; i < length1; i++) {
                 bits[i] &= bsBits[i];
@@ -599,109 +670,151 @@
             for (int i = length2; i < length1; i++) {
                 bits[i] = 0;
             }
+            actualArrayLength = length2;
         }
+        isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0));
     }
 
     /**
      * Clears all bits in the receiver which are also set in the parameter
      * {@code BitSet}. The values of this {@code BitSet} are changed accordingly.
-     * 
+     *
      * @param bs
      *            {@code BitSet} to ANDNOT with.
-     * @since Android 1.0
      */
     public void andNot(BitSet bs) {
         long[] bsBits = bs.bits;
-        int range = bits.length < bsBits.length ? bits.length : bsBits.length;
+        if (!needClear) {
+            return;
+        }
+        int range = actualArrayLength < bs.actualArrayLength ? actualArrayLength
+                : bs.actualArrayLength;
         for (int i = 0; i < range; i++) {
             bits[i] &= ~bsBits[i];
         }
+
+        if (actualArrayLength < range) {
+            actualArrayLength = range;
+        }
+        isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0));
     }
 
     /**
      * Performs the logical OR of this {@code BitSet} with another {@code BitSet}.
      * The values of this {@code BitSet} are changed accordingly.
-     * 
+     *
      * @param bs
      *            {@code BitSet} to OR with.
      * @see #xor
      * @see #and
-     * @since Android 1.0
      */
     public void or(BitSet bs) {
-        int nbits = bs.length();
-        int length = nbits / ELM_SIZE + (nbits % ELM_SIZE > 0 ? 1 : 0);
-        if (length > bits.length) {
-            growBits(nbits - 1);
+        int bsActualLen = bs.getActualArrayLength();
+        if (bsActualLen > bits.length) {
+            long[] tempBits = new long[bsActualLen];
+            System.arraycopy(bs.bits, 0, tempBits, 0, bs.actualArrayLength);
+            for (int i = 0; i < actualArrayLength; i++) {
+                tempBits[i] |= bits[i];
+            }
+            bits = tempBits;
+            actualArrayLength = bsActualLen;
+            isLengthActual = true;
+        } else {
+            long[] bsBits = bs.bits;
+            for (int i = 0; i < bsActualLen; i++) {
+                bits[i] |= bsBits[i];
+            }
+            if (bsActualLen > actualArrayLength) {
+                actualArrayLength = bsActualLen;
+                isLengthActual = true;
+            }
         }
-        long[] bsBits = bs.bits;
-        for (int i = 0; i < length; i++) {
-            bits[i] |= bsBits[i];
-        }
+        needClear();
     }
 
     /**
      * Performs the logical XOR of this {@code BitSet} with another {@code BitSet}.
      * The values of this {@code BitSet} are changed accordingly.
-     * 
+     *
      * @param bs
      *            {@code BitSet} to XOR with.
      * @see #or
      * @see #and
-     * @since Android 1.0
      */
     public void xor(BitSet bs) {
-        int nbits = bs.length();
-        int length = nbits / ELM_SIZE + (nbits % ELM_SIZE > 0 ? 1 : 0);
-        if (length > bits.length) {
-            growBits(nbits - 1);
+        int bsActualLen = bs.getActualArrayLength();
+        if (bsActualLen > bits.length) {
+            long[] tempBits = new long[bsActualLen];
+            System.arraycopy(bs.bits, 0, tempBits, 0, bs.actualArrayLength);
+            for (int i = 0; i < actualArrayLength; i++) {
+                tempBits[i] ^= bits[i];
+            }
+            bits = tempBits;
+            actualArrayLength = bsActualLen;
+            isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0));
+        } else {
+            long[] bsBits = bs.bits;
+            for (int i = 0; i < bsActualLen; i++) {
+                bits[i] ^= bsBits[i];
+            }
+            if (bsActualLen > actualArrayLength) {
+                actualArrayLength = bsActualLen;
+                isLengthActual = true;
+            }
         }
-        long[] bsBits = bs.bits;
-        for (int i = 0; i < length; i++) {
-            bits[i] ^= bsBits[i];
-        }
-
+        needClear();
     }
 
     /**
      * Returns the number of bits this {@code BitSet} has.
-     * 
+     *
      * @return the number of bits contained in this {@code BitSet}.
      * @see #length
-     * @since Android 1.0
      */
     public int size() {
-        return bits.length * ELM_SIZE;
+        return bits.length << OFFSET;
     }
 
     /**
      * Returns the number of bits up to and including the highest bit set.
-     * 
+     *
      * @return the length of the {@code BitSet}.
-     * @since Android 1.0
      */
     public int length() {
-        int idx = bits.length - 1;
+        int idx = actualArrayLength - 1;
         while (idx >= 0 && bits[idx] == 0) {
             --idx;
         }
+        actualArrayLength = idx + 1;
         if (idx == -1) {
             return 0;
         }
         int i = ELM_SIZE - 1;
         long val = bits[idx];
-        while ((val & (1L << i)) == 0 && i > 0) {
+        while ((val & (TWO_N_ARRAY[i])) == 0 && i > 0) {
             i--;
         }
-        return idx * ELM_SIZE + i + 1;
+        return (idx << OFFSET) + i + 1;
+    }
+
+    private final int getActualArrayLength() {
+        if (isLengthActual) {
+            return actualArrayLength;
+        }
+        int idx = actualArrayLength - 1;
+        while (idx >= 0 && bits[idx] == 0) {
+            --idx;
+        }
+        actualArrayLength = idx + 1;
+        isLengthActual = true;
+        return actualArrayLength;
     }
 
     /**
      * Returns a string containing a concise, human-readable description of the
      * receiver.
-     * 
+     *
      * @return a comma delimited list of the indices of all bits that are set.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -715,7 +828,7 @@
                 continue;
             }
             for (int j = 0; j < ELM_SIZE; j++) {
-                if (((bits[i] & (1L << j)) != 0)) {
+                if (((bits[i] & (TWO_N_ARRAY[j])) != 0)) {
                     if (comma) {
                         sb.append(", "); //$NON-NLS-1$
                     }
@@ -731,131 +844,152 @@
 
     /**
      * Returns the position of the first bit that is {@code true} on or after {@code pos}.
-     * 
+     *
      * @param pos
      *            the starting position (inclusive).
      * @return -1 if there is no bits that are set to {@code true} on or after {@code pos}.
-     * @since Android 1.0
      */
     public int nextSetBit(int pos) {
-        if (pos >= 0) {
-            if (pos >= bits.length * ELM_SIZE) {
-                return -1;
-            }
+        if (pos < 0) {
+            throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+        }
 
-            int idx = pos / ELM_SIZE;
-            // first check in the same bit set element
-            if (bits[idx] != 0L) {
-                for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) {
-                    if (((bits[idx] & (1L << j)) != 0)) {
-                        return idx * ELM_SIZE + j;
-                    }
-                }
-
-            }
-            idx++;
-            while (idx < bits.length && bits[idx] == 0L) {
-                idx++;
-            }
-            if (idx == bits.length) {
-                return -1;
-            }
-
-            // we know for sure there is a bit set to true in this element
-            // since the bitset value is not 0L
-            for (int j = 0; j < ELM_SIZE; j++) {
-                if (((bits[idx] & (1L << j)) != 0)) {
-                    return idx * ELM_SIZE + j;
-                }
-            }
-
+        if (pos >= actualArrayLength << OFFSET) {
             return -1;
         }
-        throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+
+        int idx = pos >> OFFSET;
+        // first check in the same bit set element
+        if (bits[idx] != 0L) {
+            for (int j = pos & RIGHT_BITS; j < ELM_SIZE; j++) {
+                if (((bits[idx] & (TWO_N_ARRAY[j])) != 0)) {
+                    return (idx << OFFSET) + j;
+                }
+            }
+
+        }
+        idx++;
+        while (idx < actualArrayLength && bits[idx] == 0L) {
+            idx++;
+        }
+        if (idx == actualArrayLength) {
+            return -1;
+        }
+
+        // we know for sure there is a bit set to true in this element
+        // since the bitset value is not 0L
+        for (int j = 0; j < ELM_SIZE; j++) {
+            if (((bits[idx] & (TWO_N_ARRAY[j])) != 0)) {
+                return (idx << OFFSET) + j;
+            }
+        }
+
+        return -1;
     }
 
     /**
      * Returns the position of the first bit that is {@code false} on or after {@code pos}.
-     * 
+     *
      * @param pos
      *            the starting position (inclusive).
      * @return the position of the next bit set to {@code false}, even if it is further
      *         than this {@code BitSet}'s size.
-     * @since Android 1.0
      */
     public int nextClearBit(int pos) {
-        if (pos >= 0) {
-            int bssize = bits.length * ELM_SIZE;
-            if (pos >= bssize) {
-                return pos;
-            }
+        if (pos < 0) {
+            throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+        }
 
-            int idx = pos / ELM_SIZE;
-            // first check in the same bit set element
-            if (bits[idx] != (~0L)) {
-                for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) {
-                    if (((bits[idx] & (1L << j)) == 0)) {
-                        return idx * ELM_SIZE + j;
-                    }
-                }
+        int length = actualArrayLength;
+        int bssize = length << OFFSET;
+        if (pos >= bssize) {
+            return pos;
+        }
 
-            }
-            idx++;
-            while (idx < bits.length && bits[idx] == (~0L)) {
-                idx++;
-            }
-            if (idx == bits.length) {
-                return bssize;
-            }
-
-            // we know for sure there is a bit set to true in this element
-            // since the bitset value is not 0L
-            for (int j = 0; j < ELM_SIZE; j++) {
-                if (((bits[idx] & (1L << j)) == 0)) {
+        int idx = pos >> OFFSET;
+        // first check in the same bit set element
+        if (bits[idx] != (~0L)) {
+            for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) {
+                if (((bits[idx] & (TWO_N_ARRAY[j])) == 0)) {
                     return idx * ELM_SIZE + j;
                 }
             }
-
+        }
+        idx++;
+        while (idx < length && bits[idx] == (~0L)) {
+            idx++;
+        }
+        if (idx == length) {
             return bssize;
         }
-        throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+
+        // we know for sure there is a bit set to true in this element
+        // since the bitset value is not 0L
+        for (int j = 0; j < ELM_SIZE; j++) {
+            if (((bits[idx] & (TWO_N_ARRAY[j])) == 0)) {
+                return (idx << OFFSET) + j;
+            }
+        }
+
+        return bssize;
     }
 
     /**
      * Returns true if all the bits in this {@code BitSet} are set to false.
-     * 
+     *
      * @return {@code true} if the {@code BitSet} is empty,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isEmpty() {
-        for (int idx = 0; idx < bits.length; idx++) {
+        if (!needClear) {
+            return true;
+        }
+        int length = bits.length;
+        for (int idx = 0; idx < length; idx++) {
             if (bits[idx] != 0L) {
                 return false;
             }
         }
-
         return true;
     }
 
     /**
      * Returns the number of bits that are {@code true} in this {@code BitSet}.
-     * 
+     *
      * @return the number of {@code true} bits in the set.
-     * @since Android 1.0
      */
     public int cardinality() {
+        if (!needClear) {
+            return 0;
+        }
         int count = 0;
-        for (int idx = 0; idx < bits.length; idx++) {
-            long temp = bits[idx];
-            if (temp != 0L) {
-                for (int i = 0; i < ELM_SIZE; i++) {
-                    if ((temp & (1L << i)) != 0L) {
-                        count++;
-                    }
-                }
-            }
+        int length = bits.length;
+        // FIXME: need to test performance, if still not satisfied, change it to
+        // 256-bits table based
+        for (int idx = 0; idx < length; idx++) {
+            count += pop(bits[idx] & 0xffffffffL);
+            count += pop(bits[idx] >>> 32);
         }
         return count;
     }
+
+    private final int pop(long x) {
+        // BEGIN android-note
+        // delegate to Integer.bitCount(i); consider using native code
+        // END android-note
+        x = x - ((x >>> 1) & 0x55555555);
+        x = (x & 0x33333333) + ((x >>> 2) & 0x33333333);
+        x = (x + (x >>> 4)) & 0x0f0f0f0f;
+        x = x + (x >>> 8);
+        x = x + (x >>> 16);
+        return (int) x & 0x0000003f;
+    }
+
+    private void readObject(ObjectInputStream ois) throws IOException,
+            ClassNotFoundException {
+        ois.defaultReadObject();
+        this.isLengthActual = false;
+        this.actualArrayLength = bits.length;
+        this.needClear = this.getActualArrayLength() != 0;
+    }
 }
diff --git a/luni/src/main/java/java/util/Calendar.java b/luni/src/main/java/java/util/Calendar.java
index 98840b2..088347d 100644
--- a/luni/src/main/java/java/util/Calendar.java
+++ b/luni/src/main/java/java/util/Calendar.java
@@ -14,27 +14,15 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2008, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamField;
 import java.io.Serializable;
 
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 /**
  * {@code Calendar} is an abstract base class for converting between a
  * {@code Date} object and a set of integer fields such as
@@ -42,22 +30,22 @@
  * {@code HOUR}, and so on. (A {@code Date} object represents a
  * specific instant in time with millisecond precision. See {@link Date} for
  * information about the {@code Date} class.)
- * 
+ *
  * <p>
  * Subclasses of {@code Calendar} interpret a {@code Date}
  * according to the rules of a specific calendar system.
- * 
+ *
  * <p>
  * Like other locale-sensitive classes, {@code Calendar} provides a class
  * method, {@code getInstance}, for getting a default instance of
  * this class for general use. {@code Calendar}'s {@code getInstance} method
  * returns a calendar whose locale is based on system settings and whose time fields
  * have been initialized with the current date and time: <blockquote>
- * 
+ *
  * <pre>Calendar rightNow = Calendar.getInstance()</pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * <p>
  * A {@code Calendar} object can produce all the time field values needed
  * to implement the date-time formatting for a particular language and calendar
@@ -68,7 +56,7 @@
  * Other values are defined by the concrete subclass, such as {@code ERA}
  * and {@code YEAR}. See individual field documentation and subclass
  * documentation for details.
- * 
+ *
  * <p>
  * When a {@code Calendar} is <em>lenient</em>, it accepts a wider
  * range of field values than it produces. For example, a lenient
@@ -79,14 +67,14 @@
  * by {@code get()}, they normalize them. For example, a
  * {@code GregorianCalendar} always produces {@code DAY_OF_MONTH}
  * values between 1 and the length of the month.
- * 
+ *
  * <p>
  * {@code Calendar} defines a locale-specific seven day week using two
  * parameters: the first day of the week and the minimal days in first week
  * (from 1 to 7). These numbers are taken from the locale resource data when a
  * {@code Calendar} is constructed. They may also be specified explicitly
  * through the API.
- * 
+ *
  * <p>
  * When setting or getting the {@code WEEK_OF_MONTH} or
  * {@code WEEK_OF_YEAR} fields, {@code Calendar} must determine
@@ -99,76 +87,74 @@
  * be different. For example, a specific {@code Calendar} subclass may
  * designate the week before week 1 of a year as week <em>n</em> of the
  * previous year.
- * 
+ *
  * <p>
  * When computing a {@code Date} from time fields, two special
  * circumstances may arise: there may be insufficient information to compute the
  * {@code Date} (such as only year and month but no day in the month), or
  * there may be inconsistent information (such as "Tuesday, July 15, 1996" --
  * July 15, 1996 is actually a Monday).
- * 
+ *
  * <p>
  * <strong>Insufficient information.</strong> The calendar will use default
  * information to specify the missing fields. This may vary by calendar; for the
  * Gregorian calendar, the default for a field is the same as that of the start
  * of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
- * 
+ *
  * <p>
  * <strong>Inconsistent information.</strong> If fields conflict, the calendar
  * will give preference to fields set more recently. For example, when
  * determining the day, the calendar will look for one of the following
  * combinations of fields. The most recent combination, as determined by the
  * most recently set single field, will be used.
- * 
+ *
  * <blockquote>
- * 
+ *
  * <pre>
  * MONTH + DAY_OF_MONTH
  * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
  * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
  * DAY_OF_YEAR
  * DAY_OF_WEEK + WEEK_OF_YEAR</pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * For the time of day:
- * 
+ *
  * <blockquote>
- * 
+ *
  * <pre>
  * HOUR_OF_DAY
  * AM_PM + HOUR</pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * <p>
  * <strong>Note:</strong> There are certain possible ambiguities in
  * interpretation of certain singular times, which are resolved in the following
  * ways:
  * <ol>
  * <li> 24:00:00 "belongs" to the following day. That is, 23:59 on Dec 31, 1969
- * &lt; 24:00 on Jan 1, 1970 &lt; 24:01:00 on Jan 1, 1970 form a sequence of 
- * three consecutive minutes in time. 
- * 
+ * &lt; 24:00 on Jan 1, 1970 &lt; 24:01:00 on Jan 1, 1970 form a sequence of
+ * three consecutive minutes in time.
+ *
  * <li> Although historically not precise, midnight also belongs to "am", and
  * noon belongs to "pm", so on the same day, we have 12:00 am (midnight) &lt; 12:01 am,
  * and 12:00 pm (noon) &lt; 12:01 pm
  * </ol>
- * 
+ *
  * <p>
  * The date or time format strings are not part of the definition of a calendar,
  * as those must be modifiable or overridable by the user at runtime. Use
  * {@link java.text.DateFormat} to format dates.
- * 
+ *
  * <p>
  * <strong>Field manipulation methods</strong>
- * </p>
- * 
+ *
  * <p>
  * {@code Calendar} fields can be changed using three methods:
  * {@code set()}, {@code add()}, and {@code roll()}.
- * </p>
- * 
+ *
  * <p>
  * <strong>{@code set(f, value)}</strong> changes field {@code f}
  * to {@code value}. In addition, it sets an internal member variable to
@@ -182,8 +168,7 @@
  * the calendar system. In addition, {@code get(f)} will not necessarily
  * return {@code value} after the fields have been recomputed. The
  * specifics are determined by the concrete calendar class.
- * </p>
- * 
+ *
  * <p>
  * <em>Example</em>: Consider a {@code GregorianCalendar} originally
  * set to August 31, 1999. Calling <code>set(Calendar.MONTH,
@@ -193,15 +178,13 @@
  * then called. However, a call to {@code set(Calendar.DAY_OF_MONTH, 30)}
  * before the call to {@code getTime()} sets the calendar to September
  * 30, 1999, since no recomputation occurs after {@code set()} itself.
- * </p>
- * 
+ *
  * <p>
  * <strong>{@code add(f, delta)}</strong> adds {@code delta} to
  * field {@code f}. This is equivalent to calling <code>set(f,
  * get(f) + delta)</code>
  * with two adjustments:
- * </p>
- * 
+ *
  * <blockquote>
  * <p>
  * <strong>Add rule 1</strong>. The value of field {@code f} after the
@@ -210,8 +193,7 @@
  * {@code f}. Overflow occurs when a field value exceeds its range and,
  * as a result, the next larger field is incremented or decremented and the
  * field value is adjusted back into its range.
- * </p>
- * 
+ *
  * <p>
  * <strong>Add rule 2</strong>. If a smaller field is expected to be invariant,
  * but &nbsp; it is impossible for it to be equal to its prior value because of
@@ -221,14 +203,12 @@
  * smaller field than {@code DAY_OF_MONTH}. No adjustment is made to
  * smaller fields that are not expected to be invariant. The calendar system
  * determines what fields are expected to be invariant.
- * </p>
  * </blockquote>
- * 
+ *
  * <p>
  * In addition, unlike {@code set()}, {@code add()} forces an
  * immediate recomputation of the calendar's milliseconds and all fields.
- * </p>
- * 
+ *
  * <p>
  * <em>Example</em>: Consider a {@code GregorianCalendar} originally
  * set to August 31, 1999. Calling {@code add(Calendar.MONTH, 13)} sets
@@ -240,22 +220,19 @@
  * Although it is a smaller field, {@code DAY_OF_WEEK} is not adjusted by
  * rule 2, since it is expected to change when the month changes in a
  * {@code GregorianCalendar}.
- * </p>
- * 
+ *
  * <p>
  * <strong>{@code roll(f, delta)}</strong> adds {@code delta} to
  * field {@code f} without changing larger fields. This is equivalent to
  * calling {@code add(f, delta)} with the following adjustment:
- * </p>
- * 
+ *
  * <blockquote>
  * <p>
  * <strong>Roll rule</strong>. Larger fields are unchanged after the call. A
  * larger field represents a larger unit of time. {@code DAY_OF_MONTH} is
  * a larger field than {@code HOUR}.
- * </p>
  * </blockquote>
- * 
+ *
  * <p>
  * <em>Example</em>: Consider a {@code GregorianCalendar} originally
  * set to August 31, 1999. Calling <code>roll(Calendar.MONTH,
@@ -265,8 +242,7 @@
  * the {@code DAY_OF_MONTH} cannot be 31 in the month April. Add rule 2
  * sets it to the closest possible value, 30. Finally, the <strong>roll rule</strong>
  * maintains the {@code YEAR} field value of 1999.
- * </p>
- * 
+ *
  * <p>
  * <em>Example</em>: Consider a {@code GregorianCalendar} originally
  * set to Sunday June 6, 1999. Calling
@@ -279,8 +255,7 @@
  * According to add rule 2, the {@code DAY_OF_WEEK}, an invariant when
  * changing the {@code WEEK_OF_MONTH}, is set to Tuesday, the closest
  * possible value to Sunday (where Sunday is the first day of the week).
- * </p>
- * 
+ *
  * <p>
  * <strong>Usage model</strong>. To motivate the behavior of {@code add()}
  * and {@code roll()}, consider a user interface component with
@@ -294,8 +269,7 @@
  * {@code add()} or {@code roll()}, depending on whether larger
  * fields should be affected, the user interface can behave as most users will
  * intuitively expect.
- * </p>
- * 
+ *
  * <p>
  * <b>Note:</b> You should always use {@code roll} and {@code add} rather than
  * attempting to perform arithmetic operations directly on the fields of a
@@ -304,11 +278,10 @@
  * during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
  * methods will take this into account, while simple arithmetic manipulations
  * may give invalid results.
- * 
+ *
  * @see Date
  * @see GregorianCalendar
  * @see TimeZone
- * @since Android 1.0
  */
 public abstract class Calendar implements Serializable, Cloneable,
         Comparable<Calendar> {
@@ -318,38 +291,28 @@
     /**
      * Set to {@code true} when the calendar fields have been set from the time, set to
      * {@code false} when a field is changed and the fields must be recomputed.
-     * 
-     * @since Android 1.0
      */
     protected boolean areFieldsSet;
 
     /**
      * An integer array of calendar fields. The length is {@code FIELD_COUNT}.
-     * 
-     * @since Android 1.0
      */
     protected int[] fields;
 
     /**
      * A boolean array. Each element indicates if the corresponding field has
      * been set. The length is {@code FIELD_COUNT}.
-     * 
-     * @since Android 1.0
      */
     protected boolean[] isSet;
 
     /**
      * Set to {@code true} when the time has been set, set to {@code false} when a field is
      * changed and the time must be recomputed.
-     * 
-     * @since Android 1.0
      */
     protected boolean isTimeSet;
 
     /**
      * The time in milliseconds since January 1, 1970.
-     * 
-     * @since Android 1.0
      */
     protected long time;
 
@@ -365,100 +328,75 @@
 
     private TimeZone zone;
 
-    // BEGIN android-changed
     /**
      * Value of the {@code MONTH} field indicating the first month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int JANUARY = 0;
 
     /**
      * Value of the {@code MONTH} field indicating the second month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int FEBRUARY = 1;
 
     /**
      * Value of the {@code MONTH} field indicating the third month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int MARCH = 2;
 
     /**
      * Value of the {@code MONTH} field indicating the fourth month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int APRIL = 3;
 
     /**
      * Value of the {@code MONTH} field indicating the fifth month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int MAY = 4;
 
     /**
      * Value of the {@code MONTH} field indicating the sixth month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int JUNE = 5;
 
     /**
      * Value of the {@code MONTH} field indicating the seventh month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int JULY = 6;
 
     /**
      * Value of the {@code MONTH} field indicating the eighth month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int AUGUST = 7;
 
     /**
      * Value of the {@code MONTH} field indicating the ninth month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int SEPTEMBER = 8;
 
     /**
      * Value of the {@code MONTH} field indicating the tenth month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int OCTOBER = 9;
 
     /**
      * Value of the {@code MONTH} field indicating the eleventh month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int NOVEMBER = 10;
 
     /**
      * Value of the {@code MONTH} field indicating the twelfth month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int DECEMBER = 11;
 
@@ -466,57 +404,41 @@
      * Value of the {@code MONTH} field indicating the thirteenth month
      * of the year. Although {@code GregorianCalendar} does not use this
      * value, lunar calendars do.
-     * 
-     * @since Android 1.0
      */
     public static final int UNDECIMBER = 12;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Sunday.
-     * 
-     * @since Android 1.0
      */
     public static final int SUNDAY = 1;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Monday.
-     * 
-     * @since Android 1.0
      */
     public static final int MONDAY = 2;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Tuesday.
-     * 
-     * @since Android 1.0
      */
     public static final int TUESDAY = 3;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Wednesday.
-     * 
-     * @since Android 1.0
      */
     public static final int WEDNESDAY = 4;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Thursday.
-     * 
-     * @since Android 1.0
      */
     public static final int THURSDAY = 5;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Friday.
-     * 
-     * @since Android 1.0
      */
     public static final int FRIDAY = 6;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Saturday.
-     * 
-     * @since Android 1.0
      */
     public static final int SATURDAY = 7;
 
@@ -524,19 +446,15 @@
      * Field number for {@code get} and {@code set} indicating the
      * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific
      * value; see subclass documentation.
-     * 
+     *
      * @see GregorianCalendar#AD
      * @see GregorianCalendar#BC
-     * 
-     * @since Android 1.0
      */
     public static final int ERA = 0;
 
     /**
      * Field number for {@code get} and {@code set} indicating the
      * year. This is a calendar-specific value; see subclass documentation.
-     * 
-     * @since Android 1.0
      */
     public static final int YEAR = 1;
 
@@ -545,7 +463,7 @@
      * month. This is a calendar-specific value. The first month of the year is
      * {@code JANUARY}; the last depends on the number of months in a
      * year.
-     * 
+     *
      * @see #JANUARY
      * @see #FEBRUARY
      * @see #MARCH
@@ -559,8 +477,6 @@
      * @see #NOVEMBER
      * @see #DECEMBER
      * @see #UNDECIMBER
-     * 
-     * @since Android 1.0
      */
     public static final int MONTH = 2;
 
@@ -571,11 +487,9 @@
      * {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses
      * define the value of {@code WEEK_OF_YEAR} for days before the first
      * week of the year.
-     * 
+     *
      * @see #getFirstDayOfWeek
      * @see #getMinimalDaysInFirstWeek
-     * 
-     * @since Android 1.0
      */
     public static final int WEEK_OF_YEAR = 3;
 
@@ -586,11 +500,9 @@
      * {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses
      * define the value of {@code WEEK_OF_MONTH} for days before the
      * first week of the month.
-     * 
+     *
      * @see #getFirstDayOfWeek
      * @see #getMinimalDaysInFirstWeek
-     * 
-     * @since Android 1.0
      */
     public static final int WEEK_OF_MONTH = 4;
 
@@ -598,10 +510,8 @@
      * Field number for {@code get} and {@code set} indicating the
      * day of the month. This is a synonym for {@code DAY_OF_MONTH}. The
      * first day of the month has value 1.
-     * 
+     *
      * @see #DAY_OF_MONTH
-     * 
-     * @since Android 1.0
      */
     public static final int DATE = 5;
 
@@ -609,10 +519,8 @@
      * Field number for {@code get} and {@code set} indicating the
      * day of the month. This is a synonym for {@code DATE}. The first
      * day of the month has value 1.
-     * 
+     *
      * @see #DATE
-     * 
-     * @since Android 1.0
      */
     public static final int DAY_OF_MONTH = 5;
 
@@ -620,8 +528,6 @@
      * Field number for {@code get} and {@code set} indicating the
      * day number within the current year. The first day of the year has value
      * 1.
-     * 
-     * @since Android 1.0
      */
     public static final int DAY_OF_YEAR = 6;
 
@@ -631,7 +537,7 @@
      * {@code MONDAY}, {@code TUESDAY}, {@code WEDNESDAY},
      * {@code THURSDAY}, {@code FRIDAY}, and
      * {@code SATURDAY}.
-     * 
+     *
      * @see #SUNDAY
      * @see #MONDAY
      * @see #TUESDAY
@@ -639,8 +545,6 @@
      * @see #THURSDAY
      * @see #FRIDAY
      * @see #SATURDAY
-     * 
-     * @since Android 1.0
      */
     public static final int DAY_OF_WEEK = 7;
 
@@ -664,11 +568,9 @@
      * within the month than positive values. For example, if a month has 31
      * days, {@code DAY_OF_WEEK_IN_MONTH -1} will overlap
      * {@code DAY_OF_WEEK_IN_MONTH 5} and the end of {@code 4}.
-     * 
+     *
      * @see #DAY_OF_WEEK
      * @see #WEEK_OF_MONTH
-     * 
-     * @since Android 1.0
      */
     public static final int DAY_OF_WEEK_IN_MONTH = 8;
 
@@ -676,12 +578,10 @@
      * Field number for {@code get} and {@code set} indicating
      * whether the {@code HOUR} is before or after noon. E.g., at
      * 10:04:15.250 PM the {@code AM_PM} is {@code PM}.
-     * 
+     *
      * @see #AM
      * @see #PM
      * @see #HOUR
-     * 
-     * @since Android 1.0
      */
     public static final int AM_PM = 9;
 
@@ -689,11 +589,9 @@
      * Field number for {@code get} and {@code set} indicating the
      * hour of the morning or afternoon. {@code HOUR} is used for the
      * 12-hour clock. E.g., at 10:04:15.250 PM the {@code HOUR} is 10.
-     * 
+     *
      * @see #AM_PM
      * @see #HOUR_OF_DAY
-     * 
-     * @since Android 1.0
      */
     public static final int HOUR = 10;
 
@@ -701,10 +599,8 @@
      * Field number for {@code get} and {@code set} indicating the
      * hour of the day. {@code HOUR_OF_DAY} is used for the 24-hour
      * clock. E.g., at 10:04:15.250 PM the {@code HOUR_OF_DAY} is 22.
-     * 
+     *
      * @see #HOUR
-     * 
-     * @since Android 1.0
      */
     public static final int HOUR_OF_DAY = 11;
 
@@ -712,8 +608,6 @@
      * Field number for {@code get} and {@code set} indicating the
      * minute within the hour. E.g., at 10:04:15.250 PM the {@code MINUTE}
      * is 4.
-     * 
-     * @since Android 1.0
      */
     public static final int MINUTE = 12;
 
@@ -721,8 +615,6 @@
      * Field number for {@code get} and {@code set} indicating the
      * second within the minute. E.g., at 10:04:15.250 PM the
      * {@code SECOND} is 15.
-     * 
-     * @since Android 1.0
      */
     public static final int SECOND = 13;
 
@@ -730,61 +622,46 @@
      * Field number for {@code get} and {@code set} indicating the
      * millisecond within the second. E.g., at 10:04:15.250 PM the
      * {@code MILLISECOND} is 250.
-     * 
-     * @since Android 1.0
      */
     public static final int MILLISECOND = 14;
 
     /**
      * Field number for {@code get} and {@code set} indicating the
      * raw offset from GMT in milliseconds.
-     * 
-     * @since Android 1.0
      */
     public static final int ZONE_OFFSET = 15;
 
     /**
      * Field number for {@code get} and {@code set} indicating the
      * daylight savings offset in milliseconds.
-     * 
-     * @since Android 1.0
      */
     public static final int DST_OFFSET = 16;
 
     /**
      * This is the total number of fields in this calendar.
-     * 
-     * @since Android 1.0
      */
     public static final int FIELD_COUNT = 17;
 
     /**
      * Value of the {@code AM_PM} field indicating the period of the day
      * from midnight to just before noon.
-     * 
-     * @since Android 1.0
      */
     public static final int AM = 0;
 
     /**
      * Value of the {@code AM_PM} field indicating the period of the day
      * from noon to just before midnight.
-     * 
-     * @since Android 1.0
      */
     public static final int PM = 1;
-    // END android-changed
 
     private static String[] fieldNames = { "ERA=", "YEAR=", "MONTH=", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-            "WEEK_OF_YEAR=", "WEEK_OF_MONTH=", "DAY_OF_MONTH=", "DAY_OF_YEAR=",  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-            "DAY_OF_WEEK=", "DAY_OF_WEEK_IN_MONTH=", "AM_PM=", "HOUR=",   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
+            "WEEK_OF_YEAR=", "WEEK_OF_MONTH=", "DAY_OF_MONTH=", "DAY_OF_YEAR=", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+            "DAY_OF_WEEK=", "DAY_OF_WEEK_IN_MONTH=", "AM_PM=", "HOUR=", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
             "HOUR_OF_DAY", "MINUTE=", "SECOND=", "MILLISECOND=", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
             "ZONE_OFFSET=", "DST_OFFSET=" }; //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Constructs a {@code Calendar} instance using the default {@code TimeZone} and {@code Locale}.
-     * 
-     * @since Android 1.0
      */
     protected Calendar() {
         this(TimeZone.getDefault(), Locale.getDefault());
@@ -800,30 +677,38 @@
 
     /**
      * Constructs a {@code Calendar} instance using the specified {@code TimeZone} and {@code Locale}.
-     * 
+     *
      * @param timezone
      *            the timezone.
      * @param locale
      *            the locale.
-     * 
-     * @since Android 1.0
      */
     protected Calendar(TimeZone timezone, Locale locale) {
         this(timezone);
+        // BEGIN android-changed
+        // com.ibm.icu.util.Calendar icuCalendar = com.ibm.icu.util.Calendar
+        //         .getInstance(com.ibm.icu.util.SimpleTimeZone
+        //                 .getTimeZone(timezone.getID()), locale);
+        // setFirstDayOfWeek(icuCalendar.getFirstDayOfWeek());
+        // setMinimalDaysInFirstWeek(icuCalendar.getMinimalDaysInFirstWeek());
         ResourceBundle bundle = Locale.getBundle("Locale", locale); //$NON-NLS-1$
         setFirstDayOfWeek(((Integer) bundle.getObject("First_Day")).intValue()); //$NON-NLS-1$
         setMinimalDaysInFirstWeek(((Integer) bundle.getObject("Minimal_Days")) //$NON-NLS-1$
                 .intValue());
+        // END android-changed
     }
 
+
     /**
      * Adds the specified amount to a {@code Calendar} field.
-     * 
+     *
      * @param field
      *            the {@code Calendar} field to modify.
      * @param value
      *            the amount to add to the field.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if {@code field} is {@code DST_OFFSET} or {@code
+     *                ZONE_OFFSET}.
      */
     abstract public void add(int field, int value);
 
@@ -831,11 +716,13 @@
      * Returns whether the {@code Date} specified by this {@code Calendar} instance is after the {@code Date}
      * specified by the parameter. The comparison is not dependent on the time
      * zones of the {@code Calendar}.
-     * 
+     *
      * @param calendar
      *            the {@code Calendar} instance to compare.
      * @return {@code true} when this Calendar is after calendar, {@code false} otherwise.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
+     *                from the current field values.
      */
     public boolean after(Object calendar) {
         if (!(calendar instanceof Calendar)) {
@@ -848,11 +735,13 @@
      * Returns whether the {@code Date} specified by this {@code Calendar} instance is before the
      * {@code Date} specified by the parameter. The comparison is not dependent on the
      * time zones of the {@code Calendar}.
-     * 
+     *
      * @param calendar
      *            the {@code Calendar} instance to compare.
      * @return {@code true} when this Calendar is before calendar, {@code false} otherwise.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
+     *                from the current field values.
      */
     public boolean before(Object calendar) {
         if (!(calendar instanceof Calendar)) {
@@ -864,8 +753,6 @@
     /**
      * Clears all of the fields of this {@code Calendar}. All fields are initialized to
      * zero.
-     * 
-     * @since Android 1.0
      */
     public final void clear() {
         for (int i = 0; i < FIELD_COUNT; i++) {
@@ -877,10 +764,9 @@
 
     /**
      * Clears the specified field to zero and sets the isSet flag to {@code false}.
-     * 
+     *
      * @param field
      *            the field to clear.
-     * @since Android 1.0
      */
     public final void clear(int field) {
         fields[field] = 0;
@@ -890,11 +776,10 @@
 
     /**
      * Returns a new {@code Calendar} with the same properties.
-     * 
+     *
      * @return a shallow copy of this {@code Calendar}.
-     * 
+     *
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -912,11 +797,10 @@
     /**
      * Computes the time from the fields if the time has not already been set.
      * Computes the fields from the time if the fields are not already set.
-     * 
-     * @exception IllegalArgumentException
-     *                when the time is not set and the time cannot be computed
+     *
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
      *                from the current field values.
-     * @since Android 1.0
      */
     protected void complete() {
         if (!isTimeSet) {
@@ -931,18 +815,15 @@
 
     /**
      * Computes the {@code Calendar} fields from {@code time}.
-     * 
-     * @since Android 1.0
      */
     protected abstract void computeFields();
 
     /**
      * Computes {@code time} from the Calendar fields.
-     * 
-     * @exception IllegalArgumentException
-     *                when the time cannot be computed from the current field
+     *
+     * @throws IllegalArgumentException
+     *                if the time cannot be computed from the current field
      *                values.
-     * @since Android 1.0
      */
     protected abstract void computeTime();
 
@@ -950,12 +831,11 @@
      * Compares the specified object to this {@code Calendar} and returns whether they are
      * equal. The object must be an instance of {@code Calendar} and have the same
      * properties.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the specified object is equal to this {@code Calendar}, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -977,18 +857,17 @@
     /**
      * Gets the value of the specified field after computing the field values by
      * calling {@code complete()} first.
-     * 
+     *
      * @param field
      *            the field to get.
      * @return the value of the specified field.
-     * 
-     * @exception IllegalArgumentException
-     *                when the fields are not set, the time is not set, and the
+     *
+     * @throws IllegalArgumentException
+     *                if the fields are not set, the time is not set, and the
      *                time cannot be computed from the current field values.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if the field is not inside the range of possible fields.
      *                The range is starting at 0 up to {@code FIELD_COUNT}.
-     * @since Android 1.0
      */
     public int get(int field) {
         complete();
@@ -997,11 +876,10 @@
 
     /**
      * Gets the maximum value of the specified field for the current date.
-     * 
+     *
      * @param field
      *            the field.
      * @return the maximum value of the specified field.
-     * @since Android 1.0
      */
     public int getActualMaximum(int field) {
         int value, next;
@@ -1023,11 +901,10 @@
 
     /**
      * Gets the minimum value of the specified field for the current date.
-     * 
+     *
      * @param field
      *            the field.
      * @return the minimum value of the specified field.
-     * @since Android 1.0
      */
     public int getActualMinimum(int field) {
         int value, next;
@@ -1049,9 +926,8 @@
 
     /**
      * Gets the list of installed {@code Locale}s which support {@code Calendar}.
-     * 
+     *
      * @return an array of {@code Locale}.
-     * @since Android 1.0
      */
     public static synchronized Locale[] getAvailableLocales() {
         return Locale.getAvailableLocales();
@@ -1059,9 +935,8 @@
 
     /**
      * Gets the first day of the week for this {@code Calendar}.
-     * 
+     *
      * @return the first day of the week.
-     * @since Android 1.0
      */
     public int getFirstDayOfWeek() {
         return firstDayOfWeek;
@@ -1071,21 +946,19 @@
      * Gets the greatest minimum value of the specified field. This is the
      * biggest value that {@code getActualMinimum} can return for any possible
      * time.
-     * 
+     *
      * @param field
      *            the field.
      * @return the greatest minimum value of the specified field.
-     * @since Android 1.0
      */
     abstract public int getGreatestMinimum(int field);
 
     /**
      * Constructs a new instance of the {@code Calendar} subclass appropriate for the
      * default {@code Locale}.
-     * 
+     *
      * @return a {@code Calendar} subclass instance set to the current date and time in
      *         the default {@code Timezone}.
-     * @since Android 1.0
      */
     public static synchronized Calendar getInstance() {
         return new GregorianCalendar();
@@ -1094,11 +967,10 @@
     /**
      * Constructs a new instance of the {@code Calendar} subclass appropriate for the
      * specified {@code Locale}.
-     * 
+     *
      * @param locale
      *            the locale to use.
      * @return a {@code Calendar} subclass instance set to the current date and time.
-     * @since Android 1.0
      */
     public static synchronized Calendar getInstance(Locale locale) {
         return new GregorianCalendar(locale);
@@ -1107,12 +979,11 @@
     /**
      * Constructs a new instance of the {@code Calendar} subclass appropriate for the
      * default {@code Locale}, using the specified {@code TimeZone}.
-     * 
+     *
      * @param timezone
      *            the {@code TimeZone} to use.
      * @return a {@code Calendar} subclass instance set to the current date and time in
      *         the specified timezone.
-     * @since Android 1.0
      */
     public static synchronized Calendar getInstance(TimeZone timezone) {
         return new GregorianCalendar(timezone);
@@ -1121,14 +992,13 @@
     /**
      * Constructs a new instance of the {@code Calendar} subclass appropriate for the
      * specified {@code Locale}.
-     * 
+     *
      * @param timezone
      *            the {@code TimeZone} to use.
      * @param locale
      *            the {@code Locale} to use.
      * @return a {@code Calendar} subclass instance set to the current date and time in
      *         the specified timezone.
-     * @since Android 1.0
      */
     public static synchronized Calendar getInstance(TimeZone timezone,
             Locale locale) {
@@ -1139,30 +1009,27 @@
      * Gets the smallest maximum value of the specified field. This is the
      * smallest value that {@code getActualMaximum()} can return for any
      * possible time.
-     * 
+     *
      * @param field
      *            the field number.
      * @return the smallest maximum value of the specified field.
-     * @since Android 1.0
      */
     abstract public int getLeastMaximum(int field);
 
     /**
      * Gets the greatest maximum value of the specified field. This returns the
      * biggest value that {@code get} can return for the specified field.
-     * 
+     *
      * @param field
      *            the field.
      * @return the greatest maximum value of the specified field.
-     * @since Android 1.0
      */
     abstract public int getMaximum(int field);
 
     /**
      * Gets the minimal days in the first week of the year.
-     * 
+     *
      * @return the minimal days in the first week of the year.
-     * @since Android 1.0
      */
     public int getMinimalDaysInFirstWeek() {
         return minimalDaysInFirstWeek;
@@ -1171,23 +1038,21 @@
     /**
      * Gets the smallest minimum value of the specified field. this returns the
      * smallest value thet {@code get} can return for the specified field.
-     * 
+     *
      * @param field
      *            the field number.
      * @return the smallest minimum value of the specified field.
-     * @since Android 1.0
      */
     abstract public int getMinimum(int field);
 
     /**
      * Gets the time of this {@code Calendar} as a {@code Date} object.
-     * 
+     *
      * @return a new {@code Date} initialized to the time of this {@code Calendar}.
-     * 
-     * @exception IllegalArgumentException
-     *                when the time is not set and the time cannot be computed
+     *
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
      *                from the current field values.
-     * @since Android 1.0
      */
     public final Date getTime() {
         return new Date(getTimeInMillis());
@@ -1195,13 +1060,12 @@
 
     /**
      * Computes the time from the fields if required and returns the time.
-     * 
+     *
      * @return the time of this {@code Calendar}.
-     * 
-     * @exception IllegalArgumentException
-     *                when the time is not set and the time cannot be computed
+     *
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
      *                from the current field values.
-     * @since Android 1.0
      */
     public long getTimeInMillis() {
         if (!isTimeSet) {
@@ -1213,9 +1077,8 @@
 
     /**
      * Gets the timezone of this {@code Calendar}.
-     * 
+     *
      * @return the {@code TimeZone} used by this {@code Calendar}.
-     * @since Android 1.0
      */
     public TimeZone getTimeZone() {
         return zone;
@@ -1224,11 +1087,10 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
-     * 
+     *
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -1238,11 +1100,10 @@
 
     /**
      * Gets the value of the specified field without recomputing.
-     * 
+     *
      * @param field
      *            the field.
      * @return the value of the specified field.
-     * @since Android 1.0
      */
     protected final int internalGet(int field) {
         return fields[field];
@@ -1251,9 +1112,8 @@
     /**
      * Returns if this {@code Calendar} accepts field values which are outside the valid
      * range for the field.
-     * 
+     *
      * @return {@code true} if this {@code Calendar} is lenient, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isLenient() {
         return lenient;
@@ -1261,11 +1121,10 @@
 
     /**
      * Returns whether the specified field is set.
-     * 
+     *
      * @param field
      *            a {@code Calendar} field number.
      * @return {@code true} if the specified field is set, {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean isSet(int field) {
         return isSet[field];
@@ -1276,12 +1135,11 @@
      * the field when it goes beyond the maximum or minimum value for the
      * current date. Other fields will be adjusted as required to maintain a
      * consistent date.
-     * 
+     *
      * @param field
      *            the field to roll.
      * @param value
      *            the amount to add.
-     * @since Android 1.0
      */
     public void roll(int field, int value) {
         boolean increment = value >= 0;
@@ -1296,23 +1154,21 @@
      * field when it goes beyond the maximum or minimum value for the current
      * date. Other fields will be adjusted as required to maintain a consistent
      * date.
-     * 
+     *
      * @param field
      *            the number indicating the field to roll.
      * @param increment
      *            {@code true} to increment the field, {@code false} to decrement.
-     * @since Android 1.0
      */
     abstract public void roll(int field, boolean increment);
 
     /**
      * Sets a field to the specified value.
-     * 
+     *
      * @param field
      *            the code indicating the {@code Calendar} field to modify.
      * @param value
      *            the value.
-     * @since Android 1.0
      */
     public void set(int field, int value) {
         fields[field] = value;
@@ -1332,14 +1188,13 @@
     /**
      * Sets the year, month and day of the month fields. Other fields are not
      * changed.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
      *            the month.
      * @param day
      *            the day of the month.
-     * @since Android 1.0
      */
     public final void set(int year, int month, int day) {
         set(YEAR, year);
@@ -1350,7 +1205,7 @@
     /**
      * Sets the year, month, day of the month, hour of day and minute fields.
      * Other fields are not changed.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
@@ -1361,7 +1216,6 @@
      *            the hour of day.
      * @param minute
      *            the minute.
-     * @since Android 1.0
      */
     public final void set(int year, int month, int day, int hourOfDay,
             int minute) {
@@ -1373,7 +1227,7 @@
     /**
      * Sets the year, month, day of the month, hour of day, minute and second
      * fields. Other fields are not changed.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
@@ -1386,7 +1240,6 @@
      *            the minute.
      * @param second
      *            the second.
-     * @since Android 1.0
      */
     public final void set(int year, int month, int day, int hourOfDay,
             int minute, int second) {
@@ -1396,10 +1249,9 @@
 
     /**
      * Sets the first day of the week for this {@code Calendar}.
-     * 
+     *
      * @param value
      *            a {@code Calendar} day of the week.
-     * @since Android 1.0
      */
     public void setFirstDayOfWeek(int value) {
         firstDayOfWeek = value;
@@ -1408,10 +1260,9 @@
     /**
      * Sets this {@code Calendar} to accept field values which are outside the valid
      * range for the field.
-     * 
+     *
      * @param value
      *            a boolean value.
-     * @since Android 1.0
      */
     public void setLenient(boolean value) {
         lenient = value;
@@ -1419,10 +1270,9 @@
 
     /**
      * Sets the minimal days in the first week of the year.
-     * 
+     *
      * @param value
      *            the minimal days in the first week of the year.
-     * @since Android 1.0
      */
     public void setMinimalDaysInFirstWeek(int value) {
         minimalDaysInFirstWeek = value;
@@ -1430,10 +1280,9 @@
 
     /**
      * Sets the time of this {@code Calendar}.
-     * 
+     *
      * @param date
      *            a {@code Date} object.
-     * @since Android 1.0
      */
     public final void setTime(Date date) {
         setTimeInMillis(date.getTime());
@@ -1441,43 +1290,45 @@
 
     /**
      * Sets the time of this {@code Calendar}.
-     * 
+     *
      * @param milliseconds
      *            the time as the number of milliseconds since Jan. 1, 1970.
-     * @since Android 1.0
      */
     public void setTimeInMillis(long milliseconds) {
-        time = milliseconds;
-        isTimeSet = true;
-        areFieldsSet = false;
-        complete();
+        if (!isTimeSet || !areFieldsSet || time != milliseconds) {
+            time = milliseconds;
+            isTimeSet = true;
+            areFieldsSet = false;
+            complete();
+        }
     }
 
     /**
      * Sets the {@code TimeZone} used by this Calendar.
-     * 
+     *
      * @param timezone
      *            a {@code TimeZone}.
-     * @since Android 1.0
      */
     public void setTimeZone(TimeZone timezone) {
         zone = timezone;
+        areFieldsSet = false;
     }
 
     /**
      * Returns the string representation of this {@code Calendar}.
-     * 
+     *
      * @return the string representation of this {@code Calendar}.
-     * @since Android 1.0
      */
     @Override
+    @SuppressWarnings("nls")
     public String toString() {
-        StringBuffer result = new StringBuffer(getClass().getName() + "[time=" //$NON-NLS-1$
-                + (isTimeSet ? String.valueOf(time) : "?") + ",areFieldsSet="  //$NON-NLS-1$//$NON-NLS-2$
-                + areFieldsSet +
-                // ",areAllFieldsSet=" + areAllFieldsSet +
-                ",lenient=" + lenient + ",zone=" + zone + ",firstDayOfWeek=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-                + firstDayOfWeek + ",minimalDaysInFirstWeek=" //$NON-NLS-1$
+        StringBuffer result = new StringBuffer(getClass().getName() + "[time="
+                + (isTimeSet ? String.valueOf(time) : "?")
+                + ",areFieldsSet="
+                + areFieldsSet
+                + // ",areAllFieldsSet=" + areAllFieldsSet +
+                ",lenient=" + lenient + ",zone=" + zone + ",firstDayOfWeek="
+                + firstDayOfWeek + ",minimalDaysInFirstWeek="
                 + minimalDaysInFirstWeek);
         for (int i = 0; i < FIELD_COUNT; i++) {
             result.append(',');
@@ -1496,7 +1347,7 @@
     /**
      * Compares the times of the two {@code Calendar}, which represent the milliseconds
      * from the January 1, 1970 00:00:00.000 GMT (Gregorian).
-     * 
+     *
      * @param anotherCalendar
      *            another calendar that this one is compared with.
      * @return 0 if the times of the two {@code Calendar}s are equal, -1 if the time of
@@ -1507,7 +1358,6 @@
      * @throws IllegalArgumentException
      *             if the argument does not include a valid time
      *             value.
-     * @since Android 1.0
      */
     public int compareTo(Calendar anotherCalendar) {
         if (null == anotherCalendar) {
@@ -1524,6 +1374,7 @@
         return -1;
     }
 
+    @SuppressWarnings("nls")
     private static final ObjectStreamField[] serialPersistentFields = {
             new ObjectStreamField("areFieldsSet", Boolean.TYPE), //$NON-NLS-1$
             new ObjectStreamField("fields", int[].class), //$NON-NLS-1$
@@ -1537,6 +1388,7 @@
             new ObjectStreamField("time", Long.TYPE), //$NON-NLS-1$
             new ObjectStreamField("zone", TimeZone.class), }; //$NON-NLS-1$
 
+    @SuppressWarnings("nls")
     private void writeObject(ObjectOutputStream stream) throws IOException {
         complete();
         ObjectOutputStream.PutField putFields = stream.putFields();
@@ -1554,6 +1406,7 @@
         stream.writeFields();
     }
 
+    @SuppressWarnings("nls")
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
         ObjectInputStream.GetField readFields = stream.readFields();
diff --git a/luni/src/main/java/java/util/Collection.java b/luni/src/main/java/java/util/Collection.java
index e26dba6..6447e39 100644
--- a/luni/src/main/java/java/util/Collection.java
+++ b/luni/src/main/java/java/util/Collection.java
@@ -22,7 +22,7 @@
  * {@code Collection} is the root of the collection hierarchy. It defines operations on
  * data collections and the behavior that they will have in all implementations
  * of {@code Collection}s.
- * 
+ *
  * All direct or indirect implementations of {@code Collection} should implement at
  * least two constuctors. One with no parameters which creates an empty
  * collection and one with a parameter of type {@code Collection}. This second
@@ -30,58 +30,55 @@
  * initial collection but with the same elements. Implementations of {@code Collection}
  * cannot be forced to implement these two constructors but at least all
  * implementations under {@code java.util} do.
- * 
+ *
  * Methods that change the content of a collection throw an
  * {@code UnsupportedOperationException} if the underlying collection does not
  * support that operation, though it's not mandatory to throw such an {@code Exception}
  * in cases where the requested operation would not change the collection. In
  * these cases it's up to the implementation whether it throws an
  * {@code UnsupportedOperationException} or not.
- * 
+ *
  * Methods marked with (optional) can throw an
  * {@code UnsupportedOperationException} if the underlying collection doesn't
  * support that method.
- * 
- * @since Android 1.0
  */
 public interface Collection<E> extends Iterable<E> {
 
     /**
      * Attempts to add {@code object} to the contents of this
      * {@code Collection} (optional).
-     * 
+     *
      * After this method finishes successfully it is guaranteed that the object
      * is contained in the collection.
-     * 
+     *
      * If the collection was modified it returns {@code true}, {@code false} if
      * no changes were made.
-     * 
+     *
      * An implementation of {@code Collection} may narrow the set of accepted
      * objects, but it has to specify this in the documentation. If the object
      * to be added does not meet this restriction, then an
      * {@code IllegalArgumentException} is thrown.
-     * 
+     *
      * If a collection does not yet contain an object that is to be added and
      * adding the object fails, this method <i>must</i> throw an appropriate
      * unchecked Exception. Returning false is not permitted in this case
      * because it would violate the postcondition that the element will be part
      * of the collection after this method finishes.
-     * 
+     *
      * @param object
      *            the object to add.
      * @return {@code true} if this {@code Collection} is
      *         modified, {@code false} otherwise.
-     * 
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code Collection} is not supported.
-     * @exception ClassCastException
-     *                when the class of the object is inappropriate for this
+     *
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code Collection} is not supported.
+     * @throws ClassCastException
+     *                if the class of the object is inappropriate for this
      *                collection.
-     * @exception IllegalArgumentException
-     *                when the object cannot be added to this {@code Collection}.
-     * @exception NullPointerException
-     *                when null elements cannot be added to the {@code Collection}.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the object cannot be added to this {@code Collection}.
+     * @throws NullPointerException
+     *                if null elements cannot be added to the {@code Collection}.
      */
     public boolean add(E object);
 
@@ -90,35 +87,33 @@
      * to the contents of this {@code Collection} (optional). If the passed {@code Collection}
      * is changed during the process of adding elements to this {@code Collection}, the
      * behavior is not defined.
-     * 
+     *
      * @param collection
      *            the {@code Collection} of objects.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code Collection} is not supported.
-     * @exception ClassCastException
-     *                when the class of an object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code Collection} is not supported.
+     * @throws ClassCastException
+     *                if the class of an object is inappropriate for this
      *                {@code Collection}.
-     * @exception IllegalArgumentException
-     *                when an object cannot be added to this {@code Collection}.
-     * @exception NullPointerException
-     *                when {@code collection} is {@code null}, or if it
+     * @throws IllegalArgumentException
+     *                if an object cannot be added to this {@code Collection}.
+     * @throws NullPointerException
+     *                if {@code collection} is {@code null}, or if it
      *                contains {@code null} elements and this {@code Collection} does
      *                not support such elements.
-     * @since Android 1.0
      */
     public boolean addAll(Collection<? extends E> collection);
 
     /**
      * Removes all elements from this {@code Collection}, leaving it empty (optional).
-     * 
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * 
+     *
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public void clear();
 
@@ -127,18 +122,17 @@
      * {@code true} if and only if at least one element {@code elem} in this
      * {@code Collection} meets following requirement:
      * {@code (object==null ? elem==null : object.equals(elem))}.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return {@code true} if object is an element of this {@code Collection},
      *         {@code false} otherwise.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if the object to look for isn't of the correct
      *                type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if the object to look for is {@code null} and this
      *                {@code Collection} doesn't support {@code null} elements.
-     * @since Android 1.0
      */
     public boolean contains(Object object);
 
@@ -147,56 +141,52 @@
      * specified {@code Collection}. If an elemenet {@code elem} is contained several
      * times in the specified {@code Collection}, the method returns {@code true} even
      * if {@code elem} is contained only once in this {@code Collection}.
-     * 
+     *
      * @param collection
      *            the collection of objects.
      * @return {@code true} if all objects in the specified {@code Collection} are
      *         elements of this {@code Collection}, {@code false} otherwise.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if one or more elements of {@code collection} isn't of the
      *                correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one {@code null}
      *                element and this {@code Collection} doesn't support {@code null}
      *                elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean containsAll(Collection<?> collection);
 
     /**
      * Compares the argument to the receiver, and returns true if they represent
      * the <em>same</em> object using a class specific comparison.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the object is the same as this object and
      *         {@code false} if it is different from this object.
      * @see #hashCode
-     * @since Android 1.0
      */
     public boolean equals(Object object);
 
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
-     * 
+     *
      * @see #equals
-     * @since Android 1.0
      */
     public int hashCode();
 
     /**
      * Returns if this {@code Collection} contains no elements.
-     * 
+     *
      * @return {@code true} if this {@code Collection} has no elements, {@code false}
      *         otherwise.
-     * 
+     *
      * @see #size
-     * @since Android 1.0
      */
     public boolean isEmpty();
 
@@ -205,9 +195,8 @@
      * objects contained by this {@code Collection}. The order in which the elements are
      * returned by the iterator is not defined. Only if the instance of the
      * {@code Collection} has a defined order the elements are returned in that order.
-     * 
+     *
      * @return an iterator for accessing the {@code Collection} contents.
-     * @since Android 1.0
      */
     public Iterator<E> iterator();
 
@@ -215,19 +204,18 @@
      * Removes one instance of the specified object from this {@code Collection} if one
      * is contained (optional). The element {@code elem} that is removed
      * complies with {@code (object==null ? elem==null : object.equals(elem)}.
-     * 
+     *
      * @param object
      *            the object to remove.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
-     *                when the object passed is not of the correct type.
-     * @exception NullPointerException
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
+     *                if the object passed is not of the correct type.
+     * @throws NullPointerException
      *                if {@code object} is {@code null} and this {@code Collection}
      *                doesn't support {@code null} elements.
-     * @since Android 1.0
      */
     public boolean remove(Object object);
 
@@ -236,24 +224,23 @@
      * specified {@code Collection} (optional). After this method returns none of the
      * elements in the passed {@code Collection} can be found in this {@code Collection}
      * anymore.
-     * 
+     *
      * @param collection
      *            the collection of objects to remove.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * 
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
+     *
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
      *                if one or more elements of {@code collection}
      *                isn't of the correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one
      *                {@code null} element and this {@code Collection} doesn't support
      *                {@code null} elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean removeAll(Collection<?> collection);
 
@@ -262,48 +249,45 @@
      * {@code Collection} passed (optional). After this method returns this {@code Collection}
      * will only contain elements that also can be found in the {@code Collection}
      * passed to this method.
-     * 
+     *
      * @param collection
      *            the collection of objects to retain.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
      *                if one or more elements of {@code collection}
      *                isn't of the correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one
      *                {@code null} element and this {@code Collection} doesn't support
      *                {@code null} elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean retainAll(Collection<?> collection);
 
     /**
      * Returns a count of how many objects this {@code Collection} contains.
-     * 
+     *
      * @return how many objects this {@code Collection} contains, or Integer.MAX_VALUE
      *         if there are more than Integer.MAX_VALUE elements in this
      *         {@code Collection}.
-     * @since Android 1.0
      */
     public int size();
 
     /**
      * Returns a new array containing all elements contained in this {@code Collection}.
-     * 
+     *
      * If the implementation has ordered elements it will return the element
      * array in the same order as an iterator would return them.
-     * 
+     *
      * The array returned does not reflect any changes of the {@code Collection}. A new
      * array is created even if the underlying data structure is already an
      * array.
-     * 
+     *
      * @return an array of the elements from this {@code Collection}.
-     * @since Android 1.0
      */
     public Object[] toArray();
 
@@ -313,21 +297,20 @@
      * array is used, otherwise an array of the same type is created. If the
      * specified array is used and is larger than this {@code Collection}, the array
      * element following the {@code Collection} elements is set to null.
-     * 
+     *
      * If the implementation has ordered elements it will return the element
      * array in the same order as an iterator would return them.
-     * 
+     *
      * {@code toArray(new Object[0])} behaves exactly the same way as
      * {@code toArray()} does.
-     * 
+     *
      * @param array
      *            the array.
      * @return an array of the elements from this {@code Collection}.
-     * 
-     * @exception ArrayStoreException
-     *                when the type of an element in this {@code Collection} cannot be
+     *
+     * @throws ArrayStoreException
+     *                if the type of an element in this {@code Collection} cannot be
      *                stored in the type of the specified array.
-     * @since Android 1.0
      */
     public <T> T[] toArray(T[] array);
 }
diff --git a/luni/src/main/java/java/util/Collections.java b/luni/src/main/java/java/util/Collections.java
index 5905bc2..767d98b 100644
--- a/luni/src/main/java/java/util/Collections.java
+++ b/luni/src/main/java/java/util/Collections.java
@@ -27,8 +27,8 @@
 /**
  * {@code Collections} contains static methods which operate on
  * {@code Collection} classes.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public class Collections {
 
@@ -69,7 +69,7 @@
 
     @SuppressWarnings("unchecked")
     private static final class EmptyList extends AbstractList implements
-            Serializable {
+            RandomAccess, Serializable {
         private static final long serialVersionUID = 8842843931221139166L;
 
         @Override
@@ -171,24 +171,18 @@
 
     /**
      * An empty immutable instance of {@link List}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final List EMPTY_LIST = new EmptyList();
 
     /**
      * An empty immutable instance of {@link Set}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Set EMPTY_SET = new EmptySet();
 
     /**
      * An empty immutable instance of {@link Map}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Map EMPTY_MAP = new EmptyMap();
@@ -532,9 +526,9 @@
          * problems. This is necessary since RandomAccess API was introduced
          * only in 1.4.
          * <p>
-         * 
+         *
          * @return SynchronizedList
-         * 
+         *
          * @see SynchronizedList#readResolve()
          */
         private Object writeReplace() {
@@ -591,15 +585,51 @@
         }
 
         public int indexOf(Object object) {
+            final int size;
+            final Object[] array;
             synchronized (mutex) {
-                return list.indexOf(object);
+                size = list.size();
+                array = new Object[size];
+                list.toArray(array);
             }
+            if (null != object)
+                for (int i = 0; i < size; i++) {
+                    if (object.equals(array[i])) {
+                        return i;
+                    }
+                }
+            else {
+                for (int i = 0; i < size; i++) {
+                    if (null == array[i]) {
+                        return i;
+                    }
+                }
+            }
+            return -1;
         }
 
         public int lastIndexOf(Object object) {
+            final int size;
+            final Object[] array;
             synchronized (mutex) {
-                return list.lastIndexOf(object);
+                size = list.size();
+                array = new Object[size];
+                list.toArray(array);
             }
+            if (null != object)
+                for (int i = size - 1; i >= 0; i--) {
+                    if (object.equals(array[i])) {
+                        return i;
+                    }
+                }
+            else {
+                for (int i = size - 1; i >= 0; i--) {
+                    if (null == array[i]) {
+                        return i;
+                    }
+                }
+            }
+            return -1;
         }
 
         public ListIterator<E> listIterator() {
@@ -646,10 +676,10 @@
          * replaced with SynchronizedList instances during serialization for
          * compliance with JREs before 1.4.
          * <p>
-         * 
+         *
          * @return a SynchronizedList instance if the underlying list implements
          *         RandomAccess interface, or this same object if not.
-         * 
+         *
          * @see SynchronizedRandomAccessList#writeReplace()
          */
         private Object readResolve() {
@@ -1033,9 +1063,9 @@
          * problems. This is necessary since RandomAccess API was introduced
          * only in 1.4.
          * <p>
-         * 
+         *
          * @return UnmodifiableList
-         * 
+         *
          * @see UnmodifiableList#readResolve()
          */
         private Object writeReplace() {
@@ -1150,11 +1180,11 @@
          * replaced with UnmodifiableList instances during serialization for
          * compliance with JREs before 1.4.
          * <p>
-         * 
+         *
          * @return an UnmodifiableList instance if the underlying list
          *         implements RandomAccess interface, or this same object if
          *         not.
-         * 
+         *
          * @see UnmodifiableRandomAccessList#writeReplace()
          */
         private Object readResolve() {
@@ -1429,13 +1459,13 @@
 
     /**
      * Performs a binary search for the specified element in the specified
-     * sorted List. The List needs to be already sorted in natural sorting
+     * sorted list. The list needs to be already sorted in natural sorting
      * order. Searching in an unsorted array has an undefined result. It's also
      * undefined which element is found if there are multiple occurrences of the
      * same element.
-     * 
+     *
      * @param list
-     *            the sorted List to search.
+     *            the sorted list to search.
      * @param object
      *            the element to find.
      * @return the non-negative index of the element, or a negative index which
@@ -1443,7 +1473,6 @@
      * @throws ClassCastException
      *             if an element in the List or the search element does not
      *             implement Comparable, or cannot be compared to each other.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static <T> int binarySearch(
@@ -1455,12 +1484,12 @@
             return -1;
         }
 
-        Comparable<T> key = (Comparable<T>) object;
+
         if (!(list instanceof RandomAccess)) {
-            ListIterator<T> it = (ListIterator<T>) list.listIterator();
+            ListIterator<? extends Comparable<? super T>> it = list.listIterator();
             while (it.hasNext()) {
                 int result;
-                if ((result = key.compareTo(it.next())) <= 0) {
+                if ((result = -it.next().compareTo(object)) <= 0) {
                     if (result == 0) {
                         return it.previousIndex();
                     }
@@ -1473,7 +1502,7 @@
         int low = 0, mid = list.size(), high = mid - 1, result = -1;
         while (low <= high) {
             mid = (low + high) >> 1;
-            if ((result = key.compareTo((T) list.get(mid))) > 0) {
+            if ((result = -list.get(mid).compareTo(object)) > 0) {
                 low = mid + 1;
             } else if (result == 0) {
                 return mid;
@@ -1486,26 +1515,28 @@
 
     /**
      * Performs a binary search for the specified element in the specified
-     * sorted List using the specified Comparator. The List needs to be already
+     * sorted list using the specified comparator. The list needs to be already
      * sorted according to the comparator passed. Searching in an unsorted array
      * has an undefined result. It's also undefined which element is found if
      * there are multiple occurrences of the same element.
-     * 
+     *
      * @param list
      *            the sorted List to search.
      * @param object
      *            the element to find.
      * @param comparator
-     *            the Comparator. If the comparator is {@code null} then the
+     *            the comparator. If the comparator is {@code null} then the
      *            search uses the objects' natural ordering.
      * @return the non-negative index of the element, or a negative index which
      *         is the {@code -index - 1} where the element would be inserted.
      * @throws ClassCastException
      *             when an element in the list and the searched element cannot
-     *             be compared to each other using the Comparator.
-     * @since Android 1.0
+     *             be compared to each other using the comparator.
      */
     @SuppressWarnings("unchecked")
+    // BEGIN android-note
+    // removed "@param <T> The element type", which is rejected by apicheck
+    // END android-note
     public static <T> int binarySearch(List<? extends T> list, T object,
             Comparator<? super T> comparator) {
         if (comparator == null) {
@@ -1516,7 +1547,7 @@
             ListIterator<? extends T> it = list.listIterator();
             while (it.hasNext()) {
                 int result;
-                if ((result = comparator.compare(object, it.next())) <= 0) {
+                if ((result = -comparator.compare(it.next(), object)) <= 0) {
                     if (result == 0) {
                         return it.previousIndex();
                     }
@@ -1529,7 +1560,7 @@
         int low = 0, mid = list.size(), high = mid - 1, result = -1;
         while (low <= high) {
             mid = (low + high) >> 1;
-            if ((result = comparator.compare(object, list.get(mid))) > 0) {
+            if ((result = -comparator.compare(list.get(mid),object)) > 0) {
                 low = mid + 1;
             } else if (result == 0) {
                 return mid;
@@ -1545,17 +1576,16 @@
      * end both lists will have the same objects at the same index. If the
      * destination array is larger than the source list, the elements in the
      * destination list with {@code index >= source.size()} will be unchanged.
-     * 
+     *
      * @param destination
      *            the list whose elements are set from the source list.
      * @param source
      *            the list with the elements to be copied into the destination.
      * @throws IndexOutOfBoundsException
-     *             when the destination List is smaller than the source List.
+     *             when the destination list is smaller than the source list.
      * @throws UnsupportedOperationException
      *             when replacing an element in the destination list is not
      *             supported.
-     * @since Android 1.0
      */
     public static <T> void copy(List<? super T> destination,
             List<? extends T> source) {
@@ -1576,11 +1606,10 @@
 
     /**
      * Returns an {@code Enumeration} on the specified collection.
-     * 
+     *
      * @param collection
      *            the collection to enumerate.
      * @return an Enumeration.
-     * @since Android 1.0
      */
     public static <T> Enumeration<T> enumeration(Collection<T> collection) {
         final Collection<T> c = collection;
@@ -1598,15 +1627,14 @@
     }
 
     /**
-     * Fills the specified List with the specified element.
-     * 
+     * Fills the specified list with the specified element.
+     *
      * @param list
-     *            the List to fill.
+     *            the list to fill.
      * @param object
      *            the element to fill the list with.
      * @throws UnsupportedOperationException
      *             when replacing an element in the List is not supported.
-     * @since Android 1.0
      */
     public static <T> void fill(List<? super T> list, T object) {
         ListIterator<? super T> it = list.listIterator();
@@ -1617,16 +1645,15 @@
     }
 
     /**
-     * Searches the specified Collection for the maximum element.
-     * 
+     * Searches the specified collection for the maximum element.
+     *
      * @param collection
-     *            the Collection to search.
+     *            the collection to search.
      * @return the maximum element in the Collection.
      * @throws ClassCastException
-     *             when an element in the Collection does not implement
+     *             when an element in the collection does not implement
      *             {@code Comparable} or elements cannot be compared to each
      *             other.
-     * @since Android 1.0
      */
     public static <T extends Object & Comparable<? super T>> T max(
             Collection<? extends T> collection) {
@@ -1642,18 +1669,17 @@
     }
 
     /**
-     * Searches the specified Collection for the maximum element using the
-     * specified Comparator.
-     * 
+     * Searches the specified collection for the maximum element using the
+     * specified comparator.
+     *
      * @param collection
-     *            the Collection to search.
+     *            the collection to search.
      * @param comparator
-     *            the Comparator.
+     *            the comparator.
      * @return the maximum element in the Collection.
      * @throws ClassCastException
-     *             when elements in the Collection cannot be compared to each
+     *             when elements in the collection cannot be compared to each
      *             other using the {@code Comparator}.
-     * @since Android 1.0
      */
     public static <T> T max(Collection<? extends T> collection,
             Comparator<? super T> comparator) {
@@ -1669,16 +1695,15 @@
     }
 
     /**
-     * Searches the specified Collection for the minimum element.
-     * 
+     * Searches the specified collection for the minimum element.
+     *
      * @param collection
-     *            the Collection to search.
-     * @return the minimum element in the Collection.
+     *            the collection to search.
+     * @return the minimum element in the collection.
      * @throws ClassCastException
-     *             when an element in the Collection does not implement
+     *             when an element in the collection does not implement
      *             {@code Comparable} or elements cannot be compared to each
      *             other.
-     * @since Android 1.0
      */
     public static <T extends Object & Comparable<? super T>> T min(
             Collection<? extends T> collection) {
@@ -1694,18 +1719,17 @@
     }
 
     /**
-     * Searches the specified Collection for the minimum element using the
-     * specified Comparator.
-     * 
+     * Searches the specified collection for the minimum element using the
+     * specified comparator.
+     *
      * @param collection
-     *            the Collection to search.
+     *            the collection to search.
      * @param comparator
-     *            the Comparator.
-     * @return the minimum element in the Collection.
+     *            the comparator.
+     * @return the minimum element in the collection.
      * @throws ClassCastException
-     *             when elements in the Collection cannot be compared to each
+     *             when elements in the collection cannot be compared to each
      *             other using the {@code Comparator}.
-     * @since Android 1.0
      */
     public static <T> T min(Collection<? extends T> collection,
             Comparator<? super T> comparator) {
@@ -1721,17 +1745,16 @@
     }
 
     /**
-     * Returns a List containing the specified number of the specified element.
+     * Returns a list containing the specified number of the specified element.
      * The list cannot be modified. The list is serializable.
-     * 
+     *
      * @param length
      *            the size of the returned list.
      * @param object
      *            the element to be added {@code length} times to a list.
-     * @return a List containing {@code length} copies of the element.
+     * @return a list containing {@code length} copies of the element.
      * @throws IllegalArgumentException
      *             when {@code length < 0}.
-     * @since Android 1.0
      */
     public static <T> List<T> nCopies(final int length, T object) {
         return new CopiesList<T>(length, object);
@@ -1740,12 +1763,11 @@
     /**
      * Modifies the specified {@code List} by reversing the order of the
      * elements.
-     * 
+     *
      * @param list
-     *            the List to reverse.
+     *            the list to reverse.
      * @throws UnsupportedOperationException
      *             when replacing an element in the List is not supported.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static void reverse(List<?> list) {
@@ -1762,14 +1784,13 @@
     }
 
     /**
-     * A Comparator which reverses the natural order of the elements. The
+     * A comparator which reverses the natural order of the elements. The
      * {@code Comparator} that's returned is {@link Serializable}.
-     * 
+     *
      * @return a {@code Comparator} instance.
      * @see Comparator
      * @see Comparable
      * @see Serializable
-     * @since Android 1.0
      */
     public static <T> Comparator<T> reverseOrder() {
         return new ReverseComparator<T>();
@@ -1782,13 +1803,12 @@
      * <p>
      * The {@code Comparator} that's returned is {@link Serializable} if the
      * {@code Comparator} passed is serializable or {@code null}.
-     * </p>
-     * 
+     *
      * @param c
      *            the {@code Comparator} to reverse or {@code null}.
      * @return a {@code Comparator} instance.
      * @see Comparator
-     * @since Android 1.0
+     * @since 1.5
      */
     public static <T> Comparator<T> reverseOrder(Comparator<T> c) {
         if (c == null) {
@@ -1798,38 +1818,35 @@
     }
 
     /**
-     * Moves every element of the List to a random new position in the list.
-     * 
+     * Moves every element of the list to a random new position in the list.
+     *
      * @param list
      *            the List to shuffle.
-     * 
+     *
      * @throws UnsupportedOperationException
      *             when replacing an element in the List is not supported.
-     * @since Android 1.0
      */
     public static void shuffle(List<?> list) {
         shuffle(list, new Random());
     }
 
     /**
-     * Moves every element of the List to a random new position in the list
+     * Moves every element of the list to a random new position in the list
      * using the specified random number generator.
-     * 
+     *
      * @param list
-     *            the List to shuffle.
+     *            the list to shuffle.
      * @param random
      *            the random number generator.
-     * 
      * @throws UnsupportedOperationException
-     *             when replacing an element in the List is not supported.
-     * @since Android 1.0
+     *             when replacing an element in the list is not supported.
      */
     @SuppressWarnings("unchecked")
     public static void shuffle(List<?> list, Random random) {
         if (!(list instanceof RandomAccess)) {
             Object[] array = list.toArray();
             for (int i = array.length - 1; i > 0; i--) {
-                int index = random.nextInt() % (i + 1);
+                int index = random.nextInt(i + 1);
                 if (index < 0) {
                     index = -index;
                 }
@@ -1848,7 +1865,7 @@
         } else {
             List<Object> rawList = (List<Object>) list;
             for (int i = rawList.size() - 1; i > 0; i--) {
-                int index = random.nextInt() % (i + 1);
+                int index = random.nextInt(i + 1);
                 if (index < 0) {
                     index = -index;
                 }
@@ -1858,26 +1875,24 @@
     }
 
     /**
-     * Returns a Set containing the specified element. The set cannot be
+     * Returns a set containing the specified element. The set cannot be
      * modified. The set is serializable.
-     * 
+     *
      * @param object
      *            the element.
-     * @return a Set containing the element.
-     * @since Android 1.0
+     * @return a set containing the element.
      */
     public static <E> Set<E> singleton(E object) {
         return new SingletonSet<E>(object);
     }
 
     /**
-     * Returns a List containing the specified element. The list cannot be
+     * Returns a list containing the specified element. The list cannot be
      * modified. The list is serializable.
-     * 
+     *
      * @param object
      *            the element.
-     * @return a List containing the element.
-     * @since Android 1.0
+     * @return a list containing the element.
      */
     public static <E> List<E> singletonList(E object) {
         return new SingletonList<E>(object);
@@ -1886,28 +1901,26 @@
     /**
      * Returns a Map containing the specified key and value. The map cannot be
      * modified. The map is serializable.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
      *            the value.
      * @return a Map containing the key and value.
-     * @since Android 1.0
      */
     public static <K, V> Map<K, V> singletonMap(K key, V value) {
         return new SingletonMap<K, V>(key, value);
     }
 
     /**
-     * Sorts the specified List in ascending natural order. The algorithm is
+     * Sorts the specified list in ascending natural order. The algorithm is
      * stable which means equal elements don't get reordered.
-     * 
+     *
      * @param list
-     *            the List to be sorted.
+     *            the list to be sorted.
      * @throws ClassCastException
      *             when an element in the List does not implement Comparable or
      *             elements cannot be compared to each other.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static <T extends Comparable<? super T>> void sort(List<T> list) {
@@ -1922,17 +1935,16 @@
     }
 
     /**
-     * Sorts the specified List using the specified Comparator. The algorithm is
+     * Sorts the specified list using the specified comparator. The algorithm is
      * stable which means equal elements don't get reordered.
-     * 
+     *
      * @param list
-     *            the List to be sorted.
+     *            the list to be sorted.
      * @param comparator
-     *            the Comparator.
+     *            the comparator.
      * @throws ClassCastException
-     *             when elements in the List cannot be compared to each other
-     *             using the Comparator.
-     * @since Android 1.0
+     *             when elements in the list cannot be compared to each other
+     *             using the comparator.
      */
     @SuppressWarnings("unchecked")
     public static <T> void sort(List<T> list, Comparator<? super T> comparator) {
@@ -1947,26 +1959,30 @@
     }
 
     /**
-     * Swaps the elements of List {@code list} at indices {@code index1} and
+     * Swaps the elements of list {@code list} at indices {@code index1} and
      * {@code index2}.
-     * 
+     *
      * @param list
-     *            the List to manipulate.
+     *            the list to manipulate.
      * @param index1
      *            position of the first element to swap with the element in
      *            index2.
      * @param index2
      *            position of the other element.
-     * 
+     *
      * @throws IndexOutOfBoundsException
      *             if index1 or index2 is out of range of this list.
-     * @since Android 1.0
+     * @since 1.4
      */
     @SuppressWarnings("unchecked")
     public static void swap(List<?> list, int index1, int index2) {
         if (list == null) {
             throw new NullPointerException();
         }
+        final int size = list.size();
+        if (index1 < 0 || index1 >= size || index2 < 0 || index2 >= size) {
+            throw new IndexOutOfBoundsException();
+        }
         if (index1 == index2) {
             return;
         }
@@ -1978,20 +1994,18 @@
      * Replaces all occurrences of Object {@code obj} in {@code list} with
      * {@code newObj}. If the {@code obj} is {@code null}, then all
      * occurrences of {@code null} are replaced with {@code newObj}.
-     * 
+     *
      * @param list
-     *            the List to modify.
+     *            the list to modify.
      * @param obj
-     *            the Object to find and replace occurrences of.
+     *            the object to find and replace occurrences of.
      * @param obj2
-     *            the Object to replace all occurrences of {@code obj} in
+     *            the object to replace all occurrences of {@code obj} in
      *            {@code list}.
      * @return true, if at least one occurrence of {@code obj} has been found in
      *         {@code list}.
-     * 
      * @throws UnsupportedOperationException
      *             if the list does not support setting elements.
-     * @since Android 1.0
      */
     public static <T> boolean replaceAll(List<T> list, T obj, T obj2) {
         int index;
@@ -2005,19 +2019,17 @@
     }
 
     /**
-     * Rotates the elements in List {@code list} by the distance {@code dist}
+     * Rotates the elements in {@code list} by the distance {@code dist}
      * <p>
      * e.g. for a given list with elements [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
      * calling rotate(list, 3) or rotate(list, -7) would modify the list to look
      * like this: [8, 9, 0, 1, 2, 3, 4, 5, 6, 7]
-     * </p>
-     * 
+     *
      * @param lst
      *            the list whose elements are to be rotated.
      * @param dist
      *            is the distance the list is rotated. This can be any valid
      *            integer. Negative values rotate the list backwards.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static void rotate(List<?> lst, int dist) {
@@ -2069,14 +2081,13 @@
      * index of the first occurrence.
      * <p>
      * -1 is returned if the {@code sublist} does not exist in {@code list}.
-     * 
+     *
      * @param list
      *            the List to search {@code sublist} in.
      * @param sublist
      *            the List to search in {@code list}.
      * @return the beginning index of the first occurrence of {@code sublist} in
      *         {@code list}, or -1.
-     * @since Android 1.0
      */
     public static int indexOfSubList(List<?> list, List<?> sublist) {
         int size = list.size();
@@ -2137,14 +2148,13 @@
      * index of the last occurrence.
      * <p>
      * -1 is returned if the {@code sublist} does not exist in {@code list}.
-     * 
+     *
      * @param list
-     *            the List to search {@code sublist} in.
+     *            the list to search {@code sublist} in.
      * @param sublist
-     *            the List to search in {@code list}.
+     *            the list to search in {@code list}.
      * @return the beginning index of the last occurrence of {@code sublist} in
      *         {@code list}, or -1.
-     * @since Android 1.0
      */
     public static int lastIndexOfSubList(List<?> list, List<?> sublist) {
         int sublistSize = sublist.size();
@@ -2198,14 +2208,13 @@
     }
 
     /**
-     * Returns an {@code ArrayList} with all the elements in the
-     * {@code enumeration}. The elements in the returned ArrayList are in the
+     * Returns an {@code ArrayList} with all the elements in the {@code
+     * enumeration}. The elements in the returned {@code ArrayList} are in the
      * same order as in the {@code enumeration}.
-     * 
+     *
      * @param enumeration
      *            the source {@link Enumeration}.
      * @return an {@code ArrayList} from {@code enumeration}.
-     * @since Android 1.0
      */
     public static <T> ArrayList<T> list(Enumeration<T> enumeration) {
         ArrayList<T> list = new ArrayList<T>();
@@ -2216,13 +2225,12 @@
     }
 
     /**
-     * Returns a wrapper on the specified Collection which synchronizes all
-     * access to the Collection.
-     * 
+     * Returns a wrapper on the specified collection which synchronizes all
+     * access to the collection.
+     *
      * @param collection
      *            the Collection to wrap in a synchronized collection.
      * @return a synchronized Collection.
-     * @since Android 1.0
      */
     public static <T> Collection<T> synchronizedCollection(
             Collection<T> collection) {
@@ -2235,11 +2243,10 @@
     /**
      * Returns a wrapper on the specified List which synchronizes all access to
      * the List.
-     * 
+     *
      * @param list
      *            the List to wrap in a synchronized list.
      * @return a synchronized List.
-     * @since Android 1.0
      */
     public static <T> List<T> synchronizedList(List<T> list) {
         if (list == null) {
@@ -2252,13 +2259,12 @@
     }
 
     /**
-     * Returns a wrapper on the specified Map which synchronizes all access to
-     * the Map.
-     * 
+     * Returns a wrapper on the specified map which synchronizes all access to
+     * the map.
+     *
      * @param map
-     *            the Map to wrap in a synchronized map.
+     *            the map to wrap in a synchronized map.
      * @return a synchronized Map.
-     * @since Android 1.0
      */
     public static <K, V> Map<K, V> synchronizedMap(Map<K, V> map) {
         if (map == null) {
@@ -2268,13 +2274,12 @@
     }
 
     /**
-     * Returns a wrapper on the specified Set which synchronizes all access to
-     * the Set.
-     * 
+     * Returns a wrapper on the specified set which synchronizes all access to
+     * the set.
+     *
      * @param set
-     *            the Set to wrap in a synchronized set.
-     * @return a synchronized Set.
-     * @since Android 1.0
+     *            the set to wrap in a synchronized set.
+     * @return a synchronized set.
      */
     public static <E> Set<E> synchronizedSet(Set<E> set) {
         if (set == null) {
@@ -2284,13 +2289,12 @@
     }
 
     /**
-     * Returns a wrapper on the specified SortedMap which synchronizes all
-     * access to the SortedMap.
-     * 
+     * Returns a wrapper on the specified sorted map which synchronizes all
+     * access to the sorted map.
+     *
      * @param map
-     *            the SortedMap to wrap in a synchronized sorted map.
-     * @return a synchronized SortedMap.
-     * @since Android 1.0
+     *            the sorted map to wrap in a synchronized sorted map.
+     * @return a synchronized sorted map.
      */
     public static <K, V> SortedMap<K, V> synchronizedSortedMap(
             SortedMap<K, V> map) {
@@ -2301,13 +2305,12 @@
     }
 
     /**
-     * Returns a wrapper on the specified SortedSet which synchronizes all
-     * access to the SortedSet.
-     * 
+     * Returns a wrapper on the specified sorted set which synchronizes all
+     * access to the sorted set.
+     *
      * @param set
-     *            the SortedSet to wrap in a synchronized sorted set.
-     * @return a synchronized SortedSet.
-     * @since Android 1.0
+     *            the sorted set to wrap in a synchronized sorted set.
+     * @return a synchronized sorted set.
      */
     public static <E> SortedSet<E> synchronizedSortedSet(SortedSet<E> set) {
         if (set == null) {
@@ -2317,14 +2320,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified Collection which throws an
+     * Returns a wrapper on the specified collection which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the Collection.
-     * 
+     * modify the collection.
+     *
      * @param collection
-     *            the Collection to wrap in an unmodifiable collection.
-     * @return an unmodifiable Collection.
-     * @since Android 1.0
+     *            the collection to wrap in an unmodifiable collection.
+     * @return an unmodifiable collection.
      */
     @SuppressWarnings("unchecked")
     public static <E> Collection<E> unmodifiableCollection(
@@ -2336,14 +2338,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified List which throws an
+     * Returns a wrapper on the specified list which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the List.
-     * 
+     * modify the list.
+     *
      * @param list
-     *            the List to wrap in an unmodifiable list.
+     *            the list to wrap in an unmodifiable list.
      * @return an unmodifiable List.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static <E> List<E> unmodifiableList(List<? extends E> list) {
@@ -2357,14 +2358,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified Map which throws an
+     * Returns a wrapper on the specified map which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the Map.
-     * 
+     * modify the map.
+     *
      * @param map
-     *            the Map to wrap in an unmodifiable map.
-     * @return a unmodifiable Map.
-     * @since Android 1.0
+     *            the map to wrap in an unmodifiable map.
+     * @return a unmodifiable map.
      */
     @SuppressWarnings("unchecked")
     public static <K, V> Map<K, V> unmodifiableMap(
@@ -2376,14 +2376,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified Set which throws an
+     * Returns a wrapper on the specified set which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the Set.
-     * 
+     * modify the set.
+     *
      * @param set
-     *            the Set to wrap in an unmodifiable set.
-     * @return a unmodifiable Set.
-     * @since Android 1.0
+     *            the set to wrap in an unmodifiable set.
+     * @return a unmodifiable set
      */
     @SuppressWarnings("unchecked")
     public static <E> Set<E> unmodifiableSet(Set<? extends E> set) {
@@ -2394,14 +2393,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified SortedMap which throws an
+     * Returns a wrapper on the specified sorted map which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the SortedMap.
-     * 
+     * modify the sorted map.
+     *
      * @param map
-     *            the SortedMap to wrap in an unmodifiable sorted map.
-     * @return a unmodifiable SortedMap.
-     * @since Android 1.0
+     *            the sorted map to wrap in an unmodifiable sorted map.
+     * @return a unmodifiable sorted map
      */
     @SuppressWarnings("unchecked")
     public static <K, V> SortedMap<K, V> unmodifiableSortedMap(
@@ -2413,14 +2411,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified SortedSet which throws an
+     * Returns a wrapper on the specified sorted set which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the SortedSet.
-     * 
+     * modify the sorted set.
+     *
      * @param set
-     *            the SortedSet to wrap in an unmodifiable sorted set.
-     * @return a unmodifiable SortedSet.
-     * @since Android 1.0
+     *            the sorted set to wrap in an unmodifiable sorted set.
+     * @return a unmodifiable sorted set.
      */
     public static <E> SortedSet<E> unmodifiableSortedSet(SortedSet<E> set) {
         if (set == null) {
@@ -2433,8 +2430,7 @@
      * Returns the number of elements in the {@code Collection} that match the
      * {@code Object} passed. If the {@code Object} is {@code null}, then the
      * number of {@code null} elements is returned.
-     * </p>
-     * 
+     *
      * @param c
      *            the {@code Collection} to search.
      * @param o
@@ -2442,7 +2438,7 @@
      * @return the number of matching elements.
      * @throws NullPointerException
      *             if the {@code Collection} parameter is {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int frequency(Collection<?> c, Object o) {
         if (c == null) {
@@ -2464,10 +2460,10 @@
 
     /**
      * Returns a type-safe empty, immutable {@link List}.
-     * 
+     *
      * @return an empty {@link List}.
+     * @since 1.5
      * @see #EMPTY_LIST
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final <T> List<T> emptyList() {
@@ -2476,10 +2472,10 @@
 
     /**
      * Returns a type-safe empty, immutable {@link Set}.
-     * 
+     *
      * @return an empty {@link Set}.
+     * @since 1.5
      * @see #EMPTY_SET
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final <T> Set<T> emptySet() {
@@ -2488,10 +2484,10 @@
 
     /**
      * Returns a type-safe empty, immutable {@link Map}.
-     * 
+     *
      * @return an empty {@link Map}.
+     * @since 1.5
      * @see #EMPTY_MAP
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final <K, V> Map<K, V> emptyMap() {
@@ -2503,13 +2499,12 @@
      * to insert an element of the wrong type into this collection throws a
      * {@code ClassCastException}. At creation time the types in {@code c} are
      * not checked for correct type.
-     * 
+     *
      * @param c
      *            the collection to be wrapped in a typesafe collection.
      * @param type
      *            the type of the elements permitted to insert.
      * @return a typesafe collection.
-     * @since Android 1.0
      */
     public static <E> Collection<E> checkedCollection(Collection<E> c,
             Class<E> type) {
@@ -2521,7 +2516,7 @@
      * insert an element of the wrong type into this map throws a
      * {@code ClassCastException}. At creation time the types in {@code m} are
      * not checked for correct type.
-     * 
+     *
      * @param m
      *            the map to be wrapped in a typesafe map.
      * @param keyType
@@ -2529,7 +2524,6 @@
      * @param valueType
      *            the type of the values permitted to insert.
      * @return a typesafe map.
-     * @since Android 1.0
      */
     public static <K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType,
             Class<V> valueType) {
@@ -2541,13 +2535,12 @@
      * insert an element of the wrong type into this list throws a
      * {@code ClassCastException}. At creation time the types in {@code list}
      * are not checked for correct type.
-     * 
+     *
      * @param list
      *            the list to be wrapped in a typesafe list.
      * @param type
      *            the type of the elements permitted to insert.
      * @return a typesafe list.
-     * @since Android 1.0
      */
     public static <E> List<E> checkedList(List<E> list, Class<E> type) {
         if (list instanceof RandomAccess) {
@@ -2561,13 +2554,12 @@
      * insert an element of the wrong type into this set throws a
      * {@code ClassCastException}. At creation time the types in {@code s} are
      * not checked for correct type.
-     * 
+     *
      * @param s
      *            the set to be wrapped in a typesafe set.
      * @param type
      *            the type of the elements permitted to insert.
      * @return a typesafe set.
-     * @since Android 1.0
      */
     public static <E> Set<E> checkedSet(Set<E> s, Class<E> type) {
         return new CheckedSet<E>(s, type);
@@ -2578,7 +2570,7 @@
      * to insert an element of the wrong type into this sorted map throws a
      * {@code ClassCastException}. At creation time the types in {@code m} are
      * not checked for correct type.
-     * 
+     *
      * @param m
      *            the sorted map to be wrapped in a typesafe sorted map.
      * @param keyType
@@ -2586,7 +2578,6 @@
      * @param valueType
      *            the type of the values permitted to insert.
      * @return a typesafe sorted map.
-     * @since Android 1.0
      */
     public static <K, V> SortedMap<K, V> checkedSortedMap(SortedMap<K, V> m,
             Class<K> keyType, Class<V> valueType) {
@@ -2598,13 +2589,12 @@
      * to insert an element of the wrong type into this sorted set throws a
      * {@code ClassCastException}. At creation time the types in {@code s} are
      * not checked for correct type.
-     * 
+     *
      * @param s
      *            the sorted set to be wrapped in a typesafe sorted set.
      * @param type
      *            the type of the elements permitted to insert.
      * @return a typesafe sorted set.
-     * @since Android 1.0
      */
     public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,
             Class<E> type) {
@@ -2613,7 +2603,7 @@
 
     /**
      * Adds all the specified elements to the specified collection.
-     * 
+     *
      * @param c
      *            the collection the elements are to be inserted into.
      * @param a
@@ -2628,7 +2618,6 @@
      * @throws IllegalArgumentException
      *             if at least one of the elements can't be inserted into the
      *             collection.
-     * @since Android 1.0
      */
     public static <T> boolean addAll(Collection<? super T> c, T... a) {
         boolean modified = false;
@@ -2640,7 +2629,7 @@
 
     /**
      * Returns whether the specified collections have no elements in common.
-     * 
+     *
      * @param c1
      *            the first collection.
      * @param c2
@@ -2649,7 +2638,6 @@
      *         {@code false} otherwise.
      * @throws NullPointerException
      *             if one of the collections is {@code null}.
-     * @since Android 1.0
      */
     public static boolean disjoint(Collection<?> c1, Collection<?> c2) {
         if ((c1 instanceof Set) && !(c2 instanceof Set)
@@ -2670,7 +2658,7 @@
     /**
      * Checks if specified object is instance of specified class. Used for a
      * dynamically typesafe view of the collections.
-     * 
+     *
      * @param obj -
      *            object is to be checked
      * @param type -
@@ -2701,7 +2689,7 @@
 
         /**
          * Constructs a dynamically typesafe view of the specified collection.
-         * 
+         *
          * @param c -
          *            the collection for which an unmodifiable view is to be
          *            constructed.
@@ -2844,7 +2832,7 @@
 
         /**
          * Constructs a dynamically typesafe view of the specified ListIterator.
-         * 
+         *
          * @param i -
          *            the listIterator for which a dynamically typesafe view to
          *            be constructed.
@@ -2930,7 +2918,7 @@
 
         /**
          * Constructs a dynamically typesafe view of the specified list.
-         * 
+         *
          * @param l -
          *            the list for which a dynamically typesafe view is to be
          *            constructed.
@@ -3049,7 +3037,7 @@
         /**
          * Constructs a dynamically typesafe view of the specified
          * randomAccessList.
-         * 
+         *
          * @param l -
          *            the randomAccessList for which a dynamically typesafe view
          *            is to be constructed.
@@ -3069,7 +3057,7 @@
 
         /**
          * Constructs a dynamically typesafe view of the specified set.
-         * 
+         *
          * @param s -
          *            the set for which a dynamically typesafe view is to be
          *            constructed.
@@ -3111,7 +3099,7 @@
 
         /**
          * Constructs a dynamically typesafe view of the specified map.
-         * 
+         *
          * @param m -
          *            the map for which a dynamically typesafe view is to be
          *            constructed.
@@ -3262,10 +3250,12 @@
             /**
              * Constructs a dynamically typesafe view of the specified map
              * entry.
-             * 
-             * @param e -
+             *
+             * @param e
              *            the map entry for which a dynamically typesafe view is
              *            to be constructed.
+             * @param valueType
+             *            the type of the value
              */
             public CheckedEntry(Map.Entry<K, V> e, Class<V> valueType) {
                 if (e == null) {
diff --git a/luni/src/main/java/java/util/Comparator.java b/luni/src/main/java/java/util/Comparator.java
index 7b09448..2d6f598 100644
--- a/luni/src/main/java/java/util/Comparator.java
+++ b/luni/src/main/java/java/util/Comparator.java
@@ -25,8 +25,8 @@
  * method has to return zero for each pair of elements (a,b) where a.equals(b)
  * holds true. It is recommended that a {@code Comparator} implements
  * {@link java.io.Serializable}.
- *  
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public interface Comparator<T> {
     /**
@@ -42,15 +42,15 @@
      * follow {@code compare(a,c) > 0} for all possible combinations of {@code
      * (a,b,c)}</li>
      * </ul>
-     * 
+     *
      * @param object1
      *            an {@code Object}.
      * @param object2
      *            a second {@code Object} to compare with {@code object1}.
      * @return an integer < 0 if {@code object1} is less than {@code object2}, 0 if they are
      *         equal, and > 0 if {@code object1} is greater than {@code object2}.
-     * @exception ClassCastException
-     *                when objects are not of the correct type.
+     * @throws ClassCastException
+     *                if objects are not of the correct type.
      */
     public int compare(T object1, T object2);
 
@@ -61,7 +61,7 @@
      * <p>
      * A {@code Comparator} never needs to override this method, but may choose so for
      * performance reasons.
-     * 
+     *
      * @param object
      *            the {@code Object} to compare with this comparator.
      * @return boolean {@code true} if specified {@code Object} is the same as this
diff --git a/luni/src/main/java/java/util/Currency.java b/luni/src/main/java/java/util/Currency.java
index 8ac0e6e..79de49d 100644
--- a/luni/src/main/java/java/util/Currency.java
+++ b/luni/src/main/java/java/util/Currency.java
@@ -17,15 +17,15 @@
 
 package java.util;
 
-import java.io.Serializable;
-
+// BEGIN android-added
 import org.apache.harmony.luni.util.Msg;
+// END android-added
+
+import java.io.Serializable;
 
 /**
  * This class represents a currency as identified in the ISO 4217 currency
  * codes.
- * 
- * @since Android 1.0
  */
 public final class Currency implements Serializable {
 
@@ -35,9 +35,11 @@
 
     private String currencyCode;
 
+    // BEGIN android-added
     private static String currencyVars = "EURO, HK, PREEURO"; //$NON-NLS-1$
 
     private transient int defaultFractionDigits;
+    // END android-added
 
     /**
      * @param currencyCode
@@ -49,20 +51,20 @@
     /**
      * Returns the {@code Currency} instance for this currency code.
      * <p>
-     * 
+     *
      * @param currencyCode
      *            the currency code.
      * @return the {@code Currency} instance for this currency code.
-     * 
+     *
      * @throws IllegalArgumentException
      *             if the currency code is not a supported ISO 4217 currency
      *             code.
-     * @since Android 1.0
      */
     public static Currency getInstance(String currencyCode) {
         Currency currency = codesToCurrencies.get(currencyCode);
 
         if (currency == null) {
+            // BEGIN android-added
             ResourceBundle bundle = Locale.getBundle(
                     "ISO4CurrenciesToDigits", Locale.getDefault()); //$NON-NLS-1$
             currency = new Currency(currencyCode);
@@ -77,6 +79,7 @@
             }
             currency.defaultFractionDigits = Integer
                     .parseInt(defaultFractionDigits);
+            // END android-added
             codesToCurrencies.put(currencyCode, currency);
         }
 
@@ -85,16 +88,26 @@
 
     /**
      * Returns the {@code Currency} instance for this {@code Locale}'s country.
-     * 
+     *
      * @param locale
      *            the {@code Locale} of a country.
      * @return the {@code Currency} used in the country defined by the locale parameter.
-     * 
+     *
      * @throws IllegalArgumentException
      *             if the locale's country is not a supported ISO 3166 Country.
-     * @since Android 1.0
      */
     public static Currency getInstance(Locale locale) {
+        // BEGIN android-changed
+        // com.ibm.icu.util.Currency currency = null;
+        // try {
+        //     currency = com.ibm.icu.util.Currency.getInstance(locale);
+        // } catch (IllegalArgumentException e) {
+        //     return null;
+        // }
+        // if (currency == null) {
+        //     throw new IllegalArgumentException(locale.getCountry());
+        // }
+        // String currencyCode = currency.getCurrencyCode();
         String country = locale.getCountry();
         String variant = locale.getVariant();
         if (!variant.equals("") && currencyVars.indexOf(variant) > -1) { //$NON-NLS-1$
@@ -110,6 +123,7 @@
             throw new IllegalArgumentException(Msg.getString(
                     "K0323", locale.toString())); //$NON-NLS-1$
         }
+        // END android-changed
 
         if (currencyCode.equals("None")) { //$NON-NLS-1$
             return null;
@@ -120,9 +134,8 @@
 
     /**
      * Returns this {@code Currency}'s ISO 4217 currency code.
-     * 
+     *
      * @return this {@code Currency}'s ISO 4217 currency code.
-     * @since Android 1.0
      */
     public String getCurrencyCode() {
         return currencyCode;
@@ -133,9 +146,8 @@
      * if the default locale is the US, the symbol of the US dollar is "$". For
      * other locales it may be "US$". If no symbol can be determined, the ISO
      * 4217 currency code of the US dollar is returned.
-     * 
+     *
      * @return the symbol for this {@code Currency} in the default {@code Locale}.
-     * @since Android 1.0
      */
     public String getSymbol() {
         return getSymbol(Locale.getDefault());
@@ -157,18 +169,19 @@
      * symbol for this currency in this bundle, then the
      * ISO 4217 currency code is returned.
      * <p>
-     * 
+     *
      * @param locale
      *            the locale for which the currency symbol should be returned.
      * @return the representation of this {@code Currency}'s symbol in the specified
      *         locale.
-     * @since Android 1.0
      */
     public String getSymbol(Locale locale) {
         if (locale.getCountry().equals("")) { //$NON-NLS-1$
             return currencyCode;
         }
 
+        // BEGIN android-changed
+        // return com.ibm.icu.util.Currency.getInstance(currencyCode).getSymbol(locale);
         // check in the Locale bundle first, if the local has the same currency
         ResourceBundle bundle = Locale.getBundle("Locale", locale); //$NON-NLS-1$
         if (((String) bundle.getObject("IntCurrencySymbol")) //$NON-NLS-1$
@@ -197,6 +210,7 @@
             return result;
         }
         return currencyCode;
+        // END android-changed
     }
 
     /**
@@ -204,19 +218,20 @@
      * instance, the default number of fraction digits for the US dollar is 2.
      * For the Japanese Yen the number is 0. In the case of pseudo-currencies,
      * such as IMF Special Drawing Rights, -1 is returned.
-     * 
+     *
      * @return the default number of fraction digits for this currency.
-     * @since Android 1.0
      */
     public int getDefaultFractionDigits() {
+        // BEGIN android-changed
+        // return com.ibm.icu.util.Currency.getInstance(currencyCode).getDefaultFractionDigits();
         return defaultFractionDigits;
+        // END android-changed
     }
 
     /**
      * Returns this currency's ISO 4217 currency code.
-     * 
+     *
      * @return this currency's ISO 4217 currency code.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/luni/src/main/java/java/util/Date.java b/luni/src/main/java/java/util/Date.java
index 172f682..7bd7261 100644
--- a/luni/src/main/java/java/util/Date.java
+++ b/luni/src/main/java/java/util/Date.java
@@ -29,13 +29,12 @@
 
 /**
  * {@code Date} represents a specific moment in time, to the millisecond.
- * 
+ *
  * @see System#currentTimeMillis
  * @see Calendar
  * @see GregorianCalendar
  * @see SimpleTimeZone
  * @see TimeZone
- * @since Android 1.0
  */
 public class Date implements Serializable, Cloneable, Comparable<Date> {
 
@@ -46,10 +45,15 @@
 
     private transient long milliseconds;
 
+    private static String[] dayOfWeekNames = { "Sun", "Mon", "Tue", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        "Wed", "Thu", "Fri", "Sat" }; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+    private static String[] monthNames = { "Jan", "Feb", "Mar", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        "Apr", "May", "Jun", "Jul", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+        "Aug", "Sep", "Oct", "Nov", "Dec"};  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
     /**
      * Initializes this {@code Date} instance to the current date and time.
-     * 
-     * @since Android 1.0
      */
     public Date() {
         this(System.currentTimeMillis());
@@ -58,17 +62,16 @@
     /**
      * Constructs a new {@code Date} initialized to midnight in the default {@code TimeZone} on
      * the specified date.
-     * 
+     *
      * @param year
      *            the year, 0 is 1900.
      * @param month
      *            the month, 0 - 11.
      * @param day
      *            the day of the month, 1 - 31.
-     * 
+     *
      * @deprecated use
      *             {@link GregorianCalendar#GregorianCalendar(int, int, int)}
-     * @since Android 1.0
      */
     @Deprecated
     public Date(int year, int month, int day) {
@@ -80,7 +83,7 @@
     /**
      * Constructs a new {@code Date} initialized to the specified date and time in the
      * default {@code TimeZone}.
-     * 
+     *
      * @param year
      *            the year, 0 is 1900.
      * @param month
@@ -91,10 +94,9 @@
      *            the hour of day, 0 - 23.
      * @param minute
      *            the minute of the hour, 0 - 59.
-     * 
+     *
      * @deprecated use
      *             {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int)}
-     * @since Android 1.0
      */
     @Deprecated
     public Date(int year, int month, int day, int hour, int minute) {
@@ -106,7 +108,7 @@
     /**
      * Constructs a new {@code Date} initialized to the specified date and time in the
      * default {@code TimeZone}.
-     * 
+     *
      * @param year
      *            the year, 0 is 1900.
      * @param month
@@ -119,10 +121,9 @@
      *            the minute of the hour, 0 - 59.
      * @param second
      *            the second of the minute, 0 - 59.
-     * 
+     *
      * @deprecated use
      *             {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int, int)}
-     * @since Android 1.0
      */
     @Deprecated
     public Date(int year, int month, int day, int hour, int minute, int second) {
@@ -134,24 +135,22 @@
     /**
      * Initializes this {@code Date} instance using the specified millisecond value. The
      * value is the number of milliseconds since Jan. 1, 1970 GMT.
-     * 
+     *
      * @param milliseconds
      *            the number of milliseconds since Jan. 1, 1970 GMT.
-     * @since Android 1.0
      */
     public Date(long milliseconds) {
-        this.setTime(milliseconds);
+        this.milliseconds = milliseconds;
     }
 
     /**
      * Constructs a new {@code Date} initialized to the date and time parsed from the
      * specified String.
-     * 
+     *
      * @param string
      *            the String to parse.
-     * 
+     *
      * @deprecated use {@link DateFormat}
-     * @since Android 1.0
      */
     @Deprecated
     public Date(String string) {
@@ -160,12 +159,11 @@
 
     /**
      * Returns if this {@code Date} is after the specified Date.
-     * 
+     *
      * @param date
      *            a Date instance to compare.
      * @return {@code true} if this {@code Date} is after the specified {@code Date},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean after(Date date) {
         return milliseconds > date.milliseconds;
@@ -173,12 +171,11 @@
 
     /**
      * Returns if this {@code Date} is before the specified Date.
-     * 
+     *
      * @param date
      *            a {@code Date} instance to compare.
      * @return {@code true} if this {@code Date} is before the specified {@code Date},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean before(Date date) {
         return milliseconds < date.milliseconds;
@@ -186,11 +183,10 @@
 
     /**
      * Returns a new {@code Date} with the same millisecond value as this {@code Date}.
-     * 
+     *
      * @return a shallow copy of this {@code Date}.
-     * 
+     *
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -204,12 +200,11 @@
     /**
      * Compare the receiver to the specified {@code Date} to determine the relative
      * ordering.
-     * 
+     *
      * @param date
      *            a {@code Date} to compare against.
      * @return an {@code int < 0} if this {@code Date} is less than the specified {@code Date}, {@code 0} if
      *         they are equal, and an {@code int > 0} if this {@code Date} is greater.
-     * @since Android 1.0
      */
     public int compareTo(Date date) {
         if (milliseconds < date.milliseconds) {
@@ -225,14 +220,13 @@
      * Compares the specified object to this {@code Date} and returns if they are equal.
      * To be equal, the object must be an instance of {@code Date} and have the same millisecond
      * value.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the specified object is equal to this {@code Date}, {@code false}
      *         otherwise.
-     * 
+     *
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -242,11 +236,10 @@
 
     /**
      * Returns the gregorian calendar day of the month for this {@code Date} object.
-     * 
+     *
      * @return the day of the month.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.DATE)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getDate() {
@@ -255,11 +248,10 @@
 
     /**
      * Returns the gregorian calendar day of the week for this {@code Date} object.
-     * 
+     *
      * @return the day of the week.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.DAY_OF_WEEK)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getDay() {
@@ -268,11 +260,10 @@
 
     /**
      * Returns the gregorian calendar hour of the day for this {@code Date} object.
-     * 
+     *
      * @return the hour of the day.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.HOUR_OF_DAY)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getHours() {
@@ -281,11 +272,10 @@
 
     /**
      * Returns the gregorian calendar minute of the hour for this {@code Date} object.
-     * 
+     *
      * @return the minutes.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.MINUTE)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getMinutes() {
@@ -294,11 +284,10 @@
 
     /**
      * Returns the gregorian calendar month for this {@code Date} object.
-     * 
+     *
      * @return the month.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.MONTH)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getMonth() {
@@ -307,11 +296,10 @@
 
     /**
      * Returns the gregorian calendar second of the minute for this {@code Date} object.
-     * 
+     *
      * @return the seconds.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.SECOND)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getSeconds() {
@@ -321,9 +309,8 @@
     /**
      * Returns this {@code Date} as a millisecond value. The value is the number of
      * milliseconds since Jan. 1, 1970, midnight GMT.
-     * 
+     *
      * @return the number of milliseconds since Jan. 1, 1970, midnight GMT.
-     * @since Android 1.0
      */
     public long getTime() {
         return milliseconds;
@@ -331,12 +318,11 @@
 
     /**
      * Returns the timezone offset in minutes of the default {@code TimeZone}.
-     * 
+     *
      * @return the timezone offset in minutes of the default {@code TimeZone}.
-     * 
+     *
      * @deprecated use
      *             {@code (Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / 60000}
-     * @since Android 1.0
      */
     @Deprecated
     public int getTimezoneOffset() {
@@ -346,11 +332,10 @@
 
     /**
      * Returns the gregorian calendar year since 1900 for this {@code Date} object.
-     * 
+     *
      * @return the year - 1900.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.YEAR) - 1900}
-     * @since Android 1.0
      */
     @Deprecated
     public int getYear() {
@@ -360,11 +345,10 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return this {@code Date}'s hash.
-     * 
+     *
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -384,13 +368,12 @@
      * Returns the millisecond value of the date and time parsed from the
      * specified {@code String}. Many date/time formats are recognized, including IETF
      * standard syntax, i.e. Tue, 22 Jun 1999 12:16:00 GMT-0500
-     * 
+     *
      * @param string
      *            the String to parse.
      * @return the millisecond value parsed from the String.
-     * 
+     *
      * @deprecated use {@link DateFormat}
-     * @since Android 1.0
      */
     @Deprecated
     public static long parse(String string) {
@@ -404,7 +387,7 @@
         int commentLevel = 0;
         int offset = 0, length = string.length(), state = 0;
         int year = -1, month = -1, date = -1;
-        int hour = -1, minute = -1, second = -1, zoneOffset = 0;
+        int hour = -1, minute = -1, second = -1, zoneOffset = 0, minutesOffset = 0;
         boolean zone = false;
         final int PAD = 0, LETTERS = 1, NUMBERS = 2;
         StringBuffer buffer = new StringBuffer();
@@ -442,6 +425,14 @@
                 if (sign == '+' || sign == '-') {
                     if (zoneOffset == 0) {
                         zone = true;
+                        if (next == ':') {
+                            minutesOffset = sign == '-' ? -Integer
+                                    .parseInt(string.substring(offset,
+                                            offset + 2)) : Integer
+                                    .parseInt(string.substring(offset,
+                                            offset + 2));
+                            offset += 2;
+                        }
                         zoneOffset = sign == '-' ? -digit : digit;
                         sign = 0;
                     } else {
@@ -557,6 +548,7 @@
             } else if (year < 100) {
                 year += 1900;
             }
+            minute -= minutesOffset;
             if (zone) {
                 if (zoneOffset >= 24 || zoneOffset <= -24) {
                     hour -= zoneOffset / 100;
@@ -574,12 +566,11 @@
 
     /**
      * Sets the gregorian calendar day of the month for this {@code Date} object.
-     * 
+     *
      * @param day
      *            the day of the month.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.DATE, day)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setDate(int day) {
@@ -590,12 +581,11 @@
 
     /**
      * Sets the gregorian calendar hour of the day for this {@code Date} object.
-     * 
+     *
      * @param hour
      *            the hour of the day.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.HOUR_OF_DAY, hour)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setHours(int hour) {
@@ -606,12 +596,11 @@
 
     /**
      * Sets the gregorian calendar minute of the hour for this {@code Date} object.
-     * 
+     *
      * @param minute
      *            the minutes.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.MINUTE, minute)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setMinutes(int minute) {
@@ -622,12 +611,11 @@
 
     /**
      * Sets the gregorian calendar month for this {@code Date} object.
-     * 
+     *
      * @param month
      *            the month.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.MONTH, month)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setMonth(int month) {
@@ -638,12 +626,11 @@
 
     /**
      * Sets the gregorian calendar second of the minute for this {@code Date} object.
-     * 
+     *
      * @param second
      *            the seconds.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.SECOND, second)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setSeconds(int second) {
@@ -655,10 +642,9 @@
     /**
      * Sets this {@code Date} to the specified millisecond value. The value is the
      * number of milliseconds since Jan. 1, 1970 GMT.
-     * 
+     *
      * @param milliseconds
      *            the number of milliseconds since Jan. 1, 1970 GMT.
-     * @since Android 1.0
      */
     public void setTime(long milliseconds) {
         this.milliseconds = milliseconds;
@@ -666,12 +652,11 @@
 
     /**
      * Sets the gregorian calendar year since 1900 for this {@code Date} object.
-     * 
+     *
      * @param year
      *            the year since 1900.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.YEAR, year + 1900)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setYear(int year) {
@@ -683,11 +668,10 @@
     /**
      * Returns the string representation of this {@code Date} in GMT in the format: 22
      * Jun 1999 13:02:00 GMT
-     * 
+     *
      * @return the string representation of this {@code Date} in GMT.
-     * 
+     *
      * @deprecated use {@link DateFormat}
-     * @since Android 1.0
      */
     @Deprecated
     public String toGMTString() {
@@ -705,11 +689,10 @@
 
     /**
      * Returns the string representation of this {@code Date} for the default {@code Locale}.
-     * 
+     *
      * @return the string representation of this {@code Date} for the default {@code Locale}.
-     * 
+     *
      * @deprecated use {@link DateFormat}
-     * @since Android 1.0
      */
     @Deprecated
     public String toLocaleString() {
@@ -719,20 +702,29 @@
     /**
      * Returns the string representation of this {@code Date} in the format: Tue Jun 22
      * 13:07:00 GMT 1999
-     * 
+     *
      * @return the string representation of this {@code Date}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
-        return new SimpleDateFormat("E MMM dd HH:mm:ss z ", Locale.US) //$NON-NLS-1$
-                .format(this)
-                + new GregorianCalendar(milliseconds).get(Calendar.YEAR);
+        Calendar cal = new GregorianCalendar(milliseconds);
+        return dayOfWeekNames[cal.get(Calendar.DAY_OF_WEEK) - 1] + " " + monthNames[cal.get(Calendar.MONTH)]//$NON-NLS-1$
+                + " " + toTwoDigits(cal.get(Calendar.DAY_OF_MONTH)) + " " + toTwoDigits(cal.get(Calendar.HOUR_OF_DAY))//$NON-NLS-1$ //$NON-NLS-2$
+                + ":" + toTwoDigits(cal.get(Calendar.MINUTE)) + ":" + toTwoDigits(cal.get(Calendar.SECOND))//$NON-NLS-1$ //$NON-NLS-2$
+                + " " + cal.getTimeZone().getID() + " " + cal.get(Calendar.YEAR);//$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    private String toTwoDigits(int digit) {
+        if(digit >= 10) {
+            return "" + digit;//$NON-NLS-1$
+        } else {
+            return "0" + digit;//$NON-NLS-1$
+        }
     }
 
     /**
      * Returns the millisecond value of the specified date and time in GMT.
-     * 
+     *
      * @param year
      *            the year, 0 is 1900.
      * @param month
@@ -746,12 +738,11 @@
      * @param second
      *            the second of the minute, 0 - 59.
      * @return the date and time in GMT in milliseconds.
-     * 
+     *
      * @deprecated use: <code>
      *  Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
      *  cal.set(year + 1900, month, day, hour, minute, second);
      *  cal.getTime().getTime();</code>
-     * @since Android 1.0
      */
     @Deprecated
     public static long UTC(int year, int month, int day, int hour, int minute,
diff --git a/luni/src/main/java/java/util/Dictionary.java b/luni/src/main/java/java/util/Dictionary.java
index 236ddf0..c29b11b 100644
--- a/luni/src/main/java/java/util/Dictionary.java
+++ b/luni/src/main/java/java/util/Dictionary.java
@@ -25,14 +25,11 @@
  * associate keys with values, such as {@code Hashtable}.
  * 
  * @see Hashtable
- * @since Android 1.0
+ * @since 1.0
  */
-public abstract class Dictionary<K,V> {
-
+public abstract class Dictionary<K, V> {
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public Dictionary() {
         super();
@@ -45,7 +42,6 @@
      * @see #keys
      * @see #size
      * @see Enumeration
-     * @since Android 1.0
      */
     public abstract Enumeration<V> elements();
 
@@ -57,7 +53,6 @@
      * @return the value associated with {@code key}, or {@code null} if the
      *         specified key does not exist.
      * @see #put
-     * @since Android 1.0
      */
     public abstract V get(Object key);
 
@@ -67,7 +62,6 @@
      * @return {@code true} if this dictionary has no key/value pairs,
      *         {@code false} otherwise.
      * @see #size
-     * @since Android 1.0
      */
     public abstract boolean isEmpty();
 
@@ -78,7 +72,6 @@
      * @see #elements
      * @see #size
      * @see Enumeration
-     * @since Android 1.0
      */
     public abstract Enumeration<K> keys();
 
@@ -96,7 +89,6 @@
      * @see #elements
      * @see #get
      * @see #keys
-     * @since Android 1.0
      */
     public abstract V put(K key, V value);
 
@@ -110,7 +102,6 @@
      *         {@code key} was not known to this dictionary.
      * @see #get
      * @see #put
-     * @since Android 1.0
      */
     public abstract V remove(Object key);
 
@@ -120,7 +111,6 @@
      * @return the number of key/value pairs in this dictionary.
      * @see #elements
      * @see #keys
-     * @since Android 1.0
      */
     public abstract int size();
 }
diff --git a/luni/src/main/java/java/util/DuplicateFormatFlagsException.java b/luni/src/main/java/java/util/DuplicateFormatFlagsException.java
index 908aa36..3330dcb 100644
--- a/luni/src/main/java/java/util/DuplicateFormatFlagsException.java
+++ b/luni/src/main/java/java/util/DuplicateFormatFlagsException.java
@@ -19,12 +19,11 @@
 /**
  * The unchecked exception will be thrown out if there are duplicate flags given
  * out in the format specifier.
- * 
+ *
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class DuplicateFormatFlagsException extends IllegalFormatException {
-    
+
     private static final long serialVersionUID = 18890531L;
 
     private String flags;
diff --git a/luni/src/main/java/java/util/EmptyStackException.java b/luni/src/main/java/java/util/EmptyStackException.java
index 73d33ba..d8a48cc 100644
--- a/luni/src/main/java/java/util/EmptyStackException.java
+++ b/luni/src/main/java/java/util/EmptyStackException.java
@@ -21,9 +21,8 @@
 /**
  * An {@code EmptyStackException} is thrown if the pop/peek method of a stack is
  * executed on an empty stack.
- * 
+ *
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class EmptyStackException extends RuntimeException {
 
diff --git a/luni/src/main/java/java/util/EnumMap.java b/luni/src/main/java/java/util/EnumMap.java
index 1351069..975fdad 100644
--- a/luni/src/main/java/java/util/EnumMap.java
+++ b/luni/src/main/java/java/util/EnumMap.java
@@ -24,11 +24,14 @@
 
 /**
  * An {@code Map} specialized for use with {@code Enum} types as keys.
- *  
- * @since Android 1.0
  */
 public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements
-        Map<K, V>, Serializable, Cloneable {
+        Serializable, Cloneable, Map<K, V> {
+
+    // BEGIN android-changed
+    // added implements Map<K, V> for apicheck
+    // END android-changed
+
     private static final long serialVersionUID = 458661240069192865L;
 
     private Class<K> keyType;
@@ -57,6 +60,7 @@
             ordinal = ((Enum) theKey).ordinal();
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public boolean equals(Object object) {
             if (!enumMap.hasMapping[ordinal]) {
@@ -83,18 +87,21 @@
                             : enumMap.values[ordinal].hashCode());
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public KT getKey() {
             checkEntryStatus();
             return (KT) enumMap.keys[ordinal];
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public VT getValue() {
             checkEntryStatus();
             return (VT) enumMap.values[ordinal];
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public VT setValue(VT value) {
             checkEntryStatus();
@@ -285,6 +292,7 @@
             super(value, em);
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public E next() {
             if (!hasNext()) {
@@ -354,6 +362,7 @@
             return toArray(entryArray);
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public Object[] toArray(Object[] array) {
             int size = enumMap.size();
@@ -378,10 +387,11 @@
 
     /**
      * Constructs an empty {@code EnumMap} using the given key type.
-     * 
+     *
      * @param keyType
      *            the class object giving the type of the keys used by this {@code EnumMap}.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code keyType} is {@code null}.
      */
     public EnumMap(Class<K> keyType) {
         initialization(keyType);
@@ -390,10 +400,11 @@
     /**
      * Constructs an {@code EnumMap} using the same key type as the given {@code EnumMap} and
      * initially containing the same mappings.
-     * 
+     *
      * @param map
      *            the {@code EnumMap} from which this {@code EnumMap} is initialized.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code map} is {@code null}.
      */
     public EnumMap(EnumMap<K, ? extends V> map) {
         initialization(map);
@@ -402,16 +413,18 @@
     /**
      * Constructs an {@code EnumMap} initialized from the given map. If the given map
      * is an {@code EnumMap} instance, this constructor behaves in the exactly the same
-     * way as {@link EnumMap#EnumMap(EnumMap)}}. Otherwise, the given map 
+     * way as {@link EnumMap#EnumMap(EnumMap)}}. Otherwise, the given map
      * should contain at least one mapping.
-     * 
+     *
      * @param map
      *            the map from which this {@code EnumMap} is initialized.
      * @throws IllegalArgumentException
      *             if {@code map} is not an {@code EnumMap} instance and does not contain
      *             any mappings.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code map} is {@code null}.
      */
+    @SuppressWarnings("unchecked")
     public EnumMap(Map<K, ? extends V> map) {
         if (map instanceof EnumMap) {
             initialization((EnumMap<K, V>) map);
@@ -433,10 +446,9 @@
 
     /**
      * Removes all elements from this {@code EnumMap}, leaving it empty.
-     * 
+     *
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -447,10 +459,10 @@
 
     /**
      * Returns a shallow copy of this {@code EnumMap}.
-     * 
+     *
      * @return a shallow copy of this {@code EnumMap}.
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     @Override
     public EnumMap<K, V> clone() {
         try {
@@ -464,12 +476,11 @@
 
     /**
      * Returns whether this {@code EnumMap} contains the specified key.
-     * 
+     *
      * @param key
      *            the key to search for.
      * @return {@code true} if this {@code EnumMap} contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsKey(Object key) {
@@ -482,12 +493,11 @@
 
     /**
      * Returns whether this {@code EnumMap} contains the specified value.
-     * 
+     *
      * @param value
      *            the value to search for.
      * @return {@code true} if this {@code EnumMap} contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsValue(Object value) {
@@ -511,9 +521,11 @@
      * Returns a {@code Set} containing all of the mappings in this {@code EnumMap}. Each mapping is
      * an instance of {@link Map.Entry}. As the {@code Set} is backed by this {@code EnumMap},
      * changes in one will be reflected in the other.
-     * 
+     * <p>
+     * The order of the entries in the set will be the order that the enum keys
+     * were declared in.
+     *
      * @return a {@code Set} of the mappings.
-     * @since Android 1.0
      */
     @Override
     public Set<Map.Entry<K, V>> entrySet() {
@@ -526,15 +538,15 @@
     /**
      * Compares the argument to the receiver, and returns {@code true} if the
      * specified {@code Object} is an {@code EnumMap} and both {@code EnumMap}s contain the same mappings.
-     * 
+     *
      * @param object
      *            the {@code Object} to compare with this {@code EnumMap}.
      * @return boolean {@code true} if {@code object} is the same as this {@code EnumMap},
      *         {@code false} otherwise.
      * @see #hashCode()
      * @see #entrySet()
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     @Override
     public boolean equals(Object object) {
         if (this == object) {
@@ -553,12 +565,11 @@
 
     /**
      * Returns the value of the mapping with the specified key.
-     * 
+     *
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -574,9 +585,11 @@
      * Returns a set of the keys contained in this {@code EnumMap}. The {@code Set} is backed by
      * this {@code EnumMap} so changes to one are reflected in the other. The {@code Set} does not
      * support adding.
-     * 
+     * <p>
+     * The order of the set will be the order that the enum keys were declared
+     * in.
+     *
      * @return a {@code Set} of the keys.
-     * @since Android 1.0
      */
     @Override
     public Set<K> keySet() {
@@ -588,7 +601,7 @@
 
     /**
      * Maps the specified key to the specified value.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
@@ -605,7 +618,6 @@
      * @throws NullPointerException
      *                if the key or value is {@code null} and this {@code EnumMap} does not
      *                support {@code null} keys or values.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -615,7 +627,7 @@
 
     /**
      * Copies every mapping in the specified {@code Map} to this {@code EnumMap}.
-     * 
+     *
      * @param map
      *            the {@code Map} to copy mappings from.
      * @throws UnsupportedOperationException
@@ -628,7 +640,6 @@
      * @throws NullPointerException
      *                if a key or value is {@code null} and this {@code EnumMap} does not
      *                support {@code null} keys or values.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -638,14 +649,13 @@
 
     /**
      * Removes a mapping with the specified key from this {@code EnumMap}.
-     * 
+     *
      * @param key
      *            the key of the mapping to remove.
      * @return the value of the removed mapping or {@code null} if no mapping
      *         for the specified key was found.
      * @throws UnsupportedOperationException
      *                if removing from this {@code EnumMap} is not supported.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -665,9 +675,8 @@
 
     /**
      * Returns the number of elements in this {@code EnumMap}.
-     * 
+     *
      * @return the number of elements in this {@code EnumMap}.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -680,9 +689,11 @@
      * {@link Map#values()}. The {@code Collection}'s {@code Iterator} will return the values
      * in the their corresponding keys' natural order (the {@code Enum} constants are
      * declared in this order).
-     * 
+     * <p>
+     * The order of the values in the collection will be the order that their
+     * corresponding enum keys were declared in.
+     *
      * @return a collection of the values contained in this {@code EnumMap}.
-     * @since Android 1.0
      */
     @Override
     public Collection<V> values() {
@@ -692,6 +703,7 @@
         return valuesCollection;
     }
 
+    @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
         stream.defaultReadObject();
diff --git a/luni/src/main/java/java/util/EnumSet.java b/luni/src/main/java/java/util/EnumSet.java
index 4e44f2e..d49d900 100644
--- a/luni/src/main/java/java/util/EnumSet.java
+++ b/luni/src/main/java/java/util/EnumSet.java
@@ -23,8 +23,6 @@
 
 /**
  * An EnumSet is a specialized Set to be used with enums as keys.
- * 
- * @since Android 1.0
  */
 public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
         implements Cloneable, Serializable {
@@ -37,7 +35,7 @@
     static /*package*/ LangAccess LANG_BOOTSTRAP = null;
     // END android-added
 
-    private static final long serialVersionUID = 4782406773684236311L;
+    private static final long serialVersionUID = 1009687484059888093L;
 
     final Class<E> elementClass;
 
@@ -48,14 +46,13 @@
     /**
      * Creates an empty enum set. The permitted elements are of type
      * Class&lt;E&gt;.
-     * 
+     *
      * @param elementType
      *            the class object for the elements contained.
      * @return an empty enum set, with permitted elements of type {@code
      *         elementType}.
      * @throws ClassCastException
      *             if the specified element type is not and enum type.
-     * @since Android 1.0
      */
     public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
         if (!elementType.isEnum()) {
@@ -73,13 +70,12 @@
     /**
      * Creates an enum set filled with all the enum elements of the specified
      * {@code elementType}.
-     * 
+     *
      * @param elementType
      *            the class object for the elements contained.
      * @return an enum set with elements solely from the specified element type.
      * @throws ClassCastException
      *             if the specified element type is not and enum type.
-     * @since Android 1.0
      */
     public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
         EnumSet<E> set = noneOf(elementType);
@@ -91,13 +87,12 @@
      * Creates an enum set. All the contained elements are of type
      * Class&lt;E&gt;, and the contained elements are the same as those
      * contained in {@code s}.
-     * 
+     *
      * @param s
      *            the enum set from which to copy.
      * @return an enum set with all the elements from the specified enum set.
      * @throws ClassCastException
      *             if the specified element type is not and enum type.
-     * @since Android 1.0
      */
     public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
         EnumSet<E> set = EnumSet.noneOf(s.elementClass);
@@ -109,14 +104,15 @@
      * Creates an enum set. The contained elements are the same as those
      * contained in collection {@code c}. If c is an enum set, invoking this
      * method is the same as invoking {@link #copyOf(EnumSet)}.
-     * 
+     *
      * @param c
      *            the collection from which to copy. if it is not an enum set,
      *            it must not be empty.
      * @return an enum set with all the elements from the specified collection.
      * @throws IllegalArgumentException
      *             if c is not an enum set and contains no elements at all.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code c} is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
         if (c instanceof EnumSet) {
@@ -138,12 +134,13 @@
     /**
      * Creates an enum set. All the contained elements complement those from the
      * specified enum set.
-     * 
+     *
      * @param s
      *            the specified enum set.
      * @return an enum set with all the elements complementary to those from the
      *         specified enum set.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code s} is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
         EnumSet<E> set = EnumSet.noneOf(s.elementClass);
@@ -159,11 +156,12 @@
      * six overloadings of the method. They accept from one to five elements
      * respectively. The sixth one receives an arbitrary number of elements, and
      * runs slower than those that only receive a fixed number of elements.
-     * 
+     *
      * @param e
      *            the element to be initially contained.
      * @return an enum set containing the specified element.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code e} is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e) {
         EnumSet<E> set = EnumSet.noneOf(e.getDeclaringClass());
@@ -172,17 +170,18 @@
     }
 
     /**
-     * Creates a new enum set, containing only the specified element. There are
+     * Creates a new enum set, containing only the specified elements. There are
      * six overloadings of the method. They accept from one to five elements
      * respectively. The sixth one receives an arbitrary number of elements, and
      * runs slower than those that only receive a fixed number of elements.
-     * 
+     *
      * @param e1
      *            the initially contained element.
      * @param e2
      *            another initially contained element.
-     * @return an enum set containing the specified element.
-     * @since Android 1.0
+     * @return an enum set containing the specified elements.
+     * @throws NullPointerException
+     *             if any of the specified elements is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) {
         EnumSet<E> set = of(e1);
@@ -191,19 +190,20 @@
     }
 
     /**
-     * Creates a new enum set, containing only the specified element. There are
+     * Creates a new enum set, containing only the specified elements. There are
      * six overloadings of the method. They accept from one to five elements
      * respectively. The sixth one receives an arbitrary number of elements, and
      * runs slower than those that only receive a fixed number of elements.
-     * 
+     *
      * @param e1
      *            the initially contained element.
      * @param e2
      *            another initially contained element.
      * @param e3
      *            another initially contained element.
-     * @return an enum set containing the specified element.
-     * @since Android 1.0
+     * @return an enum set containing the specified elements.
+     * @throws NullPointerException
+     *             if any of the specified elements is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) {
         EnumSet<E> set = of(e1, e2);
@@ -212,11 +212,11 @@
     }
 
     /**
-     * Creates a new enum set, containing only the specified element. There are
+     * Creates a new enum set, containing only the specified elements. There are
      * six overloadings of the method. They accept from one to five elements
      * respectively. The sixth one receives an arbitrary number of elements, and
      * runs slower than those that only receive a fixed number of elements.
-     * 
+     *
      * @param e1
      *            the initially contained element.
      * @param e2
@@ -225,8 +225,9 @@
      *            another initially contained element.
      * @param e4
      *            another initially contained element.
-     * @return an enum set containing the specified element.
-     * @since Android 1.0
+     * @return an enum set containing the specified elements.
+     * @throws NullPointerException
+     *             if any of the specified elements is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) {
         EnumSet<E> set = of(e1, e2, e3);
@@ -235,11 +236,11 @@
     }
 
     /**
-     * Creates a new enum set, containing only the specified element. There are
+     * Creates a new enum set, containing only the specified elements. There are
      * six overloadings of the method. They accept from one to five elements
      * respectively. The sixth one receives an arbitrary number of elements, and
      * runs slower than those that only receive a fixed number of elements.
-     * 
+     *
      * @param e1
      *            the initially contained element.
      * @param e2
@@ -250,8 +251,9 @@
      *            another initially contained element.
      * @param e5
      *            another initially contained element.
-     * @return an enum set containing the specified element.
-     * @since Android 1.0
+     * @return an enum set containing the specified elements.
+     * @throws NullPointerException
+     *             if any of the specified elements is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5) {
         EnumSet<E> set = of(e1, e2, e3, e4);
@@ -263,13 +265,14 @@
      * Creates a new enum set, containing only the specified elements. It can
      * receive an arbitrary number of elements, and runs slower than those only
      * receiving a fixed number of elements.
-     * 
+     *
      * @param start
      *            the first initially contained element.
      * @param others
      *            the other initially contained elements.
      * @return an enum set containing the specified elements.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if any of the specified elements is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E start, E... others) {
         EnumSet<E> set = of(start);
@@ -283,15 +286,16 @@
      * Creates an enum set containing all the elements within the range defined
      * by {@code start} and {@code end} (inclusive). All the elements must be in
      * order.
-     * 
+     *
      * @param start
      *            the element used to define the beginning of the range.
      * @param end
      *            the element used to define the end of the range.
      * @return an enum set with elements in the range from start to end.
+     * @throws NullPointerException
+     *             if any one of {@code start} or {@code end} is {@code null}.
      * @throws IllegalArgumentException
      *             if {@code start} is behind {@code end}.
-     * @since Android 1.0
      */
     public static <E extends Enum<E>> EnumSet<E> range(E start, E end) {
         if (start.compareTo(end) > 0) {
@@ -307,10 +311,9 @@
     /**
      * Creates a new enum set with the same elements as those contained in this
      * enum set.
-     * 
+     *
      * @return a new enum set with the same elements as those contained in this
      *         enum set.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     @Override
diff --git a/luni/src/main/java/java/util/Enumeration.java b/luni/src/main/java/java/util/Enumeration.java
index d60bdd2..8b8f7bd 100644
--- a/luni/src/main/java/java/util/Enumeration.java
+++ b/luni/src/main/java/java/util/Enumeration.java
@@ -17,18 +17,16 @@
 
 package java.util;
 
-
 /**
  * An Enumeration is used to sequence over a collection of objects.
  * <p>
- * Preferably an Iterator should be used. Iterator replaces the Enumeration
- * interface and adds a way to remove elements from a collection.
- * </p>
- * 
+ * Preferably an {@link Iterator} should be used. {@code Iterator} replaces the
+ * enumeration interface and adds a way to remove elements from a collection.
+ *
  * @see Hashtable
  * @see Properties
  * @see Vector
- * @since Android 1.0
+ * @version 1.0
  */
 public interface Enumeration<E> {
 
@@ -37,7 +35,6 @@
      * 
      * @return {@code true} if there are more elements, {@code false} otherwise.
      * @see #nextElement
-     * @since Android 1.0
      */
     public boolean hasMoreElements();
 
@@ -48,7 +45,6 @@
      * @throws NoSuchElementException
      *             if there are no more elements.
      * @see #hasMoreElements
-     * @since Android 1.0
      */
     public E nextElement();
 }
diff --git a/luni/src/main/java/java/util/EventListener.java b/luni/src/main/java/java/util/EventListener.java
index 9ff4876..b100f0c 100644
--- a/luni/src/main/java/java/util/EventListener.java
+++ b/luni/src/main/java/java/util/EventListener.java
@@ -17,13 +17,11 @@
 
 package java.util;
 
-
 /**
  * EventListener is the superclass of all event listener interfaces.
- *
+ * 
  * @see EventObject
- * @since Android 1.0
  */
 public interface EventListener {
-    /*empty*/
+    /* empty */
 }
diff --git a/luni/src/main/java/java/util/EventListenerProxy.java b/luni/src/main/java/java/util/EventListenerProxy.java
index a165385..1e023f6 100644
--- a/luni/src/main/java/java/util/EventListenerProxy.java
+++ b/luni/src/main/java/java/util/EventListenerProxy.java
@@ -20,8 +20,6 @@
 
 /**
  * This abstract class provides a simple wrapper for objects of type {@code EventListener}.
- *  
- * @since Android 1.0
  */
 public abstract class EventListenerProxy implements EventListener {
 
@@ -32,7 +30,6 @@
      * 
      * @param listener
      *            the listener wrapped by this proxy.
-     * @since Android 1.0
      */
     public EventListenerProxy(EventListener listener) {
         super();
@@ -43,7 +40,6 @@
      * Returns the wrapped {@code EventListener}.
      * 
      * @return the wrapped {@code EventListener}.
-     * @since Android 1.0
      */
     public EventListener getListener() {
         return listener;
diff --git a/luni/src/main/java/java/util/EventObject.java b/luni/src/main/java/java/util/EventObject.java
index 61e530a..76da7e2 100644
--- a/luni/src/main/java/java/util/EventObject.java
+++ b/luni/src/main/java/java/util/EventObject.java
@@ -25,8 +25,6 @@
  * add event specific information.
  * 
  * @see EventListener
- *  
- * @since Android 1.0
  */
 public class EventObject implements Serializable {
     
@@ -34,8 +32,6 @@
 
     /**
      * The event source.
-     * 
-     * @since Android 1.0
      */
     protected transient Object source;
 
@@ -44,7 +40,6 @@
      * 
      * @param source
      *            the object which fired the event.
-     * @since Android 1.0
      */
     public EventObject(Object source) {
         if (source != null) {
@@ -58,7 +53,6 @@
      * Returns the event source.
      * 
      * @return the object which fired the event.
-     * @since Android 1.0
      */
     public Object getSource() {
         return source;
@@ -68,7 +62,6 @@
      * Returns the string representation of this {@code EventObject}.
      * 
      * @return the string representation of this {@code EventObject}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java b/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java
index aa0c967..e4f39d2 100644
--- a/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java
+++ b/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java
@@ -23,7 +23,6 @@
  * conversion and the flags are incompatible.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class FormatFlagsConversionMismatchException extends
         IllegalFormatException implements Serializable {
diff --git a/luni/src/main/java/java/util/Formattable.java b/luni/src/main/java/java/util/Formattable.java
index 2564c04..15b66b5 100644
--- a/luni/src/main/java/java/util/Formattable.java
+++ b/luni/src/main/java/java/util/Formattable.java
@@ -20,16 +20,15 @@
  * Classes that handle custom formatting for the 's' specifier of {@code Formatter}
  * should implement the {@code Formattable} interface. It gives basic control over
  * formatting objects.
- *  
+ *
  * @see Formatter
- * @since Android 1.0
  */
 
 public interface Formattable {
 
     /**
      * Formats the object using the specified {@code Formatter}.
-     * 
+     *
      * @param formatter
      *            the {@code Formatter} to use.
      * @param flags
@@ -54,7 +53,6 @@
      *            is -1, then maximum length is not enforced.
      * @throws IllegalFormatException
      *             if any of the parameters is not supported.
-     * @since Android 1.0
      */
     void formatTo(Formatter formatter, int flags, int width, int precision)
             throws IllegalFormatException;
diff --git a/luni/src/main/java/java/util/FormattableFlags.java b/luni/src/main/java/java/util/FormattableFlags.java
index b5078e4..b8d44d4 100644
--- a/luni/src/main/java/java/util/FormattableFlags.java
+++ b/luni/src/main/java/java/util/FormattableFlags.java
@@ -22,7 +22,6 @@
  * flags must be done by the implementations.
  *  
  * @see Formattable
- * @since Android 1.0
  */
 public class FormattableFlags {
     
@@ -37,8 +36,6 @@
      * right-justified.
      * 
      * The flag corresponds to '-' ('\u002d') in the format specifier.
-     * 
-     * @since Android 1.0
      */
     public static final int LEFT_JUSTIFY = 1;
 
@@ -48,8 +45,6 @@
      * effect as {@code String.toUpperCase(java.util.Locale)}.
      * 
      * This flag corresponds to {@code '^' ('\u005e')} in the format specifier.
-     * 
-     * @since Android 1.0
      */
     public static final int UPPERCASE = 2;
 
@@ -58,8 +53,6 @@
      * of the alternate form is determined by the {@code Formattable}.
      * 
      * This flag corresponds to {@code '#' ('\u0023')} in the format specifier.
-     * 
-     * @since Android 1.0
      */
     public static final int ALTERNATE = 4;
 }
diff --git a/luni/src/main/java/java/util/Formatter.java b/luni/src/main/java/java/util/Formatter.java
index a6f14f0..d1dd417 100644
--- a/luni/src/main/java/java/util/Formatter.java
+++ b/luni/src/main/java/java/util/Formatter.java
@@ -28,6 +28,7 @@
 import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.math.MathContext;
 import java.nio.CharBuffer;
 import java.nio.charset.Charset;
 import java.security.AccessController;
@@ -37,63 +38,59 @@
 import java.text.DecimalFormatSymbols;
 import java.text.NumberFormat;
 
-// BEGIN android-note
-// Added quite extensive class documentation. Almost none was present before.
-// END android-note
-
 /**
  * <p>The {@code Formatter} class is a String-formatting utility that is designed
- * to work like the {@code printf} function of the C programming language. 
+ * to work like the {@code printf} function of the C programming language.
  * Its key methods are the {@code format} methods which create a formatted
- * {@code String} by replacing a set of placeholders (format tokens) with formatted 
+ * {@code String} by replacing a set of placeholders (format tokens) with formatted
  * values. The style used to format each value is determined by the format
  * token used.  For example, the call<br/>
  * {@code format("My decimal value is %d and my String is %s.", 3, "Hello");}<br/>
  * returns the {@code String}<br/>
- * {@code My decimal value is 3 and my String is Hello.}</p>
- * 
- *<p>The format token consists of a percent sign, optionally followed 
- * by flags and precision arguments, and then a single character that 
+ * {@code My decimal value is 3 and my String is Hello.}
+ *
+ * <p>The format token consists of a percent sign, optionally followed
+ * by flags and precision arguments, and then a single character that
  * indicates the type of value
  * being formatted.  If the type is a time/date, then the type character
- * {@code t} is followed by an additional character that indicates how the 
- * date is to be formatted. The two characters {@code <$} immediately 
+ * {@code t} is followed by an additional character that indicates how the
+ * date is to be formatted. The two characters {@code <$} immediately
  * following the % sign indicate that the previous value should be used again
  * instead of moving on to the next value argument. A number {@code n}
  * and a dollar sign immediately following the % sign make n the next argument
- * to be used.</p>  
- * 
- * <p>The available choices are the following:</p>
- * 
+ * to be used.
+ *
+ * <p>The available choices are the following:
+ *
  * <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Text value types</B></TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code s}</td> 
- * <td width="10%">String</td> 
- * <td width="30%">{@code format("%s, %s", "hello", "Hello");}</td> 
- * <td width="30%">{@code hello, Hello}</td> 
- * </tr>  
+ * <td width="5%">{@code s}</td>
+ * <td width="10%">String</td>
+ * <td width="30%">{@code format("%s, %s", "hello", "Hello");}</td>
+ * <td width="30%">{@code hello, Hello}</td>
+ * </tr>
  * <tr>
- * <td width="5%">{@code S}, {@code s}</td> 
- * <td width="10%">String to capitals</td> 
- * <td width="30%">{@code format("%S, %S", "hello", "Hello");}</td> 
- * <td width="30%">{@code HELLO, HELLO}</td> 
- * </tr>  
+ * <td width="5%">{@code S}, {@code s}</td>
+ * <td width="10%">String to capitals</td>
+ * <td width="30%">{@code format("%S, %S", "hello", "Hello");}</td>
+ * <td width="30%">{@code HELLO, HELLO}</td>
+ * </tr>
  * <tr>
- * <td width="5%">{@code c}</td> 
- * <td width="10%">Character</td> 
- * <td width="30%">{@code format("%c, %c", 'd', 0x65);}</td> 
+ * <td width="5%">{@code c}</td>
+ * <td width="10%">Character</td>
+ * <td width="30%">{@code format("%c, %c", 'd', 0x65);}</td>
  * <td width="30%">{@code d, e}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code C}</td> 
- * <td width="10%">Character to capitals</td> 
- * <td width="30%">{@code format("%C, %C", 'd', 0x65);}</td> 
+ * <td width="5%">{@code C}</td>
+ * <td width="10%">Character to capitals</td>
+ * <td width="30%">{@code format("%C, %C", 'd', 0x65);}</td>
  * <td width="30%">{@code D, E}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Text option flags</B><br/>The value between the
@@ -101,33 +98,33 @@
  * characters of the formatted value  </TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code -}</td> 
- * <td width="10%">Left justify (width value is required)</td> 
- * <td width="30%">{@code format("%-3C, %3C", 'd', 0x65);}</td> 
+ * <td width="5%">{@code -}</td>
+ * <td width="10%">Left justify (width value is required)</td>
+ * <td width="30%">{@code format("%-3C, %3C", 'd', 0x65);}</td>
  * <td width="30%">{@code D  ,   E}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Integer types</B></TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code d}</td> 
- * <td width="10%">int, formatted as decimal</td> 
- * <td width="30%">{@code format("%d, %d"1$, 35, 0x10);}</td> 
+ * <td width="5%">{@code d}</td>
+ * <td width="10%">int, formatted as decimal</td>
+ * <td width="30%">{@code format("%d, %d"1$, 35, 0x10);}</td>
  * <td width="30%">{@code 35, 16}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code o}</td> 
- * <td width="10%">int, formatted as octal</td> 
- * <td width="30%">{@code format("%o, %o", 8, 010);}</td> 
+ * <td width="5%">{@code o}</td>
+ * <td width="10%">int, formatted as octal</td>
+ * <td width="30%">{@code format("%o, %o", 8, 010);}</td>
  * <td width="30%">{@code 10, 10}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code X}, {@code x}</td> 
- * <td width="10%">int, formatted as hexidecimal</td> 
- * <td width="30%">{@code format("%x, %X", 10, 10);}</td> 
+ * <td width="5%">{@code X}, {@code x}</td>
+ * <td width="10%">int, formatted as hexidecimal</td>
+ * <td width="30%">{@code format("%x, %X", 10, 10);}</td>
  * <td width="30%">{@code a, A}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Integer option flags</B><br/>The value between the
@@ -135,43 +132,43 @@
  * characters of the formatted value  </TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code +}</td> 
- * <td width="10%">lead with the number's sign</td> 
- * <td width="30%">{@code format("%+d, %+4d", 5, 5);}</td> 
+ * <td width="5%">{@code +}</td>
+ * <td width="10%">lead with the number's sign</td>
+ * <td width="30%">{@code format("%+d, %+4d", 5, 5);}</td>
  * <td width="30%">{@code +5,   +5}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code -}</td> 
- * <td width="10%">Left justify (width value is required)</td> 
- * <td width="30%">{@code format("%-6dx", 5);}</td> 
+ * <td width="5%">{@code -}</td>
+ * <td width="10%">Left justify (width value is required)</td>
+ * <td width="30%">{@code format("%-6dx", 5);}</td>
  * <td width="30%">{@code 5      x}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code #}</td> 
- * <td width="10%">Print the leading characters that indicate 
- * hexidecimal or octal (for use only with hex and octal types) </td> 
- * <td width="30%">{@code format("%#o", 010);}</td> 
+ * <td width="5%">{@code #}</td>
+ * <td width="10%">Print the leading characters that indicate
+ * hexidecimal or octal (for use only with hex and octal types) </td>
+ * <td width="30%">{@code format("%#o", 010);}</td>
  * <td width="30%">{@code 010}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code  }</td> 
- * <td width="10%">A space indicates that non-negative numbers 
- * should have a leading space. </td> 
- * <td width="30%">{@code format("x% d% 5d", 4, 4);}</td> 
+ * <td width="5%">{@code  }</td>
+ * <td width="10%">A space indicates that non-negative numbers
+ * should have a leading space. </td>
+ * <td width="30%">{@code format("x% d% 5d", 4, 4);}</td>
  * <td width="30%">{@code x 4    4}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code 0}</td> 
- * <td width="10%">Pad the number with leading zeros (width value is required)</td> 
- * <td width="30%">{@code format("%07d, %03d", 4, 5555);}</td> 
+ * <td width="5%">{@code 0}</td>
+ * <td width="10%">Pad the number with leading zeros (width value is required)</td>
+ * <td width="30%">{@code format("%07d, %03d", 4, 5555);}</td>
  * <td width="30%">{@code 0000004, 5555}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code (}</td> 
- * <td width="10%">Put parentheses around negative numbers (decimal only)</td> 
- * <td width="30%">{@code format("%(d, %(d, %(6d", 12, -12, -12);}</td> 
+ * <td width="5%">{@code (}</td>
+ * <td width="10%">Put parentheses around negative numbers (decimal only)</td>
+ * <td width="30%">{@code format("%(d, %(d, %(6d", 12, -12, -12);}</td>
  * <td width="30%">{@code 12, (12),   (12)}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Float types</B><br/>A value immediately following the % symbol
@@ -180,229 +177,223 @@
  * gives the precision (6 by default).</TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code f}</td> 
- * <td width="10%">float (or double) formatted as a decimal, where 
- * the precision indicates the number of digits after the decimal.</td> 
- * <td width="30%">{@code format("%f %<.1f %<1.5f %<10f %<6.0f", 123.456f);}</td> 
+ * <td width="5%">{@code f}</td>
+ * <td width="10%">float (or double) formatted as a decimal, where
+ * the precision indicates the number of digits after the decimal.</td>
+ * <td width="30%">{@code format("%f %<.1f %<1.5f %<10f %<6.0f", 123.456f);}</td>
  * <td width="30%">{@code 123.456001 123.5 123.45600 123.456001    123}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code E}, {@code e}</td> 
+ * <td width="5%">{@code E}, {@code e}</td>
  * <td width="10%">float (or double) formatted in decimal exponential
- * notation, where the precision indicates the number of significant digits.</td> 
- * <td width="30%">{@code format("%E %<.1e %<1.5E %<10E %<6.0E", 123.456f);}</td> 
+ * notation, where the precision indicates the number of significant digits.</td>
+ * <td width="30%">{@code format("%E %<.1e %<1.5E %<10E %<6.0E", 123.456f);}</td>
  * <td width="30%">{@code 1.234560E+02 1.2e+02 1.23456E+02 1.234560E+02  1E+02}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code G}, {@code g}</td> 
+ * <td width="5%">{@code G}, {@code g}</td>
  * <td width="10%">float (or double) formatted in decimal exponential
- * notation , where the precision indicates the maximum number of significant digits.</td> 
- * <td width="30%">{@code format("%G %<.1g %<1.5G %<10G %<6.0G", 123.456f);}</td> 
+ * notation , where the precision indicates the maximum number of significant digits.</td>
+ * <td width="30%">{@code format("%G %<.1g %<1.5G %<10G %<6.0G", 123.456f);}</td>
  * <td width="30%">{@code 123.456 1e+02 123.46    123.456  1E+02}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code A}, {@code a}</td> 
+ * <td width="5%">{@code A}, {@code a}</td>
  * <td width="10%">float (or double) formatted as a hexidecimal in exponential
- * notation, where the precision indicates the number of significant digits.</td> 
- * <td width="30%">{@code format("%A %<.1a %<1.5A %<10A %<6.0A", 123.456f);}</td> 
+ * notation, where the precision indicates the number of significant digits.</td>
+ * <td width="30%">{@code format("%A %<.1a %<1.5A %<10A %<6.0A", 123.456f);}</td>
  * <td width="30%">{@code 0X1.EDD2F2P6 0x1.fp6 0X1.EDD2FP6 0X1.EDD2F2P6 0X1.FP6}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
- * <B>Float-type option flags</B><br/>See the Integer-type options.  
+ * <B>Float-type option flags</B><br/>See the Integer-type options.
  * The options for float-types are the
  * same as for integer types with one addition: </TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code ,}</td> 
+ * <td width="5%">{@code ,}</td>
  * <td width="10%">Use a comma in place of a decimal if the locale
- * requires it. </td> 
- * <td width="30%">{@code format(new Locale("fr"), "%,7.2f", 6.03f);}</td> 
+ * requires it. </td>
+ * <td width="30%">{@code format(new Locale("fr"), "%,7.2f", 6.03f);}</td>
  * <td width="30%">{@code    6,03}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Date types</B></TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code t}, {@code T}</td> 
- * <td width="10%">Date</td> 
- * <td width="30%">{@code format(new Locale("fr"), "%tB %TB", Calendar.getInstance(), Calendar.getInstance());}</td> 
+ * <td width="5%">{@code t}, {@code T}</td>
+ * <td width="10%">Date</td>
+ * <td width="30%">{@code format(new Locale("fr"), "%tB %TB", Calendar.getInstance(), Calendar.getInstance());}</td>
  * <td width="30%">{@code avril AVRIL}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
- * <B>Date format precisions</B><br/>The format precision character 
+ * <B>Date format precisions</B><br/>The format precision character
  * follows the {@code t}. </TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code A}, {@code a}</td> 
- * <td width="10%">The day of the week</td> 
- * <td width="30%">{@code format("%ta %tA", cal, cal);}</td> 
+ * <td width="5%">{@code A}, {@code a}</td>
+ * <td width="10%">The day of the week</td>
+ * <td width="30%">{@code format("%ta %tA", cal, cal);}</td>
  * <td width="30%">{@code Tue Tuesday}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code b}, {@code B}, {@code h}</td> 
- * <td width="10%">The name of the month</td> 
- * <td width="30%">{@code format("%tb %<tB %<th", cal, cal, cal);}</td> 
+ * <td width="5%">{@code b}, {@code B}, {@code h}</td>
+ * <td width="10%">The name of the month</td>
+ * <td width="30%">{@code format("%tb %<tB %<th", cal, cal, cal);}</td>
  * <td width="30%">{@code Apr April Apr}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code C}</td> 
- * <td width="10%">The century</td> 
- * <td width="30%">{@code format("%tC\n", cal);}</td> 
+ * <td width="5%">{@code C}</td>
+ * <td width="10%">The century</td>
+ * <td width="30%">{@code format("%tC\n", cal);}</td>
  * <td width="30%">{@code 20}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code d}, {@code e}</td> 
- * <td width="10%">The day of the month (with or without leading zeros)</td> 
- * <td width="30%">{@code format("%td %te", cal, cal);}</td> 
+ * <td width="5%">{@code d}, {@code e}</td>
+ * <td width="10%">The day of the month (with or without leading zeros)</td>
+ * <td width="30%">{@code format("%td %te", cal, cal);}</td>
  * <td width="30%">{@code 01 1}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code F}</td> 
- * <td width="10%">The complete date formatted as YYYY-MM-DD</td> 
- * <td width="30%">{@code format("%tF", cal);}</td> 
+ * <td width="5%">{@code F}</td>
+ * <td width="10%">The complete date formatted as YYYY-MM-DD</td>
+ * <td width="30%">{@code format("%tF", cal);}</td>
  * <td width="30%">{@code 2008-04-01}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code D}</td> 
- * <td width="10%">The complete date formatted as MM/DD/YY 
- * (not corrected for locale) </td> 
- * <td width="30%">{@code format(new Locale("en_US"), "%tD", cal);<br/>format(new Locale("en_UK"), " %tD", cal);}</td> 
+ * <td width="5%">{@code D}</td>
+ * <td width="10%">The complete date formatted as MM/DD/YY
+ * (not corrected for locale) </td>
+ * <td width="30%">{@code format(new Locale("en_US"), "%tD", cal);<br/>format(new Locale("en_UK"), " %tD", cal);}</td>
  * <td width="30%">{@code 04/01/08 04/01/08}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code j}</td> 
- * <td width="10%">The number of the day (from the beginning of the year).</td> 
- * <td width="30%">{@code format("%tj\n", cal);}</td> 
+ * <td width="5%">{@code j}</td>
+ * <td width="10%">The number of the day (from the beginning of the year).</td>
+ * <td width="30%">{@code format("%tj\n", cal);}</td>
  * <td width="30%">{@code 092}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code m}</td> 
- * <td width="10%">The number of the month</td> 
- * <td width="30%">{@code format("%tm\n", cal);}</td> 
+ * <td width="5%">{@code m}</td>
+ * <td width="10%">The number of the month</td>
+ * <td width="30%">{@code format("%tm\n", cal);}</td>
  * <td width="30%">{@code 04}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code y}, {@code Y}</td> 
- * <td width="10%">The year</td> 
- * <td width="30%">{@code format("%ty %tY", cal, cal);}</td> 
+ * <td width="5%">{@code y}, {@code Y}</td>
+ * <td width="10%">The year</td>
+ * <td width="30%">{@code format("%ty %tY", cal, cal);}</td>
  * <td width="30%">{@code 08 2008}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code H}, {@code I}, {@code k}, {@code l}</td> 
+ * <td width="5%">{@code H}, {@code I}, {@code k}, {@code l}</td>
  * <td width="10%">The hour of the day, in 12 or 24 hour format, with or
- * without a leading zero</td> 
- * <td width="30%">{@code format("%tH %tI %tk %tl", cal, cal, cal, cal);}</td> 
+ * without a leading zero</td>
+ * <td width="30%">{@code format("%tH %tI %tk %tl", cal, cal, cal, cal);}</td>
  * <td width="30%">{@code 16 04 16 4}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code p}</td> 
- * <td width="10%">a.m. or p.m.</td> 
- * <td width="30%">{@code format("%tp %Tp", cal, cal);}</td> 
+ * <td width="5%">{@code p}</td>
+ * <td width="10%">a.m. or p.m.</td>
+ * <td width="30%">{@code format("%tp %Tp", cal, cal);}</td>
  * <td width="30%">{@code pm PM}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code M}, {@code S}, {@code L}, {@code N}</td> 
- * <td width="10%">The minutes, seconds, milliseconds, and nanoseconds</td> 
- * <td width="30%">{@code format("%tM %tS %tL %tN", cal, cal, cal, cal);}</td> 
+ * <td width="5%">{@code M}, {@code S}, {@code L}, {@code N}</td>
+ * <td width="10%">The minutes, seconds, milliseconds, and nanoseconds</td>
+ * <td width="30%">{@code format("%tM %tS %tL %tN", cal, cal, cal, cal);}</td>
  * <td width="30%">{@code 08 17 359 359000000}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code Z}, {@code z}</td> 
- * <td width="10%">The time zone: its abbreviation or offset from GMT</td> 
- * <td width="30%">{@code format("%tZ %tz", cal, cal);}</td> 
+ * <td width="5%">{@code Z}, {@code z}</td>
+ * <td width="10%">The time zone: its abbreviation or offset from GMT</td>
+ * <td width="30%">{@code format("%tZ %tz", cal, cal);}</td>
  * <td width="30%">{@code CEST +0100}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code R}, {@code r}, {@code T}</td> 
- * <td width="10%">The complete time</td> 
- * <td width="30%">{@code format("%tR %tr %tT", cal, cal, cal);}</td> 
+ * <td width="5%">{@code R}, {@code r}, {@code T}</td>
+ * <td width="10%">The complete time</td>
+ * <td width="30%">{@code format("%tR %tr %tT", cal, cal, cal);}</td>
  * <td width="30%">{@code 16:15 04:15:32 PM 16:15:32}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code s}, {@code Q}</td> 
+ * <td width="5%">{@code s}, {@code Q}</td>
  * <td width="10%">The number of seconds or milliseconds from "the epoch"
- * (1 January 1970 00:00:00 UTC) </td> 
- * <td width="30%">{@code format("%ts %tQ", cal, cal);}</td> 
+ * (1 January 1970 00:00:00 UTC) </td>
+ * <td width="30%">{@code format("%ts %tQ", cal, cal);}</td>
  * <td width="30%">{@code 1207059412 1207059412656}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code c}</td> 
- * <td width="10%">The complete time and date</td> 
- * <td width="30%">{@code format("%tc", cal);}</td> 
+ * <td width="5%">{@code c}</td>
+ * <td width="10%">The complete time and date</td>
+ * <td width="30%">{@code format("%tc", cal);}</td>
  * <td width="30%">{@code Tue Apr 01 16:19:17 CEST 2008}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Other data types</B></TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code B}, {@code b}</td> 
- * <td width="10%">Boolean</td> 
- * <td width="30%">{@code format("%b, %B", true, false);}</td> 
+ * <td width="5%">{@code B}, {@code b}</td>
+ * <td width="10%">Boolean</td>
+ * <td width="30%">{@code format("%b, %B", true, false);}</td>
  * <td width="30%">{@code true, FALSE}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code H}, {@code h}</td> 
- * <td width="10%">Hashcode</td> 
- * <td width="30%">{@code format("%h, %H", obj, obj);}</td> 
+ * <td width="5%">{@code H}, {@code h}</td>
+ * <td width="10%">Hashcode</td>
+ * <td width="30%">{@code format("%h, %H", obj, obj);}</td>
  * <td width="30%">{@code 190d11, 190D11}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code n}</td> 
- * <td width="10%">line separator</td> 
- * <td width="30%">{@code format("first%nsecond", "???");}</td> 
+ * <td width="5%">{@code n}</td>
+ * <td width="10%">line separator</td>
+ * <td width="30%">{@code format("first%nsecond", "???");}</td>
  * <td width="30%">{@code first<br/>second}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Escape sequences</B></TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code %}</td> 
- * <td width="10%">Escape the % character</td> 
- * <td width="30%">{@code format("%d%%, %d", 50, 60);}</td> 
+ * <td width="5%">{@code %}</td>
+ * <td width="10%">Escape the % character</td>
+ * <td width="30%">{@code format("%d%%, %d", 50, 60);}</td>
  * <td width="30%">{@code 50%, 60}</td>
- * </tr>  
- * </table>   
- * 
+ * </tr>
+ * </table>
+ *
  * <p>An instance of Formatter can be created to write the formatted
- * output to standard types of output streams.  Its functionality can 
- * also be accessed through the format methods of an output stream 
+ * output to standard types of output streams.  Its functionality can
+ * also be accessed through the format methods of an output stream
  * or of {@code String}:<br/>
  * {@code System.out.println(String.format("%ty\n", cal));}<br/>
- * {@code System.out.format("%ty\n", cal);}</p>
- * 
- * <p>The class is not multi-threaded safe. The user is responsible for 
+ * {@code System.out.format("%ty\n", cal);}
+ *
+ * <p>The class is not multi-threaded safe. The user is responsible for
  * maintaining a thread-safe design if a {@code Formatter} is
- * accessed by multiple threads. </p>
- * 
- * @since Android 1.0
+ * accessed by multiple threads.
+ *
+ * @since 1.5
  */
 public final class Formatter implements Closeable, Flushable {
 
-    // BEGIN android-changed
     /**
      * The enumeration giving the available styles for formatting very large
      * decimal numbers.
-     * 
-     * @since Android 1.0
-     */    
+     */
     public enum BigDecimalLayoutForm {
         /**
          * Use scientific style for BigDecimals.
-         * @since Android 1.0
          */
-        SCIENTIFIC, 
+        SCIENTIFIC,
         /**
          * Use normal decimal/float style for BigDecimals.
-         * @since Android 1.0
          */
         DECIMAL_FLOAT
     }
-    // END android-changed
 
     private Appendable out;
 
@@ -414,29 +405,26 @@
 
     /**
      * Constructs a {@code Formatter}.
-     * 
+     *
      * The output is written to a {@code StringBuilder} which can be acquired by invoking
      * {@link #out()} and whose content can be obtained by calling
      * {@code toString()}.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
-     * @since Android 1.0
      */
     public Formatter() {
         this(new StringBuilder(), Locale.getDefault());
     }
 
     /**
-     * Constructs a {@code Formatter} whose output will be written to the 
+     * Constructs a {@code Formatter} whose output will be written to the
      * specified {@code Appendable}.
-     * 
+     *
      * The locale for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param a
      *            the output destination of the {@code Formatter}. If {@code a} is {@code null},
      *            then a {@code StringBuilder} will be used.
-     * @since Android 1.0
      */
     public Formatter(Appendable a) {
         this(a, Locale.getDefault());
@@ -444,32 +432,30 @@
 
     /**
      * Constructs a {@code Formatter} with the specified {@code Locale}.
-     * 
+     *
      * The output is written to a {@code StringBuilder} which can be acquired by invoking
      * {@link #out()} and whose content can be obtained by calling
      * {@code toString()}.
-     * 
+     *
      * @param l
      *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
      *            then no localization will be used.
-     * @since Android 1.0
      */
     public Formatter(Locale l) {
         this(new StringBuilder(), l);
     }
 
     /**
-     * Constructs a {@code Formatter} with the specified {@code Locale} 
-     * and whose output will be written to the 
+     * Constructs a {@code Formatter} with the specified {@code Locale}
+     * and whose output will be written to the
      * specified {@code Appendable}.
-     * 
+     *
      * @param a
      *            the output destination of the {@code Formatter}. If {@code a} is {@code null},
      *            then a {@code StringBuilder} will be used.
      * @param l
      *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
      *            then no localization will be used.
-     * @since Android 1.0
      */
     public Formatter(Appendable a, Locale l) {
         if (null == a) {
@@ -482,17 +468,16 @@
 
     /**
      * Constructs a {@code Formatter} whose output is written to the specified file.
-     * 
+     *
      * The charset of the {@code Formatter} is the default charset.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param fileName
      *            the filename of the file that is used as the output
      *            destination for the {@code Formatter}. The file will be truncated to
      *            zero size if the file exists, or else a new file will be
      *            created. The output of the {@code Formatter} is buffered.
-     * 
      * @throws FileNotFoundException
      *             if the filename does not denote a normal and writable file,
      *             or if a new file cannot be created, or if any error arises when
@@ -500,7 +485,6 @@
      * @throws SecurityException
      *             if there is a {@code SecurityManager} in place which denies permission
      *             to write to the file in {@code checkWrite(file.getPath())}.
-     * @since Android 1.0
      */
     public Formatter(String fileName) throws FileNotFoundException {
         this(new File(fileName));
@@ -509,9 +493,9 @@
 
     /**
      * Constructs a {@code Formatter} whose output is written to the specified file.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param fileName
      *            the filename of the file that is used as the output
      *            destination for the {@code Formatter}. The file will be truncated to
@@ -519,7 +503,6 @@
      *            created. The output of the {@code Formatter} is buffered.
      * @param csn
      *            the name of the charset for the {@code Formatter}.
-     * 
      * @throws FileNotFoundException
      *             if the filename does not denote a normal and writable file,
      *             or if a new file cannot be created, or if any error arises when
@@ -529,7 +512,6 @@
      *             to write to the file in {@code checkWrite(file.getPath())}.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(String fileName, String csn) throws FileNotFoundException,
             UnsupportedEncodingException {
@@ -537,9 +519,9 @@
     }
 
     /**
-     * Constructs a {@code Formatter} with the given {@code Locale} and charset, 
+     * Constructs a {@code Formatter} with the given {@code Locale} and charset,
      * and whose output is written to the specified file.
-     * 
+     *
      * @param fileName
      *            the filename of the file that is used as the output
      *            destination for the {@code Formatter}. The file will be truncated to
@@ -550,7 +532,6 @@
      * @param l
      *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
      *            then no localization will be used.
-     * 
      * @throws FileNotFoundException
      *             if the filename does not denote a normal and writable file,
      *             or if a new file cannot be created, or if any error arises when
@@ -560,7 +541,6 @@
      *             to write to the file in {@code checkWrite(file.getPath())}.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(String fileName, String csn, Locale l)
             throws FileNotFoundException, UnsupportedEncodingException {
@@ -570,17 +550,16 @@
 
     /**
      * Constructs a {@code Formatter} whose output is written to the specified {@code File}.
-     * 
+     *
      * The charset of the {@code Formatter} is the default charset.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param file
      *            the {@code File} that is used as the output destination for the
      *            {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File}
      *            exists, or else a new {@code File} will be created. The output of the
      *            {@code Formatter} is buffered.
-     * 
      * @throws FileNotFoundException
      *             if the {@code File} is not a normal and writable {@code File}, or if a
      *             new {@code File} cannot be created, or if any error rises when opening or
@@ -588,18 +567,17 @@
      * @throws SecurityException
      *             if there is a {@code SecurityManager} in place which denies permission
      *             to write to the {@code File} in {@code checkWrite(file.getPath())}.
-     * @since Android 1.0
      */
     public Formatter(File file) throws FileNotFoundException {
         this(new FileOutputStream(file));
     }
 
     /**
-     * Constructs a {@code Formatter} with the given charset, 
+     * Constructs a {@code Formatter} with the given charset,
      * and whose output is written to the specified {@code File}.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param file
      *            the {@code File} that is used as the output destination for the
      *            {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File}
@@ -616,7 +594,6 @@
      *             to write to the {@code File} in {@code checkWrite(file.getPath())}.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(File file, String csn) throws FileNotFoundException,
             UnsupportedEncodingException {
@@ -624,9 +601,9 @@
     }
 
     /**
-     * Constructs a {@code Formatter} with the given {@code Locale} and charset, 
+     * Constructs a {@code Formatter} with the given {@code Locale} and charset,
      * and whose output is written to the specified {@code File}.
-     * 
+     *
      * @param file
      *            the {@code File} that is used as the output destination for the
      *            {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File}
@@ -646,7 +623,6 @@
      *             to write to the {@code File} in {@code checkWrite(file.getPath())}.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(File file, String csn, Locale l)
             throws FileNotFoundException, UnsupportedEncodingException {
@@ -654,9 +630,9 @@
         try {
             fout = new FileOutputStream(file);
             OutputStreamWriter writer = new OutputStreamWriter(fout, csn);
-            // BEGIN android-modified
+            // BEGIN android-changed
             out = new BufferedWriter(writer, 8192);
-            // END android-modified
+            // END android-changed
         } catch (RuntimeException e) {
             closeOutputStream(fout);
             throw e;
@@ -670,37 +646,35 @@
 
     /**
      * Constructs a {@code Formatter} whose output is written to the specified {@code OutputStream}.
-     * 
+     *
      * The charset of the {@code Formatter} is the default charset.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param os
      *            the stream to be used as the destination of the {@code Formatter}.
-     * @since Android 1.0
      */
     public Formatter(OutputStream os) {
         OutputStreamWriter writer = new OutputStreamWriter(os, Charset
                 .defaultCharset());
-        // BEGIN android-modified
+        // BEGIN android-changed
         out = new BufferedWriter(writer, 8192);
-        // END android-modified
+        // END android-changed
         locale = Locale.getDefault();
     }
 
     /**
-     * Constructs a {@code Formatter} with the given charset, 
+     * Constructs a {@code Formatter} with the given charset,
      * and whose output is written to the specified {@code OutputStream}.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param os
      *            the stream to be used as the destination of the {@code Formatter}.
      * @param csn
      *            the name of the charset for the {@code Formatter}.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(OutputStream os, String csn)
             throws UnsupportedEncodingException {
@@ -709,9 +683,9 @@
     }
 
     /**
-     * Constructs a {@code Formatter} with the given {@code Locale} and charset, 
+     * Constructs a {@code Formatter} with the given {@code Locale} and charset,
      * and whose output is written to the specified {@code OutputStream}.
-     * 
+     *
      * @param os
      *            the stream to be used as the destination of the {@code Formatter}.
      * @param csn
@@ -721,31 +695,29 @@
      *            then no localization will be used.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(OutputStream os, String csn, Locale l)
             throws UnsupportedEncodingException {
 
         OutputStreamWriter writer = new OutputStreamWriter(os, csn);
-        // BEGIN android-modified
+        // BEGIN android-changed
         out = new BufferedWriter(writer, 8192);
-        // END android-modified
+        // END android-changed
 
         locale = l;
     }
 
     /**
      * Constructs a {@code Formatter} whose output is written to the specified {@code PrintStream}.
-     * 
+     *
      * The charset of the {@code Formatter} is the default charset.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param ps
      *            the {@code PrintStream} used as destination of the {@code Formatter}. If
-     *            {@code ps} is {@code null}, then a {@ code NullPointerExcepiton} will
+     *            {@code ps} is {@code null}, then a {@code NullPointerException} will
      *            be raised.
-     * @since Android 1.0
      */
     public Formatter(PrintStream ps) {
         if (null == ps) {
@@ -763,11 +735,10 @@
 
     /**
      * Returns the {@code Locale} of the {@code Formatter}.
-     * 
+     *
      * @return the {@code Locale} for the {@code Formatter} or {@code null} for no {@code Locale}.
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     public Locale locale() {
         checkClosed();
@@ -776,11 +747,10 @@
 
     /**
      * Returns the output destination of the {@code Formatter}.
-     * 
+     *
      * @return the output destination of the {@code Formatter}.
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     public Appendable out() {
         checkClosed();
@@ -790,12 +760,11 @@
     /**
      * Returns the content by calling the {@code toString()} method of the output
      * destination.
-     * 
+     *
      * @return the content by calling the {@code toString()} method of the output
      *         destination.
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -805,11 +774,10 @@
 
     /**
      * Flushes the {@code Formatter}. If the output destination is {@link Flushable},
-     * then the method {@ code flush()} will be called on that destination.
-     * 
+     * then the method {@code flush()} will be called on that destination.
+     *
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     public void flush() {
         checkClosed();
@@ -825,14 +793,12 @@
     /**
      * Closes the {@code Formatter}. If the output destination is {@link Closeable},
      * then the method {@code close()} will be called on that destination.
-     * 
+     *
      * If the {@code Formatter} has been closed, then calling the this method will have no
      * effect.
-     * 
+     *
      * Any method but the {@link #ioException()} that is called after the
      * {@code Formatter} has been closed will raise a {@code FormatterClosedException}.
-     * 
-     * @since Android 1.0
      */
     public void close() {
         closed = true;
@@ -850,10 +816,9 @@
      * Returns the last {@code IOException} thrown by the {@code Formatter}'s output
      * destination. If the {@code append()} method of the destination does not throw
      * {@code IOException}s, the {@code ioException()} method will always return {@code null}.
-     * 
+     *
      * @return the last {@code IOException} thrown by the {@code Formatter}'s output
      *         destination.
-     * @since Android 1.0
      */
     public IOException ioException() {
         return lastIOException;
@@ -861,7 +826,7 @@
 
     /**
      * Writes a formatted string to the output destination of the {@code Formatter}.
-     * 
+     *
      * @param format
      *            a format string.
      * @param args
@@ -875,23 +840,22 @@
      *             the format string, or any other illegal situation.
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     public Formatter format(String format, Object... args) {
         return format(locale, format, args);
     }
 
-// BEGIN android-changed
+    // BEGIN android-added
     /**
      * Cached transformer. Improves performance when format() is called multiple
      * times.
      */
     private Transformer transformer;
-// END android-changed
+    // END android-added
 
     /**
      * Writes a formatted string to the output destination of the {@code Formatter}.
-     * 
+     *
      * @param l
      *            the {@code Locale} used in the method. If {@code locale} is
      *            {@code null}, then no localization will be applied. This
@@ -910,7 +874,6 @@
      *             the format string, or any other illegal situation.
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     public Formatter format(Locale l, String format, Object... args) {
         checkClosed();
@@ -1275,7 +1238,7 @@
                     break;
                 }
                 case 'n': {
-                    result = transfromFromLineSeparator();
+                    result = transformFromLineSeparator();
                     break;
                 }
                 case 't':
@@ -1499,7 +1462,7 @@
          * Transforms line separator to a formatted string. Any flag, the width
          * or the precision is illegal.
          */
-        private String transfromFromLineSeparator() {
+        private String transformFromLineSeparator() {
             if (formatToken.isPrecisionSet()) {
                 throw new IllegalFormatPrecisionException(formatToken
                         .getPrecision());
@@ -2121,9 +2084,18 @@
             boolean requireScientificRepresentation = true;
             double d = ((Number) argument).doubleValue();
             d = Math.abs(d);
-            long l = Math.round(d);
+            if (Double.isInfinite(d)) {
+                precision = formatToken.getPrecision();
+                precision--;
+                formatToken.setPrecision(precision);
+                transform_e();
+                return;
+            }
+            BigDecimal b = new BigDecimal(d, new MathContext(precision));
+            d = b.doubleValue();
+            long l = b.longValue();
 
-            if (l >= 1) {
+            if (d >= 1 && d < Math.pow(10, precision)) {
                 if (l < Math.pow(10, precision)) {
                     requireScientificRepresentation = false;
                     precision -= String.valueOf(l).length();
@@ -2137,19 +2109,20 @@
                 }
 
             } else {
-                l = Math.round(d * Math.pow(10, 4));
-                if (l >= 1) {
+                l = b.movePointRight(4).longValue();
+                b.movePointLeft(4);
+                if (d >= Math.pow(10, -4) && d < 1) {
                     requireScientificRepresentation = false;
                     precision += 4 - String.valueOf(l).length();
-                    l = Math.round(d * Math.pow(10, precision + 1));
+                    l = b.movePointRight(precision + 1).longValue();
+                    b.movePointLeft(precision + 1);
                     if (String.valueOf(l).length() <= formatToken
                             .getPrecision()) {
                         precision++;
                     }
-                    l = Math.round(d * Math.pow(10, precision));
-                    if (l < Math.pow(10, precision - 4)) {
-                        requireScientificRepresentation = true;
-                    } else {
+                    l = b.movePointRight(precision).longValue();
+                    b.movePointLeft(precision);
+                    if (l >= Math.pow(10, precision - 4)) {
                         formatToken.setPrecision(precision);
                     }
                 }
@@ -2461,9 +2434,10 @@
 
         private void transform_Z() {
             TimeZone timeZone = calendar.getTimeZone();
-            result
-                    .append(timeZone.getDisplayName(true, TimeZone.SHORT,
-                            locale));
+            result.append(timeZone
+                    .getDisplayName(
+                            timeZone.inDaylightTime(calendar.getTime()),
+                            TimeZone.SHORT, locale));
         }
 
         private void transform_z() {
diff --git a/luni/src/main/java/java/util/FormatterClosedException.java b/luni/src/main/java/java/util/FormatterClosedException.java
index 63d1052..e7e57ba 100644
--- a/luni/src/main/java/java/util/FormatterClosedException.java
+++ b/luni/src/main/java/java/util/FormatterClosedException.java
@@ -23,7 +23,6 @@
  * closed.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class FormatterClosedException extends IllegalStateException implements
         Serializable {
diff --git a/luni/src/main/java/java/util/GregorianCalendar.java b/luni/src/main/java/java/util/GregorianCalendar.java
index 32368ec..d8cd556 100644
--- a/luni/src/main/java/java/util/GregorianCalendar.java
+++ b/luni/src/main/java/java/util/GregorianCalendar.java
@@ -14,12 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2008, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 package java.util;
 
@@ -27,24 +21,19 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 /**
  * {@code GregorianCalendar} is a concrete subclass of {@link Calendar}
  * and provides the standard calendar used by most of the world.
- * 
+ *
  * <p>
  * The standard (Gregorian) calendar has 2 eras, BC and AD.
- * 
+ *
  * <p>
  * This implementation handles a single discontinuity, which corresponds by
  * default to the date the Gregorian calendar was instituted (October 15, 1582
  * in some countries, later in others). The cutover date may be changed by the
  * caller by calling {@code setGregorianChange()}.
- * 
+ *
  * <p>
  * Historically, in those countries which adopted the Gregorian calendar first,
  * October 4, 1582 was thus followed by October 15, 1582. This calendar models
@@ -53,7 +42,7 @@
  * the Julian calendar is the leap year rule. The Julian calendar specifies leap
  * years every four years, whereas the Gregorian calendar omits century years
  * which are not divisible by 400.
- * 
+ *
  * <p>
  * {@code GregorianCalendar} implements <em>proleptic</em> Gregorian
  * and Julian calendars. That is, dates are computed by extrapolating the
@@ -64,13 +53,13 @@
  * 4 AD onward, when modern Julian calendar rules were adopted. Before this
  * date, leap year rules were applied irregularly, and before 45 BC the Julian
  * calendar did not even exist.
- * 
+ *
  * <p>
  * Prior to the institution of the Gregorian calendar, New Year's Day was March
  * 25. To avoid confusion, this calendar always uses January 1. A manual
  * adjustment may be made if desired for dates that are prior to the Gregorian
  * changeover and which fall between January 1 and March 24.
- * 
+ *
  * <p>
  * Values calculated for the {@code WEEK_OF_YEAR} field range from 1 to
  * 53. Week 1 for a year is the earliest seven day period starting on
@@ -80,7 +69,7 @@
  * {@code getFirstDayOfWeek()}, and the day of the week of January 1.
  * Weeks between week 1 of one year and week 1 of the following year are
  * numbered sequentially from 2 to 52 or 53 (as needed).
- * 
+ *
  * <p>
  * For example, January 1, 1998 was a Thursday. If
  * {@code getFirstDayOfWeek()} is {@code MONDAY} and
@@ -90,7 +79,7 @@
  * {@code getFirstDayOfWeek()} is {@code SUNDAY}, then week 1 of
  * 1998 starts on January 4, 1998, and ends on January 10, 1998; the first three
  * days of 1998 then are part of week 53 of 1997.
- * 
+ *
  * <p>
  * Values calculated for the {@code WEEK_OF_MONTH} field range from 0 or
  * 1 to 4 or 5. Week 1 of a month (the days with <code>WEEK_OF_MONTH =
@@ -102,7 +91,7 @@
  * {@code getFirstDayOfWeek()}, and will not include days of the
  * previous month. Days of a month before week 1 have a
  * {@code WEEK_OF_MONTH} of 0.
- * 
+ *
  * <p>
  * For example, if {@code getFirstDayOfWeek()} is {@code SUNDAY}
  * and {@code getMinimalDaysInFirstWeek()} is 4, then the first week of
@@ -111,10 +100,10 @@
  * Saturday, January 3 have a {@code WEEK_OF_MONTH} of 0. If
  * {@code getMinimalDaysInFirstWeek()} is changed to 3, then January 1
  * through January 3 have a {@code WEEK_OF_MONTH} of 1.
- * 
+ *
  * <p>
  * <strong>Example:</strong> <blockquote>
- * 
+ *
  * <pre>
  * // get the supported ids for GMT-08:00 (Pacific Standard Time)
  * String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
@@ -186,13 +175,11 @@
  * System.out.println("DST_OFFSET: "
  *        + (calendar.get(Calendar.DST_OFFSET)/(60*60*1000))); // in hours
  * </pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * @see Calendar
  * @see TimeZone
- * 
- * @since Android 1.0
  */
 public class GregorianCalendar extends Calendar {
 
@@ -200,18 +187,14 @@
 
     /**
      * Value for the BC era.
-     * 
-     * @since Android 1.0
      */
     public static final int BC = 0;
 
     /**
      * Value for the AD era.
-     * 
-     * @since Android 1.0
      */
     public static final int AD = 1;
-    
+
     private static final long defaultGregorianCutover = -12219292800000l;
 
     private long gregorianCutover = defaultGregorianCutover;
@@ -251,8 +234,6 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the current date and
      * time with the default {@code Locale} and {@code TimeZone}.
-     * 
-     * @since Android 1.0
      */
     public GregorianCalendar() {
         this(TimeZone.getDefault(), Locale.getDefault());
@@ -261,14 +242,13 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to midnight in the default
      * {@code TimeZone} and {@code Locale} on the specified date.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
      *            the month.
      * @param day
      *            the day of the month.
-     * @since Android 1.0
      */
     public GregorianCalendar(int year, int month, int day) {
         super(TimeZone.getDefault(), Locale.getDefault());
@@ -278,7 +258,7 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the specified date and
      * time in the default {@code TimeZone} and {@code Locale}.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
@@ -289,7 +269,6 @@
      *            the hour.
      * @param minute
      *            the minute.
-     * @since Android 1.0
      */
     public GregorianCalendar(int year, int month, int day, int hour, int minute) {
         super(TimeZone.getDefault(), Locale.getDefault());
@@ -299,7 +278,7 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the specified date and
      * time in the default {@code TimeZone} and {@code Locale}.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
@@ -312,7 +291,6 @@
      *            the minute.
      * @param second
      *            the second.
-     * @since Android 1.0
      */
     public GregorianCalendar(int year, int month, int day, int hour,
             int minute, int second) {
@@ -328,10 +306,9 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the current date and
      * time and using the specified {@code Locale} and the default {@code TimeZone}.
-     * 
+     *
      * @param locale
      *            the {@code Locale}.
-     * @since Android 1.0
      */
     public GregorianCalendar(Locale locale) {
         this(TimeZone.getDefault(), locale);
@@ -340,10 +317,9 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the current date and
      * time and using the specified {@code TimeZone} and the default {@code Locale}.
-     * 
+     *
      * @param timezone
      *            the {@code TimeZone}.
-     * @since Android 1.0
      */
     public GregorianCalendar(TimeZone timezone) {
         this(timezone, Locale.getDefault());
@@ -352,12 +328,11 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the current date and
      * time and using the specified {@code TimeZone} and {@code Locale}.
-     * 
+     *
      * @param timezone
      *            the {@code TimeZone}.
      * @param locale
      *            the {@code Locale}.
-     * @since Android 1.0
      */
     public GregorianCalendar(TimeZone timezone, Locale locale) {
         super(timezone, locale);
@@ -372,15 +347,14 @@
 
     /**
      * Adds the specified amount to a {@code Calendar} field.
-     * 
+     *
      * @param field
      *            the {@code Calendar} field to modify.
      * @param value
      *            the amount to add to the field.
-     * 
-     * @exception IllegalArgumentException
-     *                when the specified field is DST_OFFSET or ZONE_OFFSET.
-     * @since Android 1.0
+     *
+     * @throws IllegalArgumentException
+     *                if the specified field is DST_OFFSET or ZONE_OFFSET.
      */
     @Override
     public void add(int field, int value) {
@@ -477,9 +451,8 @@
 
     /**
      * Creates new instance of {@code GregorianCalendar} with the same properties.
-     * 
+     *
      * @return a shallow copy of this {@code GregorianCalendar}.
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -508,7 +481,7 @@
 
         int dayOfYear = computeYearAndDay(days, timeVal + zoneOffset);
         fields[DAY_OF_YEAR] = dayOfYear;
-        if(fields[YEAR] == changeYear && gregorianCutover < timeVal + zoneOffset){
+        if(fields[YEAR] == changeYear && gregorianCutover <= timeVal + zoneOffset){
             dayOfYear += currentYearSkew;
         }
         int month = dayOfYear / 32;
@@ -539,7 +512,7 @@
                 dayOfYear = computeYearAndDay(days, timeVal - zoneOffset
                         + dstOffset);
                 fields[DAY_OF_YEAR] = dayOfYear;
-                if(fields[YEAR] == changeYear && gregorianCutover < timeVal - zoneOffset + dstOffset){
+                if(fields[YEAR] == changeYear && gregorianCutover <= timeVal - zoneOffset + dstOffset){
                     dayOfYear += currentYearSkew;
                 }
                 month = dayOfYear / 32;
@@ -621,7 +594,9 @@
     protected void computeFields() {
         int zoneOffset = getTimeZone().getRawOffset();
 
-        fields[ZONE_OFFSET] = zoneOffset;
+        if(!isSet[ZONE_OFFSET]) {
+            fields[ZONE_OFFSET] = zoneOffset;
+        }
 
         int millis = (int) (time % 86400000);
         int savedMillis = millis;
@@ -864,6 +839,9 @@
                                         - (days + daysInMonth(leapYear, month) - 3))
                                 + fields[DAY_OF_WEEK_IN_MONTH] * 7;
                     }
+                } else if (isSet[DAY_OF_WEEK]) {
+                    int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
+                    days += mod7(mod7(skew + dayOfWeek - (days - 3)) - skew);
                 }
             }
         } else {
@@ -967,7 +945,7 @@
         return (year - 1970) * 365 + ((year - 1972) / 4)
                 - ((year - 2000) / 100) + ((year - 2000) / 400);
     }
-    
+
     private int daysInMonth() {
         return daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]);
     }
@@ -1003,16 +981,15 @@
      * Compares the specified {@code Object} to this {@code GregorianCalendar} and returns whether
      * they are equal. To be equal, the {@code Object} must be an instance of {@code GregorianCalendar} and
      * have the same properties.
-     * 
+     *
      * @param object
      *            the {@code Object} to compare with this {@code GregorianCalendar}.
      * @return {@code true} if {@code object} is equal to this
      *         {@code GregorianCalendar}, {@code false} otherwise.
-     * @exception IllegalArgumentException
-     *                when the time is not set and the time cannot be computed
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
      *                from the current field values.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -1023,11 +1000,10 @@
     /**
      * Gets the maximum value of the specified field for the current date. For
      * example, the maximum number of days in the current month.
-     * 
+     *
      * @param field
      *            the field.
      * @return the maximum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getActualMaximum(int field) {
@@ -1095,11 +1071,10 @@
      * Gets the minimum value of the specified field for the current date. For
      * the gregorian calendar, this value is the same as
      * {@code getMinimum()}.
-     * 
+     *
      * @param field
      *            the field.
      * @return the minimum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getActualMinimum(int field) {
@@ -1109,11 +1084,10 @@
     /**
      * Gets the greatest minimum value of the specified field. For the gregorian
      * calendar, this value is the same as {@code getMinimum()}.
-     * 
+     *
      * @param field
      *            the field.
      * @return the greatest minimum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getGreatestMinimum(int field) {
@@ -1123,9 +1097,8 @@
     /**
      * Returns the gregorian change date of this calendar. This is the date on
      * which the gregorian calendar came into effect.
-     * 
+     *
      * @return a {@code Date} which represents the gregorian change date.
-     * @since Android 1.0
      */
     public final Date getGregorianChange() {
         return new Date(gregorianCutover);
@@ -1134,11 +1107,10 @@
     /**
      * Gets the smallest maximum value of the specified field. For example, 28
      * for the day of month field.
-     * 
+     *
      * @param field
      *            the field.
      * @return the smallest maximum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getLeastMaximum(int field) {
@@ -1158,11 +1130,10 @@
     /**
      * Gets the greatest maximum value of the specified field. For example, 31
      * for the day of month field.
-     * 
+     *
      * @param field
      *            the field.
      * @return the greatest maximum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getMaximum(int field) {
@@ -1171,11 +1142,10 @@
 
     /**
      * Gets the smallest minimum value of the specified field.
-     * 
+     *
      * @param field
      *            the field.
      * @return the smallest minimum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getMinimum(int field) {
@@ -1234,11 +1204,10 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
-     * 
+     *
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -1248,12 +1217,11 @@
 
     /**
      * Returns whether the specified year is a leap year.
-     * 
+     *
      * @param year
      *            the year.
      * @return {@code true} if the specified year is a leap year, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean isLeapYear(int year) {
         if (year > changeYear) {
@@ -1288,15 +1256,14 @@
      * field when it goes beyond the maximum or minimum value for the current
      * date. Other fields will be adjusted as required to maintain a consistent
      * date.
-     * 
+     *
      * @param field
      *            the field to roll.
      * @param value
      *            the amount to add.
-     * 
-     * @exception IllegalArgumentException
-     *                when an invalid field is specified.
-     * @since Android 1.0
+     *
+     * @throws IllegalArgumentException
+     *                if an invalid field is specified.
      */
     @Override
     public void roll(int field, int value) {
@@ -1310,72 +1277,90 @@
         isCached = false;
 
         complete();
+        int days, day, mod, maxWeeks, newWeek;
         int max = -1;
         switch (field) {
-            case YEAR:
-                max = maximums[field];
-                break;
-            case WEEK_OF_YEAR:
-            case WEEK_OF_MONTH:
-                int days,
-                day;
-                if (field == WEEK_OF_YEAR) {
-                    days = daysInYear(fields[YEAR]);
-                    day = DAY_OF_YEAR;
+        case YEAR:
+            max = maximums[field];
+            break;
+        case WEEK_OF_YEAR:
+            days = daysInYear(fields[YEAR]);
+            day = DAY_OF_YEAR;
+            mod = mod7(fields[DAY_OF_WEEK] - fields[day]
+                    - (getFirstDayOfWeek() - 1));
+            maxWeeks = (days - 1 + mod) / 7 + 1;
+            newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
+            if (newWeek == maxWeeks) {
+                int addDays = (newWeek - fields[field]) * 7;
+                if (fields[day] > addDays && fields[day] + addDays > days) {
+                    set(field, 1);
                 } else {
-                    days = daysInMonth();
-                    day = DATE;
+                    set(field, newWeek - 1);
                 }
-                int mod = mod7(fields[DAY_OF_WEEK] - fields[day]
-                        - (getFirstDayOfWeek() - 1));
-                int maxWeeks = (days - 1 + mod) / 7 + 1;
-                int newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
-                if (newWeek == maxWeeks) {
-                    if (fields[day] + (newWeek - fields[field]) * 7 > days) {
-                        set(day, days);
-                    } else {
-                        set(field, newWeek);
-                    }
-                } else if (newWeek == 1) {
-                    int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
-                    if (week > 1) {
-                        set(day, 1);
-                    } else {
-                        set(field, newWeek);
-                    }
+            } else if (newWeek == 1) {
+                int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
+                if (week > 1) {
+                    set(field, 1);
                 } else {
                     set(field, newWeek);
                 }
-                break;
-            case DATE:
-                max = daysInMonth();
-                break;
-            case DAY_OF_YEAR:
-                max = daysInYear(fields[YEAR]);
-                break;
-            case DAY_OF_WEEK:
-                max = maximums[field];
-                lastDateFieldSet = WEEK_OF_MONTH;
-                break;
-            case DAY_OF_WEEK_IN_MONTH:
-                max = (fields[DATE] + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1;
-                break;
-
-            case ERA:
-            case MONTH:
-            case AM_PM:
-            case HOUR:
-            case HOUR_OF_DAY:
-            case MINUTE:
-            case SECOND:
-            case MILLISECOND:
-                set(field, mod(fields[field] + value, maximums[field] + 1));
-                if (field == MONTH && fields[DATE] > daysInMonth()) {
-                    set(DATE, daysInMonth());
-                } else if (field == AM_PM) {
-                    lastTimeFieldSet = HOUR;
+            } else {
+                set(field, newWeek);
+            }
+            break;
+        case WEEK_OF_MONTH:
+            days = daysInMonth();
+            day = DATE;
+            mod = mod7(fields[DAY_OF_WEEK] - fields[day]
+                    - (getFirstDayOfWeek() - 1));
+            maxWeeks = (days - 1 + mod) / 7 + 1;
+            newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
+            if (newWeek == maxWeeks) {
+                if (fields[day] + (newWeek - fields[field]) * 7 > days) {
+                    set(day, days);
+                } else {
+                    set(field, newWeek);
                 }
-                break;
+            } else if (newWeek == 1) {
+                int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
+                if (week > 1) {
+                    set(day, 1);
+                } else {
+                    set(field, newWeek);
+                }
+            } else {
+                set(field, newWeek);
+            }
+            break;
+        case DATE:
+            max = daysInMonth();
+            break;
+        case DAY_OF_YEAR:
+            max = daysInYear(fields[YEAR]);
+            break;
+        case DAY_OF_WEEK:
+            max = maximums[field];
+            lastDateFieldSet = WEEK_OF_MONTH;
+            break;
+        case DAY_OF_WEEK_IN_MONTH:
+            max = (fields[DATE] + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1;
+            break;
+
+        case ERA:
+        case MONTH:
+        case AM_PM:
+        case HOUR:
+        case HOUR_OF_DAY:
+        case MINUTE:
+        case SECOND:
+        case MILLISECOND:
+            set(field, mod(fields[field] + value, maximums[field] + 1));
+            if (field == MONTH && fields[DATE] > daysInMonth()) {
+                set(DATE, daysInMonth());
+            } else if (field == AM_PM) {
+                lastTimeFieldSet = HOUR;
+            }
+            break;
         }
         if (max != -1) {
             set(field, mod(fields[field] - 1 + value, max) + 1);
@@ -1389,15 +1374,14 @@
      * date. Other fields will be adjusted as required to maintain a consistent
      * date. For example, March 31 will roll to April 30 when rolling the month
      * field.
-     * 
+     *
      * @param field
      *            the field to roll.
      * @param increment
      *            {@code true} to increment the field, {@code false} to
      *            decrement.
-     * @exception IllegalArgumentException
-     *                when an invalid field is specified.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if an invalid field is specified.
      */
     @Override
     public void roll(int field, boolean increment) {
@@ -1406,10 +1390,9 @@
 
     /**
      * Sets the gregorian change date of this calendar.
-     * 
+     *
      * @param date
      *            a {@code Date} which represents the gregorian change date.
-     * @since Android 1.0
      */
     public void setGregorianChange(Date date) {
         gregorianCutover = date.getTime();
diff --git a/luni/src/main/java/java/util/HashMap.java b/luni/src/main/java/java/util/HashMap.java
index 594e8a8..4ec7a1b 100644
--- a/luni/src/main/java/java/util/HashMap.java
+++ b/luni/src/main/java/java/util/HashMap.java
@@ -25,25 +25,46 @@
 /**
  * HashMap is an implementation of Map. All optional operations (adding and
  * removing) are supported. Keys and values can be any objects.
- * 
- * @since Android 1.0
  */
 public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>,
         Cloneable, Serializable {
+
     private static final long serialVersionUID = 362498820763181265L;
 
+    /*
+     * Actual count of entries
+     */
     transient int elementCount;
 
+    /*
+     * The internal data structure to hold Entries
+     */
     transient Entry<K, V>[] elementData;
 
-    final float loadFactor;
-
-    int threshold;
-
+    /*
+     * modification count, to keep track of structural modifications between the
+     * HashMap and the iterator
+     */
     transient int modCount = 0;
 
+    /*
+     * default size that an HashMap created using the default constructor would
+     * have.
+     */
     private static final int DEFAULT_SIZE = 16;
 
+    /*
+     * maximum ratio of (stored elements)/(storage size) which does not lead to
+     * rehash
+     */
+    final float loadFactor;
+
+    /*
+     * maximum number of elements that can be put in this map before having to
+     * rehash
+     */
+    int threshold;
+
     static class Entry<K, V> extends MapEntry<K, V> {
         final int origKeyHash;
 
@@ -56,7 +77,7 @@
 
         Entry(K theKey, V theValue) {
             super(theKey, theValue);
-            origKeyHash = (theKey == null ? 0 : theKey.hashCode());
+            origKeyHash = (theKey == null ? 0 : computeHashCode(theKey));
         }
 
         @Override
@@ -70,33 +91,27 @@
         }
     }
 
-    static class HashMapIterator<E, KT, VT> implements Iterator<E> {
+    private static class AbstractMapIterator<K, V>  {
         private int position = 0;
-
         int expectedModCount;
+        Entry<K, V> futureEntry;
+        Entry<K, V> currentEntry;
+        Entry<K, V> prevEntry;
 
-        final MapEntry.Type<E, KT, VT> type;
+        final HashMap<K, V> associatedMap;
 
-        boolean canRemove = false;
-
-        Entry<KT, VT> entry;
-
-        Entry<KT, VT> lastEntry;
-
-        final HashMap<KT, VT> associatedMap;
-
-        HashMapIterator(MapEntry.Type<E, KT, VT> value, HashMap<KT, VT> hm) {
+        AbstractMapIterator(HashMap<K, V> hm) {
             associatedMap = hm;
-            type = value;
             expectedModCount = hm.modCount;
+            futureEntry = null;
         }
 
         public boolean hasNext() {
-            if (entry != null) {
+            if (futureEntry != null) {
                 return true;
             }
             // BEGIN android-changed
-            Entry<KT, VT>[] elementData = associatedMap.elementData;
+            Entry<K, V>[] elementData = associatedMap.elementData;
             int length = elementData.length;
             int newPosition = position;
             boolean result = false;
@@ -115,58 +130,88 @@
             // END android-changed
         }
 
-        void checkConcurrentMod() throws ConcurrentModificationException {
+        final void checkConcurrentMod() throws ConcurrentModificationException {
             if (expectedModCount != associatedMap.modCount) {
                 throw new ConcurrentModificationException();
             }
         }
 
-        public E next() {
+        final void makeNext() {
             // BEGIN android-changed
             // inline checkConcurrentMod()
             if (expectedModCount != associatedMap.modCount) {
                 throw new ConcurrentModificationException();
             }
+            // END android-changed
             if (!hasNext()) {
                 throw new NoSuchElementException();
             }
-
-            MapEntry<KT, VT> result;
-            Entry<KT, VT> _entry  = entry;
-            if (_entry == null) {
-                result = lastEntry = associatedMap.elementData[position++];
-                entry = lastEntry.next;
+            if (futureEntry == null) {
+                currentEntry = associatedMap.elementData[position++];
+                futureEntry = currentEntry.next;
+                prevEntry = null;
             } else {
-                if (lastEntry.next != _entry) {
-                    lastEntry = lastEntry.next;
+                if(currentEntry!=null){
+                    prevEntry = currentEntry;
                 }
-                result = _entry;
-                entry = _entry.next;
+                currentEntry = futureEntry;
+                futureEntry = futureEntry.next;
             }
-            canRemove = true;
-            return type.get(result);
-            // END android-changed
         }
 
-        public void remove() {
+        public final void remove() {
             checkConcurrentMod();
-            if (!canRemove) {
+            if (currentEntry==null) {
                 throw new IllegalStateException();
             }
-
-            canRemove = false;
-            associatedMap.modCount++;
-            if (lastEntry.next == entry) {
-                while (associatedMap.elementData[--position] == null) {
-                    // Do nothing
-                }
-                associatedMap.elementData[position] = associatedMap.elementData[position].next;
-                entry = null;
+            if(prevEntry==null){
+                int index = currentEntry.origKeyHash & (associatedMap.elementData.length - 1);
+                associatedMap.elementData[index] = associatedMap.elementData[index].next;
             } else {
-                lastEntry.next = entry;
+                prevEntry.next = currentEntry.next;
             }
-            associatedMap.elementCount--;
+            currentEntry = null;
             expectedModCount++;
+            associatedMap.modCount++;
+            associatedMap.elementCount--;
+
+        }
+    }
+
+
+    private static class EntryIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<Map.Entry<K, V>> {
+
+        EntryIterator (HashMap<K, V> map) {
+            super(map);
+        }
+
+        public Map.Entry<K, V> next() {
+            makeNext();
+            return currentEntry;
+        }
+    }
+
+    private static class KeyIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<K> {
+
+        KeyIterator (HashMap<K, V> map) {
+            super(map);
+        }
+
+        public K next() {
+            makeNext();
+            return currentEntry.key;
+        }
+    }
+
+    private static class ValueIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<V> {
+
+        ValueIterator (HashMap<K, V> map) {
+            super(map);
+        }
+
+        public V next() {
+            makeNext();
+            return currentEntry.value;
         }
     }
 
@@ -193,9 +238,13 @@
 
         @Override
         public boolean remove(Object object) {
-            if (contains(object)) {
-                associatedMap.remove(((Map.Entry<?, ?>) object).getKey());
-                return true;
+            if (object instanceof Map.Entry) {
+                Map.Entry<?, ?> oEntry = (Map.Entry<?, ?>) object;
+                Entry<KT,VT> entry = associatedMap.getEntry(oEntry.getKey());
+                if(valuesEq(entry, oEntry)) {
+                    associatedMap.removeEntry(entry);
+                    return true;
+                }
             }
             return false;
         }
@@ -203,31 +252,32 @@
         @Override
         public boolean contains(Object object) {
             if (object instanceof Map.Entry) {
-                Object key = ((Map.Entry<?, ?>) object).getKey();
-                Entry entry;
-                if (key == null) {
-                    entry = associatedMap.findNullKeyEntry();
-                } else {
-                    int hash = key.hashCode();
-                    int index = (hash & 0x7FFFFFFF) % associatedMap.elementData.length;
-                    entry = associatedMap.findNonNullKeyEntry(key, index, hash);
-                }
-                return object.equals(entry);
+                Map.Entry<?, ?> oEntry = (Map.Entry<?, ?>) object;
+                Entry<KT, VT> entry = associatedMap.getEntry(oEntry.getKey());
+                return valuesEq(entry, oEntry);
             }
             return false;
         }
 
+        private static boolean valuesEq(Entry entry, Map.Entry<?, ?> oEntry) {
+            return (entry != null) &&
+                                   ((entry.value == null) ?
+                                    (oEntry.getValue() == null) :
+                                    (areEqualValues(entry.value, oEntry.getValue())));
+        }
+
         @Override
         public Iterator<Map.Entry<KT, VT>> iterator() {
-            return new HashMapIterator<Map.Entry<KT, VT>, KT, VT>(
-                    new MapEntry.Type<Map.Entry<KT, VT>, KT, VT>() {
-                        public Map.Entry<KT, VT> get(MapEntry<KT, VT> entry) {
-                            return entry;
-                        }
-                    }, associatedMap);
+            return new EntryIterator<KT,VT> (associatedMap);
         }
     }
 
+    /**
+     * Create a new element array
+     *
+     * @param s
+     * @return Reference to the element array
+     */
     @SuppressWarnings("unchecked")
     Entry<K, V>[] newElementArray(int s) {
         return new Entry[s];
@@ -235,8 +285,6 @@
 
     /**
      * Constructs a new empty {@code HashMap} instance.
-     * 
-     * @since Android 1.0
      */
     public HashMap() {
         this(DEFAULT_SIZE);
@@ -244,28 +292,47 @@
 
     /**
      * Constructs a new {@code HashMap} instance with the specified capacity.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this hash map.
      * @throws IllegalArgumentException
      *                when the capacity is less than zero.
-     * @since Android 1.0
      */
     public HashMap(int capacity) {
-        if (capacity >= 0) {
-            elementCount = 0;
-            elementData = newElementArray(capacity == 0 ? 1 : capacity);
-            loadFactor = 0.75f; // Default load factor of 0.75
-            computeMaxSize();
-        } else {
-            throw new IllegalArgumentException();
+        this(capacity, 0.75f);  // default load factor of 0.75
         }
+
+    /**
+     * Calculates the capacity of storage required for storing given number of
+     * elements
+     *
+     * @param x
+     *            number of elements
+     * @return storage size
+     */
+    private static final int calculateCapacity(int x) {
+        if(x >= 1 << 30){
+            return 1 << 30;
+        }
+        if(x == 0){
+            return 16;
+        }
+        // BEGIN android-note
+        // this may be better optimized as Integer.highestOneBit(x)
+        // END android-note
+        x = x -1;
+        x |= x >> 1;
+        x |= x >> 2;
+        x |= x >> 4;
+        x |= x >> 8;
+        x |= x >> 16;
+        return x + 1;
     }
 
     /**
      * Constructs a new {@code HashMap} instance with the specified capacity and
      * load factor.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this hash map.
      * @param loadFactor
@@ -273,14 +340,14 @@
      * @throws IllegalArgumentException
      *                when the capacity is less than zero or the load factor is
      *                less or equal to zero.
-     * @since Android 1.0
      */
     public HashMap(int capacity, float loadFactor) {
         if (capacity >= 0 && loadFactor > 0) {
+            capacity = calculateCapacity(capacity);
             elementCount = 0;
-            elementData = newElementArray(capacity == 0 ? 1 : capacity);
+            elementData = newElementArray(capacity);
             this.loadFactor = loadFactor;
-            computeMaxSize();
+            computeThreshold();
         } else {
             throw new IllegalArgumentException();
         }
@@ -289,29 +356,29 @@
     /**
      * Constructs a new {@code HashMap} instance containing the mappings from
      * the specified map.
-     * 
+     *
      * @param map
      *            the mappings to add.
-     * @since Android 1.0
      */
     public HashMap(Map<? extends K, ? extends V> map) {
-        this(map.size() < 6 ? 11 : map.size() * 2);
+        this(calculateCapacity(map.size()));
         putAllImpl(map);
     }
 
-    // BEGIN android-changed
     /**
      * Removes all mappings from this hash map, leaving it empty.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
+        // BEGIN android-changed
         internalClear();
+        // END android-changed
     }
 
+    // BEGIN android-added
     void internalClear() {
         if (elementCount > 0) {
             elementCount = 0;
@@ -319,89 +386,71 @@
             modCount++;
         }
     }
-    // END android-changed
+    // END android-added
 
     /**
      * Returns a shallow copy of this map.
-     * 
+     *
      * @return a shallow copy of this map.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
     public Object clone() {
         try {
-            // BEGIN android-changed
-            // copied from newer version of harmony
             HashMap<K, V> map = (HashMap<K, V>) super.clone();
+            map.elementCount = 0;
             map.elementData = newElementArray(elementData.length);
-            map.internalClear();
-            Entry<K, V> entry;
-            for (int i = 0; i < elementData.length; i++) {
-                if ((entry = elementData[i]) != null){
-                    map.putImpl(entry.getKey(), entry.getValue());
-                    while (entry.next != null){
-                        entry = entry.next;
-                        map.putImpl(entry.getKey(), entry.getValue());
-                    }
-                }
-            // END android-changed
-            }
+            map.putAll(this);
+
             return map;
         } catch (CloneNotSupportedException e) {
             return null;
         }
     }
 
-    private void computeMaxSize() {
+    /**
+     * Computes the threshold for rehashing
+     */
+    private void computeThreshold() {
         threshold = (int) (elementData.length * loadFactor);
     }
 
     /**
      * Returns whether this map contains the specified key.
-     * 
+     *
      * @param key
      *            the key to search for.
      * @return {@code true} if this map contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsKey(Object key) {
-        Entry<K, V> m;
-        if (key == null) {
-            m = findNullKeyEntry();
-        } else {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
-            m = findNonNullKeyEntry(key, index, hash);
-        }
+        Entry<K, V> m = getEntry(key);
         return m != null;
     }
 
     /**
      * Returns whether this map contains the specified value.
-     * 
+     *
      * @param value
      *            the value to search for.
      * @return {@code true} if this map contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsValue(Object value) {
         if (value != null) {
-            for (int i = elementData.length; --i >= 0;) {
+            for (int i = 0; i < elementData.length; i++) {
                 Entry<K, V> entry = elementData[i];
                 while (entry != null) {
-                    if (value.equals(entry.value)) {
+                    if (areEqualValues(value, entry.value)) {
                         return true;
                     }
                     entry = entry.next;
                 }
             }
         } else {
-            for (int i = elementData.length; --i >= 0;) {
+            for (int i = 0; i < elementData.length; i++) {
                 Entry<K, V> entry = elementData[i];
                 while (entry != null) {
                     if (entry.value == null) {
@@ -418,9 +467,8 @@
      * Returns a set containing all of the mappings in this map. Each mapping is
      * an instance of {@link Map.Entry}. As the set is backed by this map,
      * changes in one will be reflected in the other.
-     * 
+     *
      * @return a set of the mappings.
-     * @since Android 1.0
      */
     @Override
     public Set<Map.Entry<K, V>> entrySet() {
@@ -429,54 +477,49 @@
 
     /**
      * Returns the value of the mapping with the specified key.
-     * 
+     *
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
     @Override
     public V get(Object key) {
-        Entry<K, V> m;
-        if (key == null) {
-            m = findNullKeyEntry();
-        } else {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
-            m = findNonNullKeyEntry(key, index, hash);
-        }
+        Entry<K, V> m = getEntry(key);
         if (m != null) {
             return m.value;
         }
         return null;
     }
 
+    final Entry<K, V> getEntry(Object key) {
+        Entry<K, V> m;
+        if (key == null) {
+            m = findNullKeyEntry();
+        } else {
+            int hash = computeHashCode(key);
+            int index = hash & (elementData.length - 1);
+            m = findNonNullKeyEntry(key, index, hash);
+        }
+        return m;
+    }
+
     final Entry<K,V> findNonNullKeyEntry(Object key, int index, int keyHash) {
         Entry<K,V> m = elementData[index];
+
         // BEGIN android-changed
         // The VM can optimize String.equals but not Object.equals
         if (key instanceof String) {
             String keyString = (String) key;
-            while (m != null) {
-                if (m.origKeyHash == keyHash) {
-                    if (keyString.equals(m.key)) {
-                        return m;
-                    }
-                }
+            while (m != null && (m.origKeyHash != keyHash || !keyString.equals(m.key))) {
                 m = m.next;
             }
         } else {
-            while (m != null) {
-                if (m.origKeyHash == keyHash) {
-                    if (key.equals(m.key)) {
-                        return m;
-                    }
-                }
+            while (m != null && (m.origKeyHash != keyHash || !areEqualKeys(key, m.key))) {
                 m = m.next;
             }
         }
-        return null;
+        return m;
         // END android-changed
     }
 
@@ -489,11 +532,10 @@
 
     /**
      * Returns whether this map is empty.
-     * 
+     *
      * @return {@code true} if this map has no elements, {@code false}
      *         otherwise.
      * @see #size()
-     * @since Android 1.0
      */
     @Override
     public boolean isEmpty() {
@@ -504,9 +546,8 @@
      * Returns a set of the keys contained in this map. The set is backed by
      * this map so changes to one are reflected by the other. The set does not
      * support adding.
-     * 
+     *
      * @return a set of the keys.
-     * @since Android 1.0
      */
     @Override
     public Set<K> keySet() {
@@ -535,12 +576,7 @@
 
                 @Override
                 public Iterator<K> iterator() {
-                    return new HashMapIterator<K, K, V>(
-                            new MapEntry.Type<K, K, V>() {
-                                public K get(MapEntry<K, V> entry) {
-                                    return entry.key;
-                                }
-                            }, HashMap.this);
+                    return new KeyIterator<K,V> (HashMap.this);
                 }
             };
         }
@@ -549,21 +585,20 @@
 
     /**
      * Maps the specified key to the specified value.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
      *            the value.
      * @return the value of any previous mapping with the specified key or
      *         {@code null} if there was no such mapping.
-     * @since Android 1.0
      */
     @Override
     public V put(K key, V value) {
         return putImpl(key, value);
     }
 
-    private V putImpl(K key, V value) {
+    V putImpl(K key, V value) {
         Entry<K,V> entry;
         if(key == null) {
             entry = findNullKeyEntry();
@@ -572,17 +607,17 @@
                 if (++elementCount > threshold) {
                     rehash();
                 }
-                entry = createHashedEntry(key, 0, 0);
+                entry = createHashedEntry(null, 0, 0);
             }
         } else {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
+            int hash = computeHashCode(key);
+            int index = hash & (elementData.length - 1);
             entry = findNonNullKeyEntry(key, index, hash);
             if (entry == null) {
                 modCount++;
                 if (++elementCount > threshold) {
                     rehash();
-                    index = (hash & 0x7FFFFFFF) % elementData.length;
+                    index = hash & (elementData.length - 1);
                 }
                 entry = createHashedEntry(key, index, hash);
             }
@@ -611,10 +646,11 @@
      * Copies all the mappings in the specified map to this map. These mappings
      * will replace all mappings that this map had for any of the keys currently
      * in the given map.
-     * 
+     *
      * @param map
      *            the map to copy mappings from.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code map} is {@code null}.
      */
     @Override
     public void putAll(Map<? extends K, ? extends V> map) {
@@ -634,13 +670,13 @@
     }
 
     void rehash(int capacity) {
-        int length = (capacity == 0 ? 1 : capacity << 1);
+        int length = calculateCapacity((capacity == 0 ? 1 : capacity << 1));
 
         Entry<K, V>[] newData = newElementArray(length);
         for (int i = 0; i < elementData.length; i++) {
             Entry<K, V> entry = elementData[i];
             while (entry != null) {
-                int index = (entry.origKeyHash & 0x7FFFFFFF) % length;
+                int index = entry.origKeyHash & (length - 1);
                 Entry<K, V> next = entry.next;
                 entry.next = newData[index];
                 newData[index] = entry;
@@ -648,7 +684,7 @@
             }
         }
         elementData = newData;
-        computeMaxSize();
+        computeThreshold();
     }
 
     void rehash() {
@@ -657,12 +693,11 @@
 
     /**
      * Removes the mapping with the specified key from this map.
-     * 
+     *
      * @param key
      *            the key of the mapping to remove.
      * @return the value of the removed mapping or {@code null} if no mapping
      *         for the specified key was found.
-     * @since Android 1.0
      */
     @Override
     public V remove(Object key) {
@@ -673,15 +708,35 @@
         return null;
     }
 
-    Entry<K, V> removeEntry(Object key) {
+    /*
+     * Remove the given entry from the hashmap.
+     * Assumes that the entry is in the map.
+     */
+    final void removeEntry(Entry<K, V> entry) {
+        int index = entry.origKeyHash & (elementData.length - 1);
+        Entry<K, V> m = elementData[index];
+        if (m == entry) {
+            elementData[index] = entry.next;
+        } else {
+            while (m.next != entry) {
+                m = m.next;
+            }
+            m.next = entry.next;
+
+        }
+        modCount++;
+        elementCount--;
+    }
+
+    final Entry<K, V> removeEntry(Object key) {
         int index = 0;
         Entry<K, V> entry;
         Entry<K, V> last = null;
         if (key != null) {
-            int hash = key.hashCode();
-            index = (hash & 0x7FFFFFFF) % elementData.length;
+            int hash = computeHashCode(key);
+            index = hash & (elementData.length - 1);
             entry = elementData[index];
-            while (entry != null && !(entry.origKeyHash == hash && key.equals(entry.key))) {
+            while (entry != null && !(entry.origKeyHash == hash && areEqualKeys(key, entry.key))) {
                 last = entry;
                 entry = entry.next;
             }
@@ -707,9 +762,8 @@
 
     /**
      * Returns the number of elements in this map.
-     * 
+     *
      * @return the number of elements in this map.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -727,16 +781,13 @@
      * "wrapper object" over the iterator of map's entrySet(). The {@code size}
      * method wraps the map's size method and the {@code contains} method wraps
      * the map's containsValue method.
-     * </p>
      * <p>
      * The collection is created when this method is called for the first time
      * and returned in response to all subsequent calls. This method may return
      * different collections when multiple concurrent calls occur, since no
      * synchronization is performed.
-     * </p>
-     * 
+     *
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     @Override
     public Collection<V> values() {
@@ -759,12 +810,7 @@
 
                 @Override
                 public Iterator<V> iterator() {
-                    return new HashMapIterator<V, K, V>(
-                            new MapEntry.Type<V, K, V>() {
-                                public V get(MapEntry<K, V> entry) {
-                                    return entry.value;
-                                }
-                            }, HashMap.this);
+                    return new ValueIterator<K,V> (HashMap.this);
                 }
             };
         }
@@ -793,10 +839,25 @@
         elementCount = stream.readInt();
         for (int i = elementCount; --i >= 0;) {
             K key = (K) stream.readObject();
-            int index = (null == key) ? 0 : (key.hashCode() & 0x7FFFFFFF)
-                    % length;
+            int index = (null == key) ? 0 : (computeHashCode(key) & (length - 1));
             createEntry(key, index, (V) stream.readObject());
         }
     }
 
+    /*
+     * Contract-related functionality
+     */
+    static int computeHashCode(Object key) {
+        return key.hashCode();
+}
+
+    static boolean areEqualKeys(Object key1, Object key2) {
+        return key1.equals(key2);
+    }
+
+    static boolean areEqualValues(Object value1, Object value2) {
+        return value1.equals(value2);
+    }
+
+
 }
diff --git a/luni/src/main/java/java/util/HashSet.java b/luni/src/main/java/java/util/HashSet.java
index fe89109..dca764f 100644
--- a/luni/src/main/java/java/util/HashSet.java
+++ b/luni/src/main/java/java/util/HashSet.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -26,8 +25,6 @@
 /**
  * HashSet is an implementation of a Set. All optional operations (adding and
  * removing) are supported. The elements can be any objects.
- * 
- * @since Android 1.0
  */
 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable,
         Serializable {
@@ -38,8 +35,6 @@
 
     /**
      * Constructs a new empty instance of {@code HashSet}.
-     * 
-     * @since Android 1.0
      */
     public HashSet() {
         this(new HashMap<E, HashSet<E>>());
@@ -50,7 +45,6 @@
      * 
      * @param capacity
      *            the initial capacity of this {@code HashSet}.
-     * @since Android 1.0
      */
     public HashSet(int capacity) {
         this(new HashMap<E, HashSet<E>>(capacity));
@@ -64,7 +58,6 @@
      *            the initial capacity.
      * @param loadFactor
      *            the initial load factor.
-     * @since Android 1.0
      */
     public HashSet(int capacity, float loadFactor) {
         this(new HashMap<E, HashSet<E>>(capacity, loadFactor));
@@ -76,10 +69,10 @@
      * 
      * @param collection
      *            the collection of elements to add.
-     * @since Android 1.0
      */
     public HashSet(Collection<? extends E> collection) {
-        this(new HashMap<E, HashSet<E>>(collection.size() < 6 ? 11 : collection.size() * 2));
+        this(new HashMap<E, HashSet<E>>(collection.size() < 6 ? 11 : collection
+                .size() * 2));
         for (E e : collection) {
             add(e);
         }
@@ -96,7 +89,6 @@
      *            the object to add.
      * @return {@code true} when this {@code HashSet} did not already contain
      *         the object, {@code false} otherwise
-     * @since Android 1.0
      */
     @Override
     public boolean add(E object) {
@@ -108,7 +100,6 @@
      * 
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -121,7 +112,6 @@
      * 
      * @return a shallow copy of this {@code HashSet}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -142,7 +132,6 @@
      *            the object to search for.
      * @return {@code true} if {@code object} is an element of this
      *         {@code HashSet}, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean contains(Object object) {
@@ -155,7 +144,6 @@
      * @return {@code true} if this {@code HashSet} has no elements,
      *         {@code false} otherwise.
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public boolean isEmpty() {
@@ -167,7 +155,6 @@
      * 
      * @return an Iterator on the elements of this {@code HashSet}.
      * @see Iterator
-     * @since Android 1.0
      */
     @Override
     public Iterator<E> iterator() {
@@ -180,7 +167,6 @@
      * @param object
      *            the object to remove.
      * @return {@code true} if the object was removed, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean remove(Object object) {
@@ -191,7 +177,6 @@
      * Returns the number of elements in this {@code HashSet}.
      * 
      * @return the number of elements in this {@code HashSet}.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -221,7 +206,7 @@
         backingMap = createBackingMap(length, loadFactor);
         int elementCount = stream.readInt();
         for (int i = elementCount; --i >= 0;) {
-            E key = (E)stream.readObject();
+            E key = (E) stream.readObject();
             backingMap.put(key, this);
         }
     }
diff --git a/luni/src/main/java/java/util/Hashtable.java b/luni/src/main/java/java/util/Hashtable.java
index abede2d..f1c1f74 100644
--- a/luni/src/main/java/java/util/Hashtable.java
+++ b/luni/src/main/java/java/util/Hashtable.java
@@ -31,12 +31,11 @@
  * factor is a float value which determines how full the Hashtable gets before
  * expanding the capacity. If the load factor of the Hashtable is exceeded, the
  * capacity is doubled.
- * 
+ *
  * @see Enumeration
  * @see java.io.Serializable
  * @see java.lang.Object#equals
  * @see java.lang.Object#hashCode
- * @since Android 1.0
  */
 
 public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>,
@@ -68,6 +67,21 @@
         }
     };
 
+    private static final Iterator<?> EMPTY_ITERATOR = new Iterator<Object>() {
+
+        public boolean hasNext() {
+            return false;
+        }
+
+        public Object next() {
+            throw new NoSuchElementException();
+        }
+
+        public void remove() {
+            throw new IllegalStateException();
+        }
+    };
+
     private static <K, V> Entry<K, V> newEntry(K key, V value, int hash) {
         return new Entry<K, V>(key, value);
     }
@@ -121,16 +135,16 @@
         }
     }
 
-    private final class HashIterator<E> implements Iterator<E> {
-        private int position, expectedModCount;
+    private class HashIterator<E> implements Iterator<E> {
+        int position, expectedModCount;
 
-        private final MapEntry.Type<E, K, V> type;
+        final MapEntry.Type<E, K, V> type;
 
-        private Entry<K, V> lastEntry;
+        Entry<K, V> lastEntry;
 
-        private int lastPosition;
+        int lastPosition;
 
-        private boolean canRemove = false;
+        boolean canRemove = false;
 
         HashIterator(MapEntry.Type<E, K, V> value) {
             type = value;
@@ -218,47 +232,9 @@
         }
     }
 
-    private final class HashEnumerator<E> implements Enumeration<E> {
-        boolean key;
-
-        int start;
-
-        Entry<K, V> entry;
-
-        HashEnumerator(boolean isKey) {
-            key = isKey;
-            start = lastSlot + 1;
-        }
-
-        public boolean hasMoreElements() {
-            if (entry != null) {
-                return true;
-            }
-            while (--start >= firstSlot) {
-                if (elementData[start] != null) {
-                    entry = elementData[start];
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @SuppressWarnings("unchecked")
-        public E nextElement() {
-            if (hasMoreElements()) {
-                Object result = key ? entry.key : entry.value;
-                entry = entry.next;
-                return (E) result;
-            }
-            throw new NoSuchElementException();
-        }
-    }
-
     /**
      * Constructs a new {@code Hashtable} using the default capacity and load
      * factor.
-     * 
-     * @since Android 1.0
      */
     public Hashtable() {
         this(11);
@@ -267,10 +243,9 @@
     /**
      * Constructs a new {@code Hashtable} using the specified capacity and the
      * default load factor.
-     * 
+     *
      * @param capacity
      *            the initial capacity.
-     * @since Android 1.0
      */
     public Hashtable(int capacity) {
         if (capacity >= 0) {
@@ -287,12 +262,11 @@
     /**
      * Constructs a new {@code Hashtable} using the specified capacity and load
      * factor.
-     * 
+     *
      * @param capacity
      *            the initial capacity.
      * @param loadFactor
      *            the initial load factor.
-     * @since Android 1.0
      */
     public Hashtable(int capacity, float loadFactor) {
         if (capacity >= 0 && loadFactor > 0) {
@@ -309,10 +283,9 @@
     /**
      * Constructs a new instance of {@code Hashtable} containing the mappings
      * from the specified map.
-     * 
+     *
      * @param map
      *            the mappings to add.
-     * @since Android 1.0
      */
     public Hashtable(Map<? extends K, ? extends V> map) {
         this(map.size() < 6 ? 11 : (map.size() * 4 / 3) + 11);
@@ -327,10 +300,9 @@
     /**
      * Removes all key/value pairs from this {@code Hashtable}, leaving the
      * size zero and the capacity unchanged.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void clear() {
         elementCount = 0;
@@ -341,17 +313,16 @@
     /**
      * Returns a new {@code Hashtable} with the same key/value pairs, capacity
      * and load factor.
-     * 
+     *
      * @return a shallow copy of this {@code Hashtable}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
     public synchronized Object clone() {
         try {
             Hashtable<K, V> hashtable = (Hashtable<K, V>) super.clone();
-            hashtable.elementData = elementData.clone();
+            hashtable.elementData = new Entry[elementData.length];
             Entry<K, V> entry;
             for (int i = elementData.length; --i >= 0;) {
                 if ((entry = elementData[i]) != null) {
@@ -371,14 +342,13 @@
     /**
      * Returns true if this {@code Hashtable} contains the specified object as
      * the value of at least one of the key/value pairs.
-     * 
+     *
      * @param value
      *            the object to look for as a value in this {@code Hashtable}.
      * @return {@code true} if object is a value in this {@code Hashtable},
      *         {@code false} otherwise.
      * @see #containsKey
      * @see java.lang.Object#equals
-     * @since Android 1.0
      */
     public synchronized boolean contains(Object value) {
         if (value == null) {
@@ -388,7 +358,7 @@
         for (int i = elementData.length; --i >= 0;) {
             Entry<K, V> entry = elementData[i];
             while (entry != null) {
-                if (value.equals(entry.value)) {
+                if (entry.value.equals(value)) {
                     return true;
                 }
                 entry = entry.next;
@@ -400,14 +370,13 @@
     /**
      * Returns true if this {@code Hashtable} contains the specified object as a
      * key of one of the key/value pairs.
-     * 
+     *
      * @param key
      *            the object to look for as a key in this {@code Hashtable}.
      * @return {@code true} if object is a key in this {@code Hashtable},
      *         {@code false} otherwise.
      * @see #contains
      * @see java.lang.Object#equals
-     * @since Android 1.0
      */
     public synchronized boolean containsKey(Object key) {
         return getEntry(key) != null;
@@ -415,12 +384,11 @@
 
     /**
      * Searches this {@code Hashtable} for the specified value.
-     * 
+     *
      * @param value
      *            the object to search for.
      * @return {@code true} if {@code value} is a value of this
      *         {@code Hashtable}, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsValue(Object value) {
         return contains(value);
@@ -430,12 +398,11 @@
      * Returns an enumeration on the values of this {@code Hashtable}. The
      * results of the Enumeration may be affected if the contents of this
      * {@code Hashtable} are modified.
-     * 
+     *
      * @return an enumeration of the values of this {@code Hashtable}.
      * @see #keys
      * @see #size
      * @see Enumeration
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -443,7 +410,11 @@
         if (elementCount == 0) {
             return (Enumeration<V>) EMPTY_ENUMERATION;
         }
-        return new HashEnumerator<V>(false);
+        return new HashEnumIterator<V>(new MapEntry.Type<V, K, V>() {
+            public V get(MapEntry<K, V> entry) {
+                return entry.value;
+            }
+        }, true);
     }
 
     /**
@@ -451,18 +422,15 @@
      * element in the set is a {@link Map.Entry}. The set is backed by this
      * {@code Hashtable} so changes to one are reflected by the other. The set
      * does not support adding.
-     * 
+     *
      * @return a set of the mappings.
-     * @since Android 1.0
      */
     public Set<Map.Entry<K, V>> entrySet() {
         return new Collections.SynchronizedSet<Map.Entry<K, V>>(
                 new AbstractSet<Map.Entry<K, V>>() {
                     @Override
                     public int size() {
-                        synchronized (Hashtable.this) {
-                            return elementCount;
-                        }
+                        return elementCount;
                     }
 
                     @Override
@@ -473,25 +441,20 @@
                     @Override
                     @SuppressWarnings("unchecked")
                     public boolean remove(Object object) {
-                        synchronized (Hashtable.this) {
-                            if (contains(object)) {
-                                Hashtable.this
-                                        .remove(((Map.Entry<K, V>) object)
-                                                .getKey());
-                                return true;
-                            }
-                            return false;
+                        if (contains(object)) {
+                            Hashtable.this.remove(((Map.Entry<K, V>) object)
+                                    .getKey());
+                            return true;
                         }
+                        return false;
                     }
 
                     @Override
                     @SuppressWarnings("unchecked")
                     public boolean contains(Object object) {
-                        synchronized (Hashtable.this) {
-                            Entry<K, V> entry = getEntry(((Map.Entry<K, V>) object)
-                                    .getKey());
-                            return object.equals(entry);
-                        }
+                        Entry<K, V> entry = getEntry(((Map.Entry<K, V>) object)
+                                .getKey());
+                        return object.equals(entry);
                     }
 
                     @Override
@@ -511,13 +474,12 @@
      * Compares this {@code Hashtable} with the specified object and indicates
      * if they are equal. In order to be equal, {@code object} must be an
      * instance of Map and contain the same key/value pairs.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the specified object is equal to this Map,
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean equals(Object object) {
@@ -544,13 +506,12 @@
     /**
      * Returns the value associated with the specified key in this
      * {@code Hashtable}.
-     * 
+     *
      * @param key
      *            the key of the value returned.
      * @return the value associated with the specified key, or {@code null} if
      *         the specified key does not exist.
      * @see #put
-     * @since Android 1.0
      */
     @Override
     public synchronized V get(Object key) {
@@ -597,11 +558,10 @@
 
     /**
      * Returns true if this {@code Hashtable} has no key/value pairs.
-     * 
+     *
      * @return {@code true} if this {@code Hashtable} has no key/value pairs,
      *         {@code false} otherwise.
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean isEmpty() {
@@ -612,12 +572,11 @@
      * Returns an enumeration on the keys of this {@code Hashtable} instance.
      * The results of the enumeration may be affected if the contents of this
      * {@code Hashtable} are modified.
-     * 
+     *
      * @return an enumeration of the keys of this {@code Hashtable}.
      * @see #elements
      * @see #size
      * @see Enumeration
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -625,31 +584,30 @@
         if (elementCount == 0) {
             return (Enumeration<K>) EMPTY_ENUMERATION;
         }
-        return new HashEnumerator<K>(true);
+        return new HashEnumIterator<K>(new MapEntry.Type<K, K, V>() {
+            public K get(MapEntry<K, V> entry) {
+                return entry.key;
+            }
+        }, true);
     }
 
     /**
      * Returns a set of the keys contained in this {@code Hashtable}. The set
      * is backed by this {@code Hashtable} so changes to one are reflected by
      * the other. The set does not support adding.
-     * 
+     *
      * @return a set of the keys.
-     * @since Android 1.0
      */
     public Set<K> keySet() {
         return new Collections.SynchronizedSet<K>(new AbstractSet<K>() {
             @Override
             public boolean contains(Object object) {
-                synchronized (Hashtable.this) {
-                    return containsKey(object);
-                }
+                return containsKey(object);
             }
 
             @Override
             public int size() {
-                synchronized (Hashtable.this) {
-                    return elementCount;
-                }
+                return elementCount;
             }
 
             @Override
@@ -659,18 +617,19 @@
 
             @Override
             public boolean remove(Object key) {
-                synchronized (Hashtable.this) {
-                    if (containsKey(key)) {
-                        Hashtable.this.remove(key);
-                        return true;
-                    }
-                    return false;
+                if (containsKey(key)) {
+                    Hashtable.this.remove(key);
+                    return true;
                 }
+                return false;
             }
 
             @Override
             public Iterator<K> iterator() {
-                return new HashIterator<K>(new MapEntry.Type<K, K, V>() {
+                if (this.size() == 0) {
+                    return (Iterator<K>) EMPTY_ITERATOR;
+                }
+                return new HashEnumIterator<K>(new MapEntry.Type<K, K, V>() {
                     public K get(MapEntry<K, V> entry) {
                         return entry.key;
                     }
@@ -679,11 +638,89 @@
         }, this);
     }
 
+    class HashEnumIterator<E> extends HashIterator<E> implements Enumeration<E> {
+
+        private boolean isEnumeration = false;
+
+        int start;
+
+        Entry<K, V> entry;
+
+        HashEnumIterator(MapEntry.Type<E, K, V> value) {
+            super(value);
+        }
+
+        HashEnumIterator(MapEntry.Type<E, K, V> value, boolean isEnumeration) {
+            super(value);
+            this.isEnumeration = isEnumeration;
+            start = lastSlot + 1;
+        }
+
+        public boolean hasMoreElements() {
+            if (isEnumeration) {
+                if (entry != null) {
+                    return true;
+                }
+                while (start > firstSlot) {
+                    if (elementData[--start] != null) {
+                        entry = elementData[start];
+                        return true;
+                    }
+                }
+                return false;
+            }
+            // iterator
+            return super.hasNext();
+        }
+
+        public boolean hasNext() {
+            if (isEnumeration) {
+                return hasMoreElements();
+            }
+            // iterator
+            return super.hasNext();
+        }
+
+        public E next() {
+            if (isEnumeration) {
+                if (expectedModCount == modCount) {
+                    return nextElement();
+                } else {
+                    throw new ConcurrentModificationException();
+                }
+            }
+            // iterator
+            return super.next();
+        }
+
+        @SuppressWarnings("unchecked")
+        public E nextElement() {
+            if (isEnumeration) {
+                if (hasMoreElements()) {
+                    Object result = type.get(entry);
+                    entry = entry.next;
+                    return (E) result;
+                }
+                throw new NoSuchElementException();
+            }
+            // iterator
+            return super.next();
+        }
+
+        public void remove() {
+            if (isEnumeration) {
+                throw new UnsupportedOperationException();
+            } else {
+                super.remove();
+            }
+        }
+    }
+
     /**
      * Associate the specified value with the specified key in this
      * {@code Hashtable}. If the key already exists, the old value is replaced.
      * The key and value cannot be null.
-     * 
+     *
      * @param key
      *            the key to add.
      * @param value
@@ -694,7 +731,6 @@
      * @see #get
      * @see #keys
      * @see java.lang.Object#equals
-     * @since Android 1.0
      */
     @Override
     public synchronized V put(K key, V value) {
@@ -731,10 +767,9 @@
 
     /**
      * Copies every mapping to this {@code Hashtable} from the specified map.
-     * 
+     *
      * @param map
      *            the map to copy mappings from.
-     * @since Android 1.0
      */
     public synchronized void putAll(Map<? extends K, ? extends V> map) {
         for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
@@ -745,8 +780,6 @@
     /**
      * Increases the capacity of this {@code Hashtable}. This method is called
      * when the size of this {@code Hashtable} exceeds the load factor.
-     * 
-     * @since Android 1.0
      */
     protected void rehash() {
         int length = (elementData.length << 1) + 1;
@@ -781,14 +814,13 @@
     /**
      * Removes the key/value pair with the specified key from this
      * {@code Hashtable}.
-     * 
+     *
      * @param key
      *            the key to remove.
      * @return the value associated with the specified key, or {@code null} if
      *         the specified key did not exist.
      * @see #get
      * @see #put
-     * @since Android 1.0
      */
     @Override
     public synchronized V remove(Object key) {
@@ -817,11 +849,10 @@
 
     /**
      * Returns the number of key/value pairs in this {@code Hashtable}.
-     * 
+     *
      * @return the number of key/value pairs in this {@code Hashtable}.
      * @see #elements
      * @see #keys
-     * @since Android 1.0
      */
     @Override
     public synchronized int size() {
@@ -830,9 +861,8 @@
 
     /**
      * Returns the string representation of this {@code Hashtable}.
-     * 
+     *
      * @return the string representation of this {@code Hashtable}.
-     * @since Android 1.0
      */
     @Override
     public synchronized String toString() {
@@ -874,25 +904,20 @@
      * Returns a collection of the values contained in this {@code Hashtable}.
      * The collection is backed by this {@code Hashtable} so changes to one are
      * reflected by the other. The collection does not support adding.
-     * 
+     *
      * @return a collection of the values.
-     * @since Android 1.0
      */
     public Collection<V> values() {
         return new Collections.SynchronizedCollection<V>(
                 new AbstractCollection<V>() {
                     @Override
                     public boolean contains(Object object) {
-                        synchronized (Hashtable.this) {
-                            return Hashtable.this.contains(object);
-                        }
+                        return Hashtable.this.contains(object);
                     }
 
                     @Override
                     public int size() {
-                        synchronized (Hashtable.this) {
-                            return elementCount;
-                        }
+                        return elementCount;
                     }
 
                     @Override
diff --git a/luni/src/main/java/java/util/HugeEnumSet.java b/luni/src/main/java/java/util/HugeEnumSet.java
index 1d43360..fd3e1bd 100644
--- a/luni/src/main/java/java/util/HugeEnumSet.java
+++ b/luni/src/main/java/java/util/HugeEnumSet.java
@@ -92,6 +92,8 @@
             currentElementMask = unProcessedBits[bitsPosition]
                     & (-unProcessedBits[bitsPosition]);
             unProcessedBits[bitsPosition] -= currentElementMask;
+            int index = Long.numberOfTrailingZeros(currentElementMask)
+                    + bitsPosition * BIT_IN_LONG;
             if (0 == unProcessedBits[bitsPosition]) {
                 int oldBitsPosition = bitsPosition;
                 findNextNoneZeroPosition(bitsPosition + 1);
@@ -99,8 +101,7 @@
                     canProcess = false;
                 }
             }
-            return enums[Long.numberOfTrailingZeros(currentElementMask)
-                    + bitsPosition * BIT_IN_LONG];
+            return enums[index];
         }
 
         public void remove() {
@@ -185,6 +186,7 @@
         }
     }
     
+    @SuppressWarnings("unchecked")
     @Override
     public boolean contains(Object object) {
         if (null == object) {
@@ -329,7 +331,7 @@
 
             // endElementInBits + 1 is the number of consecutive ones.
             // 63 - endElementInBits is the following zeros of the right most one.
-            range = -1l >>> (BIT_IN_LONG - (endElementInBits + 1)) << (63 - endElementInBits);
+            range = -1l >>> (BIT_IN_LONG - (endElementInBits + 1));
             size -= Long.bitCount(bits[endBitsIndex]);
             bits[endBitsIndex] |= range;
             size += Long.bitCount(bits[endBitsIndex]);
diff --git a/luni/src/main/java/java/util/IdentityHashMap.java b/luni/src/main/java/java/util/IdentityHashMap.java
index 3301a99..30330b5 100644
--- a/luni/src/main/java/java/util/IdentityHashMap.java
+++ b/luni/src/main/java/java/util/IdentityHashMap.java
@@ -30,16 +30,15 @@
  * <p>
  * <b>Note: This class intentionally violates the general contract of {@code
  * Map}'s on comparing objects by their {@code equals} method.</b>
- * </p>
  * <p>
  * IdentityHashMap uses open addressing (linear probing in particular) for
  * collision resolution. This is different from HashMap which uses Chaining.
- * </p>
+ * <p>
  * Like HashMap, IdentityHashMap is not thread safe, so access by multiple
  * threads must be synchronized by an external mechanism such as
  * Collections.synchronizedMap.
  * 
- * @since Android 1.0
+ * @since 1.4
  */
 public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements
         Map<K, V>, Serializable, Cloneable {
@@ -239,8 +238,6 @@
 
     /**
      * Creates an IdentityHashMap with default expected maximum size.
-     * 
-     * @since Android 1.0
      */
     public IdentityHashMap() {
         this(DEFAULT_MAX_SIZE);
@@ -252,7 +249,6 @@
      * @param maxSize
      *            The estimated maximum number of entries that will be put in
      *            this map.
-     * @since Android 1.0
      */
     public IdentityHashMap(int maxSize) {
         if (maxSize >= 0) {
@@ -274,6 +270,13 @@
         return (int) (((long) threshold * 10000) / loadFactor) * 2;
     }
 
+    /**
+     * Create a new element array
+     * 
+     * @param s
+     *            the number of elements
+     * @return Reference to the element array
+     */
     private Object[] newElementArray(int s) {
         return new Object[s];
     }
@@ -283,7 +286,6 @@
      * 
      * @param map
      *            A map of (key,value) pairs to copy into the IdentityHashMap.
-     * @since Android 1.0
      */
     public IdentityHashMap(Map<? extends K, ? extends V> map) {
         this(map.size() < 6 ? 11 : map.size() * 2);
@@ -300,7 +302,6 @@
      * 
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -318,7 +319,6 @@
      *            the key to search for.
      * @return {@code true} if this map contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsKey(Object key) {
@@ -337,7 +337,6 @@
      *            the value to search for.
      * @return {@code true} if this map contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsValue(Object value) {
@@ -359,7 +358,6 @@
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key.
-     * @since Android 1.0
      */
     @Override
     public V get(Object key) {
@@ -390,6 +388,10 @@
         return null;
     }
 
+    /**
+     * Convenience method for getting the IdentityHashMapEntry without the
+     * NULL_OBJECT elements
+     */
     @SuppressWarnings("unchecked")
     private IdentityHashMapEntry<K, V> getEntry(int index) {
         Object key = elementData[index];
@@ -405,6 +407,10 @@
         return new IdentityHashMapEntry<K, V>((K) key, (V) value);
     }
 
+    /**
+     * Returns the index where the key is found at, or the index of the next
+     * empty spot if the key is not found in this table.
+     */
     private int findIndex(Object key, Object[] array) {
         int length = array.length;
         int index = getModuloHash(key, length);
@@ -435,7 +441,6 @@
      *            the value.
      * @return the value of any previous mapping with the specified key or
      *         {@code null} if there was no such mapping.
-     * @since Android 1.0
      */
     @Override
     public V put(K key, V value) {
@@ -478,7 +483,8 @@
      * 
      * @param map
      *            the map to copy mappings from.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code map} is {@code null}.
      */
     @Override
     public void putAll(Map<? extends K, ? extends V> map) {
@@ -515,7 +521,6 @@
      *            the key of the mapping to remove.
      * @return the value of the removed mapping, or {@code null} if no mapping
      *         for the specified key was found.
-     * @since Android 1.0
      */
     @Override
     public V remove(Object key) {
@@ -575,7 +580,6 @@
      * changes in one will be reflected in the other.
      * 
      * @return a set of the mappings.
-     * @since Android 1.0
      */
     @Override
     public Set<Map.Entry<K, V>> entrySet() {
@@ -588,7 +592,6 @@
      * support adding.
      * 
      * @return a set of the keys.
-     * @since Android 1.0
      */
     @Override
     public Set<K> keySet() {
@@ -643,16 +646,13 @@
      * "wrapper object" over the iterator of map's entrySet(). The {@code size}
      * method wraps the map's size method and the {@code contains} method wraps
      * the map's containsValue method.
-     * </p>
      * <p>
      * The collection is created when this method is called for the first time
      * and returned in response to all subsequent calls. This method may return
      * different collections when multiple concurrent calls occur, since no
      * synchronization is performed.
-     * </p>
      * 
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     @Override
     public Collection<V> values() {
@@ -710,7 +710,6 @@
      * @param object
      *            the object to compare to.
      * @return whether the argument object is equal to this object.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -745,7 +744,6 @@
      * 
      * @return a shallow copy of this IdentityHashMap.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -762,7 +760,6 @@
      * @return {@code true} if this IdentityHashMap has no elements,
      *         {@code false} otherwise.
      * @see #size()
-     * @since Android 1.0
      */
     @Override
     public boolean isEmpty() {
@@ -773,7 +770,6 @@
      * Returns the number of mappings in this IdentityHashMap.
      * 
      * @return the number of mappings in this IdentityHashMap.
-     * @since Android 1.0
      */
     @Override
     public int size() {
diff --git a/luni/src/main/java/java/util/IllegalFormatCodePointException.java b/luni/src/main/java/java/util/IllegalFormatCodePointException.java
index e04eeba..c0d6b6f 100644
--- a/luni/src/main/java/java/util/IllegalFormatCodePointException.java
+++ b/luni/src/main/java/java/util/IllegalFormatCodePointException.java
@@ -24,7 +24,6 @@
  * passed as a parameter to a Formatter.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class IllegalFormatCodePointException extends IllegalFormatException
         implements Serializable {
diff --git a/luni/src/main/java/java/util/IllegalFormatConversionException.java b/luni/src/main/java/java/util/IllegalFormatConversionException.java
index 769381b..696f4f2 100644
--- a/luni/src/main/java/java/util/IllegalFormatConversionException.java
+++ b/luni/src/main/java/java/util/IllegalFormatConversionException.java
@@ -23,7 +23,8 @@
  * is incompatible with the corresponding format specifier.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public class IllegalFormatConversionException extends IllegalFormatException
         implements Serializable {
diff --git a/luni/src/main/java/java/util/IllegalFormatException.java b/luni/src/main/java/java/util/IllegalFormatException.java
index 2c1f2d7..3d37cd0 100644
--- a/luni/src/main/java/java/util/IllegalFormatException.java
+++ b/luni/src/main/java/java/util/IllegalFormatException.java
@@ -24,7 +24,6 @@
  * allowed to be instantiated.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class IllegalFormatException extends IllegalArgumentException implements
         Serializable {
diff --git a/luni/src/main/java/java/util/IllegalFormatFlagsException.java b/luni/src/main/java/java/util/IllegalFormatFlagsException.java
index 6b27c74..4fa2d9c 100644
--- a/luni/src/main/java/java/util/IllegalFormatFlagsException.java
+++ b/luni/src/main/java/java/util/IllegalFormatFlagsException.java
@@ -23,7 +23,6 @@
  * the format flags is illegal.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class IllegalFormatFlagsException extends IllegalFormatException
         implements Serializable {
diff --git a/luni/src/main/java/java/util/IllegalFormatPrecisionException.java b/luni/src/main/java/java/util/IllegalFormatPrecisionException.java
index 6ccf5d2..5d5113f 100644
--- a/luni/src/main/java/java/util/IllegalFormatPrecisionException.java
+++ b/luni/src/main/java/java/util/IllegalFormatPrecisionException.java
@@ -21,7 +21,6 @@
  * a negative other than -1 or in other cases where precision is not supported.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 
 public class IllegalFormatPrecisionException extends IllegalFormatException {
diff --git a/luni/src/main/java/java/util/IllegalFormatWidthException.java b/luni/src/main/java/java/util/IllegalFormatWidthException.java
index 8348ec7..01904f8 100644
--- a/luni/src/main/java/java/util/IllegalFormatWidthException.java
+++ b/luni/src/main/java/java/util/IllegalFormatWidthException.java
@@ -22,7 +22,6 @@
  * supported.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class IllegalFormatWidthException extends IllegalFormatException {
 
diff --git a/luni/src/main/java/java/util/InputMismatchException.java b/luni/src/main/java/java/util/InputMismatchException.java
index 0fc5385..eed0b83 100644
--- a/luni/src/main/java/java/util/InputMismatchException.java
+++ b/luni/src/main/java/java/util/InputMismatchException.java
@@ -24,13 +24,12 @@
  * 
  * @see Scanner
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class InputMismatchException extends NoSuchElementException implements
         Serializable {
 
-    static final long serialVersionUID = 8811230760997066428L;
-    
+    private static final long serialVersionUID = 8811230760997066428L;
+
     /**
      * Constructs a new {@code InputMismatchException} with the current stack
      * trace filled in.
diff --git a/luni/src/main/java/java/util/InvalidPropertiesFormatException.java b/luni/src/main/java/java/util/InvalidPropertiesFormatException.java
index 4e8a3e3..015c3d0 100644
--- a/luni/src/main/java/java/util/InvalidPropertiesFormatException.java
+++ b/luni/src/main/java/java/util/InvalidPropertiesFormatException.java
@@ -30,8 +30,6 @@
  * Even though this Exception inherits the {@code Serializable} interface, it is not
  * serializable. The methods used for serialization throw
  * {@code NotSerializableException}s.
- * 
- * @since Android 1.0
  */
 public class InvalidPropertiesFormatException extends IOException {
     
diff --git a/luni/src/main/java/java/util/Iterator.java b/luni/src/main/java/java/util/Iterator.java
index 9f20dc5..6ebae04 100644
--- a/luni/src/main/java/java/util/Iterator.java
+++ b/luni/src/main/java/java/util/Iterator.java
@@ -17,17 +17,18 @@
 
 package java.util;
 
-
 /**
- * An Iterator is used to sequence over a collection of objects. Conceptual, an
- * iterator is always positioned between two elements of a collection. A fresh
- * iterator is always positioned in front of the first element.
+ * An {@code Iterator} is used to sequence over a collection of objects.
+ * Conceptually, an iterator is always positioned between two elements of a
+ * collection. A fresh iterator is always positioned in front of the first
+ * element.
  * 
  * If a collection has been changed since its creation, methods {@code next} and
  * {@code hasNext()} may throw a {@code ConcurrentModificationException}.
  * Iterators with this behavior are called fail-fast iterators.
  * 
- * @since Android 1.0
+ * @param <E>
+ *            the type of object returned by the iterator.
  */
 public interface Iterator<E> {
     /**
@@ -36,7 +37,6 @@
      * 
      * @return {@code true} if there are more elements, {@code false} otherwise.
      * @see #next
-     * @since Android 1.0
      */
     public boolean hasNext();
 
@@ -48,7 +48,6 @@
      * @throws NoSuchElementException
      *             if there are no more elements.
      * @see #hasNext
-     * @since Android 1.0
      */
     public E next();
 
@@ -62,7 +61,6 @@
      * @throws IllegalStateException
      *             if {@code next} has not been called, or {@code remove} has
      *             already been called after the last call to {@code next}.
-     * @since Android 1.0
      */
     public void remove();
 }
diff --git a/luni/src/main/java/java/util/LinkedHashMap.java b/luni/src/main/java/java/util/LinkedHashMap.java
index a32a28b..ed526d8 100644
--- a/luni/src/main/java/java/util/LinkedHashMap.java
+++ b/luni/src/main/java/java/util/LinkedHashMap.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 /**
  * LinkedHashMap is a variant of HashMap. Its entries are kept in a
  * doubly-linked list. The iteration order is, by default, the order in which
@@ -46,8 +45,8 @@
  * elements during iteration. It is not possible to guarantee that this
  * mechanism works in all cases of unsynchronized concurrent modification. It
  * should only be used for debugging purposes.
- * 
- * @since Android 1.0
+ *
+ * @since 1.4
  */
 public class LinkedHashMap<K, V> extends HashMap<K, V> {
 
@@ -59,8 +58,6 @@
 
     /**
      * Constructs a new empty {@code LinkedHashMap} instance.
-     * 
-     * @since Android 1.0
      */
     public LinkedHashMap() {
         super();
@@ -71,12 +68,11 @@
     /**
      * Constructs a new {@code LinkedHashMap} instance with the specified
      * capacity.
-     * 
+     *
      * @param s
      *            the initial capacity of this map.
-     * @exception IllegalArgumentException
-     *                when the capacity is less than zero.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the capacity is less than zero.
      */
     public LinkedHashMap(int s) {
         super(s);
@@ -87,7 +83,7 @@
     /**
      * Constructs a new {@code LinkedHashMap} instance with the specified
      * capacity and load factor.
-     * 
+     *
      * @param s
      *            the initial capacity of this map.
      * @param lf
@@ -95,7 +91,6 @@
      * @throws IllegalArgumentException
      *             when the capacity is less than zero or the load factor is
      *             less or equal to zero.
-     * @since Android 1.0
      */
     public LinkedHashMap(int s, float lf) {
         super(s, lf);
@@ -107,7 +102,7 @@
     /**
      * Constructs a new {@code LinkedHashMap} instance with the specified
      * capacity, load factor and a flag specifying the ordering behavior.
-     * 
+     *
      * @param s
      *            the initial capacity of this hash map.
      * @param lf
@@ -120,7 +115,6 @@
      * @throws IllegalArgumentException
      *             when the capacity is less than zero or the load factor is
      *             less or equal to zero.
-     * @since Android 1.0
      */
     public LinkedHashMap(int s, float lf, boolean order) {
         super(s, lf);
@@ -132,10 +126,9 @@
     /**
      * Constructs a new {@code LinkedHashMap} instance containing the mappings
      * from the specified map. The order of the elements is preserved.
-     * 
+     *
      * @param m
      *            the mappings to add.
-     * @since Android 1.0
      */
     public LinkedHashMap(Map<? extends K, ? extends V> m) {
         accessOrder = false;
@@ -144,58 +137,47 @@
         putAll(m);
     }
 
-    static final class LinkedHashIterator<E, KT, VT> extends HashMapIterator<E, KT, VT> {
-        LinkedHashIterator(MapEntry.Type<E, KT, VT> value, LinkedHashMap<KT, VT> hm) {
-            super(value, hm);
-            entry = hm.head;
+    private static class AbstractMapIterator<K, V>  {
+        int expectedModCount;
+        LinkedHashMapEntry<K, V>  futureEntry;
+        LinkedHashMapEntry<K, V>  currentEntry;
+        final LinkedHashMap<K, V> associatedMap;
+
+        AbstractMapIterator(LinkedHashMap<K, V> map) {
+            expectedModCount = map.modCount;
+            futureEntry = map.head;
+            associatedMap = map;
         }
 
-        @Override
         public boolean hasNext() {
-            return (entry != null);
+            return (futureEntry != null);
         }
 
-        @Override
-        public E next() {
+        final void checkConcurrentMod() throws ConcurrentModificationException {
+            if (expectedModCount != associatedMap.modCount) {
+                throw new ConcurrentModificationException();
+            }
+        }
+
+        final void makeNext() {
             checkConcurrentMod();
             if (!hasNext()) {
                 throw new NoSuchElementException();
             }
-            E result = type.get(entry);
-            lastEntry = entry;
-            entry = ((LinkedHashMapEntry<KT, VT>)entry).chainForward;
-            canRemove = true;
-            return result;
+            currentEntry = futureEntry;
+            futureEntry = futureEntry.chainForward;
         }
 
-        @Override
         public void remove() {
             checkConcurrentMod();
-            if (!canRemove) {
+            if (currentEntry==null) {
                 throw new IllegalStateException();
             }
-
-            canRemove = false;
-            associatedMap.modCount++;
-
-            int index = (lastEntry.key == null)? 0 : (lastEntry.key.hashCode() & 0x7FFFFFFF) % associatedMap.elementData.length;
-            LinkedHashMapEntry<KT, VT> m = (LinkedHashMapEntry<KT, VT>) associatedMap.elementData[index];
-            if (m == lastEntry) {
-                associatedMap.elementData[index] = lastEntry.next;
-            } else {
-                while (m.next != null) {
-                    if (m.next == lastEntry) {
-                        break;
-                    }
-                    m = (LinkedHashMapEntry<KT, VT>) m.next;
-                }
-                // assert m.next == entry
-                m.next = lastEntry.next;
-            }
-            LinkedHashMapEntry<KT, VT> lhme = (LinkedHashMapEntry<KT, VT>) lastEntry;
-            LinkedHashMapEntry<KT, VT> p = lhme.chainBackward;
-            LinkedHashMapEntry<KT, VT> n = lhme.chainForward;
-            LinkedHashMap<KT, VT> lhm = (LinkedHashMap<KT, VT>) associatedMap;
+            associatedMap.removeEntry(currentEntry);
+            LinkedHashMapEntry<K, V> lhme =  currentEntry;
+            LinkedHashMapEntry<K, V> p = lhme.chainBackward;
+            LinkedHashMapEntry<K, V> n = lhme.chainForward;
+            LinkedHashMap<K, V> lhm = associatedMap;
             if (p != null) {
                 p.chainForward = n;
                 if (n != null) {
@@ -211,23 +193,56 @@
                     lhm.tail = null;
                 }
             }
-            associatedMap.elementCount--;
+            currentEntry = null;
             expectedModCount++;
         }
     }
 
-    static final class LinkedHashMapEntrySet<KT, VT> extends HashMapEntrySet<KT, VT> {
+    private static class EntryIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<Map.Entry<K, V>> {
+
+        EntryIterator (LinkedHashMap<K, V> map) {
+            super(map);
+        }
+
+        public Map.Entry<K, V> next() {
+            makeNext();
+            return currentEntry;
+        }
+    }
+
+    private static class KeyIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<K> {
+
+        KeyIterator (LinkedHashMap<K, V> map) {
+            super(map);
+        }
+
+        public K next() {
+            makeNext();
+            return currentEntry.key;
+        }
+    }
+
+    private static class ValueIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<V> {
+
+        ValueIterator (LinkedHashMap<K, V> map) {
+            super(map);
+        }
+
+        public V next() {
+            makeNext();
+            return currentEntry.value;
+        }
+    }
+
+    static final class LinkedHashMapEntrySet<KT, VT> extends
+            HashMapEntrySet<KT, VT> {
         public LinkedHashMapEntrySet(LinkedHashMap<KT, VT> lhm) {
             super(lhm);
         }
 
         @Override
-        public Iterator<Map.Entry<KT,VT>> iterator() {
-            return new LinkedHashIterator<Map.Entry<KT,VT>,KT,VT>(new MapEntry.Type<Map.Entry<KT,VT>, KT, VT>() {
-                public Map.Entry<KT,VT> get(MapEntry<KT,VT> entry) {
-                    return entry;
-                }
-            }, (LinkedHashMap<KT, VT>) hashMap());
+        public Iterator<Map.Entry<KT, VT>> iterator() {
+            return new EntryIterator<KT,VT>((LinkedHashMap<KT, VT>) hashMap());
         }
     }
 
@@ -246,11 +261,11 @@
             chainBackward = null;
         }
 
-
         @Override
         @SuppressWarnings("unchecked")
         public Object clone() {
-            LinkedHashMapEntry<K, V> entry = (LinkedHashMapEntry<K, V>) super.clone();
+            LinkedHashMapEntry<K, V> entry = (LinkedHashMapEntry<K, V>) super
+                    .clone();
             entry.chainBackward = chainBackward;
             entry.chainForward = chainForward;
             LinkedHashMapEntry<K, V> lnext = (LinkedHashMapEntry<K, V>) entry.next;
@@ -262,6 +277,33 @@
     }
 
     @Override
+    public boolean containsValue(Object value) {
+        LinkedHashMapEntry<K, V> entry = head;
+        if (null == value) {
+            while (null != entry) {
+                if (null == entry.value) {
+                    return true;
+                }
+                entry = entry.chainForward;
+            }
+        } else {
+            while (null != entry) {
+                if (value.equals(entry.value)) {
+                    return true;
+                }
+                entry = entry.chainForward;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Create a new element array
+     *
+     * @param s
+     * @return Reference to the element array
+     */
+    @Override
     @SuppressWarnings("unchecked")
     Entry<K, V>[] newElementArray(int s) {
         return new LinkedHashMapEntry[s];
@@ -269,22 +311,21 @@
 
     /**
      * Returns the value of the mapping with the specified key.
-     * 
+     *
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
     @Override
     public V get(Object key) {
         LinkedHashMapEntry<K, V> m;
         if (key == null) {
-            m = (LinkedHashMapEntry<K, V>)findNullKeyEntry();
+            m = (LinkedHashMapEntry<K, V>) findNullKeyEntry();
         } else {
             int hash = key.hashCode();
             int index = (hash & 0x7FFFFFFF) % elementData.length;
-            m = (LinkedHashMapEntry<K, V>)findNonNullKeyEntry(key, index, hash);
+            m = (LinkedHashMapEntry<K, V>) findNonNullKeyEntry(key, index, hash);
         }
         if (m == null) {
             return null;
@@ -321,7 +362,7 @@
         return m;
     }
 
-    Entry<K,V> createHashedEntry(K key, int index, int hash) {
+    Entry<K, V> createHashedEntry(K key, int index, int hash) {
         LinkedHashMapEntry<K, V> m = new LinkedHashMapEntry<K, V>(key, hash);
         m.next = elementData[index];
         elementData[index] = m;
@@ -329,22 +370,19 @@
         return m;
     }
 
-    // BEGIN android-changed
-    // copied from newer version of harmony
     /**
      * Maps the specified key to the specified value.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
      *            the value.
      * @return the value of any previous mapping with the specified key or
      *         {@code null} if there was no such mapping.
-     * @since Android 1.0
      */
     @Override
     public V put(K key, V value) {
-        V result = putImpl(key,value);
+        V result = putImpl(key, value);
 
         if (removeEldestEntry(head)) {
             remove(head.key);
@@ -352,38 +390,38 @@
 
         return result;
     }
-    
-    V putImpl(K key, V value){
+
+    V putImpl(K key, V value) {
         LinkedHashMapEntry<K, V> m;
-        if (elementCount == 0){
+        if (elementCount == 0) {
             head = tail = null;
         }
         if (key == null) {
-            m = (LinkedHashMapEntry<K, V>)findNullKeyEntry();
+            m = (LinkedHashMapEntry<K, V>) findNullKeyEntry();
             if (m == null) {
                 modCount++;
-                // Check if we need to remove the oldest entry
-                // The check includes accessOrder since an accessOrder LinkedHashMap
-                // does not record
-                // the oldest member in 'head'.
+                // Check if we need to remove the oldest entry. The check
+                // includes accessOrder since an accessOrder LinkedHashMap does
+                // not record the oldest member in 'head'.
                 if (++elementCount > threshold) {
                     rehash();
                 }
-                    m = (LinkedHashMapEntry<K, V>) createHashedEntry(null, 0, 0);
+                m = (LinkedHashMapEntry<K, V>) createHashedEntry(null, 0, 0);
             } else {
                 linkEntry(m);
             }
         } else {
             int hash = key.hashCode();
             int index = (hash & 0x7FFFFFFF) % elementData.length;
-            m = (LinkedHashMapEntry<K, V>)findNonNullKeyEntry(key, index, hash);
+            m = (LinkedHashMapEntry<K, V>) findNonNullKeyEntry(key, index, hash);
             if (m == null) {
                 modCount++;
                 if (++elementCount > threshold) {
                     rehash();
                     index = (hash & 0x7FFFFFFF) % elementData.length;
                 }
-                m = (LinkedHashMapEntry<K, V>) createHashedEntry(key, index, hash);
+                m = (LinkedHashMapEntry<K, V>) createHashedEntry(key, index,
+                        hash);
             } else {
                 linkEntry(m);
             }
@@ -393,7 +431,6 @@
         m.value = value;
         return result;
     }
-    // END android-changed
 
     /*
      * @param m
@@ -448,16 +485,14 @@
             tail.chainForward = m;
             tail = m;
         }
-
     }
 
     /**
      * Returns a set containing all of the mappings in this map. Each mapping is
      * an instance of {@link Map.Entry}. As the set is backed by this map,
      * changes in one will be reflected in the other.
-     * 
+     *
      * @return a set of the mappings.
-     * @since Android 1.0
      */
     @Override
     public Set<Map.Entry<K, V>> entrySet() {
@@ -468,9 +503,8 @@
      * Returns a set of the keys contained in this map. The set is backed by
      * this map so changes to one are reflected by the other. The set does not
      * support adding.
-     * 
+     *
      * @return a set of the keys.
-     * @since Android 1.0
      */
     @Override
     public Set<K> keySet() {
@@ -502,11 +536,7 @@
 
                 @Override
                 public Iterator<K> iterator() {
-                    return new LinkedHashIterator<K,K,V>(new MapEntry.Type<K,K,V>() {
-                        public K get(MapEntry<K,V> entry) {
-                            return entry.key;
-                        }
-                    }, LinkedHashMap.this);
+                    return new KeyIterator<K,V>(LinkedHashMap.this);
                 }
             };
         }
@@ -524,16 +554,13 @@
      * "wrapper object" over the iterator of map's entrySet(). The size method
      * wraps the map's size method and the contains method wraps the map's
      * containsValue method.
-     * </p>
      * <p>
      * The collection is created when this method is called for the first time
      * and returned in response to all subsequent calls. This method may return
      * different collections when multiple concurrent calls occur, since no
      * synchronization is performed.
-     * </p>
-     * 
+     *
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     @Override
     public Collection<V> values() {
@@ -556,11 +583,7 @@
 
                 @Override
                 public Iterator<V> iterator() {
-                    return new LinkedHashIterator<V,K,V>(new MapEntry.Type<V,K,V>() {
-                        public V get(MapEntry<K,V> entry) {
-                            return entry.value;
-                        }
-                    }, LinkedHashMap.this);
+                    return new ValueIterator<K,V>(LinkedHashMap.this);
                 }
             };
         }
@@ -569,12 +592,11 @@
 
     /**
      * Removes the mapping with the specified key from this map.
-     * 
+     *
      * @param key
      *            the key of the mapping to remove.
      * @return the value of the removed mapping or {@code null} if no mapping
      *         for the specified key was found.
-     * @since Android 1.0
      */
     @Override
     public V remove(Object key) {
@@ -602,23 +624,21 @@
      * eldest member of the map should be deleted before adding the new member.
      * If this map was created with accessOrder = true, then the result of
      * removeEldestEntry is assumed to be false.
-     * 
+     *
      * @param eldest
      *            the entry to check if it should be removed.
      * @return {@code true} if the eldest member should be removed.
-     * @since Android 1.0
      */
-    protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
+    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
         return false;
     }
 
     // BEGIN android-changed
     /**
      * Removes all elements from this map, leaving it empty.
-     * 
+     *
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -631,25 +651,4 @@
         head = tail = null;
     }
     // END android-changed
-
-    // BEGIN android-removed
-    // copied from newer version of harmony
-    // /**
-    //  * Answers a new HashMap with the same mappings and size as this HashMap.
-    //  * 
-    //  * @return a shallow copy of this HashMap
-    //  * 
-    //  * @see java.lang.Cloneable
-    //  */
-    // @Override
-    // @SuppressWarnings("unchecked")
-    // public Object clone() {
-    //     LinkedHashMap<K, V> map = (LinkedHashMap<K, V>) super.clone();
-    //     map.clear();
-    //     for (Map.Entry<K, V> entry : entrySet()) {
-    //         map.put(entry.getKey(), entry.getValue());
-    //     }
-    //     return map;
-    // }
-    // END android-removed
 }
diff --git a/luni/src/main/java/java/util/LinkedHashSet.java b/luni/src/main/java/java/util/LinkedHashSet.java
index 943e01c..3add460 100644
--- a/luni/src/main/java/java/util/LinkedHashSet.java
+++ b/luni/src/main/java/java/util/LinkedHashSet.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.Serializable;
 
 /**
@@ -30,18 +29,16 @@
  * Like HashSet, LinkedHashSet is not thread safe, so access by multiple threads
  * must be synchronized by an external mechanism such as
  * {@link Collections#synchronizedSet(Set)}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.4
  */
 public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable,
         Serializable {
-    
+
     private static final long serialVersionUID = -2851667679971038690L;
 
     /**
      * Constructs a new empty instance of {@code LinkedHashSet}.
-     * 
-     * @since Android 1.0
      */
     public LinkedHashSet() {
         super(new LinkedHashMap<E, HashSet<E>>());
@@ -53,7 +50,6 @@
      * 
      * @param capacity
      *            the initial capacity of this {@code LinkedHashSet}.
-     * @since Android 1.0
      */
     public LinkedHashSet(int capacity) {
         super(new LinkedHashMap<E, HashSet<E>>(capacity));
@@ -67,7 +63,6 @@
      *            the initial capacity.
      * @param loadFactor
      *            the initial load factor.
-     * @since Android 1.0
      */
     public LinkedHashSet(int capacity, float loadFactor) {
         super(new LinkedHashMap<E, HashSet<E>>(capacity, loadFactor));
@@ -79,7 +74,6 @@
      * 
      * @param collection
      *            the collection of elements to add.
-     * @since Android 1.0
      */
     public LinkedHashSet(Collection<? extends E> collection) {
         super(new LinkedHashMap<E, HashSet<E>>(collection.size() < 6 ? 11
diff --git a/luni/src/main/java/java/util/LinkedList.java b/luni/src/main/java/java/util/LinkedList.java
index 7cfefe6..64326e3 100644
--- a/luni/src/main/java/java/util/LinkedList.java
+++ b/luni/src/main/java/java/util/LinkedList.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -28,12 +27,12 @@
  * LinkedList is an implementation of List, backed by a linked list. All
  * optional operations (adding, removing and replacing) are supported. The
  * elements can be any objects.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public class LinkedList<E> extends AbstractSequentialList<E> implements
         List<E>, Queue<E>, Cloneable, Serializable {
-    
+
     private static final long serialVersionUID = 876323262645176354L;
 
     transient int size = 0;
@@ -178,8 +177,6 @@
 
     /**
      * Constructs a new empty instance of {@code LinkedList}.
-     * 
-     * @since Android 1.0
      */
     public LinkedList() {
         voidLink = new Link<E>(null, null, null);
@@ -192,10 +189,9 @@
      * elements contained in the specified {@code collection}. The order of the
      * elements in this new {@code LinkedList} will be determined by the
      * iteration order of {@code collection}.
-     * 
+     *
      * @param collection
      *            the collection of elements to add.
-     * @since Android 1.0
      */
     public LinkedList(Collection<? extends E> collection) {
         this();
@@ -207,14 +203,13 @@
      * specified location. The object is inserted before any previous element at
      * the specified location. If the location is equal to the size of this
      * {@code LinkedList}, the object is added at the end.
-     * 
+     *
      * @param location
      *            the index at which to insert.
      * @param object
      *            the object to add.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     @Override
     public void add(int location, E object) {
@@ -242,11 +237,10 @@
 
     /**
      * Adds the specified object at the end of this {@code LinkedList}.
-     * 
+     *
      * @param object
      *            the object to add.
      * @return always true
-     * @since Android 1.0
      */
     @Override
     public boolean add(E object) {
@@ -264,7 +258,7 @@
      * Inserts the objects in the specified collection at the specified location
      * in this {@code LinkedList}. The objects are added in the order they are
      * returned from the collection's iterator.
-     * 
+     *
      * @param location
      *            the index at which to insert.
      * @param collection
@@ -277,7 +271,6 @@
      *             if an object cannot be added to this list.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || > size()}
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(int location, Collection<? extends E> collection) {
@@ -288,6 +281,9 @@
         if (adding == 0) {
             return false;
         }
+        Collection<? extends E> elements = (collection == this) ?
+                new ArrayList<E>(collection) : collection;
+
         Link<E> previous = voidLink;
         if (location < (size / 2)) {
             for (int i = 0; i < location; i++) {
@@ -299,7 +295,7 @@
             }
         }
         Link<E> next = previous.next;
-        for (E e : collection) {
+        for (E e : elements) {
             Link<E> newLink = new Link<E>(e, previous, null);
             previous.next = newLink;
             previous = newLink;
@@ -311,15 +307,13 @@
         return true;
     }
 
-
     /**
      * Adds the objects in the specified Collection to this {@code LinkedList}.
-     * 
+     *
      * @param collection
      *            the collection of objects.
      * @return {@code true} if this {@code LinkedList} is modified,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(Collection<? extends E> collection) {
@@ -327,8 +321,11 @@
         if (adding == 0) {
             return false;
         }
+        Collection<? extends E> elements = (collection == this) ?
+                new ArrayList<E>(collection) : collection;
+
         Link<E> previous = voidLink.previous;
-        for (E e : collection) {
+        for (E e : elements) {
             Link<E> newLink = new Link<E>(e, previous, null);
             previous.next = newLink;
             previous = newLink;
@@ -342,10 +339,9 @@
 
     /**
      * Adds the specified object at the beginning of this {@code LinkedList}.
-     * 
+     *
      * @param object
      *            the object to add.
-     * @since Android 1.0
      */
     public void addFirst(E object) {
         Link<E> oldFirst = voidLink.next;
@@ -358,10 +354,9 @@
 
     /**
      * Adds the specified object at the end of this {@code LinkedList}.
-     * 
+     *
      * @param object
      *            the object to add.
-     * @since Android 1.0
      */
     public void addLast(E object) {
         Link<E> oldLast = voidLink.previous;
@@ -374,10 +369,9 @@
 
     /**
      * Removes all elements from this {@code LinkedList}, leaving it empty.
-     * 
+     *
      * @see List#isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -392,10 +386,9 @@
     /**
      * Returns a new {@code LinkedList} with the same elements and size as this
      * {@code LinkedList}.
-     * 
+     *
      * @return a shallow copy of this {@code LinkedList}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     @Override
@@ -415,12 +408,11 @@
 
     /**
      * Searches this {@code LinkedList} for the specified object.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return {@code true} if {@code object} is an element of this
      *         {@code LinkedList}, {@code false} otherwise
-     * @since Android 1.0
      */
     @Override
     public boolean contains(Object object) {
@@ -463,11 +455,10 @@
 
     /**
      * Returns the first element in this {@code LinkedList}.
-     * 
+     *
      * @return the first element.
      * @throws NoSuchElementException
      *             if this {@code LinkedList} is empty.
-     * @since Android 1.0
      */
     public E getFirst() {
         Link<E> first = voidLink.next;
@@ -479,11 +470,10 @@
 
     /**
      * Returns the last element in this {@code LinkedList}.
-     * 
+     *
      * @return the last element
      * @throws NoSuchElementException
      *             if this {@code LinkedList} is empty
-     * @since Android 1.0
      */
     public E getLast() {
         Link<E> last = voidLink.previous;
@@ -520,12 +510,11 @@
     /**
      * Searches this {@code LinkedList} for the specified object and returns the
      * index of the last occurrence.
-     * 
+     *
      * @param object
      *            the object to search for
      * @return the index of the last occurrence of the object, or -1 if it was
      *         not found.
-     * @since Android 1.0
      */
     @Override
     public int lastIndexOf(Object object) {
@@ -555,14 +544,13 @@
      * Returns a ListIterator on the elements of this {@code LinkedList}. The
      * elements are iterated in the same order that they occur in the
      * {@code LinkedList}. The iteration starts at the specified location.
-     * 
+     *
      * @param location
      *            the index at which to start the iteration
      * @return a ListIterator on the elements of this {@code LinkedList}
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
      * @see ListIterator
-     * @since Android 1.0
      */
     @Override
     public ListIterator<E> listIterator(int location) {
@@ -571,13 +559,12 @@
 
     /**
      * Removes the object at the specified location from this {@code LinkedList}.
-     * 
+     *
      * @param location
      *            the index of the object to remove
      * @return the removed object
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     @Override
     public E remove(int location) {
@@ -629,11 +616,10 @@
 
     /**
      * Removes the first object from this {@code LinkedList}.
-     * 
+     *
      * @return the removed object.
      * @throws NoSuchElementException
      *             if this {@code LinkedList} is empty.
-     * @since Android 1.0
      */
     public E removeFirst() {
         Link<E> first = voidLink.next;
@@ -650,11 +636,10 @@
 
     /**
      * Removes the last object from this {@code LinkedList}.
-     * 
+     *
      * @return the removed object.
      * @throws NoSuchElementException
      *             if this {@code LinkedList} is empty.
-     * @since Android 1.0
      */
     public E removeLast() {
         Link<E> last = voidLink.previous;
@@ -672,7 +657,7 @@
     /**
      * Replaces the element at the specified location in this {@code LinkedList}
      * with the specified object.
-     * 
+     *
      * @param location
      *            the index at which to put the specified object.
      * @param object
@@ -684,7 +669,6 @@
      *             if an object cannot be added to this list.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     @Override
     public E set(int location, E object) {
@@ -708,15 +692,14 @@
 
     /**
      * Returns the number of elements in this {@code LinkedList}.
-     * 
+     *
      * @return the number of elements in this {@code LinkedList}.
-     * @since Android 1.0
      */
     @Override
     public int size() {
         return size;
     }
-    
+
     public boolean offer(E o) {
         add(o);
         return true;
@@ -742,9 +725,8 @@
     /**
      * Returns a new array containing all elements contained in this
      * {@code LinkedList}.
-     * 
+     *
      * @return an array of the elements from this {@code LinkedList}.
-     * @since Android 1.0
      */
     @Override
     public Object[] toArray() {
@@ -765,14 +747,13 @@
      * type is created. If the specified array is used and is larger than this
      * {@code LinkedList}, the array element following the collection elements
      * is set to null.
-     * 
+     *
      * @param contents
      *            the array.
      * @return an array of the elements from this {@code LinkedList}.
      * @throws ArrayStoreException
      *             if the type of an element in this {@code LinkedList} cannot
      *             be stored in the type of the specified array.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -784,7 +765,7 @@
         }
         Link<E> link = voidLink.next;
         while (link != voidLink) {
-            contents[index++] = (T)link.data;
+            contents[index++] = (T) link.data;
             link = link.next;
         }
         if (index < contents.length) {
@@ -810,7 +791,7 @@
         voidLink = new Link<E>(null, null, null);
         Link<E> link = voidLink;
         for (int i = size; --i >= 0;) {
-            Link<E> nextLink = new Link<E>((E)stream.readObject(), link, null);
+            Link<E> nextLink = new Link<E>((E) stream.readObject(), link, null);
             link.next = nextLink;
             link = nextLink;
         }
diff --git a/luni/src/main/java/java/util/List.java b/luni/src/main/java/java/util/List.java
index d95b2d5..68e1ad9 100644
--- a/luni/src/main/java/java/util/List.java
+++ b/luni/src/main/java/java/util/List.java
@@ -23,8 +23,6 @@
  * element in the {@code List} has an index. Each element can thus be accessed by its
  * index, with the first index being zero. Normally, {@code List}s allow duplicate
  * elements, as compared to Sets, where elements have to be unique.
- * 
- * @since Android 1.0
  */
 public interface List<E> extends Collection<E> {
     /**
@@ -39,16 +37,15 @@
      *            the index at which to insert.
      * @param object
      *            the object to add.
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code List} is not supported.
-     * @exception ClassCastException
-     *                when the class of the object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code List} is not supported.
+     * @throws ClassCastException
+     *                if the class of the object is inappropriate for this
      *                {@code List}.
-     * @exception IllegalArgumentException
-     *                when the object cannot be added to this {@code List}.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || location > size()}
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the object cannot be added to this {@code List}.
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || location > size()}
      */
     public void add(int location, E object);
 
@@ -58,14 +55,13 @@
      * @param object
      *            the object to add.
      * @return always true.
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code List} is not supported.
-     * @exception ClassCastException
-     *                when the class of the object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code List} is not supported.
+     * @throws ClassCastException
+     *                if the class of the object is inappropriate for this
      *                {@code List}.
-     * @exception IllegalArgumentException
-     *                when the object cannot be added to this {@code List}.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the object cannot be added to this {@code List}.
      */
     public boolean add(E object);
 
@@ -80,16 +76,15 @@
      *            the collection of objects to be inserted.
      * @return true if this {@code List} has been modified through the insertion, false
      *         otherwise (i.e. if the passed collection was empty).
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code List} is not supported.
-     * @exception ClassCastException
-     *                when the class of an object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code List} is not supported.
+     * @throws ClassCastException
+     *                if the class of an object is inappropriate for this
      *                {@code List}.
-     * @exception IllegalArgumentException
-     *                when an object cannot be added to this {@code List}.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || > size()}
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if an object cannot be added to this {@code List}.
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || > size()}
      */
     public boolean addAll(int location, Collection<? extends E> collection);
 
@@ -102,25 +97,23 @@
      *            the collection of objects.
      * @return {@code true} if this {@code List} is modified, {@code false} otherwise
      *         (i.e. if the passed collection was empty).
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code List} is not supported.
-     * @exception ClassCastException
-     *                when the class of an object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code List} is not supported.
+     * @throws ClassCastException
+     *                if the class of an object is inappropriate for this
      *                {@code List}.
-     * @exception IllegalArgumentException
-     *                when an object cannot be added to this {@code List}.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if an object cannot be added to this {@code List}.
      */
     public boolean addAll(Collection<? extends E> collection);
 
     /**
      * Removes all elements from this {@code List}, leaving it empty.
      * 
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code List} is not supported.
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code List} is not supported.
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public void clear();
 
@@ -131,7 +124,6 @@
      *            the object to search for.
      * @return {@code true} if object is an element of this {@code List}, {@code false}
      *         otherwise
-     * @since Android 1.0
      */
     public boolean contains(Object object);
 
@@ -143,7 +135,6 @@
      *            the collection of objects
      * @return {@code true} if all objects in the specified collection are
      *         elements of this {@code List}, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsAll(Collection<?> collection);
 
@@ -158,7 +149,6 @@
      * @return boolean {@code true} if the object is the same as this object,
      *         and {@code false} if it is different from this object.
      * @see #hashCode
-     * @since Android 1.0
      */
     public boolean equals(Object object);
 
@@ -168,9 +158,8 @@
      * @param location
      *            the index of the element to return.
      * @return the element at the specified location.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || >= size()}
-     * @since Android 1.0
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || >= size()}
      */
     public E get(int location);
 
@@ -179,7 +168,6 @@
      * element' hashcode and its position in the {@code List} into account.
      * 
      * @return the hash code of the {@code List}.
-     * @since Android 1.0
      */
     public int hashCode();
 
@@ -191,7 +179,6 @@
      *            the object to search for.
      * @return the index of the first occurrence of the object or -1 if the
      *         object was not found.
-     * @since Android 1.0
      */
     public int indexOf(Object object);
 
@@ -201,7 +188,6 @@
      * @return {@code true} if this {@code List} has no elements, {@code false}
      *         otherwise.
      * @see #size
-     * @since Android 1.0
      */
     public boolean isEmpty();
 
@@ -211,7 +197,6 @@
      * 
      * @return an iterator on the elements of this {@code List}.
      * @see Iterator
-     * @since Android 1.0
      */
     public Iterator<E> iterator();
 
@@ -223,7 +208,6 @@
      *            the object to search for.
      * @return the index of the last occurrence of the object, or -1 if the
      *         object was not found.
-     * @since Android 1.0
      */
     public int lastIndexOf(Object object);
 
@@ -234,7 +218,6 @@
      * @return a {@code List} iterator on the elements of this {@code List}
      * 
      * @see ListIterator
-     * @since Android 1.0
      */
     public ListIterator<E> listIterator();
 
@@ -246,10 +229,9 @@
      * @param location
      *            the index at which to start the iteration.
      * @return a list iterator on the elements of this {@code List}.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || location > size()}
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || location > size()}
      * @see ListIterator
-     * @since Android 1.0
      */
     public ListIterator<E> listIterator(int location);
 
@@ -259,11 +241,10 @@
      * @param location
      *            the index of the object to remove.
      * @return the removed object.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code List} is not supported.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || >= size()}
-     * @since Android 1.0
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code List} is not supported.
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || >= size()}
      */
     public E remove(int location);
 
@@ -274,9 +255,8 @@
      *            the object to remove.
      * @return true if this {@code List} was modified by this operation, false
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code List} is not supported.
-     * @since Android 1.0
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code List} is not supported.
      */
     public boolean remove(Object object);
 
@@ -287,9 +267,8 @@
      * @param collection
      *            the collection of objects to remove.
      * @return {@code true} if this {@code List} is modified, {@code false} otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code List} is not supported.
-     * @since Android 1.0
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code List} is not supported.
      */
     public boolean removeAll(Collection<?> collection);
 
@@ -300,9 +279,8 @@
      * @param collection
      *            the collection of objects to retain.
      * @return {@code true} if this {@code List} is modified, {@code false} otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code List} is not supported.
-     * @since Android 1.0
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code List} is not supported.
      */
     public boolean retainAll(Collection<?> collection);
 
@@ -315,16 +293,15 @@
      * @param object
      *            the object to insert.
      * @return the previous element at the index.
-     * @exception UnsupportedOperationException
-     *                when replacing elements in this {@code List} is not supported.
-     * @exception ClassCastException
-     *                when the class of an object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if replacing elements in this {@code List} is not supported.
+     * @throws ClassCastException
+     *                if the class of an object is inappropriate for this
      *                {@code List}.
-     * @exception IllegalArgumentException
-     *                when an object cannot be added to this {@code List}.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || >= size()}
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if an object cannot be added to this {@code List}.
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || >= size()}
      */
     public E set(int location, E object);
 
@@ -332,7 +309,6 @@
      * Returns the number of elements in this {@code List}.
      * 
      * @return the number of elements in this {@code List}.
-     * @since Android 1.0
      */
     public int size();
 
@@ -346,10 +322,9 @@
      * @param end
      *            the index one past the end of the sublist.
      * @return a list of a portion of this {@code List}.
-     * @exception IndexOutOfBoundsException
-     *                when {@code start < 0, start > end} or {@code end >
+     * @throws IndexOutOfBoundsException
+     *                if {@code start < 0, start > end} or {@code end >
      *                size()}
-     * @since Android 1.0
      */
     public List<E> subList(int start, int end);
 
@@ -357,7 +332,6 @@
      * Returns an array containing all elements contained in this {@code List}.
      * 
      * @return an array of the elements from this {@code List}.
-     * @since Android 1.0
      */
     public Object[] toArray();
 
@@ -371,10 +345,9 @@
      * @param array
      *            the array.
      * @return an array of the elements from this {@code List}.
-     * @exception ArrayStoreException
-     *                when the type of an element in this {@code List} cannot be stored
+     * @throws ArrayStoreException
+     *                if the type of an element in this {@code List} cannot be stored
      *                in the type of the specified array.
-     * @since Android 1.0
      */
     public <T> T[] toArray(T[] array);
 }
diff --git a/luni/src/main/java/java/util/ListIterator.java b/luni/src/main/java/java/util/ListIterator.java
index 6ce94c3..1c62a22 100644
--- a/luni/src/main/java/java/util/ListIterator.java
+++ b/luni/src/main/java/java/util/ListIterator.java
@@ -21,8 +21,6 @@
 /**
  * An ListIterator is used to sequence over a List of objects. ListIterator can
  * move backwards or forwards through the list.
- * 
- * @since Android 1.0
  */
 public interface ListIterator<E> extends Iterator<E> {
     
@@ -38,7 +36,6 @@
      *             if the class of the object is inappropriate for the list.
      * @throws IllegalArgumentException
      *             if the object cannot be added to the list.
-     * @since Android 1.0
      */
     void add(E object);
 
@@ -47,7 +44,6 @@
      * 
      * @return {@code true} if there are more elements, {@code false} otherwise.
      * @see #next
-     * @since Android 1.0
      */
     public boolean hasNext();
 
@@ -57,7 +53,6 @@
      * @return {@code true} if there are previous elements, {@code false}
      *         otherwise.
      * @see #previous
-     * @since Android 1.0
      */
     public boolean hasPrevious();
 
@@ -68,7 +63,6 @@
      * @throws NoSuchElementException
      *             if there are no more elements.
      * @see #hasNext
-     * @since Android 1.0
      */
     public E next();
 
@@ -80,7 +74,6 @@
      * @throws NoSuchElementException
      *             if there are no more elements.
      * @see #next
-     * @since Android 1.0
      */
     public int nextIndex();
 
@@ -91,7 +84,6 @@
      * @throws NoSuchElementException
      *             if there are no previous elements.
      * @see #hasPrevious
-     * @since Android 1.0
      */
     public E previous();
 
@@ -103,7 +95,6 @@
      * @throws NoSuchElementException
      *             if there are no previous elements.
      * @see #previous
-     * @since Android 1.0
      */
     public int previousIndex();
 
@@ -117,7 +108,6 @@
      *             if {@code next} or {@code previous} have not been called, or
      *             {@code remove} or {@code add} have already been called after
      *             the last call to {@code next} or {@code previous}.
-     * @since Android 1.0
      */
     public void remove();
 
@@ -137,7 +127,6 @@
      *             if {@code next} or {@code previous} have not been called, or
      *             {@code remove} or {@code add} have already been called after
      *             the last call to {@code next} or {@code previous}.
-     * @since Android 1.0
      */
     void set(E object);
 }
diff --git a/luni/src/main/java/java/util/ListResourceBundle.java b/luni/src/main/java/java/util/ListResourceBundle.java
index 20d64ac..6206ee6 100644
--- a/luni/src/main/java/java/util/ListResourceBundle.java
+++ b/luni/src/main/java/java/util/ListResourceBundle.java
@@ -17,22 +17,19 @@
 
 package java.util;
 
-
 /**
  * {@code ListResourceBundle} is the abstract superclass of classes which provide
  * resources by implementing the {@code getContents()} method to return
  * the list of resources.
- * 
+ *
  * @see ResourceBundle
- * @since Android 1.0
+ * @since 1.1
  */
 public abstract class ListResourceBundle extends ResourceBundle {
-    Hashtable<String, Object> table;
+    HashMap<String, Object> table;
 
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public ListResourceBundle() {
         super();
@@ -43,73 +40,81 @@
      * {@code ListResourceBundle}. Each element in the array is an array of two
      * elements, the first is the resource key string and the second is the
      * resource.
-     * 
+     *
      * @return a {@code Object} array containing the resources.
-     * @since Android 1.0
      */
     protected abstract Object[][] getContents();
 
     /**
      * Returns the names of the resources contained in this {@code ListResourceBundle}.
-     * 
+     *
      * @return an {@code Enumeration} of the resource names.
-     * @since Android 1.0
      */
     @Override
     public Enumeration<String> getKeys() {
-        if (table == null) {
-            initializeTable();
-        }
-        if (parent == null) {
-            return table.keys();
-        }
-        return new Enumeration<String>() {
-            Enumeration<String> local = table.keys();
+        initializeTable();
+        if (parent != null) {
+            return new Enumeration<String>() {
+                Iterator<String> local = table.keySet().iterator();
 
-            Enumeration<String> pEnum = parent.getKeys();
+                Enumeration<String> pEnum = parent.getKeys();
 
-            String nextElement;
+                String nextElement;
 
-            private boolean findNext() {
-                if (nextElement != null) {
-                    return true;
-                }
-                while (pEnum.hasMoreElements()) {
-                    String next = pEnum.nextElement();
-                    if (!table.containsKey(next)) {
-                        nextElement = next;
+                private boolean findNext() {
+                    if (nextElement != null) {
                         return true;
                     }
+                    while (pEnum.hasMoreElements()) {
+                        String next = pEnum.nextElement();
+                        if (!table.containsKey(next)) {
+                            nextElement = next;
+                            return true;
+                        }
+                    }
+                    return false;
                 }
-                return false;
-            }
 
-            public boolean hasMoreElements() {
-                if (local.hasMoreElements()) {
-                    return true;
+                public boolean hasMoreElements() {
+                    if (local.hasNext()) {
+                        return true;
+                    }
+                    return findNext();
                 }
-                return findNext();
-            }
 
-            public String nextElement() {
-                if (local.hasMoreElements()) {
-                    return local.nextElement();
+                public String nextElement() {
+                    if (local.hasNext()) {
+                        return local.next();
+                    }
+                    if (findNext()) {
+                        String result = nextElement;
+                        nextElement = null;
+                        return result;
+                    }
+                    // Cause an exception
+                    return pEnum.nextElement();
                 }
-                if (findNext()) {
-                    String result = nextElement;
-                    nextElement = null;
-                    return result;
+            };
+        } else {
+            return new Enumeration<String>() {
+                Iterator<String> it = table.keySet().iterator();
+
+                public boolean hasMoreElements() {
+                    return it.hasNext();
                 }
-                // Cause an exception
-                return pEnum.nextElement();
-            }
-        };
+
+                public String nextElement() {
+                    return it.next();
+                }
+            };
+        }
     }
 
     @Override
     public final Object handleGetObject(String key) {
-        if (table == null) {
-            initializeTable();
+        initializeTable();
+        if (key == null) {
+            throw new NullPointerException();
         }
         return table.get(key);
     }
@@ -117,9 +122,12 @@
     private synchronized void initializeTable() {
         if (table == null) {
             Object[][] contents = getContents();
-            table = new Hashtable<String, Object>(contents.length / 3 * 4 + 3);
-            for (int i = 0; i < contents.length; i++) {
-                table.put((String)contents[i][0], contents[i][1]);
+            table = new HashMap<String, Object>(contents.length / 3 * 4 + 3);
+            for (Object[] content : contents) {
+                if (content[0] == null || content[1] == null) {
+                    throw new NullPointerException();
+                }
+                table.put((String) content[0], content[1]);
             }
         }
     }
diff --git a/luni/src/main/java/java/util/Locale.java b/luni/src/main/java/java/util/Locale.java
index bbf7239..b4558aa 100644
--- a/luni/src/main/java/java/util/Locale.java
+++ b/luni/src/main/java/java/util/Locale.java
@@ -17,7 +17,8 @@
 
 package java.util;
 
-import java.io.File;
+// BEGIN android-changed
+// import java.io.File;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -25,19 +26,14 @@
 import java.io.Serializable;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
+// import java.util.zip.ZipEntry;
+// import java.util.zip.ZipFile;
 
-// BEGIN android-removed
-//import org.apache.harmony.luni.internal.locale.Country;
-//import org.apache.harmony.luni.internal.locale.Language;
-// END android-removed
 import org.apache.harmony.luni.util.PriviAction;
 import org.apache.harmony.luni.util.Util;
 
-//BEGIN android-added
 import com.ibm.icu4jni.util.Resources;
-// END android-added
+// END android-changed
 
 /**
  * {@code Locale} represents a language/country/variant combination. It is an identifier
@@ -45,15 +41,14 @@
  * The language codes are two letter lowercase codes as defined by ISO-639. The
  * country codes are three letter uppercase codes as defined by ISO-3166. The
  * variant codes are unspecified.
- * 
+ *
  * @see ResourceBundle
- * @since Android 1.0
  */
 public final class Locale implements Cloneable, Serializable {
-    
+
     private static final long serialVersionUID = 9149081749638150636L;
 
-    private static Locale[] availableLocales;
+    private static volatile Locale[] availableLocales;
 
     // Initialize a default which is used during static
     // initialization of the default for the platform.
@@ -61,200 +56,159 @@
 
     /**
      * Locale constant for en_CA.
-     * 
-     * @since Android 1.0
      */
     public static final Locale CANADA = new Locale("en", "CA"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for fr_CA.
-     * 
-     * @since Android 1.0
      */
     public static final Locale CANADA_FRENCH = new Locale("fr", "CA"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for zh_CN.
-     * 
-     * @since Android 1.0
      */
     public static final Locale CHINA = new Locale("zh", "CN"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for zh.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale CHINESE = new Locale("zh", "");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale CHINESE = new Locale("zh", ""); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for en.
-     * 
-     * @since Android 1.0
      */
     public static final Locale ENGLISH = new Locale("en", ""); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for fr_FR.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale FRANCE = new Locale("fr", "FR");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale FRANCE = new Locale("fr", "FR"); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for fr.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale FRENCH = new Locale("fr", "");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale FRENCH = new Locale("fr", ""); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for de.
-     * 
-     * @since Android 1.0
      */
     public static final Locale GERMAN = new Locale("de", ""); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for de_DE.
-     * 
-     * @since Android 1.0
      */
     public static final Locale GERMANY = new Locale("de", "DE"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for it.
-     * 
-     * @since Android 1.0
      */
     public static final Locale ITALIAN = new Locale("it", ""); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for it_IT.
-     * 
-     * @since Android 1.0
      */
     public static final Locale ITALY = new Locale("it", "IT"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for ja_JP.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale JAPAN = new Locale("ja", "JP");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale JAPAN = new Locale("ja", "JP"); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for ja.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale JAPANESE = new Locale("ja", "");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale JAPANESE = new Locale("ja", ""); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for ko_KR.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale KOREA = new Locale("ko", "KR");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale KOREA = new Locale("ko", "KR"); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for ko.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale KOREAN = new Locale("ko", "");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale KOREAN = new Locale("ko", ""); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for zh_CN.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale PRC = new Locale("zh", "CN");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale PRC = new Locale("zh", "CN"); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for zh_CN.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale SIMPLIFIED_CHINESE = new Locale("zh", "CN");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale SIMPLIFIED_CHINESE = new Locale("zh", "CN"); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for zh_TW.
-     * 
-     * @since Android 1.0
      */
     public static final Locale TAIWAN = new Locale("zh", "TW"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for zh_TW.
-     * 
-     * @since Android 1.0
      */
     public static final Locale TRADITIONAL_CHINESE = new Locale("zh", "TW"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for en_GB.
-     * 
-     * @since Android 1.0
      */
     public static final Locale UK = new Locale("en", "GB"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for en_US.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale US = new Locale("en", "US");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale US = new Locale("en", "US"); //$NON-NLS-1$//$NON-NLS-2$
 
     private static final PropertyPermission setLocalePermission = new PropertyPermission(
-            "user.language", "write");  //$NON-NLS-1$//$NON-NLS-2$
+            "user.language", "write"); //$NON-NLS-1$//$NON-NLS-2$
 
     static {
         String language = AccessController
                 .doPrivileged(new PriviAction<String>("user.language", "en")); //$NON-NLS-1$ //$NON-NLS-2$
         // BEGIN android-changed
-        String region = AccessController
-                .doPrivileged(new PriviAction<String>("user.region", "US")); //$NON-NLS-1$ //$NON-NLS-2$
+        String region = AccessController.doPrivileged(new PriviAction<String>(
+                "user.region", "US")); //$NON-NLS-1$ //$NON-NLS-2$
         // END android-changed
-        String variant = AccessController
-                .doPrivileged(new PriviAction<String>("user.variant", "")); //$NON-NLS-1$ //$NON-NLS-2$
+        String variant = AccessController.doPrivileged(new PriviAction<String>(
+                "user.variant", "")); //$NON-NLS-1$ //$NON-NLS-2$
         defaultLocale = new Locale(language, region, variant);
     }
-    
+
     private transient String countryCode;
     private transient String languageCode;
     private transient String variantCode;
 
-    /**
-     * Constructs a default which is used during static initialization of the
-     * default for the platform.
-     */
-    private Locale() {
-        languageCode = "en"; //$NON-NLS-1$
-        countryCode = "US"; //$NON-NLS-1$
-        variantCode = ""; //$NON-NLS-1$
-    }
+    // BEGIN android-removed
+    // private transient ULocale uLocale;
+    // END android-removed
+
+	/**
+	 * Constructs a default which is used during static initialization of the
+	 * default for the platform.
+	 */
+	private Locale() {
+		languageCode = "en"; //$NON-NLS-1$
+		countryCode = "US"; //$NON-NLS-1$
+		variantCode = ""; //$NON-NLS-1$
+	}
 
     /**
      * Constructs a new {@code Locale} using the specified language.
-     * 
+     *
      * @param language
      *            the language this {@code Locale} represents.
-     * 
-     * @since Android 1.0
      */
     public Locale(String language) {
-        this(language, "", "");  //$NON-NLS-1$//$NON-NLS-2$
+        this(language, "", ""); //$NON-NLS-1$//$NON-NLS-2$
     }
 
     /**
      * Constructs a new {@code Locale} using the specified language and country codes.
-     * 
+     *
      * @param language
      *            the language this {@code Locale} represents.
      * @param country
      *            the country this {@code Locale} represents.
-     * @since Android 1.0
      */
     public Locale(String language, String country) {
         this(language, country, ""); //$NON-NLS-1$
@@ -263,7 +217,7 @@
     /**
      * Constructs a new {@code Locale} using the specified language, country, and
      * variant codes.
-     * 
+     *
      * @param language
      *            the language this {@code Locale} represents.
      * @param country
@@ -273,13 +227,22 @@
      * @throws NullPointerException
      *             if {@code language}, {@code country}, or
      *             {@code variant} is {@code null}.
-     * @since Android 1.0
      */
     public Locale(String language, String country, String variant) {
         if (language == null || country == null || variant == null) {
             throw new NullPointerException();
         }
+        if(language.length() == 0 && country.length() == 0){
+            languageCode = "";
+            countryCode = "";
+            variantCode = variant;
+            return;
+        }
+        // BEGIN android-changed
+        // this.uLocale = new ULocale(language, country, variant);
+        // languageCode = uLocale.getLanguage();
         languageCode = Util.toASCIILowerCase(language);
+        // END android-changed
         // Map new language codes to the obsolete language
         // codes so the correct resource bundles will be used.
         if (languageCode.equals("he")) {//$NON-NLS-1$
@@ -291,18 +254,21 @@
         }
 
         // countryCode is defined in ASCII character set
+        // BEGIN android-changed
+        // countryCode = country.length()!=0?uLocale.getCountry():"";
         countryCode = Util.toASCIIUpperCase(country);
+        // END android-changed
 
+        // Work around for be compatible with RI
         variantCode = variant;
     }
 
     /**
      * Returns a new {@code Locale} with the same language, country and variant codes as
      * this {@code Locale}.
-     * 
+     *
      * @return a shallow copy of this {@code Locale}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -317,13 +283,12 @@
      * Compares the specified object to this {@code Locale} and returns whether they are
      * equal. The object must be an instance of {@code Locale} and have the same
      * language, country and variant.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the specified object is equal to this {@code Locale},
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -347,13 +312,8 @@
     //     final String classPrefix = prefix.substring(last + 1, length);
     //     Set<String> result = new HashSet<String>();
     //     StringTokenizer paths = new StringTokenizer(System.getProperty(
-    //             // BEGIN android-removed
-    //             // "org.apache.harmony.boot.class.path", ""), System.getProperty( //$NON-NLS-1$ //$NON-NLS-2$
-    //             // END android-removed
-    //             // BEGIN android-added
-    //             "java.boot.class.path", ""), System.getProperty( //$NON-NLS-1$ //$NON-NLS-2$
-    //             // END android-added
-    //             "path.separator", ";"));  //$NON-NLS-1$//$NON-NLS-2$
+    //             "org.apache.harmony.boot.class.path", ""), System.getProperty( //$NON-NLS-1$ //$NON-NLS-2$
+    //             "path.separator", ";")); //$NON-NLS-1$//$NON-NLS-2$
     //     while (paths.hasMoreTokens()) {
     //         String nextToken = paths.nextToken();
     //         File directory = new File(nextToken);
@@ -378,12 +338,13 @@
     //                         String name = list[i];
     //                         if (name.startsWith(classPrefix)
     //                                 && name.endsWith(".class")) { //$NON-NLS-1$
-    //                             result.add(name.substring(0,
+    //                             result
+    //                                     .add(name.substring(0,
     //                                             name.length() - 6));
     //                         }
     //                     }
     //                 }
-    //                 
+    //
     //             } else {
     //                 // Handle ZIP/JAR files.
     //                 try {
@@ -394,25 +355,26 @@
     //                         String name = e.getName();
     //                         if (name.startsWith(prefix)
     //                                 && name.endsWith(".class")) {//$NON-NLS-1$
-    //                             result.add(name.substring(last+1, name.length() - 6));
+    //                             result.add(name.substring(last + 1, name
+    //                                     .length() - 6));
     //                         }
     //                     }
     //                     zip.close();
     //                 } catch (IOException e) {
-    //                    // Empty
+    //                     // Empty
     //                 }
     //             }
     //         }
     //     }
     //     Locale[] locales = new Locale[result.size()];
     //     int i = 0;
-    //     for (String name: result) {
+    //     for (String name : result) {
     //         int index = name.indexOf('_');
     //         int nextIndex = name.indexOf('_', index + 1);
     //         if (nextIndex == -1) {
-    //             locales[i++] = new Locale(name
-    //                     .substring(index + 1, name.length()), ""); //$NON-NLS-1$
-    //         }else{
+    //             locales[i++] = new Locale(name.substring(index + 1, name
+    //                     .length()), ""); //$NON-NLS-1$
+    //         } else {
     //             String language = name.substring(index + 1, nextIndex);
     //             String variant;
     //             if ((index = name.indexOf('_', nextIndex + 1)) == -1) {
@@ -437,7 +399,7 @@
             String s = locales[i];
             int first = s.indexOf('_');
             int second = s.indexOf('_', first + 1);
-            
+
             if (first == -1) {
                 // Language only
                 temp.add(new Locale(s));
@@ -454,37 +416,32 @@
     }
     // END android-added
 
-    /**
+	/**
      * Gets the list of installed {@code Locale}. At least a {@code Locale} that is equal to
      * {@code Locale.US} must be contained in this array.
-     * 
+     *
      * @return an array of {@code Locale}s.
-     * @since Android 1.0
-     */
-    public static Locale[] getAvailableLocales() {
+	 */
+	public static Locale[] getAvailableLocales() {
+        // BEGIN android-changed
+        // ULocale[] ulocales =  ULocale.getAvailableLocales();
+        // Locale[] locales = new Locale[ulocales.length];
+        // for (int i = 0; i < locales.length; i++) {
+        //     locales[i] = ulocales[i].toLocale();
+        // }
+        // return locales;
         if (availableLocales == null) {
-            // BEGIN android-removed
-            // availableLocales = AccessController
-            //         .doPrivileged(new PrivilegedAction<Locale[]>() {
-            //             public Locale[] run() {
-            //                 return find("org/apache/harmony/luni/internal/locale/Locale_"); //$NON-NLS-1$
-            //             }
-            //         });
-            // END android-removed
-            
-            // BEGIN android-added
             availableLocales = find();
-            // END android-added
         }
         return availableLocales.clone();
-    }
+        // END android-changed
+	}
 
     /**
      * Gets the country code for this {@code Locale} or an empty string of no country
      * was set.
-     * 
+     *
      * @return a country code.
-     * @since Android 1.0
      */
     public String getCountry() {
         return countryCode;
@@ -492,9 +449,8 @@
 
     /**
      * Gets the default {@code Locale}.
-     * 
+     *
      * @return the default {@code Locale}.
-     * @since Android 1.0
      */
     public static Locale getDefault() {
         return defaultLocale;
@@ -504,9 +460,8 @@
      * Gets the full country name in the default {@code Locale} for the country code of
      * this {@code Locale}. If there is no matching country name, the country code is
      * returned.
-     * 
+     *
      * @return a country name.
-     * @since Android 1.0
      */
     public final String getDisplayCountry() {
         return getDisplayCountry(getDefault());
@@ -516,22 +471,21 @@
      * Gets the full country name in the specified {@code Locale} for the country code
      * of this {@code Locale}. If there is no matching country name, the country code is
      * returned.
-     * 
+     *
      * @param locale
      *            the {@code Locale} for which the display name is retrieved.
      * @return a country name.
-     * @since Android 1.0
      */
-    public String getDisplayCountry(Locale locale) {
+	public String getDisplayCountry(Locale locale) {
+        // BEGIN android-changed
+		// return ULocale.forLocale(this).getDisplayCountry(ULocale.forLocale(locale));
         if (countryCode.length() == 0) {
             return countryCode;
         }
         try {
             // First try the specified locale
             ResourceBundle bundle = getBundle("Country", locale); //$NON-NLS-1$
-            // BEGIN android-changed
             String result = bundle.getString(this.toString());
-            // END android-changed
             if (result != null) {
                 return result;
             }
@@ -543,15 +497,15 @@
         } catch (MissingResourceException e) {
             return countryCode;
         }
-    }
+        // END android-changed
+	}
 
     /**
      * Gets the full language name in the default {@code Locale} for the language code
      * of this {@code Locale}. If there is no matching language name, the language code
      * is returned.
-     * 
+     *
      * @return a language name.
-     * @since Android 1.0
      */
     public final String getDisplayLanguage() {
         return getDisplayLanguage(getDefault());
@@ -561,22 +515,21 @@
      * Gets the full language name in the specified {@code Locale} for the language code
      * of this {@code Locale}. If there is no matching language name, the language code
      * is returned.
-     * 
+     *
      * @param locale
      *            the {@code Locale} for which the display name is retrieved.
      * @return a language name.
-     * @since Android 1.0
      */
-    public String getDisplayLanguage(Locale locale) {
+	public String getDisplayLanguage(Locale locale) {
+        // BEGIN android-changed
+        // return ULocale.forLocale(this).getDisplayLanguage(ULocale.forLocale(locale));
         if (languageCode.length() == 0) {
             return languageCode;
         }
         try {
             // First try the specified locale
             ResourceBundle bundle = getBundle("Language", locale); //$NON-NLS-1$
-            // BEGIN android-changed
             String result = bundle.getString(this.toString());
-            // END android-changed
             if (result != null) {
                 return result;
             }
@@ -588,14 +541,14 @@
         } catch (MissingResourceException e) {
             return languageCode;
         }
-    }
+        // END android-changed
+	}
 
     /**
      * Gets the full language, country, and variant names in the default {@code Locale}
      * for the codes of this {@code Locale}.
-     * 
+     *
      * @return a {@code Locale} name.
-     * @since Android 1.0
      */
     public final String getDisplayName() {
         return getDisplayName(getDefault());
@@ -604,11 +557,10 @@
     /**
      * Gets the full language, country, and variant names in the specified
      * Locale for the codes of this {@code Locale}.
-     * 
+     *
      * @param locale
      *            the {@code Locale} for which the display name is retrieved.
      * @return a {@code Locale} name.
-     * @since Android 1.0
      */
     public String getDisplayName(Locale locale) {
         int count = 0;
@@ -643,9 +595,8 @@
      * Gets the full variant name in the default {@code Locale} for the variant code of
      * this {@code Locale}. If there is no matching variant name, the variant code is
      * returned.
-     * 
+     *
      * @return a variant name.
-     * @since Android 1.0
      */
     public final String getDisplayVariant() {
         return getDisplayVariant(getDefault());
@@ -655,41 +606,17 @@
      * Gets the full variant name in the specified {@code Locale} for the variant code
      * of this {@code Locale}. If there is no matching variant name, the variant code is
      * returned.
-     * 
+     *
      * @param locale
      *            the {@code Locale} for which the display name is retrieved.
      * @return a variant name.
-     * @since Android 1.0
      */
-    public String getDisplayVariant(Locale locale) {
+	public String getDisplayVariant(Locale locale) {
+        // BEGIN android-changed
+        // return ULocale.forLocale(this).getDisplayVariant(ULocale.forLocale(locale));
         if (variantCode.length() == 0) {
             return variantCode;
         }
-// BEGIN android-removed
-//         ResourceBundle bundle;
-//         try {
-//             bundle = getBundle("Variant", locale); //$NON-NLS-1$
-//         } catch (MissingResourceException e) {
-//             return variantCode.replace('_', ',');
-//         }
-// 
-//         StringBuffer result = new StringBuffer();
-//         StringTokenizer tokens = new StringTokenizer(variantCode, "_"); //$NON-NLS-1$
-//         while (tokens.hasMoreTokens()) {
-//             String code, variant = tokens.nextToken();
-//             try {
-//                 code = bundle.getString(variant);
-//             } catch (MissingResourceException e) {
-//                 code = variant;
-//             }
-//             result.append(code);
-//             if (tokens.hasMoreTokens()) {
-//                 result.append(',');
-//             }
-//         }
-//         return result.toString();
-// END android-removed
-// BEGIN android-added
         try {
             // First try the specified locale
             ResourceBundle bundle = getBundle("Variant", locale); //$NON-NLS-1$
@@ -705,105 +632,78 @@
         } catch (MissingResourceException e) {
             return variantCode;
         }
-// END android-added
-    }
+        // END android-changed
+	}
 
     /**
      * Gets the three letter ISO country code which corresponds to the country
      * code for this {@code Locale}.
-     * 
+     *
      * @return a three letter ISO language code.
-     * @exception MissingResourceException
-     *                when there is no matching three letter ISO country code.
-     * @since Android 1.0
+     * @throws MissingResourceException
+     *                if there is no matching three letter ISO country code.
      */
-    public String getISO3Country() throws MissingResourceException {
+	public String getISO3Country() throws MissingResourceException {
+        // BEGIN android-changed
+        // return ULocale.forLocale(this).getISO3Country();
         if (countryCode.length() == 0) {
             return ""; //$NON-NLS-1$
         }
         ResourceBundle bundle = getBundle("ISO3Countries", this); //$NON-NLS-1$
-        // BEGIN android-changed
         return bundle.getString(this.toString());
         // END android-changed
-    }
+	}
 
     /**
      * Gets the three letter ISO language code which corresponds to the language
      * code for this {@code Locale}.
-     * 
+     *
      * @return a three letter ISO language code.
-     * @exception MissingResourceException
-     *                when there is no matching three letter ISO language code.
-     * @since Android 1.0
+     * @throws MissingResourceException
+     *                if there is no matching three letter ISO language code.
      */
-    public String getISO3Language() throws MissingResourceException {
+	public String getISO3Language() throws MissingResourceException {
+        // BEGIN android-changed
+        // return ULocale.forLocale(this).getISO3Language();
         if (languageCode.length() == 0) {
             return ""; //$NON-NLS-1$
         }
         ResourceBundle bundle = getBundle("ISO3Languages", this); //$NON-NLS-1$
-        // BEGIN android-changed
         return bundle.getString(this.toString());
         // END android-changed
-    }
+	}
 
     /**
      * Gets the list of two letter ISO country codes which can be used as the
      * country code for a {@code Locale}.
-     * 
+     *
      * @return an array of strings.
-     * @since Android 1.0
      */
     public static String[] getISOCountries() {
-        // BEGIN android-removed
-        // ListResourceBundle bundle = new Country();
-        // 
-        // // To initialize the table
-        // Enumeration<String> keys = bundle.getKeys();
-        // int size = bundle.table.size();
-        // String[] result = new String[size];
-        // int index = 0;
-        // while (keys.hasMoreElements()) {
-        //     String element = keys.nextElement();
-        //     result[index++] = element;
-        // }
-        // return result;
-        // END android-removed
-        
-        // BEGIN android-added
+        // BEGIN android-changed
+        // return ULocale.getISOCountries();
         return Resources.getISOCountries();
-        // END android-added
+        // END android-changed
     }
 
     /**
      * Gets the list of two letter ISO language codes which can be used as the
      * language code for a {@code Locale}.
-     * 
+     *
      * @return an array of strings.
-     * @since Android 1.0
      */
-    public static String[] getISOLanguages() {
-        // BEGIN android-removed
-        // ListResourceBundle bundle = new Language();
-        // Enumeration<String> keys = bundle.getKeys(); // to initialize the table
-        // String[] result = new String[bundle.table.size()];
-        // int index = 0;
-        // while (keys.hasMoreElements()) {
-        //     result[index++] = keys.nextElement();
-        // }
-        // return result;
-        // END android-removed
-        
-        // BEGIN android-added
+	public static String[] getISOLanguages() {
+        // BEGIN android-changed
+        // return ULocale.getISOLanguages();
         return Resources.getISOLanguages();
-        // END android-added
-    }
+        // END android-changed
+	}
 
     /**
      * Gets the language code for this {@code Locale} or the empty string of no language
      * was set.
-     * 
+     *
      * @return a language code.
-     * @since Android 1.0
      */
     public String getLanguage() {
         return languageCode;
@@ -812,9 +712,8 @@
     /**
      * Gets the variant code for this {@code Locale} or an empty {@code String} of no variant
      * was set.
-     * 
+     *
      * @return a variant code.
-     * @since Android 1.0
      */
     public String getVariant() {
         return variantCode;
@@ -823,10 +722,9 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public synchronized int hashCode() {
@@ -836,13 +734,12 @@
 
     /**
      * Sets the default {@code Locale} to the specified {@code Locale}.
-     * 
+     *
      * @param locale
      *            the new default {@code Locale}.
-     * @exception SecurityException
+     * @throws SecurityException
      *                if there is a {@code SecurityManager} in place which does not allow this
      *                operation.
-     * @since Android 1.0
      */
     public synchronized static void setDefault(Locale locale) {
         if (locale != null) {
@@ -864,11 +761,10 @@
      * between the language and the variant. the variant alone canot be defined
      * without a language and/or a country (in this case this method would
      * return the empty string).
-     * 
+     *
      * Examples: "en", "en_US", "_US", "en__POSIX", "en_US_POSIX"
-     * 
+     *
      * @return the string representation of this {@code Locale}.
-     * @since Android 1.0
      */
     @Override
     public final String toString() {
@@ -878,7 +774,7 @@
             result.append('_');
             result.append(countryCode);
         }
-        if (variantCode.length() > 0 && result.length() > 0 ) {
+        if (variantCode.length() > 0 && result.length() > 0) {
             if (0 == countryCode.length()) {
                 result.append("__"); //$NON-NLS-1$
             } else {
@@ -889,14 +785,16 @@
         return result.toString();
     }
 
+    // BEGIN android-added
     static ResourceBundle getBundle(final String clName, final Locale locale) {
         return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
-                    public ResourceBundle run() {
-                        return ResourceBundle.getBundle("org.apache.harmony.luni.internal.locale." //$NON-NLS-1$
-                                + clName, locale);
-                    }
-                });
+            public ResourceBundle run() {
+                return ResourceBundle.getBundle("org.apache.harmony.luni.internal.locale." //$NON-NLS-1$
+                        + clName, locale);
+            }
+        });
     }
+    // END android-added
 
     private static final ObjectStreamField[] serialPersistentFields = {
             new ObjectStreamField("country", String.class), //$NON-NLS-1$
@@ -916,9 +814,8 @@
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
         ObjectInputStream.GetField fields = stream.readFields();
-        countryCode = (String) fields.get("country", "");  //$NON-NLS-1$//$NON-NLS-2$
-        languageCode = (String) fields.get("language", "");  //$NON-NLS-1$//$NON-NLS-2$
-        variantCode = (String) fields.get("variant", "");  //$NON-NLS-1$//$NON-NLS-2$
+        countryCode = (String) fields.get("country", ""); //$NON-NLS-1$//$NON-NLS-2$
+        languageCode = (String) fields.get("language", ""); //$NON-NLS-1$//$NON-NLS-2$
+        variantCode = (String) fields.get("variant", ""); //$NON-NLS-1$//$NON-NLS-2$
     }
 }
-
diff --git a/luni/src/main/java/java/util/Map.java b/luni/src/main/java/java/util/Map.java
index d8b1e62..7509d1a 100644
--- a/luni/src/main/java/java/util/Map.java
+++ b/luni/src/main/java/java/util/Map.java
@@ -23,19 +23,15 @@
  * in which each key is mapped to a single value.  The class of the objects
  * used as keys is declared when the {@code Map} is declared, as is the 
  * class of the corresponding values.
- * <p>A {@code Map} provides helper methods to iterate through all of the 
+ * <p>
+ * A {@code Map} provides helper methods to iterate through all of the
  * keys contained in it, as well as various methods to access and update 
  * the key/value pairs.  
- * </p>  
- *  
- * @since Android 1.0
  */
 public interface Map<K,V> {
 
     /**
      * {@code Map.Entry} is a key/value mapping contained in a {@code Map}.
-     *      
-     * @since Android 1.0
      */
     public static interface Entry<K,V> {
         /**
@@ -48,7 +44,6 @@
          * @return {@code true} if the specified {@code Object} is equal to this
          *         {@code Map.Entry}, {@code false} otherwise.
          * @see #hashCode()
-         * @since Android 1.0
          */
         public boolean equals(Object object);
 
@@ -56,7 +51,6 @@
          * Returns the key.
          * 
          * @return the key
-         * @since Android 1.0
          */
         public K getKey();
 
@@ -64,7 +58,6 @@
          * Returns the value.
          * 
          * @return the value
-         * @since Android 1.0
          */
         public V getValue();
 
@@ -74,7 +67,6 @@
          * 
          * @return the receiver's hash code.
          * @see #equals(Object)
-         * @since Android 1.0
          */
         public int hashCode();
 
@@ -85,7 +77,6 @@
          * @param object
          *            the new value to set.
          * @return object the replaced value of this entry.
-         * @since Android 1.0
          */
         public V setValue(V object);
     };
@@ -97,7 +88,6 @@
      *                if removing elements from this {@code Map} is not supported.
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     public void clear();
 
@@ -108,7 +98,6 @@
      *            the key to search for.
      * @return {@code true} if this map contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsKey(Object key);
 
@@ -119,7 +108,6 @@
      *            the value to search for.
      * @return {@code true} if this map contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsValue(Object value);
 
@@ -129,7 +117,6 @@
      * changes in one will be reflected in the other.
      * 
      * @return a set of the mappings
-     * @since Android 1.0
      */
     public Set<Map.Entry<K,V>> entrySet();
 
@@ -143,7 +130,6 @@
      *         {@code false} if it is different from this {@code Object}.
      * @see #hashCode()
      * @see #entrySet()
-     * @since Android 1.0
      */
     public boolean equals(Object object);
 
@@ -154,7 +140,6 @@
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
     public V get(Object key);
 
@@ -164,7 +149,6 @@
      * 
      * @return the receiver's hash.
      * @see #equals(Object)
-     * @since Android 1.0
      */
     public int hashCode();
 
@@ -174,7 +158,6 @@
      * @return {@code true} if this map has no elements, {@code false}
      *         otherwise.
      * @see #size()
-     * @since Android 1.0
      */
     public boolean isEmpty();
 
@@ -184,7 +167,6 @@
      * support adding.
      * 
      * @return a set of the keys.
-     * @since Android 1.0
      */
     public Set<K> keySet();
 
@@ -207,7 +189,6 @@
      * @throws NullPointerException
      *                if the key or value is {@code null} and this {@code Map} does
      *                not support {@code null} keys or values.
-     * @since Android 1.0
      */
     public V put(K key, V value);
 
@@ -226,7 +207,6 @@
      * @throws NullPointerException
      *                if a key or value is {@code null} and this {@code Map} does not
      *                support {@code null} keys or values.
-     * @since Android 1.0
      */
     public void putAll(Map<? extends K,? extends V> map);
 
@@ -239,7 +219,6 @@
      *         for the specified key was found.
      * @throws UnsupportedOperationException
      *                if removing from this {@code Map} is not supported.
-     * @since Android 1.0
      */
     public V remove(Object key);
 
@@ -247,7 +226,6 @@
      * Returns the number of mappings in this {@code Map}.
      * 
      * @return the number of mappings in this {@code Map}.
-     * @since Android 1.0
      */
     public int size();
 
@@ -263,16 +241,13 @@
      * "wrapper object" over the iterator of this {@code Map}'s {@link #entrySet()}. The {@link AbstractCollection#size} method
      * wraps this {@code Map}'s {@link #size} method and the {@link AbstractCollection#contains} method wraps this {@code Map}'s
      * {@link #containsValue} method.
-     * </p>
      * <p>
      * The collection is created when this method is called at first time and
      * returned in response to all subsequent calls. This method may return
      * different Collection when multiple calls to this method, since it has no
      * synchronization performed.
-     * </p>
      * 
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     public Collection<V> values();
 }
diff --git a/luni/src/main/java/java/util/MapEntry.java b/luni/src/main/java/java/util/MapEntry.java
index a63f2fd..6a5bf0f 100644
--- a/luni/src/main/java/java/util/MapEntry.java
+++ b/luni/src/main/java/java/util/MapEntry.java
@@ -17,17 +17,16 @@
 
 package java.util;
 
-
 /**
  * MapEntry is an internal class which provides an implementation of Map.Entry.
  */
-class MapEntry<K,V> implements Map.Entry<K,V>, Cloneable {
-    
+class MapEntry<K, V> implements Map.Entry<K, V>, Cloneable {
+
     K key;
     V value;
 
-    interface Type<RT,KT,VT> {
-        RT get(MapEntry<KT,VT> entry);
+    interface Type<RT, KT, VT> {
+        RT get(MapEntry<KT, VT> entry);
     }
 
     MapEntry(K theKey) {
@@ -82,7 +81,7 @@
         value = object;
         return result;
     }
-    
+
     @Override
     public String toString() {
         return key + "=" + value;
diff --git a/luni/src/main/java/java/util/MissingFormatArgumentException.java b/luni/src/main/java/java/util/MissingFormatArgumentException.java
index bcd240c..dfa0c73 100644
--- a/luni/src/main/java/java/util/MissingFormatArgumentException.java
+++ b/luni/src/main/java/java/util/MissingFormatArgumentException.java
@@ -24,7 +24,6 @@
  * that refers to a missing argument.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class MissingFormatArgumentException extends IllegalFormatException {
     private static final long serialVersionUID = 19190115L;
diff --git a/luni/src/main/java/java/util/MissingFormatWidthException.java b/luni/src/main/java/java/util/MissingFormatWidthException.java
index 19af7d7..8b4e1f8 100644
--- a/luni/src/main/java/java/util/MissingFormatWidthException.java
+++ b/luni/src/main/java/java/util/MissingFormatWidthException.java
@@ -21,7 +21,6 @@
  * missing but is required.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class MissingFormatWidthException extends IllegalFormatException {
     private static final long serialVersionUID = 15560123L;
diff --git a/luni/src/main/java/java/util/MissingResourceException.java b/luni/src/main/java/java/util/MissingResourceException.java
index c3a7efe..9a0cbbb 100644
--- a/luni/src/main/java/java/util/MissingResourceException.java
+++ b/luni/src/main/java/java/util/MissingResourceException.java
@@ -25,7 +25,6 @@
  * 
  * @see ResourceBundle
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class MissingResourceException extends RuntimeException {
 
diff --git a/luni/src/main/java/java/util/Observable.java b/luni/src/main/java/java/util/Observable.java
index a4c0333..5ed4563 100644
--- a/luni/src/main/java/java/util/Observable.java
+++ b/luni/src/main/java/java/util/Observable.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 /**
  * Observable is used to notify a group of Observer objects when a change
  * occurs. On creation, the set of observers is empty. After a change occurred,
@@ -26,21 +25,17 @@
  * Observers. The order of invocation is not specified. This implementation will
  * call the Observers in the order they registered. Subclasses are completely
  * free in what order they call the update methods.
- * 
+ *
  * @see Observer
- * 
- * @since Android 1.0
  */
 public class Observable {
-    
-    Vector<Observer> observers = new Vector<Observer>();
+
+    List<Observer> observers = new ArrayList<Observer>();
 
     boolean changed = false;
 
     /**
      * Constructs a new {@code Observable} object.
-     * 
-     * @since Android 1.0
      */
     public Observable() {
         super();
@@ -49,68 +44,62 @@
     /**
      * Adds the specified observer to the list of observers. If it is already
      * registered, it is not added a second time.
-     * 
+     *
      * @param observer
      *            the Observer to add.
-     * @since Android 1.0
      */
-    public synchronized void addObserver(Observer observer) {
+    public void addObserver(Observer observer) {
         if (observer == null) {
             throw new NullPointerException();
         }
-        if (!observers.contains(observer))
-            observers.addElement(observer);
+        synchronized (this) {
+            if (!observers.contains(observer))
+                observers.add(observer);
+        }
     }
 
     /**
      * Clears the changed flag for this {@code Observable}. After calling
      * {@code clearChanged()}, {@code hasChanged()} will return {@code false}.
-     * 
-     * @since Android 1.0
      */
-    protected synchronized void clearChanged() {
+    protected void clearChanged() {
         changed = false;
     }
 
     /**
      * Returns the number of observers registered to this {@code Observable}.
-     * 
+     *
      * @return the number of observers.
-     * @since Android 1.0
      */
-    public synchronized int countObservers() {
+    public int countObservers() {
         return observers.size();
     }
 
     /**
      * Removes the specified observer from the list of observers. Passing null
      * won't do anything.
-     * 
+     *
      * @param observer
      *            the observer to remove.
-     * @since Android 1.0
      */
     public synchronized void deleteObserver(Observer observer) {
-        observers.removeElement(observer);
+        observers.remove(observer);
     }
 
     /**
      * Removes all observers from the list of observers.
-     * 
-     * @since Android 1.0
      */
     public synchronized void deleteObservers() {
-        observers.setSize(0);
+        observers.clear();
     }
 
     /**
      * Returns the changed flag for this {@code Observable}.
-     * 
+     *
      * @return {@code true} when the changed flag for this {@code Observable} is
      *         set, {@code false} otherwise.
-     * @since Android 1.0
      */
-    public synchronized boolean hasChanged() {
+    public boolean hasChanged() {
         return changed;
     }
 
@@ -120,9 +109,6 @@
      * argument. Afterwards, calls {@code clearChanged()}.
      * <p>
      * Equivalent to calling {@code notifyObservers(null)}.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     public void notifyObservers() {
         notifyObservers(null);
@@ -132,31 +118,34 @@
      * If {@code hasChanged()} returns {@code true}, calls the {@code update()}
      * method for every Observer in the list of observers using the specified
      * argument. Afterwards calls {@code clearChanged()}.
-     * 
+     *
      * @param data
      *            the argument passed to {@code update()}.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public void notifyObservers(Object data) {
-        if (hasChanged()) {
-            // Must clone the vector in case deleteObserver is called
-            Vector<Observer> clone = (Vector<Observer>)observers.clone();
-            int size = clone.size();
-            for (int i = 0; i < size; i++) {
-                clone.elementAt(i).update(this, data);
+        int size = 0;
+        Observer[] arrays = null;
+        synchronized (this) {
+            if (hasChanged()) {
+                clearChanged();
+                size = observers.size();
+                arrays = new Observer[size];
+                observers.toArray(arrays);
             }
-            clearChanged();
+        }
+        if (arrays != null) {
+            for (Observer observer : arrays) {
+                observer.update(this, data);
+            }
         }
     }
 
     /**
      * Sets the changed flag for this {@code Observable}. After calling
      * {@code setChanged()}, {@code hasChanged()} will return {@code true}.
-     * 
-     * @since Android 1.0
      */
-    protected synchronized void setChanged() {
+    protected void setChanged() {
         changed = true;
     }
 }
diff --git a/luni/src/main/java/java/util/Observer.java b/luni/src/main/java/java/util/Observer.java
index 2c8417b..c398e1b 100644
--- a/luni/src/main/java/java/util/Observer.java
+++ b/luni/src/main/java/java/util/Observer.java
@@ -23,7 +23,6 @@
  * receive notification of updates on an {@code Observable} object.
  * 
  * @see Observable 
- * @since Android 1.0
  */
 public interface Observer {
 
@@ -36,7 +35,6 @@
      *            the {@link Observable} object.
      * @param data
      *            the data passed to {@link Observable#notifyObservers(Object)}.
-     * @since Android 1.0
      */
     void update(Observable observable, Object data);
 }
diff --git a/luni/src/main/java/java/util/PriorityQueue.java b/luni/src/main/java/java/util/PriorityQueue.java
index 544c538..c17e7f9 100644
--- a/luni/src/main/java/java/util/PriorityQueue.java
+++ b/luni/src/main/java/java/util/PriorityQueue.java
@@ -31,8 +31,6 @@
  * <p>
  * A PriorityQueue is not synchronized. If multiple threads will have to access
  * it concurrently, use the {@link java.util.concurrent.PriorityBlockingQueue}.
- * 
- * @since Android 1.0
  */
 public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable {
 
@@ -53,8 +51,6 @@
     /**
      * Constructs a priority queue with an initial capacity of 11 and natural
      * ordering.
-     * 
-     * @since Android 1.0
      */
     public PriorityQueue() {
         this(DEFAULT_CAPACITY);
@@ -68,7 +64,6 @@
      *            the specified capacity.
      * @throws IllegalArgumentException
      *             if the initialCapacity is less than 1.
-     * @since Android 1.0
      */
     public PriorityQueue(int initialCapacity) {
         this(initialCapacity, null);
@@ -84,7 +79,6 @@
      *            will be used.
      * @throws IllegalArgumentException
      *             if the initialCapacity is less than 1.
-     * @since Android 1.0
      */
     public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) {
         if (initialCapacity < 1) {
@@ -107,7 +101,6 @@
      *             if any of the elements in the collection are not comparable.
      * @throws NullPointerException
      *             if any of the elements in the collection are null.
-     * @since Android 1.0
      */
     public PriorityQueue(Collection<? extends E> c) {
         if (c instanceof PriorityQueue) {
@@ -129,7 +122,6 @@
      * @param c
      *            the priority queue whose elements will be added to the
      *            priority queue to be constructed.
-     * @since Android 1.0
      */
     public PriorityQueue(PriorityQueue<? extends E> c) {
         getFromPriorityQueue(c);
@@ -144,7 +136,6 @@
      * @param c
      *            the sorted set whose elements will be added to the priority
      *            queue to be constructed.
-     * @since Android 1.0
      */
     public PriorityQueue(SortedSet<? extends E> c) {
         getFromSortedSet(c);
@@ -155,7 +146,6 @@
      * in any specified ordering.
      * 
      * @return the iterator of the priority queue.
-     * @since Android 1.0
      */
     @Override
     public Iterator<E> iterator() {
@@ -167,7 +157,6 @@
      * than the Integer.MAX, then it returns Integer.MAX.
      * 
      * @return the size of the priority queue.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -176,8 +165,6 @@
 
     /**
      * Removes all the elements of the priority queue.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -194,7 +181,8 @@
      * @throws ClassCastException
      *             if the element cannot be compared with the elements in the
      *             priority queue using the ordering of the priority queue.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code o} is {@code null}.
      */
     public boolean offer(E o) {
         if (null == o) {
@@ -210,7 +198,6 @@
      * Gets and removes the head of the queue.
      * 
      * @return the head of the queue or null if the queue is empty.
-     * @since Android 1.0
      */
     public E poll() {
         if (isEmpty()) {
@@ -225,7 +212,6 @@
      * Gets but does not remove the head of the queue.
      * 
      * @return the head of the queue or null if the queue is empty.
-     * @since Android 1.0
      */
     public E peek() {
         if (isEmpty()) {
@@ -239,7 +225,6 @@
      * 
      * @return the comparator of the priority queue or null if the natural
      *         ordering is used.
-     * @since Android 1.0
      */
     public Comparator<? super E> comparator() {
         return comparator;
@@ -252,7 +237,6 @@
      *            the object to be removed.
      * @return true if the object was in the priority queue, false if the object
      *         was not in the priority queue.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -282,7 +266,8 @@
      * @throws ClassCastException
      *             if the element cannot be compared with the elements in the
      *             priority queue using the ordering of the priority queue.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code o} is {@code null}.
      */
     @Override
     public boolean add(E o) {
diff --git a/luni/src/main/java/java/util/Properties.java b/luni/src/main/java/java/util/Properties.java
index 15b74ee..b1fa938 100644
--- a/luni/src/main/java/java/util/Properties.java
+++ b/luni/src/main/java/java/util/Properties.java
@@ -17,9 +17,9 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.BufferedInputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintStream;
@@ -48,45 +48,37 @@
 import org.w3c.dom.Text;
 // END android-added
 
-// BEGIN android-added
-// copied from newer version of Haromny
 import org.apache.harmony.luni.internal.nls.Messages;
-// END android-added
 import org.apache.harmony.luni.util.PriviAction;
 
 /**
- * A {@code Properties} object is a {@code Hashtable} where the keys and values 
- * must be {@code String}s. Each property can have a default 
+ * A {@code Properties} object is a {@code Hashtable} where the keys and values
+ * must be {@code String}s. Each property can have a default
  * {@code Properties} list which specifies the default
  * values to be used when a given key is not found in this {@code Properties}
  * instance.
- * 
+ *
  * @see Hashtable
  * @see java.lang.System#getProperties
- * @since Android 1.0
  */
-public class Properties extends Hashtable<Object,Object> {
-    
+public class Properties extends Hashtable<Object, Object> {
+
     private static final long serialVersionUID = 4112578634029874840L;
 
     private transient DocumentBuilder builder = null;
 
-    private static final String PROP_DTD_NAME 
-            = "http://java.sun.com/dtd/properties.dtd";
+    private static final String PROP_DTD_NAME = "http://java.sun.com/dtd/properties.dtd";
 
-    private static final String PROP_DTD 
-            = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+    private static final String PROP_DTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
             + "    <!ELEMENT properties (comment?, entry*) >"
             + "    <!ATTLIST properties version CDATA #FIXED \"1.0\" >"
             + "    <!ELEMENT comment (#PCDATA) >"
             + "    <!ELEMENT entry (#PCDATA) >"
             + "    <!ATTLIST entry key CDATA #REQUIRED >";
-    
+
     /**
      * The default values for keys not found in this {@code Properties}
      * instance.
-     * 
-     * @since Android 1.0
      */
     protected Properties defaults;
 
@@ -95,8 +87,6 @@
 
     /**
      * Constructs a new {@code Properties} object.
-     * 
-     * @since Android 1.0
      */
     public Properties() {
         super();
@@ -105,10 +95,9 @@
     /**
      * Constructs a new {@code Properties} object using the specified default
      * {@code Properties}.
-     * 
+     *
      * @param properties
      *            the default {@code Properties}.
-     * @since Android 1.0
      */
     public Properties(Properties properties) {
         defaults = properties;
@@ -158,11 +147,10 @@
      * Searches for the property with the specified name. If the property is not
      * found, the default {@code Properties} are checked. If the property is not
      * found in the default {@code Properties}, {@code null} is returned.
-     * 
+     *
      * @param name
      *            the name of the property to find.
      * @return the named property value, or {@code null} if it can't be found.
-     * @since Android 1.0
      */
     public String getProperty(String name) {
         Object result = super.get(name);
@@ -178,13 +166,12 @@
      * found, it looks in the default {@code Properties}. If the property is not
      * found in the default {@code Properties}, it returns the specified
      * default.
-     * 
+     *
      * @param name
      *            the name of the property to find.
      * @param defaultValue
      *            the default value.
      * @return the named property value.
-     * @since Android 1.0
      */
     public String getProperty(String name, String defaultValue) {
         Object result = super.get(name);
@@ -202,11 +189,10 @@
      * Lists the mappings in this {@code Properties} to the specified
      * {@code PrintStream} in a
      * human readable form.
-     * 
+     *
      * @param out
      *            the {@code PrintStream} to write the content to in human readable
      *            form.
-     * @since Android 1.0
      */
     public void list(PrintStream out) {
         if (out == null) {
@@ -239,11 +225,10 @@
      * Lists the mappings in this {@code Properties} to the specified
      * {@code PrintWriter} in a
      * human readable form.
-     * 
+     *
      * @param writer
      *            the {@code PrintWriter} to write the content to in human
      *            readable form.
-     * @since Android 1.0
      */
     public void list(PrintWriter writer) {
         if (writer == null) {
@@ -293,29 +278,40 @@
      * <li>Following escape sequences are recognized: "\ ", "\\", "\r", "\n",
      * "\!", "\#", "\t", "\b", "\f", and "&#92;uXXXX" (unicode character).</li>
      * </ul>
-     * 
+     *
      * @param in
      *            the {@code InputStream}.
      * @throws IOException
      *             if error occurs during reading from the {@code InputStream}.
-     * @since Android 1.0
      */
+    @SuppressWarnings("fallthrough")
     public synchronized void load(InputStream in) throws IOException {
+        if (in == null) {
+            throw new NullPointerException();
+        }
         int mode = NONE, unicode = 0, count = 0;
         char nextChar, buf[] = new char[40];
-        int offset = 0, keyLength = -1;
+        int offset = 0, keyLength = -1, intVal;
         boolean firstChar = true;
-        byte[] inbuf = new byte[256];
-        int inbufCount = 0, inbufPos = 0;
+        BufferedInputStream bis = new BufferedInputStream(in);
 
         while (true) {
-            if (inbufPos == inbufCount) {
-                if ((inbufCount = in.read(inbuf)) == -1) {
-                    break;
+            intVal = bis.read();
+            if (intVal == -1) {
+                // if mode is UNICODE but has less than 4 hex digits, should
+                // throw an IllegalArgumentException
+                // luni.08=Invalid Unicode sequence: expected format \\uxxxx
+                if (mode == UNICODE && count < 4) {
+                    throw new IllegalArgumentException(Messages.getString("luni.08")); //$NON-NLS-1$
                 }
-                inbufPos = 0;
+                // if mode is SLASH and no data is read, should append '\u0000'
+                // to buf
+                if (mode == SLASH) {
+                    buf[offset++] = '\u0000';
+                }
+                break;
             }
-            nextChar = (char) (inbuf[inbufPos++] & 0xff);
+            nextChar = (char) (intVal & 0xff);
 
             if (offset == buf.length) {
                 char[] newBuf = new char[buf.length * 2];
@@ -324,8 +320,6 @@
             }
             if (mode == UNICODE) {
                 int digit = Character.digit(nextChar, 16);
-                // BEGIN android-changed
-                // copied from newer version of Harmony
                 if (digit >= 0) {
                     unicode = (unicode << 4) + digit;
                     if (++count < 4) {
@@ -333,9 +327,8 @@
                     }
                 } else if (count <= 4) {
                     // luni.09=Invalid Unicode sequence: illegal character
-                    throw new IllegalArgumentException(Messages.getString("luni.09"));
+                    throw new IllegalArgumentException(Messages.getString("luni.09")); //$NON-NLS-1$
                 }
-                // END android-changed
                 mode = NONE;
                 buf[offset++] = (char) unicode;
                 if (nextChar != '\n') {
@@ -377,16 +370,12 @@
                 case '!':
                     if (firstChar) {
                         while (true) {
-                            if (inbufPos == inbufCount) {
-                                if ((inbufCount = in.read(inbuf)) == -1) {
-                                    inbufPos = -1;
-                                    break;
-                                }
-                                inbufPos = 0;
+                            intVal = bis.read();
+                            if (intVal == -1) {
+                                break;
                             }
-                            nextChar = (char) inbuf[inbufPos++]; // & 0xff
-                                                                    // not
-                                                                    // required
+                            // & 0xff not required
+                            nextChar = (char) intVal;
                             if (nextChar == '\r' || nextChar == '\n') {
                                 break;
                             }
@@ -399,7 +388,7 @@
                         mode = IGNORE; // Ignore whitespace on the next line
                         continue;
                     }
-                // fall into the next case
+                    // fall into the next case
                 case '\r':
                     mode = NONE;
                     firstChar = true;
@@ -453,13 +442,9 @@
             }
             buf[offset++] = nextChar;
         }
-        // BEGIN android-added
-        // copied from a newer version of Harmony
-        if (mode == UNICODE && count <= 4) {
-            // luni.08=Invalid Unicode sequence: expected format \\uxxxx
-            throw new IllegalArgumentException(Messages.getString("luni.08"));
+        if (keyLength == -1 && offset > 0) {
+            keyLength = offset;
         }
-        // END android-added
         if (keyLength >= 0) {
             String temp = new String(buf, 0, offset);
             put(temp.substring(0, keyLength), temp.substring(keyLength));
@@ -469,17 +454,18 @@
     /**
      * Returns all of the property names that this {@code Properties} object
      * contains.
-     * 
+     *
      * @return an {@code Enumeration} containing the names of all properties
      *         that this {@code Properties} object contains.
-     * @since Android 1.0
      */
     public Enumeration<?> propertyNames() {
         if (defaults == null) {
             return keys();
         }
 
-        Hashtable<Object, Object> set = new Hashtable<Object, Object>(defaults.size() + size());
+        Hashtable<Object, Object> set = new Hashtable<Object, Object>(defaults
+                .size()
+                + size());
         Enumeration<?> keys = defaults.propertyNames();
         while (keys.hasMoreElements()) {
             set.put(keys.nextElement(), set);
@@ -496,15 +482,14 @@
      * OutputStream}, putting the specified comment at the beginning. The output
      * from this method is suitable for being read by the
      * {@link #load(InputStream)} method.
-     * 
+     *
      * @param out the {@code OutputStream} to write to.
      * @param comment the comment to add at the beginning.
-     * @exception ClassCastException when the key or value of a mapping is not a
+     * @throws ClassCastException if the key or value of a mapping is not a
      *                String.
      * @deprecated This method ignores any {@code IOException} thrown while
      *             writing -- use {@link #store} instead for better exception
      *             handling.
-     * @since Android 1.0
      */
     @Deprecated
     public void save(OutputStream out, String comment) {
@@ -517,13 +502,12 @@
     /**
      * Maps the specified key to the specified value. If the key already exists,
      * the old value is replaced. The key and value cannot be {@code null}.
-     * 
+     *
      * @param name
      *            the key.
      * @param value
      *            the value.
      * @return the old value mapped to the key, or {@code null}.
-     * @since Android 1.0
      */
     public Object setProperty(String name, String value) {
         return put(name, value);
@@ -536,14 +520,13 @@
      * OutputStream}, putting the specified comment at the beginning. The output
      * from this method is suitable for being read by the
      * {@link #load(InputStream)} method.
-     * 
+     *
      * @param out the {@code OutputStream} to write to.
      * @param comment the comment to put at the beginning.
      * @throws IOException if an error occurs during the write to the {@code
      *             OutputStream}.
-     * @exception ClassCastException when the key or value of a mapping is not a
+     * @throws ClassCastException if the key or value of a mapping is not a
      *                {@code String}.
-     * @since Android 1.0
      */
     public synchronized void store(OutputStream out, String comment)
             throws IOException {
@@ -557,11 +540,11 @@
         if (comment != null) {
             writer.write("#"); //$NON-NLS-1$
             writer.write(comment);
-            writer.write(lineSeparator); 
+            writer.write(lineSeparator);
         }
         writer.write("#"); //$NON-NLS-1$
         writer.write(new Date().toString());
-        writer.write(lineSeparator); 
+        writer.write(lineSeparator);
 
         for (Map.Entry<Object, Object> entry : entrySet()) {
             String key = (String) entry.getKey();
@@ -579,39 +562,38 @@
      * Loads the properties from an {@code InputStream} containing the
      * properties in XML form. The XML document must begin with (and conform to)
      * following DOCTYPE:
-     * 
+     *
      * <pre>
      * &lt;!DOCTYPE properties SYSTEM &quot;http://java.sun.com/dtd/properties.dtd&quot;&gt;
      * </pre>
-     * 
+     *
      * Also the content of the XML data must satisfy the DTD but the xml is not
      * validated against it. The DTD is not loaded from the SYSTEM ID. After
      * this method returns the InputStream is not closed.
-     * 
+     *
      * @param in the InputStream containing the XML document.
      * @throws IOException in case an error occurs during a read operation.
      * @throws InvalidPropertiesFormatException if the XML data is not a valid
      *             properties file.
-     * @since Android 1.0
      */
-    public synchronized void loadFromXML(InputStream in) 
-            throws IOException, InvalidPropertiesFormatException {
+    public synchronized void loadFromXML(InputStream in) throws IOException,
+            InvalidPropertiesFormatException {
         if (in == null) {
             throw new NullPointerException();
         }
-        
+
         if (builder == null) {
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
             // BEGIN android-removed
             // factory.setValidating(true);
             // END android-removed
-            
+
             try {
                 builder = factory.newDocumentBuilder();
             } catch (ParserConfigurationException e) {
                 throw new Error(e);
             }
-            
+
             builder.setErrorHandler(new ErrorHandler() {
                 public void warning(SAXParseException e) throws SAXException {
                     throw e;
@@ -625,30 +607,30 @@
                     throw e;
                 }
             });
-            
+
             builder.setEntityResolver(new EntityResolver() {
-                public InputSource resolveEntity(String publicId, String systemId)
-                        throws SAXException, IOException {
+                public InputSource resolveEntity(String publicId,
+                        String systemId) throws SAXException, IOException {
                     if (systemId.equals(PROP_DTD_NAME)) {
                         InputSource result = new InputSource(new StringReader(
                                 PROP_DTD));
                         result.setSystemId(PROP_DTD_NAME);
                         return result;
                     }
-                    throw new SAXException(
-                            "Invalid DOCTYPE declaration: " + systemId);
+                    throw new SAXException("Invalid DOCTYPE declaration: "
+                            + systemId);
                 }
             });
         }
-        
+
         try {
             Document doc = builder.parse(in);
-            NodeList entries = doc.getElementsByTagName("entry"); 
+            NodeList entries = doc.getElementsByTagName("entry");
             if (entries == null) {
                 return;
             }
             int entriesListLength = entries.getLength();
-            
+
             for (int i = 0; i < entriesListLength; i++) {
                 Element entry = (Element) entries.item(i);
                 String key = entry.getAttribute("key");
@@ -658,10 +640,10 @@
                 // BEGIN android-added
                 String value = getTextContent(entry);
                 // END android-added
-                
+
                 /*
-                 * key != null & value != null
-                 * but key or(and) value can be empty String
+                 * key != null & value != null but key or(and) value can be
+                 * empty String
                  */
                 put(key, value);
             }
@@ -675,44 +657,41 @@
     /**
      * Writes all properties stored in this instance into the {@code
      * OutputStream} in XML representation. The DOCTYPE is
-     * 
+     *
      * <pre>
      * &lt;!DOCTYPE properties SYSTEM &quot;http://java.sun.com/dtd/properties.dtd&quot;&gt;
      * </pre>
-     * 
+     *
      * If the comment is null, no comment is added to the output. UTF-8 is used
      * as the encoding. The {@code OutputStream} is not closed at the end. A
      * call to this method is the same as a call to {@code storeToXML(os,
      * comment, "UTF-8")}.
-     * 
+     *
      * @param os the {@code OutputStream} to write to.
      * @param comment the comment to add. If null, no comment is added.
      * @throws IOException if an error occurs during writing to the output.
-     * @since Android 1.0
      */
-    public void storeToXML(OutputStream os, String comment) 
-            throws IOException {
-        storeToXML(os, comment, "UTF-8");
+    public void storeToXML(OutputStream os, String comment) throws IOException {
+        storeToXML(os, comment, "UTF-8"); //$NON-NLS-1$
     }
 
     /**
      * Writes all properties stored in this instance into the {@code
      * OutputStream} in XML representation. The DOCTYPE is
-     * 
+     *
      * <pre>
      * &lt;!DOCTYPE properties SYSTEM &quot;http://java.sun.com/dtd/properties.dtd&quot;&gt;
      * </pre>
-     * 
+     *
      * If the comment is null, no comment is added to the output. The parameter
      * {@code encoding} defines which encoding should be used. The {@code
      * OutputStream} is not closed at the end.
-     * 
+     *
      * @param os the {@code OutputStream} to write to.
      * @param comment the comment to add. If null, no comment is added.
      * @param encoding the code identifying the encoding that should be used to
      *            write into the {@code OutputStream}.
      * @throws IOException if an error occurs during writing to the output.
-     * @since Android 1.0
      */
     public synchronized void storeToXML(OutputStream os, String comment,
             String encoding) throws IOException {
@@ -720,14 +699,14 @@
         if (os == null || encoding == null) {
             throw new NullPointerException();
         }
-        
+
         /*
          * We can write to XML file using encoding parameter but note that some
          * aliases for encodings are not supported by the XML parser. Thus we
          * have to know canonical name for encoding used to store data in XML
          * since the XML parser must recognize encoding name used to store data.
          */
-        
+
         String encodingCanonicalName;
         try {
             encodingCanonicalName = Charset.forName(encoding).name();
@@ -741,18 +720,19 @@
             encodingCanonicalName = "UTF-8";
         }
 
-        PrintStream printStream = new PrintStream(os, false, encodingCanonicalName);
-        
+        PrintStream printStream = new PrintStream(os, false,
+                encodingCanonicalName);
+
         printStream.print("<?xml version=\"1.0\" encoding=\"");
         printStream.print(encodingCanonicalName);
         printStream.println("\"?>");
-        
+
         printStream.print("<!DOCTYPE properties SYSTEM \"");
         printStream.print(PROP_DTD_NAME);
         printStream.println("\">");
-        
+
         printStream.println("<properties>");
-        
+
         if (comment != null) {
             printStream.print("<comment>");
             printStream.print(substitutePredefinedEntries(comment));
@@ -771,18 +751,16 @@
         printStream.println("</properties>");
         printStream.flush();
     }
-    
+
     private String substitutePredefinedEntries(String s) {
-        
+
         /*
-         * substitution for predefined character entities
-         * to use them safely in XML
+         * substitution for predefined character entities to use them safely in
+         * XML
          */
-        return s.replaceAll("&", "&amp;")
-            .replaceAll("<", "&lt;")
-            .replaceAll(">", "&gt;")
-            .replaceAll("\u0027", "&apos;")
-            .replaceAll("\"", "&quot;");
+        return s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(
+                ">", "&gt;").replaceAll("\u0027", "&apos;").replaceAll("\"",
+                "&quot;");
     }
 
     // BEGIN android-added
diff --git a/luni/src/main/java/java/util/PropertyPermission.java b/luni/src/main/java/java/util/PropertyPermission.java
index cdbfe34..1cd7143 100644
--- a/luni/src/main/java/java/util/PropertyPermission.java
+++ b/luni/src/main/java/java/util/PropertyPermission.java
@@ -39,8 +39,6 @@
  * <p>
  * There are two possible permission action types: read and write. Possible
  * actions are "read", "write", or "read,write"/"write,read".
- *  
- * @since Android 1.0
  */
 public final class PropertyPermission extends BasicPermission {
     private static final long serialVersionUID = 885438825399942851L;
@@ -56,7 +54,6 @@
      *            the actions which are applicable to it. Possible actions are
      *            "read", "write", or "read,write"/"write,read". Anything else
      *            will result in an {@code IllegalArgumentException}.
-     * @since Android 1.0
      */
     public PropertyPermission(String name, String actions) {
         super(name);
@@ -84,17 +81,16 @@
     /**
      * Compares the argument to the receiver, and returns true if they represent
      * the <em>same</em> object using a class specific comparison. In this
-     * case, the receiver must be a {@code PropertyPermission} for the same 
+     * case, the receiver must be a {@code PropertyPermission} for the same
      * property as the argument, and must have the same actions.
      * If {@code o} is a permission that is not a {@code PropertyPermission},
-     * this method may throw a {@code ClassCastException}.     
-     * 
+     * this method may throw a {@code ClassCastException}.
+     *
      * @param o
      *            the {@code Object} to compare with this {@code Object}.
      * @return {@code true} if the {@code Object} is the same as this {@code Object},
      *         {@code false} if it is different from this {@code Object}.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -110,7 +106,6 @@
      * either "read", "write", or "read,write".
      * 
      * @return the actions associated with the receiver.
-     * @since Android 1.0
      */
     @Override
     public String getActions() {
@@ -124,7 +119,6 @@
      * 
      * @return the receiver's hash.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -138,7 +132,6 @@
      *         receiver, and {@code false} if it is not.
      * @param permission
      *            the permission to check.
-     * @since Android 1.0
      */
     @Override
     public boolean implies(Permission permission) {
@@ -155,7 +148,6 @@
      * 
      * @return a new {@code PermissionCollection} or {@code null}.
      * @see java.security.PermissionCollection
-     * @since Android 1.0
      */
     @Override
     public PermissionCollection newPermissionCollection() {
diff --git a/luni/src/main/java/java/util/PropertyPermissionCollection.java b/luni/src/main/java/java/util/PropertyPermissionCollection.java
index 45e89d9..bf88534 100644
--- a/luni/src/main/java/java/util/PropertyPermissionCollection.java
+++ b/luni/src/main/java/java/util/PropertyPermissionCollection.java
@@ -26,8 +26,6 @@
 
 /**
  * A {@code PermissionCollection} for holding {@code PropertyPermission}s.
- *  
- * @since Android 1.0
  */
 class PropertyPermissionCollection extends PermissionCollection {
 
diff --git a/luni/src/main/java/java/util/PropertyResourceBundle.java b/luni/src/main/java/java/util/PropertyResourceBundle.java
index acc3263..835e892 100644
--- a/luni/src/main/java/java/util/PropertyResourceBundle.java
+++ b/luni/src/main/java/java/util/PropertyResourceBundle.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.InputStream;
 
@@ -28,9 +27,10 @@
  * 
  * @see ResourceBundle
  * @see Properties
- * @since Android 1.0
+ * @since 1.1
  */
 public class PropertyResourceBundle extends ResourceBundle {
+
     Properties resources;
 
     /**
@@ -42,18 +42,23 @@
      * @throws IOException
      *             if an error occurs during a read operation on the
      *             {@code InputStream}.
-     * @since Android 1.0
      */
     public PropertyResourceBundle(InputStream stream) throws IOException {
         resources = new Properties();
         resources.load(stream);
     }
-    
+
     @SuppressWarnings("unchecked")
     private Enumeration<String> getLocalKeys() {
-        return (Enumeration<String>)resources.propertyNames();
+        return (Enumeration<String>) resources.propertyNames();
     }
 
+    /**
+     * Returns the names of the resources contained in this
+     * PropertyResourceBundle.
+     * 
+     * @return an Enumeration of the resource names
+     */
     @Override
     public Enumeration<String> getKeys() {
         if (parent == null) {
@@ -102,6 +107,14 @@
         };
     }
 
+    /**
+     * Returns the named resource from this PropertyResourceBundle, or null if
+     * the resource is not found.
+     * 
+     * @param key
+     *            the name of the resource
+     * @return the resource object
+     */
     @Override
     public Object handleGetObject(String key) {
         return resources.get(key);
diff --git a/luni/src/main/java/java/util/Queue.java b/luni/src/main/java/java/util/Queue.java
index 5035ce7..6ef776a 100644
--- a/luni/src/main/java/java/util/Queue.java
+++ b/luni/src/main/java/java/util/Queue.java
@@ -24,22 +24,17 @@
  * However, a priority queue orders its elements according to a comparator
  * specified or the elements' natural order. Furthermore, a stack orders its
  * elements last-in-first out.
- * </p>
  * <p>
  * A typical queue does not allow {@code null} to be inserted as its element,
  * while some implementations such as {@code LinkedList} allow it. But {@code
  * null} should not be inserted even in these implementations, since the method
  * {@code poll} returns {@code null} to indicate that there is no element left
  * in the queue.
- * </p>
  * <p>
  * {@code Queue} does not provide blocking queue methods, which would block
  * until the operation of the method is allowed. See the
  * {@link java.util.concurrent.BlockingQueue} interface for information about
  * blocking queue methods.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface Queue<E> extends Collection<E> {
 
@@ -53,7 +48,6 @@
      *            the specified element to insert into the queue.
      * @return {@code true} if the operation succeeds and {@code false} if it
      *         fails.
-     * @since Android 1.0
      */
     public boolean offer(E o);
 
@@ -63,7 +57,6 @@
      * 
      * @return the element at the head of the queue or {@code null} if there is
      *         no element in the queue.
-     * @since Android 1.0
      */
     public E poll();
 
@@ -74,7 +67,6 @@
      * @return the element at the head of the queue.
      * @throws NoSuchElementException
      *             if there is no element in the queue.
-     * @since Android 1.0
      */
     public E remove();
 
@@ -83,7 +75,6 @@
      * 
      * @return the element at the head of the queue or {@code null} if there is
      *         no element in the queue.
-     * @since Android 1.0
      */
     public E peek();
 
@@ -94,7 +85,6 @@
      * @return the element at the head of the queue.
      * @throws NoSuchElementException
      *             if there is no element in the queue.
-     * @since Android 1.0
      */
     public E element();
 
diff --git a/luni/src/main/java/java/util/Random.java b/luni/src/main/java/java/util/Random.java
index f92c3ee..be27258 100644
--- a/luni/src/main/java/java/util/Random.java
+++ b/luni/src/main/java/java/util/Random.java
@@ -26,44 +26,40 @@
  * 
  * @see Properties
  * @see PropertyResourceBundle
- * @since Android 1.0
  */
 public class Random implements Serializable {
     
     private static final long serialVersionUID = 3905348978240129619L;
 
-    static final long multiplier = 0x5deece66dL;
+    private static final long multiplier = 0x5deece66dL;
 
     /**
      * The boolean value indicating if the second Gaussian number is available.
      * 
      * @serial
      */
-    boolean haveNextNextGaussian = false;
+    private boolean haveNextNextGaussian;
 
     /**
-     * It is associated with the internal state of this generator.
-     *      
-     * @serial
+     * @serial It is associated with the internal state of this generator.
      */
-    long seed;
+    private long seed;
 
     /**
      * The second Gaussian generated number.
      * 
      * @serial
      */
-    double nextNextGaussian = 0;
+    private double nextNextGaussian;
 
     /**
      * Construct a random generator with the current time of day in milliseconds
      * as the initial state.
      * 
      * @see #setSeed
-     * @since Android 1.0
      */
     public Random() {
-        setSeed(System.currentTimeMillis());
+        setSeed(System.currentTimeMillis() + hashCode());
     }
 
     /**
@@ -74,7 +70,6 @@
      *            the seed that will determine the initial state of this random
      *            number generator.
      * @see #setSeed
-     * @since Android 1.0
      */
     public Random(long seed) {
         setSeed(seed);
@@ -89,7 +84,6 @@
      * @param bits
      *            number of bits of the returned value.
      * @return a pseudo-random generated int number.
-     * @since Android 1.0
      * @see #nextBytes
      * @see #nextDouble
      * @see #nextFloat
@@ -97,7 +91,6 @@
      * @see #nextInt(int)
      * @see #nextGaussian
      * @see #nextLong
-     * @since Android 1.0
      */
     protected synchronized int next(int bits) {
         seed = (seed * multiplier + 0xbL) & ((1L << 48) - 1);
@@ -109,7 +102,6 @@
      * generated by this generator.
      * 
      * @return a pseudo-random, uniformly distributed boolean value.
-     * @since Android 1.0
      */
     public boolean nextBoolean() {
         return next(1) != 0;
@@ -122,7 +114,6 @@
      * @param buf
      *            non-null array to contain the new random {@code byte}s.
      * @see #next
-     * @since Android 1.0
      */
     public void nextBytes(byte[] buf) {
         int rand = 0, count = 0, loop = 0;
@@ -144,7 +135,6 @@
      * 
      * @return a random {@code double} in the range [0.0 - 1.0)
      * @see #nextFloat
-     * @since Android 1.0
      */
     public double nextDouble() {
         return ((((long) next(26) << 27) + next(27)) / (double) (1L << 53));
@@ -156,7 +146,6 @@
      * 
      * @return float a random {@code float} number between [0.0 and 1.0)
      * @see #nextDouble
-     * @since Android 1.0
      */
     public float nextFloat() {
         return (next(24) / 16777216f);
@@ -172,7 +161,6 @@
      * 
      * @return a random {@code double}
      * @see #nextDouble
-     * @since Android 1.0
      */
     public synchronized double nextGaussian() {
         if (haveNextNextGaussian) { // if X1 has been returned, return the
@@ -205,7 +193,6 @@
      * @see java.lang.Integer#MIN_VALUE
      * @see #next
      * @see #nextLong
-     * @since Android 1.0
      */
     public int nextInt() {
         return next(32);
@@ -218,7 +205,6 @@
      * @param n
      *            the exclusive upper border of the range [0 - n).
      * @return a random {@code int}.
-     * @since Android 1.0
      */
     public int nextInt(int n) {
         if (n > 0) {
@@ -245,7 +231,6 @@
      * @see #next
      * @see #nextInt()
      * @see #nextInt(int)
-     * @since Android 1.0
      */
     public long nextLong() {
         return ((long) next(32) << 32) + next(32);
@@ -260,7 +245,6 @@
      * @see #next
      * @see #Random()
      * @see #Random(long)
-     * @since Android 1.0
      */
     public synchronized void setSeed(long seed) {
         this.seed = (seed ^ multiplier) & ((1L << 48) - 1);
diff --git a/luni/src/main/java/java/util/RandomAccess.java b/luni/src/main/java/java/util/RandomAccess.java
index a8a90de..7121bff 100644
--- a/luni/src/main/java/java/util/RandomAccess.java
+++ b/luni/src/main/java/java/util/RandomAccess.java
@@ -17,13 +17,10 @@
 
 package java.util;
 
-
 /**
  * RandomAccess is implemented by {@code List} implementations that support fast
  * (usually constant time) random access.
- * 
- * @since Android 1.0
  */
 public interface RandomAccess {
-    /*empty*/
+    /* empty */
 }
diff --git a/luni/src/main/java/java/util/ResourceBundle.java b/luni/src/main/java/java/util/ResourceBundle.java
index 1187358..218d3f3 100644
--- a/luni/src/main/java/java/util/ResourceBundle.java
+++ b/luni/src/main/java/java/util/ResourceBundle.java
@@ -27,6 +27,7 @@
 import com.ibm.icu4jni.util.Resources;
 import dalvik.system.VMStack;
 // END android-changed
+import org.apache.harmony.luni.util.Msg;
 
 /**
  * {@code ResourceBundle} is an abstract class which is the superclass of classes which
@@ -35,7 +36,7 @@
  * and when a resource is not found in a bundle, the parent bundle is searched for
  * the resource. If the fallback mechanism reaches the base bundle and still
  * can't find the resource it throws a {@code MissingResourceException}.
- * 
+ *
  * <ul>
  * <li>All bundles for the same group of resources share a common base bundle.
  * This base bundle acts as the root and is the last fallback in case none of
@@ -53,7 +54,7 @@
  * current currency (Euro) and the {@code PREEURO} variant bundle would return the old
  * currency (e.g. DM for Germany).</li>
  * </ul>
- * 
+ *
  * <strong>Examples</strong>
  * <ul>
  * <li>BaseName (base bundle)
@@ -67,24 +68,22 @@
  * <li>BaseName_fr_FR_PREEURO (bundle with France specific resources in french of
  * the time before the Euro)
  * </ul>
- * 
+ *
  * It's also possible to create variants for languages or countries. This can be
  * done by just skipping the country or language abbreviation:
  * BaseName_us__POSIX or BaseName__DE_PREEURO. But it's not allowed to
  * circumvent both language and country: BaseName___VARIANT is illegal.
- * 
+ *
  * @see Properties
  * @see PropertyResourceBundle
  * @see ListResourceBundle
- * @since Android 1.0
+ * @since 1.1
  */
 public abstract class ResourceBundle {
 
     /**
      * The parent of this {@code ResourceBundle} that is used if this bundle doesn't
      * include the requested resource.
-     * 
-     * @since Android 1.0
      */
     protected ResourceBundle parent;
 
@@ -114,8 +113,6 @@
 
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public ResourceBundle() {
         /* empty */
@@ -124,13 +121,12 @@
     /**
      * Finds the named resource bundle for the default {@code Locale} and the caller's
      * {@code ClassLoader}.
-     * 
+     *
      * @param bundleName
      *            the name of the {@code ResourceBundle}.
      * @return the requested {@code ResourceBundle}.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the {@code ResourceBundle} cannot be found.
-     * @since Android 1.0
      */
     public static final ResourceBundle getBundle(String bundleName)
             throws MissingResourceException {
@@ -143,15 +139,14 @@
     /**
      * Finds the named {@code ResourceBundle} for the specified {@code Locale} and the caller
      * {@code ClassLoader}.
-     * 
+     *
      * @param bundleName
      *            the name of the {@code ResourceBundle}.
      * @param locale
      *            the {@code Locale}.
      * @return the requested resource bundle.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the resource bundle cannot be found.
-     * @since Android 1.0
      */
     public static final ResourceBundle getBundle(String bundleName,
             Locale locale) {
@@ -163,17 +158,17 @@
 
     /**
      * Finds the named resource bundle for the specified {@code Locale} and {@code ClassLoader}.
-     * 
+     *
      * The passed base name and {@code Locale} are used to create resource bundle names.
      * The first name is created by concatenating the base name with the result
      * of {@link Locale#toString()}. From this name all parent bundle names are
      * derived. Then the same thing is done for the default {@code Locale}. This results
      * in a list of possible bundle names.
-     * 
+     *
      * <strong>Example</strong> For the basename "BaseName", the {@code Locale} of the
      * German part of Switzerland (de_CH) and the default {@code Locale} en_US the list
      * would look something like this:
-     * 
+     *
      * <ol>
      * <li>BaseName_de_CH</li>
      * <li>BaseName_de</li>
@@ -181,11 +176,11 @@
      * <li>Basename_en</li>
      * <li>BaseName</li>
      * </ol>
-     * 
+     *
      * This list also shows the order in which the bundles will be searched for a requested
      * resource in the German part of Switzerland (de_CH).
-     * 
-     * As a first step, this method tries to instantiate 
+     *
+     * As a first step, this method tries to instantiate
      * a {@code ResourceBundle} with the names provided.
      * If such a class can be instantiated and initialized, it is returned and
      * all the parent bundles are instantiated too. If no such class can be
@@ -195,11 +190,11 @@
      * by calling {@link ClassLoader#getResource(String)} it is used to
      * initialize a {@link PropertyResourceBundle}. If this succeeds, it will
      * also load the parents of this {@code ResourceBundle}.
-     * 
+     *
      * For compatibility with older code, the bundle name isn't required to be
      * a fully qualified class name. It's also possible to directly pass
      * the path to a properties file (without a file extension).
-     * 
+     *
      * @param bundleName
      *            the name of the {@code ResourceBundle}.
      * @param locale
@@ -207,9 +202,8 @@
      * @param loader
      *            the {@code ClassLoader} to use.
      * @return the requested {@code ResourceBundle}.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the {@code ResourceBundle} cannot be found.
-     * @since Android 1.0
      */
     public static ResourceBundle getBundle(String bundleName, Locale locale,
             ClassLoader loader) throws MissingResourceException {
@@ -248,7 +242,7 @@
             if ((bundle = handleGetBundle(bundleName, localeName, true, loader)) != null) {
                 return bundle;
             }
-            throw new MissingResourceException(null, bundleName + '_' + locale,
+            throw new MissingResourceException(Msg.getString("KA029", bundleName, locale), bundleName + '_' + locale, //$NON-NLS-1$
                     ""); //$NON-NLS-1$
         }
         throw new NullPointerException();
@@ -256,9 +250,8 @@
 
     /**
      * Returns the names of the resources contained in this {@code ResourceBundle}.
-     * 
+     *
      * @return an {@code Enumeration} of the resource names.
-     * @since Android 1.0
      */
     public abstract Enumeration<String> getKeys();
 
@@ -266,9 +259,8 @@
      * Gets the {@code Locale} of this {@code ResourceBundle}. In case a bundle was not
      * found for the requested {@code Locale}, this will return the actual {@code Locale} of
      * this resource bundle that was found after doing a fallback.
-     * 
+     *
      * @return the {@code Locale} of this {@code ResourceBundle}.
-     * @since Android 1.0
      */
     public Locale getLocale() {
         return locale;
@@ -279,13 +271,12 @@
      * cannot be found in this bundle, it falls back to the parent bundle (if
      * it's not null) by calling the {@link #handleGetObject} method. If the resource still
      * can't be found it throws a {@code MissingResourceException}.
-     * 
+     *
      * @param key
      *            the name of the resource.
      * @return the resource object.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the resource is not found.
-     * @since Android 1.0
      */
     public final Object getObject(String key) {
         ResourceBundle last, theParent = this;
@@ -297,21 +288,20 @@
             last = theParent;
             theParent = theParent.parent;
         } while (theParent != null);
-        throw new MissingResourceException(null, last.getClass().getName(), key);
+        throw new MissingResourceException(Msg.getString("KA029", last.getClass().getName(), key), last.getClass().getName(), key); //$NON-NLS-1$
     }
 
     /**
      * Returns the named string resource from this {@code ResourceBundle}.
-     * 
+     *
      * @param key
      *            the name of the resource.
      * @return the resource string.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the resource is not found.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if the resource found is not a string.
      * @see #getObject(String)
-     * @since Android 1.0
      */
     public final String getString(String key) {
         return (String) getObject(key);
@@ -319,16 +309,15 @@
 
     /**
      * Returns the named resource from this {@code ResourceBundle}.
-     * 
+     *
      * @param key
      *            the name of the resource.
      * @return the resource string array.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the resource is not found.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if the resource found is not an array of strings.
      * @see #getObject(String)
-     * @since Android 1.0
      */
     public final String[] getStringArray(String key) {
         return (String[]) getObject(key);
@@ -343,7 +332,7 @@
         synchronized (cache) {
             loaderCache = cache.get(cacheKey);
             if (loaderCache == null) {
-                loaderCache = new Hashtable<String, ResourceBundle>(13);
+                loaderCache = new Hashtable<String, ResourceBundle>();
                 cache.put(cacheKey, loaderCache);
             }
         }
@@ -389,13 +378,9 @@
         } catch (Exception e) {
         }
 
-        // BEGIN android-added
-        // copied from newer version of Harmony
         if (bundle != null) {
             bundle.setLocale(locale);
-        }
-        // END android-added
-        if (bundle == null) {
+        } else {
             final String fileName = bundleName.replace('.', '/');
             InputStream stream = AccessController
                     .doPrivileged(new PrivilegedAction<InputStream>() {
@@ -447,21 +432,19 @@
     /**
      * Returns the named resource from this {@code ResourceBundle}, or null if the
      * resource is not found.
-     * 
+     *
      * @param key
      *            the name of the resource.
      * @return the resource object.
-     * @since Android 1.0
      */
     protected abstract Object handleGetObject(String key);
 
     /**
      * Sets the parent resource bundle of this {@code ResourceBundle}. The parent is
      * searched for resources which are not found in this {@code ResourceBundle}.
-     * 
+     *
      * @param bundle
      *            the parent {@code ResourceBundle}.
-     * @since Android 1.0
      */
     protected void setParent(ResourceBundle bundle) {
         parent = bundle;
diff --git a/luni/src/main/java/java/util/Scanner.java b/luni/src/main/java/java/util/Scanner.java
index acacebb..dd5c024 100644
--- a/luni/src/main/java/java/util/Scanner.java
+++ b/luni/src/main/java/java/util/Scanner.java
@@ -44,7 +44,7 @@
  * next* methods. If the token is not in a valid format, an
  * {@code InputMismatchException} is thrown.
  * <p>
- * For example: </p>
+ * For example:
  * <pre>
  * Scanner s = new Scanner("1A true");
  * System.out.println(s.nextInt(16));
@@ -52,28 +52,25 @@
  * </pre>
  * <p>
  * Yields the result: {@code 26 true}
- * </p>
  * <p>A {@code Scanner} can also find or skip specific patterns without regard for the
  * delimiter. All these methods and the various next* and hasNext* methods may
  * block.
- * </p>
+ * <p>
  * The {@code Scanner} class is not thread-safe.
- * @since Android 1.0
  */
 public final class Scanner implements Iterator<String> {
 
-    //  Default delimiting pattern.
+    // Default delimiting pattern.
     private static final Pattern DEFAULT_DELIMITER = Pattern
             .compile("\\p{javaWhitespace}+"); //$NON-NLS-1$
-    
+
     // The boolean's pattern.
     private static final Pattern BOOLEAN_PATTERN = Pattern.compile(
             "true|false", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
-    
-    
+
     // Pattern used to recognize line terminator.
     private static final Pattern LINE_TERMINATOR;
-    
+
     // Pattern used to recognize multiple line terminators.
     private static final Pattern MULTI_LINE_TERMINATOR;
 
@@ -81,24 +78,22 @@
     private static final Pattern LINE_PATTERN;
 
     static {
-        String terminator = "\n|\r\n|\r|\u0085|\u2028|\u2029";  //$NON-NLS-1$
-        
+        String terminator = "\n|\r\n|\r|\u0085|\u2028|\u2029"; //$NON-NLS-1$
+
         LINE_TERMINATOR = Pattern.compile(terminator);
-        
+
+        // BEGIN android-note
+        // consider plain old string concatenation for better performance
+        // END android-note
         StringBuilder multiTerminator = new StringBuilder();
-        MULTI_LINE_TERMINATOR = Pattern
-            .compile(multiTerminator.append("(") //$NON-NLS-1$
-                    .append(terminator)
-                    .append(")+").toString()); //$NON-NLS-1$
+        MULTI_LINE_TERMINATOR = Pattern.compile(multiTerminator.append("(") //$NON-NLS-1$
+                .append(terminator).append(")+").toString()); //$NON-NLS-1$
         StringBuilder line = new StringBuilder();
-        LINE_PATTERN = Pattern
-            .compile(line.append(".*(") //$NON-NLS-1$
-                    .append(terminator)
-                    .append(")|.+(") //$NON-NLS-1$
-                    .append(terminator)
-                    .append(")?").toString()); //$NON-NLS-1$
+        LINE_PATTERN = Pattern.compile(line.append(".*(") //$NON-NLS-1$
+                .append(terminator).append(")|.+(") //$NON-NLS-1$
+                .append(terminator).append(")?").toString()); //$NON-NLS-1$
     }
-    
+
     // The pattern matches anything.
     private static final Pattern ANY_PATTERN = Pattern.compile("(?s).*"); //$NON-NLS-1$
 
@@ -131,24 +126,24 @@
     // The length of the buffer.
     private int bufferLength = 0;
 
-    // Record the status of this scanner. True if the scanner 
+    // Record the status of this scanner. True if the scanner
     // is closed.
     private boolean closed = false;
 
     private IOException lastIOException;
-    
+
     private boolean matchSuccessful = false;
-    
+
     private DecimalFormat decimalFormat;
-    
+
     // Records whether the underlying readable has more input.
     private boolean inputExhausted = false;
-    
+
     private Object cacheHasNextValue = null;
-    
+
     private int cachehasNextIndex = -1;
-    
-    private enum DataType{
+
+    private enum DataType {
         /*
          * Stands for Integer
          */
@@ -162,12 +157,11 @@
     /**
      * Creates a {@code Scanner} with the specified {@code File} as input. The default charset
      * is applied when reading the file.
-     * 
+     *
      * @param src
      *            the file to be scanned.
      * @throws FileNotFoundException
      *             if the specified file does not exist.
-     * @since Android 1.0
      */
     public Scanner(File src) throws FileNotFoundException {
         this(src, Charset.defaultCharset().name());
@@ -176,7 +170,7 @@
     /**
      * Creates a {@code Scanner} with the specified {@code File} as input. The specified charset
      * is applied when reading the file.
-     * 
+     *
      * @param src
      *            the file to be scanned.
      * @param charsetName
@@ -185,7 +179,6 @@
      *             if the specified file does not exist.
      * @throws IllegalArgumentException
      *             if the specified coding does not exist.
-     * @since Android 1.0
      */
     public Scanner(File src, String charsetName) throws FileNotFoundException {
         if (null == src) {
@@ -212,10 +205,9 @@
 
     /**
      * Creates a {@code Scanner} on the specified string.
-     * 
+     *
      * @param src
      *            the string to be scanned.
-     * @since Android 1.0
      */
     public Scanner(String src) {
         input = new StringReader(src);
@@ -225,10 +217,9 @@
     /**
      * Creates a {@code Scanner} on the specified {@code InputStream}. The default charset is
      * applied when decoding the input.
-     * 
+     *
      * @param src
      *            the {@code InputStream} to be scanned.
-     * @since Android 1.0
      */
     public Scanner(InputStream src) {
         this(src, Charset.defaultCharset().name());
@@ -237,14 +228,13 @@
     /**
      * Creates a {@code Scanner} on the specified {@code InputStream}. The specified charset is
      * applied when decoding the input.
-     * 
+     *
      * @param src
      *            the {@code InputStream} to be scanned.
      * @param charsetName
      *            the encoding type of the {@code InputStream}.
      * @throws IllegalArgumentException
      *             if the specified character set is not found.
-     * @since Android 1.0
      */
     public Scanner(InputStream src, String charsetName) {
         if (null == src) {
@@ -261,10 +251,9 @@
 
     /**
      * Creates a {@code Scanner} with the specified {@code Readable} as input.
-     * 
+     *
      * @param src
      *            the {@code Readable} to be scanned.
-     * @since Android 1.0
      */
     public Scanner(Readable src) {
         if (null == src) {
@@ -277,10 +266,9 @@
     /**
      * Creates a {@code Scanner} with the specified {@code ReadableByteChannel} as
      * input. The default charset is applied when decoding the input.
-     * 
+     *
      * @param src
      *            the {@code ReadableByteChannel} to be scanned.
-     * @since Android 1.0
      */
     public Scanner(ReadableByteChannel src) {
         this(src, Charset.defaultCharset().name());
@@ -289,14 +277,13 @@
     /**
      * Creates a {@code Scanner} with the specified {@code ReadableByteChannel} as
      * input. The specified charset is applied when decoding the input.
-     * 
+     *
      * @param src
      *            the {@code ReadableByteChannel} to be scanned.
      * @param charsetName
      *            the encoding type of the content.
      * @throws IllegalArgumentException
      *             if the specified character set is not found.
-     * @since Android 1.0
      */
     public Scanner(ReadableByteChannel src, String charsetName) {
         if (null == src) {
@@ -316,9 +303,8 @@
      * {@code Closeable}. If the {@code Scanner} has been closed, this method will have
      * no effect. Any scanning operation called after calling this method will throw
      * an {@code IllegalStateException}.
-     * 
+     *
      * @see Closeable
-     * @since Android 1.0
      */
     public void close() {
         if (closed) {
@@ -336,9 +322,8 @@
 
     /**
      * Returns the delimiter {@code Pattern} in use by this {@code Scanner}.
-     * 
+     *
      * @return the delimiter {@code Pattern} in use by this {@code Scanner}.
-     * @since Android 1.0
      */
     public Pattern delimiter() {
         return delimiter;
@@ -351,14 +336,13 @@
      * Otherwise, {@code null} will be returned and the {@code Scanner} will not advance.
      * When waiting for input, the {@code Scanner} may be blocked. All the
      * input may be cached if no line terminator exists in the buffer.
-     * 
+     *
      * @param pattern
      *            the pattern to find in the input.
      * @return the matched string or {@code null} if the pattern is not found
      *         before the next line terminator.
      * @throws IllegalStateException
      *             if the {@code Scanner} is closed.
-     * @since Android 1.0
      */
     public String findInLine(Pattern pattern) {
         checkClosed();
@@ -395,17 +379,32 @@
          * bug is fixed.
          */
         int oldLimit = buffer.limit();
-        buffer.limit(horizonLineSeparator);
+        // Considering the look ahead feature, the line terminator should be involved as RI
+        buffer.limit(horizonLineSeparator + terminatorLength);
         // ========== To deal with regex bug ====================
 
-        matcher.region(findStartIndex, horizonLineSeparator);
+        // Considering the look ahead feature, the line terminator should be involved as RI
+        matcher.region(findStartIndex, horizonLineSeparator + terminatorLength);
         if (matcher.find()) {
             // The scanner advances past the input that matched
             findStartIndex = matcher.end();
-            // If the matched pattern is immediately followed by line terminator. 
-            if(horizonLineSeparator == matcher.end()) {
+            // If the matched pattern is immediately followed by line
+            // terminator.
+            if (horizonLineSeparator == matcher.end()) {
                 findStartIndex += terminatorLength;
             }
+            // the line terminator itself should not be a part of
+            // the match result according to the Spec
+            if (horizonLineSeparator != bufferLength
+                    && (horizonLineSeparator + terminatorLength == matcher
+                            .end())) {
+                // ========== To deal with regex bug ====================
+                buffer.limit(oldLimit);
+                // ========== To deal with regex bug ====================
+
+                matchSuccessful = false;
+                return null;
+            }
             matchSuccessful = true;
 
             // ========== To deal with regex bug ====================
@@ -427,7 +426,7 @@
      * Compiles the pattern string and tries to find a substing matching it in the input data. The
      * delimiter will be ignored. This is the same as invoking
      * {@code findInLine(Pattern.compile(pattern))}.
-     * 
+     *
      * @param pattern
      *            a string used to construct a pattern which is in turn used to
      *            match a substring of the input data.
@@ -436,7 +435,6 @@
      * @throws IllegalStateException
      *             if the {@code Scanner} is closed.
      * @see #findInLine(Pattern)
-     * @since Android 1.0
      */
     public String findInLine(String pattern) {
         return findInLine(Pattern.compile(pattern));
@@ -450,7 +448,7 @@
      * advance. When waiting for input, the {@code Scanner} may be blocked.
      * <p>
      * The {@code Scanner}'s search will never go more than {@code horizon} code points from current
-     * position. The position of {@code horizon} does have an effect on the result of the 
+     * position. The position of {@code horizon} does have an effect on the result of the
      * match. For example, when the input is "123" and current position is at zero,
      * {@code findWithinHorizon(Pattern.compile("\\p&#123;Digit&#125;&#123;3&#125;"), 2)}
      * will return {@code null}. While
@@ -459,10 +457,10 @@
      * non-anchoring bound. (refer to
      * {@link Matcher#useTransparentBounds(boolean)} and
      * {@link Matcher#useAnchoringBounds(boolean)})
-     * </p>
+     * <p>
      * A {@code horizon} whose value is zero will be ignored and the whole input will be
      * used for search. In this situation, all the input may be cached.
-     * 
+     *
      * @param pattern
      *            the pattern used to scan.
      * @param horizon
@@ -473,7 +471,6 @@
      *             if the {@code Scanner} is closed.
      * @throws IllegalArgumentException
      *             if {@code horizon} is less than zero.
-     * @since Android 1.0
      */
     public String findWithinHorizon(Pattern pattern, int horizon) {
         checkClosed();
@@ -538,7 +535,7 @@
      * Tries to find the pattern in the input between the current position and the specified
      * {@code horizon}. Delimiters are ignored. This call is the same as invoking
      * {@code findWithinHorizon(Pattern.compile(pattern))}.
-     * 
+     *
      * @param pattern
      *            the pattern used to scan.
      * @param horizon
@@ -550,7 +547,6 @@
      * @throws IllegalArgumentException
      *             if {@code horizon} is less than zero.
      * @see #findWithinHorizon(Pattern, int)
-     * @since Android 1.0
      */
     public String findWithinHorizon(String pattern, int horizon) {
         return findWithinHorizon(Pattern.compile(pattern), horizon);
@@ -559,12 +555,11 @@
     /**
      * Returns whether this {@code Scanner} has one or more tokens remaining to parse.
      * This method will block if the data is still being read.
-     * 
+     *
      * @return {@code true} if this {@code Scanner} has one or more tokens remaining,
      *         otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNext() {
         return hasNext(ANY_PATTERN);
@@ -574,28 +569,28 @@
      * Returns whether this {@code Scanner} has one or more tokens remaining to parse
      * and the next token matches the given pattern. This method will block if the data is
      * still being read.
-     * 
+     *
      * @param pattern
      *            the pattern to check for.
      * @return {@code true} if this {@code Scanner} has more tokens and the next token
      *         matches the pattern, {@code false} otherwise.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNext(Pattern pattern) {
         checkClosed();
         checkNull(pattern);
         matchSuccessful = false;
         saveCurrentStatus();
-        //if the next token exists, set the match region, otherwise return false
+        // if the next token exists, set the match region, otherwise return
+        // false
         if (!setTokenRegion()) {
             recoverPreviousStatus();
             return false;
         }
         matcher.usePattern(pattern);
         boolean hasNext = false;
-        //check whether next token matches the specified pattern
+        // check whether next token matches the specified pattern
         if (matcher.matches()) {
             cachehasNextIndex = findStartIndex;
             matchSuccessful = true;
@@ -605,20 +600,18 @@
         return hasNext;
     }
 
-
     /**
      * Returns {@code true} if this {@code Scanner} has one or more tokens remaining to parse
      * and the next token matches a pattern compiled from the given string. This method will
      * block if the data is still being read. This call is equivalent to
      * {@code hasNext(Pattern.compile(pattern))}.
-     * 
+     *
      * @param pattern
      *            the string specifying the pattern to scan for
      * @return {@code true} if the specified pattern matches this {@code Scanner}'s
      *         next token, {@code false} otherwise.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNext(String pattern) {
         return hasNext(Pattern.compile(pattern));
@@ -627,12 +620,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code BigDecimal}.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code BigDecimal}, otherwise {@code false.}
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextBigDecimal() {
         Pattern floatPattern = getFloatPattern();
@@ -653,12 +645,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code BigInteger} in the default radix.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code BigInteger}, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextBigInteger() {
         return hasNextBigInteger(integerRadix);
@@ -667,7 +658,7 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code BigInteger} in the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a
      *            {@code BigInteger}.
@@ -675,7 +666,6 @@
      *         {@code BigInteger}, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextBigInteger(int radix) {
         Pattern integerPattern = getIntegerPattern(radix);
@@ -696,12 +686,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code boolean} value.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code boolean} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextBoolean() {
         return hasNext(BOOLEAN_PATTERN);
@@ -710,12 +699,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code byte} value in the default radix.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code byte} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextByte() {
         return hasNextByte(integerRadix);
@@ -724,7 +712,7 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code byte} value in the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a {@code byte}
      *            value
@@ -732,7 +720,6 @@
      *         {@code byte} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextByte(int radix) {
         Pattern integerPattern = getIntegerPattern(radix);
@@ -753,12 +740,11 @@
     /**
      * Returns whether the next token translated into a valid {@code double}
      * value.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code double} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextDouble() {
         Pattern floatPattern = getFloatPattern();
@@ -779,12 +765,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code float} value.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code float} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextFloat() {
         Pattern floatPattern = getFloatPattern();
@@ -805,12 +790,11 @@
     /**
      * Returns whether the next token can be translated into a valid {@code int}
      * value in the default radix.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code int} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed,
-     * @since Android 1.0
      */
     public boolean hasNextInt() {
         return hasNextInt(integerRadix);
@@ -819,7 +803,7 @@
     /**
      * Returns whether the next token can be translated into a valid {@code int}
      * value in the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into an {@code int}
      *            value.
@@ -828,7 +812,6 @@
      *         {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextInt(int radix) {
         Pattern integerPattern = getIntegerPattern(radix);
@@ -849,12 +832,11 @@
     /**
      * Returns whether there is a line terminator in the input.
      * This method may block.
-     * 
+     *
      * @return {@code true} if there is a line terminator in the input,
      *         otherwise, {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} is closed.
-     * @since Android 1.0
      */
     public boolean hasNextLine() {
         checkClosed();
@@ -886,12 +868,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code long} value in the default radix.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code long} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextLong() {
         return hasNextLong(integerRadix);
@@ -900,7 +881,7 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code long} value in the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a {@code long}
      *            value.
@@ -908,7 +889,6 @@
      *         {@code long} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextLong(int radix) {
         Pattern integerPattern = getIntegerPattern(radix);
@@ -926,16 +906,14 @@
         return isLongValue;
     }
 
-
     /**
      * Returns whether the next token can be translated into a valid
      * {@code short} value in the default radix.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code short} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextShort() {
         return hasNextShort(integerRadix);
@@ -944,7 +922,7 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code short} value in the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a {@code short}
      *            value.
@@ -952,7 +930,6 @@
      *         {@code short} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextShort(int radix) {
         Pattern integerPattern = getIntegerPattern(radix);
@@ -973,9 +950,8 @@
     /**
      * Returns the last {@code IOException} that was raised while reading from the underlying
      * input.
-     * 
+     *
      * @return the last thrown {@code IOException}, or {@code null} if none was thrown.
-     * @since Android 1.0
      */
     public IOException ioException() {
         return lastIOException;
@@ -983,9 +959,8 @@
 
     /**
      * Return the {@code Locale} of this {@code Scanner}.
-     * 
+     *
      * @return the {@code Locale} of this {@code Scanner}.
-     * @since Android 1.0
      */
     public Locale locale() {
         return locale;
@@ -996,13 +971,11 @@
      * <p>
      * The next* and find* methods return the match result in the case of a
      * successful match.
-     * </p>
-     * 
+     *
      * @return the match result of the last successful match operation
      * @throws IllegalStateException
      *             if the match result is not available, of if the last match
      *             was not successful.
-     * @since Android 1.0
      */
     public MatchResult match() {
         if (!matchSuccessful) {
@@ -1015,13 +988,12 @@
      * Returns the next token. The token will be both prefixed and postfixed by
      * the delimiter that is currently being used (or a string that matches the
      * delimiter pattern). This method will block if input is being read.
-     * 
+     *
      * @return the next complete token.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
      * @throws NoSuchElementException
      *             if input has been exhausted.
-     * @since Android 1.0
      */
     public String next() {
         return next(ANY_PATTERN);
@@ -1032,7 +1004,7 @@
      * will be both prefixed and postfixed by the delimiter that is currently
      * being used (or a string that matches the delimiter pattern). This method will block
      * if input is being read.
-     * 
+     *
      * @param pattern
      *            the specified pattern to scan.
      * @return the next token.
@@ -1042,7 +1014,6 @@
      *             if input has been exhausted.
      * @throws InputMismatchException
      *             if the next token does not match the pattern given.
-     * @since Android 1.0
      */
     public String next(Pattern pattern) {
         checkClosed();
@@ -1070,7 +1041,7 @@
      * being used (or a string that matches the delimiter pattern). This method will block
      * if input is being read. Calling this methos is equivalent to
      * {@code next(Pattern.compile(pattern))}.
-     * 
+     *
      * @param pattern
      *            the string specifying the pattern to scan for.
      * @return the next token.
@@ -1080,7 +1051,6 @@
      *             if input has been exhausted.
      * @throws InputMismatchException
      *             if the next token does not match the pattern given.
-     * @since Android 1.0
      */
     public String next(String pattern) {
         return next(Pattern.compile(pattern));
@@ -1095,7 +1065,7 @@
      * negative sign (-) is added if the {@code Locale}-specific negative prefix or
      * suffix was present. Finally the resulting string is passed to
      * {@code BigDecimal(String) }.
-     * 
+     *
      * @return the next token as a {@code BigDecimal}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1104,7 +1074,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code BigDecimal}.
-     * @since Android 1.0
      */
     public BigDecimal nextBigDecimal() {
         checkClosed();
@@ -1131,7 +1100,7 @@
     /**
      * Returns the next token as a {@code BigInteger}. This method will block if input is
      * being read. Equivalent to {@code nextBigInteger(DEFAULT_RADIX)}.
-     * 
+     *
      * @return the next token as {@code BigInteger}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1140,7 +1109,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code BigInteger}.
-     * @since Android 1.0
      */
     public BigInteger nextBigInteger() {
         return nextBigInteger(integerRadix);
@@ -1156,7 +1124,7 @@
      * {@code Locale}-specific negative prefix or suffix was present. Finally the
      * resulting String is passed to {@link BigInteger#BigInteger(String, int)}}
      * with the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a
      *            {@code BigInteger}.
@@ -1168,7 +1136,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code BigInteger}.
-     * @since Android 1.0
      */
     public BigInteger nextBigInteger(int radix) {
         checkClosed();
@@ -1195,7 +1162,7 @@
     /**
      * Returns the next token as a {@code boolean}. This method will block if input is
      * being read.
-     * 
+     *
      * @return the next token as a {@code boolean}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1204,7 +1171,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code boolean} value.
-     * @since Android 1.0
      */
     public boolean nextBoolean() {
         return Boolean.parseBoolean(next(BOOLEAN_PATTERN));
@@ -1213,7 +1179,7 @@
     /**
      * Returns the next token as a {@code byte}. This method will block if input is being
      * read. Equivalent to {@code nextByte(DEFAULT_RADIX)}.
-     * 
+     *
      * @return the next token as a {@code byte}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1222,7 +1188,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code byte} value.
-     * @since Android 1.0
      */
     public byte nextByte() {
         return nextByte(integerRadix);
@@ -1238,7 +1203,7 @@
      * {@code Locale}-specific negative prefix or suffix was present. Finally the
      * resulting String is passed to {@link Byte#parseByte(String, int)}} with
      * the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into {@code byte} value.
      * @return the next token as a {@code byte}.
@@ -1249,7 +1214,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code byte} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public byte nextByte(int radix) {
@@ -1285,7 +1249,7 @@
      * {@link Double#parseDouble(String)}}. If the token matches the localized
      * NaN or infinity strings, it is also passed to
      * {@link Double#parseDouble(String)}}.
-     * 
+     *
      * @return the next token as a {@code double}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1294,7 +1258,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code double} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public double nextDouble() {
@@ -1330,7 +1293,7 @@
      * {@link Float#parseFloat(String)}}.If the token matches the localized NaN
      * or infinity strings, it is also passed to
      * {@link Float#parseFloat(String)}}.
-     * 
+     *
      * @return the next token as a {@code float}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1339,7 +1302,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code float} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public float nextFloat() {
@@ -1367,7 +1329,7 @@
     /**
      * Returns the next token as an {@code int}. This method will block if input is being
      * read. Equivalent to {@code nextInt(DEFAULT_RADIX)}.
-     * 
+     *
      * @return the next token as an {@code int}
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1376,7 +1338,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code int} value.
-     * @since Android 1.0
      */
     public int nextInt() {
         return nextInt(integerRadix);
@@ -1392,7 +1353,7 @@
      * {@code Locale}-specific negative prefix or suffix was present. Finally the
      * resulting String is passed to {@link Integer#parseInt(String, int)} with
      * the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into an {@code int}
      *            value.
@@ -1404,7 +1365,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code int} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public int nextInt(int radix) {
@@ -1416,7 +1376,7 @@
             return (Integer) obj;
         }
         Pattern integerPattern = getIntegerPattern(radix);
-        String intString=next(integerPattern);
+        String intString = next(integerPattern);
         intString = removeLocaleInfo(intString, DataType.INT);
         int intValue = 0;
         try {
@@ -1435,13 +1395,12 @@
      * searching, if no line terminator is found, then a large amount of input
      * will be cached. If no line at all can be found, a {@code NoSuchElementException}
      * will be thrown.
-     * 
+     *
      * @return the skipped line.
      * @throws IllegalStateException
      *             if the {@code Scanner} is closed.
      * @throws NoSuchElementException
      *             if no line can be found, e.g. when input is an empty string.
-     * @since Android 1.0
      */
     public String nextLine() {
         checkClosed();
@@ -1451,7 +1410,8 @@
         String result = null;
         while (true) {
             if (matcher.find()) {
-                if (inputExhausted || matcher.end() != bufferLength) {
+                if (inputExhausted || matcher.end() != bufferLength
+                        || bufferLength < buffer.capacity()) {
                     matchSuccessful = true;
                     findStartIndex = matcher.end();
                     result = matcher.group();
@@ -1466,7 +1426,7 @@
             if (!inputExhausted) {
                 readMore();
                 resetMatcher();
-            } 
+            }
         }
         // Find text without line terminator here.
         if (null != result) {
@@ -1481,7 +1441,7 @@
     /**
      * Returns the next token as a {@code long}. This method will block if input is being
      * read. Equivalent to {@code nextLong(DEFAULT_RADIX)}.
-     * 
+     *
      * @return the next token as a {@code long}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1490,7 +1450,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code long} value.
-     * @since Android 1.0
      */
     public long nextLong() {
         return nextLong(integerRadix);
@@ -1506,7 +1465,7 @@
      * {@code Locale}-specific negative prefix or suffix was present. Finally the
      * resulting String is passed to {@link Long#parseLong(String, int)}} with
      * the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a {@code long}
      *            value.
@@ -1518,7 +1477,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code long} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public long nextLong(int radix) {
@@ -1546,7 +1504,7 @@
     /**
      * Returns the next token as a {@code short}. This method will block if input is being
      * read. Equivalent to {@code nextShort(DEFAULT_RADIX)}.
-     * 
+     *
      * @return the next token as a {@code short}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1555,7 +1513,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code short} value.
-     * @since Android 1.0
      */
     public short nextShort() {
         return nextShort(integerRadix);
@@ -1571,7 +1528,7 @@
      * {@code Locale}-specific negative prefix or suffix was present. Finally the
      * resulting String is passed to {@link Short#parseShort(String, int)}}
      * with the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into {@code short}
      *            value.
@@ -1583,7 +1540,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code short} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public short nextShort(int radix) {
@@ -1610,9 +1566,8 @@
 
     /**
      * Return the radix of this {@code Scanner}.
-     * 
+     *
      * @return the radix of this {@code Scanner}
-     * @since Android 1.0
      */
     public int radix() {
         return integerRadix;
@@ -1624,8 +1579,8 @@
      * skipped. If an anchored match of the specified pattern succeeds, the corresponding input
      * will also be skipped. Otherwise, a {@code NoSuchElementException} will be thrown.
      * Patterns that can match a lot of input may cause the {@code Scanner} to read
-     * in a large amount of input. 
-     * 
+     * in a large amount of input.
+     *
      * @param pattern
      *            used to skip over input.
      * @return the {@code Scanner} itself.
@@ -1633,7 +1588,6 @@
      *             if the {@code Scanner} is closed.
      * @throws NoSuchElementException
      *             if the specified pattern match fails.
-     * @since Android 1.0
      */
     public Scanner skip(Pattern pattern) {
         checkClosed();
@@ -1668,14 +1622,13 @@
      * the constructed pattern to match input starting from the current position. The
      * delimiter will be ignored. This call is the same as invoke
      * {@code skip(Pattern.compile(pattern))}.
-     * 
+     *
      * @param pattern
      *            the string used to construct a pattern which in turn is used to
      *            match input.
      * @return the {@code Scanner} itself.
      * @throws IllegalStateException
      *             if the {@code Scanner} is closed.
-     * @since Android 1.0
      */
     public Scanner skip(String pattern) {
         return skip(Pattern.compile(pattern));
@@ -1684,9 +1637,8 @@
     /**
      * Returns a string representation of this {@code Scanner}. The information
      * returned may be helpful for debugging. The format of the string is unspecified.
-     * 
+     *
      * @return a string represendation of this {@code Scanner}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -1702,11 +1654,10 @@
 
     /**
      * Sets the delimiting pattern of this {@code Scanner}.
-     * 
+     *
      * @param pattern
      *            the delimiting pattern to use.
      * @return this {@code Scanner}.
-     * @since Android 1.0
      */
     public Scanner useDelimiter(Pattern pattern) {
         delimiter = pattern;
@@ -1716,11 +1667,10 @@
     /**
      * Sets the delimiting pattern of this {@code Scanner} with a pattern compiled from
      * the supplied string value.
-     * 
+     *
      * @param pattern
      *            a string from which a {@code Pattern} can be compiled.
      * @return this {@code Scanner}.
-     * @since Android 1.0
      */
     public Scanner useDelimiter(String pattern) {
         return useDelimiter(Pattern.compile(pattern));
@@ -1728,11 +1678,10 @@
 
     /**
      * Sets the {@code Locale} of this {@code Scanner} to a specified {@code Locale}.
-     * 
+     *
      * @param l
      *            the specified {@code Locale} to use.
      * @return this {@code Scanner}.
-     * @since Android 1.0
      */
     public Scanner useLocale(Locale l) {
         if (null == l) {
@@ -1744,11 +1693,10 @@
 
     /**
      * Sets the radix of this {@code Scanner} to the specified radix.
-     * 
+     *
      * @param radix
      *            the specified radix to use.
      * @return this {@code Scanner}.
-     * @since Android 1.0
      */
     public Scanner useRadix(int radix) {
         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
@@ -1761,10 +1709,9 @@
 
     /**
      * Remove is not a supported operation on {@code Scanner}.
-     * 
+     *
      * @throws UnsupportedOperationException
      *             if this method is invoked.
-     * @since Android 1.0
      */
     public void remove() {
         throw new UnsupportedOperationException();
@@ -1778,7 +1725,7 @@
         buffer.limit(0);
         matcher = delimiter.matcher(buffer);
     }
-    
+
     /*
      * Check the {@code Scanner}'s state, if it is closed, IllegalStateException will be
      * thrown.
@@ -1788,7 +1735,7 @@
             throw new IllegalStateException();
         }
     }
-    
+
     /*
      * Check the inputed pattern. If it is null, then a NullPointerException
      * will be thrown out.
@@ -1824,7 +1771,7 @@
     private void recoverPreviousStatus() {
         findStartIndex = preStartIndex;
     }
-    
+
     /*
      * Get integer's pattern
      */
@@ -1834,12 +1781,12 @@
                     .getString("KA00e", radix)); //$NON-NLS-1$
         }
         decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
-        
-        String allAvailableDigits="0123456789abcdefghijklmnopqrstuvwxyz"; //$NON-NLS-1$ 
-        String ASCIIDigit=allAvailableDigits.substring(0, radix);
-        String nonZeroASCIIDigit=allAvailableDigits.substring(1, radix);
 
-        StringBuilder digit = new StringBuilder("((?i)[").append(ASCIIDigit) //$NON-NLS-1$ 
+        String allAvailableDigits = "0123456789abcdefghijklmnopqrstuvwxyz"; //$NON-NLS-1$
+        String ASCIIDigit = allAvailableDigits.substring(0, radix);
+        String nonZeroASCIIDigit = allAvailableDigits.substring(1, radix);
+
+        StringBuilder digit = new StringBuilder("((?i)[").append(ASCIIDigit) //$NON-NLS-1$
                 .append("]|\\p{javaDigit})"); //$NON-NLS-1$
         StringBuilder nonZeroDigit = new StringBuilder("((?i)[").append( //$NON-NLS-1$
                 nonZeroASCIIDigit).append("]|([\\p{javaDigit}&&[^0]]))"); //$NON-NLS-1$
@@ -1912,16 +1859,16 @@
     }
 
     /*
-     * Add the {@code Locale}-specific positive prefixes and suffixes to the pattern
+     * Add the locale specific positive prefixes and suffixes to the pattern
      */
     private StringBuilder addPositiveSign(StringBuilder unSignNumeral) {
         String positivePrefix = ""; //$NON-NLS-1$
         String positiveSuffix = ""; //$NON-NLS-1$
         if (!decimalFormat.getPositivePrefix().equals("")) { //$NON-NLS-1$
-            positivePrefix = "\\Q" + decimalFormat.getPositivePrefix()+"\\E"; //$NON-NLS-1$ //$NON-NLS-2$
+            positivePrefix = "\\Q" + decimalFormat.getPositivePrefix() + "\\E"; //$NON-NLS-1$ //$NON-NLS-2$
         }
         if (!decimalFormat.getPositiveSuffix().equals("")) { //$NON-NLS-1$
-            positiveSuffix = "\\Q" + decimalFormat.getPositiveSuffix()+"\\E"; //$NON-NLS-1$ //$NON-NLS-2$
+            positiveSuffix = "\\Q" + decimalFormat.getPositiveSuffix() + "\\E"; //$NON-NLS-1$ //$NON-NLS-2$
         }
         StringBuilder signedNumeral = new StringBuilder()
                 .append(positivePrefix).append(unSignNumeral).append(
@@ -1930,16 +1877,16 @@
     }
 
     /*
-     * Add the {@code Locale} specific negative prefixes and suffixes to the pattern
+     * Add the locale specific negative prefixes and suffixes to the pattern
      */
     private StringBuilder addNegativeSign(StringBuilder unSignNumeral) {
         String negativePrefix = ""; //$NON-NLS-1$
         String negativeSuffix = ""; //$NON-NLS-1$
         if (!decimalFormat.getNegativePrefix().equals("")) { //$NON-NLS-1$
-            negativePrefix = "\\Q" + decimalFormat.getNegativePrefix()+"\\E"; //$NON-NLS-1$//$NON-NLS-2$
+            negativePrefix = "\\Q" + decimalFormat.getNegativePrefix() + "\\E"; //$NON-NLS-1$//$NON-NLS-2$
         }
         if (!decimalFormat.getNegativeSuffix().equals("")) { //$NON-NLS-1$
-            negativeSuffix = "\\Q" + decimalFormat.getNegativeSuffix()+"\\E"; //$NON-NLS-1$//$NON-NLS-2$
+            negativeSuffix = "\\Q" + decimalFormat.getNegativeSuffix() + "\\E"; //$NON-NLS-1$//$NON-NLS-2$
         }
         StringBuilder signedNumeral = new StringBuilder()
                 .append(negativePrefix).append(unSignNumeral).append(
@@ -1948,15 +1895,14 @@
     }
 
     /*
-     * Remove {@code Locale} related information from float String
+     * Remove locale related information from float String
      */
     private String removeLocaleInfoFromFloat(String floatString) {
         // If the token is HexFloat
-        if (-1 != floatString.indexOf('x')
-                || -1 != floatString.indexOf('X')) {
+        if (-1 != floatString.indexOf('x') || -1 != floatString.indexOf('X')) {
             return floatString;
         }
-        
+
         int exponentIndex;
         String decimalNumeralString;
         String exponentString;
@@ -1968,11 +1914,11 @@
                     floatString.length());
             decimalNumeralString = removeLocaleInfo(decimalNumeralString,
                     DataType.FLOAT);
-            return decimalNumeralString + "e" + exponentString; //$NON-NLS-1$ 
+            return decimalNumeralString + "e" + exponentString; //$NON-NLS-1$
         }
         return removeLocaleInfo(floatString, DataType.FLOAT);
     }
-    
+
     /*
      * Remove the locale specific prefixes, group separators, and locale
      * specific suffixes from input string
@@ -2001,12 +1947,12 @@
             }
         }
         if (DataType.FLOAT == type) {
-            if (tokenBuilder.toString().equals(decimalFormat.getDecimalFormatSymbols()
-                    .getNaN())) {
-                result.append("NaN");//$NON-NLS-1$ 
-            } else if (tokenBuilder.toString().equals(decimalFormat
-                    .getDecimalFormatSymbols().getInfinity())) {
-                result.append("Infinity");//$NON-NLS-1$ 
+            if (tokenBuilder.toString().equals(
+                    decimalFormat.getDecimalFormatSymbols().getNaN())) {
+                result.append("NaN");//$NON-NLS-1$
+            } else if (tokenBuilder.toString().equals(
+                    decimalFormat.getDecimalFormatSymbols().getInfinity())) {
+                result.append("Infinity");//$NON-NLS-1$
             } else {
                 for (int i = 0; i < tokenBuilder.length(); i++) {
                     if (-1 != Character.digit(tokenBuilder.charAt(i), 10)) {
@@ -2029,8 +1975,9 @@
         }
         return result.toString();
     }
+
     /*
-     * remove positive and negative sign from the parameter stringBuilder, and
+     * Remove positive and negative sign from the parameter stringBuilder, and
      * return whether the input string is negative
      */
     private boolean removeLocaleSign(StringBuilder tokenBuilder) {
@@ -2106,7 +2053,7 @@
     }
 
     /*
-     * Find prefixed delimiter
+     * Find prefix delimiter
      */
     private int findPreDelimiter() {
         int tokenStartIndex;
@@ -2166,7 +2113,7 @@
     }
 
     /*
-     * Find postfixed delimiter
+     * Find postfix delimiter
      */
     private int findPostDelimiter() {
         int tokenEndIndex = 0;
@@ -2215,7 +2162,8 @@
             }
         } catch (IOException e) {
             // Consider the scenario: readable puts 4 chars into
-            // buffer and then an IOException is thrown out. In this case, buffer is
+            // buffer and then an IOException is thrown out. In this case,
+            // buffer is
             // actually grown, but readable.read() will never return.
             bufferLength = buffer.position();
             /*
@@ -2226,7 +2174,6 @@
             lastIOException = e;
         }
 
-
         buffer.flip();
         buffer.position(oldPosition);
         if (-1 == readCount) {
diff --git a/luni/src/main/java/java/util/Set.java b/luni/src/main/java/java/util/Set.java
index f52666d..109c8df 100644
--- a/luni/src/main/java/java/util/Set.java
+++ b/luni/src/main/java/java/util/Set.java
@@ -20,8 +20,8 @@
 
 /**
  * A {@code Set} is a data structure which does not allow duplicate elements.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public interface Set<E> extends Collection<E> {
     
@@ -38,7 +38,6 @@
      *             when the class of the object is inappropriate for this set.
      * @throws IllegalArgumentException
      *             when the object cannot be added to this set.
-     * @since Android 1.0
      */
     public boolean add(E object);
 
@@ -55,7 +54,6 @@
      *             when the class of an object is inappropriate for this set.
      * @throws IllegalArgumentException
      *             when an object cannot be added to this set.
-     * @since Android 1.0
      */
     public boolean addAll(Collection<? extends E> collection);
 
@@ -66,7 +64,6 @@
      *             when removing from this set is not supported.
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public void clear();
 
@@ -77,7 +74,6 @@
      *            the object to search for.
      * @return {@code true} if object is an element of this set, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean contains(Object object);
 
@@ -88,7 +84,6 @@
      *            the collection of objects.
      * @return {@code true} if all objects in the specified collection are
      *         elements of this set, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsAll(Collection<?> collection);
 
@@ -103,7 +98,6 @@
      * @return boolean {@code true} if the object is the same as this object,
      *         and {@code false} if it is different from this object.
      * @see #hashCode
-     * @since Android 1.0
      */
     public boolean equals(Object object);
 
@@ -114,7 +108,6 @@
      * @return the hash code of this set.
      * 
      * @see #equals
-     * @since Android 1.0
      */
     public int hashCode();
 
@@ -124,7 +117,6 @@
      * @return {@code true} if this set has no elements, {@code false}
      *         otherwise.
      * @see #size
-     * @since Android 1.0
      */
     public boolean isEmpty();
 
@@ -134,7 +126,6 @@
      * 
      * @return an iterator on the elements of this set.
      * @see Iterator
-     * @since Android 1.0
      */
     public Iterator<E> iterator();
 
@@ -146,7 +137,6 @@
      * @return {@code true} if this set was modified, {@code false} otherwise.
      * @throws UnsupportedOperationException
      *             when removing from this set is not supported.
-     * @since Android 1.0
      */
     public boolean remove(Object object);
 
@@ -158,7 +148,6 @@
      * @return {@code true} if this set was modified, {@code false} otherwise.
      * @throws UnsupportedOperationException
      *             when removing from this set is not supported.
-     * @since Android 1.0
      */
     public boolean removeAll(Collection<?> collection);
 
@@ -171,7 +160,6 @@
      * @return {@code true} if this set was modified, {@code false} otherwise.
      * @throws UnsupportedOperationException
      *             when removing from this set is not supported.
-     * @since Android 1.0
      */
     public boolean retainAll(Collection<?> collection);
 
@@ -179,7 +167,6 @@
      * Returns the number of elements in this set.
      * 
      * @return the number of elements in this set.
-     * @since Android 1.0
      */
     public int size();
 
@@ -187,7 +174,6 @@
      * Returns an array containing all elements contained in this set.
      * 
      * @return an array of the elements from this set.
-     * @since Android 1.0
      */
     public Object[] toArray();
 
@@ -205,7 +191,6 @@
      *             when the type of an element in this set cannot be stored in
      *             the type of the specified array.
      * @see Collection#toArray(Object[])
-     * @since Android 1.0
      */
     public <T> T[] toArray(T[] array);
 }
diff --git a/luni/src/main/java/java/util/SimpleTimeZone.java b/luni/src/main/java/java/util/SimpleTimeZone.java
index 18d076f..702b6ef 100644
--- a/luni/src/main/java/java/util/SimpleTimeZone.java
+++ b/luni/src/main/java/java/util/SimpleTimeZone.java
@@ -14,12 +14,12 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2008, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
+
+// BEGIN android-note
+// This implementation is based on an old version of Apache Harmony. The current
+// Harmony uses ICU4J, which makes it much simpler. We should consider updating
+// this implementation to leverage ICU4JNI.
+// END android-note
 
 package java.util;
 
@@ -27,33 +27,41 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamField;
+// BEGIN android-removed
+// import java.security.AccessController;
+// import java.security.PrivilegedAction;
+// END android-removed
 
 import org.apache.harmony.luni.util.Msg;
 
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 /**
  * {@code SimpleTimeZone} is a concrete subclass of {@code TimeZone}
  * that represents a time zone for use with a Gregorian calendar. This class
  * does not handle historical changes.
- * <P>
+ * <p>
  * Use a negative value for {@code dayOfWeekInMonth} to indicate that
  * {@code SimpleTimeZone} should count from the end of the month
  * backwards. For example, Daylight Savings Time ends at the last
  * (dayOfWeekInMonth = -1) Sunday in October, at 2 AM in standard time.
- * 
+ *
  * @see Calendar
  * @see GregorianCalendar
  * @see TimeZone
- * @since Android 1.0
  */
 public class SimpleTimeZone extends TimeZone {
-    
+
     private static final long serialVersionUID = -403250971215465050L;
 
+    // BEGIN android-removed
+    // private static com.ibm.icu.util.TimeZone getICUTimeZone(final String name){
+    //     return AccessController.doPrivileged(new PrivilegedAction<com.ibm.icu.util.TimeZone>(){
+    //         public com.ibm.icu.util.TimeZone run() {
+    //             return com.ibm.icu.util.TimeZone.getTimeZone(name);
+    //         }
+    //     });
+    // }
+    // END android-removed
+
     private int rawOffset;
 
     private int startYear, startMonth, startDay, startDayOfWeek, startTime;
@@ -67,8 +75,6 @@
 
     /**
      * The constant for representing a start or end time in GMT time mode.
-     * 
-     * @since Android 1.0
      */
     public static final int UTC_TIME = 2;
 
@@ -76,8 +82,6 @@
      * The constant for representing a start or end time in standard local time mode,
      * based on timezone's raw offset from GMT; does not include Daylight
      * savings.
-     * 
-     * @since Android 1.0
      */
     public static final int STANDARD_TIME = 1;
 
@@ -85,8 +89,6 @@
      * The constant for representing a start or end time in local wall clock time
      * mode, based on timezone's adjusted offset from GMT; includes
      * Daylight savings.
-     * 
-     * @since Android 1.0
      */
     public static final int WALL_TIME = 0;
 
@@ -96,22 +98,37 @@
 
     private int dstSavings = 3600000;
 
+    // BEGIN android-removed
+    // private final transient com.ibm.icu.util.TimeZone icuTZ;
+    //
+    // private final transient boolean isSimple;
+    // END android-removed
+
     /**
      * Constructs a {@code SimpleTimeZone} with the given base time zone offset from GMT
      * and time zone ID. Timezone IDs can be obtained from
      * {@code TimeZone.getAvailableIDs}. Normally you should use {@code TimeZone.getDefault} to
      * construct a {@code TimeZone}.
-     * 
+     *
      * @param offset
      *            the given base time zone offset to GMT.
      * @param name
      *            the time zone ID which is obtained from
      *            {@code TimeZone.getAvailableIDs}.
-     * @since Android 1.0
      */
-    public SimpleTimeZone(int offset, String name) {
+    public SimpleTimeZone(int offset, final String name) {
         setID(name);
         rawOffset = offset;
+        // BEGIN android-removed
+        // icuTZ = getICUTimeZone(name);
+        // if (icuTZ instanceof com.ibm.icu.util.SimpleTimeZone) {
+        //     isSimple = true;
+        //     icuTZ.setRawOffset(offset);
+        // } else {
+        //     isSimple = false;
+        // }
+        // useDaylight = icuTZ.useDaylightTime();
+        // END android-removed
     }
 
     /**
@@ -146,8 +163,8 @@
      * The above examples refer to the {@code startMonth}, {@code startDay}, and {@code startDayOfWeek};
      * the same applies for the {@code endMonth}, {@code endDay}, and {@code endDayOfWeek}.
      * <p>
-     * The daylight savings time difference is set to the default value: one hour.          
-     * 
+     * The daylight savings time difference is set to the default value: one hour.
+     *
      * @param offset
      *            the given base time zone offset to GMT.
      * @param name
@@ -182,7 +199,6 @@
      * @throws IllegalArgumentException
      *             if the month, day, dayOfWeek, or time parameters are out of
      *             range for the start or end rule.
-     * @since Android 1.0
      */
     public SimpleTimeZone(int offset, String name, int startMonth,
             int startDay, int startDayOfWeek, int startTime, int endMonth,
@@ -193,9 +209,9 @@
 
     /**
      * Constructs a {@code SimpleTimeZone} with the given base time zone offset from GMT,
-     * time zone ID, times to start and end the daylight savings time, and 
-     * the daylight savings time difference in milliseconds
-     * 
+     * time zone ID, times to start and end the daylight savings time, and
+     * the daylight savings time difference in milliseconds.
+     *
      * @param offset
      *            the given base time zone offset to GMT.
      * @param name
@@ -212,7 +228,7 @@
      *            description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param startTime
      *            The daylight savings starting time in local wall time, which
-     *            is standard time in this case. Please see the description of 
+     *            is standard time in this case. Please see the description of
      *            {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param endMonth
      *            the daylight savings ending month. Month is 0-based. eg, 0 for
@@ -221,7 +237,7 @@
      *            the daylight savings ending day-of-week-in-month. Please see
      *            the description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param endDayOfWeek
-     *            the daylight savings ending day-of-week. Please see the description of 
+     *            the daylight savings ending day-of-week. Please see the description of
      *            {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param endTime
      *            the daylight savings ending time in local wall time, which is
@@ -229,31 +245,50 @@
      *            for an example.
      * @param daylightSavings
      *            the daylight savings time difference in milliseconds.
-     * @exception IllegalArgumentException
-     *                the month, day, dayOfWeek, or time parameters are out of
+     * @throws IllegalArgumentException
+     *                if the month, day, dayOfWeek, or time parameters are out of
      *                range for the start or end rule.
-     * @since Android 1.0
      */
     public SimpleTimeZone(int offset, String name, int startMonth,
             int startDay, int startDayOfWeek, int startTime, int endMonth,
             int endDay, int endDayOfWeek, int endTime, int daylightSavings) {
+        // BEGIN android-changed
+        // icuTZ = getICUTimeZone(name);
+        // if (icuTZ instanceof com.ibm.icu.util.SimpleTimeZone) {
+        //     isSimple = true;
+        //     com.ibm.icu.util.SimpleTimeZone tz = (com.ibm.icu.util.SimpleTimeZone)icuTZ;
+        //     tz.setRawOffset(offset);
+        //     tz.setStartRule(startMonth, startDay, startDayOfWeek, startTime);
+        //     tz.setEndRule(endMonth, endDay, endDayOfWeek, endTime);
+        //     tz.setDSTSavings(daylightSavings);
+        // } else {
+        //     isSimple = false;
+        // }
+        // setID(name);
+        // rawOffset = offset;
         this(offset, name);
+        // END android-changed
         if (daylightSavings <= 0) {
-            throw new IllegalArgumentException(Msg.getString("K00e9", daylightSavings)); //$NON-NLS-1$
+            throw new IllegalArgumentException(Msg.getString(
+                    "K00e9", daylightSavings)); //$NON-NLS-1$
         }
         dstSavings = daylightSavings;
 
         setStartRule(startMonth, startDay, startDayOfWeek, startTime);
         setEndRule(endMonth, endDay, endDayOfWeek, endTime);
+
+        // BEGIN android-removed
+        // useDaylight = daylightSavings > 0 || icuTZ.useDaylightTime();
+        // END android-removed
     }
 
     /**
      * Construct a {@code SimpleTimeZone} with the given base time zone offset from GMT,
-     * time zone ID, times to start and end the daylight savings time including a 
+     * time zone ID, times to start and end the daylight savings time including a
      * mode specifier, the daylight savings time difference in milliseconds.
      * The mode specifies either {@link #WALL_TIME}, {@link #STANDARD_TIME}, or
      * {@link #UTC_TIME}.
-     * 
+     *
      * @param offset
      *            the given base time zone offset to GMT.
      * @param name
@@ -269,21 +304,21 @@
      *            the daylight savings starting day-of-week. Please see the
      *            description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param startTime
-     *            the time of day in milliseconds on which daylight savings 
+     *            the time of day in milliseconds on which daylight savings
      *            time starts, based on the {@code startTimeMode}.
      * @param startTimeMode
      *            the mode (UTC, standard, or wall time) of the start time
      *            value.
-     * @param endDay 
-     *            the day of the week on which daylight savings time ends. 
+     * @param endDay
+     *            the day of the week on which daylight savings time ends.
      * @param endMonth
      *            the daylight savings ending month. The month indexing is 0-based. eg, 0 for
      *            January.
      * @param endDayOfWeek
-     *            the daylight savings ending day-of-week. Please see the description of 
+     *            the daylight savings ending day-of-week. Please see the description of
      *            {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param endTime
-     *            the time of day in milliseconds on which daylight savings 
+     *            the time of day in milliseconds on which daylight savings
      *            time ends, based on the {@code endTimeMode}.
      * @param endTimeMode
      *            the mode (UTC, standard, or wall time) of the end time value.
@@ -292,7 +327,6 @@
      * @throws IllegalArgumentException
      *             if the month, day, dayOfWeek, or time parameters are out of
      *             range for the start or end rule.
-     * @since Android 1.0
      */
     public SimpleTimeZone(int offset, String name, int startMonth,
             int startDay, int startDayOfWeek, int startTime, int startTimeMode,
@@ -308,10 +342,9 @@
     /**
      * Returns a new {@code SimpleTimeZone} with the same ID, {@code rawOffset} and daylight
      * savings time rules as this SimpleTimeZone.
-     * 
+     *
      * @return a shallow copy of this {@code SimpleTimeZone}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -326,13 +359,12 @@
      * Compares the specified object to this {@code SimpleTimeZone} and returns whether they
      * are equal. The object must be an instance of {@code SimpleTimeZone} and have the
      * same internal data.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the specified object is equal to this
      *         {@code SimpleTimeZone}, {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -372,6 +404,8 @@
             checkDay(month, day);
         }
 
+        // BEGIN android-changed
+        // return icuTZ.getOffset(era, year, month, day, dayOfWeek, time);
         if (!useDaylightTime() || era != GregorianCalendar.AD
                 || year < startYear) {
             return rawOffset;
@@ -389,38 +423,39 @@
         int ruleDay = 0, daysInMonth, firstDayOfMonth = mod7(dayOfWeek - day);
         if (month == startMonth) {
             switch (startMode) {
-            case DOM_MODE:
-                ruleDay = startDay;
-                break;
-            case DOW_IN_MONTH_MODE:
-                if (startDay >= 0) {
-                    ruleDay = mod7(startDayOfWeek - firstDayOfMonth) + 1
-                            + (startDay - 1) * 7;
-                } else {
-                    daysInMonth = GregorianCalendar.DaysInMonth[startMonth];
-                    if (startMonth == Calendar.FEBRUARY && isLeapYear(year)) {
-                        daysInMonth += 1;
+                case DOM_MODE:
+                    ruleDay = startDay;
+                    break;
+                case DOW_IN_MONTH_MODE:
+                    if (startDay >= 0) {
+                        ruleDay = mod7(startDayOfWeek - firstDayOfMonth) + 1
+                                + (startDay - 1) * 7;
+                    } else {
+                        daysInMonth = GregorianCalendar.DaysInMonth[startMonth];
+                        if (startMonth == Calendar.FEBRUARY && isLeapYear(
+                                year)) {
+                            daysInMonth += 1;
+                        }
+                        ruleDay = daysInMonth
+                                + 1
+                                + mod7(startDayOfWeek
+                                - (firstDayOfMonth + daysInMonth))
+                                + startDay * 7;
                     }
-                    ruleDay = daysInMonth
-                            + 1
+                    break;
+                case DOW_GE_DOM_MODE:
+                    ruleDay = startDay
                             + mod7(startDayOfWeek
-                                    - (firstDayOfMonth + daysInMonth))
-                            + startDay * 7;
-                }
-                break;
-            case DOW_GE_DOM_MODE:
-                ruleDay = startDay
-                        + mod7(startDayOfWeek
-                                - (firstDayOfMonth + startDay - 1));
-                break;
-            case DOW_LE_DOM_MODE:
-                ruleDay = startDay
-                        + mod7(startDayOfWeek
-                                - (firstDayOfMonth + startDay - 1));
-                if (ruleDay != startDay) {
-                    ruleDay -= 7;
-                }
-                break;
+                            - (firstDayOfMonth + startDay - 1));
+                    break;
+                case DOW_LE_DOM_MODE:
+                    ruleDay = startDay
+                            + mod7(startDayOfWeek
+                            - (firstDayOfMonth + startDay - 1));
+                    if (ruleDay != startDay) {
+                        ruleDay -= 7;
+                    }
+                    break;
             }
             if (ruleDay > day || ruleDay == day && time < startTime) {
                 return rawOffset;
@@ -431,36 +466,38 @@
         int nextMonth = (month + 1) % 12;
         if (month == endMonth || (ruleTime < 0 && nextMonth == endMonth)) {
             switch (endMode) {
-            case DOM_MODE:
-                ruleDay = endDay;
-                break;
-            case DOW_IN_MONTH_MODE:
-                if (endDay >= 0) {
-                    ruleDay = mod7(endDayOfWeek - firstDayOfMonth) + 1
-                            + (endDay - 1) * 7;
-                } else {
-                    daysInMonth = GregorianCalendar.DaysInMonth[endMonth];
-                    if (endMonth == Calendar.FEBRUARY && isLeapYear(year)) {
-                        daysInMonth++;
+                case DOM_MODE:
+                    ruleDay = endDay;
+                    break;
+                case DOW_IN_MONTH_MODE:
+                    if (endDay >= 0) {
+                        ruleDay = mod7(endDayOfWeek - firstDayOfMonth) + 1
+                                + (endDay - 1) * 7;
+                    } else {
+                        daysInMonth = GregorianCalendar.DaysInMonth[endMonth];
+                        if (endMonth == Calendar.FEBRUARY && isLeapYear(year)) {
+                            daysInMonth++;
+                        }
+                        ruleDay = daysInMonth
+                                + 1
+                                + mod7(endDayOfWeek
+                                - (firstDayOfMonth + daysInMonth)) + endDay
+                                * 7;
                     }
-                    ruleDay = daysInMonth
-                            + 1
-                            + mod7(endDayOfWeek
-                                    - (firstDayOfMonth + daysInMonth)) + endDay
-                            * 7;
-                }
-                break;
-            case DOW_GE_DOM_MODE:
-                ruleDay = endDay
-                        + mod7(endDayOfWeek - (firstDayOfMonth + endDay - 1));
-                break;
-            case DOW_LE_DOM_MODE:
-                ruleDay = endDay
-                        + mod7(endDayOfWeek - (firstDayOfMonth + endDay - 1));
-                if (ruleDay != endDay) {
-                    ruleDay -= 7;
-                }
-                break;
+                    break;
+                case DOW_GE_DOM_MODE:
+                    ruleDay = endDay
+                            + mod7(
+                            endDayOfWeek - (firstDayOfMonth + endDay - 1));
+                    break;
+                case DOW_LE_DOM_MODE:
+                    ruleDay = endDay
+                            + mod7(
+                            endDayOfWeek - (firstDayOfMonth + endDay - 1));
+                    if (ruleDay != endDay) {
+                        ruleDay -= 7;
+                    }
+                    break;
             }
 
             int ruleMonth = endMonth;
@@ -488,10 +525,13 @@
             }
         }
         return rawOffset + dstSavings;
+        // END android-changed
     }
 
     @Override
     public int getOffset(long time) {
+        // BEGIN android-changed
+        // return icuTZ.getOffset(time);
         if (!useDaylightTime()) {
             return rawOffset;
         }
@@ -499,6 +539,7 @@
             daylightSavings = new GregorianCalendar(this);
         }
         return daylightSavings.getOffset(time + rawOffset);
+        // END android-changed
     }
 
     @Override
@@ -509,10 +550,9 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public synchronized int hashCode() {
@@ -548,6 +588,8 @@
 
     @Override
     public boolean inDaylightTime(Date time) {
+        // BEGIN android-changed
+        // return icuTZ.inDaylightTime(time);
         // check for null pointer
         long millis = time.getTime();
         if (!useDaylightTime()) {
@@ -557,6 +599,7 @@
             daylightSavings = new GregorianCalendar(this);
         }
         return daylightSavings.getOffset(millis + rawOffset) != rawOffset;
+        // END android-changed
     }
 
     private boolean isLeapYear(int year) {
@@ -566,17 +609,18 @@
         return year % 4 == 0;
     }
 
+    // BEGIN android-added
     private int mod7(int num1) {
         int rem = num1 % 7;
         return (num1 < 0 && rem < 0) ? 7 + rem : rem;
     }
+    // END android-added
 
     /**
      * Sets the daylight savings offset in milliseconds for this {@code SimpleTimeZone}.
-     * 
+     *
      * @param milliseconds
      *            the daylight savings offset in milliseconds.
-     * @since Android 1.0
      */
     public void setDSTSavings(int milliseconds) {
         if (milliseconds > 0) {
@@ -591,7 +635,8 @@
             throw new IllegalArgumentException(Msg.getString("K00e5", month)); //$NON-NLS-1$
         }
         if (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY) {
-            throw new IllegalArgumentException(Msg.getString("K00e7", dayOfWeek)); //$NON-NLS-1$
+            throw new IllegalArgumentException(Msg
+                    .getString("K00e7", dayOfWeek)); //$NON-NLS-1$
         }
         if (time < 0 || time >= 24 * 3600000) {
             throw new IllegalArgumentException(Msg.getString("K00e8", time)); //$NON-NLS-1$
@@ -626,7 +671,8 @@
                 checkDay(endMonth, endDay);
             } else {
                 if (endDay < -5 || endDay > 5) {
-                    throw new IllegalArgumentException(Msg.getString("K00f8", endDay)); //$NON-NLS-1$
+                    throw new IllegalArgumentException(Msg.getString(
+                            "K00f8", endDay)); //$NON-NLS-1$
                 }
             }
         }
@@ -637,7 +683,7 @@
 
     /**
      * Sets the rule which specifies the end of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time ends.
      * @param dayOfMonth
@@ -646,7 +692,6 @@
      * @param time
      *            the time of day in milliseconds standard time on which
      *            daylight savings time ends.
-     * @since Android 1.0
      */
     public void setEndRule(int month, int dayOfMonth, int time) {
         endMonth = month;
@@ -654,11 +699,17 @@
         endDayOfWeek = 0; // Initialize this value for hasSameRules()
         endTime = time;
         setEndMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setEndRule(month,
+        //             dayOfMonth, time);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the rule which specifies the end of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time ends.
      * @param day
@@ -670,7 +721,6 @@
      * @param time
      *            the time of day in milliseconds standard time on which
      *            daylight savings time ends.
-     * @since Android 1.0
      */
     public void setEndRule(int month, int day, int dayOfWeek, int time) {
         endMonth = month;
@@ -678,11 +728,17 @@
         endDayOfWeek = dayOfWeek;
         endTime = time;
         setEndMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setEndRule(month, day,
+        //             dayOfWeek, time);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the rule which specifies the end of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time ends.
      * @param day
@@ -695,7 +751,6 @@
      *            ends.
      * @param after
      *            selects the day after or before the day of month.
-     * @since Android 1.0
      */
     public void setEndRule(int month, int day, int dayOfWeek, int time,
             boolean after) {
@@ -704,18 +759,26 @@
         endDayOfWeek = -dayOfWeek;
         endTime = time;
         setEndMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setEndRule(month, day,
+        //             dayOfWeek, time, after);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the offset for standard time from GMT for this {@code SimpleTimeZone}.
-     * 
+     *
      * @param offset
      *            the offset from GMT of standard time in milliseconds.
-     * @since Android 1.0
      */
     @Override
     public void setRawOffset(int offset) {
         rawOffset = offset;
+        // BEGIN android-removed
+        // icuTZ.setRawOffset(offset);
+        // END android-removed
     }
 
     private void setStartMode() {
@@ -740,7 +803,8 @@
                 checkDay(startMonth, startDay);
             } else {
                 if (startDay < -5 || startDay > 5) {
-                    throw new IllegalArgumentException(Msg.getString("K00f8", startDay)); //$NON-NLS-1$
+                    throw new IllegalArgumentException(Msg.getString(
+                            "K00f8", startDay)); //$NON-NLS-1$
                 }
             }
         }
@@ -751,7 +815,7 @@
 
     /**
      * Sets the rule which specifies the start of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time starts.
      * @param dayOfMonth
@@ -760,7 +824,6 @@
      * @param time
      *            the time of day in milliseconds on which daylight savings time
      *            starts.
-     * @since Android 1.0
      */
     public void setStartRule(int month, int dayOfMonth, int time) {
         startMonth = month;
@@ -768,11 +831,17 @@
         startDayOfWeek = 0; // Initialize this value for hasSameRules()
         startTime = time;
         setStartMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setStartRule(month,
+        //             dayOfMonth, time);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the rule which specifies the start of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time starts.
      * @param day
@@ -784,7 +853,6 @@
      * @param time
      *            the time of day in milliseconds on which daylight savings time
      *            starts.
-     * @since Android 1.0
      */
     public void setStartRule(int month, int day, int dayOfWeek, int time) {
         startMonth = month;
@@ -792,11 +860,17 @@
         startDayOfWeek = dayOfWeek;
         startTime = time;
         setStartMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setStartRule(month, day,
+        //             dayOfWeek, time);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the rule which specifies the start of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time starts.
      * @param day
@@ -809,7 +883,6 @@
      *            starts.
      * @param after
      *            selects the day after or before the day of month.
-     * @since Android 1.0
      */
     public void setStartRule(int month, int day, int dayOfWeek, int time,
             boolean after) {
@@ -818,15 +891,20 @@
         startDayOfWeek = -dayOfWeek;
         startTime = time;
         setStartMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setStartRule(month, day,
+        //             dayOfWeek, time, after);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the starting year for daylight savings time in this {@code SimpleTimeZone}.
      * Years before this start year will always be in standard time.
-     * 
+     *
      * @param year
      *            the starting year.
-     * @since Android 1.0
      */
     public void setStartYear(int year) {
         startYear = year;
@@ -835,9 +913,8 @@
 
     /**
      * Returns the string representation of this {@code SimpleTimeZone}.
-     * 
+     *
      * @return the string representation of this {@code SimpleTimeZone}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -864,7 +941,7 @@
                 + endMode + ",endMonth=" + endMonth + ",endDay=" + endDay //$NON-NLS-1$ //$NON-NLS-2$
                 + ",endDayOfWeek=" //$NON-NLS-1$
                 + (useDaylight && (endMode != DOM_MODE) ? endDayOfWeek + 1 : 0)
-                + ",endTime=" + endTime + "]";  //$NON-NLS-1$//$NON-NLS-2$
+                + ",endTime=" + endTime + "]"; //$NON-NLS-1$//$NON-NLS-2$
     }
 
     @Override
diff --git a/luni/src/main/java/java/util/SortedMap.java b/luni/src/main/java/java/util/SortedMap.java
index 10b2647..2fb25fd 100644
--- a/luni/src/main/java/java/util/SortedMap.java
+++ b/luni/src/main/java/java/util/SortedMap.java
@@ -21,8 +21,6 @@
 /**
  * A map that has its keys ordered. The sorting is according to either the
  * natural ordering of its keys or the ordering given by a specified comparator.
- * 
- * @since Android 1.0
  */
 public interface SortedMap<K,V> extends Map<K,V> {
     
@@ -30,7 +28,6 @@
      * Returns the comparator used to compare keys in this sorted map.
      * 
      * @return the comparator or {@code null} if the natural order is used.
-     * @since Android 1.0
      */
     public Comparator<? super K> comparator();
 
@@ -38,9 +35,8 @@
      * Returns the first key in this sorted map.
      * 
      * @return the first key in this sorted map.
-     * @exception NoSuchElementException
+     * @throws NoSuchElementException
      *                if this sorted map is empty.
-     * @since Android 1.0
      */
     public K firstKey();
 
@@ -51,8 +47,7 @@
      * <p>
      * Note: The returned map will not allow an insertion of a key outside the
      * specified range.
-     * </p>
-     * 
+     *
      * @param endKey
      *            the high boundary of the range specified.
      * @return a sorted map where the keys are less than {@code endKey}.
@@ -65,7 +60,6 @@
      * @throws IllegalArgumentException
      *             if this map is itself a sorted map over a range of another
      *             map and the specified key is outside of its range.
-     * @since Android 1.0
      */
     public SortedMap<K,V> headMap(K endKey);
 
@@ -73,9 +67,8 @@
      * Returns the last key in this sorted map.
      * 
      * @return the last key in this sorted map.
-     * @exception NoSuchElementException
+     * @throws NoSuchElementException
      *                if this sorted map is empty.
-     * @since Android 1.0
      */
     public K lastKey();
 
@@ -87,8 +80,7 @@
      * <p>
      * Note: The returned map will not allow an insertion of a key outside the
      * specified range.
-     * </p>
-     * 
+     *
      * @param startKey
      *            the low boundary of the range (inclusive).
      * @param endKey
@@ -104,7 +96,6 @@
      *             if the start key is greater than the end key, or if this map
      *             is itself a sorted map over a range of another sorted map and
      *             the specified range is outside of its range.
-     * @since Android 1.0
      */
     public SortedMap<K,V> subMap(K startKey, K endKey);
 
@@ -115,7 +106,6 @@
      * <p>
      * Note: The returned map will not allow an insertion of a key outside the
      * specified range.
-     * </p>
      * 
      * @param startKey
      *            the low boundary of the range specified.
@@ -130,7 +120,6 @@
      * @throws IllegalArgumentException
      *             if this map itself a sorted map over a range of another map
      *             and the specified key is outside of its range.
-     * @since Android 1.0
      */
     public SortedMap<K,V> tailMap(K startKey);
 }
diff --git a/luni/src/main/java/java/util/SortedSet.java b/luni/src/main/java/java/util/SortedSet.java
index 24fa017..d387540 100644
--- a/luni/src/main/java/java/util/SortedSet.java
+++ b/luni/src/main/java/java/util/SortedSet.java
@@ -27,7 +27,6 @@
  * 
  * @see Comparator
  * @see Comparable
- * @since Android 1.0
  */
 public interface SortedSet<E> extends Set<E> {
     
@@ -35,7 +34,6 @@
      * Returns the comparator used to compare elements in this {@code SortedSet}.
      * 
      * @return a comparator or null if the natural ordering is used.
-     * @since Android 1.0
      */
     public Comparator<? super E> comparator();
 
@@ -46,7 +44,6 @@
      * @return the first element.
      * @throws NoSuchElementException
      *             when this {@code SortedSet} is empty.
-     * @since Android 1.0
      */
     public E first();
 
@@ -65,7 +62,6 @@
      * @throws NullPointerException
      *             when the end element is null and this {@code SortedSet} does
      *             not support null elements.
-     * @since Android 1.0
      */
     public SortedSet<E> headSet(E end);
 
@@ -76,7 +72,6 @@
      * @return the last element.
      * @throws NoSuchElementException
      *             when this {@code SortedSet} is empty.
-     * @since Android 1.0
      */
     public E last();
 
@@ -101,7 +96,6 @@
      *             {@code SortedSet} does not support null elements.
      * @throws IllegalArgumentException
      *             when the start element is greater than the end element.
-     * @since Android 1.0
      */
     public SortedSet<E> subSet(E start, E end);
 
@@ -120,7 +114,6 @@
      * @throws NullPointerException
      *             when the start element is null and this {@code SortedSet}
      *             does not support null elements.
-     * @since Android 1.0
      */
     public SortedSet<E> tailSet(E start);
 }
diff --git a/luni/src/main/java/java/util/Stack.java b/luni/src/main/java/java/util/Stack.java
index 8ecb765..1572a08 100644
--- a/luni/src/main/java/java/util/Stack.java
+++ b/luni/src/main/java/java/util/Stack.java
@@ -17,22 +17,17 @@
 
 package java.util;
 
-
 /**
  * {@code Stack} is a Last-In/First-Out(LIFO) data structure which represents a
  * stack of objects. It enables users to pop to and push from the stack,
  * including null objects. There is no limit to the size of the stack.
- * 
- * @since Android 1.0
  */
 public class Stack<E> extends Vector<E> {
-    
+
     private static final long serialVersionUID = 1224463164541339165L;
 
     /**
      * Constructs a stack with the default size of {@code Vector}.
-     * 
-     * @since Android 1.0
      */
     public Stack() {
         super();
@@ -40,9 +35,8 @@
 
     /**
      * Returns whether the stack is empty or not.
-     * 
+     *
      * @return {@code true} if the stack is empty, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean empty() {
         return elementCount == 0;
@@ -50,16 +44,16 @@
 
     /**
      * Returns the element at the top of the stack without removing it.
-     * 
+     *
      * @return the element at the top of the stack.
      * @throws EmptyStackException
      *             if the stack is empty.
      * @see #pop
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public synchronized E peek() {
         try {
-            return (E)elementData[elementCount - 1];
+            return (E) elementData[elementCount - 1];
         } catch (IndexOutOfBoundsException e) {
             throw new EmptyStackException();
         }
@@ -67,36 +61,35 @@
 
     /**
      * Returns the element at the top of the stack and removes it.
-     * 
+     *
      * @return the element at the top of the stack.
      * @throws EmptyStackException
      *             if the stack is empty.
      * @see #peek
      * @see #push
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public synchronized E pop() {
-        try {
-            int index = elementCount - 1;
-            E obj = (E)elementData[index];
-            removeElementAt(index);
-            return obj;
-        } catch (IndexOutOfBoundsException e) {
+        if (elementCount == 0) {
             throw new EmptyStackException();
         }
+        final int index = --elementCount;
+        final E obj = (E) elementData[index];
+        elementData[index] = null;
+        modCount++;
+        return obj;
     }
 
     /**
      * Pushes the specified object onto the top of the stack.
-     * 
+     *
      * @param object
      *            The object to be added on top of the stack.
      * @return the object argument.
      * @see #peek
      * @see #pop
-     * @since Android 1.0
      */
-    public synchronized E push(E object) {
+    public E push(E object) {
         addElement(object);
         return object;
     }
@@ -104,17 +97,28 @@
     /**
      * Returns the index of the first occurrence of the object, starting from
      * the top of the stack.
-     * 
+     *
      * @return the index of the first occurrence of the object, assuming that
      *         the topmost object on the stack has a distance of one.
      * @param o
      *            the object to be searched.
-     * @since Android 1.0
      */
     public synchronized int search(Object o) {
-        int index = lastIndexOf(o);
-        if (index >= 0)
-            return (elementCount - index);
+        final Object[] dumpArray = elementData;
+        final int size = elementCount;
+        if (o != null) {
+            for (int i = size - 1; i >= 0; i--) {
+                if (o.equals(dumpArray[i])) {
+                    return size - i;
+                }
+            }
+        } else {
+            for (int i = size - 1; i >= 0; i--) {
+                if (dumpArray[i] == null) {
+                    return size - i;
+                }
+            }
+        }
         return -1;
     }
 }
diff --git a/luni/src/main/java/java/util/StringTokenizer.java b/luni/src/main/java/java/util/StringTokenizer.java
index 3bbeefa..2800283 100644
--- a/luni/src/main/java/java/util/StringTokenizer.java
+++ b/luni/src/main/java/java/util/StringTokenizer.java
@@ -14,32 +14,17 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2006, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 package java.util;
 
-
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 /**
- * <p>
  * The {@code StringTokenizer} class allows an application to break a string
  * into tokens by performing code point comparison. The {@code StringTokenizer}
  * methods do not distinguish among identifiers, numbers, and quoted strings,
  * nor do they recognize and skip comments.
- * </p>
  * <p>
  * The set of delimiters (the codepoints that separate tokens) may be specified
  * either at creation time or on a per-token basis.
- * </p>
  * <p>
  * An instance of {@code StringTokenizer} behaves in one of three ways,
  * depending on whether it was created with the {@code returnDelimiters} flag
@@ -55,45 +40,40 @@
  * <p>
  * A token is thus either one delimiter code point, or a maximal sequence of
  * consecutive code points that are not delimiters.
- * </p>
  * <p>
  * A {@code StringTokenizer} object internally maintains a current position
  * within the string to be tokenized. Some operations advance this current
  * position past the code point processed.
- * </p>
  * <p>
  * A token is returned by taking a substring of the string that was used to
  * create the {@code StringTokenizer} object.
- * </p>
  * <p>
  * Here's an example of the use of the default delimiter {@code StringTokenizer}
  * : <blockquote>
- * 
+ *
  * <pre>
  * StringTokenizer st = new StringTokenizer(&quot;this is a test&quot;);
  * while (st.hasMoreTokens()) {
  *     println(st.nextToken());
  * }
  * </pre>
- * 
+ *
  * </blockquote>
- * </p>
  * <p>
  * This prints the following output: <blockquote>
- * 
+ *
  * <pre>
  *     this
  *     is
  *     a
  *     test
  * </pre>
- * 
+ *
  * </blockquote>
- * </p>
  * <p>
  * Here's an example of how to use a {@code StringTokenizer} with a user
  * specified delimiter: <blockquote>
- * 
+ *
  * <pre>
  * StringTokenizer st = new StringTokenizer(
  *         &quot;this is a test with supplementary characters \ud800\ud800\udc00\udc00&quot;,
@@ -102,12 +82,11 @@
  *     println(st.nextToken());
  * }
  * </pre>
- * 
+ *
  * </blockquote>
- * </p>
  * <p>
  * This prints the following output: <blockquote>
- * 
+ *
  * <pre>
  *     this
  *     is
@@ -119,14 +98,11 @@
  *     \ud800
  *     \udc00
  * </pre>
- * 
+ *
  * </blockquote>
- * </p>
- * 
- * @since Android 1.0
  */
 public class StringTokenizer implements Enumeration<Object> {
-    
+
     private String string;
 
     private String delimiters;
@@ -139,10 +115,9 @@
      * Constructs a new {@code StringTokenizer} for the parameter string using
      * whitespace as the delimiter. The {@code returnDelimiters} flag is set to
      * {@code false}.
-     * 
+     *
      * @param string
      *            the string to be tokenized.
-     * @since Android 1.0
      */
     public StringTokenizer(String string) {
         this(string, " \t\n\r\f", false); //$NON-NLS-1$
@@ -154,12 +129,11 @@
      * {@code false}. If {@code delimiters} is {@code null}, this constructor
      * doesn't throw an {@code Exception}, but later calls to some methods might
      * throw a {@code NullPointerException}.
-     * 
+     *
      * @param string
      *            the string to be tokenized.
      * @param delimiters
      *            the delimiters to use.
-     * @since Android 1.0
      */
     public StringTokenizer(String string, String delimiters) {
         this(string, delimiters, false);
@@ -171,14 +145,13 @@
      * parameter {@code returnDelimiters} is {@code true}. If {@code delimiters}
      * is null this constructor doesn't throw an {@code Exception}, but later
      * calls to some methods might throw a {@code NullPointerException}.
-     * 
+     *
      * @param string
      *            the string to be tokenized.
      * @param delimiters
      *            the delimiters to use.
      * @param returnDelimiters
      *            {@code true} to return each delimiter as a token.
-     * @since Android 1.0
      */
     public StringTokenizer(String string, String delimiters,
             boolean returnDelimiters) {
@@ -193,10 +166,9 @@
 
     /**
      * Returns the number of unprocessed tokens remaining in the string.
-     * 
+     *
      * @return number of tokens that can be retreived before an {@code
      *         Exception} will result from a call to {@code nextToken()}.
-     * @since Android 1.0
      */
     public int countTokens() {
         int count = 0;
@@ -221,9 +193,8 @@
     /**
      * Returns {@code true} if unprocessed tokens remain. This method is
      * implemented in order to satisfy the {@code Enumeration} interface.
-     * 
+     *
      * @return {@code true} if unprocessed tokens remain.
-     * @since Android 1.0
      */
     public boolean hasMoreElements() {
         return hasMoreTokens();
@@ -231,11 +202,13 @@
 
     /**
      * Returns {@code true} if unprocessed tokens remain.
-     * 
+     *
      * @return {@code true} if unprocessed tokens remain.
-     * @since Android 1.0
      */
     public boolean hasMoreTokens() {
+        if (delimiters == null) {
+            throw new NullPointerException();
+        }
         int length = string.length();
         if (position < length) {
             if (returnDelimiters)
@@ -253,11 +226,10 @@
     /**
      * Returns the next token in the string as an {@code Object}. This method is
      * implemented in order to satisfy the {@code Enumeration} interface.
-     * 
+     *
      * @return next token in the string as an {@code Object}
-     * @exception NoSuchElementException
+     * @throws NoSuchElementException
      *                if no tokens remain.
-     * @since Android 1.0
      */
     public Object nextElement() {
         return nextToken();
@@ -265,13 +237,15 @@
 
     /**
      * Returns the next token in the string as a {@code String}.
-     * 
+     *
      * @return next token in the string as a {@code String}.
-     * @exception NoSuchElementException
+     * @throws NoSuchElementException
      *                if no tokens remain.
-     * @since Android 1.0
      */
     public String nextToken() {
+        if (delimiters == null) {
+            throw new NullPointerException();
+        }
         int i = position;
         int length = string.length();
 
@@ -301,20 +275,14 @@
     /**
      * Returns the next token in the string as a {@code String}. The delimiters
      * used are changed to the specified delimiters.
-     * 
+     *
      * @param delims
      *            the new delimiters to use.
      * @return next token in the string as a {@code String}.
-     * @exception NoSuchElementException
+     * @throws NoSuchElementException
      *                if no tokens remain.
-     * @since Android 1.0
      */
     public String nextToken(String delims) {
-        // BEGIN android-added
-        if (delims == null) {
-            throw new NullPointerException();
-        }
-        // END android-added
         this.delimiters = delims;
         return nextToken();
     }
diff --git a/luni/src/main/java/java/util/TimeZone.java b/luni/src/main/java/java/util/TimeZone.java
index c9709ce..b0bcc6b 100644
--- a/luni/src/main/java/java/util/TimeZone.java
+++ b/luni/src/main/java/java/util/TimeZone.java
@@ -14,35 +14,17 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2008, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
-
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 
 package java.util;
 
-
 import java.io.Serializable;
-// BEGIN android-removed
-// import java.security.AccessController;
-// import java.text.DateFormatSymbols;
-// 
-// import org.apache.harmony.luni.util.PriviAction;
-// END android-removed
 
 // BEGIN android-added
 import org.apache.harmony.luni.internal.util.ZoneInfo;
 import org.apache.harmony.luni.internal.util.ZoneInfoDB;
 import com.ibm.icu4jni.util.Resources;
 // END android-added
+
 /**
  * {@code TimeZone} represents a time zone offset, taking into account
  * daylight savings.
@@ -57,21 +39,21 @@
  * along with a time zone ID. For instance, the time zone ID for the U.S.
  * Pacific Time zone is "America/Los_Angeles". So, you can get a U.S. Pacific
  * Time {@code TimeZone} object with the following: <blockquote>
- * 
+ *
  * <pre>
  * TimeZone tz = TimeZone.getTimeZone(&quot;America/Los_Angeles&quot;);
  * </pre>
- * 
+ *
  * </blockquote> You can use the {@code getAvailableIDs} method to iterate
  * through all the supported time zone IDs. You can then choose a supported ID
  * to get a {@code TimeZone}. If the time zone you want is not
  * represented by one of the supported IDs, then you can create a custom time
  * zone ID with the following syntax: <blockquote>
- * 
+ *
  * <pre>
  * GMT[+|-]hh[[:]mm]
  * </pre>
- * 
+ *
  * </blockquote> For example, you might specify GMT+14:00 as a custom time zone
  * ID. The {@code TimeZone} that is returned when you specify a custom
  * time zone ID does not include daylight savings time.
@@ -83,33 +65,26 @@
  * "China Standard Time"), and the Java platform can then only recognize one of
  * them.
  * <p>
- * Please note the type returned by factory methods, i.e.
- * {@code getDefault()} and {@code getTimeZone(String)}, is
- * implementation dependent, so it may introduce serialization
- * incompatibility issues between different implementations. Android returns
- * instances of {@link SimpleTimeZone} so that the bytes serialized by Android
- * can be deserialized successfully on other implementations, but the reverse
- * compatibility cannot be guaranteed.
- * 
+ * Please note the type returned by factory methods, i.e. {@code getDefault()}
+ * and {@code getTimeZone(String)}, is implementation dependent, so it may
+ * introduce serialization incompatibility issues between different
+ * implementations. Android returns instances of {@link SimpleTimeZone} so that
+ * the bytes serialized by Android can be deserialized successfully on other
+ * implementations, but the reverse compatibility cannot be guaranteed.
+ *
  * @see GregorianCalendar
  * @see SimpleTimeZone
- * @since Android 1.0
  */
-
 public abstract class TimeZone implements Serializable, Cloneable {
     private static final long serialVersionUID = 3581463369166924961L;
 
     /**
      * The SHORT display name style.
-     * 
-     * @since Android 1.0
      */
     public static final int SHORT = 0;
 
     /**
      * The LONG display name style.
-     * 
-     * @since Android 1.0
      */
     public static final int LONG = 1;
 
@@ -124,41 +99,49 @@
     private String ID;
 
     // BEGIN android-removed
+    // private com.ibm.icu.util.TimeZone icuTimeZone = null;
+    //
     // private static void initializeAvailable() {
     //     TimeZone[] zones = TimeZones.getTimeZones();
-    //     AvailableZones = new HashMap<String, TimeZone>((zones.length + 1) * 4 / 3);
+    //     AvailableZones = new HashMap<String, TimeZone>(
+    //             (zones.length + 1) * 4 / 3);
     //     AvailableZones.put(GMT.getID(), GMT);
     //     for (int i = 0; i < zones.length; i++) {
     //         AvailableZones.put(zones[i].getID(), zones[i]);
     //     }
+    //}
+    //
+    // private static boolean isAvailableIDInICU(String name) {
+    //     String[] availableIDs = com.ibm.icu.util.TimeZone.getAvailableIDs();
+    //     for (int i = 0; i < availableIDs.length; i++) {
+    //         if (availableIDs[i].equals(name)) {
+    //             return true;
+    //         }
+    //     }
+    //     return false;
+    // }
+    //
+    // private static void appendAvailableZones(String name) {
+    //     com.ibm.icu.util.TimeZone icuTZ = com.ibm.icu.util.TimeZone
+    //             .getTimeZone(name);
+    //     int raw = icuTZ.getRawOffset();
+    //     TimeZone zone = new SimpleTimeZone(raw, name);
+    //     AvailableZones.put(name, zone);
     // }
     // END android-removed
 
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public TimeZone() {
     }
 
-    private void appendNumber(StringBuffer buffer, int count, int value) {
-        String string = Integer.toString(value);
-        if (count > string.length()) {
-            for (int i = 0; i < count - string.length(); i++) {
-                buffer.append('0');
-            }
-        }
-        buffer.append(string);
-    }
-
     /**
      * Returns a new {@code TimeZone} with the same ID, {@code rawOffset} and daylight savings
      * time rules as this {@code TimeZone}.
-     * 
+     *
      * @return a shallow copy of this {@code TimeZone}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -173,49 +156,34 @@
     /**
      * Gets the available time zone IDs. Any one of these IDs can be passed to
      * {@code get()} to create the corresponding {@code TimeZone} instance.
-     * 
+     *
      * @return an array of time zone ID strings.
-     * @since Android 1.0
      */
     public static synchronized String[] getAvailableIDs() {
-        // BEGIN android-removed
-        // if (AvailableZones == null) {
-        //     initializeAvailable();
-        // }
-        // int length = AvailableZones.size();
-        // String[] answer = new String[length];
-        // Iterator<String> keys = AvailableZones.keySet().iterator();
-        // for (int i = 0; i < length; i++) {
-        //     answer[i] = keys.next();
-        // }
-        // return answer;
-        // END android-removed
-
-        // BEGIN android-added
+        // BEGIN android-changed
+        // return com.ibm.icu.util.TimeZone.getAvailableIDs();
         return ZoneInfoDB.getAvailableIDs();
-        // END android-added
+        // END android-changed
     }
 
     /**
      * Gets the available time zone IDs which match the specified offset from
      * GMT. Any one of these IDs can be passed to {@code get()} to create the corresponding
      * {@code TimeZone} instance.
-     * 
+     *
      * @param offset
      *            the offset from GMT in milliseconds.
      * @return an array of time zone ID strings.
-     * @since Android 1.0
      */
     public static synchronized String[] getAvailableIDs(int offset) {
-        // BEGIN android-removed
-        // if (AvailableZones == null) {
-        //     initializeAvailable();
-        // }
-        // int count = 0, length = AvailableZones.size();
+        // BEGIN android-changed
+        // String[] availableIDs = com.ibm.icu.util.TimeZone.getAvailableIDs();
+        // int count = 0;
+        // int length = availableIDs.length;
         // String[] all = new String[length];
-        // Iterator<TimeZone> zones = AvailableZones.values().iterator();
         // for (int i = 0; i < length; i++) {
-        //     TimeZone tz = zones.next();
+        //     com.ibm.icu.util.TimeZone tz = com.ibm.icu.util.TimeZone
+        //             .getTimeZone(availableIDs[i]);
         //     if (tz.getRawOffset() == offset) {
         //         all[count++] = tz.getID();
         //     }
@@ -223,23 +191,21 @@
         // String[] answer = new String[count];
         // System.arraycopy(all, 0, answer, 0, count);
         // return answer;
-        // END android-removed
-        
-        // BEGIN android-added
         return ZoneInfoDB.getAvailableIDs(offset);
-        // END android-added
-        
+        // END android-changed
     }
 
     /**
      * Gets the default time zone.
-     * 
+     *
      * @return the default time zone.
-     * @since Android 1.0
      */
     public static synchronized TimeZone getDefault() {
         if (Default == null) {
+            // BEGIN android-changed
+            // setDefault(null);
             Default = ZoneInfoDB.getDefault();
+            // END android-changed
         }
         return (TimeZone) Default.clone();
     }
@@ -248,9 +214,8 @@
      * Gets the LONG name for this {@code TimeZone} for the default {@code Locale} in standard
      * time. If the name is not available, the result is in the format
      * {@code GMT[+-]hh:mm}.
-     * 
+     *
      * @return the {@code TimeZone} name.
-     * @since Android 1.0
      */
     public final String getDisplayName() {
         return getDisplayName(false, LONG, Locale.getDefault());
@@ -260,11 +225,10 @@
      * Gets the LONG name for this {@code TimeZone} for the specified {@code Locale} in standard
      * time. If the name is not available, the result is in the format
      * {@code GMT[+-]hh:mm}.
-     * 
+     *
      * @param locale
      *            the {@code Locale}.
      * @return the {@code TimeZone} name.
-     * @since Android 1.0
      */
     public final String getDisplayName(Locale locale) {
         return getDisplayName(false, LONG, locale);
@@ -274,14 +238,13 @@
      * Gets the specified style of name ({@code LONG} or {@code SHORT}) for this {@code TimeZone} for
      * the default {@code Locale} in either standard or daylight time as specified. If
      * the name is not available, the result is in the format {@code GMT[+-]hh:mm}.
-     * 
+     *
      * @param daylightTime
      *            {@code true} for daylight time, {@code false} for standard
      *            time.
      * @param style
-     *            Either {@code LONG} or {@code SHORT}.
+     *            either {@code LONG} or {@code SHORT}.
      * @return the {@code TimeZone} name.
-     * @since Android 1.0
      */
     public final String getDisplayName(boolean daylightTime, int style) {
         return getDisplayName(daylightTime, style, Locale.getDefault());
@@ -291,39 +254,31 @@
      * Gets the specified style of name ({@code LONG} or {@code SHORT}) for this {@code TimeZone} for
      * the specified {@code Locale} in either standard or daylight time as specified. If
      * the name is not available, the result is in the format {@code GMT[+-]hh:mm}.
-     * 
+     *
      * @param daylightTime
      *            {@code true} for daylight time, {@code false} for standard
      *            time.
      * @param style
-     *            Either LONG or SHORT.
+     *            either LONG or SHORT.
      * @param locale
-     *            Either {@code LONG} or {@code SHORT}.
+     *            either {@code LONG} or {@code SHORT}.
      * @return the {@code TimeZone} name.
-     * @since Android 1.0
      */
     public String getDisplayName(boolean daylightTime, int style, Locale locale) {
+        // BEGIN android-changed
+        // if(icuTimeZone == null || !ID.equals(icuTimeZone.getID())){
+        //     icuTimeZone = com.ibm.icu.util.TimeZone.getTimeZone(ID);
+        // }
+        // return icuTimeZone.getDisplayName(
+        //         daylightTime, style, locale);
         if (style == SHORT || style == LONG) {
             boolean useDaylight = daylightTime && useDaylightTime();
-            // BEGIN android-removed
-            // DateFormatSymbols data = new DateFormatSymbols(locale);
-            // String id = getID();
-            // String[][] zones = data.getZoneStrings();
-            // for (int i = 0; i < zones.length; i++) {
-            //     if (id.equals(zones[i][0])) {
-            //         return style == SHORT ? zones[i][useDaylight ? 4 : 2]
-            //                 : zones[i][useDaylight ? 3 : 1];
-            //     }
-            // }
-            // BEGIN android-removed
-            
-            // BEGIN android-added
+
             String result = Resources.getDisplayTimeZone(getID(), daylightTime, style, locale.toString());
             if (result != null) {
                 return result;
             }
-            // END android-added
-            
+
             int offset = getRawOffset();
             if (useDaylight && this instanceof SimpleTimeZone) {
                 offset += ((SimpleTimeZone) this).getDSTSavings();
@@ -343,13 +298,25 @@
             return buffer.toString();
         }
         throw new IllegalArgumentException();
+        // END android-changed
     }
 
+    // BEGIN android-added
+    private void appendNumber(StringBuffer buffer, int count, int value) {
+        String string = Integer.toString(value);
+        if (count > string.length()) {
+            for (int i = 0; i < count - string.length(); i++) {
+                buffer.append('0');
+            }
+        }
+        buffer.append(string);
+    }
+    // END android-added
+
     /**
      * Gets the ID of this {@code TimeZone}.
-     * 
+     *
      * @return the time zone ID string.
-     * @since Android 1.0
      */
     public String getID() {
         return ID;
@@ -364,10 +331,9 @@
      * Subclasses may override to return daylight savings values other than 1
      * hour.
      * <p>
-     * 
+     *
      * @return the daylight savings offset in milliseconds if this {@code TimeZone}
      *         observes daylight savings, zero otherwise.
-     * @since Android 1.0
      */
     public int getDSTSavings() {
         if (useDaylightTime()) {
@@ -380,11 +346,10 @@
      * Gets the offset from GMT of this {@code TimeZone} for the specified date. The
      * offset includes daylight savings time if the specified date is within the
      * daylight savings time period.
-     * 
+     *
      * @param time
      *            the date in milliseconds since January 1, 1970 00:00:00 GMT
      * @return the offset from GMT in milliseconds.
-     * @since Android 1.0
      */
     public int getOffset(long time) {
         if (inDaylightTime(new Date(time))) {
@@ -397,7 +362,7 @@
      * Gets the offset from GMT of this {@code TimeZone} for the specified date and
      * time. The offset includes daylight savings time if the specified date and
      * time are within the daylight savings time period.
-     * 
+     *
      * @param era
      *            the {@code GregorianCalendar} era, either {@code GregorianCalendar.BC} or
      *            {@code GregorianCalendar.AD}.
@@ -412,39 +377,38 @@
      * @param time
      *            the time of day in milliseconds.
      * @return the offset from GMT in milliseconds.
-     * @since Android 1.0
      */
     abstract public int getOffset(int era, int year, int month, int day,
             int dayOfWeek, int time);
 
     /**
      * Gets the offset for standard time from GMT for this {@code TimeZone}.
-     * 
+     *
      * @return the offset from GMT in milliseconds.
-     * @since Android 1.0
      */
     abstract public int getRawOffset();
 
     /**
      * Gets the {@code TimeZone} with the specified ID.
-     * 
+     *
      * @param name
      *            a time zone string ID.
      * @return the {@code TimeZone} with the specified ID or null if no {@code TimeZone} with
      *         the specified ID exists.
-     * @since Android 1.0
      */
     public static synchronized TimeZone getTimeZone(String name) {
-        // BEGIN android-removed
+        // BEGIN android-changed
         // if (AvailableZones == null) {
         //     initializeAvailable();
         // }
+        //
         // TimeZone zone = AvailableZones.get(name);
-        // END android-removed
-        
-        // BEGIN android-added
+        // if(zone == null && isAvailableIDInICU(name)){
+        //     appendAvailableZones(name);
+        //     zone = AvailableZones.get(name);
+        // }
         TimeZone zone = ZoneInfo.getTimeZone(name);
-        // END android-added
+        // END android-changed
         if (zone == null) {
             if (name.startsWith("GMT") && name.length() > 3) {
                 char sign = name.charAt(3);
@@ -513,12 +477,11 @@
     /**
      * Returns whether the specified {@code TimeZone} has the same raw offset as this
      * {@code TimeZone}.
-     * 
+     *
      * @param zone
      *            a {@code TimeZone}.
      * @return {@code true} when the {@code TimeZone} have the same raw offset, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean hasSameRules(TimeZone zone) {
         if (zone == null) {
@@ -530,12 +493,11 @@
     /**
      * Returns whether the specified {@code Date} is in the daylight savings time period for
      * this {@code TimeZone}.
-     * 
+     *
      * @param time
      *            a {@code Date}.
      * @return {@code true} when the {@code Date} is in the daylight savings time period, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     abstract public boolean inDaylightTime(Date time);
 
@@ -555,34 +517,30 @@
      * time {@link #getDefault} is called, the default time zone will be
      * determined. This behavior is slightly different than the canonical
      * description of this method, but it follows the spirit of it.
-     * 
+     *
      * @param timezone
      *            a {@code TimeZone} object.
-     * @since Android 1.0
      */
     public static synchronized void setDefault(TimeZone timezone) {
         // BEGIN android-removed
         // if (timezone != null) {
+        //     setICUDefaultTimeZone(timezone);
         //     Default = timezone;
         //     return;
         // }
-        // END android-removed
-
-        // BEGIN android-added
-        Default = timezone;
-
-        // TODO Not sure if this is spec-compliant. Shouldn't be persistent.
-        ZoneInfoDB.setDefault(timezone);
-        // END android-added
-        
-        // BEGIN android-removed
+        //
         // String zone = AccessController.doPrivileged(new PriviAction<String>(
-        // "user.timezone"));
+        //         "user.timezone"));
+        //
+        // // sometimes DRLVM incorrectly adds "\n" to the end of timezone ID
+        // if (zone != null && zone.contains("\n")) {
+        //     zone = zone.substring(0, zone.indexOf("\n"));
+        // }
         //
         // // if property user.timezone is not set, we call the native method
         // // getCustomTimeZone
-        // if (zone == null) {
-        //    int[] tzinfo = new int[10];
+        // if (zone == null || zone.length() == 0) {
+        //     int[] tzinfo = new int[10];
         //     boolean[] isCustomTimeZone = new boolean[1];
         //
         //     String zoneId = getCustomTimeZone(tzinfo, isCustomTimeZone);
@@ -609,15 +567,45 @@
         //     // if property user.timezone is set in command line (with -D option)
         //     Default = getTimeZone(zone);
         // }
+        // setICUDefaultTimeZone(Default);
         // END android-removed
+
+        // BEGIN android-added
+        Default = timezone;
+
+        // TODO Not sure if this is spec-compliant. Shouldn't be persistent.
+        ZoneInfoDB.setDefault(timezone);
+        // END android-added
     }
 
+    // BEGIN android-removed
+    // private static void setICUDefaultTimeZone(TimeZone timezone) {
+    //     final com.ibm.icu.util.TimeZone icuTZ = com.ibm.icu.util.TimeZone
+    //             .getTimeZone(timezone.getID());
+    //
+    //     AccessController
+    //             .doPrivileged(new PrivilegedAction<java.lang.reflect.Field>() {
+    //                 public java.lang.reflect.Field run() {
+    //                     java.lang.reflect.Field field = null;
+    //                     try {
+    //                         field = com.ibm.icu.util.TimeZone.class
+    //                                 .getDeclaredField("defaultZone");
+    //                         field.setAccessible(true);
+    //                         field.set("defaultZone", icuTZ);
+    //                     } catch (Exception e) {
+    //                         return null;
+    //                     }
+    //                     return field;
+    //                 }
+    //             });
+    // }
+    // END android-removed
+
     /**
      * Sets the ID of this {@code TimeZone}.
-     * 
+     *
      * @param name
      *            a string which is the time zone ID.
-     * @since Android 1.0
      */
     public void setID(String name) {
         if (name == null) {
@@ -628,44 +616,40 @@
 
     /**
      * Sets the offset for standard time from GMT for this {@code TimeZone}.
-     * 
+     *
      * @param offset
      *            the offset from GMT in milliseconds.
-     * @since Android 1.0
      */
     abstract public void setRawOffset(int offset);
 
     /**
      * Returns whether this {@code TimeZone} has a daylight savings time period.
-     * 
+     *
      * @return {@code true} if this {@code TimeZone} has a daylight savings time period, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     abstract public boolean useDaylightTime();
 
-    // BEGIN android-removed
-    // /**
-    //  * Gets the name and the details of the user-selected TimeZone on the
-    //  * device.
-    //  * 
-    //  * @param tzinfo
-    //  *            int array of 10 elements to be filled with the TimeZone
-    //  *            information. Once filled, the contents of the array are
-    //  *            formatted as follows: tzinfo[0] -> the timezone offset;
-    //  *            tzinfo[1] -> the dst adjustment; tzinfo[2] -> the dst start
-    //  *            hour; tzinfo[3] -> the dst start day of week; tzinfo[4] -> the
-    //  *            dst start week of month; tzinfo[5] -> the dst start month;
-    //  *            tzinfo[6] -> the dst end hour; tzinfo[7] -> the dst end day of
-    //  *            week; tzinfo[8] -> the dst end week of month; tzinfo[9] -> the
-    //  *            dst end month;
-    //  * @param isCustomTimeZone
-    //  *            boolean array of size 1 that indicates if a timezone
-    //  *            match is found
-    //  * @return the name of the TimeZone or null if error occurs in native
-    //  *         method.
-    //  */
-    // private static native String getCustomTimeZone(int[] tzinfo,
-    //         boolean[] isCustomTimeZone);
-    // END android-removed
+    /**
+     * Gets the name and the details of the user-selected TimeZone on the
+     * device.
+     *
+     * @param tzinfo
+     *            int array of 10 elements to be filled with the TimeZone
+     *            information. Once filled, the contents of the array are
+     *            formatted as follows: tzinfo[0] -> the timezone offset;
+     *            tzinfo[1] -> the dst adjustment; tzinfo[2] -> the dst start
+     *            hour; tzinfo[3] -> the dst start day of week; tzinfo[4] -> the
+     *            dst start week of month; tzinfo[5] -> the dst start month;
+     *            tzinfo[6] -> the dst end hour; tzinfo[7] -> the dst end day of
+     *            week; tzinfo[8] -> the dst end week of month; tzinfo[9] -> the
+     *            dst end month;
+     * @param isCustomTimeZone
+     *            boolean array of size 1 that indicates if a timezone match is
+     *            found
+     * @return the name of the TimeZone or null if error occurs in native
+     *         method.
+     */
+    private static native String getCustomTimeZone(int[] tzinfo,
+            boolean[] isCustomTimeZone);
 }
diff --git a/luni/src/main/java/java/util/Timer.java b/luni/src/main/java/java/util/Timer.java
index ccff929..48970be 100644
--- a/luni/src/main/java/java/util/Timer.java
+++ b/luni/src/main/java/java/util/Timer.java
@@ -29,145 +29,143 @@
  * excessive amount of time to run it may impact the time at which subsequent
  * tasks may run.
  * <p>
- * 
+ *
  * The {@code TimerTask} does not offer any guarantees about the real-time nature of
  * scheduling tasks as its underlying implementation relies on the
  * {@code Object.wait(long)} method.
- * </p>
  * <p>
  * Multiple threads can share a single {@code Timer} without the need for their own
- * synchronization.</p>
+ * synchronization.
  * <p>
- * A {@code Timer} can be set to schedule tasks either at a fixed rate or 
- * with a fixed period. Fixed-period execution is the default.</p>
+ * A {@code Timer} can be set to schedule tasks either at a fixed rate or
+ * with a fixed period. Fixed-period execution is the default.
  * <p>
- * The difference between fixed-rate and fixed-period execution 
- * is the following:  With fixed-rate execution, the start time of each 
+ * The difference between fixed-rate and fixed-period execution
+ * is the following:  With fixed-rate execution, the start time of each
  * successive run of the task is scheduled in absolute terms without regard for when the previous
- * task run actually took place. This can result in a series of bunched-up runs 
- * (one launched immediately after another) if busy resources or other 
+ * task run actually took place. This can result in a series of bunched-up runs
+ * (one launched immediately after another) if busy resources or other
  * system delays prevent the {@code Timer} from firing for an extended time.
- * With fixed-period execution, each successive run of the 
- * task is scheduled relative to the start time of the previous run of the 
- * task, so two runs of the task are never fired closer together in time than 
- * the specified {@code period}.</p>
- * </p>
- * 
+ * With fixed-period execution, each successive run of the
+ * task is scheduled relative to the start time of the previous run of the
+ * task, so two runs of the task are never fired closer together in time than
+ * the specified {@code period}.
+ *
  * @see TimerTask
  * @see java.lang.Object#wait(long)
- * @since Android 1.0
  */
 public class Timer {
 
     private static final class TimerImpl extends Thread {
 
-        private static final class TimerNode {
-            TimerNode parent, left, right;
+        private static final class TimerHeap {
+            private int DEFAULT_HEAP_SIZE = 256;
 
-            TimerTask task;
+            private TimerTask[] timers = new TimerTask[DEFAULT_HEAP_SIZE];
 
-            public TimerNode(TimerTask value) {
-                this.task = value;
+            private int size = 0;
+
+            private int deletedCancelledNumber = 0;
+
+            public TimerTask minimum() {
+                return timers[0];
             }
 
-            public void deleteIfCancelled(TimerTree tasks) {
-                /*
-                 * All changes in the tree structure during deleting this node
-                 * affect only the structure of the subtree having this node as
-                 * its root
-                 */
-                if (left != null) {
-                    left.deleteIfCancelled(tasks);
-                }
-                if (right != null) {
-                    right.deleteIfCancelled(tasks);
-                }
-                if (task.cancelled) {
-                    tasks.delete(this);
-                    tasks.deletedCancelledNumber++;
-                }
-            }
-        }
-
-        private static final class TimerTree {
-
-            int deletedCancelledNumber;
-
-            TimerNode root;
-
-            boolean isEmpty() {
-                return root == null;
+            public boolean isEmpty() {
+                return size == 0;
             }
 
-            void insert(TimerNode z) {
-                TimerNode y = null, x = root;
-                while (x != null) {
-                    y = x;
-                    if (z.task.getWhen() < x.task.getWhen()) {
-                        x = x.left;
-                    } else {
-                        x = x.right;
+            public void insert(TimerTask task) {
+                if (timers.length == size) {
+                    TimerTask[] appendedTimers = new TimerTask[size * 2];
+                    System.arraycopy(timers, 0, appendedTimers, 0, size);
+                    timers = appendedTimers;
+                }
+                timers[size++] = task;
+                upHeap();
+            }
+
+            public void delete(int pos) {
+                // posible to delete any position of the heap
+                if (pos >= 0 && pos < size) {
+                    timers[pos] = timers[--size];
+                    timers[size] = null;
+                    downHeap(pos);
+                }
+            }
+
+            private void upHeap() {
+                int current = size - 1;
+                int parent = (current - 1) / 2;
+
+                while (timers[current].when < timers[parent].when) {
+                    // swap the two
+                    TimerTask tmp = timers[current];
+                    timers[current] = timers[parent];
+                    timers[parent] = tmp;
+
+                    // update pos and current
+                    current = parent;
+                    parent = (current - 1) / 2;
+                }
+            }
+
+            private void downHeap(int pos) {
+                int current = pos;
+                int child = 2 * current + 1;
+
+                while (child < size && size > 0) {
+                    // compare the children if they exist
+                    if (child + 1 < size
+                            && timers[child + 1].when < timers[child].when) {
+                        child++;
+                    }
+
+                    // compare selected child with parent
+                    if (timers[current].when < timers[child].when) {
+                        break;
+                    }
+
+                    // swap the two
+                    TimerTask tmp = timers[current];
+                    timers[current] = timers[child];
+                    timers[child] = tmp;
+
+                    // update pos and current
+                    current = child;
+                    child = 2 * current + 1;
+                }
+            }
+
+            public void reset() {
+                timers = new TimerTask[DEFAULT_HEAP_SIZE];
+                size = 0;
+            }
+
+            public void adjustMinimum() {
+                downHeap(0);
+            }
+
+            public void deleteIfCancelled() {
+                for (int i = 0; i < size; i++) {
+                    if (timers[i].cancelled) {
+                        deletedCancelledNumber++;
+                        delete(i);
+                        // re-try this point
+                        i--;
                     }
                 }
-                z.parent = y;
-                if (y == null) {
-                    root = z;
-                } else if (z.task.getWhen() < y.task.getWhen()) {
-                    y.left = z;
-                } else {
-                    y.right = z;
-                }
             }
 
-            void delete(TimerNode z) {
-                TimerNode y = null, x = null;
-                if (z.left == null || z.right == null) {
-                    y = z;
-                } else {
-                    y = successor(z);
+            private int getTask(TimerTask task) {
+                for (int i = 0; i < timers.length; i++) {
+                    if (timers[i] == task) {
+                        return i;
+                    }
                 }
-                if (y.left != null) {
-                    x = y.left;
-                } else {
-                    x = y.right;
-                }
-                if (x != null) {
-                    x.parent = y.parent;
-                }
-                if (y.parent == null) {
-                    root = x;
-                } else if (y == y.parent.left) {
-                    y.parent.left = x;
-                } else {
-                    y.parent.right = x;
-                }
-                if (y != z) {
-                    z.task = y.task;
-                }
+                return -1;
             }
 
-            private TimerNode successor(TimerNode x) {
-                if (x.right != null) {
-                    return minimum(x.right);
-                }
-                TimerNode y = x.parent;
-                while (y != null && x == y.right) {
-                    x = y;
-                    y = y.parent;
-                }
-                return y;
-            }
-
-            private TimerNode minimum(TimerNode x) {
-                while (x.left != null) {
-                    x = x.left;
-                }
-                return x;
-            }
-
-            TimerNode minimum() {
-                return minimum(root);
-            }
         }
 
         /**
@@ -185,11 +183,11 @@
          * Vector consists of scheduled events, sorted according to
          * {@code when} field of TaskScheduled object.
          */
-        private TimerTree tasks = new TimerTree();
+        private TimerHeap tasks = new TimerHeap();
 
         /**
          * Starts a new timer.
-         * 
+         *
          * @param isDaemon
          */
         TimerImpl(boolean isDaemon) {
@@ -230,13 +228,12 @@
 
                     long currentTime = System.currentTimeMillis();
 
-                    TimerNode taskNode = tasks.minimum();
-                    task = taskNode.task;
+                    task = tasks.minimum();
                     long timeToSleep;
 
                     synchronized (task.lock) {
                         if (task.cancelled) {
-                            tasks.delete(taskNode);
+                            tasks.delete(0);
                             continue;
                         }
 
@@ -257,8 +254,12 @@
                     // no sleep is necessary before launching the task
 
                     synchronized (task.lock) {
+                        int pos = 0;
+                        if (tasks.minimum().when != task.when) {
+                            pos = tasks.getTask(task);
+                        }
                         if (task.cancelled) {
-                            tasks.delete(taskNode);
+                            tasks.delete(tasks.getTask(task));
                             continue;
                         }
 
@@ -266,7 +267,7 @@
                         task.setScheduledTime(task.when);
 
                         // remove task from queue
-                        tasks.delete(taskNode);
+                        tasks.delete(pos);
 
                         // set when the next task should be launched
                         if (task.period >= 0) {
@@ -299,7 +300,7 @@
 
         private void insertTask(TimerTask newTask) {
             // callers are synchronized
-            tasks.insert(new TimerNode(newTask));
+            tasks.insert(newTask);
             this.notify();
         }
 
@@ -308,7 +309,7 @@
          */
         public synchronized void cancel() {
             cancelled = true;
-            tasks = new TimerTree();
+            tasks.reset();
             this.notify();
         }
 
@@ -318,7 +319,7 @@
             }
             // callers are synchronized
             tasks.deletedCancelledNumber = 0;
-            tasks.root.deleteIfCancelled(tasks);
+            tasks.deleteIfCancelled();
             return tasks.deletedCancelledNumber;
         }
 
@@ -329,71 +330,72 @@
 
     // Used to finalize thread
     @SuppressWarnings("unused")
-    private Object finalizer = new Object() { // $NON-LOCK-1$
-        @Override
-        protected void finalize() {
-            synchronized (impl) {
-                impl.finished = true;
-                impl.notify();
-            }
-        }
-    };
+    private final Object finalizer;
 
     /**
      * Creates a new {@code Timer} which may be specified to be run as a daemon thread.
-     * 
+     *
      * @param isDaemon
      *            {@code true} if the {@code Timer}'s thread should be a daemon thread.
-     * @since Android 1.0
      */
     public Timer(boolean isDaemon) {
         // BEGIN android-changed
         impl = new TimerImpl("java.util.Timer", isDaemon);
         // END android-changed
+        finalizer = newFinalizer();
     }
 
     /**
      * Creates a new non-daemon {@code Timer}.
-     * 
-     * @since Android 1.0
      */
     public Timer() {
         // BEGIN android-changed
         impl = new TimerImpl("java.util.Timer", false);
         // END android-changed
+        finalizer = newFinalizer();
     }
 
     /**
      * Creates a new named {@code Timer} which may be specified to be run as a
      * daemon thread.
-     * 
+     *
      * @param name
      *            the name of the {@code Timer}.
      * @param isDaemon
      *            true if {@code Timer}'s thread should be a daemon thread.
-     * @since Android 1.0
      */
     public Timer(String name, boolean isDaemon) {
         impl = new TimerImpl(name, isDaemon);
+        finalizer = newFinalizer();
     }
 
     /**
      * Creates a new named {@code Timer} which does not run as a daemon thread.
-     * 
+     *
      * @param name
      *            the name of the Timer.
-     * @since Android 1.0
      */
     public Timer(String name) {
         impl = new TimerImpl(name, false);
+        finalizer = newFinalizer();
+    }
+
+    private Object newFinalizer() {
+        return new Object() { // $NON-LOCK-1$
+            @Override
+            protected void finalize() {
+                synchronized (impl) {
+                    impl.finished = true;
+                    impl.notify();
+                }
+            }
+        };
     }
 
     /**
      * Cancels the {@code Timer} and removes any scheduled tasks. If there is a
      * currently running task it is not affected. No more tasks may be scheduled
      * on this {@code Timer}. Subsequent calls do nothing.
-     * 
-     * @since Android 1.0
      */
     public void cancel() {
         impl.cancel();
@@ -401,12 +403,11 @@
 
     /**
      * Removes all canceled tasks from the task queue. If there are no
-     * other references on the tasks, then after this call they are free 
+     * other references on the tasks, then after this call they are free
      * to be garbage collected.
-     * 
+     *
      * @return the number of canceled tasks that were removed from the task
      *         queue.
-     * @since Android 1.0
      */
     public int purge() {
         synchronized (impl) {
@@ -417,17 +418,16 @@
     /**
      * Schedule a task for single execution. If {@code when} is less than the
      * current time, it will be scheduled to be executed as soon as possible.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param when
      *            time of execution.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code when.getTime() < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void schedule(TimerTask task, Date when) {
         if (when.getTime() < 0) {
@@ -439,17 +439,16 @@
 
     /**
      * Schedule a task for single execution after a specified delay.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param delay
      *            amount of time before execution.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code delay < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void schedule(TimerTask task, long delay) {
         if (delay < 0) {
@@ -460,19 +459,18 @@
 
     /**
      * Schedule a task for repeated fixed-delay execution after a specific delay.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param delay
      *            amount of time before first execution.
      * @param period
      *            amount of time between subsequent executions.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code delay < 0} or {@code period < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void schedule(TimerTask task, long delay, long period) {
         if (delay < 0 || period <= 0) {
@@ -484,19 +482,18 @@
     /**
      * Schedule a task for repeated fixed-delay execution after a specific time
      * has been reached.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param when
      *            time of first execution.
      * @param period
      *            amount of time between subsequent executions.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code when.getTime() < 0} or {@code period < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void schedule(TimerTask task, Date when, long period) {
         if (period <= 0 || when.getTime() < 0) {
@@ -509,19 +506,18 @@
     /**
      * Schedule a task for repeated fixed-rate execution after a specific delay
      * has passed.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param delay
      *            amount of time before first execution.
      * @param period
      *            amount of time between subsequent executions.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code delay < 0} or {@code period < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
         if (delay < 0 || period <= 0) {
@@ -533,19 +529,18 @@
     /**
      * Schedule a task for repeated fixed-rate execution after a specific time
      * has been reached.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param when
      *            time of first execution.
      * @param period
      *            amount of time between subsequent executions.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code when.getTime() < 0} or {@code period < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void scheduleAtFixedRate(TimerTask task, Date when, long period) {
         if (period <= 0 || when.getTime() < 0) {
@@ -555,13 +550,8 @@
         scheduleImpl(task, delay < 0 ? 0 : delay, period, true);
     }
 
-    /**
+    /*
      * Schedule a task.
-     * 
-     * @param task
-     * @param delay
-     * @param period
-     * @param fixed
      */
     private void scheduleImpl(TimerTask task, long delay, long period,
             boolean fixed) {
diff --git a/luni/src/main/java/java/util/TimerTask.java b/luni/src/main/java/java/util/TimerTask.java
index 384746f..319ed58 100644
--- a/luni/src/main/java/java/util/TimerTask.java
+++ b/luni/src/main/java/java/util/TimerTask.java
@@ -23,7 +23,6 @@
  * 
  * @see Timer
  * @see java.lang.Object#wait(long)
- * @since Android 1.0
  */
 public abstract class TimerTask implements Runnable {
     /* Lock object for synchronization. It's also used by Timer class. */
@@ -77,8 +76,6 @@
 
     /**
      * Creates a new {@code TimerTask}.
-     * 
-     * @since Android 1.0
      */
     protected TimerTask() {
         super();
@@ -91,7 +88,6 @@
      * 
      * @return {@code true} if the call prevented a scheduled execution
      *         from taking place, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean cancel() {
         synchronized (lock) {
@@ -107,7 +103,6 @@
      * have not yet run return an undefined value.
      * 
      * @return the most recent execution time.
-     * @since Android 1.0
      */
     public long scheduledExecutionTime() {
         synchronized (lock) {
@@ -118,8 +113,6 @@
     /**
      * The task to run should be specified in the implementation of the {@code run()}
      * method.
-     * 
-     * @since Android 1.0
      */
     public abstract void run();
 
diff --git a/luni/src/main/java/java/util/TooManyListenersException.java b/luni/src/main/java/java/util/TooManyListenersException.java
index 32b2133..8c044c0 100644
--- a/luni/src/main/java/java/util/TooManyListenersException.java
+++ b/luni/src/main/java/java/util/TooManyListenersException.java
@@ -22,8 +22,6 @@
  * A {@code TooManyListenersException} is thrown when an attempt is made to add
  * more than one listener to an event source which only supports a single
  * listener. It is also thrown when the same listener is added more than once.
- * 
- * @since Android 1.0
  */
 public class TooManyListenersException extends Exception {
 
diff --git a/luni/src/main/java/java/util/TreeMap.java b/luni/src/main/java/java/util/TreeMap.java
index e3dc5a7..b97821f 100644
--- a/luni/src/main/java/java/util/TreeMap.java
+++ b/luni/src/main/java/java/util/TreeMap.java
@@ -27,43 +27,124 @@
  * and removing) are supported. The values can be any objects. The keys can be
  * any objects which are comparable to each other either using their natural
  * order or a specified Comparator.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
-public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, Cloneable,
-        Serializable {
+public class TreeMap <K, V> extends AbstractMap<K, V> implements SortedMap<K, V>,
+                                                        Cloneable, Serializable {
     private static final long serialVersionUID = 919286545866124006L;
 
     transient int size;
 
-    transient Entry<K, V> root;
-
     private Comparator<? super K> comparator;
 
     transient int modCount;
 
     transient Set<Map.Entry<K, V>> entrySet;
 
-    /**
-     * Entry is an internal class which is used to hold the entries of a
-     * TreeMap.
-     */
-    static class Entry<K, V> extends MapEntry<K, V> {
-        Entry<K, V> parent, left, right;
+    transient Node<K, V> root;
+    
+class MapEntry implements Map.Entry<K, V>, Cloneable {
+		
+		final int offset;
+		final Node<K, V> node;
+		final K key;
+		
+	    MapEntry(Node<K, V> node, int offset) {
+	    	this.node = node;
+	    	this.offset = offset;
+	    	key = node.keys[offset];
+	    }
 
+	    @Override
+	    public Object clone() {
+	        try {
+	            return super.clone();
+	        } catch (CloneNotSupportedException e) {
+	            return null;
+	        }
+	    }
+
+	    @Override
+	    public boolean equals(Object object) {
+	        if (this == object) {
+	            return true;
+	        }
+	        if (object instanceof Map.Entry) {
+	            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;	            
+	            V value = getValue();
+	            return (key == null ? entry.getKey() == null : key.equals(entry
+	                    .getKey()))
+	                    && (value == null ? entry.getValue() == null : value
+	                            .equals(entry.getValue()));
+	        }
+	        return false;
+	    }
+
+	    public K getKey() {
+	        return key;
+	    }
+
+	    public V getValue() {
+	    	if (node.keys[offset] == key) {
+	    		return node.values[offset];
+	    	}
+	    	if (containsKey(key)) {
+	    		return get(key);
+	    	}
+	    	throw new IllegalStateException();
+	    }
+
+	    @Override
+	    public int hashCode() {
+	    	V value = getValue();
+	        return (key == null ? 0 : key.hashCode())
+	                ^ (value == null ? 0 : value.hashCode());
+	    }
+
+	    public V setValue(V object) {
+	    	if (node.keys[offset] == key) {
+	    		V res = node.values[offset];
+	    		node.values[offset] = object;
+	    		return res;
+	    	}
+	    	if (containsKey(key)) {
+	    		return put(key, object);
+	    	}
+	    	throw new IllegalStateException();
+	    }
+
+	    @Override
+	    public String toString() {
+	        return key + "=" + getValue();
+	    }
+	}
+
+    static class Node <K,V> implements Cloneable {
+        static final int NODE_SIZE = 64;
+        Node<K, V> prev, next;
+        Node<K, V> parent, left, right;
+        V[] values;
+        K[] keys;
+        int left_idx = 0;
+        int right_idx = -1;
+        int size = 0;
         boolean color;
 
-        Entry(K key) {
-            super(key);
-        }
-
-        Entry(K key, V value) {
-            super(key, value);
+        public Node() {
+            keys = (K[]) new Object[NODE_SIZE];
+            values = (V[]) new Object[NODE_SIZE];
         }
 
         @SuppressWarnings("unchecked")
-        Entry<K, V> clone(Entry<K, V> parent) {
-            Entry<K, V> clone = (Entry<K, V>) super.clone();
+        Node<K, V> clone(Node<K, V> parent) throws CloneNotSupportedException {
+            Node<K, V> clone = (Node<K, V>) super.clone();
+            clone.keys   = (K[]) new Object[NODE_SIZE];
+            clone.values = (V[]) new Object[NODE_SIZE];
+            System.arraycopy(keys,   0, clone.keys,   0, keys.length);
+            System.arraycopy(values, 0, clone.values, 0, values.length);
+            clone.left_idx  = left_idx;
+            clone.right_idx = right_idx;
             clone.parent = parent;
             if (left != null) {
                 clone.left = left.clone(clone);
@@ -71,45 +152,45 @@
             if (right != null) {
                 clone.right = right.clone(clone);
             }
+            clone.prev = null;
+            clone.next = null;
             return clone;
         }
     }
-    
+
     @SuppressWarnings("unchecked")
-    private static <T> Comparable<T> toComparable(T obj) {
-        return (Comparable<T>)obj;
+     private static <T> Comparable<T> toComparable(T obj) {
+        return (Comparable) obj;
     }
 
-    private static class AbstractMapIterator <K,V> {
+    static class AbstractMapIterator <K,V> {
         TreeMap<K, V> backingMap;
         int expectedModCount;
-        TreeMap.Entry<K, V> node;
-        TreeMap.Entry<K, V> lastNode;
+        Node<K, V> node;
+        Node<K, V> lastNode;
+        int offset;
+        int lastOffset;
 
-        AbstractMapIterator(TreeMap<K, V> map, Entry<K, V> startNode) {
+        AbstractMapIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
             backingMap = map;
             expectedModCount = map.modCount;
             node = startNode;
+            offset = startOffset;
+        }
+
+        AbstractMapIterator(TreeMap<K, V> map, Node<K, V> startNode) {
+            this(map, startNode, startNode != null ?
+                                 startNode.right_idx - startNode.left_idx : 0);
+        }
+
+        AbstractMapIterator(TreeMap<K, V> map) {
+            this(map, minimum(map.root));
         }
 
         public boolean hasNext() {
             return node != null;
         }
 
-        final public void remove() {
-            if (expectedModCount == backingMap.modCount) {
-                if (lastNode != null) {
-                    backingMap.rbDelete(lastNode);
-                    lastNode = null;
-                    expectedModCount++;
-                } else {
-                    throw new IllegalStateException();
-                }
-            } else {
-                throw new ConcurrentModificationException();
-            }
-        }
-
         final void makeNext() {
             if (expectedModCount != backingMap.modCount) {
                 throw new ConcurrentModificationException();
@@ -117,564 +198,777 @@
                 throw new NoSuchElementException();
             }
             lastNode = node;
-            node = TreeMap.successor(node);
+            lastOffset = offset;
+            if (offset != 0) {
+                offset--;
+            } else {
+                node = node.next;
+                if (node != null) {
+                    offset = node.right_idx - node.left_idx;
+                }
             }
         }
 
-        private static class UnboundedEntryIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<Map.Entry<K, V>> {
-
-            UnboundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode) {
-                super(map, startNode);
-            }
-
-            UnboundedEntryIterator(TreeMap<K, V> map) {
-                super(map, map.root == null ? null : TreeMap.minimum(map.root));
-            }
-
-            public Map.Entry<K, V> next() {
-                makeNext();
-                return lastNode;
+        final public void remove() {
+            if (expectedModCount == backingMap.modCount) {
+                if (lastNode != null) {
+                    int idx = lastNode.right_idx - lastOffset;
+                    backingMap.removeFromIterator(lastNode, idx);
+                    lastNode = null;
+                    expectedModCount++;
+                } else {
+                    throw new IllegalStateException();
+                }
+            } else {
+                throw new ConcurrentModificationException();
             }
         }
+    }
 
-        static class UnboundedKeyIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<K> {
-            public UnboundedKeyIterator(TreeMap<K, V> treeMap, Entry<K, V> entry) {
-                super(treeMap, entry);
-            }
+    static class UnboundedEntryIterator <K, V> extends AbstractMapIterator<K, V>
+                                            implements Iterator<Map.Entry<K, V>> {
 
-            public UnboundedKeyIterator(TreeMap<K, V> map) {
-                super(map, map.root == null ? null : TreeMap.minimum(map.root));
-            }
-
-            public K next() {
-                makeNext();
-                return lastNode.key;
-            }
+        UnboundedEntryIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
+            super(map, startNode, startOffset);
         }
 
-        static class UnboundedValueIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<V> {
-     
-            public UnboundedValueIterator(TreeMap<K, V> treeMap, Entry<K, V> startNode) {
-                super(treeMap, startNode);
-            }
-     
-            public UnboundedValueIterator(TreeMap<K, V> map) {
-                super(map, map.root == null ? null : TreeMap.minimum(map.root));
-            }
-     
-            public V next() {
-                makeNext();
-                return lastNode.value;
-            }
+        UnboundedEntryIterator(TreeMap<K, V> map) {
+            super(map);
         }
 
-        private static class ComparatorBoundedIterator<K, V> extends AbstractMapIterator<K, V> {
-            private final  K endKey;
+        public Map.Entry<K, V> next() {
+            makeNext();
+            int idx = lastNode.right_idx - lastOffset;
+            return backingMap.new MapEntry(lastNode, idx);
+        }
+    }
 
-            private final Comparator<? super K> cmp;
+    static class UnboundedKeyIterator <K, V> extends AbstractMapIterator<K, V>
+                                                          implements Iterator<K> {
 
-        ComparatorBoundedIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
-            super(map, startNode);
+        UnboundedKeyIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
+            super(map, startNode, startOffset);
+        }
+
+        UnboundedKeyIterator(TreeMap<K, V> map) {
+            super(map);
+        }
+
+        public K next() {
+            makeNext();
+            return lastNode.keys[lastNode.right_idx - lastOffset];
+        }
+    }
+
+    static class UnboundedValueIterator <K, V> extends AbstractMapIterator<K, V>
+                                                          implements Iterator<V> {
+
+        UnboundedValueIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
+            super(map, startNode, startOffset);
+        }
+
+        UnboundedValueIterator(TreeMap<K, V> map) {
+            super(map);
+        }
+
+        public V next() {
+            makeNext();
+            return lastNode.values[lastNode.right_idx - lastOffset];
+        }
+    }
+
+    static class BoundedMapIterator <K, V> extends AbstractMapIterator<K, V> {
+
+        Node<K, V> finalNode;
+        int finalOffset;
+
+        BoundedMapIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
+                           Node<K, V> finalNode, int finalOffset) {
+            super(map, finalNode==null? null : startNode, startOffset);
+            this.finalNode = finalNode;
+            this.finalOffset = finalOffset;
+        }
+
+        BoundedMapIterator(Node<K, V> startNode, TreeMap<K, V> map,
+                           Node<K, V> finalNode, int finalOffset) {
+            this(startNode, startNode != null ?
+                            startNode.right_idx - startNode.left_idx : 0,
+                            map, finalNode, finalOffset);
+        }
+
+        BoundedMapIterator(Node<K, V> startNode, int startOffset,
+                           TreeMap<K, V> map, Node<K, V> finalNode) {
+            this(startNode, startOffset, map, finalNode,
+                         finalNode.right_idx - finalNode.left_idx);
+        }
+
+        void makeBoundedNext() {
+            makeNext();
+            if (lastNode == finalNode && lastOffset == finalOffset) {
+                node = null;
+            }
+        }
+    }
+
+    static class BoundedEntryIterator <K, V> extends BoundedMapIterator<K, V>
+                                          implements Iterator<Map.Entry<K, V>> {
+
+        public BoundedEntryIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
+                                    Node<K, V> finalNode, int finalOffset) {
+            super(startNode, startOffset, map, finalNode, finalOffset);
+        }
+
+        public Map.Entry<K, V> next() {
+            makeBoundedNext();
+            int idx = lastNode.right_idx - lastOffset;
+            return backingMap.new MapEntry(lastNode, idx);
+        }
+    }
+
+    static class BoundedKeyIterator <K, V> extends BoundedMapIterator<K, V>
+                                                     implements Iterator<K> {
+
+        public BoundedKeyIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
+                                  Node<K, V> finalNode, int finalOffset) {
+            super(startNode, startOffset, map, finalNode, finalOffset);
+        }
+
+        public K next() {
+            makeBoundedNext();
+            return lastNode.keys[lastNode.right_idx - lastOffset];
+        }
+    }
+
+    static class BoundedValueIterator <K, V> extends BoundedMapIterator<K, V>
+                                                       implements Iterator<V> {
+
+        public BoundedValueIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
+                                    Node<K, V> finalNode, int finalOffset) {
+            super(startNode, startOffset, map, finalNode, finalOffset);
+        }
+
+        public V next() {
+            makeBoundedNext();
+            return lastNode.values[lastNode.right_idx - lastOffset];
+        }
+    }
+
+    static final class SubMap <K,V> extends AbstractMap<K, V>
+                                 implements SortedMap<K, V>, Serializable {
+        private static final long serialVersionUID = -6520786458950516097L;
+
+        private TreeMap<K, V> backingMap;
+
+        boolean hasStart, hasEnd;
+        K startKey, endKey;
+        transient Set<Map.Entry<K, V>> entrySet = null;
+        transient int firstKeyModCount = -1;
+        transient int lastKeyModCount = -1;
+        transient Node<K, V> firstKeyNode;
+        transient int firstKeyIndex;
+        transient Node<K, V> lastKeyNode;
+        transient int lastKeyIndex;
+
+        SubMap(K start, TreeMap<K, V> map) {
+            backingMap = map;
+            hasStart = true;
+            startKey = start;
+        }
+
+        SubMap(K start, TreeMap<K, V> map, K end) {
+            backingMap = map;
+            hasStart = hasEnd = true;
+            startKey = start;
             endKey = end;
-            cmp = map.comparator();
         }
 
-        final void cleanNext() {
-            if (node != null && cmp.compare(endKey, node.key) <= 0) {
-                node = null;
+        SubMap(TreeMap<K, V> map, K end) {
+            backingMap = map;
+            hasEnd = true;
+            endKey = end;
+        }
+
+        private void checkRange(K key) {
+            Comparator<? super K> cmp = backingMap.comparator;
+            if (cmp == null) {
+                Comparable<K> object = toComparable(key);
+                if (hasStart && object.compareTo(startKey) < 0) {
+                    throw new IllegalArgumentException();
+                }
+                if (hasEnd && object.compareTo(endKey) > 0) {
+                    throw new IllegalArgumentException();
+                }
+            } else {
+                if (hasStart
+                    && backingMap.comparator().compare(key, startKey) < 0) {
+                    throw new IllegalArgumentException();
+                }
+                if (hasEnd && backingMap.comparator().compare(key, endKey) > 0) {
+                    throw new IllegalArgumentException();
+                }
             }
         }
 
+        private boolean isInRange(K key) {
+            Comparator<? super K> cmp = backingMap.comparator;
+            if (cmp == null) {
+                Comparable<K> object = toComparable(key);
+                if (hasStart && object.compareTo(startKey) < 0) {
+                    return false;
+                }
+                if (hasEnd && object.compareTo(endKey) >= 0) {
+                    return false;
+                }
+            } else {
+                if (hasStart && cmp.compare(key, startKey) < 0) {
+                    return false;
+                }
+                if (hasEnd && cmp.compare(key, endKey) >= 0) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private boolean checkUpperBound(K key) {
+            if (hasEnd) {
+                Comparator<? super K> cmp = backingMap.comparator;
+                if (cmp == null) {
+                    return (toComparable(key).compareTo(endKey) < 0);
+                }
+                return (cmp.compare(key, endKey) < 0);
+            }
+            return true;
+        }
+
+        private boolean checkLowerBound(K key) {
+            if (hasStart) {
+                Comparator<? super K> cmp = backingMap.comparator;
+                if (cmp == null) {
+                    return (toComparable(key).compareTo(startKey) >= 0);
+                }
+                return (cmp.compare(key, startKey) >= 0);
+            }
+            return true;
+        }
+
+        public Comparator<? super K> comparator() {
+            return backingMap.comparator();
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean containsKey(Object key) {
+            if (isInRange((K) key)) {
+                return backingMap.containsKey(key);
+            }
+            return false;
+        }
+
         @Override
-        public boolean hasNext() {
-            return (node != null && endKey != null) && (cmp.compare(node.key, endKey) < 0);
-        }
-    }
-
-    private static class ComparatorBoundedEntryIterator<K, V> extends
-            ComparatorBoundedIterator<K, V> implements Iterator<Map.Entry<K, V>> {
-
-        ComparatorBoundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
-            super(map, startNode, end);
-        }
-
-        public Map.Entry<K, V> next() {
-            makeNext();
-            cleanNext();
-            return lastNode;
-        }
-    }
-
-    private static class ComparatorBoundedKeyIterator<K, V> extends
-            ComparatorBoundedIterator<K, V> implements Iterator<K> {
-
-        ComparatorBoundedKeyIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
-            super(map, startNode, end);
-        }
-
-        public K next() {
-            makeNext();
-            cleanNext();
-            return lastNode.key;
-        }
-    }
-
-    private static class ComparatorBoundedValueIterator<K, V> extends
-            ComparatorBoundedIterator<K, V> implements Iterator<V> {
-
-        ComparatorBoundedValueIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
-            super(map, startNode, end);
-        }
-
-        public V next() {
-            makeNext();
-            cleanNext();
-            return lastNode.value;
-        }
-    }
-
-    private static class ComparableBoundedIterator<K, V> extends AbstractMapIterator<K, V> {
-        private final Comparable<K> endKey;
-
-        public ComparableBoundedIterator(TreeMap<K, V> treeMap, Entry<K, V> entry,
-                Comparable<K> endKey) {
-            super(treeMap, entry);
-            this.endKey = endKey;
-        }
-
-        final void cleanNext() {
-            if ((node != null) && (endKey.compareTo(node.key) <= 0)) {
-                node = null;
-            }
+         public void clear() {
+            keySet().clear();
         }
 
         @Override
-        public boolean hasNext() {
-            return (node != null) && (endKey.compareTo(node.key) > 0);
-        }
-    }
-
-    private static class ComparableBoundedEntryIterator<K, V> extends
-            ComparableBoundedIterator<K, V> implements Iterator<Map.Entry<K, V>> {
-
-        ComparableBoundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode,
-                Comparable<K> end) {
-            super(map, startNode, end);
-        }
-
-        public Map.Entry<K, V> next() {
-            makeNext();
-            cleanNext();
-            return lastNode;
-        }
-
-    }
-
-    private static class ComparableBoundedKeyIterator<K, V> extends
-            ComparableBoundedIterator<K, V> implements Iterator<K> {
-
-        ComparableBoundedKeyIterator(TreeMap<K, V> map, Entry<K, V> startNode, Comparable<K> end) {
-            super(map, startNode, end);
-        }
-
-        public K next() {
-            makeNext();
-            cleanNext();
-            return lastNode.key;
-        }
-    }
-
-    private static class ComparableBoundedValueIterator<K, V> extends
-            ComparableBoundedIterator<K, V> implements Iterator<V> {
-
-        ComparableBoundedValueIterator(TreeMap<K, V> map, Entry<K, V> startNode,
-                Comparable<K> end) {
-            super(map, startNode, end);
-        }
-
-        public V next() {
-            makeNext();
-            cleanNext();
-            return lastNode.value;
-        }
-    }
-
-        static final class SubMap<K,V> extends AbstractMap<K,V> implements SortedMap<K,V>, Serializable {
-            private static final long serialVersionUID = -6520786458950516097L;
-
-            private TreeMap<K,V> backingMap;
-
-            boolean hasStart, hasEnd;
-
-            K startKey, endKey;
-
-            transient Set<Map.Entry<K,V>> entrySet = null;
-
-            SubMap(K start, TreeMap<K,V> map) {
-                backingMap = map;
-                hasStart = true;
-                startKey = start;
-            }
-
-            SubMap(K start, TreeMap<K,V> map, K end) {
-                backingMap = map;
-                hasStart = hasEnd = true;
-                startKey = start;
-                endKey = end;
-            }
-            
-            SubMap(TreeMap<K,V> map, K end) {
-                backingMap = map;
-                hasEnd = true;
-                endKey = end;
-            }
-
-            private void checkRange(K key) {
-                Comparator<? super K> cmp = backingMap.comparator;
-                if (cmp == null) {
-                    Comparable<K> object = toComparable(key);
-                    if (hasStart && object.compareTo(startKey) < 0) {
-                        throw new IllegalArgumentException();
+         public boolean containsValue(Object value) {
+            Iterator<V> it = values().iterator();
+            if (value != null) {
+                while (it.hasNext()) {
+                    if (value.equals(it.next())) {
+                        return true;
                     }
-                    if (hasEnd && object.compareTo(endKey) > 0) {
-                        throw new IllegalArgumentException();
+                }
+            } else {
+                while (it.hasNext()) {
+                    if (it.next() == null) {
+                        return true;
                     }
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public Set<Map.Entry<K, V>> entrySet() {
+            if (entrySet == null) {
+                entrySet = new SubMapEntrySet<K, V>(this);
+            }
+            return entrySet;
+        }
+
+        private void setFirstKey() {
+            if (firstKeyModCount == backingMap.modCount) {
+                return;
+            }
+            Comparable<K> object = backingMap.comparator == null ?
+                                   toComparable((K) startKey) : null;
+            K key = (K) startKey;
+            Node<K, V> node = backingMap.root;
+            Node<K, V> foundNode = null;
+            int foundIndex = -1;
+            TOP_LOOP:
+            while (node != null) {
+                K[] keys = node.keys;
+                int left_idx = node.left_idx;
+                int result = backingMap.cmp(object, key, keys[left_idx]);
+                if (result < 0) {
+                    foundNode = node;
+                    foundIndex = left_idx;
+                    node = node.left;
+                } else if (result == 0) {
+                    foundNode = node;
+                    foundIndex = left_idx;
+                    break;
                 } else {
-                    if (hasStart
-                            && backingMap.comparator().compare(key, startKey) < 0) {
-                        throw new IllegalArgumentException();
+                    int right_idx = node.right_idx;
+                    if (left_idx != right_idx) {
+                        result = backingMap.cmp(object, key, keys[right_idx]);
                     }
-                    if (hasEnd && backingMap.comparator().compare(key, endKey) > 0) {
-                        throw new IllegalArgumentException();
+                    if (result > 0) {
+                        node = node.right;
+                    } else if (result == 0) {
+                        foundNode = node;
+                        foundIndex = right_idx;
+                        break;
+                    } else { /*search in node*/
+                        foundNode = node;
+                        foundIndex = right_idx;
+                        int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                        while (low <= high) {
+                            mid = (low + high) >> 1;
+                            result = backingMap.cmp(object, key, keys[mid]);
+                            if (result > 0) {
+                                low = mid + 1;
+                            } else if (result == 0) {
+                                foundNode = node;
+                                foundIndex = mid;
+                                break TOP_LOOP;
+                            } else {
+                                foundNode = node;
+                                foundIndex = mid;
+                                high = mid - 1;
+                            }
+                        }
+                        break TOP_LOOP;
                     }
                 }
             }
-
-            private boolean isInRange(K key) {
-                Comparator<? super K> cmp = backingMap.comparator;
-                if (cmp == null) {
-                    Comparable<K> object = toComparable(key);
-                    if (hasStart && object.compareTo(startKey) < 0) {
-                        return false;
-                    }
-                    if (hasEnd && object.compareTo(endKey) >= 0) {
-                        return false;
-                    }
-                } else {
-                    if (hasStart && cmp.compare(key, startKey) < 0) {
-                        return false;
-                    }
-                    if (hasEnd && cmp.compare(key, endKey) >= 0) {
-                        return false;
-                    }
-                }
-                return true;
+            if (foundNode != null && !checkUpperBound(foundNode.keys[foundIndex])) {
+                foundNode = null;
             }
+            firstKeyNode = foundNode;
+            firstKeyIndex = foundIndex;
+            firstKeyModCount = backingMap.modCount;
+        }
 
-            private boolean checkUpperBound(K key) {
-                if (hasEnd) {
-                    Comparator<? super K> cmp = backingMap.comparator;
-                    if (cmp == null) {
-                        return (toComparable(key).compareTo(endKey) < 0);
-                    }
-                    return (cmp.compare(key, endKey) < 0);
-                }
-                return true;
-            }
-
-            private boolean checkLowerBound(K key) {
-                if (hasStart) {
-                    Comparator<? super K> cmp = backingMap.comparator;
-                    if (cmp == null) {
-                        return (toComparable(key).compareTo(startKey) >= 0);
-                    }
-                    return (cmp.compare(key, startKey) >= 0);
-                }
-                return true;
-            }
-
-            public Comparator<? super K> comparator() {
-                return backingMap.comparator();
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public boolean containsKey(Object key) {
-                if (isInRange((K)key)) {
-                    return backingMap.containsKey(key);
-                }
-                return false;
-            }
-
-            @Override
-            public Set<Map.Entry<K,V>> entrySet() {
-                if(entrySet==null) {
-                    entrySet = new SubMapEntrySet<K,V>(this);
-                }
-                return entrySet;
-            }
-
-            public K firstKey() {
-                TreeMap.Entry<K,V> node = firstEntry();
-                if (node != null ) {
-                    return node.key;
-                }
-                throw new NoSuchElementException();
-            }
-
-            TreeMap.Entry<K,V> firstEntry() {
+        public K firstKey() {
+            if (backingMap.size > 0) {
                 if (!hasStart) {
-                    TreeMap.Entry<K,V> root = backingMap.root;
-                    return (root == null) ? null : minimum(backingMap.root);
-                }
-                TreeMap.Entry<K,V> node = backingMap.findAfter(startKey);
-                if (node != null && checkUpperBound(node.key)) {
-                    return node;
-                }
-                return null;
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public V get(Object key) {
-                if (isInRange((K)key)) {
-                    return backingMap.get(key);
-                }
-                return null;
-            }
-
-            public SortedMap<K,V> headMap(K endKey) {
-                checkRange(endKey);
-                if (hasStart) {
-                    return new SubMap<K,V>(startKey, backingMap, endKey);
-                }
-                return new SubMap<K,V>(backingMap, endKey);
-            }
-
-            @Override
-            public boolean isEmpty() {
-                if (hasStart) {
-                    TreeMap.Entry<K,V> node = backingMap.findAfter(startKey);
-                    return node == null || !checkUpperBound(node.key);
-                }
-                return backingMap.findBefore(endKey) == null;
-            }
-
-            @Override
-            public Set<K> keySet() {
-                if (keySet == null) {
-                    keySet = new SubMapKeySet<K,V>(this);
-                }
-                return keySet;
-            }
-
-            public K lastKey() {
-                if (!hasEnd) {
-                    return backingMap.lastKey();
-                }
-                TreeMap.Entry<K,V> node = backingMap.findBefore(endKey);
-                if (node != null && checkLowerBound(node.key)) {
-                    return node.key;
-                }
-                throw new NoSuchElementException();
-            }
-
-            @Override
-            public V put(K key, V value) {
-                if (isInRange(key)) {
-                    return backingMap.put(key, value);
-                }
-                throw new IllegalArgumentException();
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public V remove(Object key) {
-                if (isInRange((K)key)) {
-                    return backingMap.remove(key);
-                }
-                return null;
-            }
-
-            public SortedMap<K,V> subMap(K startKey, K endKey) {
-                checkRange(startKey);
-                checkRange(endKey);
-                Comparator<? super K> c = backingMap.comparator();
-                if (c == null) {
-                    if (toComparable(startKey).compareTo(endKey) <= 0) {
-                        return new SubMap<K,V>(startKey, backingMap, endKey);
+                    Node<K, V> node = minimum(backingMap.root);
+                    if (node != null && checkUpperBound(node.keys[node.left_idx])) {
+                        return node.keys[node.left_idx];
                     }
                 } else {
-                    if (c.compare(startKey, endKey) <= 0) {
-                        return new SubMap<K,V>(startKey, backingMap, endKey);
+                    setFirstKey();
+                    if (firstKeyNode != null) {
+                        return firstKeyNode.keys[firstKeyIndex];
                     }
                 }
-                throw new IllegalArgumentException();
             }
+            throw new NoSuchElementException();
+        }
 
-            public SortedMap<K,V> tailMap(K startKey) {
-                checkRange(startKey);
-                if (hasEnd) {
-                    return new SubMap<K,V>(startKey, backingMap, endKey);
-                }
-                return new SubMap<K,V>(startKey, backingMap);
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public V get(Object key) {
+            if (isInRange((K) key)) {
+                return backingMap.get(key);
             }
+            return null;
+        }
 
-            @Override
-            public Collection<V> values() {
-                if(valuesCollection==null) {
-                    valuesCollection = new SubMapValuesCollection<K,V>(this);
-                }
-                return valuesCollection;
+        public SortedMap<K, V> headMap(K endKey) {
+            checkRange(endKey);
+            if (hasStart) {
+                return new SubMap<K, V>(startKey, backingMap, endKey);
+            }
+            return new SubMap<K, V>(backingMap, endKey);
+        }
+
+        @Override
+        public boolean isEmpty() {
+            if (hasStart) {
+                setFirstKey();
+                return firstKeyNode == null;
+            } else {
+                setLastKey();
+                return lastKeyNode == null;
             }
         }
 
-        static class SubMapEntrySet<K,V> extends AbstractSet<Map.Entry<K,V>> implements Set<Map.Entry<K,V>> {
-            SubMap<K,V> subMap;
-
-            SubMapEntrySet(SubMap<K,V> map) {
-                subMap = map;
+        @Override
+        public Set<K> keySet() {
+            if (keySet == null) {
+                keySet = new SubMapKeySet<K, V>(this);
             }
-
-            @Override
-            public boolean isEmpty() {
-                return subMap.isEmpty();
-            }
-
-            @Override
-            public Iterator<Map.Entry<K,V>> iterator() {
-                TreeMap.Entry<K,V> startNode = subMap.firstEntry();
-                if (subMap.hasEnd) {
-                    Comparator<? super K> cmp = subMap.comparator();
-                    if (cmp == null) {
-                        return new ComparableBoundedEntryIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey));
-                    }
-                    return new ComparatorBoundedEntryIterator<K,V>(subMap.backingMap, startNode, subMap.endKey);
-                }
-                return new UnboundedEntryIterator<K,V>(subMap.backingMap, startNode);
-            }
-
-            @Override
-            public int size() {
-                int size = 0;
-                Iterator<Map.Entry<K,V>> it = iterator();
-                while (it.hasNext()) {
-                    size++;
-                    it.next();
-                }
-                return size;
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public boolean contains(Object object) {
-                if (object instanceof Map.Entry) {
-                    Map.Entry<K,V> entry = (Map.Entry<K,V>) object;
-                    K key = entry.getKey();
-                    if (subMap.isInRange(key)) {
-                        V v1 = subMap.get(key), v2 = entry.getValue();
-                        return v1 == null ? v2 == null : v1.equals(v2);
-                    }
-                }
-                return false;
-            }
-
+            return keySet;
         }
 
-        static class SubMapKeySet<K,V> extends  AbstractSet<K> implements Set<K> {
-            SubMap<K,V> subMap;
-
-            SubMapKeySet(SubMap<K,V> map) {
-                subMap = map;
+        private void setLastKey() {
+            if (lastKeyModCount == backingMap.modCount) {
+                return;
             }
-
-            @Override
-            public boolean contains(Object object) {
-                return subMap.containsKey(object);
-            }
-
-            @Override
-            public boolean isEmpty() {
-                return subMap.isEmpty();
-            }
-
-            @Override
-            public int size() {
-                int size = 0;
-                Iterator<K> it = iterator();
-                while (it.hasNext()) {
-                    size++;
-                    it.next();
-                }
-                return size;
-            }
-
-            @Override
-            public Iterator<K> iterator() {
-                TreeMap.Entry<K,V> startNode = subMap.firstEntry();
-                if (subMap.hasEnd) {
-                    Comparator<? super K> cmp = subMap.comparator();
-                    if (cmp == null) {
-                        return new ComparableBoundedKeyIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey));
+            Comparable<K> object = backingMap.comparator == null ?
+                                   toComparable((K) endKey) : null;
+            K key = (K) endKey;
+            Node<K, V> node = backingMap.root;
+            Node<K, V> foundNode = null;
+            int foundIndex = -1;
+            TOP_LOOP:
+            while (node != null) {
+                K[] keys = node.keys;
+                int left_idx = node.left_idx;
+                int result = backingMap.cmp(object, key, keys[left_idx]);
+                if (result <= 0) {
+                    node = node.left;
+                } else {
+                    int right_idx = node.right_idx;
+                    if (left_idx != right_idx) {
+                        result = backingMap.cmp(object, key, keys[right_idx]);
                     }
-                    return new ComparatorBoundedKeyIterator<K,V>(subMap.backingMap, startNode, subMap.endKey);
+                    if (result > 0) {
+                        foundNode = node;
+                        foundIndex = right_idx;
+                        node = node.right;
+                    } else if (result == 0) {
+                        if (node.left_idx == node.right_idx) {
+                            foundNode = node.prev;
+                            if (foundNode != null) {
+                                foundIndex = foundNode.right_idx - 1;
+                            }
+                        } else {
+                            foundNode = node;
+                            foundIndex = right_idx - 1;
+                        }
+                        break;
+                    } else { /*search in node*/
+                        foundNode = node;
+                        foundIndex = left_idx;
+                        int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                        while (low <= high) {
+                            mid = (low + high) >> 1;
+                            result = backingMap.cmp(object, key, keys[mid]);
+                            if (result > 0) {
+                                foundNode = node;
+                                foundIndex = mid;
+                                low = mid + 1;
+                            } else if (result == 0) {
+                                foundNode = node;
+                                foundIndex = mid - 1;
+                                break TOP_LOOP;
+                            } else {
+                                high = mid - 1;
+                            }
+                        }
+                        break TOP_LOOP;
+                    }
                 }
-                return new UnboundedKeyIterator<K,V>(subMap.backingMap, startNode);
             }
+            if (foundNode != null && !checkLowerBound(foundNode.keys[foundIndex])) {
+                foundNode = null;
+            }
+            lastKeyNode = foundNode;
+            lastKeyIndex = foundIndex;
+            lastKeyModCount = backingMap.modCount;
         }
 
-        static class SubMapValuesCollection<K,V> extends AbstractCollection<V> {
-            SubMap<K,V> subMap;
-
-            public SubMapValuesCollection(SubMap<K,V> subMap) {
-                this.subMap = subMap;
-            }
-
-            @Override
-            public boolean isEmpty() {
-                return subMap.isEmpty();
-            }
-
-            @Override
-            public Iterator<V> iterator() {
-                TreeMap.Entry<K,V> startNode = subMap.firstEntry();
-                if (subMap.hasEnd) {
-                    Comparator<? super K> cmp = subMap.comparator();
-                    if (cmp == null) {
-                        return new ComparableBoundedValueIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey));
+        public K lastKey() {
+            if (backingMap.size > 0) {
+                if (!hasEnd) {
+                    Node<K, V> node = maximum(backingMap.root);
+                    if (node != null && checkLowerBound(node.keys[node.right_idx])) {
+                        return node.keys[node.right_idx];
                     }
-                    return new ComparatorBoundedValueIterator<K,V>(subMap.backingMap, startNode, subMap.endKey);
+                } else {
+                    setLastKey();
+                    if (lastKeyNode != null) {
+                        return lastKeyNode.keys[lastKeyIndex];
+                    }
                 }
-                return new UnboundedValueIterator<K,V>(subMap.backingMap, startNode);
             }
-
-            @Override
-            public int size() {
-                int cnt = 0;
-                for (Iterator<V> it = iterator(); it.hasNext();) {
-                    it.next();
-                    cnt++;
-                }
-                return cnt;
-            }
+            throw new NoSuchElementException();
         }
 
+
+        @Override
+        public V put(K key, V value) {
+            if (isInRange(key)) {
+                return backingMap.put(key, value);
+            }
+            throw new IllegalArgumentException();
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public V remove(Object key) {
+            if (isInRange((K) key)) {
+                return backingMap.remove(key);
+            }
+            return null;
+        }
+
+        public SortedMap<K, V> subMap(K startKey, K endKey) {
+            checkRange(startKey);
+            checkRange(endKey);
+            Comparator<? super K> c = backingMap.comparator();
+            if (c == null) {
+                if (toComparable(startKey).compareTo(endKey) <= 0) {
+                    return new SubMap<K, V>(startKey, backingMap, endKey);
+                }
+            } else {
+                if (c.compare(startKey, endKey) <= 0) {
+                    return new SubMap<K, V>(startKey, backingMap, endKey);
+                }
+            }
+            throw new IllegalArgumentException();
+        }
+
+        public SortedMap<K, V> tailMap(K startKey) {
+            checkRange(startKey);
+            if (hasEnd) {
+                return new SubMap<K, V>(startKey, backingMap, endKey);
+            }
+            return new SubMap<K, V>(startKey, backingMap);
+        }
+
+        @Override
+        public Collection<V> values() {
+            if (valuesCollection == null) {
+                valuesCollection = new SubMapValuesCollection<K, V>(this);
+            }
+            return valuesCollection;
+        }
+
+        public int size() {
+            Node<K, V> from, to;
+            int fromIndex, toIndex;
+            if (hasStart) {
+                setFirstKey();
+                from = firstKeyNode;
+                fromIndex = firstKeyIndex;
+            } else {
+                from = minimum(backingMap.root);
+                fromIndex = from == null ? 0 : from.left_idx;
+            }
+            if (from == null) {
+                return 0;
+            }
+            if (hasEnd) {
+                setLastKey();
+                to = lastKeyNode;
+                toIndex = lastKeyIndex;
+            } else {
+                to = maximum(backingMap.root);
+                toIndex = to == null ? 0 : to.right_idx;
+            }
+            if (to == null) {
+                return 0;
+            }
+            if (from == to) {
+                return toIndex - fromIndex + 1;
+            }
+            int sum = 0;
+            while (from != to) {
+                sum += (from.right_idx - fromIndex + 1);
+                from = from.next;
+                fromIndex = from.left_idx;
+            }
+            return sum + toIndex - fromIndex + 1;
+        }
+
+        private void readObject(ObjectInputStream stream) throws IOException,
+                                                                 ClassNotFoundException {
+            stream.defaultReadObject();
+            firstKeyModCount = -1;
+            lastKeyModCount = -1;
+        }
+    }
+
+    static class SubMapEntrySet <K,V> extends AbstractSet<Map.Entry<K, V>>
+                                                implements Set<Map.Entry<K, V>> {
+        SubMap<K, V> subMap;
+
+        SubMapEntrySet(SubMap<K, V> map) {
+            subMap = map;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return subMap.isEmpty();
+        }
+
+        public Iterator<Map.Entry<K, V>> iterator() {
+            Node<K, V> from;
+            int fromIndex;
+            if (subMap.hasStart) {
+                subMap.setFirstKey();
+                from = subMap.firstKeyNode;
+                fromIndex = subMap.firstKeyIndex;
+            } else {
+                from = minimum(subMap.backingMap.root);
+                fromIndex = from != null ? from.left_idx : 0;
+            }
+            if (!subMap.hasEnd) {
+                return new UnboundedEntryIterator<K, V>(subMap.backingMap, from, from == null ? 0 : from.right_idx - fromIndex);
+            }
+            subMap.setLastKey();
+            Node<K, V> to = subMap.lastKeyNode;
+            int toIndex = subMap.lastKeyIndex;
+            return new BoundedEntryIterator<K, V>(from, from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to, to == null ? 0 : to.right_idx - toIndex);
+        }
+
+        @Override
+        public int size() {
+            return subMap.size();
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean contains(Object object) {
+            if (object instanceof Map.Entry) {
+                Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
+                K key = entry.getKey();
+                if (subMap.isInRange(key)) {
+                    V v1 = subMap.get(key), v2 = entry.getValue();
+                    return v1 == null ? ( v2 == null && subMap.containsKey(key) ) : v1.equals(v2);
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public boolean remove(Object object) {
+            if (contains(object)) {
+                Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
+                K key = entry.getKey();
+                subMap.remove(key);
+                return true;
+            }
+            return false;
+        }
+    }
+
+    static class SubMapKeySet <K,V> extends AbstractSet<K> implements Set<K> {
+        SubMap<K, V> subMap;
+
+        SubMapKeySet(SubMap<K, V> map) {
+            subMap = map;
+        }
+
+        @Override
+        public boolean contains(Object object) {
+            return subMap.containsKey(object);
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return subMap.isEmpty();
+        }
+
+        @Override
+        public int size() {
+            return subMap.size();
+        }
+
+        @Override
+        public boolean remove(Object object) {
+            if (subMap.containsKey(object)) {
+                subMap.remove(object);
+                return true;
+            }
+            return false;
+        }
+
+        public Iterator<K> iterator() {
+            Node<K, V> from;
+            int fromIndex;
+            if (subMap.hasStart) {
+                subMap.setFirstKey();
+                from = subMap.firstKeyNode;
+                fromIndex = subMap.firstKeyIndex;
+            } else {
+                from = minimum(subMap.backingMap.root);
+                fromIndex = from != null ? from.left_idx : 0;
+            }
+            if (!subMap.hasEnd) {
+                return new UnboundedKeyIterator<K, V>(subMap.backingMap, from,
+                                   from == null ? 0 : from.right_idx - fromIndex);
+            }
+            subMap.setLastKey();
+            Node<K, V> to = subMap.lastKeyNode;
+            int toIndex = subMap.lastKeyIndex;
+            return new BoundedKeyIterator<K, V>(from,
+               from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to,
+                 to == null ? 0 : to.right_idx   - toIndex);
+        }
+    }
+
+    static class SubMapValuesCollection <K,V> extends AbstractCollection<V> {
+        SubMap<K, V> subMap;
+
+        public SubMapValuesCollection(SubMap<K, V> subMap) {
+            this.subMap = subMap;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return subMap.isEmpty();
+        }
+
+        @Override
+        public Iterator<V> iterator() {
+            Node<K, V> from;
+            int fromIndex;
+            if (subMap.hasStart) {
+                subMap.setFirstKey();
+                from = subMap.firstKeyNode;
+                fromIndex = subMap.firstKeyIndex;
+            } else {
+                from = minimum(subMap.backingMap.root);
+                fromIndex = from != null ? from.left_idx : 0;
+            }
+            if (!subMap.hasEnd) {
+                return new UnboundedValueIterator<K, V>(subMap.backingMap, from,
+                                   from == null ? 0 : from.right_idx - fromIndex);
+            }
+            subMap.setLastKey();
+            Node<K, V> to = subMap.lastKeyNode;
+            int toIndex = subMap.lastKeyIndex;
+            return new BoundedValueIterator<K, V>(from,
+               from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to,
+                 to == null ? 0 : to.right_idx - toIndex);
+        }
+
+        @Override
+        public int size() {
+            return subMap.size();
+        }
+    }
+
     /**
      * Constructs a new empty {@code TreeMap} instance.
-     * 
-     * @since Android 1.0
      */
     public TreeMap() {
-        super();
     }
 
     /**
      * Constructs a new empty {@code TreeMap} instance with the specified
      * comparator.
-     * 
+     *
      * @param comparator
      *            the comparator to compare keys with.
-     * @since Android 1.0
      */
     public TreeMap(Comparator<? super K> comparator) {
         this.comparator = comparator;
@@ -683,50 +977,753 @@
     /**
      * Constructs a new {@code TreeMap} instance containing the mappings from
      * the specified map and using natural ordering.
-     * 
+     *
      * @param map
      *            the mappings to add.
      * @throws ClassCastException
      *             if a key in the specified map does not implement the
      *             Comparable interface, or if the keys in the map cannot be
      *             compared.
-     * @since Android 1.0
      */
-    public TreeMap(Map<? extends K,? extends V> map) {
-        this();
+    public TreeMap(Map<? extends K, ? extends V> map) {
         putAll(map);
     }
 
     /**
      * Constructs a new {@code TreeMap} instance containing the mappings from
      * the specified SortedMap and using the same comparator.
-     * 
+     *
      * @param map
      *            the mappings to add.
-     * @since Android 1.0
      */
-    public TreeMap(SortedMap<K,? extends V> map) {
+    public TreeMap(SortedMap<K, ? extends V> map) {
         this(map.comparator());
+        Node<K, V> lastNode = null;
         Iterator<? extends Map.Entry<K, ? extends V>> it = map.entrySet().iterator();
-        if (it.hasNext()) {
+        while (it.hasNext()) {
             Map.Entry<K, ? extends V> entry = it.next();
-            Entry<K, V> last = new Entry<K, V>(entry.getKey(), entry.getValue());
-            root = last;
-            size = 1;
-            while (it.hasNext()) {
-                entry = it.next();
-                Entry<K, V> x = new Entry<K, V>(entry.getKey(), entry.getValue());
-                x.parent = last;
-                last.right = x;
-                size++;
-                balance(x);
-                last = x;
-            }
+            lastNode = addToLast(lastNode, entry.getKey(), entry.getValue());
         }
     }
 
-    void balance(Entry<K, V> x) {
-        Entry<K, V> y;
+    Node<K, V> addToLast(Node<K, V> last, K key, V value) {
+        if (last == null) {
+            root = last = createNode(key, value);
+            size = 1;
+        } else if (last.size == Node.NODE_SIZE) {
+            Node<K, V> newNode = createNode(key, value);
+            attachToRight(last, newNode);
+            balance(newNode);
+            size++;
+            last = newNode;
+        } else {
+            appendFromRight(last, key, value);
+            size++;
+        }
+        return last;
+    }
+
+    /**
+     * Removes all mappings from this TreeMap, leaving it empty.
+     *
+     * @see Map#isEmpty()
+     * @see #size()
+     */
+    @Override
+    public void clear() {
+        root = null;
+        size = 0;
+        modCount++;
+    }
+
+    /**
+     * Returns a new {@code TreeMap} with the same mappings, size and comparator
+     * as this instance.
+     *
+     * @return a shallow copy of this instance.
+     * @see java.lang.Cloneable
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object clone() {
+        try {
+            TreeMap<K, V> clone = (TreeMap<K, V>) super.clone();
+            clone.entrySet = null;
+            if (root != null) {
+                clone.root = root.clone(null);
+                // restore prev/next chain
+                Node<K, V> node = minimum(clone.root);
+                while (true) {
+                    Node<K, V> nxt = successor(node);
+                    if (nxt == null) {
+                        break;
+                    }
+                    nxt.prev = node;
+                    node.next = nxt;
+                    node = nxt;
+                }
+            }
+            return clone;
+        } catch (CloneNotSupportedException e) {
+            return null;
+        }
+    }
+
+    static private <K, V> Node<K, V> successor(Node<K, V> x) {
+        if (x.right != null) {
+            return minimum(x.right);
+        }
+        Node<K, V> y = x.parent;
+        while (y != null && x == y.right) {
+            x = y;
+            y = y.parent;
+        }
+        return y;
+    }
+
+    /**
+     * Returns the comparator used to compare elements in this map.
+     *
+     * @return the comparator or {@code null} if the natural ordering is used.
+     */
+    public Comparator<? super K> comparator() {
+        return comparator;
+    }
+
+    /**
+     * Returns whether this map contains the specified key.
+     *
+     * @param key
+     *            the key to search for.
+     * @return {@code true} if this map contains the specified key,
+     *         {@code false} otherwise.
+     * @throws ClassCastException
+     *             if the specified key cannot be compared with the keys in this
+     *             map.
+     * @throws NullPointerException
+     *             if the specified key is {@code null} and the comparator
+     *             cannot handle {@code null} keys.
+     */
+    @Override
+    public boolean containsKey(Object key) {
+        Comparable<K> object = comparator == null ? toComparable((K) key) : null;
+        K keyK = (K) key;
+        Node<K, V> node = root;
+        while (node != null) {
+            K[] keys = node.keys;
+            int left_idx = node.left_idx;
+            int result = cmp(object, keyK, keys[left_idx]);
+            if (result < 0) {
+                node = node.left;
+            } else if (result == 0) {
+                return true;
+            } else {
+                int right_idx = node.right_idx;
+                if (left_idx != right_idx) {
+                    result = cmp(object, keyK, keys[right_idx]);
+                }
+                if (result > 0) {
+                    node = node.right;
+                } else if (result == 0) {
+                    return true;
+                } else { /*search in node*/
+                    int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                    while (low <= high) {
+                        mid = (low + high) >> 1;
+                        result = cmp(object, keyK, keys[mid]);
+                        if (result > 0) {
+                            low = mid + 1;
+                        } else if (result == 0) {
+                            return true;
+                        } else {
+                            high = mid - 1;
+                        }
+                    }
+                    return false;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns whether this map contains the specified value.
+     *
+     * @param value
+     *            the value to search for.
+     * @return {@code true} if this map contains the specified value,
+     *         {@code false} otherwise.
+     */
+    @Override
+    public boolean containsValue(Object value) {
+        if (root == null) {
+            return false;
+        }
+        Node<K, V> node = minimum(root);
+        if (value != null) {
+            while (node != null) {
+                int to = node.right_idx;
+                V[] values = node.values;
+                for (int i = node.left_idx; i <= to; i++) {
+                    if (value.equals(values[i])) {
+                        return true;
+                    }
+                }
+                node = node.next;
+            }
+        } else {
+            while (node != null) {
+                int to = node.right_idx;
+                V[] values = node.values;
+                for (int i = node.left_idx; i <= to; i++) {
+                    if (values[i] == null) {
+                        return true;
+                    }
+                }
+                node = node.next;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns a set containing all of the mappings in this map. Each mapping is
+     * an instance of {@link Map.Entry}. As the set is backed by this map,
+     * changes in one will be reflected in the other. It does not support adding
+     * operations.
+     *
+     * @return a set of the mappings.
+     */
+    @Override
+    public Set<Map.Entry<K, V>> entrySet() {
+        if (entrySet == null) {
+            entrySet = new AbstractSet<Map.Entry<K, V>>() {
+                @Override
+                public int size() {
+                    return size;
+                }
+
+                @Override
+                public void clear() {
+                    TreeMap.this.clear();
+                }
+
+                @SuppressWarnings("unchecked")
+                @Override
+                public boolean contains(Object object) {
+                    if (object instanceof Map.Entry) {
+                        Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
+                        K key = entry.getKey();
+                        Object v1 = TreeMap.this.get(key), v2 = entry.getValue();
+                        return v1 == null ? ( v2 == null && TreeMap.this.containsKey(key) ) : v1.equals(v2);
+                    }
+                    return false;
+                }
+
+                @Override
+                public boolean remove(Object object) {
+                    if (contains(object)) {
+                        Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
+                        K key = entry.getKey();
+                        TreeMap.this.remove(key);
+                        return true;
+                    }
+                    return false;
+                }
+
+                @Override
+                public Iterator<Map.Entry<K, V>> iterator() {
+                    return new UnboundedEntryIterator<K, V>(TreeMap.this);
+                }
+            };
+        }
+        return entrySet;
+    }
+
+    /**
+     * Returns the first key in this map.
+     *
+     * @return the first key in this map.
+     * @throws NoSuchElementException
+     *                if this map is empty.
+     */
+    public K firstKey() {
+        if (root != null) {
+            Node<K, V> node = minimum(root);
+            return node.keys[node.left_idx];
+        }
+        throw new NoSuchElementException();
+    }
+
+
+    /**
+     * Returns the value of the mapping with the specified key.
+     *
+     * @param key
+     *            the key.
+     * @return the value of the mapping with the specified key.
+     * @throws ClassCastException
+     *             if the key cannot be compared with the keys in this map.
+     * @throws NullPointerException
+     *             if the key is {@code null} and the comparator cannot handle
+     *             {@code null}.
+     */
+    @Override
+    public V get(Object key) {
+        Comparable<K> object = comparator == null ? toComparable((K) key) : null;
+        K keyK = (K) key;
+        Node<K, V> node = root;
+        while (node != null) {
+            K[] keys = node.keys;
+            int left_idx = node.left_idx;
+            int result = cmp(object, keyK, keys[left_idx]);
+            if (result < 0) {
+                node = node.left;
+            } else if (result == 0) {
+                return node.values[left_idx];
+            } else {
+                int right_idx = node.right_idx;
+                if (left_idx != right_idx) {
+                    result = cmp(object, keyK, keys[right_idx]);
+                }
+                if (result > 0) {
+                    node = node.right;
+                } else if (result == 0) {
+                    return node.values[right_idx];
+                } else { /*search in node*/
+                    int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                    while (low <= high) {
+                        mid = (low + high) >> 1;
+                        result = cmp(object, keyK, keys[mid]);
+                        if (result > 0) {
+                            low = mid + 1;
+                        } else if (result == 0) {
+                            return node.values[mid];
+                        } else {
+                            high = mid - 1;
+                        }
+                    }
+                    return null;
+                }
+            }
+        }
+        return null;
+    }
+
+    private int cmp(Comparable<K> object, K key1, K key2) {
+        return object != null ?
+               object.compareTo(key2) : comparator.compare(key1, key2);
+    }
+
+    /**
+     * Returns a sorted map over a range of this sorted map with all keys that
+     * are less than the specified {@code endKey}. Changes to the returned
+     * sorted map are reflected in this sorted map and vice versa.
+     * <p>
+     * Note: The returned map will not allow an insertion of a key outside the
+     * specified range.
+     *
+     * @param endKey
+     *            the high boundary of the range specified.
+     * @return a sorted map where the keys are less than {@code endKey}.
+     * @throws ClassCastException
+     *             if the specified key cannot be compared with the keys in this
+     *             map.
+     * @throws NullPointerException
+     *             if the specified key is {@code null} and the comparator
+     *             cannot handle {@code null} keys.
+     * @throws IllegalArgumentException
+     *             if this map is itself a sorted map over a range of another
+     *             map and the specified key is outside of its range.
+     */
+    public SortedMap<K, V> headMap(K endKey) {
+        // Check for errors
+        if (comparator == null) {
+            toComparable(endKey).compareTo(endKey);
+        } else {
+            comparator.compare(endKey, endKey);
+        }
+        return new SubMap<K, V>(this, endKey);
+    }
+
+    /**
+     * Returns a set of the keys contained in this map. The set is backed by
+     * this map so changes to one are reflected by the other. The set does not
+     * support adding.
+     *
+     * @return a set of the keys.
+     */
+    @Override
+    public Set<K> keySet() {
+        if (keySet == null) {
+            keySet = new AbstractSet<K>() {
+                @Override
+                public boolean contains(Object object) {
+                    return TreeMap.this.containsKey(object);
+                }
+
+                @Override
+                public int size() {
+                    return TreeMap.this.size;
+                }
+
+                @Override
+                public void clear() {
+                    TreeMap.this.clear();
+                }
+
+                @Override
+                public boolean remove(Object object) {
+                    if (contains(object)) {
+                        TreeMap.this.remove(object);
+                        return true;
+                    }
+                    return false;
+                }
+
+                @Override
+                public Iterator<K> iterator() {
+                    return new UnboundedKeyIterator<K, V>(TreeMap.this);
+                }
+            };
+        }
+        return keySet;
+    }
+
+    /**
+     * Returns the last key in this map.
+     *
+     * @return the last key in this map.
+     * @throws NoSuchElementException
+     *             if this map is empty.
+     */
+    public K lastKey() {
+        if (root != null) {
+            Node<K, V> node = maximum(root);
+            return node.keys[node.right_idx];
+        }
+        throw new NoSuchElementException();
+    }
+
+    static <K,V> Node<K, V> minimum(Node<K, V> x) {
+        if (x == null) {
+            return null;
+        }
+        while (x.left != null) {
+            x = x.left;
+        }
+        return x;
+    }
+
+    static <K,V> Node<K, V> maximum(Node<K, V> x) {
+        if (x == null) {
+            return null;
+        }
+        while (x.right != null) {
+            x = x.right;
+        }
+        return x;
+    }
+
+    /**
+     * Maps the specified key to the specified value.
+     *
+     * @param key
+     *            the key.
+     * @param value
+     *            the value.
+     * @return the value of any previous mapping with the specified key or
+     *         {@code null} if there was no mapping.
+     * @throws ClassCastException
+     *             if the specified key cannot be compared with the keys in this
+     *             map.
+     * @throws NullPointerException
+     *             if the specified key is {@code null} and the comparator
+     *             cannot handle {@code null} keys.
+     */
+    @Override
+    public V put(K key, V value) {
+        if (root == null) {
+            root = createNode(key, value);
+            size = 1;
+            modCount++;
+            return null;
+        }
+        Comparable<K> object = comparator == null ? toComparable((K) key) : null;
+        K keyK = (K) key;
+        Node<K, V> node = root;
+        Node<K, V> prevNode = null;
+        int result = 0;
+        while (node != null) {
+            prevNode = node;
+            K[] keys = node.keys;
+            int left_idx = node.left_idx;
+            result = cmp(object, keyK, keys[left_idx]);
+            if (result < 0) {
+                node = node.left;
+            } else if (result == 0) {
+                V res = node.values[left_idx];
+                node.values[left_idx] = value;
+                return res;
+            } else {
+                int right_idx = node.right_idx;
+                if (left_idx != right_idx) {
+                    result = cmp(object, keyK, keys[right_idx]);
+                }
+                if (result > 0) {
+                    node = node.right;
+                } else if (result == 0) {
+                    V res = node.values[right_idx];
+                    node.values[right_idx] = value;
+                    return res;
+                } else { /*search in node*/
+                    int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                    while (low <= high) {
+                        mid = (low + high) >> 1;
+                        result = cmp(object, keyK, keys[mid]);
+                        if (result > 0) {
+                            low = mid + 1;
+                        } else if (result == 0) {
+                            V res = node.values[mid];
+                            node.values[mid] = value;
+                            return res;
+                        } else {
+                            high = mid - 1;
+                        }
+                    }
+                    result = low;
+                    break;
+                }
+            }
+        } /* while */
+/*
+          if(node == null) {
+             if(prevNode==null) {
+                - case of empty Tree
+             } else {
+                result < 0 - prevNode.left==null - attach here
+                result > 0 - prevNode.right==null - attach here
+             }
+          } else {
+             insert into node.
+             result - index where it should be inserted.
+          }
+        */
+        size++;
+        modCount++;
+        if (node == null) {
+            if (prevNode == null) {
+                // case of empty Tree
+                root = createNode(key, value);
+            } else if (prevNode.size < Node.NODE_SIZE) {
+                // there is a place for insert
+                if (result < 0) {
+                    appendFromLeft(prevNode, key, value);
+                } else {
+                    appendFromRight(prevNode, key, value);
+                }
+            } else {
+                // create and link
+                Node<K, V> newNode = createNode(key, value);
+                if (result < 0) {
+                    attachToLeft(prevNode, newNode);
+                } else {
+                    attachToRight(prevNode, newNode);
+                }
+                balance(newNode);
+            }
+        } else {
+            // insert into node.
+            // result - index where it should be inserted.
+            if (node.size < Node.NODE_SIZE) { // insert and ok
+                int left_idx = node.left_idx;
+                int right_idx = node.right_idx;
+                if (left_idx == 0 || ((right_idx != Node.NODE_SIZE - 1) && (right_idx - result <= result - left_idx))) {
+                    int right_idxPlus1 = right_idx + 1;
+                    System.arraycopy(node.keys,   result, node.keys,   result + 1, right_idxPlus1 - result);
+                    System.arraycopy(node.values, result, node.values, result + 1, right_idxPlus1 - result);
+                    node.right_idx = right_idxPlus1;
+                    node.keys[result] = key;
+                    node.values[result] = value;
+                } else {
+                    int left_idxMinus1 = left_idx - 1;
+                    System.arraycopy(node.keys,   left_idx, node.keys,   left_idxMinus1, result - left_idx);
+                    System.arraycopy(node.values, left_idx, node.values, left_idxMinus1, result - left_idx);
+                    node.left_idx = left_idxMinus1;
+                    node.keys[result - 1] = key;
+                    node.values[result - 1] = value;
+                }
+                node.size++;
+            } else {
+                // there are no place here
+                // insert and push old pair
+                Node<K, V> previous = node.prev;
+                Node<K, V> nextNode = node.next;
+                boolean removeFromStart;
+                boolean attachFromLeft = false;
+                Node<K, V> attachHere = null;
+                if (previous == null) {
+                    if (nextNode != null && nextNode.size < Node.NODE_SIZE) {
+                        // move last pair to next
+                        removeFromStart = false;
+                    } else {
+                        // next node doesn't exist or full
+                        // left==null
+                        // drop first pair to new node from left
+                        removeFromStart = true;
+                        attachFromLeft = true;
+                        attachHere = node;
+                    }
+                } else if (nextNode == null) {
+                    if (previous.size < Node.NODE_SIZE) {
+                        // move first pair to prev
+                        removeFromStart = true;
+                    } else {
+                        // right == null;
+                        // drop last pair to new node from right
+                        removeFromStart = false;
+                        attachFromLeft = false;
+                        attachHere = node;
+                    }
+                } else {
+                    if (previous.size < Node.NODE_SIZE) {
+                        if (nextNode.size < Node.NODE_SIZE) {
+                            // choose prev or next for moving
+                            removeFromStart = previous.size < nextNode.size;
+                        } else {
+                            // move first pair to prev
+                            removeFromStart = true;
+                        }
+                    } else {
+                        if (nextNode.size < Node.NODE_SIZE) {
+                            // move last pair to next
+                            removeFromStart = false;
+                        } else {
+                            // prev & next are full
+                            // if node.right!=null then node.next.left==null
+                            // if node.left!=null then node.prev.right==null
+                            if (node.right == null) {
+                                attachHere = node;
+                                attachFromLeft = false;
+                                removeFromStart = false;
+                            } else {
+                                attachHere = nextNode;
+                                attachFromLeft = true;
+                                removeFromStart = false;
+                            }
+                        }
+                    }
+                }
+                K movedKey;
+                V movedValue;
+                if (removeFromStart) {
+                    // node.left_idx == 0
+                    movedKey = node.keys[0];
+                    movedValue = node.values[0];
+                    int resMunus1 = result - 1;
+                    System.arraycopy(node.keys,   1, node.keys,   0, resMunus1);
+                    System.arraycopy(node.values, 1, node.values, 0, resMunus1);
+                    node.keys  [resMunus1] = key;
+                    node.values[resMunus1] = value;
+                } else {
+                    // node.right_idx == Node.NODE_SIZE - 1
+                    movedKey   = node.keys[Node.NODE_SIZE - 1];
+                    movedValue = node.values[Node.NODE_SIZE - 1];
+                    System.arraycopy(node.keys,   result, node.keys,   result + 1, Node.NODE_SIZE - 1 - result);
+                    System.arraycopy(node.values, result, node.values, result + 1, Node.NODE_SIZE - 1 - result);
+                    node.keys[result] = key;
+                    node.values[result] = value;
+                }
+                if (attachHere == null) {
+                    if (removeFromStart) {
+                        appendFromRight(previous, movedKey, movedValue);
+                    } else {
+                        appendFromLeft(nextNode, movedKey, movedValue);
+                    }
+                } else {
+                    Node<K, V> newNode = createNode(movedKey, movedValue);
+                    if (attachFromLeft) {
+                        attachToLeft(attachHere, newNode);
+                    } else {
+                        attachToRight(attachHere, newNode);
+                    }
+                    balance(newNode);
+                }
+            }
+        }
+        return null;
+    }
+
+    private void appendFromLeft(Node<K, V> node, K keyObj, V value) {
+        if (node.left_idx == 0) {
+            int new_right = node.right_idx + 1;
+            System.arraycopy(node.keys,   0, node.keys,   1, new_right);
+            System.arraycopy(node.values, 0, node.values, 1, new_right);
+            node.right_idx = new_right;
+        } else {
+            node.left_idx--;
+        }
+        node.size++;
+        node.keys[node.left_idx] = keyObj;
+        node.values[node.left_idx] = value;
+    }
+
+    private void attachToLeft(Node<K, V> node, Node<K, V> newNode) {
+        newNode.parent = node;
+        // node.left==null - attach here
+        node.left = newNode;
+        Node<K, V> predecessor = node.prev;
+        newNode.prev = predecessor;
+        newNode.next = node;
+        if (predecessor != null) {
+            predecessor.next = newNode;
+        }
+        node.prev = newNode;
+    }
+
+    /* add pair into node; existence free room in the node should be checked
+     * before call
+     */
+    private void appendFromRight(Node<K, V> node, K keyObj, V value) {
+        if (node.right_idx == Node.NODE_SIZE - 1) {
+            int left_idx = node.left_idx;
+            int left_idxMinus1 = left_idx - 1;
+            System.arraycopy(node.keys,   left_idx, node.keys,   left_idxMinus1, Node.NODE_SIZE - left_idx);
+            System.arraycopy(node.values, left_idx, node.values, left_idxMinus1, Node.NODE_SIZE - left_idx);
+            node.left_idx = left_idxMinus1;
+        } else {
+            node.right_idx++;
+        }
+        node.size++;
+        node.keys[node.right_idx] = keyObj;
+        node.values[node.right_idx] = value;
+    }
+
+    private void attachToRight(Node<K, V> node, Node<K, V> newNode) {
+        newNode.parent = node;
+        // - node.right==null - attach here
+        node.right = newNode;
+        newNode.prev = node;
+        Node<K, V> successor = node.next;
+        newNode.next = successor;
+        if (successor != null) {
+            successor.prev = newNode;
+        }
+        node.next = newNode;
+    }
+
+    private Node<K, V> createNode(K keyObj, V value) {
+        Node<K, V> node = new Node<K, V>();
+        node.keys[0] = keyObj;
+        node.values[0] = value;
+        node.left_idx = 0;
+        node.right_idx = 0;
+        node.size = 1;
+        return node;
+    }
+
+    void balance(Node<K, V> x) {
+        Node<K, V> y;
         x.color = true;
         while (x != root && x.parent.color) {
             if (x.parent == x.parent.parent.left) {
@@ -766,226 +1763,421 @@
         root.color = false;
     }
 
+    private void rightRotate(Node<K, V> x) {
+        Node<K, V> y = x.left;
+        x.left = y.right;
+        if (y.right != null) {
+            y.right.parent = x;
+        }
+        y.parent = x.parent;
+        if (x.parent == null) {
+            root = y;
+        } else {
+            if (x == x.parent.right) {
+                x.parent.right = y;
+            } else {
+                x.parent.left = y;
+            }
+        }
+        y.right = x;
+        x.parent = y;
+    }
+
+
+    private void leftRotate(Node<K, V> x) {
+        Node<K, V> y = x.right;
+        x.right = y.left;
+        if (y.left != null) {
+            y.left.parent = x;
+        }
+        y.parent = x.parent;
+        if (x.parent == null) {
+            root = y;
+        } else {
+            if (x == x.parent.left) {
+                x.parent.left = y;
+            } else {
+                x.parent.right = y;
+            }
+        }
+        y.left = x;
+        x.parent = y;
+    }
+
+
     /**
-     * Removes all mappings from this TreeMap, leaving it empty.
-     * 
-     * @see Map#isEmpty()
-     * @see #size()
-     * @since Android 1.0
+     * Copies all the mappings in the given map to this map. These mappings will
+     * replace all mappings that this map had for any of the keys currently in
+     * the given map.
+     *
+     * @param map
+     *            the map to copy mappings from.
+     * @throws ClassCastException
+     *             if a key in the specified map cannot be compared with the
+     *             keys in this map.
+     * @throws NullPointerException
+     *             if a key in the specified map is {@code null} and the
+     *             comparator cannot handle {@code null} keys.
      */
     @Override
-    public void clear() {
-        root = null;
-        size = 0;
-        modCount++;
+    public void putAll(Map<? extends K, ? extends V> map) {
+        super.putAll(map);
     }
 
     /**
-     * Returns a new {@code TreeMap} with the same mappings, size and comparator
-     * as this instance.
-     * 
-     * @return a shallow copy of this instance.
-     * @see java.lang.Cloneable
-     * @since Android 1.0
+     * Removes the mapping with the specified key from this map.
+     *
+     * @param key
+     *            the key of the mapping to remove.
+     * @return the value of the removed mapping or {@code null} if no mapping
+     *         for the specified key was found.
+     * @throws ClassCastException
+     *             if the specified key cannot be compared with the keys in this
+     *             map.
+     * @throws NullPointerException
+     *             if the specified key is {@code null} and the comparator
+     *             cannot handle {@code null} keys.
      */
-    @SuppressWarnings("unchecked")
     @Override
-    public Object clone() {
-        try {
-            TreeMap<K, V> clone = (TreeMap<K, V>) super.clone();
-            clone.entrySet = null;
-            if (root != null) {
-                clone.root = root.clone(null);
-            }
-            return clone;
-        } catch (CloneNotSupportedException e) {
+    public V remove(Object key) {
+        if (size == 0) {
             return null;
         }
-    }
-
-    /**
-     * Returns the comparator used to compare elements in this map.
-     * 
-     * @return the comparator or {@code null} if the natural ordering is used.
-     * @since Android 1.0
-     */
-    public Comparator<? super K> comparator() {
-        return comparator;
-    }
-
-    /**
-     * Returns whether this map contains the specified key.
-     * 
-     * @param key
-     *            the key to search for.
-     * @return {@code true} if this map contains the specified key,
-     *         {@code false} otherwise.
-     * @since Android 1.0
-     */
-    @Override
-    public boolean containsKey(Object key) {
-        return find(key) != null;
-    }
-
-    /**
-     * Returns whether this map contains the specified value.
-     * 
-     * @param value
-     *            the value to search for.
-     * @return {@code true} if this map contains the specified value,
-     *         {@code false} otherwise.
-     * @since Android 1.0
-     */
-    @Override
-    public boolean containsValue(Object value) {
-        if (root != null) {
-            return containsValue(root, value);
-        }
-        return false;
-    }
-
-    private boolean containsValue(Entry<K, V> node, Object value) {
-        if (value == null ? node.value == null : value.equals(node.value)) {
-            return true;
-        }
-        if (node.left != null) {
-            if (containsValue(node.left, value)) {
-                return true;
-            }
-        }
-        if (node.right != null) {
-            if (containsValue(node.right, value)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns a set containing all of the mappings in this map. Each mapping is
-     * an instance of {@link Map.Entry}. As the set is backed by this map,
-     * changes in one will be reflected in the other. It does not support adding
-     * operations.
-     * 
-     * @return a set of the mappings.
-     * @since Android 1.0
-     */
-    @Override
-    public Set<Map.Entry<K, V>> entrySet() {
-        if (entrySet == null) {
-            entrySet = new AbstractSet<Map.Entry<K, V>>() {
-                 @Override
-                public int size() {
-                    return size;
+        Comparable<K> object = comparator == null ? toComparable((K) key) : null;
+        K keyK = (K) key;
+        Node<K, V> node = root;
+        while (node != null) {
+            K[] keys = node.keys;
+            int left_idx = node.left_idx;
+            int result = cmp(object, keyK, keys[left_idx]);
+            if (result < 0) {
+                node = node.left;
+            } else if (result == 0) {
+                V value = node.values[left_idx];
+                removeLeftmost(node);
+                return value;
+            } else {
+                int right_idx = node.right_idx;
+                if (left_idx != right_idx) {
+                    result = cmp(object, keyK, keys[right_idx]);
                 }
-
-                @Override
-                public void clear() {
-                    TreeMap.this.clear();
-                }
-
-                @SuppressWarnings("unchecked")
-                @Override
-                public boolean contains(Object object) {
-                    if (object instanceof Map.Entry) {
-                        Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
-                        Object v1 = get(entry.getKey()), v2 = entry.getValue();
-                        return v1 == null ? v2 == null : v1.equals(v2);
+                if (result > 0) {
+                    node = node.right;
+                } else if (result == 0) {
+                    V value = node.values[right_idx];
+                    removeRightmost(node);
+                    return value;
+                } else { /*search in node*/
+                    int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                    while (low <= high) {
+                        mid = (low + high) >> 1;
+                        result = cmp(object, keyK, keys[mid]);
+                        if (result > 0) {
+                            low = mid + 1;
+                        } else if (result == 0) {
+                            V value = node.values[mid];
+                            removeMiddleElement(node, mid);
+                            return value;
+                        } else {
+                            high = mid - 1;
+                        }
                     }
-                    return false;
+                    return null;
                 }
-
-                @Override
-                public Iterator<Map.Entry<K, V>> iterator() {
-                    return new UnboundedEntryIterator<K, V>(TreeMap.this);
-                }
-            };
-        }
-        return entrySet;
-    }
-
-    @SuppressWarnings("unchecked")
-    private Entry<K, V> find(Object keyObj) {
-        int result;
-        K key = (K)keyObj;
-        Comparable<K> object = null;
-        if (comparator == null) {
-            object = toComparable(key);
-        }
-        Entry<K, V> x = root;
-        while (x != null) {
-            result = object != null ? object.compareTo(x.key) : comparator
-                    .compare(key, x.key);
-            if (result == 0) {
-                return x;
             }
-            x = result < 0 ? x.left : x.right;
         }
         return null;
     }
 
-    @SuppressWarnings("unchecked")
-    Entry<K, V> findAfter(Object keyObj) {
-        K key = (K)keyObj;
-        int result;
-        Comparable<K> object = null;
-        if (comparator == null) {
-            object = toComparable(key);
-        }
-        Entry<K, V> x = root, last = null;
-        while (x != null) {
-            result = object != null ? object.compareTo(x.key) : comparator
-                    .compare(key, x.key);
-            if (result == 0) {
-                return x;
+    void removeLeftmost(Node<K, V> node) {
+        int index = node.left_idx;
+        if (node.size == 1) {
+            deleteNode(node);
+        } else if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) {
+            // move all to prev node and kill it
+            Node<K, V> prev = node.prev;
+            int size = node.right_idx - index;
+            System.arraycopy(node.keys,   index + 1, prev.keys,   prev.right_idx + 1, size);
+            System.arraycopy(node.values, index + 1, prev.values, prev.right_idx + 1, size);
+            prev.right_idx += size;
+            prev.size += size;
+            deleteNode(node);
+        } else if (node.next != null && (node.next.left_idx) > node.size) {
+            // move all to next node and kill it
+            Node<K, V> next = node.next;
+            int size = node.right_idx - index;
+            int next_new_left = next.left_idx - size;
+            next.left_idx = next_new_left;
+            System.arraycopy(node.keys,   index + 1, next.keys,   next_new_left, size);
+            System.arraycopy(node.values, index + 1, next.values, next_new_left, size);
+            next.size += size;
+            deleteNode(node);
+        } else {
+            node.keys[index] = null;
+            node.values[index] = null;
+            node.left_idx++;
+            node.size--;
+            Node<K, V> prev = node.prev;
+            if (prev != null && prev.size == 1) {
+                node.size++;
+                node.left_idx--;
+                node.keys  [node.left_idx] = prev.keys  [prev.left_idx];
+                node.values[node.left_idx] = prev.values[prev.left_idx];
+                deleteNode(prev);
             }
-            if (result < 0) {
-                last = x;
-                x = x.left;
+        }
+        modCount++;
+        size--;
+    }
+
+    void removeRightmost(Node<K, V> node) {
+        int index = node.right_idx;
+        if (node.size == 1) {
+            deleteNode(node);
+        } else if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) {
+            // move all to prev node and kill it
+            Node<K, V> prev = node.prev;
+            int left_idx = node.left_idx;
+            int size = index - left_idx;
+            System.arraycopy(node.keys,   left_idx, prev.keys,   prev.right_idx + 1, size);
+            System.arraycopy(node.values, left_idx, prev.values, prev.right_idx + 1, size);
+            prev.right_idx += size;
+            prev.size += size;
+            deleteNode(node);
+        } else if (node.next != null && (node.next.left_idx) > node.size) {
+            // move all to next node and kill it
+            Node<K, V> next = node.next;
+            int left_idx = node.left_idx;
+            int size = index - left_idx;
+            int next_new_left = next.left_idx - size;
+            next.left_idx = next_new_left;
+            System.arraycopy(node.keys,   left_idx, next.keys,   next_new_left, size);
+            System.arraycopy(node.values, left_idx, next.values, next_new_left, size);
+            next.size += size;
+            deleteNode(node);
+        } else {
+            node.keys[index] = null;
+            node.values[index] = null;
+            node.right_idx--;
+            node.size--;
+            Node<K, V> next = node.next;
+            if (next != null && next.size == 1) {
+                node.size++;
+                node.right_idx++;
+                node.keys[node.right_idx]   = next.keys[next.left_idx];
+                node.values[node.right_idx] = next.values[next.left_idx];
+                deleteNode(next);
+            }
+        }
+        modCount++;
+        size--;
+    }
+
+    void removeMiddleElement(Node<K, V> node, int index) {
+        // this function is called iff index if some middle element;
+        // so node.left_idx < index < node.right_idx
+        // condition above assume that node.size > 1
+        if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) {
+            // move all to prev node and kill it
+            Node<K, V> prev = node.prev;
+            int left_idx = node.left_idx;
+            int size = index - left_idx;
+            System.arraycopy(node.keys,   left_idx, prev.keys,   prev.right_idx + 1, size);
+            System.arraycopy(node.values, left_idx, prev.values, prev.right_idx + 1, size);
+            prev.right_idx += size;
+            size = node.right_idx - index;
+            System.arraycopy(node.keys,   index + 1, prev.keys,   prev.right_idx + 1, size);
+            System.arraycopy(node.values, index + 1, prev.values, prev.right_idx + 1, size);
+            prev.right_idx += size;
+            prev.size += (node.size - 1);
+            deleteNode(node);
+        } else if (node.next != null && (node.next.left_idx) > node.size) {
+            // move all to next node and kill it
+            Node<K, V> next = node.next;
+            int left_idx = node.left_idx;
+            int next_new_left = next.left_idx - node.size + 1;
+            next.left_idx = next_new_left;
+            int size = index - left_idx;
+            System.arraycopy(node.keys,   left_idx, next.keys,   next_new_left, size);
+            System.arraycopy(node.values, left_idx, next.values, next_new_left, size);
+            next_new_left += size;
+            size = node.right_idx - index;
+            System.arraycopy(node.keys,   index + 1, next.keys,   next_new_left, size);
+            System.arraycopy(node.values, index + 1, next.values, next_new_left, size);
+            next.size += (node.size - 1);
+            deleteNode(node);
+        } else {
+            int moveFromRight = node.right_idx - index;
+            int left_idx = node.left_idx;
+            int moveFromLeft = index - left_idx ;
+            if (moveFromRight <= moveFromLeft) {
+                System.arraycopy(node.keys,   index + 1, node.keys,   index, moveFromRight);
+                System.arraycopy(node.values, index + 1, node.values, index, moveFromRight);
+                Node<K, V> next = node.next;
+                if (next != null && next.size == 1) {
+                    node.keys  [node.right_idx] = next.keys  [next.left_idx];
+                    node.values[node.right_idx] = next.values[next.left_idx];
+                    deleteNode(next);
+                } else {
+                    node.keys  [node.right_idx] = null;
+                    node.values[node.right_idx] = null;
+                    node.right_idx--;
+                    node.size--;
+                }
             } else {
-                x = x.right;
+                System.arraycopy(node.keys,   left_idx , node.keys,   left_idx  + 1, moveFromLeft);
+                System.arraycopy(node.values, left_idx , node.values, left_idx + 1, moveFromLeft);
+                Node<K, V> prev = node.prev;
+                if (prev != null && prev.size == 1) {
+                    node.keys  [left_idx ] = prev.keys  [prev.left_idx];
+                    node.values[left_idx ] = prev.values[prev.left_idx];
+                    deleteNode(prev);
+                } else {
+                    node.keys  [left_idx ] = null;
+                    node.values[left_idx ] = null;
+                    node.left_idx++;
+                    node.size--;
+                }
             }
         }
-        return last;
+        modCount++;
+        size--;
     }
 
-    Entry<K, V> findBefore(K key) {
-        int result;
-        Comparable<K> object = null;
-        if (comparator == null) {
-            object = toComparable(key);
-        }
-        Entry<K, V> x = root, last = null;
-        while (x != null) {
-            result = object != null ? object.compareTo(x.key) : comparator
-                    .compare(key, x.key);
-            if (result <= 0) {
-                x = x.left;
+    void removeFromIterator(Node<K, V> node, int index) {
+        if (node.size == 1) {
+            // it is safe to delete the whole node here.
+            // iterator already moved to the next node;
+            deleteNode(node);
+        } else {
+            int left_idx = node.left_idx;
+            if (index == left_idx) {
+                Node<K, V> prev = node.prev;
+                if (prev != null && prev.size == 1) {
+                    node.keys  [left_idx] = prev.keys  [prev.left_idx];
+                    node.values[left_idx] = prev.values[prev.left_idx];
+                    deleteNode(prev);
+                } else {
+                    node.keys  [left_idx] = null;
+                    node.values[left_idx] = null;
+                    node.left_idx++;
+                    node.size--;
+                }
+            } else if (index == node.right_idx) {
+                node.keys  [index] = null;
+                node.values[index] = null;
+                node.right_idx--;
+                node.size--;
             } else {
-                last = x;
-                x = x.right;
+                int moveFromRight = node.right_idx - index;
+                int moveFromLeft = index - left_idx;
+                if (moveFromRight <= moveFromLeft) {
+                    System.arraycopy(node.keys,   index + 1, node.keys,   index, moveFromRight );
+                    System.arraycopy(node.values, index + 1, node.values, index, moveFromRight );
+                    node.keys  [node.right_idx] = null;
+                    node.values[node.right_idx] = null;
+                    node.right_idx--;
+                    node.size--;
+                } else {
+                    System.arraycopy(node.keys,   left_idx, node.keys,   left_idx+ 1, moveFromLeft);
+                    System.arraycopy(node.values, left_idx, node.values, left_idx+ 1, moveFromLeft);
+                    node.keys  [left_idx] = null;
+                    node.values[left_idx] = null;
+                    node.left_idx++;
+                    node.size--;
+               }
             }
         }
-        return last;
+        modCount++;
+        size--;
     }
 
-    /**
-     * Returns the first key in this map.
-     * 
-     * @return the first key in this map.
-     * @exception NoSuchElementException
-     *                if this sorted map is empty.
-     * @since Android 1.0
-     */
-    public K firstKey() {
-        if (root != null) {
-            return minimum(root).key;
+    private void deleteNode(Node<K, V> node) {
+        if (node.right == null) {
+            if (node.left != null) {
+                attachToParent(node, node.left);
+           } else {
+                attachNullToParent(node);
+            }
+            fixNextChain(node);
+        } else if(node.left == null) { // node.right != null
+            attachToParent(node, node.right);
+            fixNextChain(node);
+        } else {
+            // Here node.left!=nul && node.right!=null
+            // node.next should replace node in tree
+            // node.next!=null by tree logic.
+            // node.next.left==null by tree logic.
+            // node.next.right may be null or non-null
+            Node<K, V> toMoveUp = node.next;
+            fixNextChain(node);
+            if(toMoveUp.right==null){
+                attachNullToParent(toMoveUp);
+            } else {
+                attachToParent(toMoveUp, toMoveUp.right);
+            }
+            // Here toMoveUp is ready to replace node
+            toMoveUp.left = node.left;
+            if (node.left != null) {
+            	node.left.parent = toMoveUp;
+            }
+            toMoveUp.right = node.right;
+            if (node.right != null) {
+            	node.right.parent = toMoveUp;
+            }
+            attachToParentNoFixup(node,toMoveUp);
+            toMoveUp.color = node.color;
         }
-        throw new NoSuchElementException();
     }
 
-    private void fixup(Entry<K, V> x) {
-        Entry<K, V> w;
+    private void attachToParentNoFixup(Node<K, V> toDelete, Node<K, V> toConnect) {
+        // assert toConnect!=null
+        Node<K,V> parent = toDelete.parent;
+        toConnect.parent = parent;
+        if (parent == null) {
+            root = toConnect;
+        } else if (toDelete == parent.left) {
+            parent.left = toConnect;
+        } else {
+            parent.right = toConnect;
+        }
+    }
+
+    private void attachToParent(Node<K, V> toDelete, Node<K, V> toConnect) {
+        // assert toConnect!=null
+        attachToParentNoFixup(toDelete,toConnect);
+        if (!toDelete.color) {
+            fixup(toConnect);
+        }
+    }
+
+    private void attachNullToParent(Node<K, V> toDelete) {
+        Node<K, V> parent = toDelete.parent;
+        if (parent == null) {
+            root = null;
+        } else {
+            if (toDelete == parent.left) {
+                parent.left = null;
+            } else {
+                parent.right = null;
+            }
+            if (!toDelete.color) {
+                fixup(parent);
+            }
+        }
+    }
+
+    private void fixNextChain(Node<K, V> node) {
+        if (node.prev != null) {
+            node.prev.next = node.next;
+        }
+        if (node.next != null) {
+            node.next.prev = node.prev;
+        }
+    }
+
+    private void fixup(Node<K, V> x) {
+        Node<K, V> w;
         while (x != root && !x.color) {
             if (x == x.parent.left) {
                 w = x.parent.right;
@@ -1004,7 +2196,7 @@
                     }
                 }
                 if ((w.left == null || !w.left.color)
-                        && (w.right == null || !w.right.color)) {
+                    && (w.right == null || !w.right.color)) {
                     w.color = true;
                     x = x.parent;
                 } else {
@@ -1037,7 +2229,7 @@
                     }
                 }
                 if ((w.left == null || !w.left.color)
-                        && (w.right == null || !w.right.color)) {
+                    && (w.right == null || !w.right.color)) {
                     w.color = true;
                     x = x.parent;
                 } else {
@@ -1058,321 +2250,11 @@
         x.color = false;
     }
 
-    /**
-     * Returns the value of the mapping with the specified key.
-     * 
-     * @param key
-     *            the key.
-     * @return the value of the mapping with the specified key.
-     * @throws ClassCastException
-     *             if the key cannot be compared with the keys in this map.
-     * @throws NullPointerException
-     *             if the key is {@code null} and the comparator cannot handle
-     *             {@code null}.
-     * @since Android 1.0
-     */
-    @Override
-    public V get(Object key) {
-        Entry<K, V> node = find(key);
-        if (node != null) {
-            return node.value;
-        }
-        return null;
-    }
-
-    /**
-     * Returns a sorted map over a range of this sorted map with all keys that
-     * are less than the specified {@code endKey}. Changes to the returned
-     * sorted map are reflected in this sorted map and vice versa.
-     * <p>
-     * Note: The returned map will not allow an insertion of a key outside the
-     * specified range.
-     * </p>
-     * 
-     * @param endKey
-     *            the high boundary of the range specified.
-     * @return a sorted map where the keys are less than {@code endKey}.
-     * @throws ClassCastException
-     *             if the specified key cannot be compared with the keys in this
-     *             map.
-     * @throws NullPointerException
-     *             if the specified key is {@code null} and the comparator
-     *             cannot handle {@code null} keys.
-     * @throws IllegalArgumentException
-     *             if this map is itself a sorted map over a range of another
-     *             map and the specified key is outside of its range.
-     * @since Android 1.0
-     */
-    public SortedMap<K, V> headMap(K endKey) {
-        // Check for errors
-        if (comparator == null) {
-            toComparable(endKey).compareTo(endKey);
-        } else {
-            comparator.compare(endKey, endKey);
-        }
-        return new SubMap<K, V>(this, endKey);
-    }
-
-    /**
-     * Returns a set of the keys contained in this map. The set is backed by
-     * this map so changes to one are reflected by the other. The set does not
-     * support adding.
-     * 
-     * @return a set of the keys.
-     * @since Android 1.0
-     */
-    @Override
-    public Set<K> keySet() {
-        if (keySet == null) {
-            keySet = new AbstractSet<K>() {
-                @Override
-                public boolean contains(Object object) {
-                    return containsKey(object);
-                }
-
-                @Override
-                public int size() {
-                    return size;
-                }
-
-                @Override
-                public void clear() {
-                    TreeMap.this.clear();
-                }
-
-                @Override
-                public Iterator<K> iterator() {
-                    return new UnboundedKeyIterator<K,V> (TreeMap.this);
-                }
-            };
-        }
-        return keySet;
-    }
-
-    /**
-     * Returns the last key in this map.
-     * 
-     * @return the last key in this map.
-     * @throws NoSuchElementException
-     *             if this map is empty.
-     * @since Android 1.0
-     */
-    public K lastKey() {
-        if (root != null) {
-            return maximum(root).key;
-        }
-        throw new NoSuchElementException();
-    }
-
-    private void leftRotate(Entry<K, V> x) {
-        Entry<K, V> y = x.right;
-        x.right = y.left;
-        if (y.left != null) {
-            y.left.parent = x;
-        }
-        y.parent = x.parent;
-        if (x.parent == null) {
-            root = y;
-        } else {
-            if (x == x.parent.left) {
-                x.parent.left = y;
-            } else {
-                x.parent.right = y;
-            }
-        }
-        y.left = x;
-        x.parent = y;
-    }
-
-    static <K, V> Entry<K, V> maximum(Entry<K, V> x) {
-        while (x.right != null) {
-            x = x.right;
-        }
-        return x;
-    }
-
-    static <K, V> Entry<K, V> minimum(Entry<K, V> x) {
-        while (x.left != null) {
-            x = x.left;
-        }
-        return x;
-    }
-
-    static <K, V> Entry<K, V> predecessor(Entry<K, V> x) {
-        if (x.left != null) {
-            return maximum(x.left);
-        }
-        Entry<K, V> y = x.parent;
-        while (y != null && x == y.left) {
-            x = y;
-            y = y.parent;
-        }
-        return y;
-    }
-
-    /**
-     * Maps the specified key to the specified value.
-     * 
-     * @param key
-     *            the key.
-     * @param value
-     *            the value.
-     * @return the value of any previous mapping with the specified key or
-     *         {@code null} if there was no mapping.
-     * @throws ClassCastException
-     *             if the specified key cannot be compared with the keys in this
-     *             map.
-     * @throws NullPointerException
-     *             if the specified key is {@code null} and the comparator
-     *             cannot handle {@code null} keys.
-     * @since Android 1.0
-     */
-    @Override
-    public V put(K key, V value) {
-        MapEntry<K, V> entry = rbInsert(key);
-        V result = entry.value;
-        entry.value = value;
-        return result;
-    }
-
-    /**
-     * Copies all the mappings in the given map to this map. These mappings will
-     * replace all mappings that this map had for any of the keys currently in
-     * the given map.
-     * 
-     * @param map
-     *            the map to copy mappings from.
-     * @throws ClassCastException
-     *             if a key in the specified map cannot be compared with the
-     *             keys in this map.
-     * @throws NullPointerException
-     *             if a key in the specified map is {@code null} and the
-     *             comparator cannot handle {@code null} keys.
-     * @since Android 1.0
-     */
-    @Override
-    public void putAll(Map<? extends K, ? extends V> map) {
-        super.putAll(map);
-    }
-
-    void rbDelete(Entry<K, V> z) {
-        Entry<K, V> y = z.left == null || z.right == null ? z : successor(z);
-        Entry<K, V> x = y.left != null ? y.left : y.right;
-        if (x != null) {
-            x.parent = y.parent;
-        }
-        if (y.parent == null) {
-            root = x;
-        } else if (y == y.parent.left) {
-            y.parent.left = x;
-        } else {
-            y.parent.right = x;
-        }
-        modCount++;
-        if (y != z) {
-            z.key = y.key;
-            z.value = y.value;
-        }
-        if (!y.color && root != null) {
-            if (x == null) {
-                fixup(y.parent);
-            } else {
-                fixup(x);
-            }
-        }
-        size--;
-    }
-
-    private Entry<K, V> rbInsert(K object) {
-        int result = 0;
-        Entry<K, V> y = null;
-        if (size != 0) {
-            Comparable<K> key = null;
-            if (comparator == null) {
-                key = toComparable(object);
-            }
-            Entry<K, V> x = root;
-            while (x != null) {
-                y = x;
-                result = key != null ? key.compareTo(x.key) : comparator
-                        .compare(object, x.key);
-                if (result == 0) {
-                    return x;
-                }
-                x = result < 0 ? x.left : x.right;
-            }
-        }
-
-        size++;
-        modCount++;
-        Entry<K, V> z = new Entry<K, V>(object);
-        if (y == null) {
-            return root = z;
-        }
-        z.parent = y;
-        if (result < 0) {
-            y.left = z;
-        } else {
-            y.right = z;
-        }
-        balance(z);
-        return z;
-    }
-
-    /**
-     * Removes the mapping with the specified key from this map.
-     * 
-     * @param key
-     *            the key of the mapping to remove.
-     * @return the value of the removed mapping or {@code null} if no mapping
-     *         for the specified key was found.
-     * @throws ClassCastException
-     *             if the specified key cannot be compared with the keys in this
-     *             map.
-     * @throws NullPointerException
-     *             if the specified key is {@code null} and the comparator
-     *             cannot handle {@code null} keys.
-     * @since Android 1.0
-     */
-    @Override
-    public V remove(Object key) {
-        if (size == 0) {
-            return null;
-        }
-        Entry<K, V> node = find(key);
-        if (node == null) {
-            return null;
-        }
-        V result = node.value;
-        rbDelete(node);
-        return result;
-    }
-
-    private void rightRotate(Entry<K, V> x) {
-        Entry<K, V> y = x.left;
-        x.left = y.right;
-        if (y.right != null) {
-            y.right.parent = x;
-        }
-        y.parent = x.parent;
-        if (x.parent == null) {
-            root = y;
-        } else {
-            if (x == x.parent.right) {
-                x.parent.right = y;
-            } else {
-                x.parent.left = y;
-            }
-        }
-        y.right = x;
-        x.parent = y;
-    }
 
     /**
      * Returns the number of mappings in this map.
-     * 
+     *
      * @return the number of mappings in this map.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -1387,8 +2269,7 @@
      * <p>
      * Note: The returned map will not allow an insertion of a key outside the
      * specified range.
-     * </p>
-     * 
+     *
      * @param startKey
      *            the low boundary of the range (inclusive).
      * @param endKey
@@ -1404,7 +2285,6 @@
      *             if the start key is greater than the end key, or if this map
      *             is itself a sorted map over a range of another sorted map and
      *             the specified range is outside of its range.
-     * @since Android 1.0
      */
     public SortedMap<K, V> subMap(K startKey, K endKey) {
         if (comparator == null) {
@@ -1419,18 +2299,6 @@
         throw new IllegalArgumentException();
     }
 
-    static <K, V> Entry<K, V> successor(Entry<K, V> x) {
-        if (x.right != null) {
-            return minimum(x.right);
-        }
-        Entry<K, V> y = x.parent;
-        while (y != null && x == y.right) {
-            x = y;
-            y = y.parent;
-        }
-        return y;
-    }
-
     /**
      * Returns a sorted map over a range of this sorted map with all keys that
      * are greater than or equal to the specified {@code startKey}. Changes to
@@ -1438,8 +2306,7 @@
      * <p>
      * Note: The returned map will not allow an insertion of a key outside the
      * specified range.
-     * </p>
-     * 
+     *
      * @param startKey
      *            the low boundary of the range specified.
      * @return a sorted map where the keys are greater or equal to
@@ -1453,7 +2320,6 @@
      * @throws IllegalArgumentException
      *             if this map itself a sorted map over a range of another map
      *             and the specified key is outside of its range.
-     * @since Android 1.0
      */
     public SortedMap<K, V> tailMap(K startKey) {
         // Check for errors
@@ -1476,16 +2342,13 @@
      * "wrapper object" over the iterator of map's entrySet(). The {@code size}
      * method wraps the map's size method and the {@code contains} method wraps
      * the map's containsValue method.
-     * </p>
      * <p>
      * The collection is created when this method is called for the first time
      * and returned in response to all subsequent calls. This method may return
      * different collections when multiple concurrent calls occur, since no
      * synchronization is performed.
-     * </p>
-     * 
+     *
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     @Override
     public Collection<V> values() {
@@ -1508,7 +2371,7 @@
 
                 @Override
                 public Iterator<V> iterator() {
-                    return new UnboundedValueIterator<K,V> (TreeMap.this);
+                    return new UnboundedValueIterator<K, V>(TreeMap.this);
                 }
             };
         }
@@ -1519,32 +2382,26 @@
         stream.defaultWriteObject();
         stream.writeInt(size);
         if (size > 0) {
-            Entry<K, V> node = minimum(root);
+            Node<K, V> node = minimum(root);
             while (node != null) {
-                stream.writeObject(node.key);
-                stream.writeObject(node.value);
-                node = successor(node);
+                int to = node.right_idx;
+                for (int i = node.left_idx; i <= to; i++) {
+                    stream.writeObject(node.keys[i]);
+                    stream.writeObject(node.values[i]);
+                }
+                node = node.next;
             }
         }
     }
 
     @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream stream) throws IOException,
-            ClassNotFoundException {
+                                                          ClassNotFoundException {
         stream.defaultReadObject();
-        size = stream.readInt();
-        Entry<K, V> last = null;
-        for (int i = size; --i >= 0;) {
-            Entry<K, V> node = new Entry<K, V>((K)stream.readObject());
-            node.value = (V)stream.readObject();
-            if (last == null) {
-                root = node;
-            } else {
-                node.parent = last;
-                last.right = node;
-                balance(node);
-            }
-            last = node;
+        int size = stream.readInt();
+        Node<K, V> lastNode = null;
+        for (int i = 0; i < size; i++) {
+            lastNode = addToLast(lastNode, (K) stream.readObject(), (V) stream.readObject());
         }
     }
 }
diff --git a/luni/src/main/java/java/util/TreeSet.java b/luni/src/main/java/java/util/TreeSet.java
index bfd572f..375b9c8 100644
--- a/luni/src/main/java/java/util/TreeSet.java
+++ b/luni/src/main/java/java/util/TreeSet.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -28,25 +27,23 @@
  * and removing) are supported. The elements can be any objects which are
  * comparable to each other either using their natural order or a specified
  * Comparator.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
-public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneable,
-        Serializable {
-    
+public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>,
+        Cloneable, Serializable {
+
     private static final long serialVersionUID = -2479143000061671589L;
 
     private transient SortedMap<E, E> backingMap;
 
-    private TreeSet(SortedMap<E,E> map) {
+    private TreeSet(SortedMap<E, E> map) {
         this.backingMap = map;
     }
 
     /**
      * Constructs a new empty instance of {@code TreeSet} which uses natural
      * ordering.
-     * 
-     * @since Android 1.0
      */
     public TreeSet() {
         backingMap = new TreeMap<E, E>();
@@ -55,14 +52,13 @@
     /**
      * Constructs a new instance of {@code TreeSet} which uses natural ordering
      * and containing the unique elements in the specified collection.
-     * 
+     *
      * @param collection
      *            the collection of elements to add.
      * @throws ClassCastException
      *                when an element in the collection does not implement the
      *                Comparable interface, or the elements in the collection
      *                cannot be compared.
-     * @since Android 1.0
      */
     public TreeSet(Collection<? extends E> collection) {
         this();
@@ -72,10 +68,9 @@
     /**
      * Constructs a new empty instance of {@code TreeSet} which uses the
      * specified comparator.
-     * 
+     *
      * @param comparator
      *            the comparator to use.
-     * @since Android 1.0
      */
     public TreeSet(Comparator<? super E> comparator) {
         backingMap = new TreeMap<E, E>(comparator);
@@ -84,10 +79,9 @@
     /**
      * Constructs a new instance of {@code TreeSet} containing the elements of
      * the specified SortedSet and using the same Comparator.
-     * 
+     *
      * @param set
      *            the SortedSet of elements to add.
-     * @since Android 1.0
      */
     public TreeSet(SortedSet<E> set) {
         this(set.comparator());
@@ -99,7 +93,7 @@
 
     /**
      * Adds the specified object to this {@code TreeSet}.
-     * 
+     *
      * @param object
      *            the object to add.
      * @return {@code true} when this {@code TreeSet} did not already contain
@@ -110,7 +104,6 @@
      * @throws NullPointerException
      *             when the object is null and the comparator cannot handle
      *             null.
-     * @since Android 1.0
      */
     @Override
     public boolean add(E object) {
@@ -119,7 +112,7 @@
 
     /**
      * Adds the objects in the specified collection to this {@code TreeSet}.
-     * 
+     *
      * @param collection
      *            the collection of objects to add.
      * @return {@code true} if this {@code TreeSet} was modified, {@code false}
@@ -130,7 +123,6 @@
      * @throws NullPointerException
      *             when an object in the collection is null and the comparator
      *             cannot handle null.
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(Collection<? extends E> collection) {
@@ -139,10 +131,9 @@
 
     /**
      * Removes all elements from this {@code TreeSet}, leaving it empty.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -152,10 +143,9 @@
     /**
      * Returns a new {@code TreeSet} with the same elements, size and comparator
      * as this {@code TreeSet}.
-     * 
+     *
      * @return a shallow copy of this {@code TreeSet}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     @Override
@@ -163,7 +153,8 @@
         try {
             TreeSet<E> clone = (TreeSet<E>) super.clone();
             if (backingMap instanceof TreeMap) {
-                clone.backingMap = (SortedMap<E, E>) ((TreeMap<E, E>) backingMap).clone();
+                clone.backingMap = (SortedMap<E, E>) ((TreeMap<E, E>) backingMap)
+                        .clone();
             } else {
                 clone.backingMap = new TreeMap<E, E>(backingMap);
             }
@@ -175,9 +166,8 @@
 
     /**
      * Returns the comparator used to compare elements in this {@code TreeSet}.
-     * 
+     *
      * @return a Comparator or null if the natural ordering is used
-     * @since Android 1.0
      */
     public Comparator<? super E> comparator() {
         return backingMap.comparator();
@@ -185,7 +175,7 @@
 
     /**
      * Searches this {@code TreeSet} for the specified object.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return {@code true} if {@code object} is an element of this
@@ -196,7 +186,6 @@
      * @throws NullPointerException
      *             when the object is null and the comparator cannot handle
      *             null.
-     * @since Android 1.0
      */
     @Override
     public boolean contains(Object object) {
@@ -205,11 +194,10 @@
 
     /**
      * Returns the first element in this {@code TreeSet}.
-     * 
+     *
      * @return the first element.
      * @throws NoSuchElementException
      *             when this {@code TreeSet} is empty.
-     * @since Android 1.0
      */
     public E first() {
         return backingMap.firstKey();
@@ -220,7 +208,7 @@
      * which contains elements which are all less than the end element. The
      * returned SortedSet is backed by this {@code TreeSet} so changes to one
      * are reflected by the other.
-     * 
+     *
      * @param end
      *            the end element.
      * @return a subset where the elements are less than {@code end}
@@ -230,7 +218,6 @@
      * @throws NullPointerException
      *             when the end object is null and the comparator cannot handle
      *             null.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public SortedSet<E> headSet(E end) {
@@ -246,10 +233,9 @@
 
     /**
      * Returns true if this {@code TreeSet} has no element, otherwise false.
-     * 
+     *
      * @return true if this {@code TreeSet} has no element.
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public boolean isEmpty() {
@@ -258,10 +244,9 @@
 
     /**
      * Returns an Iterator on the elements of this {@code TreeSet}.
-     * 
+     *
      * @return an Iterator on the elements of this {@code TreeSet}.
      * @see Iterator
-     * @since Android 1.0
      */
     @Override
     public Iterator<E> iterator() {
@@ -271,11 +256,10 @@
     /**
      * Returns the last element in this {@code TreeSet}. The last element is
      * the highest element.
-     * 
+     *
      * @return the last element.
      * @throws NoSuchElementException
      *             when this {@code TreeSet} is empty.
-     * @since Android 1.0
      */
     public E last() {
         return backingMap.lastKey();
@@ -283,7 +267,7 @@
 
     /**
      * Removes an occurrence of the specified object from this {@code TreeSet}.
-     * 
+     *
      * @param object
      *            the object to remove.
      * @return {@code true} if this {@code TreeSet} was modified, {@code false}
@@ -294,7 +278,6 @@
      * @throws NullPointerException
      *             when the object is null and the comparator cannot handle
      *             null.
-     * @since Android 1.0
      */
     @Override
     public boolean remove(Object object) {
@@ -303,9 +286,8 @@
 
     /**
      * Returns the number of elements in this {@code TreeSet}.
-     * 
+     *
      * @return the number of elements in this {@code TreeSet}.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -317,7 +299,7 @@
      * which contains elements greater or equal to the start element but less
      * than the end element. The returned SortedSet is backed by this
      * {@code TreeSet} so changes to one are reflected by the other.
-     * 
+     *
      * @param start
      *            the start element.
      * @param end
@@ -330,7 +312,6 @@
      * @throws NullPointerException
      *             when the start or end object is null and the comparator
      *             cannot handle null.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public SortedSet<E> subSet(E start, E end) {
@@ -352,7 +333,7 @@
      * which contains elements greater or equal to the start element. The
      * returned SortedSet is backed by this {@code TreeSet} so changes to one
      * are reflected by the other.
-     * 
+     *
      * @param start
      *            the start element.
      * @return a subset where the elements are greater or equal to {@code start}
@@ -362,7 +343,6 @@
      * @throws NullPointerException
      *             when the start object is null and the comparator cannot
      *             handle null.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public SortedSet<E> tailSet(E start) {
@@ -391,23 +371,16 @@
 
     @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream stream) throws IOException,
-    ClassNotFoundException {
+            ClassNotFoundException {
         stream.defaultReadObject();
-        TreeMap<E, E> map = new TreeMap<E, E>((Comparator<? super E>) stream.readObject());
+        TreeMap<E, E> map = new TreeMap<E, E>((Comparator<? super E>) stream
+                .readObject());
         int size = stream.readInt();
         if (size > 0) {
-            E key = (E)stream.readObject();
-            TreeMap.Entry<E,E> last = new TreeMap.Entry<E,E>(key,key);
-            map.root = last;
-            map.size = 1;
-            for (int i=1; i<size; i++) {
-                key = (E)stream.readObject();
-                TreeMap.Entry<E,E> x = new TreeMap.Entry<E,E>(key,key);
-                x.parent = last;
-                last.right = x;
-                map.size++;
-                map.balance(x);
-                last = x;
+            TreeMap.Node<E,E> lastNode = null;
+            for(int i=0; i<size; i++) {
+                E elem = (E)stream.readObject();
+                lastNode = map.addToLast(lastNode,elem,elem);
             }
         }
         backingMap = map;
diff --git a/luni/src/main/java/java/util/UUID.java b/luni/src/main/java/java/util/UUID.java
index a5ab702..081e900 100644
--- a/luni/src/main/java/java/util/UUID.java
+++ b/luni/src/main/java/java/util/UUID.java
@@ -27,19 +27,16 @@
 import org.apache.harmony.luni.util.Msg;
 
 /**
- * <p>
  * UUID is an immutable representation of a 128-bit universally unique
  * identifier (UUID).
- * </p>
  * <p>
  * There are multiple, variant layouts of UUIDs, but this class is based upon
  * variant 2 of <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>, the
  * Leach-Salz variant. This class can be used to model alternate variants, but
  * most of the methods will be unsupported in those cases; see each method for
  * details.
- * </p>
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public final class UUID implements Serializable, Comparable<UUID> {
 
@@ -60,13 +57,11 @@
     /**
      * <p>
      * Constructs an instance with the specified bits.
-     * </p>
-     * 
+     *
      * @param mostSigBits
      *            The 64 most significant bits of the UUID.
      * @param leastSigBits
      *            The 64 least significant bits of the UUID.
-     * @since Android 1.0
      */
     public UUID(long mostSigBits, long leastSigBits) {
         super();
@@ -79,7 +74,6 @@
      * <p>
      * Sets up the transient fields of this instance based on the current values
      * of the {@code mostSigBits} and {@code leastSigBits} fields.
-     * </p>
      */
     private void init() {
         // setup hash field
@@ -123,10 +117,8 @@
      * <p>
      * Generates a variant 2, version 4 (randomly generated number) UUID as per
      * <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * @return an UUID instance.
-     * @since Android 1.0
      */
     public static UUID randomUUID() {
         byte[] data;
@@ -135,9 +127,8 @@
             if (rng == null) {
                 rng = new SecureRandom();
             }
-            rng.nextBytes(data = new byte[16]);
         }
-
+        rng.nextBytes(data = new byte[16]);
         long msb = (data[0] & 0xFFL) << 56;
         msb |= (data[1] & 0xFFL) << 48;
         msb |= (data[2] & 0xFFL) << 40;
@@ -164,12 +155,10 @@
      * <p>
      * Generates a variant 2, version 3 (name-based, MD5-hashed) UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * @param name
      *            the name used as byte array to create an UUID.
      * @return an UUID instance.
-     * @since Android 1.0
      */
     public static UUID nameUUIDFromBytes(byte[] name) {
         if (name == null) {
@@ -209,57 +198,57 @@
     /**
      * <p>
      * Parses a UUID string with the format defined by {@link #toString()}.
-     * </p>
-     * 
+     *
      * @param uuid
      *            the UUID string to parse.
      * @return an UUID instance.
+     * @throws NullPointerException
+     *             if {@code uuid} is {@code null}.
      * @throws IllegalArgumentException
      *             if {@code uuid} is not formatted correctly.
-     * @since Android 1.0
      */
     public static UUID fromString(String uuid) {
         if (uuid == null) {
             throw new NullPointerException();
         }
-        
+
         int[] position = new int[5];
         int lastPosition = 1;
         int startPosition = 0;
-        
+
         int i = 0;
-        for (; i < position.length  && lastPosition > 0; i++) {
+        for (; i < position.length && lastPosition > 0; i++) {
             position[i] = uuid.indexOf("-", startPosition); //$NON-NLS-1$
             lastPosition = position[i];
             startPosition = position[i] + 1;
         }
 
         // should have and only can have four "-" in UUID
-        if(i != position.length || lastPosition != -1)
-        {
+        if (i != position.length || lastPosition != -1) {
             throw new IllegalArgumentException(Msg.getString("KA014") + uuid); //$NON-NLS-1$
         }
 
         long m1 = Long.parseLong(uuid.substring(0, position[0]), 16);
-        long m2 = Long.parseLong(uuid.substring(position[0]+ 1, position[1]), 16);
-        long m3 = Long.parseLong(uuid.substring(position[1] + 1, position[2]), 16);
+        long m2 = Long.parseLong(uuid.substring(position[0] + 1, position[1]),
+                16);
+        long m3 = Long.parseLong(uuid.substring(position[1] + 1, position[2]),
+                16);
 
-        long lsb1 = Long.parseLong(uuid.substring(position[2] + 1, position[3]), 16);
-        long lsb2 = Long.parseLong(uuid.substring(position[3]+ 1), 16);
+        long lsb1 = Long.parseLong(
+                uuid.substring(position[2] + 1, position[3]), 16);
+        long lsb2 = Long.parseLong(uuid.substring(position[3] + 1), 16);
 
         long msb = (m1 << 32) | (m2 << 16) | m3;
         long lsb = (lsb1 << 48) | lsb2;
-        
+
         return new UUID(msb, lsb);
     }
 
     /**
      * <p>
      * The 64 least significant bits of the UUID.
-     * </p>
-     * 
+     *
      * @return the 64 least significant bits.
-     * @since Android 1.0
      */
     public long getLeastSignificantBits() {
         return leastSigBits;
@@ -268,10 +257,8 @@
     /**
      * <p>
      * The 64 most significant bits of the UUID.
-     * </p>
-     * 
+     *
      * @return the 64 most significant bits.
-     * @since Android 1.0
      */
     public long getMostSignificantBits() {
         return mostSigBits;
@@ -282,7 +269,6 @@
      * The version of the variant 2 UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. If the variant
      * is not 2, then the version will be 0.
-     * </p>
      * <ul>
      * <li>1 - Time-based UUID</li>
      * <li>2 - DCE Security UUID</li>
@@ -290,9 +276,8 @@
      * <li>4 - Randomly generated UUID ({@link #randomUUID()})</li>
      * <li>5 - Name-based with SHA-1 hashing UUID</li>
      * </ul>
-     * 
+     *
      * @return an {@code int} value.
-     * @since Android 1.0
      */
     public int version() {
         return version;
@@ -302,16 +287,14 @@
      * <p>
      * The variant of the UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
      * <ul>
      * <li>0 - Reserved for NCS compatibility</li>
      * <li>2 - RFC 4122/Leach-Salz</li>
      * <li>6 - Reserved for Microsoft Corporation compatibility</li>
      * <li>7 - Reserved for future use</li>
      * </ul>
-     * 
+     *
      * @return an {@code int} value.
-     * @since Android 1.0
      */
     public int variant() {
         return variant;
@@ -321,12 +304,10 @@
      * <p>
      * The timestamp value of the version 1, variant 2 UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * @return a {@code long} value.
      * @throws UnsupportedOperationException
      *             if {@link #version()} is not 1.
-     * @since Android 1.0
      */
     public long timestamp() {
         if (version != 1) {
@@ -339,12 +320,10 @@
      * <p>
      * The clock sequence value of the version 1, variant 2 UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * @return a {@code long} value.
      * @throws UnsupportedOperationException
      *             if {@link #version()} is not 1.
-     * @since Android 1.0
      */
     public int clockSequence() {
         if (version != 1) {
@@ -357,12 +336,10 @@
      * <p>
      * The node value of the version 1, variant 2 UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * @return a {@code long} value.
      * @throws UnsupportedOperationException
      *             if {@link #version()} is not 1.
-     * @since Android 1.0
      */
     public long node() {
         if (version != 1) {
@@ -376,13 +353,11 @@
      * Compares this UUID to the specified UUID. The natural ordering of UUIDs
      * is based upon the value of the bits from most significant to least
      * significant.
-     * </p>
-     * 
+     *
      * @param uuid
      *            the UUID to compare to.
      * @return a value of -1, 0 or 1 if this UUID is less than, equal to or
      *         greater than {@code uuid}.
-     * @since Android 1.0
      */
     public int compareTo(UUID uuid) {
         if (uuid == this) {
@@ -409,13 +384,11 @@
      * Compares this UUID to another object for equality. If {@code object}
      * is not {@code null}, is a UUID instance, and all bits are equal, then
      * {@code true} is returned.
-     * </p>
-     * 
+     *
      * @param object
      *            the {@code Object} to compare to.
      * @return {@code true} if this UUID is equal to {@code object}
      *         or {@code false} if not.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -441,10 +414,8 @@
      * <p>
      * Returns a hash value for this UUID that is consistent with the
      * {@link #equals(Object)} method.
-     * </p>
-     * 
+     *
      * @return an {@code int} value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -455,8 +426,7 @@
      * <p>
      * Returns a string representation of this UUID in the following format, as
      * per <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * <pre>
      *            UUID                   = time-low &quot;-&quot; time-mid &quot;-&quot;
      *                                     time-high-and-version &quot;-&quot;
@@ -474,9 +444,8 @@
      *                &quot;a&quot; / &quot;b&quot; / &quot;c&quot; / &quot;d&quot; / &quot;e&quot; / &quot;f&quot; /
      *                &quot;A&quot; / &quot;B&quot; / &quot;C&quot; / &quot;D&quot; / &quot;E&quot; / &quot;F&quot;
      * </pre>
-     * 
+     *
      * @return a String instance.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -507,8 +476,7 @@
     /**
      * <p>
      * Resets the transient fields to match the behavior of the constructor.
-     * </p>
-     * 
+     *
      * @param in
      *            the {@code InputStream} to read from.
      * @throws IOException
diff --git a/luni/src/main/java/java/util/UnknownFormatConversionException.java b/luni/src/main/java/java/util/UnknownFormatConversionException.java
index 19b9b6d..8bb9441 100644
--- a/luni/src/main/java/java/util/UnknownFormatConversionException.java
+++ b/luni/src/main/java/java/util/UnknownFormatConversionException.java
@@ -22,7 +22,6 @@
  * conversion is unknown.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class UnknownFormatConversionException extends IllegalFormatException {
     private static final long serialVersionUID = 19060418L;
diff --git a/luni/src/main/java/java/util/UnknownFormatFlagsException.java b/luni/src/main/java/java/util/UnknownFormatFlagsException.java
index 837328a..2a1b075 100644
--- a/luni/src/main/java/java/util/UnknownFormatFlagsException.java
+++ b/luni/src/main/java/java/util/UnknownFormatFlagsException.java
@@ -23,7 +23,6 @@
  * an unknown flag.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class UnknownFormatFlagsException extends IllegalFormatException {
 
diff --git a/luni/src/main/java/java/util/Vector.java b/luni/src/main/java/java/util/Vector.java
index 7a5c775..8634c13 100644
--- a/luni/src/main/java/java/util/Vector.java
+++ b/luni/src/main/java/java/util/Vector.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
@@ -36,26 +35,21 @@
  * The capacity of a vector may be specified when the vector is created. If the
  * capacity of the vector is exceeded, the capacity is increased (doubled by
  * default).
- * 
+ *
  * @see java.lang.StringBuffer
- * @since Android 1.0
  */
-public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess,
-        Cloneable, Serializable {
-    
+public class Vector<E> extends AbstractList<E> implements List<E>,
+        RandomAccess, Cloneable, Serializable {
+
     private static final long serialVersionUID = -2767605614048989439L;
 
     /**
      * The number of elements or the size of the vector.
-     * 
-     * @since Android 1.0
      */
     protected int elementCount;
 
     /**
      * The elements of the vector.
-     * 
-     * @since Android 1.0
      */
     protected Object[] elementData;
 
@@ -63,8 +57,6 @@
      * How many elements should be added to the vector when it is detected that
      * it needs to grow to accommodate extra entries. If this value is zero or
      * negative the size will be doubled if an increase is needed.
-     * 
-     * @since Android 1.0
      */
     protected int capacityIncrement;
 
@@ -72,8 +64,6 @@
 
     /**
      * Constructs a new vector using the default capacity.
-     * 
-     * @since Android 1.0
      */
     public Vector() {
         this(DEFAULT_SIZE, 0);
@@ -81,12 +71,11 @@
 
     /**
      * Constructs a new vector using the specified capacity.
-     * 
+     *
      * @param capacity
      *            the initial capacity of the new vector.
      * @throws IllegalArgumentException
      *             if {@code capacity} is negative.
-     * @since Android 1.0
      */
     public Vector(int capacity) {
         this(capacity, 0);
@@ -95,22 +84,20 @@
     /**
      * Constructs a new vector using the specified capacity and capacity
      * increment.
-     * 
+     *
      * @param capacity
      *            the initial capacity of the new vector.
      * @param capacityIncrement
      *            the amount to increase the capacity when this vector is full.
      * @throws IllegalArgumentException
      *             if {@code capacity} is negative.
-     * @since Android 1.0
      */
     public Vector(int capacity, int capacityIncrement) {
-        elementCount = 0;
-        try {
-            elementData = newElementArray(capacity);
-        } catch (NegativeArraySizeException e) {
+        if (capacity < 0) {
             throw new IllegalArgumentException();
         }
+        elementData = newElementArray(capacity);
+        elementCount = 0;
         this.capacityIncrement = capacityIncrement;
     }
 
@@ -118,10 +105,9 @@
      * Constructs a new instance of {@code Vector} containing the elements in
      * {@code collection}. The order of the elements in the new {@code Vector}
      * is dependent on the iteration order of the seed collection.
-     * 
+     *
      * @param collection
      *            the collection of elements to add.
-     * @since Android 1.0
      */
     public Vector(Collection<? extends E> collection) {
         this(collection.size(), 0);
@@ -130,10 +116,10 @@
             elementData[elementCount++] = it.next();
         }
     }
-    
+
     @SuppressWarnings("unchecked")
     private E[] newElementArray(int size) {
-        return (E[])new Object[size];
+        return (E[]) new Object[size];
     }
 
     /**
@@ -141,16 +127,15 @@
      * object is inserted before any element with the same or a higher index
      * increasing their index by 1. If the location is equal to the size of this
      * vector, the object is added at the end.
-     * 
+     *
      * @param location
      *            the index at which to insert the element.
      * @param object
      *            the object to insert in this vector.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location > size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location > size()}.
      * @see #addElement
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void add(int location, E object) {
@@ -159,15 +144,18 @@
 
     /**
      * Adds the specified object at the end of this vector.
-     * 
+     *
      * @param object
      *            the object to add to the vector.
      * @return {@code true}
-     * @since Android 1.0
      */
     @Override
-    public boolean add(E object) {
-        addElement(object);
+    public synchronized boolean add(E object) {
+        if (elementCount == elementData.length) {
+            growByOne();
+        }
+        elementData[elementCount++] = object;
+        modCount++;
         return true;
     }
 
@@ -177,18 +165,18 @@
      * returned from the Collection iterator. The elements with an index equal
      * or higher than {@code location} have their index increased by the size of
      * the added collection.
-     * 
+     *
      * @param location
      *            the location to insert the objects.
      * @param collection
      *            the collection of objects.
      * @return {@code true} if this vector is modified, {@code false} otherwise.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0} or {@code location > size()}.
-     * @since Android 1.0
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0} or {@code location > size()}.
      */
     @Override
-    public synchronized boolean addAll(int location, Collection<? extends E> collection) {
+    public synchronized boolean addAll(int location,
+            Collection<? extends E> collection) {
         if (0 <= location && location <= elementCount) {
             int size = collection.size();
             if (size == 0) {
@@ -216,11 +204,10 @@
 
     /**
      * Adds the objects in the specified collection to the end of this vector.
-     * 
+     *
      * @param collection
      *            the collection of objects.
      * @return {@code true} if this vector is modified, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean addAll(Collection<? extends E> collection) {
@@ -229,10 +216,9 @@
 
     /**
      * Adds the specified object at the end of this vector.
-     * 
+     *
      * @param object
      *            the object to add to the vector.
-     * @since Android 1.0
      */
     public synchronized void addElement(E object) {
         if (elementCount == elementData.length) {
@@ -244,11 +230,10 @@
 
     /**
      * Returns the number of elements this vector can hold without growing.
-     * 
+     *
      * @return the capacity of this vector.
      * @see #ensureCapacity
      * @see #size
-     * @since Android 1.0
      */
     public synchronized int capacity() {
         return elementData.length;
@@ -256,10 +241,9 @@
 
     /**
      * Removes all elements from this vector, leaving it empty.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -269,10 +253,9 @@
     /**
      * Returns a new vector with the same elements, size, capacity and capacity
      * increment as this vector.
-     * 
+     *
      * @return a shallow copy of this vector.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -288,7 +271,7 @@
 
     /**
      * Searches this vector for the specified object.
-     * 
+     *
      * @param object
      *            the object to look for in this vector.
      * @return {@code true} if object is an element of this vector,
@@ -296,7 +279,6 @@
      * @see #indexOf(Object)
      * @see #indexOf(Object, int)
      * @see java.lang.Object#equals
-     * @since Android 1.0
      */
     @Override
     public boolean contains(Object object) {
@@ -305,12 +287,11 @@
 
     /**
      * Searches this vector for all objects in the specified collection.
-     * 
+     *
      * @param collection
      *            the collection of objects.
      * @return {@code true} if all objects in the specified collection are
      *         elements of this vector, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean containsAll(Collection<?> collection) {
@@ -320,14 +301,13 @@
     /**
      * Attempts to copy elements contained by this {@code Vector} into the
      * corresponding elements of the supplied {@code Object} array.
-     * 
+     *
      * @param elements
      *            the {@code Object} array into which the elements of this
      *            vector are copied.
      * @throws IndexOutOfBoundsException
      *             if {@code elements} is not big enough.
      * @see #clone
-     * @since Android 1.0
      */
     public synchronized void copyInto(Object[] elements) {
         System.arraycopy(elementData, 0, elements, 0, elementCount);
@@ -335,18 +315,18 @@
 
     /**
      * Returns the element at the specified location in this vector.
-     * 
+     *
      * @param location
      *            the index of the element to return in this vector.
      * @return the element at the specified location.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      * @see #size
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public synchronized E elementAt(int location) {
         if (location < elementCount) {
-            return (E)elementData[location];
+            return (E) elementData[location];
         }
         throw new ArrayIndexOutOfBoundsException(location);
     }
@@ -354,26 +334,24 @@
     /**
      * Returns an enumeration on the elements of this vector. The results of the
      * enumeration may be affected if the contents of this vector is modified.
-     * 
+     *
      * @return an enumeration of the elements of this vector.
      * @see #elementAt
      * @see Enumeration
-     * @since Android 1.0
      */
     public Enumeration<E> elements() {
         return new Enumeration<E>() {
             int pos = 0;
 
             public boolean hasMoreElements() {
-                synchronized (Vector.this) {
-                    return pos < elementCount;
-                }
+                return pos < elementCount;
             }
 
+            @SuppressWarnings("unchecked")
             public E nextElement() {
                 synchronized (Vector.this) {
                     if (pos < elementCount) {
-                        return (E)elementData[pos++];
+                        return (E) elementData[pos++];
                     }
                 }
                 throw new NoSuchElementException();
@@ -384,12 +362,11 @@
     /**
      * Ensures that this vector can hold the specified number of elements
      * without growing.
-     * 
+     *
      * @param minimumCapacity
      *            the minimum number of elements that this vector will hold
      *            before growing.
      * @see #capacity
-     * @since Android 1.0
      */
     public synchronized void ensureCapacity(int minimumCapacity) {
         if (elementData.length < minimumCapacity) {
@@ -404,13 +381,12 @@
      * Compares the specified object to this vector and returns if they are
      * equal. The object must be a List which contains the same objects in the
      * same order.
-     * 
+     *
      * @param object
      *            the object to compare with this object
      * @return {@code true} if the specified object is equal to this vector,
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean equals(Object object) {
@@ -418,8 +394,8 @@
             return true;
         }
         if (object instanceof List) {
-            List<?> list = (List) object;
-            if (list.size() != size()) {
+            List<?> list = (List<?>) object;
+            if (list.size() != elementCount) {
                 return false;
             }
 
@@ -438,35 +414,34 @@
 
     /**
      * Returns the first element in this vector.
-     * 
+     *
      * @return the element at the first position.
-     * @exception NoSuchElementException
-     *                when this vector is empty.
+     * @throws NoSuchElementException
+     *                if this vector is empty.
      * @see #elementAt
      * @see #lastElement
      * @see #size
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public synchronized E firstElement() {
         if (elementCount > 0) {
-            return (E)elementData[0];
+            return (E) elementData[0];
         }
         throw new NoSuchElementException();
     }
 
     /**
      * Returns the element at the specified location in this vector.
-     * 
+     *
      * @param location
      *            the index of the element to return in this vector.
      * @return the element at the specified location.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      * @see #size
-     * @since Android 1.0
      */
     @Override
-    public synchronized E get(int location) {
+    public E get(int location) {
         return elementAt(location);
     }
 
@@ -474,7 +449,7 @@
         E[] newData = newElementArray(newCapacity);
         // Assumes elementCount is <= newCapacity
         assert elementCount <= newCapacity;
-        System.arraycopy(elementData, 0, newData, 0, elementCount); 
+        System.arraycopy(elementData, 0, newData, 0, elementCount);
         elementData = newData;
     }
 
@@ -519,10 +494,9 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public synchronized int hashCode() {
@@ -538,7 +512,7 @@
      * Searches in this vector for the index of the specified object. The search
      * for the object starts at the beginning and moves towards the end of this
      * vector.
-     * 
+     *
      * @param object
      *            the object to find in this vector.
      * @return the index in this vector of the specified element, -1 if the
@@ -546,7 +520,6 @@
      * @see #contains
      * @see #lastIndexOf(Object)
      * @see #lastIndexOf(Object, int)
-     * @since Android 1.0
      */
     @Override
     public int indexOf(Object object) {
@@ -557,19 +530,18 @@
      * Searches in this vector for the index of the specified object. The search
      * for the object starts at the specified location and moves towards the end
      * of this vector.
-     * 
+     *
      * @param object
      *            the object to find in this vector.
      * @param location
      *            the index at which to start searching.
      * @return the index in this vector of the specified element, -1 if the
      *         element isn't found.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0}.
      * @see #contains
      * @see #lastIndexOf(Object)
      * @see #lastIndexOf(Object, int)
-     * @since Android 1.0
      */
     public synchronized int indexOf(Object object, int location) {
         if (object != null) {
@@ -594,16 +566,15 @@
      * location. All elements with an index equal or greater than
      * {@code location} have their index increased by 1. If the location is
      * equal to the size of this vector, the object is added at the end.
-     * 
+     *
      * @param object
      *            the object to insert in this vector.
      * @param location
      *            the index at which to insert the element.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location > size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location > size()}.
      * @see #addElement
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void insertElementAt(E object, int location) {
         if (0 <= location && location <= elementCount) {
@@ -625,11 +596,10 @@
 
     /**
      * Returns if this vector has no elements, a size of zero.
-     * 
+     *
      * @return {@code true} if this vector has no elements, {@code false}
      *         otherwise.
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean isEmpty() {
@@ -638,18 +608,18 @@
 
     /**
      * Returns the last element in this vector.
-     * 
+     *
      * @return the element at the last position.
-     * @exception NoSuchElementException
-     *                when this vector is empty.
+     * @throws NoSuchElementException
+     *                if this vector is empty.
      * @see #elementAt
      * @see #firstElement
      * @see #size
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public synchronized E lastElement() {
         try {
-            return (E)elementData[elementCount - 1];
+            return (E) elementData[elementCount - 1];
         } catch (IndexOutOfBoundsException e) {
             throw new NoSuchElementException();
         }
@@ -659,7 +629,7 @@
      * Searches in this vector for the index of the specified object. The search
      * for the object starts at the end and moves towards the start of this
      * vector.
-     * 
+     *
      * @param object
      *            the object to find in this vector.
      * @return the index in this vector of the specified element, -1 if the
@@ -667,7 +637,6 @@
      * @see #contains
      * @see #indexOf(Object)
      * @see #indexOf(Object, int)
-     * @since Android 1.0
      */
     @Override
     public synchronized int lastIndexOf(Object object) {
@@ -678,19 +647,18 @@
      * Searches in this vector for the index of the specified object. The search
      * for the object starts at the specified location and moves towards the
      * start of this vector.
-     * 
+     *
      * @param object
      *            the object to find in this vector.
      * @param location
      *            the index at which to start searching.
      * @return the index in this vector of the specified element, -1 if the
      *         element isn't found.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location >= size()}.
      * @see #contains
      * @see #indexOf(Object)
      * @see #indexOf(Object, int)
-     * @since Android 1.0
      */
     public synchronized int lastIndexOf(Object object, int location) {
         if (location < elementCount) {
@@ -716,18 +684,18 @@
      * Removes the object at the specified location from this vector. All
      * elements with an index bigger than {@code location} have their index
      * decreased by 1.
-     * 
+     *
      * @param location
      *            the index of the object to remove.
      * @return the removed object.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
-     * @since Android 1.0
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      */
+    @SuppressWarnings("unchecked")
     @Override
     public synchronized E remove(int location) {
         if (location < elementCount) {
-            E result = (E)elementData[location];
+            E result = (E) elementData[location];
             elementCount--;
             int size = elementCount - location;
             if (size > 0) {
@@ -746,7 +714,7 @@
      * towards the end, of the specified object from this vector. All elements
      * with an index bigger than the element that gets removed have their index
      * decreased by 1.
-     * 
+     *
      * @param object
      *            the object to remove from this vector.
      * @return {@code true} if the specified object was found, {@code false}
@@ -754,7 +722,6 @@
      * @see #removeAllElements
      * @see #removeElementAt
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public boolean remove(Object object) {
@@ -764,13 +731,12 @@
     /**
      * Removes all occurrences in this vector of each object in the specified
      * Collection.
-     * 
+     *
      * @param collection
      *            the collection of objects to remove.
      * @return {@code true} if this vector is modified, {@code false} otherwise.
      * @see #remove(Object)
      * @see #contains(Object)
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean removeAll(Collection<?> collection) {
@@ -780,13 +746,14 @@
     /**
      * Removes all elements from this vector, leaving the size zero and the
      * capacity unchanged.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void removeAllElements() {
-        Arrays.fill(elementData, 0, elementCount, null);
+        for (int i = 0; i < elementCount; i++) {
+            elementData[i] = null;
+        }
         modCount++;
         elementCount = 0;
     }
@@ -796,7 +763,7 @@
      * towards the end, of the specified object from this vector. All elements
      * with an index bigger than the element that gets removed have their index
      * decreased by 1.
-     * 
+     *
      * @param object
      *            the object to remove from this vector.
      * @return {@code true} if the specified object was found, {@code false}
@@ -804,7 +771,6 @@
      * @see #removeAllElements
      * @see #removeElementAt
      * @see #size
-     * @since Android 1.0
      */
     public synchronized boolean removeElement(Object object) {
         int index;
@@ -819,15 +785,14 @@
      * Removes the element found at index position {@code location} from
      * this {@code Vector}. All elements with an index bigger than
      * {@code location} have their index decreased by 1.
-     * 
+     *
      * @param location
      *            the index of the element to remove.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      * @see #removeElement
      * @see #removeAllElements
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void removeElementAt(int location) {
         if (0 <= location && location < elementCount) {
@@ -848,19 +813,18 @@
      * Removes the objects in the specified range from the start to the, but not
      * including, end index. All elements with an index bigger than or equal to
      * {@code end} have their index decreased by {@code end - start}.
-     * 
+     *
      * @param start
      *            the index at which to start removing.
      * @param end
      *            the index one past the end of the range to remove.
-     * @exception IndexOutOfBoundsException
-     *                when {@code start < 0, start > end} or
+     * @throws IndexOutOfBoundsException
+     *                if {@code start < 0, start > end} or
      *                {@code end > size()}.
-     * @since Android 1.0
      */
     @Override
     protected void removeRange(int start, int end) {
-        if (start >= 0 && start <= end && end <= size()) {
+        if (start >= 0 && start <= end && end <= elementCount) {
             if (start == end) {
                 return;
             }
@@ -883,12 +847,11 @@
     /**
      * Removes all objects from this vector that are not contained in the
      * specified collection.
-     * 
+     *
      * @param collection
      *            the collection of objects to retain.
      * @return {@code true} if this vector is modified, {@code false} otherwise.
      * @see #remove(Object)
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean retainAll(Collection<?> collection) {
@@ -898,21 +861,21 @@
     /**
      * Replaces the element at the specified location in this vector with the
      * specified object.
-     * 
+     *
      * @param location
      *            the index at which to put the specified object.
      * @param object
      *            the object to add to this vector.
      * @return the previous element at the location.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      * @see #size
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     @Override
     public synchronized E set(int location, E object) {
         if (location < elementCount) {
-            E result = (E)elementData[location];
+            E result = (E) elementData[location];
             elementData[location] = object;
             return result;
         }
@@ -922,15 +885,14 @@
     /**
      * Replaces the element at the specified location in this vector with the
      * specified object.
-     * 
+     *
      * @param object
      *            the object to add to this vector.
      * @param location
      *            the index at which to put the specified object.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void setElementAt(E object, int location) {
         if (location < elementCount) {
@@ -945,11 +907,10 @@
      * than length elements in this vector, the elements at end are lost. If
      * there are less than length elements in the vector, the additional
      * elements contain null.
-     * 
+     *
      * @param length
      *            the new size of this vector.
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void setSize(int length) {
         if (length == elementCount) {
@@ -965,11 +926,10 @@
 
     /**
      * Returns the number of elements in this vector.
-     * 
+     *
      * @return the number of elements in this vector.
      * @see #elementCount
      * @see #lastElement
-     * @since Android 1.0
      */
     @Override
     public synchronized int size() {
@@ -980,29 +940,27 @@
      * Returns a List of the specified portion of this vector from the start
      * index to one less than the end index. The returned List is backed by this
      * vector so changes to one are reflected by the other.
-     * 
+     *
      * @param start
      *            the index at which to start the sublist.
      * @param end
      *            the index one past the end of the sublist.
      * @return a List of a portion of this vector.
-     * @exception IndexOutOfBoundsException
-     *                when {@code start < 0} or {@code end > size()}.
-     * @exception IllegalArgumentException
-     *                when {@code start > end}.
-     * @since Android 1.0
+     * @throws IndexOutOfBoundsException
+     *                if {@code start < 0} or {@code end > size()}.
+     * @throws IllegalArgumentException
+     *                if {@code start > end}.
      */
     @Override
     public synchronized List<E> subList(int start, int end) {
-        return new Collections.SynchronizedRandomAccessList<E>(
-                super.subList(start, end), this);
+        return new Collections.SynchronizedRandomAccessList<E>(super.subList(
+                start, end), this);
     }
 
     /**
      * Returns a new array containing all elements contained in this vector.
-     * 
+     *
      * @return an array of the elements from this vector.
-     * @since Android 1.0
      */
     @Override
     public synchronized Object[] toArray() {
@@ -1017,14 +975,13 @@
      * is used, otherwise an array of the same type is created. If the specified
      * array is used and is larger than this vector, the array element following
      * the collection elements is set to null.
-     * 
+     *
      * @param contents
      *            the array to fill.
      * @return an array of the elements from this vector.
-     * @exception ArrayStoreException
-     *                when the type of an element in this vector cannot be
+     * @throws ArrayStoreException
+     *                if the type of an element in this vector cannot be
      *                stored in the type of the specified array.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -1042,29 +999,28 @@
 
     /**
      * Returns the string representation of this vector.
-     * 
+     *
      * @return the string representation of this vector.
      * @see #elements
-     * @since Android 1.0
      */
     @Override
     public synchronized String toString() {
         if (elementCount == 0) {
-            return "[]";
+            return "[]"; //$NON-NLS-1$
         }
         int length = elementCount - 1;
-        StringBuffer buffer = new StringBuffer(size() * 16);
+        StringBuffer buffer = new StringBuffer(elementCount * 16);
         buffer.append('[');
         for (int i = 0; i < length; i++) {
             if (elementData[i] == this) {
-                buffer.append("(this Collection)");
+                buffer.append("(this Collection)"); //$NON-NLS-1$
             } else {
                 buffer.append(elementData[i]);
             }
-            buffer.append(", ");
+            buffer.append(", "); //$NON-NLS-1$
         }
         if (elementData[length] == this) {
-            buffer.append("(this Collection)");
+            buffer.append("(this Collection)"); //$NON-NLS-1$
         } else {
             buffer.append(elementData[length]);
         }
@@ -1074,11 +1030,10 @@
 
     /**
      * Sets the capacity of this vector to be the same as the size.
-     * 
+     *
      * @see #capacity
      * @see #ensureCapacity
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void trimToSize() {
         if (elementData.length != elementCount) {
diff --git a/luni/src/main/java/java/util/WeakHashMap.java b/luni/src/main/java/java/util/WeakHashMap.java
index e0228e2..01e15af 100644
--- a/luni/src/main/java/java/util/WeakHashMap.java
+++ b/luni/src/main/java/java/util/WeakHashMap.java
@@ -26,10 +26,10 @@
  * optional operations (adding and removing) are supported. Keys and values can
  * be any objects. Note that the garbage collector acts similar to a second
  * thread on this collection, possibly removing keys.
- * 
+ *
+ * @since 1.2
  * @see HashMap
  * @see WeakReference
- * @since Android 1.0
  */
 public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {
 
@@ -127,7 +127,7 @@
         }
 
         public boolean hasNext() {
-            if (nextEntry != null) {
+            if (nextEntry != null && (nextKey != null || nextEntry.isNull)) {
                 return true;
             }
             while (true) {
@@ -183,8 +183,6 @@
 
     /**
      * Constructs a new empty {@code WeakHashMap} instance.
-     * 
-     * @since Android 1.0
      */
     public WeakHashMap() {
         this(DEFAULT_SIZE);
@@ -193,12 +191,11 @@
     /**
      * Constructs a new {@code WeakHashMap} instance with the specified
      * capacity.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this map.
      * @throws IllegalArgumentException
      *                if the capacity is less than zero.
-     * @since Android 1.0
      */
     public WeakHashMap(int capacity) {
         if (capacity >= 0) {
@@ -215,7 +212,7 @@
     /**
      * Constructs a new {@code WeakHashMap} instance with the specified capacity
      * and load factor.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this map.
      * @param loadFactor
@@ -223,7 +220,6 @@
      * @throws IllegalArgumentException
      *             if the capacity is less than zero or the load factor is less
      *             or equal to zero.
-     * @since Android 1.0
      */
     public WeakHashMap(int capacity, float loadFactor) {
         if (capacity >= 0 && loadFactor > 0) {
@@ -240,10 +236,9 @@
     /**
      * Constructs a new {@code WeakHashMap} instance containing the mappings
      * from the specified map.
-     * 
+     *
      * @param map
      *            the mappings to add.
-     * @since Android 1.0
      */
     public WeakHashMap(Map<? extends K, ? extends V> map) {
         this(map.size() < 6 ? 11 : map.size() * 2);
@@ -252,10 +247,9 @@
 
     /**
      * Removes all mappings from this map, leaving it empty.
-     * 
+     *
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -275,12 +269,11 @@
 
     /**
      * Returns whether this map contains the specified key.
-     * 
+     *
      * @param key
      *            the key to search for.
      * @return {@code true} if this map contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsKey(Object key) {
@@ -292,9 +285,8 @@
      * an instance of {@link Map.Entry}. As the set is backed by this map,
      * changes in one will be reflected in the other. It does not support adding
      * operations.
-     * 
+     *
      * @return a set of the mappings.
-     * @since Android 1.0
      */
     @Override
     public Set<Map.Entry<K, V>> entrySet() {
@@ -351,9 +343,8 @@
      * Returns a set of the keys contained in this map. The set is backed by
      * this map so changes to one are reflected by the other. The set does not
      * support adding.
-     * 
+     *
      * @return a set of the keys.
-     * @since Android 1.0
      */
     @Override
     public Set<K> keySet() {
@@ -392,6 +383,26 @@
                         }
                     });
                 }
+
+                @Override
+                public Object[] toArray() {
+                    Collection<K> coll = new ArrayList<K>(size());
+
+                    for (Iterator<K> iter = iterator(); iter.hasNext();) {
+                        coll.add(iter.next());
+                    }
+                    return coll.toArray();
+                }
+
+                @Override
+                public <T> T[] toArray(T[] contents) {
+                    Collection<K> coll = new ArrayList<K>(size());
+
+                    for (Iterator<K> iter = iterator(); iter.hasNext();) {
+                        coll.add(iter.next());
+                    }
+                    return coll.toArray(contents);
+                }
             };
         }
         return keySet;
@@ -408,16 +419,13 @@
      * "wrapper object" over the iterator of map's entrySet(). The size method
      * wraps the map's size method and the contains method wraps the map's
      * containsValue method.
-     * </p>
      * <p>
      * The collection is created when this method is called at first time and
      * returned in response to all subsequent calls. This method may return
      * different Collection when multiple calls to this method, since it has no
      * synchronization performed.
-     * </p>
-     * 
+     *
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     @Override
     public Collection<V> values() {
@@ -454,12 +462,11 @@
 
     /**
      * Returns the value of the mapping with the specified key.
-     * 
+     *
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
     @Override
     public V get(Object key) {
@@ -510,12 +517,11 @@
 
     /**
      * Returns whether this map contains the specified value.
-     * 
+     *
      * @param value
      *            the value to search for.
      * @return {@code true} if this map contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsValue(Object value) {
@@ -549,9 +555,8 @@
 
     /**
      * Returns the number of elements in this map.
-     * 
+     *
      * @return the number of elements in this map.
-     * @since Android 1.0
      */
     @Override
     public boolean isEmpty() {
@@ -590,14 +595,13 @@
 
     /**
      * Maps the specified key to the specified value.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
      *            the value.
      * @return the value of any previous mapping with the specified key or
      *         {@code null} if there was no mapping.
-     * @since Android 1.0
      */
     @Override
     public V put(K key, V value) {
@@ -658,10 +662,11 @@
      * Copies all the mappings in the given map to this map. These mappings will
      * replace all mappings that this map had for any of the keys currently in
      * the given map.
-     * 
+     *
      * @param map
      *            the map to copy mappings from.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code map} is {@code null}.
      */
     @Override
     public void putAll(Map<? extends K, ? extends V> map) {
@@ -670,12 +675,11 @@
 
     /**
      * Removes the mapping with the specified key from this map.
-     * 
+     *
      * @param key
      *            the key of the mapping to remove.
      * @return the value of the removed mapping or {@code null} if no mapping
      *         for the specified key was found.
-     * @since Android 1.0
      */
     @Override
     public V remove(Object key) {
@@ -711,9 +715,8 @@
 
     /**
      * Returns the number of elements in this map.
-     * 
+     *
      * @return the number of elements in this map.
-     * @since Android 1.0
      */
     @Override
     public int size() {
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java
index e288f1a..be6da05 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java
@@ -51,7 +51,7 @@
     }
 
     /**
-     * Contructs a MIME table using the default values defined in this class.
+     * Constructs a MIME table using the default values defined in this class.
      * 
      * It then augments this table by reading pairs of extensions and
      * corresponding content types from the file "content-types.properties",
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java
index 07357be..7f738d3 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java
@@ -59,16 +59,9 @@
     public FileURLConnection(URL url) {
         super(url);
         fileName = url.getFile();
-        if (url.getRef() != null) {
-            fileName += "#" + url.getRef(); //$NON-NLS-1$
-        }
         if (fileName == null) {
             fileName = ""; //$NON-NLS-1$
         }
-        String host = url.getHost();
-        if (host != null && host.length() > 0) {
-            fileName = "//" + host + fileName; //$NON-NLS-1$
-        }
         fileName = Util.decode(fileName, false);
     }
 
@@ -131,13 +124,23 @@
             return MimeTable.UNKNOWN;
         }
         if (isDir) {
-            return "text/html"; //$NON-NLS-1$
+            return "text/plain"; //$NON-NLS-1$
         }
         String result = guessContentTypeFromName(url.getFile());
-        if (result == null) {
-            return MimeTable.UNKNOWN;
+        if (result != null) {
+            return result;
         }
-        return result;
+
+        try {
+            result = guessContentTypeFromStream(is);
+        } catch (IOException e) {
+            // Ignore
+        }
+        if (result != null) {
+            return result;
+        }
+
+        return MimeTable.UNKNOWN;
     }
 
     /**
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java
index 909e611..1b5bfb9 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java
@@ -41,15 +41,15 @@
      * 
      */
     @Override
-    public URLConnection openConnection(URL url) {
-        return new FileURLConnection(url);
+    public URLConnection openConnection(URL url) throws IOException {
+        return openConnection(url, null);
     }
 
     /**
      * The behaviour of this method is the same as openConnection(URL).
      * <code>proxy</code> is not used in FileURLConnection.
      * 
-     * @param u
+     * @param url
      *            the URL which the connection is pointing to
      * @param proxy
      *            Proxy
@@ -58,18 +58,28 @@
      * @throws IOException
      *             if this handler fails to establish a connection.
      * @throws IllegalArgumentException
-     *             if any argument is null or of an invalid type.
+     *             if the url argument is null.
      * @throws UnsupportedOperationException
      *             if the protocol handler doesn't support this method.
      */
     @Override
     public URLConnection openConnection(URL url, Proxy proxy)
             throws IOException {
-        if (null == url || null == proxy) {
+        if (null == url) {
             // K034b=url and proxy can not be null
             throw new IllegalArgumentException(Msg.getString("K034b")); //$NON-NLS-1$
         }
-        return new FileURLConnection(url);
+
+        String host = url.getHost();
+        if (host == null || host.length() == 0
+                || host.equalsIgnoreCase("localhost")) { //$NON-NLS-1$
+            return new FileURLConnection(url);
+        }
+
+        // If a hostname is specified try to get the resource using FTP
+        URL ftpURL = new URL("ftp", host, url.getFile()); //$NON-NLS-1$
+        return (proxy == null) ? ftpURL.openConnection() : ftpURL
+                .openConnection(proxy);
     }
 
     /**
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java
index 2d4ab0d..016d5a7 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java
@@ -183,22 +183,24 @@
             ProxySelector selector = ProxySelector.getDefault();
             Iterator<Proxy> iter = proxyList.iterator();
             boolean connectOK = false;
+            String failureReason = ""; //$NON-NLS-1$
             while (iter.hasNext() && !connectOK) {
                 currentProxy = iter.next();
                 try {
                     connectInternal();
                     connectOK = true;
                 } catch (IOException ioe) {
+                    failureReason = ioe.getLocalizedMessage();
                     // If connect failed, callback "connectFailed"
                     // should be invoked.
                     if (null != selector && Proxy.NO_PROXY != currentProxy) {
-                        selector
-                                .connectFailed(uri, currentProxy.address(), ioe);
+                        selector.connectFailed(uri, currentProxy.address(), ioe);
                     }
                 }
             }
             if (!connectOK) {
-                throw new IOException(Msg.getString("K0097")); //$NON-NLS-1$
+                // K0097=Unable to connect to server\: {0}
+                throw new IOException(Msg.getString("K0097", failureReason)); //$NON-NLS-1$
             }
         }
     }
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
index 1f7589d..24be092 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
@@ -118,7 +118,7 @@
     /**
      * Set a field with the specified value. If the field is not found, it is
      * added. If the field is found, the existing value(s) are overwritten.
-     * 
+     *
      * @param key
      * @param value
      */
@@ -148,8 +148,10 @@
      * Provides an unmodifiable map with all String header names mapped to their
      * String values. The map keys are Strings and the values are unmodifiable
      * Lists of Strings.
-     * 
+     *
      * @return an unmodifiable map of the headers
+     *
+     * @since 1.4
      */
     public Map<String, List<String>> getFieldMap() {
         Map<String, List<String>> result = new HashMap<String, List<String>>(
@@ -164,7 +166,7 @@
     /**
      * Returns the element at <code>pos</code>, null if no such element
      * exist.
-     * 
+     *
      * @return java.lang.String the value of the key
      * @param pos
      *            int the position to look for
@@ -179,8 +181,8 @@
     /**
      * Returns the key of this header at <code>pos</code>, null if there are
      * fewer keys in the header
-     * 
-     * 
+     *
+     *
      * @return the key the desired position
      * @param pos
      *            the position to look for
@@ -193,11 +195,12 @@
     }
 
     /**
-     * Returns the value corresponding to the specified key, null if no such key
-     * exists.
-     * 
+     * Returns the value corresponding to the specified key.
+     *
      * @param key
-     * @return
+     *            the key to look up.
+     * @return Answers the value for the given key, or <code>null</code> if no
+     *         such key exists.
      */
     public String get(String key) {
         LinkedList<String> result = keyTable.get(key.toLowerCase());
@@ -209,8 +212,8 @@
 
     /**
      * Returns the number of keys stored in this header
-     * 
-     * @return
+     *
+     * @return the number of keys.
      */
     public int length() {
         return props.size() / 2;
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java
index 6a26365..55d762d 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java
@@ -14,12 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-// BEGIN android-note
-// This class was copied from a newer version of harmony
-// to improve reusability of URLConnections
-// END android-note
-
 package org.apache.harmony.luni.internal.net.www.protocol.http;
 
 import java.net.InetSocketAddress;
@@ -141,4 +135,4 @@
         return uri.hashCode();
     }
 
-}
+}
\ No newline at end of file
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java
index f7c8d96..4c51bdc 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java
@@ -14,12 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-// BEGIN android-note
-// This class was copied from a newer version of harmony
-// to improve reusability of URLConnections
-// END android-note
-
 package org.apache.harmony.luni.internal.net.www.protocol.http;
 
 import java.io.IOException;
@@ -42,6 +36,7 @@
  * various utility methods to access that connection.
  */
 public class HttpConnection {
+
     private boolean usingSecureSocket = false;
 
     private Socket socket;
@@ -233,7 +228,7 @@
      * Returns whether this connection is eligible to be recycled. This
      * is like {@link #isStale} except that it doesn't try to actually
      * perform any I/O.
-     * 
+     *
      * @return <code>true</code> if the connection is eligible to be
      * recycled
      */
@@ -272,4 +267,5 @@
             return null;
         }
     }
-}
+
+}
\ No newline at end of file
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java
index 9a90612..61d7cbe 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java
@@ -14,12 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-// BEGIN android-note
-// This class was copied from a newer version of harmony
-// to improve reusability of URLConnections
-// END android-note
-
 package org.apache.harmony.luni.internal.net.www.protocol.http;
 
 import java.io.IOException;
@@ -179,4 +173,4 @@
         pool.clear();
     }
 
-}
+}
\ No newline at end of file
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
index 6f5a2be..505c6b2 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-// BEGIN android-note
-// This class and some helper classes where copied from a newer version of harmony
-// to improve reusability of URLConnections
-// END android-note
-
 package org.apache.harmony.luni.internal.net.www.protocol.http;
 
 import java.io.ByteArrayOutputStream;
@@ -185,7 +180,7 @@
 
             return is.skip(n);
         }
-        
+
         public int available() throws IOException {
             if (closed) {
                 throwClosed();
@@ -222,9 +217,9 @@
         private void throwClosed() throws IOException {
             throw new IOException("stream closed");
         }
-    }    
+    }
     // END android-added
-    
+
     private class LimitedInputStream extends InputStream {
         int bytesRemaining;
 
@@ -523,7 +518,7 @@
          * size minus chunk head (which writes chunk data size in HEX and
          * "\r\n") size. For example, a string "abcd" use chunk whose size is 5
          * must be written to socket as "2\r\nab","2\r\ncd" ...
-         * 
+         *
          */
         private int calculateChunkDataLength() {
             /*
@@ -691,7 +686,7 @@
     /**
      * Creates an instance of the <code>HttpURLConnection</code> using default
      * port 80.
-     * 
+     *
      * @param url
      *            URL The URL this connection is connecting
      */
@@ -701,7 +696,7 @@
 
     /**
      * Creates an instance of the <code>HttpURLConnection</code>
-     * 
+     *
      * @param url
      *            URL The URL this connection is connecting
      * @param port
@@ -711,7 +706,7 @@
         super(url);
         defaultPort = port;
         reqHeader = (Header) defaultReqHeader.clone();
-        
+
         try {
             uri = url.toURI();
         } catch (URISyntaxException e) {
@@ -727,7 +722,7 @@
 
     /**
      * Creates an instance of the <code>HttpURLConnection</code>
-     * 
+     *
      * @param url
      *            URL The URL this connection is connecting
      * @param port
@@ -742,12 +737,12 @@
 
     /**
      * Establishes the connection to the remote HTTP server
-     * 
+     *
      * Any methods that requires a valid connection to the resource will call
      * this method implicitly. After the connection is established,
      * <code>connected</code> is set to true.
-     * 
-     * 
+     *
+     *
      * @see #connected
      * @see java.io.IOException
      * @see URLStreamHandler
@@ -762,9 +757,9 @@
         }
         // BEGIN android-changed
         // url.toURI(); throws an URISyntaxException if the url contains
-        // illegal characters in e.g. the query. 
-        // Since the query is not needed for proxy selection, we just create an 
-        // URI that only contains the necessary information. 
+        // illegal characters in e.g. the query.
+        // Since the query is not needed for proxy selection, we just create an
+        // URI that only contains the necessary information.
         try {
             uri = new URI(url.getProtocol(),
                           null,
@@ -817,7 +812,7 @@
     }
 
     /**
-     * Returns connected socket to be used for this HTTP connection. 
+     * Returns connected socket to be used for this HTTP connection.
      */
     protected HttpConnection getHTTPConnection(Proxy proxy) throws IOException {
         HttpConnection connection;
@@ -832,7 +827,7 @@
 
     /**
      * Sets up the data streams used to send request[s] and read response[s].
-     * 
+     *
      * @param connection
      *            HttpConnection to be used
      */
@@ -882,8 +877,8 @@
 
     /**
      * Closes the connection with the HTTP server
-     * 
-     * 
+     *
+     *
      * @see URLConnection#connect()
      */
     @Override
@@ -940,7 +935,7 @@
      * <p>
      * If the content type is not what stated above,
      * <code>FileNotFoundException</code> is thrown.
-     * 
+     *
      * @return InputStream the error input stream returned by the server.
      */
     @Override
@@ -978,14 +973,14 @@
     /**
      * Returns the value of the field corresponding to the <code>key</code>
      * Returns <code>null</code> if there is no such field.
-     * 
+     *
      * If there are multiple fields with that key, the last field value is
      * returned.
-     * 
+     *
      * @return java.lang.String The value of the header field
      * @param key
      *            java.lang.String the name of the header field
-     * 
+     *
      * @see #getHeaderField(int)
      * @see #getHeaderFieldKey
      */
@@ -1019,8 +1014,10 @@
      * Provides an unmodifiable map of the connection header values. The map
      * keys are the String header field names. Each map value is a list of the
      * header field values associated with that key name.
-     * 
+     *
      * @return the mapping of header field names to values
+     *
+     * @since 1.4
      */
     @Override
     public Map<String, List<String>> getHeaderFields() {
@@ -1172,7 +1169,7 @@
 
     /**
      * Returns a line read from the input stream. Does not include the \n
-     * 
+     *
      * @return The line that was read.
      */
     String readln() throws IOException {
@@ -1215,7 +1212,7 @@
      * Sends the request header to the remote HTTP server Not all of them are
      * guaranteed to have any effect on the content the server will return,
      * depending on if the server supports that field.
-     * 
+     *
      * Examples : Accept: text/*, text/html, text/html;level=1, Accept-Charset:
      * iso-8859-5, unicode-1-1;q=0.8
      */
@@ -1327,6 +1324,45 @@
         } else {
             output.append("1\r\n"); //$NON-NLS-1$
         }
+        // add user-specified request headers if any
+        boolean hasContentLength = false;
+        for (int i = 0; i < reqHeader.length(); i++) {
+            String key = reqHeader.getKey(i);
+            if (key != null) {
+                String lKey = key.toLowerCase();
+                if ((os != null && !os.isChunked())
+                        || (!lKey.equals("transfer-encoding") && !lKey //$NON-NLS-1$
+                                .equals("content-length"))) { //$NON-NLS-1$
+                    output.append(key);
+                    String value = reqHeader.get(i);
+                    /*
+                     * duplicates are allowed under certain conditions see
+                     * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
+                     */
+                    if (lKey.equals("content-length")) { //$NON-NLS-1$
+                        hasContentLength = true;
+                        /*
+                         * if both setFixedLengthStreamingMode and
+                         * content-length are set, use fixedContentLength first
+                         */
+                        if(fixedContentLength >= 0){
+                            value = String.valueOf(fixedContentLength);
+                        }
+                    }
+                    if (value != null) {
+                        output.append(": "); //$NON-NLS-1$
+                        output.append(value);
+                    }
+                    output.append("\r\n"); //$NON-NLS-1$
+                }
+            }
+        }
+        if (fixedContentLength >= 0 && !hasContentLength) {
+            output.append("content-length: "); //$NON-NLS-1$
+            output.append(String.valueOf(fixedContentLength));
+            output.append("\r\n"); //$NON-NLS-1$
+        }
+
         if (reqHeader.get("User-Agent") == null) { //$NON-NLS-1$
             output.append("User-Agent: "); //$NON-NLS-1$
             String agent = getSystemProperty("http.agent"); //$NON-NLS-1$
@@ -1348,6 +1384,9 @@
             }
             output.append("\r\n"); //$NON-NLS-1$
         }
+        if (reqHeader.get("Accept") == null) { //$NON-NLS-1$
+            output.append("Accept: *; */*\r\n"); //$NON-NLS-1$
+        }
         if (httpVersion > 0 && reqHeader.get("Connection") == null) { //$NON-NLS-1$
             output.append("Connection: Keep-Alive\r\n"); //$NON-NLS-1$
         }
@@ -1367,43 +1406,6 @@
                 output.append("Transfer-Encoding: chunked\r\n"); //$NON-NLS-1$
             }
         }
-
-        boolean hasContentLength = false;
-        // then the user-specified request headers, if any
-        for (int i = 0; i < reqHeader.length(); i++) {
-            String key = reqHeader.getKey(i);
-            if (key != null) {
-                String lKey = key.toLowerCase();
-                if ((os != null && !os.isChunked())
-                        || (!lKey.equals("transfer-encoding") && !lKey //$NON-NLS-1$
-                                .equals("content-length"))) { //$NON-NLS-1$
-                    output.append(key);
-                    output.append(": "); //$NON-NLS-1$
-                    /*
-                     * duplicates are allowed under certain conditions see
-                     * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
-                     */
-                    if (lKey.equals("content-length")) { //$NON-NLS-1$
-                        hasContentLength = true;
-                        /*
-                         * if both setFixedLengthStreamingMode and
-                         * content-length are set, use fixedContentLength first
-                         */
-                        output.append((fixedContentLength >= 0) ? String
-                                        .valueOf(fixedContentLength)
-                                        : reqHeader.get(i));
-                    } else {
-                        output.append(reqHeader.get(i));
-                    }
-                    output.append("\r\n"); //$NON-NLS-1$
-                }
-            }
-        }
-        if (fixedContentLength >= 0 && !hasContentLength) {
-            output.append("content-length: "); //$NON-NLS-1$
-            output.append(String.valueOf(fixedContentLength));
-            output.append("\r\n"); //$NON-NLS-1$
-        }
         // end the headers
         output.append("\r\n"); //$NON-NLS-1$
         return output.toString().getBytes("ISO8859_1"); //$NON-NLS-1$
@@ -1412,7 +1414,7 @@
     /**
      * Sets the default request header fields to be sent to the remote server.
      * This does not affect the current URL Connection, only newly created ones.
-     * 
+     *
      * @param field
      *            java.lang.String The name of the field to be changed
      * @param value
@@ -1427,11 +1429,11 @@
      * <code>setIfModifiedSince()</code> Since this HTTP impl supports
      * IfModifiedSince as one of the header field, the request header is updated
      * with the new value.
-     * 
-     * 
+     *
+     *
      * @param newValue
      *            the number of millisecond since epoch
-     * 
+     *
      * @throws IllegalStateException
      *             if already connected.
      */
@@ -1655,7 +1657,7 @@
     /**
      * Returns the authorization credentials on the base of provided
      * authorization challenge
-     * 
+     *
      * @param challenge
      * @return authorization credentials
      * @throws IOException
@@ -1707,4 +1709,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java
index 31c1198..4d0aff7 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java
@@ -14,7 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package org.apache.harmony.luni.internal.net.www.protocol.https;
 
 import java.io.IOException;
@@ -22,10 +21,6 @@
 import java.io.OutputStream;
 import java.net.ProtocolException;
 import java.net.Proxy;
-// BEGIN andorid-removed
-// copied from newer version of harmony
-// import java.net.Socket;
-// END android-removed
 import java.net.URL;
 import java.security.Permission;
 import java.security.Principal;
@@ -390,10 +385,7 @@
                             responseMessage, responseCode));
                 }
                 // if there are some remaining data in the stream - read it out
-                // BEGIN andorid-changed
-                // copied from newer version of harmony
                 InputStream is = connection.getInputStream();
-                // END android-changed
                 while (is.available() != 0) {
                     is.read();
                 }
@@ -403,11 +395,8 @@
                 super.connect();
             }
             if (!makingSSLTunnel) {
-                // BEGIN andorid-changed
-                // copied from newer version of harmony
                 sslSocket = connection.getSecureSocket(getSSLSocketFactory(), getHostnameVerifier());
                 setUpTransportIO(connection);
-                // END android-changed
             }
         }
 
@@ -430,23 +419,5 @@
             return super.requestString();
         }
 
-        // BEGIN android-removed
-        // /**
-        //  * Create the secure socket over the connected socket and verify remote
-        //  * hostname.
-        //  */
-        // private Socket wrapConnection(Socket socket) throws IOException {
-        //     String hostname = url.getHost();
-        //     // create the wrapper over connected socket
-        //     sslSocket = (SSLSocket) getSSLSocketFactory().createSocket(socket,
-        //             hostname, url.getPort(), true);
-        //     sslSocket.setUseClientMode(true);
-        //     sslSocket.startHandshake();
-        //     if (!getHostnameVerifier().verify(hostname, sslSocket.getSession())) {
-        //         throw new IOException(Messages.getString("luni.02", hostname)); //$NON-NLS-1$
-        //     }
-        //     return sslSocket;
-        // }
-        // END android-removed
     }
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
index da34969..d299913 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
@@ -36,8 +36,9 @@
      * @param u
      *            java.net.URL The URL to which the connection is pointing to
      * 
-     * @thows IOException thrown if an IO error occurs when this method tries to
-     *        establish connection.
+     * @throws IOException
+     *             thrown if an IO error occurs when this method tries to
+     *             establish connection.
      */
     @Override
     protected URLConnection openConnection(URL u) throws IOException {
@@ -75,7 +76,8 @@
             file = file.substring(0, file.indexOf('!') + 1) + spec;
         } else {
             int idx = file.indexOf('!');
-            String tmpFile = file.substring(idx + 1, file.lastIndexOf('/') + 1) + spec;
+            String tmpFile = file.substring(idx + 1, file.lastIndexOf('/') + 1)
+                    + spec;
             tmpFile = URLUtil.canonicalizePath(tmpFile);
             file = file.substring(0, idx + 1) + tmpFile;
         }
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java
index 5f4896a..56c1f3c 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java
@@ -23,8 +23,6 @@
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
 import java.net.ContentHandler;
 import java.net.ContentHandlerFactory;
 import java.net.MalformedURLException;
@@ -32,120 +30,38 @@
 import java.security.AccessController;
 import java.security.Permission;
 import java.security.PrivilegedAction;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.TreeSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.zip.ZipFile;
 
-// BEGIN android-removed
-// import org.apache.harmony.kernel.vm.VM;
-// END android-removed
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.Util;
 
 /**
  * This subclass extends <code>URLConnection</code>.
  * <p>
- * 
+ *
  * This class is responsible for connecting and retrieving resources from a Jar
  * file which can be anywhere that can be refered to by an URL.
  */
 public class JarURLConnection extends java.net.JarURLConnection {
 
-    static Hashtable<String, CacheEntry<? extends JarFile>> jarCache = new Hashtable<String, CacheEntry<?>>();
+    static HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>();
 
-    InputStream jarInput;
+    private URL jarFileURL;
+
+    private InputStream jarInput;
 
     private JarFile jarFile;
 
     private JarEntry jarEntry;
-    
+
     private boolean closed;
 
-    ReferenceQueue<JarFile> cacheQueue = new ReferenceQueue<JarFile>();
-
-    static TreeSet<LRUKey> lru = new TreeSet<LRUKey>(
-            new LRUComparator<LRUKey>());
-
-    static int Limit;
-
-    static {
-        Limit = AccessController.doPrivileged(new PrivilegedAction<Integer>() {
-            public Integer run() {
-                return Integer.getInteger("jar.cacheSize", 500); //$NON-NLS-1$
-            }
-        });
-        // BEGIN android-removed
-        // TODO this needs to be implemented once this is available.
-        // VM.closeJars();
-        // END android-removed
-    }
-
-    static final class CacheEntry<T extends JarFile> extends WeakReference<T> {
-        Object key;
-
-        CacheEntry(T jar, String key, ReferenceQueue<JarFile> queue) {
-            super(jar, queue);
-            this.key = key;
-        }
-    }
-
-    static final class LRUKey {
-        JarFile jar;
-
-        long ts;
-
-        LRUKey(JarFile file, long time) {
-            jar = file;
-            ts = time;
-        }
-
-        /**
-         * @see java.lang.Object#equals(java.lang.Object)
-         */
-        @Override
-        public boolean equals(Object obj) {
-            return (obj instanceof LRUKey) &&
-                (jar == ((LRUKey) obj).jar);
-        }
-
-        @Override
-        public int hashCode() {
-            return jar.hashCode();
-        }
-    }
-
-    static final class LRUComparator<T> implements Comparator<LRUKey> {
-
-        LRUComparator() {
-        }
-
-        /**
-         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
-         */
-        public int compare(LRUKey o1, LRUKey o2) {
-            if ((o1).ts > (o2).ts) {
-                return 1;
-            }
-            return (o1).ts == (o2).ts ? 0 : -1;
-        }
-
-        /**
-         * @param o1
-         *            an object to compare
-         * @param o2
-         *            an object to compare
-         * @return <code>true</code> if the objects are equal,
-         *         <code>false</code> otherwise.
-         */
-        public boolean equals(Object o1, Object o2) {
-            return o1.equals(o2);
-        }
-    }
 
     /**
      * @param url
@@ -153,8 +69,10 @@
      * @throws MalformedURLException
      *             if the URL is malformed
      */
-    public JarURLConnection(java.net.URL url) throws MalformedURLException {
+    public JarURLConnection(java.net.URL url) throws MalformedURLException, IOException {
         super(url);
+        jarFileURL = getJarFileURL();
+        jarFileURLConnection = jarFileURL.openConnection();
     }
 
     /**
@@ -162,77 +80,76 @@
      */
     @Override
     public void connect() throws IOException {
-        jarFileURLConnection = getJarFileURL().openConnection();
-        findJarFile(); // ensure the file can be found
-        findJarEntry(); // ensure the entry, if any, can be found
-        connected = true;
+        if (!connected) {
+            findJarFile(); // ensure the file can be found
+            findJarEntry(); // ensure the entry, if any, can be found
+            connected = true;
+        }
     }
 
     /**
      * Returns the Jar file refered by this <code>URLConnection</code>
-     * 
+     *
      * @return the JAR file referenced by this connection
-     * 
+     *
      * @throws IOException
      *             thrown if an IO error occurs while connecting to the
      *             resource.
      */
     @Override
     public JarFile getJarFile() throws IOException {
-        if (!connected) {
-            connect();
-        }
+        connect();
         return jarFile;
     }
 
     /**
      * Returns the Jar file refered by this <code>URLConnection</code>
-     * 
+     *
      * @throws IOException
      *             if an IO error occurs while connecting to the resource.
      */
     private void findJarFile() throws IOException {
-        URL jarFileURL = getJarFileURL();
-        if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$
-            String fileName = jarFileURL.getFile();
-            if(!new File(Util.decode(fileName,false)).exists()){
-                // KA026=JAR entry {0} not found in {1}
-                throw new FileNotFoundException(Msg.getString("KA026", //$NON-NLS-1$
-                        getEntryName(), fileName));
+        JarFile jar = null;
+        if (getUseCaches()) {
+            synchronized(jarCache){
+                jarFile = jarCache.get(jarFileURL);
             }
-            String host = jarFileURL.getHost();
-            if (host != null && host.length() > 0) {
-                fileName = "//" + host + fileName; //$NON-NLS-1$
-            }
-            jarFile = openJarFile(fileName, fileName, false);
-            return;
-        }
-
-        final String externalForm = jarFileURLConnection.getURL()
-                .toExternalForm();
-        jarFile = AccessController
-                .doPrivileged(new PrivilegedAction<JarFile>() {
-                    public JarFile run() {
-                        try {
-                            return openJarFile(null, externalForm, false);
-                        } catch (IOException e) {
-                            return null;
-                        }
+            if (jarFile == null) {
+                jar = openJarFile();
+                synchronized(jarCache){
+                    jarFile = jarCache.get(jarFileURL);
+                    if (jarFile == null){
+                        jarCache.put(jarFileURL, jar);
+                        jarFile = jar;
+                    }else{
+                        jar.close();
                     }
-                });
-        if (jarFile != null) {
-            return;
+                }
+            }
+        }else{
+            jarFile = openJarFile();
         }
 
-        // Build a temp jar file
-        final InputStream is = jarFileURLConnection.getInputStream();
-        try {
-            jarFile = AccessController
+        if (jarFile == null) {
+            throw new IOException();
+        }
+    }
+
+    JarFile openJarFile() throws IOException {
+        JarFile jar = null;
+        if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$
+            jar = new JarFile(new File(Util.decode(jarFileURL.getFile(), false)),
+                        true, ZipFile.OPEN_READ);
+        } else{
+            final InputStream is = jarFileURL.openConnection().getInputStream();
+            try {
+                jar = AccessController
                     .doPrivileged(new PrivilegedAction<JarFile>() {
                         public JarFile run() {
                             try {
                                 File tempJar = File.createTempFile("hyjar_", //$NON-NLS-1$
                                         ".tmp", null); //$NON-NLS-1$
+                                tempJar.deleteOnExit();
                                 FileOutputStream fos = new FileOutputStream(
                                         tempJar);
                                 byte[] buf = new byte[4096];
@@ -241,79 +158,33 @@
                                     fos.write(buf, 0, nbytes);
                                 }
                                 fos.close();
-                                String path = tempJar.getPath();
-                                return openJarFile(path, externalForm, true);
+                                return new JarFile(tempJar,
+                                        true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
                             } catch (IOException e) {
                                 return null;
                             }
                         }
                     });
-        } finally {
-            is.close();
-        }
-        if (jarFile == null) {
-            throw new IOException();
-        }
-    }
-
-    JarFile openJarFile(String fileString, String key, boolean temp)
-            throws IOException {
-
-        JarFile jar = null;
-        if (useCaches) {
-            CacheEntry<? extends JarFile> entry;
-            while ((entry = (CacheEntry<? extends JarFile>) cacheQueue.poll()) != null) {
-                jarCache.remove(entry.key);
+            } finally {
+                if (is != null) is.close();
             }
-            entry = jarCache.get(key);
-            if (entry != null) {
-                jar = entry.get();
-            }
-            if (jar == null && fileString != null) {
-                int flags = ZipFile.OPEN_READ
-                        + (temp ? ZipFile.OPEN_DELETE : 0);
-                jar = new JarFile(new File(Util.decode(fileString, false)),
-                        true, flags);
-                jarCache
-                        .put(key, new CacheEntry<JarFile>(jar, key, cacheQueue));
-            } else {
-                SecurityManager security = System.getSecurityManager();
-                if (security != null) {
-                    security.checkPermission(getPermission());
-                }
-                if (temp) {
-                    lru.remove(new LRUKey(jar, 0));
-                }
-            }
-        } else if (fileString != null) {
-            int flags = ZipFile.OPEN_READ + (temp ? ZipFile.OPEN_DELETE : 0);
-            jar = new JarFile(new File(Util.decode(fileString, false)), true,
-                    flags);
         }
 
-        if (temp) {
-            lru.add(new LRUKey(jar, new Date().getTime()));
-            if (lru.size() > Limit) {
-                lru.remove(lru.first());
-            }
-        }
         return jar;
     }
 
     /**
      * Returns the JarEntry of the entry referenced by this
      * <code>URLConnection</code>.
-     * 
+     *
      * @return java.util.jar.JarEntry the JarEntry referenced
-     * 
+     *
      * @throws IOException
      *             if an IO error occurs while getting the entry
      */
     @Override
     public JarEntry getJarEntry() throws IOException {
-        if (!connected) {
-            connect();
-        }
+        connect();
         return jarEntry;
 
     }
@@ -334,20 +205,19 @@
 
     /**
      * Creates an input stream for reading from this URL Connection.
-     * 
+     *
      * @return the input stream
-     * 
+     *
      * @throws IOException
      *             if an IO error occurs while connecting to the resource.
      */
     @Override
     public InputStream getInputStream() throws IOException {
+
         if (closed) {
             throw new IllegalStateException(Msg.getString("KA027"));
         }
-        if (!connected) {
-            connect();
-        }
+        connect();
         if (jarInput != null) {
             return jarInput;
         }
@@ -359,39 +229,56 @@
     }
 
     /**
-     * Returns the content type of the resource. Test cases reveal that only if
-     * the URL is refering to a Jar file, that this method returns a non-null
-     * value - x-java/jar.
-     * 
+     * Returns the content type of the resource.
+     * For jar file itself "x-java/jar" should be returned,
+     * for jar entries the content type of the entry should be returned.
+     * Returns non-null results ("content/unknown" for unknown types).
+     *
      * @return the content type
      */
     @Override
     public String getContentType() {
-        // it could also return "x-java/jar" which jdk returns but here, we get
-        // it from the URLConnection
-        try {
-            if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
-                return getJarFileURL().openConnection().getContentType();
+        if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
+            // the type for jar file itself is always "x-java/jar"
+            return "x-java/jar"; //$NON-NLS-1$
+        } else {
+            String cType = null;
+            String entryName = getEntryName();
+
+            if (entryName != null) {
+                // if there is an Jar Entry, get the content type from the name
+                cType = guessContentTypeFromName(entryName);
+            } else {
+                try {
+                    connect();
+                    cType = jarFileURLConnection.getContentType();
+                } catch (IOException ioe) {
+                    // Ignore
+                }
             }
-        } catch (IOException ioe) {
-            // Ignore
+            if (cType == null) {
+                cType = "content/unknown"; //$NON-NLS-1$
+            }
+            return cType;
         }
-        // if there is an Jar Entry, get the content type from the name
-        return guessContentTypeFromName(url.getFile());
     }
 
     /**
      * Returns the content length of the resource. Test cases reveal that if the
      * URL is refering to a Jar file, this method returns a content-length
-     * returned by URLConnection. If not, it will return -1.
-     * 
+     * returned by URLConnection. For jar entry it should return it's size.
+     * Otherwise, it will return -1.
+     *
      * @return the content length
      */
     @Override
     public int getContentLength() {
         try {
-            if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
-                return getJarFileURL().openConnection().getContentLength();
+            connect();
+            if (jarEntry == null) {
+                return jarFileURLConnection.getContentLength();
+            } else {
+                return (int) getJarEntry().getSize();
             }
         } catch (IOException e) {
             //Ignored
@@ -404,12 +291,12 @@
      * URLConnection is pointing to a Jar File (no Jar Entry), this method will
      * return a <code>JarFile</code> If there is a Jar Entry, it will return
      * the object corresponding to the Jar entry content type.
-     * 
+     *
      * @return a non-null object
-     * 
+     *
      * @throws IOException
      *             if an IO error occured
-     * 
+     *
      * @see ContentHandler
      * @see ContentHandlerFactory
      * @see java.io.IOException
@@ -417,9 +304,7 @@
      */
     @Override
     public Object getContent() throws IOException {
-        if (!connected) {
-            connect();
-        }
+        connect();
         // if there is no Jar Entry, return a JarFile
         if (jarEntry == null) {
             return jarFile;
@@ -431,37 +316,57 @@
      * Returns the permission, in this case the subclass, FilePermission object
      * which represents the permission necessary for this URLConnection to
      * establish the connection.
-     * 
+     *
      * @return the permission required for this URLConnection.
-     * 
+     *
      * @throws IOException
      *             thrown when an IO exception occurs while creating the
      *             permission.
      */
+
     @Override
     public Permission getPermission() throws IOException {
-        if (jarFileURLConnection != null) {
-            return jarFileURLConnection.getPermission();
-        }
-        return getJarFileURL().openConnection().getPermission();
+        return jarFileURLConnection.getPermission();
+    }
+
+    @Override
+    public boolean getUseCaches() {
+        return jarFileURLConnection.getUseCaches();
+    }
+
+    @Override
+    public void setUseCaches(boolean usecaches) {
+        jarFileURLConnection.setUseCaches(usecaches);
+    }
+
+    @Override
+    public boolean getDefaultUseCaches() {
+        return jarFileURLConnection.getDefaultUseCaches();
+    }
+
+    @Override
+    public void setDefaultUseCaches(boolean defaultusecaches) {
+        jarFileURLConnection.setDefaultUseCaches(defaultusecaches);
     }
 
     /**
      * Closes the cached files.
      */
     public static void closeCachedFiles() {
-        Enumeration<CacheEntry<? extends JarFile>> elemEnum = jarCache
-                .elements();
-        while (elemEnum.hasMoreElements()) {
-            try {
-                ZipFile zip = elemEnum.nextElement().get();
-                if (zip != null) {
-                    zip.close();
+        Set<Map.Entry<URL, JarFile>> s = jarCache.entrySet();
+        synchronized(jarCache){
+            Iterator<Map.Entry<URL, JarFile>> i = s.iterator();
+            while(i.hasNext()){
+                try {
+                    ZipFile zip = i.next().getValue();
+                    if (zip != null) {
+                        zip.close();
+                    }
+                } catch (IOException e) {
+                    // Ignored
                 }
-            } catch (IOException e) {
-                // Ignored
             }
-        }
+       }
     }
 
     private class JarURLConnectionInputStream extends FilterInputStream {
@@ -478,7 +383,7 @@
         @Override
         public void close() throws IOException {
             super.close();
-            if (!useCaches) {
+            if (!getUseCaches()) {
                 closed = true;
                 jarFile.close();
             }
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties b/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties
index fe392b7..2ee09f7 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties
@@ -21,8 +21,6 @@
 luni.04=this Map
 luni.05=Attempt to insert {0} element into collection with element type {1}
 luni.06=The string argument is null
-# // BEGIN android-added
-# // copied from newer version of harmony
+luni.07=The stream is corrupted
 luni.08=Invalid Unicode sequence: expected format \\uxxxx
 luni.09=Invalid Unicode sequence: illegal character
-# // END android-added
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java
deleted file mode 100644
index a359b8b..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.internal.reflect;
-
-class ProxyCharArrayCache {
-    static boolean equals(char[] first, char[] second) {
-        if (first == second) {
-            return true;
-        }
-        if (first == null || second == null) {
-            return false;
-        }
-        if (first.length != second.length) {
-            return false;
-        }
-
-        for (int i = first.length; --i >= 0;) {
-            if (first[i] != second[i]) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    // to avoid using Enumerations, walk the individual tables skipping nulls
-    private char[] keyTable[];
-
-    private int valueTable[];
-
-    // number of elements in the table
-    private int elementSize;
-
-    private int threshold;
-
-    ProxyCharArrayCache(int initialCapacity) {
-        if (initialCapacity < 13) {
-            initialCapacity = 13;
-        }
-        this.elementSize = 0;
-        this.threshold = (int) (initialCapacity * 0.66f);
-        this.keyTable = new char[initialCapacity][];
-        this.valueTable = new int[initialCapacity];
-    }
-
-    int get(char[] key) {
-        int index = hashCodeChar(key);
-        while (keyTable[index] != null) {
-            if (equals(keyTable[index], key)) {
-                return valueTable[index];
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        return -1;
-    }
-
-    private int hashCodeChar(char[] val) {
-        int length = val.length;
-        int hash = 0;
-        int n = 2; // number of characters skipped
-        for (int i = 0; i < length; i += n) {
-            hash += val[i];
-        }
-        return (hash & 0x7FFFFFFF) % keyTable.length;
-    }
-
-    int put(char[] key, int value) {
-        int index = hashCodeChar(key);
-        while (keyTable[index] != null) {
-            if (equals(keyTable[index], key)) {
-                return valueTable[index] = value;
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        keyTable[index] = key;
-        valueTable[index] = value;
-
-        // assumes the threshold is never equal to the size of the table
-        if (++elementSize > threshold) {
-            rehash();
-        }
-        return value;
-    }
-
-    private void rehash() {
-        ProxyCharArrayCache newHashtable = new ProxyCharArrayCache(
-                keyTable.length * 2);
-        for (int i = keyTable.length; --i >= 0;) {
-            if (keyTable[i] != null) {
-                newHashtable.put(keyTable[i], valueTable[i]);
-            }
-        }
-
-        this.keyTable = newHashtable.keyTable;
-        this.valueTable = newHashtable.valueTable;
-        this.threshold = newHashtable.threshold;
-    }
-
-    int size() {
-        return elementSize;
-    }
-
-    @Override
-    public String toString() {
-        int max = size();
-        StringBuilder buf = new StringBuilder();
-        buf.append("{"); //$NON-NLS-1$
-        for (int i = 0; i < max; ++i) {
-            if (keyTable[i] != null) {
-                buf.append(keyTable[i]).append("->").append(valueTable[i]); //$NON-NLS-1$
-            }
-            if (i < max) {
-                buf.append(", "); //$NON-NLS-1$
-            }
-        }
-        buf.append("}"); //$NON-NLS-1$
-        return buf.toString();
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java
deleted file mode 100644
index 43fa5a3..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java
+++ /dev/null
@@ -1,937 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.internal.reflect;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.UndeclaredThrowableException;
-import java.util.ArrayList;
-import java.util.HashSet;
-
-public final class ProxyClassFile implements ProxyConstants {
-
-    private static final int INITIAL_CONTENTS_SIZE = 1000;
-
-    private static final int INITIAL_HEADER_SIZE = 500;
-
-    private static final int INCREMENT_SIZE = 250;
-
-    private static Method ObjectEqualsMethod;
-
-    private static Method ObjectHashCodeMethod;
-
-    private static Method ObjectToStringMethod;
-
-    private static Method ClassForNameMethod;
-
-    private static Method ClassGetMethod;
-
-    private static Method HandlerInvokeMethod;
-
-    private static Constructor<?> ProxyConstructor;
-
-    private static Constructor<?> UndeclaredThrowableExceptionConstructor;
-
-    private static Field ProxyHandlerField;
-
-    public static byte[] generateBytes(String typeName, Class[] interfaces) {
-        ProxyClassFile classFile = new ProxyClassFile(typeName, interfaces);
-        classFile.addFields();
-        classFile.findMethods(interfaces);
-        classFile.addMethods();
-        classFile.addAttributes();
-        return classFile.getBytes();
-    }
-
-    static char[] getConstantPoolName(Class<?> c) {
-        if (c.isArray()) {
-            // Array classes are named/ with their signature
-            return c.getName().replace('.', '/').toCharArray();
-        }
-
-        if (c.isPrimitive()) {
-            // Special cases for each base type.
-            if (c == void.class) {
-                return new char[] { 'V' };
-            }
-            if (c == int.class) {
-                return new char[] { 'I' };
-            }
-            if (c == boolean.class) {
-                return new char[] { 'Z' };
-            }
-            if (c == byte.class) {
-                return new char[] { 'B' };
-            }
-            if (c == char.class) {
-                return new char[] { 'C' };
-            }
-            if (c == short.class) {
-                return new char[] { 'S' };
-            }
-            if (c == long.class) {
-                return new char[] { 'J' };
-            }
-            if (c == float.class) {
-                return new char[] { 'F' };
-            }
-            if (c == double.class) {
-                return new char[] { 'D' };
-            }
-        }
-        return ("L" + c.getName().replace('.', '/') + ";").toCharArray();
-    }
-
-    static char[] getConstantPoolName(Constructor<?> method) /* (ILjava/lang/Thread;)V */{
-        Class[] parameters = method.getParameterTypes();
-        StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
-        buffer.append('(');
-        for (Class<?> element : parameters) {
-            buffer.append(getConstantPoolName(element));
-        }
-        buffer.append(')');
-        buffer.append(getConstantPoolName(void.class));
-        return buffer.toString().toCharArray();
-    }
-
-    static char[] getConstantPoolName(Method method) /* (ILjava/lang/Thread;)Ljava/lang/Object; */{
-        Class[] parameters = method.getParameterTypes();
-        StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
-        buffer.append('(');
-        for (Class<?> element : parameters) {
-            buffer.append(getConstantPoolName(element));
-        }
-        buffer.append(')');
-        buffer.append(getConstantPoolName(method.getReturnType()));
-        return buffer.toString().toCharArray();
-    }
-
-    private ProxyConstantPool constantPool;
-
-    // the header contains all the bytes till the end of the constant pool
-    byte[] header;
-
-    int headerOffset;
-
-    // that collection contains all the remaining bytes of the .class file
-    private byte[] contents;
-
-    private int contentsOffset;
-
-    private int constantPoolOffset;
-
-    private ProxyMethod[] proxyMethods;
-
-    ProxyClassFile(String typeName, Class[] interfaces) {
-        super();
-        header = new byte[INITIAL_HEADER_SIZE];
-        // generate the magic numbers inside the header
-        header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
-        header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
-        header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
-        header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
-        // Compatible with JDK 1.2
-        header[headerOffset++] = 0;
-        header[headerOffset++] = 0;
-        header[headerOffset++] = 0;
-        header[headerOffset++] = 46;
-        constantPoolOffset = headerOffset;
-        headerOffset += 2;
-        constantPool = new ProxyConstantPool(this);
-        contents = new byte[INITIAL_CONTENTS_SIZE];
-        // now we continue to generate the bytes inside the contents array
-        int accessFlags = AccPublic | AccFinal | AccSuper;
-        contents[contentsOffset++] = (byte) (accessFlags >> 8);
-        contents[contentsOffset++] = (byte) accessFlags;
-        int classNameIndex = constantPool.typeIndex(typeName);
-        contents[contentsOffset++] = (byte) (classNameIndex >> 8);
-        contents[contentsOffset++] = (byte) classNameIndex;
-        int superclassNameIndex = constantPool
-                .typeIndex("java/lang/reflect/Proxy");
-        contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
-        contents[contentsOffset++] = (byte) superclassNameIndex;
-        int interfacesCount = interfaces.length;
-        contents[contentsOffset++] = (byte) (interfacesCount >> 8);
-        contents[contentsOffset++] = (byte) interfacesCount;
-        for (int i = 0; i < interfacesCount; i++) {
-            int interfaceIndex = constantPool
-                    .typeIndex(interfaces[i].getName());
-            contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
-            contents[contentsOffset++] = (byte) interfaceIndex;
-        }
-    }
-
-    private void addAttributes() {
-        writeUnsignedShort(0); // classFile does not have attributes of its own
-
-        // resynchronize all offsets of the classfile
-        header = constantPool.poolContent;
-        headerOffset = constantPool.currentOffset;
-        int constantPoolCount = constantPool.currentIndex;
-        header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
-        header[constantPoolOffset] = (byte) constantPoolCount;
-    }
-
-    private void addFields() {
-        writeUnsignedShort(0); // we have no fields
-    }
-
-    private void addMethods() {
-        int methodCount = proxyMethods.length;
-        writeUnsignedShort(methodCount + 1);
-
-        // save constructor
-        writeUnsignedShort(AccPublic);
-        writeUnsignedShort(constantPool.literalIndex(Init));
-        if (ProxyConstructor == null) {
-            try {
-                ProxyConstructor = Proxy.class
-                        .getDeclaredConstructor(new Class[] { InvocationHandler.class });
-            } catch (NoSuchMethodException e) {
-                throw new InternalError();
-            }
-        }
-        writeUnsignedShort(constantPool
-                .literalIndex(getConstantPoolName(ProxyConstructor)));
-        writeUnsignedShort(1); // store just the code attribute
-        writeUnsignedShort(constantPool.literalIndex(CodeName));
-        // save attribute_length(4), max_stack(2), max_locals(2), code_length(4)
-        int codeLength = 6;
-        writeUnsignedWord(12 + codeLength); // max_stack(2), max_locals(2),
-        // code_length(4), 2 zero shorts
-        writeUnsignedShort(2);
-        writeUnsignedShort(2);
-        writeUnsignedWord(codeLength);
-        writeUnsignedByte(OPC_aload_0);
-        writeUnsignedByte(OPC_aload_1);
-        writeUnsignedByte(OPC_invokespecial);
-        writeUnsignedShort(constantPool.literalIndex(ProxyConstructor));
-        writeUnsignedByte(OPC_return);
-        writeUnsignedShort(0); // no exceptions table
-        writeUnsignedShort(0); // there are no attributes for the code
-        // attribute
-
-        for (int i = 0; i < methodCount; i++) {
-            ProxyMethod pMethod = proxyMethods[i];
-            Method method = pMethod.method;
-            writeUnsignedShort(AccPublic | AccFinal);
-            writeUnsignedShort(constantPool.literalIndex(method.getName()
-                    .toCharArray()));
-            writeUnsignedShort(constantPool
-                    .literalIndex(getConstantPoolName(method)));
-            Class[] thrownsExceptions = pMethod.commonExceptions;
-            int eLength = thrownsExceptions.length;
-            if (eLength > 0) {
-                writeUnsignedShort(2); // store the exception & code attributes
-                // The method has a throw clause. So we need to add an exception
-                // attribute
-                writeUnsignedShort(constantPool.literalIndex(ExceptionsName));
-                // The attribute length = length * 2 + 2 in case of a exception
-                // attribute
-                writeUnsignedWord(eLength * 2 + 2);
-                writeUnsignedShort(eLength);
-                for (int e = 0; e < eLength; e++) {
-                    writeUnsignedShort(constantPool
-                            .typeIndex(thrownsExceptions[e].getName()));
-                }
-            } else {
-                writeUnsignedShort(1); // store just the code attribute
-            }
-            generateCodeAttribute(pMethod);
-        }
-    }
-
-    private void findMethods(Class[] interfaces) {
-        /*
-         * find all methods defined by the interfaces (including inherited
-         * interfaces) plus hashCode, equals & toString from Object build an
-         * array with the methods... no duplicates - check up to the array size
-         * when the interface's first method was added
-         */
-        if (ObjectEqualsMethod == null) {
-            try {
-                ObjectEqualsMethod = Object.class.getMethod("equals",
-                        new Class[] { Object.class });
-                ObjectHashCodeMethod = Object.class.getMethod("hashCode",
-                        new Class[0]);
-                ObjectToStringMethod = Object.class.getMethod("toString",
-                        new Class[0]);
-            } catch (NoSuchMethodException ex) {
-                throw new InternalError();
-            }
-        }
-
-        ArrayList<ProxyMethod> allMethods = new ArrayList<ProxyMethod>(25);
-        allMethods.add(new ProxyMethod(ObjectEqualsMethod));
-        allMethods.add(new ProxyMethod(ObjectHashCodeMethod));
-        allMethods.add(new ProxyMethod(ObjectToStringMethod));
-
-        HashSet<Class<?>> interfacesSeen = new HashSet<Class<?>>();
-        for (Class<?> element : interfaces) {
-            findMethods(element, allMethods, interfacesSeen);
-        }
-
-        proxyMethods = new ProxyMethod[allMethods.size()];
-        allMethods.toArray(proxyMethods);
-    }
-
-    private void findMethods(Class<?> nextInterface,
-            ArrayList<ProxyMethod> allMethods, HashSet<Class<?>> interfacesSeen) {
-        /*
-         * add the nextInterface's methods to allMethods if an equivalent method
-         * already exists then return types must be identical... don't replace
-         * it
-         */
-        if (interfacesSeen.contains(nextInterface)) {
-            return; // already walked it
-        }
-        interfacesSeen.add(nextInterface);
-
-        int existingMethodCount = allMethods.size();
-        Method[] methods = nextInterface.getMethods();
-        nextMethod: for (Method method : methods) {
-            for (int j = 0; j < existingMethodCount; j++) {
-                if (allMethods.get(j).matchMethod(method)) {
-                    continue nextMethod;
-                }
-            }
-            allMethods.add(new ProxyMethod(method));
-        }
-
-        Class<?>[] superInterfaces = nextInterface.getInterfaces();
-        for (Class<?> element : superInterfaces) {
-            // recursion should be minimal
-            findMethods(element, allMethods, interfacesSeen);
-        }
-    }
-
-    private void generateCodeAttribute(ProxyMethod pMethod) {
-        int codeAttributeOffset = contentsOffset;
-        int contentsLength = contents.length;
-        if (contentsOffset + 20 + 100 >= contentsLength) {
-            System.arraycopy(contents, 0, (contents = new byte[contentsLength
-                    + INCREMENT_SIZE]), 0, contentsLength);
-        }
-        writeUnsignedShort(constantPool.literalIndex(CodeName));
-        // leave space for attribute_length(4), max_stack(2), max_locals(2),
-        // code_length(4)
-        contentsOffset += 12;
-
-        /*
-         * to push the args for the call to invoke push the receiver field h 0
-         * aload0 1 getfield 33 java.lang.reflect.Proxy.h
-         * Ljava.lang.reflect.InvocationHandler; push the receiver as the first
-         * arg 4 aload0 push the method push the array of args call invoke 89
-         * invokeinterface 67
-         * java.lang.reflect.InvocationHandler.invoke(Ljava.lang.Object;Ljava.lang.reflect.Method;[Ljava.lang.Object;)Ljava.lang.Object;
-         * cast return result catch & convert exceptions if necessary
-         */
-
-        int codeStartOffset = contentsOffset;
-        writeUnsignedByte(OPC_aload_0);
-        writeUnsignedByte(OPC_getfield);
-        if (ProxyHandlerField == null) {
-            try {
-                ProxyHandlerField = Proxy.class.getDeclaredField("h");
-            } catch (NoSuchFieldException e) {
-                throw new InternalError();
-            }
-        }
-        writeUnsignedShort(constantPool.literalIndex(ProxyHandlerField));
-        writeUnsignedByte(OPC_aload_0);
-        Method method = pMethod.method;
-        Class[] argTypes = method.getParameterTypes();
-        genCallGetMethod(method.getDeclaringClass(), method.getName(), argTypes);
-        int maxLocals = genInvokeArgs(argTypes);
-        writeUnsignedByte(OPC_invokeinterface);
-        if (HandlerInvokeMethod == null) {
-            try {
-                HandlerInvokeMethod = InvocationHandler.class.getMethod(
-                        "invoke", new Class[] { Object.class, Method.class,
-                                Object[].class });
-            } catch (NoSuchMethodException e) {
-                throw new InternalError();
-            }
-        }
-        writeUnsignedShort(constantPool.literalIndex(HandlerInvokeMethod));
-        writeUnsignedByte(4); // invoke has 3 args
-        writeUnsignedByte(0); // 4th operand must be 0
-        genCastReturnType(method.getReturnType());
-        int codeLength = contentsOffset - codeStartOffset;
-
-        Class[] checkedExceptions = pMethod.getCheckedExceptions();
-        int checkedLength = checkedExceptions.length;
-        if (checkedLength > 0) {
-            int codeEndIndex = contentsOffset - codeStartOffset;
-            writeUnsignedByte(OPC_athrow); // re-throw the caught exception
-
-            genStoreArg(maxLocals);
-            writeUnsignedByte(OPC_new);
-            writeUnsignedShort(constantPool
-                    .typeIndex("java/lang/reflect/UndeclaredThrowableException"));
-            writeUnsignedByte(OPC_dup);
-            genLoadArg(maxLocals);
-            maxLocals++; // now expecting the exception
-            writeUnsignedByte(OPC_invokespecial);
-            if (UndeclaredThrowableExceptionConstructor == null) {
-                try {
-                    UndeclaredThrowableExceptionConstructor = UndeclaredThrowableException.class
-                            .getConstructor(new Class[] { Throwable.class });
-                } catch (NoSuchMethodException e) {
-                    throw new InternalError();
-                }
-            }
-            writeUnsignedShort(constantPool
-                    .literalIndex(UndeclaredThrowableExceptionConstructor));
-            writeUnsignedByte(OPC_athrow);
-
-            codeLength = contentsOffset - codeStartOffset;
-
-            // write the exception table
-            writeUnsignedShort(checkedLength + 1);
-            for (int i = 0; i < checkedLength; i++) {
-                writeUnsignedShort(0);
-                writeUnsignedShort(codeEndIndex);
-                writeUnsignedShort(codeEndIndex);
-                writeUnsignedShort(constantPool.typeIndex(checkedExceptions[i]
-                        .getName()));
-            }
-            writeUnsignedShort(0);
-            writeUnsignedShort(codeEndIndex);
-            writeUnsignedShort(codeEndIndex + 1); // starts after the first
-            // throw
-            writeUnsignedShort(constantPool.typeIndex("java/lang/Throwable"));
-        } else {
-            writeUnsignedShort(0); // no exceptions table
-        }
-        // there are no attributes for the code attribute
-        writeUnsignedShort(0);
-
-        /*
-         * Complete the creation of the code attribute by setting the
-         * attribute_length, max_stack max_locals, code_length & exception table
-         * codeAttributeOffset is the position inside contents byte array before
-         * we started to write That means that to write the attribute_length you
-         * need to offset by 2 the value of codeAttributeOffset to get the right
-         * position, 6 for the max_stack etc...
-         */
-        int codeAttributeLength = contentsOffset - (codeAttributeOffset + 6);
-        contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
-        contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
-        contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
-        contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
-
-        int maxStack = maxLocals + 10; // larger than the exact amount
-        contents[codeAttributeOffset + 6] = (byte) (maxStack >> 8);
-        contents[codeAttributeOffset + 7] = (byte) maxStack;
-        contents[codeAttributeOffset + 8] = (byte) (maxLocals >> 8);
-        contents[codeAttributeOffset + 9] = (byte) maxLocals;
-        contents[codeAttributeOffset + 10] = (byte) (codeLength >> 24);
-        contents[codeAttributeOffset + 11] = (byte) (codeLength >> 16);
-        contents[codeAttributeOffset + 12] = (byte) (codeLength >> 8);
-        contents[codeAttributeOffset + 13] = (byte) codeLength;
-    }
-
-    /**
-     * Perform call to Class.getMethod(String, Class[]) receiver 13 ldc 37
-     * (java.lang.String) "java.lang.Object" 15 invokestatic 43
-     * java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; selector 37
-     * ldc 55 (java.lang.String) "equals" plus method args 39 iconst0 40
-     * anewarray 39 java.lang.Class or 39 iconst1 40 anewarray 39
-     * java.lang.Class 43 dup 44 iconst0 53 ldc 37 (java.lang.String)
-     * "java.lang.Object" 55 invokestatic 43
-     * java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; 77 aastore
-     * or 39 iconst2 40 anewarray 39 java.lang.Class 43 dup 44 iconst0 45
-     * getstatic 102 java.lang.Integer.TYPE Ljava.lang.Class; 48 aastore 49 dup
-     * 50 iconst1 51 getstatic 104 java.lang.Boolean.TYPE Ljava.lang.Class; 54
-     * aastore then 78 invokevirtual 59
-     * java.lang.Class.getMethod(Ljava.lang.String;[Ljava.lang.Class;)Ljava.lang.reflect.Method;
-     */
-    private void genCallGetMethod(Class<?> receiverType, String selector,
-            Class[] argTypes) {
-        genCallClassForName(receiverType.getName());
-        writeLdc(selector);
-        int length = argTypes.length;
-        writeIntConstant(length);
-        writeUnsignedByte(OPC_anewarray);
-        writeUnsignedShort(constantPool.typeIndex("java/lang/Class"));
-        for (int i = 0; i < length; i++) {
-            writeUnsignedByte(OPC_dup);
-            writeIntConstant(i);
-            Class<?> type = argTypes[i];
-            if (type.isPrimitive()) {
-                writeUnsignedByte(OPC_getstatic);
-                writeUnsignedShort(constantPool.literalIndex(typeField(type)));
-            } else {
-                genCallClassForName(type.getName());
-            }
-            writeUnsignedByte(OPC_aastore);
-        }
-        writeUnsignedByte(OPC_invokevirtual);
-        if (ClassGetMethod == null) {
-            try {
-                ClassGetMethod = Class.class.getMethod("getMethod",
-                        new Class[] { String.class, Class[].class });
-            } catch (NoSuchMethodException e) {
-                throw new InternalError();
-            }
-        }
-        writeUnsignedShort(constantPool.literalIndex(ClassGetMethod));
-    }
-
-    /**
-     * Add argument array for call to InvocationHandler.invoke
-     * 
-     * 46 aconstnull or 81 iconst1 82 anewarray 61 java.lang.Object 85 dup 86
-     * iconst0 87 aload1 88 aastore or 58 iconst2 59 anewarray 61
-     * java.lang.Object 62 dup 63 iconst0 64 new 84 java.lang.Integer 67 dup 68
-     * iload1 69 invokespecial 107 java.lang.Integer.<init>(I)V 72 aastore 73
-     * dup 74 iconst1 75 new 69 java.lang.Boolean 78 dup 79 iload2 80
-     * invokespecial 110 java.lang.Boolean.<init>(Z)V 83 aastore
-     */
-    private int genInvokeArgs(Class[] argTypes) {
-        int argByteOffset = 1; // remember h is at position 0
-        int length = argTypes.length;
-        if (length == 0) {
-            writeUnsignedByte(OPC_aconst_null);
-        } else {
-            writeIntConstant(length);
-            writeUnsignedByte(OPC_anewarray);
-            writeUnsignedShort(constantPool.typeIndex("java/lang/Object"));
-            for (int i = 0; i < length; i++) {
-                writeUnsignedByte(OPC_dup);
-                writeIntConstant(i);
-                argByteOffset = genInvokeArg(argTypes[i], argByteOffset);
-                writeUnsignedByte(OPC_aastore);
-            }
-        }
-        return argByteOffset;
-    }
-
-    private int genInvokeArg(Class<?> type, int argByteOffset) {
-        // offset represents maxLocals in bytes
-        if (type.isPrimitive()) {
-            writeUnsignedByte(OPC_new);
-            writeUnsignedShort(constantPool.typeIndex(typeWrapperName(type)));
-            writeUnsignedByte(OPC_dup);
-            if (argByteOffset > 255) {
-                writeUnsignedByte(OPC_wide);
-            }
-            if (type == long.class) {
-                switch (argByteOffset) {
-                    case 0:
-                        writeUnsignedByte(OPC_lload_0);
-                        break;
-                    case 1:
-                        writeUnsignedByte(OPC_lload_1);
-                        break;
-                    case 2:
-                        writeUnsignedByte(OPC_lload_2);
-                        break;
-                    case 3:
-                        writeUnsignedByte(OPC_lload_3);
-                        break;
-                    default:
-                        writeUnsignedByte(OPC_lload);
-                        if (argByteOffset > 255) {
-                            writeUnsignedShort(argByteOffset);
-                        } else {
-                            writeUnsignedByte(argByteOffset);
-                        }
-                }
-                argByteOffset += 2;
-            } else if (type == float.class) {
-                switch (argByteOffset) {
-                    case 0:
-                        writeUnsignedByte(OPC_fload_0);
-                        break;
-                    case 1:
-                        writeUnsignedByte(OPC_fload_1);
-                        break;
-                    case 2:
-                        writeUnsignedByte(OPC_fload_2);
-                        break;
-                    case 3:
-                        writeUnsignedByte(OPC_fload_3);
-                        break;
-                    default:
-                        writeUnsignedByte(OPC_fload);
-                        if (argByteOffset > 255) {
-                            writeUnsignedShort(argByteOffset);
-                        } else {
-                            writeUnsignedByte(argByteOffset);
-                        }
-                }
-                argByteOffset++;
-            } else if (type == double.class) {
-                switch (argByteOffset) {
-                    case 0:
-                        writeUnsignedByte(OPC_dload_0);
-                        break;
-                    case 1:
-                        writeUnsignedByte(OPC_dload_1);
-                        break;
-                    case 2:
-                        writeUnsignedByte(OPC_dload_2);
-                        break;
-                    case 3:
-                        writeUnsignedByte(OPC_dload_3);
-                        break;
-                    default:
-                        writeUnsignedByte(OPC_dload);
-                        if (argByteOffset > 255) {
-                            writeUnsignedShort(argByteOffset);
-                        } else {
-                            writeUnsignedByte(argByteOffset);
-                        }
-                }
-                argByteOffset += 2;
-            } else { // handles int, short, byte, boolean & char
-                switch (argByteOffset) {
-                    case 0:
-                        writeUnsignedByte(OPC_iload_0);
-                        break;
-                    case 1:
-                        writeUnsignedByte(OPC_iload_1);
-                        break;
-                    case 2:
-                        writeUnsignedByte(OPC_iload_2);
-                        break;
-                    case 3:
-                        writeUnsignedByte(OPC_iload_3);
-                        break;
-                    default:
-                        writeUnsignedByte(OPC_iload);
-                        if (argByteOffset > 255) {
-                            writeUnsignedShort(argByteOffset);
-                        } else {
-                            writeUnsignedByte(argByteOffset);
-                        }
-                }
-                argByteOffset++;
-            }
-            writeUnsignedByte(OPC_invokespecial);
-            writeUnsignedShort(constantPool.literalIndex(typeInitMethod(type)));
-        } else {
-            genLoadArg(argByteOffset);
-            argByteOffset++;
-        }
-        return argByteOffset;
-    }
-
-    /**
-     * 94 checkcast 69 java.lang.Boolean 97 invokevirtual 73
-     * java.lang.Boolean.booleanValue()Z 100 ireturn or 52 checkcast 91
-     * java.lang.String 55 areturn
-     */
-    private void genCastReturnType(Class<?> type) {
-        if (type.isPrimitive()) {
-            if (type == void.class) {
-                writeUnsignedByte(OPC_pop);
-                writeUnsignedByte(OPC_return);
-            } else {
-                writeUnsignedByte(OPC_checkcast);
-                writeUnsignedShort(constantPool
-                        .typeIndex(typeWrapperName(type)));
-                writeUnsignedByte(OPC_invokevirtual);
-                writeUnsignedShort(constantPool
-                        .literalIndex(typeAccessMethod(type)));
-                if (type == long.class) {
-                    writeUnsignedByte(OPC_lreturn);
-                } else if (type == float.class) {
-                    writeUnsignedByte(OPC_freturn);
-                } else if (type == double.class) {
-                    writeUnsignedByte(OPC_dreturn);
-                } else { // handles int, short, byte, boolean & char
-                    writeUnsignedByte(OPC_ireturn);
-                }
-            }
-        } else {
-            writeUnsignedByte(OPC_checkcast);
-            writeUnsignedShort(constantPool.typeIndex(type.getName()));
-            writeUnsignedByte(OPC_areturn);
-        }
-    }
-
-    private void genCallClassForName(String typeName) {
-        writeLdc(typeName);
-        writeUnsignedByte(OPC_invokestatic);
-        if (ClassForNameMethod == null) {
-            try {
-                ClassForNameMethod = Class.class.getMethod("forName",
-                        new Class[] { String.class });
-            } catch (NoSuchMethodException e) {
-                throw new InternalError();
-            }
-        }
-        writeUnsignedShort(constantPool.literalIndex(ClassForNameMethod));
-    }
-
-    private void genLoadArg(int argByteOffset) {
-        if (argByteOffset > 255) {
-            writeUnsignedByte(OPC_wide);
-            writeUnsignedByte(OPC_aload);
-            writeUnsignedShort(argByteOffset);
-        } else {
-            switch (argByteOffset) {
-                case 0:
-                    writeUnsignedByte(OPC_aload_0);
-                    break;
-                case 1:
-                    writeUnsignedByte(OPC_aload_1);
-                    break;
-                case 2:
-                    writeUnsignedByte(OPC_aload_2);
-                    break;
-                case 3:
-                    writeUnsignedByte(OPC_aload_3);
-                    break;
-                default:
-                    writeUnsignedByte(OPC_aload);
-                    writeUnsignedByte(argByteOffset);
-            }
-        }
-    }
-
-    private void genStoreArg(int argByteOffset) {
-        if (argByteOffset > 255) {
-            writeUnsignedByte(OPC_wide);
-            writeUnsignedByte(OPC_astore);
-            writeUnsignedShort(argByteOffset);
-        } else {
-            switch (argByteOffset) {
-                case 0:
-                    writeUnsignedByte(OPC_astore_0);
-                    break;
-                case 1:
-                    writeUnsignedByte(OPC_astore_1);
-                    break;
-                case 2:
-                    writeUnsignedByte(OPC_astore_2);
-                    break;
-                case 3:
-                    writeUnsignedByte(OPC_astore_3);
-                    break;
-                default:
-                    writeUnsignedByte(OPC_astore);
-                    writeUnsignedByte(argByteOffset);
-            }
-        }
-    }
-
-    private byte[] getBytes() {
-        byte[] fullContents = new byte[headerOffset + contentsOffset];
-        System.arraycopy(header, 0, fullContents, 0, headerOffset);
-        System.arraycopy(contents, 0, fullContents, headerOffset,
-                contentsOffset);
-        return fullContents;
-    }
-
-    private Method typeAccessMethod(Class<?> baseType) {
-        try {
-            if (baseType == int.class) {
-                return Integer.class.getMethod("intValue", (Class[]) null);
-            }
-            if (baseType == short.class) {
-                return Short.class.getMethod("shortValue", (Class[]) null);
-            }
-            if (baseType == byte.class) {
-                return Byte.class.getMethod("byteValue", (Class[]) null);
-            }
-            if (baseType == boolean.class) {
-                return Boolean.class.getMethod("booleanValue", (Class[]) null);
-            }
-            if (baseType == char.class) {
-                return Character.class.getMethod("charValue", (Class[]) null);
-            }
-            if (baseType == long.class) {
-                return Long.class.getMethod("longValue", (Class[]) null);
-            }
-            if (baseType == float.class) {
-                return Float.class.getMethod("floatValue", (Class[]) null);
-            }
-            if (baseType == double.class) {
-                return Double.class.getMethod("doubleValue", (Class[]) null);
-            }
-        } catch (NoSuchMethodException e) {
-            throw new InternalError();
-        }
-        return null;
-    }
-
-    private Field typeField(Class<?> baseType) {
-        try {
-            if (baseType == int.class) {
-                return Integer.class.getField("TYPE");
-            }
-            if (baseType == short.class) {
-                return Short.class.getField("TYPE");
-            }
-            if (baseType == byte.class) {
-                return Byte.class.getField("TYPE");
-            }
-            if (baseType == boolean.class) {
-                return Boolean.class.getField("TYPE");
-            }
-            if (baseType == char.class) {
-                return Character.class.getField("TYPE");
-            }
-            if (baseType == long.class) {
-                return Long.class.getField("TYPE");
-            }
-            if (baseType == float.class) {
-                return Float.class.getField("TYPE");
-            }
-            if (baseType == double.class) {
-                return Double.class.getField("TYPE");
-            }
-        } catch (NoSuchFieldException e) {
-            throw new InternalError();
-        }
-        return null;
-    }
-
-    private Constructor<?> typeInitMethod(Class<?> baseType) {
-        try {
-            if (baseType == int.class) {
-                return Integer.class.getConstructor(new Class[] { int.class });
-            }
-            if (baseType == short.class) {
-                return Short.class.getConstructor(new Class[] { short.class });
-            }
-            if (baseType == byte.class) {
-                return Byte.class.getConstructor(new Class[] { byte.class });
-            }
-            if (baseType == boolean.class) {
-                return Boolean.class
-                        .getConstructor(new Class[] { boolean.class });
-            }
-            if (baseType == char.class) {
-                return Character.class
-                        .getConstructor(new Class[] { char.class });
-            }
-            if (baseType == long.class) {
-                return Long.class.getConstructor(new Class[] { long.class });
-            }
-            if (baseType == float.class) {
-                return Float.class.getConstructor(new Class[] { float.class });
-            }
-            if (baseType == double.class) {
-                return Double.class
-                        .getConstructor(new Class[] { double.class });
-            }
-        } catch (NoSuchMethodException e) {
-            throw new InternalError();
-        }
-        return null;
-    }
-
-    private String typeWrapperName(Class<?> baseType) {
-        if (baseType == int.class) {
-            return "java/lang/Integer";
-        }
-        if (baseType == short.class) {
-            return "java/lang/Short";
-        }
-        if (baseType == byte.class) {
-            return "java/lang/Byte";
-        }
-        if (baseType == boolean.class) {
-            return "java/lang/Boolean";
-        }
-        if (baseType == char.class) {
-            return "java/lang/Character";
-        }
-        if (baseType == long.class) {
-            return "java/lang/Long";
-        }
-        if (baseType == float.class) {
-            return "java/lang/Float";
-        }
-        if (baseType == double.class) {
-            return "java/lang/Double";
-        }
-        return null;
-    }
-
-    private void writeIntConstant(int b) {
-        switch (b) {
-            case 0:
-                writeUnsignedByte(OPC_iconst_0);
-                break;
-            case 1:
-                writeUnsignedByte(OPC_iconst_1);
-                break;
-            case 2:
-                writeUnsignedByte(OPC_iconst_2);
-                break;
-            case 3:
-                writeUnsignedByte(OPC_iconst_3);
-                break;
-            case 4:
-                writeUnsignedByte(OPC_iconst_4);
-                break;
-            case 5:
-                writeUnsignedByte(OPC_iconst_5);
-                break;
-            default:
-                writeUnsignedByte(OPC_bipush);
-                writeUnsignedByte(b);
-        }
-    }
-
-    private void writeLdc(String constant) {
-        int index = constantPool.literalIndexForLdc(constant.toCharArray());
-        if (index <= 0) {
-            throw new InternalError();
-        }
-        if (index > 255) {
-            writeUnsignedByte(OPC_ldc_w);
-            writeUnsignedShort(index);
-        } else {
-            writeUnsignedByte(OPC_ldc);
-            writeUnsignedByte(index);
-        }
-    }
-
-    private void writeUnsignedByte(int b) {
-        try {
-            contents[contentsOffset++] = (byte) b;
-        } catch (IndexOutOfBoundsException e) {
-            int actualLength = contents.length;
-            System.arraycopy(contents, 0, (contents = new byte[actualLength
-                    + INCREMENT_SIZE]), 0, actualLength);
-            contents[contentsOffset - 1] = (byte) b;
-        }
-    }
-
-    private void writeUnsignedShort(int b) {
-        writeUnsignedByte(b >>> 8);
-        writeUnsignedByte(b);
-    }
-
-    private void writeUnsignedWord(int b) {
-        writeUnsignedByte(b >>> 24);
-        writeUnsignedByte(b >>> 16);
-        writeUnsignedByte(b >>> 8);
-        writeUnsignedByte(b);
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java
deleted file mode 100644
index 3789730..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.internal.reflect;
-
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-class ProxyConstantPool implements ProxyConstants {
-    public static final int UTF8_INITIAL_SIZE = 50;
-
-    public static final int STRING_INITIAL_SIZE = 21;
-
-    public static final int FIELD_INITIAL_SIZE = 7;
-
-    public static final int METHOD_INITIAL_SIZE = 21;
-
-    public static final int INTERFACE_INITIAL_SIZE = 21;
-
-    public static final int CLASS_INITIAL_SIZE = 21;
-
-    public static final int NAMEANDTYPE_INITIAL_SIZE = 21;
-
-    public static final int CONSTANTPOOL_INITIAL_SIZE = 500;
-
-    public static final int CONSTANTPOOL_GROW_SIZE = 1000;
-
-    ProxyCharArrayCache UTF8Cache;
-
-    ProxyCharArrayCache stringCache;
-
-    ProxyCharArrayCache classNameCache;
-
-    ProxyObjectCache fieldCache;
-
-    ProxyObjectCache methodCache;
-
-    ProxyObjectCache interfaceMethodCache;
-
-    ProxyNameAndTypeCache nameAndTypeCache;
-
-    byte[] poolContent;
-
-    int currentIndex;
-
-    int currentOffset;
-
-    ProxyConstantPool(ProxyClassFile classFile) {
-        UTF8Cache = new ProxyCharArrayCache(UTF8_INITIAL_SIZE);
-        stringCache = new ProxyCharArrayCache(STRING_INITIAL_SIZE);
-        classNameCache = new ProxyCharArrayCache(CLASS_INITIAL_SIZE);
-        fieldCache = new ProxyObjectCache(FIELD_INITIAL_SIZE);
-        methodCache = new ProxyObjectCache(METHOD_INITIAL_SIZE);
-        interfaceMethodCache = new ProxyObjectCache(INTERFACE_INITIAL_SIZE);
-        nameAndTypeCache = new ProxyNameAndTypeCache(NAMEANDTYPE_INITIAL_SIZE);
-        poolContent = classFile.header;
-        currentOffset = classFile.headerOffset;
-        currentIndex = 1;
-    }
-
-    int literalIndex(char[] utf8Constant) {
-        int index;
-        if ((index = UTF8Cache.get(utf8Constant)) < 0) {
-            writeU1(Utf8Tag);
-            int savedCurrentOffset = currentOffset;
-            if (currentOffset + 2 >= poolContent.length) {
-                int length = poolContent.length;
-                System.arraycopy(poolContent, 0, (poolContent = new byte[length
-                        + CONSTANTPOOL_GROW_SIZE]), 0, length);
-            }
-            currentOffset += 2;
-            int length = 0;
-            for (int i = 0; i < utf8Constant.length; i++) {
-                char current = utf8Constant[i];
-                if ((current >= 0x0001) && (current <= 0x007F)) {
-                    // we only need one byte: ASCII table
-                    writeU1(current);
-                    length++;
-                } else if (current > 0x07FF) {
-                    // we need 3 bytes
-                    length += 3;
-                    writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110
-                                                                // 0000
-                    writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000
-                                                                // 0000
-                    writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
-                } else {
-                    // we can be 0 or between 0x0080 and 0x07FF
-                    // In that case we only need 2 bytes
-                    length += 2;
-                    writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100
-                                                                // 0000
-                    writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
-                }
-            }
-            if (length >= 65535) {
-                currentOffset = savedCurrentOffset - 1;
-                return -1;
-            }
-            index = UTF8Cache.put(utf8Constant, currentIndex++);
-            // Now we know the length that we have to write in the constant pool
-            // we use savedCurrentOffset to do that
-            poolContent[savedCurrentOffset] = (byte) (length >> 8);
-            poolContent[savedCurrentOffset + 1] = (byte) length;
-        }
-        return index;
-    }
-
-    int literalIndex(Field aField) {
-        int index;
-        if ((index = fieldCache.get(aField)) < 0) {
-            int classIndex = typeIndex(aField.getDeclaringClass().getName());
-            int nameAndTypeIndex = literalIndexForNameAndType(
-                    literalIndex(aField.getName().toCharArray()),
-                    literalIndex(ProxyClassFile.getConstantPoolName(aField
-                            .getType())));
-            index = fieldCache.put(aField, currentIndex++);
-            writeU1(FieldRefTag);
-            writeU2(classIndex);
-            writeU2(nameAndTypeIndex);
-        }
-        return index;
-    }
-
-    int literalIndex(Constructor<?> aMethod) {
-        int index;
-        if ((index = methodCache.get(aMethod)) < 0) {
-            int classIndex = typeIndex(aMethod.getDeclaringClass().getName());
-            int nameAndTypeIndex = literalIndexForNameAndType(
-                    literalIndex(Init), literalIndex(ProxyClassFile
-                            .getConstantPoolName(aMethod)));
-            index = methodCache.put(aMethod, currentIndex++);
-            writeU1(MethodRefTag);
-            writeU2(classIndex);
-            writeU2(nameAndTypeIndex);
-        }
-        return index;
-    }
-
-    int literalIndex(Method aMethod) {
-        int index;
-        if (aMethod.getDeclaringClass().isInterface()) {
-            if ((index = interfaceMethodCache.get(aMethod)) < 0) {
-                int classIndex = typeIndex(aMethod.getDeclaringClass()
-                        .getName());
-                int nameAndTypeIndex = literalIndexForNameAndType(
-                        literalIndex(aMethod.getName().toCharArray()),
-                        literalIndex(ProxyClassFile
-                                .getConstantPoolName(aMethod)));
-                index = interfaceMethodCache.put(aMethod, currentIndex++);
-                writeU1(InterfaceMethodRefTag);
-                writeU2(classIndex);
-                writeU2(nameAndTypeIndex);
-            }
-        } else if ((index = methodCache.get(aMethod)) < 0) {
-            int classIndex = typeIndex(aMethod.getDeclaringClass().getName());
-            int nameAndTypeIndex = literalIndexForNameAndType(
-                    literalIndex(aMethod.getName().toCharArray()),
-                    literalIndex(ProxyClassFile.getConstantPoolName(aMethod)));
-            index = methodCache.put(aMethod, currentIndex++);
-            writeU1(MethodRefTag);
-            writeU2(classIndex);
-            writeU2(nameAndTypeIndex);
-        }
-        return index;
-    }
-
-    int literalIndex(String stringConstant) {
-        int index;
-        char[] stringCharArray = stringConstant.toCharArray();
-        if ((index = stringCache.get(stringCharArray)) < 0) {
-            int stringIndex = literalIndex(stringCharArray);
-            index = stringCache.put(stringCharArray, currentIndex++);
-            writeU1(StringTag);
-            writeU2(stringIndex);
-        }
-        return index;
-    }
-
-    int literalIndexForLdc(char[] stringCharArray) {
-        int index;
-        if ((index = stringCache.get(stringCharArray)) < 0) {
-            int stringIndex;
-            if ((stringIndex = UTF8Cache.get(stringCharArray)) < 0) {
-                writeU1(Utf8Tag);
-                int savedCurrentOffset = currentOffset;
-                if (currentOffset + 2 >= poolContent.length) {
-                    int length = poolContent.length;
-                    System.arraycopy(poolContent, 0,
-                            (poolContent = new byte[length
-                                    + CONSTANTPOOL_GROW_SIZE]), 0, length);
-                }
-                currentOffset += 2;
-                int length = 0;
-                for (int i = 0; i < stringCharArray.length; i++) {
-                    char current = stringCharArray[i];
-                    if ((current >= 0x0001) && (current <= 0x007F)) {
-                        // we only need one byte: ASCII table
-                        writeU1(current);
-                        length++;
-                    } else if (current > 0x07FF) {
-                        // we need 3 bytes
-                        length += 3;
-                        writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 =
-                                                                    // 1110 0000
-                        writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 =
-                                                                    // 1000 0000
-                        writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
-                    } else {
-                        // we can be 0 or between 0x0080 and 0x07FF
-                        // In that case we only need 2 bytes
-                        length += 2;
-                        writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 =
-                                                                    // 1100 0000
-                        writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
-                    }
-                }
-                if (length >= 65535) {
-                    currentOffset = savedCurrentOffset - 1;
-                    return -1;
-                }
-                stringIndex = UTF8Cache.put(stringCharArray, currentIndex++);
-                // Now we know the length that we have to write in the constant
-                // pool
-                // we use savedCurrentOffset to do that
-                if (length > 65535)
-                    return 0;
-                poolContent[savedCurrentOffset] = (byte) (length >> 8);
-                poolContent[savedCurrentOffset + 1] = (byte) length;
-            }
-            index = stringCache.put(stringCharArray, currentIndex++);
-            writeU1(StringTag);
-            writeU2(stringIndex);
-        }
-        return index;
-    }
-
-    private int literalIndexForNameAndType(int nameIndex, int typeIndex) {
-        int index;
-        int[] key = new int[] { nameIndex, typeIndex };
-        if ((index = nameAndTypeCache.get(key)) == -1) {
-            index = nameAndTypeCache.put(key, currentIndex++);
-            writeU1(NameAndTypeTag);
-            writeU2(nameIndex);
-            writeU2(typeIndex);
-        }
-        return index;
-    }
-
-    int typeIndex(String typeName) {
-        int index;
-        if (typeName.indexOf('.') != -1)
-            typeName = typeName.replace('.', '/');
-        char[] charArray = typeName.toCharArray();
-        if ((index = classNameCache.get(charArray)) < 0) {
-            int nameIndex = literalIndex(charArray);
-            index = classNameCache.put(charArray, currentIndex++);
-            writeU1(ClassTag);
-            writeU2(nameIndex);
-        }
-        return index;
-    }
-
-    private final void writeU1(int value) {
-        try {
-            poolContent[currentOffset++] = (byte) value;
-        } catch (IndexOutOfBoundsException e) {
-            // currentOffset has been ++ already (see the -1)
-            int length = poolContent.length;
-            System.arraycopy(poolContent, 0, (poolContent = new byte[length
-                    + CONSTANTPOOL_GROW_SIZE]), 0, length);
-            poolContent[currentOffset - 1] = (byte) value;
-        }
-    }
-
-    private final void writeU2(int value) {
-        try {
-            poolContent[currentOffset++] = (byte) (value >> 8);
-        } catch (IndexOutOfBoundsException e) {
-            // currentOffset has been ++ already (see the -1)
-            int length = poolContent.length;
-            System.arraycopy(poolContent, 0, (poolContent = new byte[length
-                    + CONSTANTPOOL_GROW_SIZE]), 0, length);
-            poolContent[currentOffset - 1] = (byte) (value >> 8);
-        }
-        try {
-            poolContent[currentOffset++] = (byte) value;
-        } catch (IndexOutOfBoundsException e) {
-            // currentOffset has been ++ already (see the -1)
-            int length = poolContent.length;
-            System.arraycopy(poolContent, 0, (poolContent = new byte[length
-                    + CONSTANTPOOL_GROW_SIZE]), 0, length);
-            poolContent[currentOffset - 1] = (byte) value;
-        }
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstants.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstants.java
deleted file mode 100644
index 93db394..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstants.java
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.internal.reflect;
-
-
-interface ProxyConstants {
-    final char[] CodeName = new char[] { 'C', 'o', 'd', 'e' };
-
-    final char[] ExceptionsName = new char[] { 'E', 'x', 'c', 'e', 'p', 't',
-            'i', 'o', 'n', 's' };
-
-    final char[] Init = new char[] { '<', 'i', 'n', 'i', 't', '>' };
-
-    final int AccPublic = 0x0001;
-
-    final int AccPrivate = 0x0002;
-
-    final int AccProtected = 0x0004;
-
-    final int AccStatic = 0x0008;
-
-    final int AccFinal = 0x0010;
-
-    final int AccSuper = 0x0020;
-
-    final int Utf8Tag = 1;
-
-    final int IntegerTag = 3;
-
-    final int FloatTag = 4;
-
-    final int LongTag = 5;
-
-    final int DoubleTag = 6;
-
-    final int ClassTag = 7;
-
-    final int StringTag = 8;
-
-    final int FieldRefTag = 9;
-
-    final int MethodRefTag = 10;
-
-    final int InterfaceMethodRefTag = 11;
-
-    final int NameAndTypeTag = 12;
-
-    final int OPC_nop = 0;
-
-    final int OPC_aconst_null = 1;
-
-    final int OPC_iconst_m1 = 2;
-
-    final int OPC_iconst_0 = 3;
-
-    final int OPC_iconst_1 = 4;
-
-    final int OPC_iconst_2 = 5;
-
-    final int OPC_iconst_3 = 6;
-
-    final int OPC_iconst_4 = 7;
-
-    final int OPC_iconst_5 = 8;
-
-    final int OPC_lconst_0 = 9;
-
-    final int OPC_lconst_1 = 10;
-
-    final int OPC_fconst_0 = 11;
-
-    final int OPC_fconst_1 = 12;
-
-    final int OPC_fconst_2 = 13;
-
-    final int OPC_dconst_0 = 14;
-
-    final int OPC_dconst_1 = 15;
-
-    final int OPC_bipush = 16;
-
-    final int OPC_sipush = 17;
-
-    final int OPC_ldc = 18;
-
-    final int OPC_ldc_w = 19;
-
-    final int OPC_ldc2_w = 20;
-
-    final int OPC_iload = 21;
-
-    final int OPC_lload = 22;
-
-    final int OPC_fload = 23;
-
-    final int OPC_dload = 24;
-
-    final int OPC_aload = 25;
-
-    final int OPC_iload_0 = 26;
-
-    final int OPC_iload_1 = 27;
-
-    final int OPC_iload_2 = 28;
-
-    final int OPC_iload_3 = 29;
-
-    final int OPC_lload_0 = 30;
-
-    final int OPC_lload_1 = 31;
-
-    final int OPC_lload_2 = 32;
-
-    final int OPC_lload_3 = 33;
-
-    final int OPC_fload_0 = 34;
-
-    final int OPC_fload_1 = 35;
-
-    final int OPC_fload_2 = 36;
-
-    final int OPC_fload_3 = 37;
-
-    final int OPC_dload_0 = 38;
-
-    final int OPC_dload_1 = 39;
-
-    final int OPC_dload_2 = 40;
-
-    final int OPC_dload_3 = 41;
-
-    final int OPC_aload_0 = 42;
-
-    final int OPC_aload_1 = 43;
-
-    final int OPC_aload_2 = 44;
-
-    final int OPC_aload_3 = 45;
-
-    final int OPC_iaload = 46;
-
-    final int OPC_laload = 47;
-
-    final int OPC_faload = 48;
-
-    final int OPC_daload = 49;
-
-    final int OPC_aaload = 50;
-
-    final int OPC_baload = 51;
-
-    final int OPC_caload = 52;
-
-    final int OPC_saload = 53;
-
-    final int OPC_istore = 54;
-
-    final int OPC_lstore = 55;
-
-    final int OPC_fstore = 56;
-
-    final int OPC_dstore = 57;
-
-    final int OPC_astore = 58;
-
-    final int OPC_istore_0 = 59;
-
-    final int OPC_istore_1 = 60;
-
-    final int OPC_istore_2 = 61;
-
-    final int OPC_istore_3 = 62;
-
-    final int OPC_lstore_0 = 63;
-
-    final int OPC_lstore_1 = 64;
-
-    final int OPC_lstore_2 = 65;
-
-    final int OPC_lstore_3 = 66;
-
-    final int OPC_fstore_0 = 67;
-
-    final int OPC_fstore_1 = 68;
-
-    final int OPC_fstore_2 = 69;
-
-    final int OPC_fstore_3 = 70;
-
-    final int OPC_dstore_0 = 71;
-
-    final int OPC_dstore_1 = 72;
-
-    final int OPC_dstore_2 = 73;
-
-    final int OPC_dstore_3 = 74;
-
-    final int OPC_astore_0 = 75;
-
-    final int OPC_astore_1 = 76;
-
-    final int OPC_astore_2 = 77;
-
-    final int OPC_astore_3 = 78;
-
-    final int OPC_iastore = 79;
-
-    final int OPC_lastore = 80;
-
-    final int OPC_fastore = 81;
-
-    final int OPC_dastore = 82;
-
-    final int OPC_aastore = 83;
-
-    final int OPC_bastore = 84;
-
-    final int OPC_castore = 85;
-
-    final int OPC_sastore = 86;
-
-    final int OPC_pop = 87;
-
-    final int OPC_pop2 = 88;
-
-    final int OPC_dup = 89;
-
-    final int OPC_dup_x1 = 90;
-
-    final int OPC_dup_x2 = 91;
-
-    final int OPC_dup2 = 92;
-
-    final int OPC_dup2_x1 = 93;
-
-    final int OPC_dup2_x2 = 94;
-
-    final int OPC_swap = 95;
-
-    final int OPC_iadd = 96;
-
-    final int OPC_ladd = 97;
-
-    final int OPC_fadd = 98;
-
-    final int OPC_dadd = 99;
-
-    final int OPC_isub = 100;
-
-    final int OPC_lsub = 101;
-
-    final int OPC_fsub = 102;
-
-    final int OPC_dsub = 103;
-
-    final int OPC_imul = 104;
-
-    final int OPC_lmul = 105;
-
-    final int OPC_fmul = 106;
-
-    final int OPC_dmul = 107;
-
-    final int OPC_idiv = 108;
-
-    final int OPC_ldiv = 109;
-
-    final int OPC_fdiv = 110;
-
-    final int OPC_ddiv = 111;
-
-    final int OPC_irem = 112;
-
-    final int OPC_lrem = 113;
-
-    final int OPC_frem = 114;
-
-    final int OPC_drem = 115;
-
-    final int OPC_ineg = 116;
-
-    final int OPC_lneg = 117;
-
-    final int OPC_fneg = 118;
-
-    final int OPC_dneg = 119;
-
-    final int OPC_ishl = 120;
-
-    final int OPC_lshl = 121;
-
-    final int OPC_ishr = 122;
-
-    final int OPC_lshr = 123;
-
-    final int OPC_iushr = 124;
-
-    final int OPC_lushr = 125;
-
-    final int OPC_iand = 126;
-
-    final int OPC_land = 127;
-
-    final int OPC_ior = 128;
-
-    final int OPC_lor = 129;
-
-    final int OPC_ixor = 130;
-
-    final int OPC_lxor = 131;
-
-    final int OPC_iinc = 132;
-
-    final int OPC_i2l = 133;
-
-    final int OPC_i2f = 134;
-
-    final int OPC_i2d = 135;
-
-    final int OPC_l2i = 136;
-
-    final int OPC_l2f = 137;
-
-    final int OPC_l2d = 138;
-
-    final int OPC_f2i = 139;
-
-    final int OPC_f2l = 140;
-
-    final int OPC_f2d = 141;
-
-    final int OPC_d2i = 142;
-
-    final int OPC_d2l = 143;
-
-    final int OPC_d2f = 144;
-
-    final int OPC_i2b = 145;
-
-    final int OPC_i2c = 146;
-
-    final int OPC_i2s = 147;
-
-    final int OPC_lcmp = 148;
-
-    final int OPC_fcmpl = 149;
-
-    final int OPC_fcmpg = 150;
-
-    final int OPC_dcmpl = 151;
-
-    final int OPC_dcmpg = 152;
-
-    final int OPC_ifeq = 153;
-
-    final int OPC_ifne = 154;
-
-    final int OPC_iflt = 155;
-
-    final int OPC_ifge = 156;
-
-    final int OPC_ifgt = 157;
-
-    final int OPC_ifle = 158;
-
-    final int OPC_if_icmpeq = 159;
-
-    final int OPC_if_icmpne = 160;
-
-    final int OPC_if_icmplt = 161;
-
-    final int OPC_if_icmpge = 162;
-
-    final int OPC_if_icmpgt = 163;
-
-    final int OPC_if_icmple = 164;
-
-    final int OPC_if_acmpeq = 165;
-
-    final int OPC_if_acmpne = 166;
-
-    final int OPC_goto = 167;
-
-    final int OPC_jsr = 168;
-
-    final int OPC_ret = 169;
-
-    final int OPC_tableswitch = 170;
-
-    final int OPC_lookupswitch = 171;
-
-    final int OPC_ireturn = 172;
-
-    final int OPC_lreturn = 173;
-
-    final int OPC_freturn = 174;
-
-    final int OPC_dreturn = 175;
-
-    final int OPC_areturn = 176;
-
-    final int OPC_return = 177;
-
-    final int OPC_getstatic = 178;
-
-    final int OPC_putstatic = 179;
-
-    final int OPC_getfield = 180;
-
-    final int OPC_putfield = 181;
-
-    final int OPC_invokevirtual = 182;
-
-    final int OPC_invokespecial = 183;
-
-    final int OPC_invokestatic = 184;
-
-    final int OPC_invokeinterface = 185;
-
-    final int OPC_new = 187;
-
-    final int OPC_newarray = 188;
-
-    final int OPC_anewarray = 189;
-
-    final int OPC_arraylength = 190;
-
-    final int OPC_athrow = 191;
-
-    final int OPC_checkcast = 192;
-
-    final int OPC_instanceof = 193;
-
-    final int OPC_monitorenter = 194;
-
-    final int OPC_monitorexit = 195;
-
-    final int OPC_wide = 196;
-
-    final int OPC_multianewarray = 197;
-
-    final int OPC_ifnull = 198;
-
-    final int OPC_ifnonnull = 199;
-
-    final int OPC_goto_w = 200;
-
-    final int OPC_jsr_w = 201;
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java
deleted file mode 100644
index cd112b5..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.internal.reflect;
-
-import java.lang.reflect.Method;
-
-import org.apache.harmony.luni.util.Msg;
-
-class ProxyMethod {
-    Method method;
-
-    Class[] commonExceptions;
-
-    ProxyMethod(Method method) {
-        this.method = method;
-        this.commonExceptions = method.getExceptionTypes();
-    }
-
-    Class[] getCheckedExceptions() {
-        Class[] newExceptions = commonExceptions.clone();
-        int cLength = newExceptions.length;
-        for (int c = 0, cL = cLength; c < cL; c++) {
-            Class<?> ex = newExceptions[c];
-            if (Throwable.class == ex) {
-                // if Throwable is included then treat as if no exceptions are
-                // checked
-                return new Class[0];
-            }
-            if (Error.class.isAssignableFrom(ex) || RuntimeException.class.isAssignableFrom(ex)) {
-                newExceptions[c] = null;
-                cLength--;
-            }
-        }
-
-        // All errors & runtime exceptions are passed back without being wrapped
-        Class[] result = new Class[cLength + 2];
-        int index = 0;
-        result[index++] = Error.class;
-        result[index++] = RuntimeException.class;
-        for (Class<?> ex : newExceptions) {
-            if (ex != null) {
-                result[index++] = ex;
-            }
-        }
-        return result;
-    }
-
-    boolean matchMethod(Method otherMethod) {
-        if (!method.getName().equals(otherMethod.getName())) {
-            return false;
-        }
-
-        Class[] params1 = method.getParameterTypes();
-        Class[] params2 = otherMethod.getParameterTypes();
-        int p = params1.length;
-        if (p != params2.length) {
-            return false;
-        }
-        while (--p >= 0) {
-            if (params1[p] != params2[p]) {
-                return false;
-            }
-        }
-
-        Class<?> thisMethodReturnType = method.getReturnType();
-        Class<?> otherMethodReturnType = otherMethod.getReturnType();
-        if (!thisMethodReturnType.isAssignableFrom(otherMethodReturnType)) {
-            if (otherMethodReturnType.isAssignableFrom(thisMethodReturnType)) {
-                // substitute returnType of method with that of otherMethod
-                method = otherMethod;
-            } else {
-                throw new IllegalArgumentException(Msg.getString("K00f2",
-                        method.getName()));
-            }
-        }        
-        
-        if (commonExceptions.length != 0) {
-            Class[] otherExceptions = otherMethod.getExceptionTypes();
-            if (otherExceptions.length == 0) {
-                commonExceptions = otherExceptions;
-            } else {
-                int cLength = commonExceptions.length;
-                nextException: for (int c = 0, cL = cLength, oL = otherExceptions.length; c < cL; c++) {
-                    Class<?> cException = commonExceptions[c];
-                    for (int o = 0; o < oL; o++) {
-                        Class<?> oException = otherExceptions[o];
-                        if (cException == oException) {
-                            continue nextException;
-                        }
-                        if (oException.isAssignableFrom(cException)) {
-                            continue nextException; // cException is a subclass
-                        }
-                        if (cException.isAssignableFrom(oException)) {
-                            // oException is a subclass, keep it instead
-                            commonExceptions[c] = cException = oException;
-                            continue nextException;
-                        }
-                    }
-                    commonExceptions[c] = null;
-                    cLength--;
-                }
-                if (cLength != commonExceptions.length) {
-                    Class[] newExceptions = new Class[cLength];
-                    for (int i = 0, j = 0, length = commonExceptions.length; i < length; i++) {
-                        Class<?> ex = commonExceptions[i];
-                        if (ex != null) {
-                            newExceptions[j++] = ex;
-                        }
-                    }
-                    commonExceptions = newExceptions;
-                }
-            }
-        }
-        return true;
-    }
-
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyNameAndTypeCache.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyNameAndTypeCache.java
deleted file mode 100644
index 09eb23e..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyNameAndTypeCache.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.internal.reflect;
-
-class ProxyNameAndTypeCache {
-    int[][] keyTable;
-
-    int[] valueTable;
-
-    int elementSize;
-
-    int threshold;
-
-    ProxyNameAndTypeCache(int initialCapacity) {
-        if (initialCapacity < 13) {
-            initialCapacity = 13;
-        }
-        this.elementSize = 0;
-        this.threshold = (int) (initialCapacity * 0.66f);
-        this.keyTable = new int[initialCapacity][];
-        this.valueTable = new int[initialCapacity];
-    }
-
-    int get(int[] key) {
-        int index = hashCode(key);
-        while (keyTable[index] != null) {
-            if (keyTable[index][0] == key[0] && keyTable[index][1] == key[1]) {
-                return valueTable[index];
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        return -1;
-    }
-
-    int hashCode(int[] key) {
-        return (key[0] + key[1]) % keyTable.length;
-    }
-
-    int put(int[] key, int value) {
-        int index = hashCode(key);
-        while (keyTable[index] != null) {
-            if (keyTable[index][0] == key[0] && keyTable[index][1] == key[1]) {
-                return valueTable[index] = value;
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        keyTable[index] = key;
-        valueTable[index] = value;
-
-        // assumes the threshold is never equal to the size of the table
-        if (++elementSize > threshold) {
-            rehash();
-        }
-        return value;
-    }
-
-    private void rehash() {
-        ProxyNameAndTypeCache newHashtable = new ProxyNameAndTypeCache(keyTable.length * 2);
-        for (int i = keyTable.length; --i >= 0;) {
-            if (keyTable[i] != null) {
-                newHashtable.put(keyTable[i], valueTable[i]);
-            }
-        }
-
-        this.keyTable = newHashtable.keyTable;
-        this.valueTable = newHashtable.valueTable;
-        this.threshold = newHashtable.threshold;
-    }
-
-    int size() {
-        return elementSize;
-    }
-
-    @Override
-    public String toString() {
-        int max = size();
-        StringBuilder buf = new StringBuilder();
-        buf.append("{");
-        for (int i = 0; i < max; ++i) {
-            if (keyTable[i] != null) {
-                buf.append(keyTable[i]).append("->").append(valueTable[i]);
-            }
-            if (i < max) {
-                buf.append(", ");
-            }
-        }
-        buf.append("}");
-        return buf.toString();
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyObjectCache.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyObjectCache.java
deleted file mode 100644
index b3089c5..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyObjectCache.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.internal.reflect;
-
-class ProxyObjectCache {
-    Object keyTable[];
-
-    int valueTable[];
-
-    int elementSize;
-
-    int threshold;
-
-    ProxyObjectCache(int initialCapacity) {
-        if (initialCapacity < 13) {
-            initialCapacity = 13;
-        }
-        this.elementSize = 0;
-        this.threshold = (int) (initialCapacity * 0.66f);
-        this.keyTable = new Object[initialCapacity];
-        this.valueTable = new int[initialCapacity];
-    }
-
-    int get(Object key) {
-        int index = hashCode(key);
-        while (keyTable[index] != null) {
-            if (keyTable[index].equals(key)) {
-                return valueTable[index];
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        return -1;
-    }
-
-    int hashCode(Object key) {
-        return (key.hashCode() & 0x7FFFFFFF) % keyTable.length;
-    }
-
-    int put(Object key, int value) {
-        int index = hashCode(key);
-        while (keyTable[index] != null) {
-            if (keyTable[index].equals(key)) {
-                return valueTable[index] = value;
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        keyTable[index] = key;
-        valueTable[index] = value;
-
-        // assumes the threshold is never equal to the size of the table
-        if (++elementSize > threshold) {
-            rehash();
-        }
-        return value;
-    }
-
-    private void rehash() {
-        ProxyObjectCache newHashtable = new ProxyObjectCache(
-                keyTable.length * 2);
-        for (int i = keyTable.length; --i >= 0;) {
-            if (keyTable[i] != null) {
-                newHashtable.put(keyTable[i], valueTable[i]);
-            }
-        }
-
-        this.keyTable = newHashtable.keyTable;
-        this.valueTable = newHashtable.valueTable;
-        this.threshold = newHashtable.threshold;
-    }
-
-    int size() {
-        return elementSize;
-    }
-
-    @Override
-    public String toString() {
-        int max = size();
-        StringBuilder buf = new StringBuilder();
-        buf.append("{"); //$NON-NLS-1$
-        for (int i = 0; i < max; ++i) {
-            if (keyTable[i] != null) {
-                buf.append(keyTable[i]).append("->").append(valueTable[i]); //$NON-NLS-1$
-            }
-            if (i < max) {
-                buf.append(", "); //$NON-NLS-1$
-            }
-        }
-        buf.append("}"); //$NON-NLS-1$
-        return buf.toString();
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
index 230df13..ac0c877 100644
--- a/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
@@ -42,7 +42,7 @@
  * support security checks. Alternative types of DatagramSocketImpl's may be
  * used by setting the <code>impl.prefix</code> system property.
  */
-class PlainDatagramSocketImpl extends DatagramSocketImpl {
+public class PlainDatagramSocketImpl extends DatagramSocketImpl {
 
     static final int MULTICAST_IF = 1;
 
@@ -70,7 +70,8 @@
      */
     static final int REUSEADDR_AND_REUSEPORT = 10001;
 
-    private boolean bindToDevice;
+    // Ignored in native code
+    private boolean bindToDevice = false;
 
     private byte[] ipaddress = { 0, 0, 0, 0 };
 
@@ -116,7 +117,7 @@
     public void bind(int port, InetAddress addr) throws SocketException {
         String prop = AccessController.doPrivileged(new PriviAction<String>("bindToDevice")); //$NON-NLS-1$
         boolean useBindToDevice = prop != null && prop.toLowerCase().equals("true"); //$NON-NLS-1$
-        bindToDevice = netImpl.bind2(fd, port, useBindToDevice, addr);
+        netImpl.bind(fd, addr, port);
         if (0 != port) {
             localPort = port;
         } else {
diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java
deleted file mode 100644
index 7f5ac50..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.net;
-
-import java.net.SocketException;
-
-import org.apache.harmony.luni.platform.Platform;
-
-/**
- * This class was added so we can create sockets with options that are needed
- * for server sockets. It just overrides create so that we call new natives
- * which only set the options required for server sockets. In order to preserve
- * behaviour of older versions the create PlainSocketImpl was left as is and
- * this new class was added. For newer versions an instance of this class is
- * used, for earlier versions the original PlainSocketImpl is used.
- */
-class PlainMulticastSocketImpl extends PlainDatagramSocketImpl {
-
-    @Override
-    public void create() throws SocketException {
-        Platform.getNetworkSystem().createMulticastSocket(fd, NetUtil.preferIPv4Stack());
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java
index de6cb8f..4343ffb 100644
--- a/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java
@@ -24,14 +24,10 @@
 import org.apache.harmony.luni.net.PlainSocketImpl;
 
 /**
- * This class was added so we can create sockets with options that are needed
- * for server sockets. It just overrides create so that we call new natives
- * which only set the options required for server sockets. In order to preserve
- * behaviour of older versions the create PlainSocketImpl was left as is and
- * this new class was added. For newer versions an instance of this class is
- * used, for earlier versions the original PlainSocketImpl is used.
+ * This class overrides create to call natives that set the options required
+ * for server sockets.
  */
-class PlainServerSocketImpl extends PlainSocketImpl {
+public class PlainServerSocketImpl extends PlainSocketImpl {
 
     public PlainServerSocketImpl() {
         super();
diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
index 4fb8b91..9a3ae6e 100644
--- a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
@@ -43,7 +43,7 @@
 /**
  * A concrete connected-socket implementation.
  */
-class PlainSocketImpl extends SocketImpl {
+public class PlainSocketImpl extends SocketImpl {
 
     // Const copy from socket
 
@@ -89,6 +89,27 @@
         fd = new FileDescriptor();
     }
 
+    public PlainSocketImpl(FileDescriptor fd) {
+        super();
+        this.fd = fd;
+    }
+
+    /**
+     * creates an instance with specified proxy.
+     */
+    public PlainSocketImpl(Proxy proxy) {
+        this();
+        this.proxy = proxy;
+    }
+
+    public PlainSocketImpl(FileDescriptor fd, int localport, InetAddress addr, int port) {
+        super();
+        this.fd = fd;
+        this.localport = localport;
+        this.address = addr;
+        this.port = port;
+    }
+
     @Override
     protected void accept(SocketImpl newImpl) throws IOException {
         if (NetUtil.usingSocks(proxy)) {
@@ -160,7 +181,7 @@
 
     @Override
     protected void bind(InetAddress anAddr, int aPort) throws IOException {
-        netImpl.bind(fd, aPort, anAddr);
+        netImpl.bind(fd, anAddr, aPort);
         // PlainSocketImpl2.socketBindImpl2(fd, aPort, anAddr);
         address = anAddr;
         if (0 != aPort) {
@@ -201,7 +222,7 @@
 
     /**
      * Connects this socket to the specified remote host address/port.
-     * 
+     *
      * @param anAddr
      *            the remote host address to connect to
      * @param aPort
@@ -211,13 +232,10 @@
      * @throws IOException
      *             if an error occurs while connecting
      */
-    // BEGIN android-changed
-    // copied from a newer harmony revision
     private void connect(InetAddress anAddr, int aPort, int timeout)
             throws IOException {
-        InetAddress normalAddr = anAddr.isAnyLocalAddress() ? InetAddress
-                .getLocalHost() : anAddr;
 
+        InetAddress normalAddr = anAddr.isAnyLocalAddress() ? InetAddress.getLocalHost() : anAddr;
         try {
             if (streaming) {
                 if (NetUtil.usingSocks(proxy)) {
@@ -231,7 +249,7 @@
                     }
                 }
             } else {
-                netImpl.connectDatagram(fd, aPort, trafficClass, normalAddr);
+            	netImpl.connectDatagram(fd, aPort, trafficClass, normalAddr);
             }
         } catch (ConnectException e) {
             throw new ConnectException(anAddr + ":" + aPort + " - "
@@ -240,16 +258,12 @@
         super.address = normalAddr;
         super.port = aPort;
     }
-    // END android-changed
 
     @Override
     protected void create(boolean streaming) throws IOException {
         this.streaming = streaming;
         if (streaming) {
-            // BEGIN android-changed
-            // call createSocket instead of createStreamSocket
-            netImpl.createSocket(fd, NetUtil.preferIPv4Stack());
-            // END android-changed
+            netImpl.createStreamSocket(fd, NetUtil.preferIPv4Stack());
         } else {
             netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack());
         }
@@ -546,16 +560,19 @@
         if (shutdownInput) {
             return -1;
         }
-        try {
-            int read = netImpl.receiveStream(fd, buffer, offset, count,
-                    receiveTimeout);
-            if (read == -1) {
-                shutdownInput = true;
-            }
-            return read;
-        } catch (InterruptedIOException e) {
-            throw new SocketTimeoutException(e.getMessage());
+        // BEGIN android-changed
+        // call receiveStream() instead of read()
+        int read = netImpl.receiveStream(fd, buffer, offset, count, receiveTimeout);
+        // END android-changed
+        // Return of zero bytes for a blocking socket means a timeout occurred
+        if (read == 0) {
+            throw new SocketTimeoutException();
         }
+        // Return of -1 indicates the peer was closed
+        if (read == -1) {
+            shutdownInput = true;
+        }
+        return read;
     }
 
     int write(byte[] buffer, int offset, int count) throws IOException {
@@ -563,6 +580,9 @@
             return netImpl.sendDatagram2(fd, buffer, offset, count, port,
                     address);
         }
+        // BEGIN android-changed
+        // call sendStream() instead of write()
         return netImpl.sendStream(fd, buffer, offset, count);
+        // END android-changed
     }
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java
deleted file mode 100644
index 160de7c..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.net;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Proxy;
-
-/**
- * This class was added so we can create sockets without options that were
- * needed for server sockets. It just overrides create so that we call new
- * natives which only set the options required for plain sockets. In order to
- * preserve behaviour of older versions the create PlainSocketImpl was left as
- * is and this new class was added. For newer versions an instance of this class
- * is used, for earlier versions the original PlainSocketImpl is used.
- */
-class PlainSocketImpl2 extends PlainSocketImpl {
-
-    public PlainSocketImpl2(FileDescriptor fd, int localport, InetAddress addr, int port) {
-        super();
-        super.fd = fd;
-        super.localport = localport;
-        super.address = addr;
-        super.port = port;
-    }
-
-    public PlainSocketImpl2() {
-        super();
-    }
-
-    /**
-     * creates an instance with specified proxy.
-     */
-    public PlainSocketImpl2(Proxy proxy) {
-        super();
-        this.proxy = proxy;
-    }
-
-    @Override
-    protected void create(boolean isStreaming) throws IOException {
-        streaming = isStreaming;
-        if (isStreaming) {
-            netImpl.createSocket(fd, NetUtil.preferIPv4Stack());
-        } else {
-            netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack());
-        }
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java b/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java
deleted file mode 100644
index e8e7dc3..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.harmony.luni.net;
-
-import java.io.FileDescriptor;
-import java.net.DatagramSocketImpl;
-import java.net.InetAddress;
-import java.net.Proxy;
-import java.net.SocketImpl;
-
-public class SocketImplProvider {
-
-    public static SocketImpl getSocketImpl() {
-        return new PlainSocketImpl2();
-    }
-
-    /**
-     * gets a SocketImpl with specified proxy.
-     */
-    public static SocketImpl getSocketImpl(Proxy proxy) {
-        return new PlainSocketImpl2(proxy);
-    }
-
-    public static SocketImpl getSocketImpl(FileDescriptor fd, int localport, InetAddress addr,
-            int port) {
-        return new PlainSocketImpl2(fd, localport, addr, port);
-    }
-
-    public static SocketImpl getServerSocketImpl() {
-        return new PlainServerSocketImpl();
-    }
-
-    public static SocketImpl getServerSocketImpl(FileDescriptor fd) {
-        return new PlainServerSocketImpl(fd);
-    }
-
-    public static DatagramSocketImpl getDatagramSocketImpl() {
-        return new PlainDatagramSocketImpl();
-    }
-
-    public static DatagramSocketImpl getMulticastSocketImpl() {
-        return new PlainMulticastSocketImpl();
-    }
-
-    public static DatagramSocketImpl getDatagramSocketImpl(FileDescriptor fd, int localPort) {
-        return new PlainDatagramSocketImpl(fd, localPort);
-    }
-
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java b/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java
index 130454f..5462cf0 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java
@@ -30,84 +30,82 @@
  */
 abstract class AbstractMemorySpy implements IMemorySpy {
 
-    // TODO: figure out how to prevent this being a synchronization bottleneck
-    protected Map<PlatformAddress,AddressWrapper> memoryInUse = new HashMap<PlatformAddress, AddressWrapper>(); // Shadow to Wrapper
+	// TODO: figure out how to prevent this being a synchronization bottleneck
+	protected Map<PlatformAddress,AddressWrapper> memoryInUse = new HashMap<PlatformAddress, AddressWrapper>(); // Shadow to Wrapper
 
-    protected Map<Reference,PlatformAddress> refToShadow = new HashMap<Reference, PlatformAddress>(); // Reference to Shadow
+	protected Map<Reference,PlatformAddress> refToShadow = new HashMap<Reference, PlatformAddress>(); // Reference to Shadow
 
-    protected ReferenceQueue<Object> notifyQueue = new ReferenceQueue<Object>();
+	protected ReferenceQueue<Object> notifyQueue = new ReferenceQueue<Object>();
 
-       final class AddressWrapper {
-        final PlatformAddress shadow;
+   	final class AddressWrapper {
+		final PlatformAddress shadow;
 
-        final PhantomReference<PlatformAddress> wrAddress;
+		final PhantomReference<PlatformAddress> wrAddress;
 
-        volatile boolean autoFree = false;
+		volatile boolean autoFree = false;
 
-        AddressWrapper(PlatformAddress address) {
-            super();
-            this.shadow = address.duplicate();
-            this.wrAddress = new PhantomReference<PlatformAddress>(address, notifyQueue);
-        }
-    }
+		AddressWrapper(PlatformAddress address) {
+			super();
+			this.shadow = address.duplicate();
+			this.wrAddress = new PhantomReference<PlatformAddress>(address, notifyQueue);
+		}
+	}
 
-    public AbstractMemorySpy() {
-        super();
-    }
+	public AbstractMemorySpy() {
+		super();
+	}
 
-    public void alloc(PlatformAddress address) {
-        AddressWrapper wrapper = new AddressWrapper(address);
-        synchronized (this) {
-            memoryInUse.put(wrapper.shadow, wrapper);
-            refToShadow.put(wrapper.wrAddress, wrapper.shadow);
-        }
-    }
+	public void alloc(PlatformAddress address) {
+		AddressWrapper wrapper = new AddressWrapper(address);
+		synchronized (this) {
+			memoryInUse.put(wrapper.shadow, wrapper);
+			refToShadow.put(wrapper.wrAddress, wrapper.shadow);
+		}
+	}
 
-    public boolean free(PlatformAddress address) {
-        AddressWrapper wrapper;
-        synchronized (this) {
-            wrapper = memoryInUse.remove(address);
+	public boolean free(PlatformAddress address) {
+		AddressWrapper wrapper;
+		synchronized (this) {
+			wrapper = memoryInUse.remove(address);
             // BEGIN android-added
             if (wrapper != null) {
                 refToShadow.remove(wrapper.wrAddress);
             }
             // END android-added
-        }
-        if (wrapper == null) {
-            // Attempt to free memory we didn't alloc
-            System.err
-                    .println("Memory Spy! Fixed attempt to free memory that was not allocated " + address); //$NON-NLS-1$
-        }
-        return wrapper != null;
-    }
+		}
+		if (wrapper == null) {
+			// Attempt to free memory we didn't alloc
+			System.err
+					.println("Memory Spy! Fixed attempt to free memory that was not allocated " + address); //$NON-NLS-1$
+		}
+		return wrapper != null;
+	}
 
-    public void rangeCheck(PlatformAddress address, int offset, int length)
-            throws IndexOutOfBoundsException {
-        // Do nothing
-    }
+	public void rangeCheck(PlatformAddress address, int offset, int length)
+			throws IndexOutOfBoundsException {
+		// Do nothing
+	}
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.harmony.luni.platform.struct.IMemorySpy#autoFree(org.apache.harmony.luni.platform.struct.PlatformAddress)
-     */
-    public void autoFree(PlatformAddress address) {
-        AddressWrapper wrapper;
-        synchronized (this) {
-            wrapper = memoryInUse.get(address);
-        }
-        if (wrapper != null) {
-            wrapper.autoFree = true;
-        }
-    }
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.apache.harmony.luni.platform.struct.IMemorySpy#autoFree(org.apache.harmony.luni.platform.struct.PlatformAddress)
+	 */
+	public void autoFree(PlatformAddress address) {
+		AddressWrapper wrapper;
+		synchronized (this) {
+			wrapper = memoryInUse.get(address);
+		}
+		if (wrapper != null) {
+			wrapper.autoFree = true;
+		}
+	}
 
-    protected void orphanedMemory(Reference ref) {
-        AddressWrapper wrapper;
-        // BEGIN android-changed
-        // copied from newer version of harmony
-        synchronized (this) {
-            PlatformAddress shadow = refToShadow.remove(ref);
-            wrapper = memoryInUse.get(shadow);
+	protected void orphanedMemory(Reference ref) {
+		AddressWrapper wrapper;
+		synchronized (this) {
+			PlatformAddress shadow = refToShadow.remove(ref);
+			wrapper = memoryInUse.get(shadow);
             if (wrapper != null) {
                 // There is a leak if we were not auto-freeing this memory.
                 if (!wrapper.autoFree) {
@@ -116,8 +114,7 @@
                 }
                 wrapper.shadow.free();
             }
-        }
+		}
         ref.clear();
-        // END android-changed
-    }
+	}
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/AdapterManager.java b/luni/src/main/java/org/apache/harmony/luni/platform/AdapterManager.java
deleted file mode 100644
index 2380fbc..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/platform/AdapterManager.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.luni.platform;
-
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Adapter Manager
- *  
- */
-final class AdapterManager implements IAdapterManager {
-
-    /*
-     * key is adaptable type, and value is list of adapter factories for that
-     * type.
-     */
-    private final HashMap<Class, List<IAdapterFactory>> factories = new HashMap<Class, List<IAdapterFactory>>();
-
-    public Object getAdapter(IAdaptable adaptable, Class adapterType) {
-        List factoryList = factories.get(adapterType);
-        if (factoryList != null) {
-            for (Iterator factoryItr = factoryList.iterator(); factoryItr
-                    .hasNext();) {
-                IAdapterFactory factory = (IAdapterFactory) factoryItr.next();
-                Object adapter = factory.getAdapter(adaptable, adapterType);
-                if (adapter != null) {
-                    return adapter;
-                }
-            }
-        }
-        return null;
-    }
-
-    public boolean hasAdapter(IAdaptable adaptable, Class adapterType) {
-        return null == getAdapter(adaptable, adapterType);
-    }
-
-    public void registerAdapters(IAdapterFactory factory, Class adaptable) {
-        List<IAdapterFactory> factoryList = factories.get(adaptable);
-        if (factoryList == null) {
-            factoryList = new ArrayList<IAdapterFactory>();
-            factories.put(adaptable, factoryList);
-        }
-        factoryList.add(factory);
-    }
-
-    public void unregisterAdapters(IAdapterFactory factory, Class adaptable) {
-        List factoryList = factories.get(adaptable);
-        if (factoryList != null) {
-            factoryList.remove(factory);
-        }
-    }
-
-    public void unregisterAdapters(IAdapterFactory factory) {
-        for (Iterator<Class> knownAdaptablesItr = factories.keySet().iterator(); knownAdaptablesItr
-                .hasNext();) {
-            Class adaptable = knownAdaptablesItr.next();
-            unregisterAdapters(factory, adaptable);
-        }
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IAdaptable.java b/luni/src/main/java/org/apache/harmony/luni/platform/IAdaptable.java
deleted file mode 100644
index e4c72ea..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/platform/IAdaptable.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.luni.platform;
-
-
-/**
- * The interface to extensible objects.
- * <p>
- * Classes can implement this interface (a single method) to provide interfaces
- * that are not API -- each interface type has to be handled in the
- * implementation of <code>getAdapter(Class)</code>. This is a good way to
- * extend the class without breaking existing API.
- * </p>
- * <p>
- * In addition, classes can be augmented by interfaces that are defined by other
- * classes (which requires the <code>getAdapter(Class)</code> to be
- * implemented by a factory.
- * 
- */
-public interface IAdaptable {
-
-    /**
-     * Returns the adapter corresponding to the given class.
-     * <p>
-     * The adapter is typically obtained using the class literal, like this:
-     * 
-     * <pre>
-     *    ...
-     *    IAdaptable = (IAdaptable) foo;
-     *    IMyInterface bar = (IMyInterface)foo.getAdapter(IMyInterface.class);
-     *    bar.doMyThing();
-     *    ...
-     * </pre>
-     * 
-     * @param adapter
-     *            the type of adapter requested
-     * @return the adapter
-     */
-    public Object getAdapter(Class adapter);
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterFactory.java b/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterFactory.java
deleted file mode 100644
index 49fcd15..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterFactory.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.luni.platform;
-
-
-/**
- * IAdapterFactory
- * 
- */
-public interface IAdapterFactory {
-
-    /**
-     * Answer the adapter of the given type for the given object.
-     * 
-     * @param adaptableObject
-     *            the object that implements IAdaptable.
-     * @param adapterType
-     *            the type of adapter to return.
-     * @return the adapter of the requested type.
-     */
-    public Object getAdapter(IAdaptable adaptableObject, Class adapterType);
-
-    /**
-     * Returns the adapters that this factory provides.
-     * 
-     * @return the list of adapters as an array of classes.
-     */
-    public Class[] getAdapterList();
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterManager.java b/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterManager.java
deleted file mode 100644
index 886dda7..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterManager.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.luni.platform;
-
-
-/**
- * IAdapterManager
- * 
- */
-public interface IAdapterManager {
-    public Object getAdapter(IAdaptable adaptable, Class adapterType);
-
-    public boolean hasAdapter(IAdaptable adaptable, Class adapterType);
-
-    public void registerAdapters(IAdapterFactory factory, Class adaptable);
-
-    public void unregisterAdapters(IAdapterFactory factory);
-
-    public void unregisterAdapters(IAdapterFactory factory, Class adaptable);
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
index fb2ff9d..7613f0e 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
@@ -29,7 +29,7 @@
  * TODO Type description
  * 
  */
-public interface IFileSystem extends ISystemComponent {
+public interface IFileSystem {
 
     public final int SHARED_LOCK_TYPE = 1;
 
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
index 9f70515..eae5261 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
@@ -29,17 +29,12 @@
 import java.net.SocketImpl;
 import java.net.UnknownHostException;
 import java.nio.channels.Channel;
-import java.nio.channels.SelectableChannel;
 
 /*
  * The interface for network methods.
  */
 public interface INetworkSystem {
 
-    // -----------------------------------------------
-    // Class Const
-    // -----------------------------------------------
-
     /*
      * Socket connect Step start
      */
@@ -50,34 +45,24 @@
      */
     public final int SOCKET_CONNECT_STEP_CHECK = 1;
 
-    // -----------------------------------------------
-    // Methods
-    // -----------------------------------------------
-
     /*
      * socket accept
      */
     public void accept(FileDescriptor fdServer, SocketImpl newSocket,
             FileDescriptor fdnewSocket, int timeout) throws IOException;
 
-    public void bind(FileDescriptor aFD, int port, InetAddress inetAddress)
+    public void bind(FileDescriptor aFD, InetAddress inetAddress, int port)
             throws SocketException;
 
-    public boolean bind2(FileDescriptor aFD, int port, boolean bindToDevice,
-            InetAddress inetAddress) throws SocketException;
-
-    public void createSocket(FileDescriptor fd, boolean preferIPv4Stack)
-            throws IOException;
-
     public int read(FileDescriptor aFD, byte[] data, int offset, int count,
             int timeout) throws IOException;
-    
+
     public int readDirect(FileDescriptor aFD, int address, int offset, int count,
             int timeout) throws IOException;
 
     public int write(FileDescriptor fd, byte[] data, int offset, int count)
             throws IOException;
-    
+
     public int writeDirect(FileDescriptor fd, int address, int offset, int count)
             throws IOException;
 
@@ -96,7 +81,7 @@
     public int sendDatagram(FileDescriptor fd, byte[] data, int offset,
             int length, int port, boolean bindToDevice, int trafficClass,
             InetAddress inetAddress) throws IOException;
-    
+
     public int sendDatagramDirect(FileDescriptor fd, int address, int offset,
             int length, int port, boolean bindToDevice, int trafficClass,
             InetAddress inetAddress) throws IOException;
@@ -104,7 +89,7 @@
     public int receiveDatagram(FileDescriptor aFD, DatagramPacket packet,
             byte[] data, int offset, int length, int receiveTimeout,
             boolean peek) throws IOException;
-    
+
     public int receiveDatagramDirect(FileDescriptor aFD, DatagramPacket packet,
             int address, int offset, int length, int receiveTimeout,
             boolean peek) throws IOException;
@@ -112,17 +97,17 @@
     public int recvConnectedDatagram(FileDescriptor aFD, DatagramPacket packet,
             byte[] data, int offset, int length, int receiveTimeout,
             boolean peek) throws IOException;
-    
+
     public int recvConnectedDatagramDirect(FileDescriptor aFD,
             DatagramPacket packet, int address, int offset, int length,
             int receiveTimeout, boolean peek) throws IOException;
-    
+
     public int peekDatagram(FileDescriptor aFD, InetAddress sender,
             int receiveTimeout) throws IOException;
 
     public int sendConnectedDatagram(FileDescriptor fd, byte[] data,
             int offset, int length, boolean bindToDevice) throws IOException;
-    
+
     public int sendConnectedDatagramDirect(FileDescriptor fd, int address,
             int offset, int length, boolean bindToDevice) throws IOException;
 
@@ -134,17 +119,17 @@
     public void connectDatagram(FileDescriptor aFD, int port, int trafficClass,
             InetAddress inetAddress) throws SocketException;
 
-    public void createMulticastSocket(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException;
-
-    public void createServerStreamSocket(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException;
-
+    /**
+     * @deprecated Use {@link #read(FileDescriptor, byte[], int, int, int)}
+     */
+    @Deprecated
     public int receiveStream(FileDescriptor aFD, byte[] data, int offset,
             int count, int timeout) throws IOException;
 
+    // BEGIN android-added
     public int sendStream(FileDescriptor fd, byte[] data, int offset, int count)
             throws IOException;
+    // END android-added
 
     public void shutdownInput(FileDescriptor descriptor) throws IOException;
 
@@ -160,11 +145,14 @@
     // public void acceptStreamSocket(FileDescriptor fdServer,
     //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
     //         throws IOException;
-    // 
-    // public void createStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack)
-    //         throws SocketException;
     // END android-removed
 
+    public void createServerStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack)
+            throws SocketException;
+
+    public void createStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack)
+            throws SocketException;
+
     public void listenStreamSocket(FileDescriptor aFD, int backlog)
             throws SocketException;
 
@@ -184,7 +172,7 @@
 
     /*
      * Query the IP stack for the local port to which this socket is bound.
-     * 
+     *
      * @param aFD the socket descriptor @param preferIPv6Addresses address
      * preference for nodes that support both IPv4 and IPv6 @return int the
      * local port to which the socket is bound
@@ -194,10 +182,10 @@
 
     /*
      * Query the IP stack for the nominated socket option.
-     * 
+     *
      * @param aFD the socket descriptor @param opt the socket option type
      * @return the nominated socket option value
-     * 
+     *
      * @throws SocketException if the option is invalid
      */
     public Object getSocketOption(FileDescriptor aFD, int opt)
@@ -205,10 +193,10 @@
 
     /*
      * Set the nominated socket option in the IP stack.
-     * 
+     *
      * @param aFD the socket descriptor @param opt the option selector @param
      * optVal the nominated option value
-     * 
+     *
      * @throws SocketException if the option is invalid or cannot be set
      */
     public void setSocketOption(FileDescriptor aFD, int opt, Object optVal)
@@ -218,7 +206,7 @@
 
     /*
      * Close the socket in the IP stack.
-     * 
+     *
      * @param aFD the socket descriptor
      */
     public void socketClose(FileDescriptor aFD) throws IOException;
@@ -233,8 +221,8 @@
     // BEGIN android-removed
     // public boolean isReachableByICMP(InetAddress dest,InetAddress source,int ttl,int timeout);
     // END android-removed
-    
+
     public Channel inheritedChannel();
-    
+
     public void oneTimeInitialization(boolean jcl_supports_ipv6);
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/ISystemComponent.java b/luni/src/main/java/org/apache/harmony/luni/platform/ISystemComponent.java
deleted file mode 100644
index 29cf555..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/platform/ISystemComponent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.luni.platform;
-
-
-/**
- * ISystemComponent
- * 
- */
-public interface ISystemComponent extends IAdaptable {
-    /*empty*/
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSComponent.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSComponent.java
deleted file mode 100644
index b5f14f2..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/platform/OSComponent.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.luni.platform;
-
-
-//BEGIN android-changed
-import dalvik.system.VMStack;
-// END android-changed
-
-/**
- * OSComponent
- * 
- */
-class OSComponent implements IAdaptable {
-
-    /**
-     * 
-     */
-    public OSComponent() {
-        super();
-        // BEGIN android-changed
-        if (VMStack.getCallingClassLoader() != null) {
-            throw new SecurityException();
-        }
-        // END android-changed
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.harmony.luni.platform.IAdaptable#getAdapter(java.lang.Class)
-     */
-    public Object getAdapter(Class adapter) {
-        return Platform.getAdapterManager().getAdapter(this, adapter);
-    }
-
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSComponentFactory.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSComponentFactory.java
deleted file mode 100644
index a883ee0..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/platform/OSComponentFactory.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.luni.platform;
-
-
-/**
- * OSComponentFactory
- * 
- */
-class OSComponentFactory {
-
-    /**
-     * @return OSFileSystem
-     */
-    public static IFileSystem getFileSystem() {
-        //  Auto-generated method stub
-        return new OSFileSystem();
-    }
-
-    /**
-     * @return OSMemory
-     */
-    public static IMemorySystem getMemorySystem() {
-        // Auto-generated method stub
-        return new OSMemory();
-    }
-
-    /**
-     * @return OSNetwork
-     */
-    public static INetworkSystem getNetworkSystem() {
-        return OSNetworkSystem.getOSNetworkSystem();
-    }
-
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
index 2759d6b..20cf7cb 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
@@ -27,14 +27,17 @@
 
 /**
  * This is the portable implementation of the file system interface.
- * 
+ *
  */
-class OSFileSystem extends OSComponent implements IFileSystem {
+class OSFileSystem implements IFileSystem {
 
-    /**
-     * 
-     */
-    public OSFileSystem() {
+    private static final OSFileSystem singleton = new OSFileSystem();
+
+    public static OSFileSystem getOSFileSystem() {
+        return singleton;
+    }
+
+    private OSFileSystem() {
         super();
     }
 
@@ -153,6 +156,14 @@
         }
         long bytesRead = readImpl(fileDescriptor, bytes, offset, length);
         if (bytesRead < -1) {
+            /*
+             * TODO: bytesRead is never less than -1 so this code
+             * does nothing?
+             * The native code throws an exception in only one case
+             * so perhaps this should be 'bytesRead < 0' to handle
+             * any other cases.  But the other cases have been
+             * ignored until now so fixing this could break things
+             */
             throw new IOException();
         }
         return bytesRead;
@@ -203,7 +214,7 @@
 
     /*
      * (non-Javadoc)
-     * 
+     *
      * @see org.apache.harmony.luni.platform.IFileSystem#close(long)
      */
     public void close(int fileDescriptor) throws IOException {
@@ -238,7 +249,8 @@
     public long transfer(int fileHandler, FileDescriptor socketDescriptor,
             long offset, long count) throws IOException {
         long result = transferImpl(fileHandler, socketDescriptor, offset, count);
-        if (result < 0) throw new IOException();
+        if (result < 0)
+                throw new IOException();
         return result;
     }
 
@@ -268,7 +280,7 @@
     }
 
     private native long ttyReadImpl(byte[] bytes, int offset, int length);
-    
+
     // BEGIN android-added
     public native int ioctlAvailable(int fileDescriptor) throws IOException;
     // END android-added
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
index e3e7c46..0061d2a 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
@@ -43,7 +43,7 @@
  * above.
  * </p>
  */
-final class OSMemory extends OSComponent implements IMemorySystem {
+final class OSMemory implements IMemorySystem {
 
     /**
      * Defines the size, in bytes, of a native pointer type for the underlying
@@ -74,142 +74,150 @@
     }
 
     /**
-     * This class is not designed to be publically instantiated.
-     * 
+     * This class is not designed to be publicly instantiated.
+     *
      * @see #getOSMemory()
      */
-    OSMemory() {
+    private OSMemory() {
         super();
     }
 
-    // BEGIN android-note
-    // changed to private
-    // END android-note
     /**
      * Returns whether the byte order of this machine is little endian or not..
-     * 
-     * @return <code>false</code> for Big Endian, and
-     *         <code>true</code. for Little Endian.
+     *
+	 * @return <code>false</code> for Big Endian, and
+	 *         <code>true</code. for Little Endian.
      */
+    // BEGIN android-changed
+    /*public*/
     private static native boolean isLittleEndianImpl();
+    // END android-changed
 
     public boolean isLittleEndian() {
         return isLittleEndianImpl();
     }
 
-    /**
-     * Returns the natural byte order for this machine.
-     * 
-     * @return the native byte order for the current platform.
-     */
-    public Endianness getNativeOrder() {
-        return NATIVE_ORDER;
-    }
+	/**
+	 * Returns the natural byte order for this machine.
+	 *
+	 * @return the native byte order for the current platform.
+	 */
+	public Endianness getNativeOrder() {
+		return NATIVE_ORDER;
+	}
 
-    /**
-     * Returns the size of a native pointer type for the underlying platform.
-     * 
-     * @return the size of a pointer, in bytes.
-     */
-    private static native int getPointerSizeImpl();
+	/**
+	 * Returns the size of a native pointer type for the underlying platform.
+	 *
+	 * @return the size of a pointer, in bytes.
+	 */
+	private static native int getPointerSizeImpl();
 
-    public int getPointerSize() {
-        return POINTER_SIZE;
-    }
+	public int getPointerSize() {
+		return POINTER_SIZE;
+	}
 
     /**
      * Allocates and returns a pointer to space for a memory block of
      * <code>length</code> bytes. The space is uninitialized and may be larger
      * than the number of bytes requested; however, the guaranteed usable memory
      * block is exactly <code>length</code> bytes int.
-     * 
-     * @param length
-     *            number of bytes requested.
+     *
+	 * @param length
+	 *            number of bytes requested.
      * @return the address of the start of the memory block.
-     * @throws OutOfMemoryError
-     *             if the request cannot be satisfied.
+	 * @throws OutOfMemoryError
+	 *             if the request cannot be satisfied.
      */
+    // BEGIN android-changed
+    // public long malloc(long length) throws OutOfMemoryError
+    // {
+    //     OSResourcesMonitor.ensurePhysicalMemoryCapacity();
+    //     return mallocNative(length);
+    // }
+    // private native long mallocNative(long length) throws OutOfMemoryError;
     public native int malloc(int length) throws OutOfMemoryError;
+    // END android-changed
 
     /**
      * Deallocates space for a memory block that was previously allocated by a
      * call to {@link #malloc(int) malloc(int)}. The number of bytes freed is
      * identical to the number of bytes acquired when the memory block was
-     * allocated. If <code>address</code> is zero the method does nothing.
-     * <p>
+	 * allocated. If <code>address</code> is zero the method does nothing.
+	 * <p>
      * Freeing a pointer to a memory block that was not allocated by
-     * <code>malloc()</code> has unspecified effect.
-     * </p>
-     * 
-     * @param address
-     *            the address of the memory block to deallocate.
+	 * <code>malloc()</code> has unspecified effect.
+	 * </p>
+     *
+	 * @param address
+	 *            the address of the memory block to deallocate.
      */
     public native void free(int address);
 
     /**
      * Places <code>value</code> into first <code>length</code> bytes of the
-     * memory block starting at <code>address</code>.
-     * <p>
-     * The behavior is unspecified if
-     * <code>(address ... address + length)</code> is not wholly within the
-     * range that was previously allocated using <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the address of the first memory location.
-     * @param value
-     *            the byte value to set at each location.
-     * @param length
-     *            the number of byte-length locations to set.
+	 * memory block starting at <code>address</code>.
+	 * <p>
+	 * The behavior is unspecified if
+	 * <code>(address ... address + length)</code> is not wholly within the
+	 * range that was previously allocated using <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the address of the first memory location.
+	 * @param value
+	 *            the byte value to set at each location.
+	 * @param length
+	 *            the number of byte-length locations to set.
      */
     public native void memset(int address, byte value, long length);
 
     /**
      * Copies <code>length</code> bytes from <code>srcAddress</code> to
-     * <code>destAddress</code>. Where any part of the source memory block
-     * and the destination memory block overlap <code>memmove()</code> ensures
-     * that the original source bytes in the overlapping region are copied
-     * before being overwritten.
-     * <p>
-     * The behavior is unspecified if
-     * <code>(srcAddress ... srcAddress + length)</code> and
-     * <code>(destAddress ... destAddress + length)</code> are not both wholly
-     * within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param destAddress
-     *            the address of the destination memory block.
-     * @param srcAddress
-     *            the address of the source memory block.
-     * @param length
-     *            the number of bytes to move.
+	 * <code>destAddress</code>. Where any part of the source memory block
+	 * and the destination memory block overlap <code>memmove()</code> ensures
+	 * that the original source bytes in the overlapping region are copied
+	 * before being overwritten.
+	 * <p>
+	 * The behavior is unspecified if
+	 * <code>(srcAddress ... srcAddress + length)</code> and
+	 * <code>(destAddress ... destAddress + length)</code> are not both wholly
+	 * within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param destAddress
+	 *            the address of the destination memory block.
+	 * @param srcAddress
+	 *            the address of the source memory block.
+	 * @param length
+	 *            the number of bytes to move.
      */
     public native void memmove(int destAddress, int srcAddress, long length);
 
     /**
      * Copies <code>length</code> bytes from the memory block at
-     * <code>address</code> into the byte array <code>bytes</code> starting
-     * at element <code>offset</code> within the byte array.
-     * <p>
-     * The behavior of this method is undefined if the range
-     * <code>(address ... address + length)</code> is not within a memory
+	 * <code>address</code> into the byte array <code>bytes</code> starting
+	 * at element <code>offset</code> within the byte array.
+	 * <p>
+	 * The behavior of this method is undefined if the range
+	 * <code>(address ... address + length)</code> is not within a memory
      * block that was allocated using {@link #malloc(int) malloc(int)}.
-     * </p>
-     * 
-     * @param address
-     *            the address of the OS memory block from which to copy bytes.
-     * @param bytes
-     *            the byte array into which to copy the bytes.
-     * @param offset
-     *            the index of the first element in <code>bytes</code> that
-     *            will be overwritten.
-     * @param length
-     *            the total number of bytes to copy into the byte array.
-     * @throws NullPointerException
-     *             if <code>bytes</code> is <code>null</code>.
-     * @throws IndexOutOfBoundsException
-     *             if <code>offset + length > bytes.length</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the address of the OS memory block from which to copy bytes.
+	 * @param bytes
+	 *            the byte array into which to copy the bytes.
+	 * @param offset
+	 *            the index of the first element in <code>bytes</code> that
+	 *            will be overwritten.
+	 * @param length
+	 *            the total number of bytes to copy into the byte array.
+	 * @throws NullPointerException
+	 *             if <code>bytes</code> is <code>null</code>.
+	 * @throws IndexOutOfBoundsException
+	 *             if <code>offset + length > bytes.length</code>.
      */
     public native void getByteArray(int address, byte[] bytes, int offset,
             int length) throws NullPointerException, IndexOutOfBoundsException;
@@ -217,32 +225,32 @@
     /**
      * Copies <code>length</code> bytes from the byte array <code>bytes</code>
      * into the memory block at <code>address</code>, starting at element
-     * <code>offset</code> within the byte array.
-     * <p>
-     * The behavior of this method is undefined if the range
-     * <code>(address ... address + length)</code> is not within a memory
+	 * <code>offset</code> within the byte array.
+	 * <p>
+	 * The behavior of this method is undefined if the range
+	 * <code>(address ... address + length)</code> is not within a memory
      * block that was allocated using {@link #malloc(int) malloc(int)}.
-     * </p>
-     * 
-     * @param address
-     *            the address of the OS memory block into which to copy the
-     *            bytes.
-     * @param bytes
-     *            the byte array from which to copy the bytes.
-     * @param offset
-     *            the index of the first element in <code>bytes</code> that
-     *            will be read.
-     * @param length
-     *            the total number of bytes to copy from <code>bytes</code>
-     *            into the memory block.
-     * @throws NullPointerException
-     *             if <code>bytes</code> is <code>null</code>.
-     * @throws IndexOutOfBoundsException
-     *             if <code>offset + length > bytes.length</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the address of the OS memory block into which to copy the
+	 *            bytes.
+	 * @param bytes
+	 *            the byte array from which to copy the bytes.
+	 * @param offset
+	 *            the index of the first element in <code>bytes</code> that
+	 *            will be read.
+	 * @param length
+	 *            the total number of bytes to copy from <code>bytes</code>
+	 *            into the memory block.
+	 * @throws NullPointerException
+	 *             if <code>bytes</code> is <code>null</code>.
+	 * @throws IndexOutOfBoundsException
+	 *             if <code>offset + length > bytes.length</code>.
      */
     public native void setByteArray(int address, byte[] bytes, int offset,
             int length) throws NullPointerException, IndexOutOfBoundsException;
-    
+
     // BEGIN android-added
     /**
      * Copies <code>length</code> shorts from the short array <code>shorts</code>
@@ -253,7 +261,7 @@
      * <code>(address ... address + 2*length)</code> is not within a memory
      * block that was allocated using {@link #malloc(int) malloc(int)}.
      * </p>
-     * 
+     *
      * @param address
      *            the address of the OS memory block into which to copy the
      *            shorts.
@@ -285,7 +293,7 @@
      * <code>(address ... address + 2*length)</code> is not within a memory
      * block that was allocated using {@link #malloc(int) malloc(int)}.
      * </p>
-     * 
+     *
      * @param address
      *            the address of the OS memory block into which to copy the
      *            ints.
@@ -312,43 +320,43 @@
     // Primitive get & set methods
 
     /**
-     * Gets the value of the single byte at the given address.
-     * <p>
-     * The behavior is unspecified if <code>address</code> is not in the range
-     * that was previously allocated using <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the byte.
+	 * Gets the value of the single byte at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>address</code> is not in the range
+	 * that was previously allocated using <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the byte.
      * @return the byte value.
      */
     public native byte getByte(int address);
 
     /**
-     * Sets the given single byte value at the given address.
-     * <p>
-     * The behavior is unspecified if <code>address</code> is not in the range
-     * that was previously allocated using <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the address at which to set the byte value.
-     * @param value
-     *            the value to set.
+	 * Sets the given single byte value at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>address</code> is not in the range
+	 * that was previously allocated using <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the address at which to set the byte value.
+	 * @param value
+	 *            the value to set.
      */
     public native void setByte(int address, byte value);
 
     /**
      * Gets the value of the signed two-byte integer stored in platform byte
-     * order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 2)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the two-byte value.
+	 * order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 2)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the two-byte value.
      * @return the value of the two-byte integer as a Java <code>short</code>.
      */
     public native short getShort(int address);
@@ -360,17 +368,17 @@
 
     /**
      * Sets the value of the signed two-byte integer at the given address in
-     * platform byte order.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 2)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the two-byte value.
-     * @param value
-     *            the value of the two-byte integer as a Java <code>short</code>.
+	 * platform byte order.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 2)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the two-byte value.
+	 * @param value
+	 *            the value of the two-byte integer as a Java <code>short</code>.
      */
     public native void setShort(int address, short value);
 
@@ -384,15 +392,15 @@
 
     /**
      * Gets the value of the signed four-byte integer stored in platform
-     * byte-order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 4)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the four-byte value.
+	 * byte-order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 4)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the four-byte value.
      * @return the value of the four-byte integer as a Java <code>int</code>.
      */
     public native int getInt(int address);
@@ -404,17 +412,17 @@
 
     /**
      * Sets the value of the signed four-byte integer at the given address in
-     * platform byte order.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 4)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the four-byte value.
-     * @param value
-     *            the value of the four-byte integer as a Java <code>int</code>.
+	 * platform byte order.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 4)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the four-byte value.
+	 * @param value
+	 *            the value of the four-byte integer as a Java <code>int</code>.
      */
     public native void setInt(int address, int value);
 
@@ -428,15 +436,15 @@
 
     /**
      * Gets the value of the signed eight-byte integer stored in platform byte
-     * order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 8)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
+	 * order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 8)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
      * @return the value of the eight-byte integer as a Java <code>long</code>.
      */
     public native long getLong(int address);
@@ -448,17 +456,17 @@
 
     /**
      * Sets the value of the signed eight-byte integer at the given address in
-     * the platform byte order.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 8)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
-     * @param value
-     *            the value of the eight-byte integer as a Java
+	 * the platform byte order.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 8)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
+	 * @param value
+	 *            the value of the eight-byte integer as a Java
      *            <code>long</code>.
      */
     public native void setLong(int address, long value);
@@ -473,15 +481,15 @@
 
     /**
      * Gets the value of the IEEE754-format four-byte float stored in platform
-     * byte order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 4)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
+	 * byte order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 4)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
      * @return the value of the four-byte float as a Java <code>float</code>.
      */
     public native float getFloat(int address);
@@ -496,17 +504,17 @@
 
     /**
      * Sets the value of the IEEE754-format four-byte float stored in platform
-     * byte order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 4)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
-     * @param value
-     *            the value of the four-byte float as a Java <code>float</code>.
+	 * byte order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 4)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
+	 * @param value
+	 *            the value of the four-byte float as a Java <code>float</code>.
      */
     public native void setFloat(int address, float value);
 
@@ -521,15 +529,15 @@
 
     /**
      * Gets the value of the IEEE754-format eight-byte float stored in platform
-     * byte order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 8)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
+	 * byte order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 8)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
      * @return the value of the eight-byte float as a Java <code>double</code>.
      */
     public native double getDouble(int address);
@@ -544,17 +552,17 @@
 
     /**
      * Sets the value of the IEEE754-format eight-byte float store in platform
-     * byte order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 8)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
-     * @param value
-     *            the value of the eight-byte float as a Java
+	 * byte order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 8)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
+	 * @param value
+	 *            the value of the eight-byte float as a Java
      *            <code>double</code>.
      */
     public native void setDouble(int address, double value);
@@ -569,44 +577,44 @@
     }
 
     /**
-     * Gets the value of the platform pointer at the given address.
-     * <p>
-     * The length of the platform pointer is defined by
-     * <code>POINTER_SIZE</code>.
-     * </p>
-     * The behavior is unspecified if
-     * <code>(address ... address + POINTER_SIZE)</code> is not wholly within
-     * the range that was previously allocated using <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the platform pointer.
+	 * Gets the value of the platform pointer at the given address.
+	 * <p>
+	 * The length of the platform pointer is defined by
+	 * <code>POINTER_SIZE</code>.
+	 * </p>
+	 * The behavior is unspecified if
+	 * <code>(address ... address + POINTER_SIZE)</code> is not wholly within
+	 * the range that was previously allocated using <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the platform pointer.
      * @return the value of the platform pointer as a Java <code>int</code>.
      */
     public native int getAddress(int address);
 
     /**
-     * Sets the value of the platform pointer at the given address.
-     * <p>
-     * The length of the platform pointer is defined by
-     * <code>POINTER_SIZE</code>. This method only sets
-     * <code>POINTER_SIZE</code> bytes at the given address.
-     * </p>
-     * The behavior is unspecified if
-     * <code>(address ... address + POINTER_SIZE)</code> is not wholly within
-     * the range that was previously allocated using <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the platform pointer.
-     * @param value
+	 * Sets the value of the platform pointer at the given address.
+	 * <p>
+	 * The length of the platform pointer is defined by
+	 * <code>POINTER_SIZE</code>. This method only sets
+	 * <code>POINTER_SIZE</code> bytes at the given address.
+	 * </p>
+	 * The behavior is unspecified if
+	 * <code>(address ... address + POINTER_SIZE)</code> is not wholly within
+	 * the range that was previously allocated using <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the platform pointer.
+	 * @param value
      *            the value of the platform pointer as a Java <code>int</code>.
      */
     public native void setAddress(int address, int value);
 
     /*
-     * Memory mapped file
-     */
+         * Memory mapped file
+         */
     private native int mmapImpl(int fileDescriptor, long alignment,
             long size, int mapMode);
 
@@ -632,39 +640,48 @@
     private native int loadImpl(int l, long size);
 
     public boolean isLoaded(int addr, long size) {
-        return size == 0 ? true : isLoadedImpl(addr, size);
-    }
+		return size == 0 ? true : isLoadedImpl(addr, size);
+	}
 
     private native boolean isLoadedImpl(int l, long size);
 
     public void flush(int addr, long size) {
-        flushImpl(addr, size);
-    }
+		flushImpl(addr, size);
+	}
 
     private native int flushImpl(int l, long size);
 
-    /*
-     * Helper methods to change byte order.
-     */
-    private short swap(short value) {
-        int topEnd = value << 8;
-        int btmEnd = (value >> 8) & 0xFF;
-        return (short) (topEnd | btmEnd);
-    }
+	/*
+	 * Helper methods to change byte order.
+	 */
+	private short swap(short value) {
+        // BEGIN android-note
+        // is Integer.reverseBytes() >>> 16 be faster?
+        // END android-note
+		int topEnd = value << 8;
+		int btmEnd = (value >> 8) & 0xFF;
+		return (short) (topEnd | btmEnd);
+	}
 
-    private int swap(int value) {
-        short left = (short) (value >> 16);
-        short right = (short) value;
-        int topEnd = swap(right) << 16;
-        int btmEnd = swap(left) & 0xFFFF;
-        return topEnd | btmEnd;
-    }
+	private int swap(int value) {
+        // BEGIN android-note
+        // is Integer.reverseBytes() be faster?
+        // END android-note
+		short left = (short) (value >> 16);
+		short right = (short) value;
+		int topEnd = swap(right) << 16;
+		int btmEnd = swap(left) & 0xFFFF;
+		return topEnd | btmEnd;
+	}
 
-    private long swap(long value) {
-        int left = (int) (value >> 32);
-        int right = (int) value;
-        long topEnd = ((long) swap(right)) << 32;
-        long btmEnd = swap(left) & 0xFFFFFFFFL;
-        return topEnd | btmEnd;
-    }
+	private long swap(long value) {
+        // BEGIN android-note
+        // is Long.reverseBytes() be faster?
+        // END android-note
+		int left = (int) (value >> 32);
+		int right = (int) value;
+		long topEnd = ((long) swap(right)) << 32;
+		long btmEnd = swap(left) & 0xFFFFFFFFL;
+		return topEnd | btmEnd;
+	}
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
index c153428..0c9ac8a 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
@@ -16,7 +16,10 @@
  */
 
 // BEGIN android-note
-// address length was changed from long to int for performance reasons.
+// Address length was changed from long to int for performance reasons.
+// Harmony implements INetworkSystem's methods with native methods; Android
+// implements them with Java that call through to native wrappers.
+// TODO: change the native code to eliminate the wrappers
 // END android-note
 
 package org.apache.harmony.luni.platform;
@@ -32,123 +35,33 @@
 // BEGIN android-removed
 // import java.nio.channels.SelectableChannel;
 // END android-removed
-/*
- * 
- * This Class is used for native code wrap, the implement class of
- * INetworkSystem.
- * 
+
+/**
+ * This wraps native code that implements the INetworkSystem interface.
  */
 final class OSNetworkSystem implements INetworkSystem {
 
-    // ----------------------------------------------------
-    // Class Variables
-    // ----------------------------------------------------
-
     private static final int ERRORCODE_SOCKET_TIMEOUT = -209;
+    private static final int ERRORCODE_SOCKET_INTERRUPTED = -208;
 
-    private static OSNetworkSystem ref = new OSNetworkSystem();
-    
     private static final int INETADDR_REACHABLE = 0;
-    
+
     private static boolean isNetworkInited = false;
-    
 
-    // ----------------------------------------------------
-    // Class Constructor
-    // ----------------------------------------------------
+    private static OSNetworkSystem singleton = new OSNetworkSystem();
 
-    // can not be instantiated.
-    private OSNetworkSystem() {
-        super();
-    }
-
-    /*
-     * @return a static ref of this class
+    /**
+     * Answers the unique instance of the OSNetworkSystem.
+     *
+     * @return the network system interface instance
      */
     public static OSNetworkSystem getOSNetworkSystem() {
-        return ref;
+        return singleton;
     }
 
-    // Useing when cache set/get is OK
-    // public static native void oneTimeInitializationDatagram(
-    // boolean jcl_IPv6_support);
-    //
-    // public static native void oneTimeInitializationSocket(
-    // boolean jcl_IPv6_support);
-
-    // --------------------------------------------------
-    // java codes that wrap native codes
-    // --------------------------------------------------
-
-    public void createSocket(FileDescriptor fd, boolean preferIPv4Stack)
-            throws IOException {
-        createSocketImpl(fd, preferIPv4Stack);
-    }
-
-    public void createDatagramSocket(FileDescriptor fd, boolean preferIPv4Stack)
-            throws SocketException {
-        createDatagramSocketImpl(fd, preferIPv4Stack);
-    }
-
-    public int read(FileDescriptor aFD, byte[] data, int offset, int count,
-            int timeout) throws IOException {
-        return readSocketImpl(aFD, data, offset, count, timeout);
-    }
-    
-    public int readDirect(FileDescriptor aFD, int address, int offset, int count,
-            int timeout) throws IOException {
-        return readSocketDirectImpl(aFD, address, offset, count, timeout);
-    }
-
-    public int write(FileDescriptor aFD, byte[] data, int offset, int count)
-            throws IOException {
-        return writeSocketImpl(aFD, data, offset, count);
-    }
-    
-    public int writeDirect(FileDescriptor aFD, int address, int offset,
-            int count) throws IOException {
-        return writeSocketDirectImpl(aFD, address, offset, count);
-    }
-
-    public void setNonBlocking(FileDescriptor aFD, boolean block)
-            throws IOException {
-        setNonBlockingImpl(aFD, block);
-    }
-
-    public void connectDatagram(FileDescriptor aFD, int port, int trafficClass,
-            InetAddress inetAddress) throws SocketException {
-        connectDatagramImpl2(aFD, port, trafficClass, inetAddress);
-    }
-
-    public int connect(FileDescriptor aFD, int trafficClass,
-            InetAddress inetAddress, int port)  throws IOException{
-        return connectSocketImpl(aFD, trafficClass, inetAddress, port);
-    }
-
-    // BEGIN android-changed
-    public int connectWithTimeout(FileDescriptor aFD, int timeout,
-            int trafficClass, InetAddress inetAddress, int port, int step,
-            byte[] context)  throws IOException{
-        return connectWithTimeoutSocketImpl(aFD, timeout, trafficClass,
-                inetAddress, port, step, context);
-    }
-    // END android-changed
-
-    public void connectStreamWithTimeoutSocket(FileDescriptor aFD, int aport,
-            int timeout, int trafficClass, InetAddress inetAddress)
-            throws IOException {
-        connectStreamWithTimeoutSocketImpl(aFD, aport, timeout, trafficClass,
-                inetAddress);
-    }
-
-    public void bind(FileDescriptor aFD, int port, InetAddress inetAddress)
-            throws SocketException {
-        socketBindImpl(aFD, port, inetAddress);
-    }
-
-    public boolean bind2(FileDescriptor aFD, int port, boolean bindToDevice,
-            InetAddress inetAddress) throws SocketException {
-        return socketBindImpl2(aFD, port, bindToDevice, inetAddress);
+    // Can not be instantiated.
+    private OSNetworkSystem() {
+        super();
     }
 
     public void accept(FileDescriptor fdServer, SocketImpl newSocket,
@@ -156,110 +69,9 @@
         acceptSocketImpl(fdServer, newSocket, fdnewSocket, timeout);
     }
 
-    public int sendDatagram(FileDescriptor fd, byte[] data, int offset,
-            int length, int port, boolean bindToDevice, int trafficClass,
-            InetAddress inetAddress) throws IOException {
-        return sendDatagramImpl(fd, data, offset, length, port, bindToDevice,
-                trafficClass, inetAddress);
-    }
-    
-    public int sendDatagramDirect(FileDescriptor fd, int address, int offset,
-            int length, int port, boolean bindToDevice, int trafficClass,
-            InetAddress inetAddress) throws IOException {
-        return sendDatagramDirectImpl(fd, address, offset, length, port, bindToDevice,
-                trafficClass, inetAddress);
-    }
-
-    public int sendDatagram2(FileDescriptor fd, byte[] data, int offset,
-            int length, int port, InetAddress inetAddress) throws IOException {
-        return sendDatagramImpl2(fd, data, offset, length, port, inetAddress);
-    }
-
-    public int receiveDatagram(FileDescriptor aFD, DatagramPacket packet,
-            byte[] data, int offset, int length, int receiveTimeout,
-            boolean peek) throws IOException {
-        return receiveDatagramImpl(aFD, packet, data, offset, length,
-                receiveTimeout, peek);
-    }
-    
-    public int receiveDatagramDirect(FileDescriptor aFD, DatagramPacket packet,
-            int address, int offset, int length, int receiveTimeout,
-            boolean peek) throws IOException {
-        return receiveDatagramDirectImpl(aFD, packet, address, offset, length,
-                receiveTimeout, peek);
-    }
-
-    public int recvConnectedDatagram(FileDescriptor aFD, DatagramPacket packet,
-            byte[] data, int offset, int length, int receiveTimeout,
-            boolean peek) throws IOException {
-        return recvConnectedDatagramImpl(aFD, packet, data, offset, length,
-                receiveTimeout, peek);
-    }
-    
-    public int recvConnectedDatagramDirect(FileDescriptor aFD, DatagramPacket packet, int address,
-             int offset, int length, int receiveTimeout, boolean peek)
-            throws IOException {
-        return recvConnectedDatagramDirectImpl(aFD, packet, address, offset, length, receiveTimeout, peek);
-    }
-
-    public int peekDatagram(FileDescriptor aFD, InetAddress sender,
-            int receiveTimeout) throws IOException {
-        return peekDatagramImpl(aFD, sender, receiveTimeout);
-    }
-
-    public int sendConnectedDatagram(FileDescriptor fd, byte[] data,
-            int offset, int length, boolean bindToDevice) throws IOException {
-        return sendConnectedDatagramImpl(fd, data, offset, length, bindToDevice);
-    }
-    
-    public int sendConnectedDatagramDirect(FileDescriptor fd, int address,
-            int offset, int length, boolean bindToDevice) throws IOException {
-        return sendConnectedDatagramDirectImpl(fd, address, offset, length, bindToDevice);
-    }
-
-    public void disconnectDatagram(FileDescriptor aFD) throws SocketException {
-        disconnectDatagramImpl(aFD);
-    }
-
-    public void createMulticastSocket(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException {
-        createMulticastSocketImpl(aFD, preferIPv4Stack);
-    }
-
-    public void createServerStreamSocket(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException {
-        createServerStreamSocketImpl(aFD, preferIPv4Stack);
-    }
-
-    public int receiveStream(FileDescriptor aFD, byte[] data, int offset,
-            int count, int timeout) throws IOException {
-        return receiveStreamImpl(aFD, data, offset, count, timeout);
-    }
-
-    public int sendStream(FileDescriptor fd, byte[] data, int offset, int count)
-            throws IOException {
-        return sendStreamImpl(fd, data, offset, count);
-    }
-
-    public void shutdownInput(FileDescriptor descriptor) throws IOException {
-        shutdownInputImpl(descriptor);
-    }
-
-    public void shutdownOutput(FileDescriptor descriptor) throws IOException {
-        shutdownOutputImpl(descriptor);
-    }
-
-    public boolean supportsUrgentData(FileDescriptor fd) {
-        return supportsUrgentDataImpl(fd);
-    }
-
-    public void sendUrgentData(FileDescriptor fd, byte value) {
-        sendUrgentDataImpl(fd, value);
-    }
-
-    public int availableStream(FileDescriptor aFD) throws SocketException {
-        return availableStreamImpl(aFD);
-    }
+    static native void acceptSocketImpl(FileDescriptor fdServer,
+            SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
+            throws IOException;
 
     // BEGIN android-removed
     // public void acceptStreamSocket(FileDescriptor fdServer,
@@ -267,41 +79,479 @@
     //         throws IOException {
     //     acceptStreamSocketImpl(fdServer, newSocket, fdnewSocket, timeout);
     // }
-    // 
-    // public void createStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack)
-    //         throws SocketException {
-    //     createStreamSocketImpl(aFD, preferIPv4Stack);
+
+    // static native void acceptStreamSocketImpl(FileDescriptor fdServer,
+    //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
+    //         throws IOException;
+    // END android-removed
+
+    public int availableStream(FileDescriptor fd) throws SocketException {
+        return availableStreamImpl(fd);
+    }
+
+    static native int availableStreamImpl(FileDescriptor aFD) throws SocketException;
+
+    /**
+     * Associates a local address with a socket.
+     *
+     * @param fd
+     *            the socket descriptor
+     * @param port
+     *            the port number
+     * @param inetAddress
+     *            address to bind
+     * @throws SocketException
+     *             thrown if bind operation fails
+     */
+    public void bind(FileDescriptor fd, InetAddress inetAddress, int port) throws SocketException {
+        socketBindImpl(fd, port, inetAddress);
+    }
+
+    static native void socketBindImpl(FileDescriptor aFD, int port, InetAddress inetAddress) throws SocketException;
+
+    public int connect(FileDescriptor fd, int trafficClass,
+            InetAddress inetAddress, int port) throws IOException{
+        return connectSocketImpl(fd, trafficClass, inetAddress, port);
+    }
+
+    static native int connectSocketImpl(FileDescriptor aFD,
+            int trafficClass, InetAddress inetAddress, int port);
+
+    public void connectDatagram(FileDescriptor fd, int port,
+            int trafficClass, InetAddress inetAddress) throws SocketException {
+        connectDatagramImpl2(fd, port, trafficClass, inetAddress);
+    }
+
+    static native void connectDatagramImpl2(FileDescriptor aFD, int port,
+            int trafficClass, InetAddress inetAddress) throws SocketException;
+
+    public void connectStreamWithTimeoutSocket(FileDescriptor aFD,
+            int aport, int timeout, int trafficClass, InetAddress inetAddress)
+            throws IOException {
+        connectStreamWithTimeoutSocketImpl(aFD, aport, timeout, trafficClass,
+                inetAddress);
+    }
+
+    static native void connectStreamWithTimeoutSocketImpl(FileDescriptor aFD,
+            int aport, int timeout, int trafficClass, InetAddress inetAddress)
+            throws IOException;
+
+    // BEGIN android-changed
+    // changed context from Long to byte[]
+    public int connectWithTimeout(FileDescriptor fd, int timeout,
+            int trafficClass, InetAddress inetAddress, int port, int step,
+            byte[] context) throws IOException {
+        return connectWithTimeoutSocketImpl(fd, timeout, trafficClass,
+                inetAddress, port, step, context);
+    }
+
+    static native int connectWithTimeoutSocketImpl(FileDescriptor aFD,
+            int timeout, int trafficClass, InetAddress hostname, int port, int step,
+            byte[] context);
+    // END android-changed
+
+    public void createDatagramSocket(FileDescriptor fd,
+            boolean preferIPv4Stack) throws SocketException {
+        createDatagramSocketImpl(fd, preferIPv4Stack);
+    }
+
+    /*
+    * Allocate a datagram socket in the IP stack. The socket is associated with
+    * the <code>aFD</code>.
+    *
+    * @param aFD the FileDescriptor to associate with the socket @param
+    * preferIPv4Stack IP stack preference if underlying platform is V4/V6
+    * @exception SocketException upon an allocation error
+    */
+    static native void createDatagramSocketImpl(FileDescriptor aFD,
+            boolean preferIPv4Stack) throws SocketException;
+
+    public void createServerStreamSocket(FileDescriptor fd,
+            boolean preferIPv4Stack) throws SocketException {
+        createServerStreamSocketImpl(fd, preferIPv4Stack);
+    }
+
+    /*
+     * Answer the result of attempting to create a server stream socket in the
+     * IP stack. Any special options required for server sockets will be set by
+     * this method.
+     *
+     * @param aFD the socket FileDescriptor @param preferIPv4Stack if use IPV4
+     * @exception SocketException if an error occurs while creating the socket
+     */
+    static native void createServerStreamSocketImpl(FileDescriptor aFD,
+            boolean preferIPv4Stack) throws SocketException;
+
+    public void createStreamSocket(FileDescriptor fd,
+            boolean preferIPv4Stack) throws SocketException {
+        createStreamSocketImpl(fd, preferIPv4Stack);
+    }
+
+    static native void createStreamSocketImpl(FileDescriptor aFD,
+            boolean preferIPv4Stack) throws SocketException;
+
+    /**
+     * Disconnect the socket to a port and address
+     *a
+     * @param fd
+     *            the FileDescriptor associated with the socket
+     *
+     * @throws SocketException
+     *             if the disconnect fails
+     */
+    public void disconnectDatagram(FileDescriptor fd)
+            throws SocketException {
+        disconnectDatagramImpl(fd);
+    }
+
+    static native void disconnectDatagramImpl(FileDescriptor aFD)
+            throws SocketException;
+
+    public InetAddress getHostByAddr(byte[] addr)
+            throws UnknownHostException {
+        return getHostByAddrImpl(addr);
+    }
+    static native InetAddress getHostByAddrImpl(byte[] addr)
+            throws UnknownHostException;
+
+    public InetAddress getHostByName(String addr,
+            boolean preferIPv6Addresses) throws UnknownHostException {
+        return getHostByNameImpl(addr, preferIPv6Addresses);
+    }
+
+    static native InetAddress getHostByNameImpl(String addr,
+            boolean preferIPv6Addresses) throws UnknownHostException;
+
+    public int getSocketFlags() {
+        return getSocketFlagsImpl();
+    }
+
+    static native int getSocketFlagsImpl();
+
+    public InetAddress getSocketLocalAddress(FileDescriptor fd,
+            boolean preferIPv6Addresses) {
+        return getSocketLocalAddressImpl(fd, preferIPv6Addresses);
+    }
+    static native InetAddress getSocketLocalAddressImpl(FileDescriptor aFD,
+            boolean preferIPv6Addresses);
+
+    /**
+     * Query the IP stack for the local port to which this socket is bound.
+     *
+     * @param aFD
+     *            the socket descriptor
+     * @param preferIPv6Addresses
+     *            address preference for nodes that support both IPv4 and IPv6
+     * @return the local port to which the socket is bound
+     */
+    public int getSocketLocalPort(FileDescriptor aFD,
+            boolean preferIPv6Addresses) {
+        return getSocketLocalPortImpl(aFD, preferIPv6Addresses);
+    }
+
+    static native int getSocketLocalPortImpl(FileDescriptor aFD,
+            boolean preferIPv6Addresses);
+
+    /**
+     * Query the IP stack for the nominated socket option.
+     *
+     * @param fd
+     *            the socket descriptor
+     * @param opt
+     *            the socket option type
+     * @return the nominated socket option value
+     * @throws SocketException
+     *             if the option is invalid
+     */
+    public Object getSocketOption(FileDescriptor fd, int opt)
+            throws SocketException {
+        return getSocketOptionImpl(fd, opt);
+    }
+
+    static native Object getSocketOptionImpl(FileDescriptor aFD, int opt)
+            throws SocketException;
+
+    public Channel inheritedChannel() {
+        return inheritedChannelImpl();
+    }
+
+    native Channel inheritedChannelImpl();
+
+    // BEGIN android-removed
+    // public boolean isReachableByICMP(final InetAddress dest,
+    //         InetAddress source, final int ttl, final int timeout) {
+    //     return INETADDR_REACHABLE == isReachableByICMPImpl(dest, source, ttl,
+    //     timeout);
     // }
+
+    // native int isReachableByICMPImpl(InetAddress addr,
+    //         InetAddress local, int ttl, int timeout);
     // END android-removed
 
     public void listenStreamSocket(FileDescriptor aFD, int backlog)
             throws SocketException {
         listenStreamSocketImpl(aFD, backlog);
     }
-    
-    // BEGIN android-removed
-    // public boolean isReachableByICMP(final InetAddress dest,
-    //         InetAddress source, final int ttl, final int timeout) {
-    //     return INETADDR_REACHABLE == isReachableByICMPImpl(dest, source, ttl,
-    //             timeout);
-    // }
-    // END android-removed
 
-    /*
-     * 
-     * @param 
-     *      readChannels all channels interested in read and accept 
-     * @param
-     *      writeChannels all channels interested in write and connect 
-     * @param timeout
-     *      timeout in millis @return a set of channels that are ready for operation
-     * @throws 
-     *      SocketException @return int array, each int approve one of the     * channel if OK
+    static native void listenStreamSocketImpl(FileDescriptor aFD, int backlog)
+            throws SocketException;
+
+    public void oneTimeInitialization(boolean jcl_supports_ipv6) {
+        if (!isNetworkInited) {
+            oneTimeInitializationImpl(jcl_supports_ipv6);
+            isNetworkInited = true;
+        }
+    }
+
+    native void oneTimeInitializationImpl (boolean jcl_supports_ipv6);
+
+    /**
+     * Peek on the socket, update <code>sender</code> address and answer the
+     * sender port.
+     *
+     * @param fd
+     *            the socket FileDescriptor
+     * @param sender
+     *            an InetAddress, to be updated with the sender's address
+     * @param receiveTimeout
+     *            the maximum length of time the socket should block, reading
+     * @return the sender port
+     *
+     * @throws IOException
+     *             upon an read error or timeout
      */
+    public int peekDatagram(FileDescriptor fd, InetAddress sender,
+            int receiveTimeout) throws IOException {
+        return peekDatagramImpl(fd, sender, receiveTimeout);
+    }
 
-    public int[] select(FileDescriptor[] readFDs,
-            FileDescriptor[] writeFDs, long timeout)
-            throws SocketException {
+    static native int peekDatagramImpl(FileDescriptor aFD,
+            InetAddress sender, int receiveTimeout) throws IOException;
+
+    /**
+     * Read available bytes from the given file descriptor into a byte array.
+     *
+     * The read has an optional timeout parameter, which if non-zero is the
+     * length of time that the read will wait on a select call to see if any
+     * bytes are available for reading. If the timeout expires the method
+     * returns zero to indicate no bytes were read.
+     *
+     * @param fd
+     *            the socket file descriptor to read
+     * @param data
+     *            the byte array in which to store the results
+     * @param offset
+     *            the offset into the byte array in which to start reading the
+     *            results
+     * @param count
+     *            the maximum number of bytes to read
+     * @param timeout
+     *            the length of time to wait for the bytes, in milliseconds; or
+     *            zero to indicate no timeout applied. When there is no timeout
+     *            applied the read may block based upon socket options.
+     * @return number of bytes read, or zero if there were no bytes available
+     *         before the timeout occurred, or -1 to indicate the socket is
+     *         closed
+     * @throws IOException
+     *             if an underlying socket exception occurred
+     */
+    public int read(FileDescriptor fd, byte[] data, int offset, int count,
+            int timeout) throws IOException {
+        return readSocketImpl(fd, data, offset, count, timeout);
+    }
+
+    static native int readSocketImpl(FileDescriptor aFD, byte[] data,
+            int offset, int count, int timeout) throws IOException;
+
+    /**
+     * Read available bytes from the given file descriptor into OS memory at a
+     * given address.
+     *
+     * @param fd
+     *            the socket file descriptor to read
+     * @param address
+     *            the address of the memory in which to store the results
+     * @param count
+     *            the maximum number of bytes to read
+     * @param timeout
+     *            the length of time to wait for the bytes, in milliseconds
+     * @return number of bytes read, or zero if there were no bytes available
+     *         before the timeout occurred, or -1 to indicate the socket is
+     *         closed
+     * @throws IOException
+     *             if an underlying socket exception occurred
+     */
+    public int readDirect(FileDescriptor fd, int address, int offset, int count,
+            int timeout) throws IOException {
+        return readSocketDirectImpl(fd, address, offset, count, timeout);
+    }
+
+    static native int readSocketDirectImpl(FileDescriptor aFD, int address, int offset, int count,
+            int timeout) throws IOException;
+
+    /**
+     * Receive data on the socket into the specified buffer. The packet fields
+     * <code>data</code> & <code>length</code> are passed in addition to
+     * <code>packet</code> to eliminate the JNI field access calls.
+     *
+     * @param fd
+     *            the socket FileDescriptor
+     * @param packet
+     *            the DatagramPacket to receive into
+     * @param data
+     *            the data buffer of the packet
+     * @param offset
+     *            the offset in the data buffer
+     * @param length
+     *            the length of the data buffer in the packet
+     * @param receiveTimeout
+     *            the maximum length of time the socket should block, reading
+     * @param peek
+     *            indicates to peek at the data
+     * @return number of data received
+     * @throws IOException
+     *             upon an read error or timeout
+     */
+    public int receiveDatagram(FileDescriptor fd, DatagramPacket packet,
+            byte[] data, int offset, int length, int receiveTimeout,
+            boolean peek) throws IOException {
+        return receiveDatagramImpl(fd, packet, data, offset, length,
+                receiveTimeout, peek);
+    }
+
+    static native int receiveDatagramImpl(FileDescriptor aFD,
+            DatagramPacket packet, byte[] data, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException;
+
+    public int receiveDatagramDirect(FileDescriptor fd,
+            DatagramPacket packet, int address, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException {
+        return receiveDatagramDirectImpl(fd, packet, address, offset, length,
+                receiveTimeout, peek);
+    }
+
+    static native int receiveDatagramDirectImpl(FileDescriptor aFD,
+            DatagramPacket packet, int address, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException;
+
+    /**
+     * Receive at most <code>count</code> bytes into the buffer
+     * <code>data</code> at the <code>offset</code> on the socket.
+     *
+     * @param aFD
+     *            the socket FileDescriptor
+     * @param data
+     *            the receive buffer
+     * @param offset
+     *            the offset into the buffer
+     * @param count
+     *            the max number of bytes to receive
+     * @param timeout
+     *            the max time the read operation should block waiting for data
+     * @return the actual number of bytes read
+     * @throws IOException
+     * @throws SocketException
+     *             if an error occurs while reading
+     * @deprecated use {@link #read(FileDescriptor, byte[], int, int, int)}
+     */
+    public int receiveStream(FileDescriptor aFD, byte[] data,
+            int offset, int count, int timeout) throws IOException {
+        return receiveStreamImpl(aFD, data, offset, count, timeout);
+    }
+
+    static native int receiveStreamImpl(FileDescriptor aFD, byte[] data,
+            int offset, int count, int timeout) throws IOException;
+
+    // BEGIN android-added
+    /**
+     * Send <code>count</code> bytes from the buffer <code>data</code> at
+     * the <code>offset</code>, on the socket.
+     *
+     * @param fd
+     *
+     * @param data the send buffer @param offset the offset into the buffer
+     * @param count the number of bytes to receive @return int the actual number
+     * of bytes sent @throws IOException @exception SocketException if an error
+     * occurs while writing
+     */
+    public int sendStream(FileDescriptor fd, byte[] data, int offset, int count)
+            throws IOException {
+        return sendStreamImpl(fd, data, offset, count);
+    }
+
+    static native int sendStreamImpl(FileDescriptor fd, byte[] data,
+            int offset, int count) throws IOException;
+    // END android-added
+
+    /**
+     * Recieve data on the connected socket into the specified buffer. The
+     * packet fields <code>data</code> and <code>length</code> are passed in
+     * addition to <code>packet</code> to eliminate the JNI field access calls.
+     *
+     * @param fd
+     *            the socket FileDescriptor
+     * @param packet
+     *            the DatagramPacket to receive into
+     * @param data
+     *            the data buffer of the packet
+     * @param offset
+     *            the offset in the data buffer
+     * @param length
+     *            the length of the data buffer in the packet
+     * @param receiveTimeout
+     *            the maximum length of time the socket should block, reading
+     * @param peek
+     *            indicates to peek at the data
+     * @return number of data received
+     * @throws IOException
+     *             upon an read error or timeout
+     */
+    public int recvConnectedDatagram(FileDescriptor fd,
+            DatagramPacket packet, byte[] data, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException {
+        return recvConnectedDatagramImpl(fd, packet, data, offset, length,
+                receiveTimeout, peek);
+    }
+
+    static native int recvConnectedDatagramImpl(FileDescriptor aFD,
+            DatagramPacket packet, byte[] data, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException;
+
+    public int recvConnectedDatagramDirect(FileDescriptor aFD, DatagramPacket packet, int address,
+            int offset, int length, int receiveTimeout, boolean peek)
+            throws IOException {
+        return recvConnectedDatagramDirectImpl(aFD, packet, address, offset, length, receiveTimeout, peek);
+    }
+
+    static native int recvConnectedDatagramDirectImpl(FileDescriptor aFD,
+            DatagramPacket packet, int address, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException;
+
+    /**
+     * Select the given file descriptors for read and write operations.
+     *
+     * The file descriptors passed in as readFDs will be selected for read-ready
+     * operations, and those in the writeFDs will be selected for write-ready
+     * operations. A file descriptor can appear in either or both array, and
+     * must not be <code>null</code>. If the file descriptor is closed during
+     * the select the behavior depends upon the underlying OS.
+     *
+     * Upon return the result is a single array of length
+     * <code>readFDs.length</code> + <code>writeFDs.length</code> laid out as
+     * the result of the select operation on the corresponding file descriptors.
+     *
+     * @param readFDs
+     *            all sockets interested in read and accept
+     * @param writeFDs
+     *            all sockets interested in write and connect
+     * @param timeout
+     *            timeout in milliseconds
+     * @returns each element describes the corresponding state of the descriptor
+     *          in the read and write arrays.
+     * @throws SocketException
+     */
+    public int[] select(FileDescriptor[] readFDs, FileDescriptor[] writeFDs,
+            long timeout) throws SocketException {
         int countRead = readFDs.length;
         int countWrite = writeFDs.length;
         int result = 0;
@@ -310,6 +560,8 @@
         }
         int[] flags = new int[countRead + countWrite];
 
+        assert validateFDs(readFDs, writeFDs) : "Invalid file descriptor arrays"; //$NON-NLS-1$
+
         // handle timeout in native
         result = selectImpl(readFDs, writeFDs, countRead, countWrite, flags,
                 timeout);
@@ -317,430 +569,245 @@
         if (0 <= result) {
             return flags;
         }
-        if (ERRORCODE_SOCKET_TIMEOUT == result) {
+        if (ERRORCODE_SOCKET_TIMEOUT == result ||
+                ERRORCODE_SOCKET_INTERRUPTED == result) {
             return new int[0];
         }
         throw new SocketException();
-
     }
 
-    public InetAddress getSocketLocalAddress(FileDescriptor aFD,
-            boolean preferIPv6Addresses) {
-        return getSocketLocalAddressImpl(aFD, preferIPv6Addresses);
-    }
-
-    /*
-     * Query the IP stack for the local port to which this socket is bound.
-     * 
-     * @param aFD the socket descriptor @param preferIPv6Addresses address
-     * preference for nodes that support both IPv4 and IPv6 @return int the
-     * local port to which the socket is bound
-     */
-    public int getSocketLocalPort(FileDescriptor aFD,
-            boolean preferIPv6Addresses) {
-        return getSocketLocalPortImpl(aFD, preferIPv6Addresses);
-    }
-
-    /*
-     * Query the IP stack for the nominated socket option.
-     * 
-     * @param aFD the socket descriptor @param opt the socket option type
-     * @return the nominated socket option value
-     * 
-     * @throws SocketException if the option is invalid
-     */
-    public Object getSocketOption(FileDescriptor aFD, int opt)
-            throws SocketException {
-        return getSocketOptionImpl(aFD, opt);
-    }
-
-    /*
-     * Set the nominated socket option in the IP stack.
-     * 
-     * @param aFD the socket descriptor @param opt the option selector @param
-     * optVal the nominated option value
-     * 
-     * @throws SocketException if the option is invalid or cannot be set
-     */
-    public void setSocketOption(FileDescriptor aFD, int opt, Object optVal)
-            throws SocketException {
-        setSocketOptionImpl(aFD, opt, optVal);
-    }
-
-    public int getSocketFlags() {
-        return getSocketFlagsImpl();
-    }
-
-    /*
-     * Close the socket in the IP stack.
-     * 
-     * @param aFD the socket descriptor
-     */
-    public void socketClose(FileDescriptor aFD) throws IOException {
-        socketCloseImpl(aFD);
-    }
-
-    public InetAddress getHostByAddr(byte[] addr) throws UnknownHostException {
-        return getHostByAddrImpl(addr);
-    }
-
-    public InetAddress getHostByName(String addr, boolean preferIPv6Addresses)
-            throws UnknownHostException {
-        return getHostByNameImpl(addr, preferIPv6Addresses);
-    }
-
-    public void setInetAddress(InetAddress sender, byte[] address) {
-        setInetAddressImpl(sender, address);
-    }
-
-    // ---------------------------------------------------
-    // Native Codes
-    // ---------------------------------------------------
-
-    static native void createSocketImpl(FileDescriptor fd,
-            boolean preferIPv4Stack);
-
-    /*
-     * Allocate a datagram socket in the IP stack. The socket is associated with
-     * the <code>aFD</code>.
-     * 
-     * @param aFD the FileDescriptor to associate with the socket @param
-     * preferIPv4Stack IP stack preference if underlying platform is V4/V6
-     * @exception SocketException upon an allocation error
-     */
-    static native void createDatagramSocketImpl(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException;
-
-    static native int readSocketImpl(FileDescriptor aFD, byte[] data,
-            int offset, int count, int timeout) throws IOException;
-    
-    static native int readSocketDirectImpl(FileDescriptor aFD, int address,
-            int offset, int count, int timeout) throws IOException;
-
-    static native int writeSocketImpl(FileDescriptor fd, byte[] data,
-            int offset, int count) throws IOException;
-    
-    static native int writeSocketDirectImpl(FileDescriptor fd, int address,
-            int offset, int count) throws IOException;
-
-    static native void setNonBlockingImpl(FileDescriptor aFD,
-            boolean block);
-
-    static native int connectSocketImpl(FileDescriptor aFD,
-            int trafficClass, InetAddress inetAddress, int port);
-
-    // BEGIN android-changed
-    static native int connectWithTimeoutSocketImpl(
-            FileDescriptor aFD, int timeout, int trafficClass,
-            InetAddress hostname, int port, int step, byte[] context);
-    // END android-changed
-
-    static native void connectStreamWithTimeoutSocketImpl(FileDescriptor aFD,
-            int aport, int timeout, int trafficClass, InetAddress inetAddress)
-            throws IOException;
-
-    static native void socketBindImpl(FileDescriptor aFD, int port,
-            InetAddress inetAddress) throws SocketException;
-
-    static native void listenStreamSocketImpl(FileDescriptor aFD, int backlog)
-            throws SocketException;
-
-    static native int availableStreamImpl(FileDescriptor aFD)
-            throws SocketException;
-
-    static native void acceptSocketImpl(FileDescriptor fdServer,
-            SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
-            throws IOException;
-
-    static native boolean supportsUrgentDataImpl(FileDescriptor fd);
-
-    static native void sendUrgentDataImpl(FileDescriptor fd, byte value);
-
-    /*
-     * Connect the socket to a port and address
-     * 
-     * @param aFD the FileDescriptor to associate with the socket @param port
-     * the port to connect to @param trafficClass the traffic Class to be used
-     * then the connection is made @param inetAddress address to connect to.
-     * 
-     * @exception SocketException if the connect fails
-     */
-    static native void connectDatagramImpl2(FileDescriptor aFD,
-            int port, int trafficClass, InetAddress inetAddress)
-            throws SocketException;
-
-    /*
-     * Disconnect the socket to a port and address
-     * 
-     * @param aFD the FileDescriptor to associate with the socket
-     * 
-     * @exception SocketException if the disconnect fails
-     */
-    static native void disconnectDatagramImpl(FileDescriptor aFD)
-            throws SocketException;
-
-    /*
-     * Allocate a datagram socket in the IP stack. The socket is associated with
-     * the <code>aFD</code>.
-     * 
-     * @param aFD the FileDescriptor to associate with the socket @param
-     * preferIPv4Stack IP stack preference if underlying platform is V4/V6
-     * @exception SocketException upon an allocation error
-     */
-
-    /*
-     * Bind the socket to the port/localhost in the IP stack.
-     * 
-     * @param aFD the socket descriptor @param port the option selector @param
-     * bindToDevice bind the socket to the specified interface @param
-     * inetAddress address to connect to. @return if bind successful @exception
-     * SocketException thrown if bind operation fails
-     */
-    static native boolean socketBindImpl2(FileDescriptor aFD,
-            int port, boolean bindToDevice, InetAddress inetAddress)
-            throws SocketException;
-
-    /*
-     * Peek on the socket, update <code>sender</code> address and answer the
-     * sender port.
-     * 
-     * @param aFD the socket FileDescriptor @param sender an InetAddress, to be
-     * updated with the sender's address @param receiveTimeout the maximum
-     * length of time the socket should block, reading @return int the sender
-     * port
-     * 
-     * @exception IOException upon an read error or timeout
-     */
-    static native int peekDatagramImpl(FileDescriptor aFD,
-            InetAddress sender, int receiveTimeout) throws IOException;
-
-    /*
-     * Recieve data on the socket into the specified buffer. The packet fields
-     * <code>data</code> & <code>length</code> are passed in addition to
-     * <code>packet</code> to eliminate the JNI field access calls.
-     * 
-     * @param aFD the socket FileDescriptor @param packet the DatagramPacket to
-     * receive into @param data the data buffer of the packet @param offset the
-     * offset in the data buffer @param length the length of the data buffer in
-     * the packet @param receiveTimeout the maximum length of time the socket
-     * should block, reading @param peek indicates to peek at the data @return
-     * number of data received @exception IOException upon an read error or
-     * timeout
-     */
-    static native int receiveDatagramImpl(FileDescriptor aFD,
-            DatagramPacket packet, byte[] data, int offset, int length,
-            int receiveTimeout, boolean peek) throws IOException;
-    
-    static native int receiveDatagramDirectImpl(FileDescriptor aFD,
-            DatagramPacket packet, int address, int offset, int length,
-            int receiveTimeout, boolean peek) throws IOException;
-
-    /*
-     * Recieve data on the connected socket into the specified buffer. The
-     * packet fields <code>data</code> & <code>length</code> are passed in
-     * addition to <code>packet</code> to eliminate the JNI field access
-     * calls.
-     * 
-     * @param aFD the socket FileDescriptor @param packet the DatagramPacket to
-     * receive into @param data the data buffer of the packet @param offset the
-     * offset in the data buffer @param length the length of the data buffer in
-     * the packet @param receiveTimeout the maximum length of time the socket
-     * should block, reading @param peek indicates to peek at the data @return
-     * number of data received @exception IOException upon an read error or
-     * timeout
-     */
-    static native int recvConnectedDatagramImpl(FileDescriptor aFD,
-            DatagramPacket packet, byte[] data, int offset, int length,
-            int receiveTimeout, boolean peek) throws IOException;
-    
-    static native int recvConnectedDatagramDirectImpl(FileDescriptor aFD,
-            DatagramPacket packet, int address, int offset, int length,
-            int receiveTimeout, boolean peek) throws IOException;
-
-    /*
-     * Send the <code>data</code> to the nominated target <code>address</code>
-     * and <code>port</code>. These values are derived from the
-     * DatagramPacket to reduce the field calls within JNI.
-     * 
-     * @param fd the socket FileDescriptor @param data the data buffer of the
-     * packet @param offset the offset in the data buffer @param length the
-     * length of the data buffer in the packet @param port the target host port
-     * @param bindToDevice if bind to device @param trafficClass the traffic
-     * class to be used when the datagram is sent @param inetAddress address to
-     * connect to. @return number of data send
-     * 
-     * @exception IOException upon an read error or timeout
-     */
-    static native int sendDatagramImpl(FileDescriptor fd,
-            byte[] data, int offset, int length, int port,
-            boolean bindToDevice, int trafficClass, InetAddress inetAddress)
-            throws IOException;
-    
-    static native int sendDatagramDirectImpl(FileDescriptor fd,
-            int address, int offset, int length, int port,
-            boolean bindToDevice, int trafficClass, InetAddress inetAddress)
-            throws IOException;
-
-    /*
-     * Send the <code>data</code> to the address and port to which the was
-     * connnected and <code>port</code>.
-     * 
-     * @param fd the socket FileDescriptor @param data the data buffer of the
-     * packet @param offset the offset in the data buffer @param length the
-     * length of the data buffer in the packet @param bindToDevice not used,
-     * current kept in case needed as was the case for sendDatagramImpl @return
-     * number of data send @exception IOException upon an read error or timeout
-     */
-    static native int sendConnectedDatagramImpl(FileDescriptor fd,
-            byte[] data, int offset, int length, boolean bindToDevice)
-            throws IOException;
-    
-    static native int sendConnectedDatagramDirectImpl(FileDescriptor fd,
-            int address, int offset, int length, boolean bindToDevice)
-            throws IOException;
-
-    /*
-     * Answer the result of attempting to create a server stream socket in the
-     * IP stack. Any special options required for server sockets will be set by
-     * this method.
-     * 
-     * @param aFD the socket FileDescriptor @param preferIPv4Stack if use IPV4
-     * @exception SocketException if an error occurs while creating the socket
-     */
-    static native void createServerStreamSocketImpl(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException;
-
-    /*
-     * Answer the result of attempting to create a multicast socket in the IP
-     * stack. Any special options required for server sockets will be set by
-     * this method.
-     * 
-     * @param aFD the socket FileDescriptor @param preferIPv4Stack if use IPV4
-     * @exception SocketException if an error occurs while creating the socket
-     */
-    static native void createMulticastSocketImpl(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException;
-
-    /*
-     * Recieve at most <code>count</code> bytes into the buffer <code>data</code>
-     * at the <code>offset</code> on the socket.
-     * 
-     * @param aFD the socket FileDescriptor @param data the receive buffer
-     * @param offset the offset into the buffer @param count the max number of
-     * bytes to receive @param timeout the max time the read operation should
-     * block waiting for data @return int the actual number of bytes read
-     * @throws IOException @exception SocketException if an error occurs while
-     * reading
-     */
-    static native int receiveStreamImpl(FileDescriptor aFD, byte[] data,
-            int offset, int count, int timeout) throws IOException;
-
-    /*
-     * Send <code>count</code> bytes from the buffer <code>data</code> at
-     * the <code>offset</code>, on the socket.
-     * 
-     * @param fd
-     * 
-     * @param data the send buffer @param offset the offset into the buffer
-     * @param count the number of bytes to receive @return int the actual number
-     * of bytes sent @throws IOException @exception SocketException if an error
-     * occurs while writing
-     */
-    static native int sendStreamImpl(FileDescriptor fd, byte[] data,
-            int offset, int count) throws IOException;
-
-    private native void shutdownInputImpl(FileDescriptor descriptor)
-            throws IOException;
-
-    private native void shutdownOutputImpl(FileDescriptor descriptor)
-            throws IOException;
-
-    // BEGIN android-removed
-    // static native void acceptStreamSocketImpl(FileDescriptor fdServer,
-    //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
-    //         throws IOException;
-    // 
-    // static native void createStreamSocketImpl(FileDescriptor aFD,
-    //         boolean preferIPv4Stack) throws SocketException;
-    // END android-removed
-
-    static native int sendDatagramImpl2(FileDescriptor fd, byte[] data,
-            int offset, int length, int port, InetAddress inetAddress)
-            throws IOException;
-
     static native int selectImpl(FileDescriptor[] readfd,
             FileDescriptor[] writefd, int cread, int cwirte, int[] flags,
             long timeout);
 
-    static native InetAddress getSocketLocalAddressImpl(FileDescriptor aFD,
-            boolean preferIPv6Addresses);
-
-    /*
-     * Query the IP stack for the local port to which this socket is bound.
-     * 
-     * @param aFD the socket descriptor @param preferIPv6Addresses address
-     * preference for nodes that support both IPv4 and IPv6 @return int the
-     * local port to which the socket is bound
+    /**
+     * Send the <code>data</code> to the address and port to which the was
+     * connected and <code>port</code>.
+     *
+     * @param fd
+     *            the socket FileDescriptor
+     * @param data
+     *            the data buffer of the packet
+     * @param offset
+     *            the offset in the data buffer
+     * @param length
+     *            the length of the data buffer in the packet
+     * @param bindToDevice
+     *            not used, current kept in case needed as was the case for
+     *            sendDatagramImpl
+     * @return number of data send
+     * @throws IOException
+     *             upon an read error or timeout
      */
-    static native int getSocketLocalPortImpl(FileDescriptor aFD,
-            boolean preferIPv6Addresses);
+    public int sendConnectedDatagram(FileDescriptor fd, byte[] data,
+            int offset, int length, boolean bindToDevice) throws IOException {
+        return sendConnectedDatagramImpl(fd, data, offset, length, bindToDevice);
+    }
 
-    /*
-     * Query the IP stack for the nominated socket option.
-     * 
-     * @param aFD the socket descriptor @param opt the socket option type
-     * @return the nominated socket option value
-     * 
-     * @throws SocketException if the option is invalid
+    static native int sendConnectedDatagramImpl(FileDescriptor fd,
+            byte[] data, int offset, int length, boolean bindToDevice)
+            throws IOException;
+
+    public int sendConnectedDatagramDirect(FileDescriptor fd,
+            int address, int offset, int length, boolean bindToDevice)
+            throws IOException {
+        return sendConnectedDatagramDirectImpl(fd, address, offset, length, bindToDevice);
+    }
+    static native int sendConnectedDatagramDirectImpl(FileDescriptor fd,
+            int address, int offset, int length, boolean bindToDevice)
+            throws IOException;
+
+    /**
+     * Send the <code>data</code> to the nominated target <code>address</code>
+     * and <code>port</code>. These values are derived from the DatagramPacket
+     * to reduce the field calls within JNI.
+     *
+     * @param fd
+     *            the socket FileDescriptor
+     * @param data
+     *            the data buffer of the packet
+     * @param offset
+     *            the offset in the data buffer
+     * @param length
+     *            the length of the data buffer in the packet
+     * @param port
+     *            the target host port
+     * @param bindToDevice
+     *            if bind to device
+     * @param trafficClass
+     *            the traffic class to be used when the datagram is sent
+     * @param inetAddress
+     *            address to connect to.
+     * @return number of data send
+     *
+     * @throws IOException
+     *             upon an read error or timeout
      */
-    static native Object getSocketOptionImpl(FileDescriptor aFD, int opt)
-            throws SocketException;
+    public int sendDatagram(FileDescriptor fd, byte[] data, int offset,
+            int length, int port, boolean bindToDevice, int trafficClass,
+            InetAddress inetAddress) throws IOException {
+        return sendDatagramImpl(fd, data, offset, length, port, bindToDevice,
+                trafficClass, inetAddress);
+    }
 
-    /*
-     * Set the nominated socket option in the IP stack.
-     * 
-     * @param aFD the socket descriptor @param opt the option selector @param
-     * optVal the nominated option value
-     * 
-     * @throws SocketException if the option is invalid or cannot be set
-     */
-    static native void setSocketOptionImpl(FileDescriptor aFD, int opt,
-            Object optVal) throws SocketException;
+    static native int sendDatagramImpl(FileDescriptor fd, byte[] data, int offset,
+            int length, int port, boolean bindToDevice, int trafficClass,
+            InetAddress inetAddress) throws IOException;
 
-    static native int getSocketFlagsImpl();
+    public int sendDatagram2(FileDescriptor fd, byte[] data, int offset,
+            int length, int port, InetAddress inetAddress) throws IOException {
+        return sendDatagramImpl2(fd, data, offset, length, port, inetAddress);
+    }
 
-    /*
-     * Close the socket in the IP stack.
-     * 
-     * @param aFD the socket descriptor
-     */
-    static native void socketCloseImpl(FileDescriptor aFD);
+    static native int sendDatagramImpl2(FileDescriptor fd, byte[] data,
+            int offset, int length, int port, InetAddress inetAddress) throws IOException;
 
-    static native InetAddress getHostByAddrImpl(byte[] addr)
-            throws UnknownHostException;
 
-    static native InetAddress getHostByNameImpl(String addr,
-            boolean preferIPv6Addresses) throws UnknownHostException;
+    public int sendDatagramDirect(FileDescriptor fd, int address,
+            int offset, int length, int port, boolean bindToDevice,
+            int trafficClass, InetAddress inetAddress) throws IOException {
+        return sendDatagramDirectImpl(fd, address, offset, length, port, bindToDevice,
+                trafficClass, inetAddress);
+    }
+
+    static native int sendDatagramDirectImpl(FileDescriptor fd, int address,
+            int offset, int length, int port, boolean bindToDevice,
+            int trafficClass, InetAddress inetAddress) throws IOException;
+
+    public void sendUrgentData(FileDescriptor fd, byte value) {
+        sendUrgentDataImpl(fd, value);
+    }
+
+    static native void sendUrgentDataImpl(FileDescriptor fd, byte value);
+
+    public void setInetAddress(InetAddress sender, byte[] address) {
+        setInetAddressImpl(sender, address);
+    }
 
     native void setInetAddressImpl(InetAddress sender, byte[] address);
 
-    // BEGIN android-removed
-    // native int isReachableByICMPImpl(InetAddress addr, InetAddress local,
-    //         int ttl, int timeout);
-    // END android-removed
-    
-    native Channel inheritedChannelImpl();
+    public void setNonBlocking(FileDescriptor fd, boolean block)
+            throws IOException {
+        setNonBlockingImpl(fd, block);
+    }
 
-    public Channel inheritedChannel() {
-        return inheritedChannelImpl();
+    static native void setNonBlockingImpl(FileDescriptor aFD, boolean block);
+
+    /**
+     * Set the nominated socket option in the IP stack.
+     *
+     * @param aFD
+     *            the socket descriptor @param opt the option selector @param
+     *            optVal the nominated option value
+     *
+     * @throws SocketException
+     *             if the option is invalid or cannot be set
+     */
+    public void setSocketOption(FileDescriptor aFD, int opt,
+            Object optVal) throws SocketException {
+        setSocketOptionImpl(aFD, opt, optVal);
     }
-    
-    public void oneTimeInitialization(boolean jcl_supports_ipv6){
-        if (!isNetworkInited){
-            oneTimeInitializationImpl(jcl_supports_ipv6);
-            isNetworkInited = true;
-        } 
+
+    static native void setSocketOptionImpl(FileDescriptor aFD, int opt,
+            Object optVal) throws SocketException;
+
+    public void shutdownInput(FileDescriptor descriptor) throws IOException {
+        shutdownInputImpl(descriptor);
     }
-    
-    native void oneTimeInitializationImpl (boolean jcl_supports_ipv6);
+
+    private native void shutdownInputImpl(FileDescriptor descriptor)
+            throws IOException;
+
+    public void shutdownOutput(FileDescriptor fd) throws IOException {
+        shutdownOutputImpl(fd);
+    }
+
+    private native void shutdownOutputImpl(FileDescriptor descriptor)
+            throws IOException;
+    /**
+     * Close the socket in the IP stack.
+     *
+     * @param fd
+     *            the socket descriptor
+     */
+    public void socketClose(FileDescriptor fd) throws IOException {
+        socketCloseImpl(fd);
+    }
+
+    static native void socketCloseImpl(FileDescriptor fD);
+
+    public boolean supportsUrgentData(FileDescriptor fd) {
+        return supportsUrgentDataImpl(fd);
+    }
+
+    static native boolean supportsUrgentDataImpl(FileDescriptor fd);
+
+    /*
+    * Used to check if the file descriptor arrays are valid before passing them
+    * into the select native call.
+    */
+    private boolean validateFDs(FileDescriptor[] readFDs,
+            FileDescriptor[] writeFDs) {
+        for (FileDescriptor fd : readFDs) {
+            // Also checks fd not null
+            if (!fd.valid()) {
+                return false;
+            }
+        }
+        for (FileDescriptor fd : writeFDs) {
+            if (!fd.valid()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Write bytes from a byte array to a socket.
+     *
+     * @param fd
+     *            the socket on which to write the bytes
+     * @param data
+     *            the array containing the bytes to be written
+     * @param offset
+     *            the offset in the byte array from which to take the bytes
+     * @param count
+     *            the maximum number of bytes to be written. Callers are trusted
+     *            not to send values of length+count that are larger than
+     *            data.length
+     * @return the actual number of bytes written, which will be between zero
+     *         and count
+     * @throws IOException
+     *             if there is an underlying socket problem
+     */
+    public int write(FileDescriptor fd, byte[] data, int offset, int count)
+            throws IOException {
+        return writeSocketImpl(fd, data, offset, count);
+    }
+
+    static native int writeSocketImpl(FileDescriptor fd, byte[] data, int offset,
+            int count) throws IOException;
+
+
+    /**
+     * Write bytes from the given address to a socket.
+     *
+     * @param fd
+     *            the socket on which to write the bytes
+     * @param address
+     *            the start address of the bytes to be written
+     * @param count
+     *            the maximum number of bytes to be written
+     * @return the actual number of bytes written, which will be between zero
+     *         and count
+     * @throws IOException
+     *             if there is an underlying socket problem
+     */
+    public int writeDirect(FileDescriptor fd, int address, int offset, int count)
+            throws IOException {
+        return writeSocketDirectImpl(fd, address, offset, count);
+    }
+
+    static native int writeSocketDirectImpl(FileDescriptor fd, int address, int offset, int count)
+            throws IOException;
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java b/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java
index 68d2515..ab71a00 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java
@@ -21,25 +21,33 @@
 // END android-changed
 
 /**
- * Platform
- *  
+ * The Platform class gives access to the low-level underlying capabilities of
+ * the operating system.
+ *
+ * The platform is structured into operations on the process heap memory,
+ * network subsystem, and file system through different OS components.
+ *
+ * OS components are 'dangerous' in that they pass through the calls and
+ * arguments to the OS with very little checking, and as such may cause fatal
+ * exceptions in the runtime. Access to the OS components is restricted to
+ * trusted code running on the system classpath.
+ *
+ * @see IFileSystem
+ * @see INetworkSystem
+ * @see IMemorySystem
  */
 public class Platform {
 
-    static final IAdapterManager ADAPTER_MANAGER = new AdapterManager();
+    static final IFileSystem FILE_SYSTEM = OSFileSystem.getOSFileSystem();
 
-    static final IFileSystem FILE_SYSTEM = OSComponentFactory.getFileSystem();
+    static final IMemorySystem MEMORY_SYSTEM = OSMemory.getOSMemory();
 
-    static final IMemorySystem MEMORY_SYSTEM = OSComponentFactory
-            .getMemorySystem();
+    static final INetworkSystem NETWORK_SYSTEM = OSNetworkSystem.getOSNetworkSystem();
 
-    static final INetworkSystem NETWORK_SYSTEM = OSComponentFactory
-            .getNetworkSystem();
-
-    public static IAdapterManager getAdapterManager() {
-        return ADAPTER_MANAGER;
-    }
-
+    /**
+     * Checks to ensure that whoever is asking for the OS component is running
+     * on the system classpath.
+     */
     private static final void accessCheck() {
         // BEGIN android-changed
         if (VMStack.getCallingClassLoader() != null) {
@@ -48,16 +56,31 @@
         // END android-changed
     }
 
+    /**
+     * Answers the instance that interacts directly with the OS file system.
+     *
+     * @return a low-level file system interface.
+     */
     public static IFileSystem getFileSystem() {
         accessCheck();
         return FILE_SYSTEM;
     }
 
+    /**
+     * Answers the instance that interacts directly with the OS memory system.
+     *
+     * @return a low-level memory system interface.
+     */
     public static IMemorySystem getMemorySystem() {
         accessCheck();
         return MEMORY_SYSTEM;
     }
 
+    /**
+     * Answers the instance that interacts directly with the OS network system.
+     *
+     * @return a low-level network system interface.
+     */
     public static INetworkSystem getNetworkSystem() {
         accessCheck();
         return NETWORK_SYSTEM;
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java b/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java
index e897506..3692819 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java
@@ -20,17 +20,18 @@
 
 final class RuntimeMemorySpy extends AbstractMemorySpy {
 
-    public RuntimeMemorySpy() {
-        super();
-    }
+	public RuntimeMemorySpy() {
+		super();
+	}
 
-    public void alloc(PlatformAddress address) {
+	public void alloc(PlatformAddress address) {
+		// Pay a tax on the allocation to see if there are any frees pending.
+		Reference ref = notifyQueue.poll(); // non-blocking check
+		while (ref != null) {
+			orphanedMemory(ref);
+			ref = notifyQueue.poll();
+		}
+
         super.alloc(address);
-        // Pay a tax on the allocation to see if there are any frees pending.
-        Reference ref = notifyQueue.poll(); // non-blocking check
-        while (ref != null) {
-            orphanedMemory(ref);
-            ref = notifyQueue.poll();
-        }
-    }
+	}
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/DeleteOnExit.java b/luni/src/main/java/org/apache/harmony/luni/util/DeleteOnExit.java
new file mode 100644
index 0000000..ac3275e
--- /dev/null
+++ b/luni/src/main/java/org/apache/harmony/luni/util/DeleteOnExit.java
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.luni.util;
+
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+
+// BEGIN android-changed
+/**
+ * Implements the actual DeleteOnExit mechanism. Is registered as a shutdown
+ * hook in the Runtime, once it is actually being used.
+ */
+public class DeleteOnExit extends Thread {
+
+    /**
+     * Our singleton instance.
+     */
+    private static DeleteOnExit instance;
+
+    /**
+     * Our list of files scheduled for deletion.
+     */
+    private ArrayList<String> files = new ArrayList<String>();
+
+    /**
+     * Returns our singleton instance, creating it if necessary.
+     */
+    public static synchronized DeleteOnExit getInstance() {
+        if (instance == null) {
+            instance = new DeleteOnExit();
+            Runtime.getRuntime().addShutdownHook(instance);
+        }
+
+        return instance;
+    }
+
+    /**
+     * Schedules a file for deletion.
+     *
+     * @param filename The file to delete.
+     */
+    public void addFile(String filename) {
+        synchronized(files) {
+            if (!files.contains(filename)) {
+                files.add(filename);
+            }
+        }
+    }
+
+    /**
+     * Does the actual work. Note we (a) first sort the files lexicographically
+     * and then (b) delete them in reverse order. This is to make sure files
+     * get deleted before their parent directories.
+     */
+    @Override
+    public void run() {
+        Collections.sort(files);
+        for (int i = files.size() - 1; i >= 0; i--) {
+            new File(files.get(i)).delete();
+        }
+    }
+}
+// END android-changed
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java b/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java
new file mode 100644
index 0000000..0ff073c
--- /dev/null
+++ b/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java
@@ -0,0 +1,57 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.luni.util;
+
+import java.io.ByteArrayInputStream;
+
+/**
+ * The extension of <code>ByteArrayInputStream</code> which exposes an
+ * underlying buffer.
+ */
+public class ExposedByteArrayInputStream extends ByteArrayInputStream {
+
+    /**
+     * @see java.io.ByteArrayInputStream(byte[])
+     */
+    public ExposedByteArrayInputStream(byte buf[]) {
+        super(buf);
+    }
+
+    /**
+     * @see java.io.ByteArrayInputStream(byte[], int, int)
+     */
+    public ExposedByteArrayInputStream(byte buf[], int offset, int length) {
+        super(buf, offset, length);
+    }
+
+    /**
+     * Reads the whole stream and returns the stream snapshot.
+     */
+    public synchronized byte[] expose() {
+        if (pos == 0 && count == buf.length) {
+            skip(count);
+            return buf;
+        }
+
+        final int available = available();
+        final byte[] buffer = new byte[available];
+        System.arraycopy(buf, pos, buffer, 0, available);
+        skip(available);
+        return buffer;
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties b/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
index bc1688f..c740ae9 100644
--- a/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
+++ b/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
@@ -61,8 +61,8 @@
 K0046=Local port declared out of range
 K0047=buffer is null
 K0048=Invalid action specified\: {0}
-K0049=MinPort is greater than MaxPort
-K004a=Invalid port number specified
+K0049=MinPort is greater than MaxPort\: {0}
+K004a=Invalid port number specified\: {0}
 K004b=Attempt to set factory more than once.
 K004c=Package is sealed
 K004d=Does not support writing to the input stream
@@ -288,6 +288,7 @@
 K034d=method has not been implemented yet
 K034e=Build rules empty
 K0351=format is null
+K0352=package is sealed
 KA000=Line too long
 KA001=Argument must not be null
 KA002=Unshared read of back reference
@@ -322,3 +323,5 @@
 KA025=Method has not been implemented
 KA026=JAR entry {0} not found in {1}
 KA027=Inputstream of the JarURLConnection has been closed
+KA028=Cannot set protocol version when stream in use
+KA029=Can't find resource for bundle {0}, key {1}
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java b/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java
index 820de0f..642d309 100644
--- a/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java
+++ b/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java
@@ -17,8 +17,6 @@
 
 package org.apache.harmony.luni.util;
 
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * Used to parse a string and return either a single or double precision
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java b/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java
index 93bd9da..8072165 100644
--- a/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java
+++ b/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java
@@ -304,13 +304,13 @@
     private int getOffset(String strIntegerPart, String strDecimalPart) {
         strIntegerPart = strIntegerPart.replaceFirst("^0+", ""); //$NON-NLS-1$ //$NON-NLS-2$
         
-        //If the Interger part is a nonzero number.
+        //If the Integer part is a nonzero number.
         if (strIntegerPart.length() != 0) {
             String leadingNumber = strIntegerPart.substring(0, 1);
             return (strIntegerPart.length() - 1) * 4 + countBitsLength(Long.parseLong(leadingNumber,HEX_RADIX)) - 1;
         }
         
-        //If the Interger part is a zero number.
+        //If the Integer part is a zero number.
         int i;
         for (i = 0; i < strDecimalPart.length() && strDecimalPart.charAt(i) == '0'; i++);   
         if (i == strDecimalPart.length()) {
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/HistoricalNamesUtil.java b/luni/src/main/java/org/apache/harmony/luni/util/HistoricalNamesUtil.java
new file mode 100644
index 0000000..f32f976
--- /dev/null
+++ b/luni/src/main/java/org/apache/harmony/luni/util/HistoricalNamesUtil.java
@@ -0,0 +1,170 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.harmony.luni.util;
+
+import java.util.HashMap;
+
+public class HistoricalNamesUtil {
+    private static HashMap<String, String> historicalNames = new HashMap<String, String>();
+
+    static {
+        historicalNames.put("Big5-HKSCS", "Big5_HKSCS");
+        historicalNames.put("EUC-JP", "EUC_JP");
+        historicalNames.put("EUC-KR", "EUC_KR");
+        historicalNames.put("GB2312", "EUC_CN");
+        historicalNames.put("IBM-Thai", "Cp838");
+        historicalNames.put("IBM00858", "Cp858");
+        historicalNames.put("IBM01140", "Cp1140");
+        historicalNames.put("IBM01141", "Cp1141");
+        historicalNames.put("IBM01142", "Cp1142");
+        historicalNames.put("IBM01143", "Cp1143");
+        historicalNames.put("IBM01144", "Cp1144");
+        historicalNames.put("IBM01145", "Cp1145");
+        historicalNames.put("IBM01146", "Cp1146");
+        historicalNames.put("IBM01147", "Cp1147");
+        historicalNames.put("IBM01148", "Cp1148");
+        historicalNames.put("IBM01149", "Cp1149");
+        historicalNames.put("IBM037", "Cp037");
+        historicalNames.put("IBM1026", "Cp1026");
+        historicalNames.put("IBM1047", "Cp1047");
+        historicalNames.put("IBM273", "Cp273");
+        historicalNames.put("IBM277", "Cp277");
+        historicalNames.put("IBM278", "Cp278");
+        historicalNames.put("IBM280", "Cp280");
+        historicalNames.put("IBM284", "Cp284");
+        historicalNames.put("IBM285", "Cp285");
+        historicalNames.put("IBM297", "Cp297");
+        historicalNames.put("IBM420", "Cp420");
+        historicalNames.put("IBM424", "Cp424");
+        historicalNames.put("IBM437", "Cp437");
+        historicalNames.put("IBM500", "Cp500");
+        historicalNames.put("IBM775", "Cp775");
+        historicalNames.put("IBM850", "Cp850");
+        historicalNames.put("IBM852", "Cp852");
+        historicalNames.put("IBM855", "Cp855");
+        historicalNames.put("IBM857", "Cp857");
+        historicalNames.put("IBM860", "Cp860");
+        historicalNames.put("IBM861", "Cp861");
+        historicalNames.put("IBM862", "Cp862");
+        historicalNames.put("IBM863", "Cp863");
+        historicalNames.put("IBM864", "Cp864");
+        historicalNames.put("IBM865", "Cp865");
+        historicalNames.put("IBM866", "Cp866");
+        historicalNames.put("IBM868", "Cp868");
+        historicalNames.put("IBM869", "Cp869");
+        historicalNames.put("IBM870", "Cp870");
+        historicalNames.put("IBM871", "Cp871");
+        historicalNames.put("IBM918", "Cp918");
+        historicalNames.put("ISO-2022-CN", "ISO2022CN");
+        historicalNames.put("ISO-2022-JP", "ISO2022JP");
+        historicalNames.put("ISO-2022-KR", "ISO2022KR");
+        historicalNames.put("ISO-8859-1", "ISO8859_1");
+        historicalNames.put("ISO-8859-13", "ISO8859_13");
+        historicalNames.put("ISO-8859-15", "ISO8859_15");
+        historicalNames.put("ISO-8859-2", "ISO8859_2");
+        historicalNames.put("ISO-8859-3", "ISO8859_3");
+        historicalNames.put("ISO-8859-4", "ISO8859_4");
+        historicalNames.put("ISO-8859-5", "ISO8859_5");
+        historicalNames.put("ISO-8859-6", "ISO8859_6");
+        historicalNames.put("ISO-8859-7", "ISO8859_7");
+        historicalNames.put("ISO-8859-8", "ISO8859_8");
+        historicalNames.put("ISO-8859-9", "ISO8859_9");
+        historicalNames.put("KOI8-R", "KOI8_R");
+        historicalNames.put("Shift_JIS", "SJIS");
+        historicalNames.put("TIS-620", "TIS620");
+        historicalNames.put("US-ASCII", "ASCII");
+        historicalNames.put("UTF-16BE", "UnicodeBigUnmarked");
+        historicalNames.put("UTF-16LE", "UnicodeLittleUnmarked");
+        historicalNames.put("UTF-8", "UTF8");
+        historicalNames.put("windows-1250", "Cp1250");
+        historicalNames.put("windows-1251", "Cp1251");
+        historicalNames.put("windows-1252", "Cp1252");
+        historicalNames.put("windows-1253", "Cp1253");
+        historicalNames.put("windows-1254", "Cp1254");
+        historicalNames.put("windows-1255", "Cp1255");
+        historicalNames.put("windows-1256", "Cp1256");
+        historicalNames.put("windows-1257", "Cp1257");
+        historicalNames.put("windows-1258", "Cp1258");
+        historicalNames.put("windows-31j", "MS932");
+        historicalNames.put("x-Big5-Solaris", "Big5_Solaris");
+        historicalNames.put("x-euc-jp-linux", "EUC_JP_LINUX");
+        historicalNames.put("x-EUC-TW", "EUC_TW");
+        historicalNames.put("x-eucJP-Open", "EUC_JP_Solaris");
+        historicalNames.put("x-IBM1006", "Cp1006");
+        historicalNames.put("x-IBM1025", "Cp1025");
+        historicalNames.put("x-IBM1046", "Cp1046");
+        historicalNames.put("x-IBM1097", "Cp1097");
+        historicalNames.put("x-IBM1098", "Cp1098");
+        historicalNames.put("x-IBM1112", "Cp1112");
+        historicalNames.put("x-IBM1122", "Cp1122");
+        historicalNames.put("x-IBM1123", "Cp1123");
+        historicalNames.put("x-IBM1124", "Cp1124");
+        historicalNames.put("x-IBM1381", "Cp1381");
+        historicalNames.put("x-IBM1383", "Cp1383");
+        historicalNames.put("x-IBM33722", "Cp33722");
+        historicalNames.put("x-IBM737", "Cp737");
+        historicalNames.put("x-IBM856", "Cp856");
+        historicalNames.put("x-IBM874", "Cp874");
+        historicalNames.put("x-IBM875", "Cp875");
+        historicalNames.put("x-IBM921", "Cp921");
+        historicalNames.put("x-IBM922", "Cp922");
+        historicalNames.put("x-IBM930", "Cp930");
+        historicalNames.put("x-IBM933", "Cp933");
+        historicalNames.put("x-IBM935", "Cp935");
+        historicalNames.put("x-IBM937", "Cp937");
+        historicalNames.put("x-IBM939", "Cp939");
+        historicalNames.put("x-IBM942", "Cp942");
+        historicalNames.put("x-IBM942C", "Cp942C");
+        historicalNames.put("x-IBM943", "Cp943");
+        historicalNames.put("x-IBM943C", "Cp943C");
+        historicalNames.put("x-IBM948", "Cp948");
+        historicalNames.put("x-IBM949", "Cp949");
+        historicalNames.put("x-IBM949C", "Cp949C");
+        historicalNames.put("x-IBM950", "Cp950");
+        historicalNames.put("x-IBM964", "Cp964");
+        historicalNames.put("x-IBM970", "Cp970");
+        historicalNames.put("x-ISCII91", "ISCII91");
+        historicalNames.put("x-ISO-2022-CN-CNS", "ISO2022CN");
+        historicalNames.put("x-ISO-2022-CN-GB", "ISO2022CN");
+        historicalNames.put("x-JISAutoDetect", "JISAutoDetect");
+        historicalNames.put("x-MacArabic", "MacArabic");
+        historicalNames.put("x-MacCentralEurope", "MacCentralEurope");
+        historicalNames.put("x-MacCroatian", "MacCroatian");
+        historicalNames.put("x-MacCyrillic", "MacCyrillic");
+        historicalNames.put("x-MacDingbat", "MacDingbat");
+        historicalNames.put("x-MacGreek", "MacGreek");
+        historicalNames.put("x-MacHebrew", "MacHebrew");
+        historicalNames.put("x-MacIceland", "MacIceland");
+        historicalNames.put("x-MacRoman", "MacRoman");
+        historicalNames.put("x-MacRomania", "MacRomania");
+        historicalNames.put("x-MacSymbol", "MacSymbol");
+        historicalNames.put("x-MacThai", "MacThai");
+        historicalNames.put("x-MacTurkish", "MacTurkish");
+        historicalNames.put("x-MacUkraine", "MacUkraine");
+        historicalNames.put("x-MS950-HKSCS", "MS950_HKSCS");
+        historicalNames.put("x-mswin-936", "MS936");
+        historicalNames.put("x-PCK", "PCK");
+        historicalNames.put("x-windows-874", "MS874");
+        historicalNames.put("x-windows-949", "MS949");
+        historicalNames.put("x-windows-950", "MS950");
+    }
+
+    public static String getHistoricalName(String name) {
+        return (!historicalNames.containsKey(name) ? name : historicalNames
+                .get(name));
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java b/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java
index 8c8257b..d8b261d 100644
--- a/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java
+++ b/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java
@@ -24,28 +24,28 @@
  */
 public class Inet6Util {
 
-    /**
-     * Creates an byte[] based on an ipAddressString. No error handling is
-     * performed here.
-     */
-    public static byte[] createByteArrayFromIPAddressString(
-            String ipAddressString) {
+	/**
+	 * Creates an byte[] based on an ipAddressString. No error handling is
+	 * performed here.
+	 */
+	public static byte[] createByteArrayFromIPAddressString(
+			String ipAddressString) {
 
-        if (isValidIPV4Address(ipAddressString)) {
+		if (isValidIPV4Address(ipAddressString)) {
             StringTokenizer tokenizer = new StringTokenizer(ipAddressString, ".");
-            String token = "";
-            int tempInt = 0;
-            byte[] byteAddress = new byte[4];
-            for (int i = 0; i < 4; i++) {
-                token = tokenizer.nextToken();
-                tempInt = Integer.parseInt(token);
-                byteAddress[i] = (byte) tempInt;
-            }
+			String token = "";
+			int tempInt = 0;
+			byte[] byteAddress = new byte[4];
+			for (int i = 0; i < 4; i++) {
+				token = tokenizer.nextToken();
+				tempInt = Integer.parseInt(token);
+				byteAddress[i] = (byte) tempInt;
+			}
 
-            return byteAddress;
-        }
-        
-        if (ipAddressString.charAt(0) == '[') {
+			return byteAddress;
+		}
+
+		if (ipAddressString.charAt(0) == '[') {
             ipAddressString = ipAddressString.substring(1, ipAddressString.length() - 1);
         }
 
@@ -63,105 +63,105 @@
          * or decimal list. In the case where we hit a :: we will save the index
          * of the hexStrings so we can add zeros in to fill out the string
          */
-        while (tokenizer.hasMoreTokens()) {
-            prevToken = token;
-            token = tokenizer.nextToken();
+		while (tokenizer.hasMoreTokens()) {
+			prevToken = token;
+			token = tokenizer.nextToken();
 
-            if (token.equals(":")) {
-                if (prevToken.equals(":")) {
-                    doubleColonIndex = hexStrings.size();
-                } else if (!prevToken.equals("")) {
-                    hexStrings.add(prevToken);
-                }
-            } else if (token.equals(".")) {
-                decStrings.add(prevToken);
-            }
-        }
+			if (token.equals(":")) {
+				if (prevToken.equals(":")) {
+					doubleColonIndex = hexStrings.size();
+				} else if (!prevToken.equals("")) {
+					hexStrings.add(prevToken);
+				}
+			} else if (token.equals(".")) {
+				decStrings.add(prevToken);
+			}
+		}
 
-        if (prevToken.equals(":")) {
-            if (token.equals(":")) {
-                doubleColonIndex = hexStrings.size();
-            } else {
-                hexStrings.add(token);
-            }
-        } else if (prevToken.equals(".")) {
-            decStrings.add(token);
-        }
+		if (prevToken.equals(":")) {
+			if (token.equals(":")) {
+				doubleColonIndex = hexStrings.size();
+			} else {
+				hexStrings.add(token);
+			}
+		} else if (prevToken.equals(".")) {
+			decStrings.add(token);
+		}
 
-        // figure out how many hexStrings we should have
-        // also check if it is a IPv4 address
-        int hexStringsLength = 8;
+		// figure out how many hexStrings we should have
+		// also check if it is a IPv4 address
+		int hexStringsLength = 8;
 
-        // If we have an IPv4 address tagged on at the end, subtract
-        // 4 bytes, or 2 hex words from the total
-        if (decStrings.size() > 0) {
-            hexStringsLength -= 2;
-        }
+		// If we have an IPv4 address tagged on at the end, subtract
+		// 4 bytes, or 2 hex words from the total
+		if (decStrings.size() > 0) {
+			hexStringsLength -= 2;
+		}
 
-        // if we hit a double Colon add the appropriate hex strings
-        if (doubleColonIndex != -1) {
-            int numberToInsert = hexStringsLength - hexStrings.size();
-            for (int i = 0; i < numberToInsert; i++) {
-                hexStrings.add(doubleColonIndex, "0");
-            }
-        }
+		// if we hit a double Colon add the appropriate hex strings
+		if (doubleColonIndex != -1) {
+			int numberToInsert = hexStringsLength - hexStrings.size();
+			for (int i = 0; i < numberToInsert; i++) {
+				hexStrings.add(doubleColonIndex, "0");
+			}
+		}
 
-        byte ipByteArray[] = new byte[16];
+		byte ipByteArray[] = new byte[16];
 
-        // Finally convert these strings to bytes...
-        for (int i = 0; i < hexStrings.size(); i++) {
-            convertToBytes(hexStrings.get(i), ipByteArray, i * 2);
-        }
+		// Finally convert these strings to bytes...
+		for (int i = 0; i < hexStrings.size(); i++) {
+			convertToBytes(hexStrings.get(i), ipByteArray, i * 2);
+		}
 
-        // Now if there are any decimal values, we know where they go...
-        for (int i = 0; i < decStrings.size(); i++) {
+		// Now if there are any decimal values, we know where they go...
+		for (int i = 0; i < decStrings.size(); i++) {
             ipByteArray[i + 12] = (byte) (Integer.parseInt(decStrings.get(i)) & 255);
         }
 
-        // now check to see if this guy is actually and IPv4 address
-        // an ipV4 address is ::FFFF:d.d.d.d
-        boolean ipV4 = true;
-        for (int i = 0; i < 10; i++) {
-            if (ipByteArray[i] != 0) {
-                ipV4 = false;
-                break;
-            }
-        }
+		// now check to see if this guy is actually and IPv4 address
+		// an ipV4 address is ::FFFF:d.d.d.d
+		boolean ipV4 = true;
+		for (int i = 0; i < 10; i++) {
+			if (ipByteArray[i] != 0) {
+				ipV4 = false;
+				break;
+			}
+		}
 
-        if (ipByteArray[10] != -1 || ipByteArray[11] != -1) {
-            ipV4 = false;
-        }
+		if (ipByteArray[10] != -1 || ipByteArray[11] != -1) {
+			ipV4 = false;
+		}
 
-        if (ipV4) {
-            byte ipv4ByteArray[] = new byte[4];
-            for (int i = 0; i < 4; i++) {
-                ipv4ByteArray[i] = ipByteArray[i + 12];
-            }
-            return ipv4ByteArray;
-        }
-        
-        return ipByteArray;
+		if (ipV4) {
+			byte ipv4ByteArray[] = new byte[4];
+			for (int i = 0; i < 4; i++) {
+				ipv4ByteArray[i] = ipByteArray[i + 12];
+			}
+			return ipv4ByteArray;
+		}
 
-    }
+		return ipByteArray;
+
+	}
 
     // BEGIN android-changed
     static char[] hexCharacters = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
             '9', 'a', 'b', 'c', 'd', 'e', 'f'};
     // END android-changed
 
-    public static String createIPAddrStringFromByteArray(byte ipByteArray[]) {
-        if (ipByteArray.length == 4) {
-            return addressToString(bytesToInt(ipByteArray, 0));
-        }
+	public static String createIPAddrStringFromByteArray(byte ipByteArray[]) {
+		if (ipByteArray.length == 4) {
+			return addressToString(bytesToInt(ipByteArray, 0));
+		}
 
-        if (ipByteArray.length == 16) {
-            if (isIPv4MappedAddress(ipByteArray)) {
-                byte ipv4ByteArray[] = new byte[4];
-                for (int i = 0; i < 4; i++) {
-                    ipv4ByteArray[i] = ipByteArray[i + 12];
-                }
-                return addressToString(bytesToInt(ipv4ByteArray, 0));
-            }
+		if (ipByteArray.length == 16) {
+			if (isIPv4MappedAddress(ipByteArray)) {
+				byte ipv4ByteArray[] = new byte[4];
+				for (int i = 0; i < 4; i++) {
+					ipv4ByteArray[i] = ipByteArray[i + 12];
+				}
+				return addressToString(bytesToInt(ipv4ByteArray, 0));
+			}
             StringBuilder buffer = new StringBuilder();
             // BEGIN android-changed
             for (int i = 0; i < 8; i++) { // ipByteArray.length / 2
@@ -189,131 +189,129 @@
             }
             // END android-changed
             return buffer.toString();
-        }
-        return null;
-    }
+		}
+		return null;
+	}
 
-    /** Converts a 4 character hex word into a 2 byte word equivalent */
-    public static void convertToBytes(String hexWord, byte ipByteArray[],
-            int byteIndex) {
+	/** Converts a 4 character hex word into a 2 byte word equivalent */
+	public static void convertToBytes(String hexWord, byte ipByteArray[],
+			int byteIndex) {
 
-        int hexWordLength = hexWord.length();
-        int hexWordIndex = 0;
-        ipByteArray[byteIndex] = 0;
-        ipByteArray[byteIndex + 1] = 0;
-        int charValue;
+		int hexWordLength = hexWord.length();
+		int hexWordIndex = 0;
+		ipByteArray[byteIndex] = 0;
+		ipByteArray[byteIndex + 1] = 0;
+		int charValue;
 
-        // high order 4 bits of first byte
-        if (hexWordLength > 3) {
-            charValue = getIntValue(hexWord.charAt(hexWordIndex++));
-            ipByteArray[byteIndex] = (byte) (ipByteArray[byteIndex] | (charValue << 4));
-        }
+		// high order 4 bits of first byte
+		if (hexWordLength > 3) {
+			charValue = getIntValue(hexWord.charAt(hexWordIndex++));
+			ipByteArray[byteIndex] = (byte) (ipByteArray[byteIndex] | (charValue << 4));
+		}
 
-        // low order 4 bits of the first byte
-        if (hexWordLength > 2) {
-            charValue = getIntValue(hexWord.charAt(hexWordIndex++));
-            ipByteArray[byteIndex] = (byte) (ipByteArray[byteIndex] | charValue);
-        }
+		// low order 4 bits of the first byte
+		if (hexWordLength > 2) {
+			charValue = getIntValue(hexWord.charAt(hexWordIndex++));
+			ipByteArray[byteIndex] = (byte) (ipByteArray[byteIndex] | charValue);
+		}
 
-        // high order 4 bits of second byte
-        if (hexWordLength > 1) {
-            charValue = getIntValue(hexWord.charAt(hexWordIndex++));
-            ipByteArray[byteIndex + 1] = (byte) (ipByteArray[byteIndex + 1] | (charValue << 4));
-        }
+		// high order 4 bits of second byte
+		if (hexWordLength > 1) {
+			charValue = getIntValue(hexWord.charAt(hexWordIndex++));
+			ipByteArray[byteIndex + 1] = (byte) (ipByteArray[byteIndex + 1] | (charValue << 4));
+		}
 
-        // low order 4 bits of the first byte
-        charValue = getIntValue(hexWord.charAt(hexWordIndex));
-        ipByteArray[byteIndex + 1] = (byte) (ipByteArray[byteIndex + 1] | charValue & 15);
-    }
+		// low order 4 bits of the first byte
+		charValue = getIntValue(hexWord.charAt(hexWordIndex));
+		ipByteArray[byteIndex + 1] = (byte) (ipByteArray[byteIndex + 1] | charValue & 15);
+	}
 
-    static int getIntValue(char c) {
+	static int getIntValue(char c) {
 
-        switch (c) {
-        case '0':
-            return 0;
-        case '1':
-            return 1;
-        case '2':
-            return 2;
-        case '3':
-            return 3;
-        case '4':
-            return 4;
-        case '5':
-            return 5;
-        case '6':
-            return 6;
-        case '7':
-            return 7;
-        case '8':
-            return 8;
-        case '9':
-            return 9;
-        }
+		switch (c) {
+		case '0':
+			return 0;
+		case '1':
+			return 1;
+		case '2':
+			return 2;
+		case '3':
+			return 3;
+		case '4':
+			return 4;
+		case '5':
+			return 5;
+		case '6':
+			return 6;
+		case '7':
+			return 7;
+		case '8':
+			return 8;
+		case '9':
+			return 9;
+		}
 
-        c = Character.toLowerCase(c);
-        switch (c) {
-        case 'a':
-            return 10;
-        case 'b':
-            return 11;
-        case 'c':
-            return 12;
-        case 'd':
-            return 13;
-        case 'e':
-            return 14;
-        case 'f':
-            return 15;
-        }
-        return 0;
-    }
+		c = Character.toLowerCase(c);
+		switch (c) {
+		case 'a':
+			return 10;
+		case 'b':
+			return 11;
+		case 'c':
+			return 12;
+		case 'd':
+			return 13;
+		case 'e':
+			return 14;
+		case 'f':
+			return 15;
+		}
+		return 0;
+	}
 
-    private static boolean isIPv4MappedAddress(byte ipAddress[]) {
+	private static boolean isIPv4MappedAddress(byte ipAddress[]) {
 
-        // Check if the address matches ::FFFF:d.d.d.d
-        // The first 10 bytes are 0. The next to are -1 (FF).
-        // The last 4 bytes are varied.
-        for (int i = 0; i < 10; i++) {
-            if (ipAddress[i] != 0) {
-                return false;
-            }
-        }
+		// Check if the address matches ::FFFF:d.d.d.d
+		// The first 10 bytes are 0. The next to are -1 (FF).
+		// The last 4 bytes are varied.
+		for (int i = 0; i < 10; i++) {
+			if (ipAddress[i] != 0) {
+				return false;
+			}
+		}
 
-        if (ipAddress[10] != -1 || ipAddress[11] != -1) {
-            return false;
-        }
+		if (ipAddress[10] != -1 || ipAddress[11] != -1) {
+			return false;
+		}
 
-        return true;
+		return true;
 
-    }
+	}
 
-    /**
-     * Takes the byte array and creates an integer out of four bytes starting at
-     * start as the high-order byte. This method makes no checks on the validity
-     * of the parameters.
-     */
-    public static int bytesToInt(byte bytes[], int start) {
-        // First mask the byte with 255, as when a negative
-        // signed byte converts to an integer, it has bits
-        // on in the first 3 bytes, we are only concerned
-        // about the right-most 8 bits.
-        // Then shift the rightmost byte to align with its
-        // position in the integer.
-        int value = ((bytes[start + 3] & 255))
-                | ((bytes[start + 2] & 255) << 8)
-                | ((bytes[start + 1] & 255) << 16)
-                | ((bytes[start] & 255) << 24);
-        return value;
-    }
+	/**
+	 * Takes the byte array and creates an integer out of four bytes starting at
+	 * start as the high-order byte. This method makes no checks on the validity
+	 * of the parameters.
+	 */
+	public static int bytesToInt(byte bytes[], int start) {
+		// First mask the byte with 255, as when a negative
+		// signed byte converts to an integer, it has bits
+		// on in the first 3 bytes, we are only concerned
+		// about the right-most 8 bits.
+		// Then shift the rightmost byte to align with its
+		// position in the integer.
+		int value = ((bytes[start + 3] & 255))
+				| ((bytes[start + 2] & 255) << 8)
+				| ((bytes[start + 1] & 255) << 16)
+				| ((bytes[start] & 255) << 24);
+		return value;
+	}
 
-    public static String addressToString(int value) {
-        return ((value >> 24) & 0xff) + "." + ((value >> 16) & 0xff) + "."
-                + ((value >> 8) & 0xff) + "." + (value & 0xff);
-    }
+	public static String addressToString(int value) {
+		return ((value >> 24) & 0xff) + "." + ((value >> 16) & 0xff) + "."
+				+ ((value >> 8) & 0xff) + "." + (value & 0xff);
+	}
 
-    // BEGIN android-added
-    // copied from a newer version of harmony
     public static boolean isIP6AddressInFullForm(String ipAddress) {
         if (isValidIP6Address(ipAddress)) {
             int doubleColonIndex = ipAddress.indexOf("::");
@@ -325,215 +323,214 @@
         }
         return false;
     }
-    // END android-added
 
-    public static boolean isValidIP6Address(String ipAddress) {
-        int length = ipAddress.length();
-        boolean doubleColon = false;
-        int numberOfColons = 0;
-        int numberOfPeriods = 0;
-        int numberOfPercent = 0;
-        String word = "";
-        char c = 0;
-        char prevChar = 0;
-        int offset = 0; // offset for [] IP addresses
+	public static boolean isValidIP6Address(String ipAddress) {
+		int length = ipAddress.length();
+		boolean doubleColon = false;
+		int numberOfColons = 0;
+		int numberOfPeriods = 0;
+		int numberOfPercent = 0;
+		String word = "";
+		char c = 0;
+		char prevChar = 0;
+		int offset = 0; // offset for [] IP addresses
 
-        if (length < 2) {
+		if (length < 2) {
             return false;
         }
 
-        for (int i = 0; i < length; i++) {
-            prevChar = c;
-            c = ipAddress.charAt(i);
-            switch (c) {
+		for (int i = 0; i < length; i++) {
+			prevChar = c;
+			c = ipAddress.charAt(i);
+			switch (c) {
 
-            // case for an open bracket [x:x:x:...x]
-            case '[':
-                if (i != 0) {
+			// case for an open bracket [x:x:x:...x]
+			case '[':
+				if (i != 0) {
                     return false; // must be first character
                 }
-                if (ipAddress.charAt(length - 1) != ']') {
+				if (ipAddress.charAt(length - 1) != ']') {
                     return false; // must have a close ]
                 }
-                offset = 1;
-                if (length < 4) {
+				offset = 1;
+				if (length < 4) {
                     return false;
                 }
-                break;
+				break;
 
-            // case for a closed bracket at end of IP [x:x:x:...x]
-            case ']':
-                if (i != length - 1) {
+			// case for a closed bracket at end of IP [x:x:x:...x]
+			case ']':
+				if (i != length - 1) {
                     return false; // must be last character
                 }
-                if (ipAddress.charAt(0) != '[') {
+				if (ipAddress.charAt(0) != '[') {
                     return false; // must have a open [
                 }
-                break;
+				break;
 
-            // case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d
-            case '.':
-                numberOfPeriods++;
-                if (numberOfPeriods > 3) {
+			// case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d
+			case '.':
+				numberOfPeriods++;
+				if (numberOfPeriods > 3) {
                     return false;
                 }
-                if (!isValidIP4Word(word)) {
+				if (!isValidIP4Word(word)) {
                     return false;
                 }
-                if (numberOfColons != 6 && !doubleColon) {
+				if (numberOfColons != 6 && !doubleColon) {
                     return false;
                 }
-                // a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an
-                // IPv4 ending, otherwise 7 :'s is bad
-                if (numberOfColons == 7 && ipAddress.charAt(0 + offset) != ':'
-                        && ipAddress.charAt(1 + offset) != ':') {
+				// a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an
+				// IPv4 ending, otherwise 7 :'s is bad
+				if (numberOfColons == 7 && ipAddress.charAt(0 + offset) != ':'
+						&& ipAddress.charAt(1 + offset) != ':') {
                     return false;
                 }
-                word = "";
-                break;
+				word = "";
+				break;
 
-            case ':':
-                numberOfColons++;
-                if (numberOfColons > 7) {
+			case ':':
+				numberOfColons++;
+				if (numberOfColons > 7) {
                     return false;
                 }
-                if (numberOfPeriods > 0) {
+				if (numberOfPeriods > 0) {
                     return false;
                 }
-                if (prevChar == ':') {
-                    if (doubleColon) {
+				if (prevChar == ':') {
+					if (doubleColon) {
                         return false;
                     }
-                    doubleColon = true;
-                }
-                word = "";
-                break;
-            case '%':
-                if (numberOfColons == 0) {
+					doubleColon = true;
+				}
+				word = "";
+				break;
+			case '%':
+				if (numberOfColons == 0) {
                     return false;
                 }
-                numberOfPercent++;
+				numberOfPercent++;
 
-                // validate that the stuff after the % is valid
-                if ((i + 1) >= length) {
-                    // in this case the percent is there but no number is
-                    // available
-                    return false;
-                }
-                try {
-                    Integer.parseInt(ipAddress.substring(i + 1));
-                } catch (NumberFormatException e) {
-                    // right now we just support an integer after the % so if
-                    // this is not
-                    // what is there then return
-                    return false;
-                }
-                break;
+				// validate that the stuff after the % is valid
+				if ((i + 1) >= length) {
+					// in this case the percent is there but no number is
+					// available
+					return false;
+				}
+				try {
+					Integer.parseInt(ipAddress.substring(i + 1));
+				} catch (NumberFormatException e) {
+					// right now we just support an integer after the % so if
+					// this is not
+					// what is there then return
+					return false;
+				}
+				break;
 
-            default:
-                if (numberOfPercent == 0) {
-                    if (word.length() > 3) {
+			default:
+				if (numberOfPercent == 0) {
+					if (word.length() > 3) {
                         return false;
                     }
-                    if (!isValidHexChar(c)) {
+					if (!isValidHexChar(c)) {
                         return false;
                     }
-                }
-                word += c;
-            }
-        }
+				}
+				word += c;
+			}
+		}
 
-        // Check if we have an IPv4 ending
-        if (numberOfPeriods > 0) {
-            if (numberOfPeriods != 3 || !isValidIP4Word(word)) {
+		// Check if we have an IPv4 ending
+		if (numberOfPeriods > 0) {
+			if (numberOfPeriods != 3 || !isValidIP4Word(word)) {
                 return false;
             }
-        } else {
-            // If we're at then end and we haven't had 7 colons then there is a
-            // problem unless we encountered a doubleColon
-            if (numberOfColons != 7 && !doubleColon) {
+		} else {
+			// If we're at then end and we haven't had 7 colons then there is a
+			// problem unless we encountered a doubleColon
+			if (numberOfColons != 7 && !doubleColon) {
+				return false;
+			}
+
+			// If we have an empty word at the end, it means we ended in either
+			// a : or a .
+			// If we did not end in :: then this is invalid
+			if (numberOfPercent == 0) {
+				if (word == "" && ipAddress.charAt(length - 1 - offset) == ':'
+						&& ipAddress.charAt(length - 2 - offset) != ':') {
+					return false;
+				}
+			}
+		}
+
+		return true;
+	}
+
+	public static boolean isValidIP4Word(String word) {
+		char c;
+		if (word.length() < 1 || word.length() > 3) {
+            return false;
+        }
+		for (int i = 0; i < word.length(); i++) {
+			c = word.charAt(i);
+			if (!(c >= '0' && c <= '9')) {
+                return false;
+            }
+		}
+		if (Integer.parseInt(word) > 255) {
+            return false;
+        }
+		return true;
+	}
+
+	static boolean isValidHexChar(char c) {
+
+		return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
+				|| (c >= 'a' && c <= 'f');
+	}
+
+	/**
+	 * Takes a string and parses it to see if it is a valid IPV4 address.
+	 *
+	 * @return true, if the string represents an IPV4 address in dotted
+	 *         notation, false otherwise
+	 */
+	public static boolean isValidIPV4Address(String value) {
+            // BEGIN android-changed
+            // general test
+            if (!value.matches("\\p{Digit}+(\\.\\p{Digit}+)*")) {
                 return false;
             }
 
-            // If we have an empty word at the end, it means we ended in either
-            // a : or a .
-            // If we did not end in :: then this is invalid
-            if (numberOfPercent == 0) {
-                if (word == "" && ipAddress.charAt(length - 1 - offset) == ':'
-                        && ipAddress.charAt(length - 2 - offset) != ':') {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-
-    public static boolean isValidIP4Word(String word) {
-        char c;
-        if (word.length() < 1 || word.length() > 3) {
-            return false;
-        }
-        for (int i = 0; i < word.length(); i++) {
-            c = word.charAt(i);
-            if (!(c >= '0' && c <= '9')) {
+            String[] parts = value.split("\\.");
+            int length = parts.length;
+            if (length < 1 || length > 4) {
                 return false;
             }
-        }
-        if (Integer.parseInt(word) > 255) {
-            return false;
-        }
-        return true;
-    }
 
-    static boolean isValidHexChar(char c) {
-
-        return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
-                || (c >= 'a' && c <= 'f');
-    }
-
-    /**
-     * Takes a string and parses it to see if it is a valid IPV4 address.
-     * 
-     * @return true, if the string represents an IPV4 address in dotted
-     *         notation, false otherwise
-     */
-    public static boolean isValidIPV4Address(String value) {
-        // BEGIN android-changed
-        // general test
-        if (!value.matches("\\p{Digit}+(\\.\\p{Digit}+)*")) {
-            return false;
-        }
-
-        String[] parts = value.split("\\.");
-        int length = parts.length;
-        if (length < 1 || length > 4) {
-            return false;
-        }
-
-        if (length == 1) {
-            // One part decimal numeric address
-            long longValue = Long.parseLong(parts[0]);
-            return longValue <= 0xFFFFFFFFL;
-        } else {
-            // Test each part for inclusion in the correct range
-            for (int i = 0; i < length; i++) {
-                // For two part addresses, the second part expresses
-                // a 24-bit quantity; for three part addresses, the third
-                // part expresses a 16-bit quantity.
-                int max = 0xff;
-                if ((length == 2) && (i == 1)) {
-                    max = 0xffffff;
-                } else if ((length == 3) && (i == 2)) {
-                    max = 0xffff;
+            if (length == 1) {
+                // One part decimal numeric address
+                long longValue = Long.parseLong(parts[0]);
+                return longValue <= 0xFFFFFFFFL;
+            } else {
+                // Test each part for inclusion in the correct range
+                for (int i = 0; i < length; i++) {
+                    // For two part addresses, the second part expresses
+                    // a 24-bit quantity; for three part addresses, the third
+                    // part expresses a 16-bit quantity.
+                    int max = 0xff;
+                    if ((length == 2) && (i == 1)) {
+                        max = 0xffffff;
+                    } else if ((length == 3) && (i == 2)) {
+                        max = 0xffff;
+                    }
+                    if (Integer.parseInt(parts[i]) > max) {
+                        return false;
+                    }
                 }
-                if (Integer.parseInt(parts[i]) > max) {
-                    return false;
-                }
+                return true;
             }
-            return true;
-        }
-        // END android-changed
-    }
+            // END android-changed
+	}
 
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java b/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java
index d7c2ab8..51a2d28 100644
--- a/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java
+++ b/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java
@@ -106,6 +106,7 @@
         // if (is instanceof ExposedByteArrayInputStream) {
         //     return ((ExposedByteArrayInputStream) is).expose();
         // }
+        // END android-changed
 
         if (is.getClass().equals(ByteArrayInputStream.class)) {
             return expose((ByteArrayInputStream) is);
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/Sorter.java b/luni/src/main/java/org/apache/harmony/luni/util/Sorter.java
deleted file mode 100644
index 1a994b2..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/util/Sorter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.util;
-
-import java.util.Arrays;
-
-/**
- * Helper class with methods for sorting arrays.
- * @deprecated Use {@link Comparator} and {@link Arrays.sort()}
- */
-@Deprecated
-public final class Sorter {
-    public interface Comparator<T> extends java.util.Comparator<T> {
-    }
-
-    /**
-     * Sorts the array of objects using the default sorting algorithm.
-     * 
-     * @param objs
-     *            array of objects to be sorted
-     * @param comp
-     *            A Comparator to be used to sort the elements
-     * 
-     */
-    public static <T> void sort(T[] objs, Comparator<T> comp) {
-        Arrays.sort(objs, comp);
-    }
-
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java b/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java
index 26e8d01..655d156 100644
--- a/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java
+++ b/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java
@@ -29,7 +29,7 @@
 import java.util.Set;
 
 /**
- *
+ * 
  * Reductive hash with two keys
  * 
  */
@@ -37,13 +37,13 @@
 
     static final float DEFAULT_LOAD_FACTOR = 0.75f;
     static final int DEFAULT_INITIAL_SIZE = 16;
-    
+
     private Set<Map.Entry<String, V>> entrySet;
     private Collection<V> values;
     private int size;
     private int arrSize;
     private int modCount;
-    
+
     private Entry<E, K, V>[] arr;
 
     private float loadFactor;
@@ -55,9 +55,10 @@
     public TwoKeyHashMap() {
         this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR);
     }
-    
+
     /**
      * Constructs an empty HashMap
+     * 
      * @param initialCapacity
      */
     public TwoKeyHashMap(int initialCapacity) {
@@ -65,16 +66,19 @@
     }
 
     /**
-     * Constructs an empty HashMap 
+     * Constructs an empty HashMap
+     * 
      * @param initialCapacity
      * @param initialLoadFactor
      */
+    @SuppressWarnings("unchecked")
     public TwoKeyHashMap(int initialCapacity, float initialLoadFactor) {
-         if (initialCapacity < 0) {
+        if (initialCapacity < 0) {
             throw new IllegalArgumentException("initialCapacity should be >= 0");
         }
         if (initialLoadFactor <= 0) {
-            throw new IllegalArgumentException("initialLoadFactor should be > 0");
+            throw new IllegalArgumentException(
+                    "initialLoadFactor should be > 0");
         }
         loadFactor = initialLoadFactor;
         if (initialCapacity == Integer.MAX_VALUE) {
@@ -84,9 +88,9 @@
         threshold = (int) (arrSize * loadFactor);
         arr = new Entry[arrSize + 1];
     }
-    
+
     /**
-     * Returns a collection view of the values 
+     * Returns a collection view of the values
      */
     public Collection<V> values() {
         if (values == null) {
@@ -94,9 +98,9 @@
         }
         return values;
     }
-    
+
     /**
-     * Returns a collection view of the mappings  
+     * Returns a collection view of the mappings
      */
     public Set<Map.Entry<String, V>> entrySet() {
         if (entrySet == null) {
@@ -104,7 +108,7 @@
         }
         return entrySet;
     }
-    
+
     /**
      * Clears the map
      */
@@ -116,6 +120,7 @@
 
     /**
      * Removes the mapping for the keys
+     * 
      * @param key1
      * @param key2
      * @return
@@ -124,9 +129,10 @@
         Entry<E, K, V> e = removeEntry(key1, key2);
         return null != e ? e.value : null;
     }
-    
+
     /**
      * Associates the specified value with the specified keys in this map
+     * 
      * @param key1
      * @param key2
      * @param value
@@ -152,7 +158,8 @@
         Entry<E, K, V> e = arr[index];
 
         while (e != null) {
-            if (hash == e.hash && key1.equals(e.getKey1()) && key2.equals(e.getKey2())) {
+            if (hash == e.hash && key1.equals(e.getKey1())
+                    && key2.equals(e.getKey2())) {
                 V oldValue = e.value;
                 e.value = value;
                 return oldValue;
@@ -172,8 +179,9 @@
 
     /**
      * Rehash the map
-     *
+     * 
      */
+    @SuppressWarnings("unchecked")
     void rehash() {
         int newArrSize = (arrSize + 1) * 2 + 1;
         if (newArrSize < 0) {
@@ -206,10 +214,12 @@
     }
 
     /**
-     * Returns true if this map contains a mapping for the specified keys
-     * @param key1
-     * @param key2
-     * @return
+     * Answers whether this map contains a mapping for the specified keys.
+     * 
+     * @param key1 first key
+     * @param key2 second key
+     * @return true if this map contains a mapping for the specified keys, and
+     *         false otherwise.
      */
     public boolean containsKey(Object key1, Object key2) {
         return findEntry(key1, key2) != null;
@@ -217,6 +227,7 @@
 
     /**
      * Return the value by keys
+     * 
      * @param key1
      * @param key2
      * @return
@@ -237,14 +248,15 @@
     }
 
     /**
-     * Returns the number of mappings 
+     * Returns the number of mappings
      */
     public int size() {
         return size;
     }
-    
+
     /**
-     *  Creates new entry
+     * Creates new entry
+     * 
      * @param hashCode
      * @param key1
      * @param key2
@@ -252,13 +264,14 @@
      * @param next
      * @return
      */
-    Entry<E, K, V> createEntry(int hashCode, E key1, K key2, 
-            V value, Entry<E, K, V> next) {
+    Entry<E, K, V> createEntry(int hashCode, E key1, K key2, V value,
+            Entry<E, K, V> next) {
         return new Entry<E, K, V>(hashCode, key1, key2, value, next);
     }
 
     /**
      * Creates entries iterator
+     * 
      * @return
      */
     Iterator<Map.Entry<String, V>> createEntrySetIterator() {
@@ -267,18 +280,18 @@
 
     /**
      * Creates values iterator
+     * 
      * @return
      */
     Iterator<V> createValueCollectionIterator() {
         return new ValueIteratorImpl();
     }
 
-    
     /**
      * Entry implementation for the TwoKeyHashMap class
      * 
      */
-    public static class Entry<E, K, V> implements Map.Entry<String, V> { 
+    public static class Entry<E, K, V> implements Map.Entry<String, V> {
         int hash;
         E key1;
         K key2;
@@ -292,7 +305,7 @@
             this.value = value;
             this.next = next;
         }
-        
+
         public String getKey() {
             return key1.toString() + key2.toString();
         }
@@ -300,7 +313,7 @@
         public E getKey1() {
             return key1;
         }
-        
+
         public K getKey2() {
             return key2;
         }
@@ -324,12 +337,11 @@
             Object getKey1 = e.getKey1();
             Object getKey2 = e.getKey2();
             Object getValue = e.getValue();
-            if ((key1 == null && getKey1 != null) || 
-                    (key2 == null && getKey2 != null) ||
-                    (value == null && getValue != null) ||
-                    !key1.equals(e.getKey1()) ||
-                    !key2.equals(e.getKey2()) ||
-                    !value.equals(getValue)) {
+            if ((key1 == null && getKey1 != null)
+                    || (key2 == null && getKey2 != null)
+                    || (value == null && getValue != null)
+                    || !key1.equals(e.getKey1()) || !key2.equals(e.getKey2())
+                    || !value.equals(getValue)) {
                 return false;
             }
             return true;
@@ -340,9 +352,9 @@
             int hash2 = (key2 == null ? 0 : key2.hashCode());
             return (hash1 + hash2) ^ (value == null ? 0 : value.hashCode());
         }
-        
+
     }
-    
+
     class EntrySetImpl extends AbstractSet<Map.Entry<String, V>> {
         public int size() {
             return size;
@@ -375,7 +387,7 @@
             if (!(obj instanceof Entry)) {
                 return false;
             }
-            return removeEntry(((Entry) obj).getKey1(), ((Entry)obj).getKey2()) != null;
+            return removeEntry(((Entry) obj).getKey1(), ((Entry) obj).getKey2()) != null;
         }
 
         public Iterator<Map.Entry<String, V>> iterator() {
@@ -425,14 +437,14 @@
             found = false;
             returned_index = curr;
             returned_entry = curr_entry;
-            return (Map.Entry<String, V>)curr_entry;
+            return (Map.Entry<String, V>) curr_entry;
         }
 
         public void remove() {
             if (returned_index == -1) {
                 throw new IllegalStateException();
             }
-            
+
             if (modCount != startModCount) {
                 throw new ConcurrentModificationException();
             }
@@ -454,7 +466,7 @@
             returned_index = -1;
         }
     }
-    
+
     private final Entry<E, K, V> findEntry(Object key1, Object key2) {
         if (key1 == null && key2 == null) {
             return arr[arrSize];
@@ -465,14 +477,15 @@
         Entry<E, K, V> e = arr[index];
 
         while (e != null) {
-            if (hash == e.hash && key1.equals(e.getKey1()) && key2.equals(e.getKey2())) {
+            if (hash == e.hash && key1.equals(e.getKey1())
+                    && key2.equals(e.getKey2())) {
                 return e;
             }
             e = e.next;
         }
         return null;
     }
-    
+
     // Removes entry
     private final Entry<E, K, V> removeEntry(Object key1, Object key2) {
         if (key1 == null && key2 == null) {
@@ -493,7 +506,8 @@
         Entry<E, K, V> e = arr[index];
         Entry<E, K, V> prev = e;
         while (e != null) {
-            if (hash == e.hash && key1.equals(e.getKey1()) && key2.equals(e.getKey2())) {
+            if (hash == e.hash && key1.equals(e.getKey1())
+                    && key2.equals(e.getKey2())) {
                 if (prev == e) {
                     arr[index] = e.next;
                 } else {
@@ -529,12 +543,12 @@
         public Iterator<V> iterator() {
             return createValueCollectionIterator();
         }
-        
+
         public boolean contains(Object obj) {
             return containsValue(obj);
         }
     }
-    
+
     class ValueIteratorImpl implements Iterator<V> {
         private EntryIteratorImpl itr;
 
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/Util.java b/luni/src/main/java/org/apache/harmony/luni/util/Util.java
index bfb0149..0688e7d 100644
--- a/luni/src/main/java/org/apache/harmony/luni/util/Util.java
+++ b/luni/src/main/java/org/apache/harmony/luni/util/Util.java
@@ -41,13 +41,19 @@
         if (encoding != null) {
             try {
                 "".getBytes(encoding);
-            } catch (java.io.UnsupportedEncodingException e) {
+            } catch (Throwable t) {
                 encoding = null;
             }
         }
         defaultEncoding = encoding;
     }
 
+    /**
+     * Get bytes from String using default encoding; default encoding can
+     * be changed via "os.encoding" property
+     * @param name input String
+     * @return byte array
+     */
     public static byte[] getBytes(String name) {
         if (defaultEncoding != null) {
             try {
@@ -58,6 +64,20 @@
         return name.getBytes();
     }
 
+    /**
+     * Get bytes from String with UTF8 encoding
+     * @param name
+     *          input String
+     * @return byte array
+     */
+    public static byte[] getUTF8Bytes(String name) {
+        try {
+            return name.getBytes("UTF-8");
+        } catch (java.io.UnsupportedEncodingException e) {
+            return getBytes(name);
+        }
+    }
+
     public static String toString(byte[] bytes) {
         if (defaultEncoding != null) {
             try {
@@ -68,6 +88,10 @@
         return new String(bytes, 0, bytes.length);
     }
 
+    public static String toUTF8String(byte[] bytes) {
+        return toUTF8String(bytes, 0, bytes.length);
+    }
+
     public static String toString(byte[] bytes, int offset, int length) {
         if (defaultEncoding != null) {
             try {
@@ -78,10 +102,18 @@
         return new String(bytes, offset, length);
     }
 
+    public static String toUTF8String(byte[] bytes, int offset, int length) {
+        try {
+            return new String(bytes, offset, length, "UTF-8");
+        } catch (java.io.UnsupportedEncodingException e) {
+            return toString(bytes, offset, length);
+        }
+    }
+
     /**
      * Returns the millisecond value of the date and time parsed from the
      * specified String. Many date/time formats are recognized
-     * 
+     *
      * @param string
      *            the String to parse
      * @return the millisecond value parsed from the String
@@ -236,7 +268,7 @@
      * '%' and two following hex digit characters are converted to the
      * equivalent byte value. All other characters are passed through
      * unmodified. e.g. "ABC %24%25" -> "ABC $%"
-     * 
+     *
      * @param s
      *            java.lang.String The encoded string.
      * @return java.lang.String The decoded version.
@@ -273,7 +305,7 @@
         }
         return result.toString();
     }
-    
+
     public static String toASCIILowerCase(String s) {
         int len = s.length();
         StringBuilder buffer = new StringBuilder(len);
@@ -287,7 +319,7 @@
         }
         return buffer.toString();
     }
-    
+
     public static String toASCIIUpperCase(String s) {
         int len = s.length();
         StringBuilder buffer = new StringBuilder(len);
diff --git a/luni/src/main/native/cbigint.c b/luni/src/main/native/cbigint.c
index 0f65ca0..77ee0f8 100644
--- a/luni/src/main/native/cbigint.c
+++ b/luni/src/main/native/cbigint.c
@@ -18,7 +18,7 @@
 #include <string.h>
 #include "cbigint.h"
 
-#if defined(LINUX) || defined(FREEBSD)
+#if defined(LINUX) || defined(FREEBSD) || defined(ZOS)
 #define USE_LL
 #endif
 
@@ -691,7 +691,7 @@
    */
   /* Replace the current implementaion which performs a
    * "multiplication" by 10 e number of times with an actual
-   * mulitplication. 10e19 is the largest exponent to the power of ten
+   * multiplication. 10e19 is the largest exponent to the power of ten
    * that will fit in a 64-bit integer, and 10e9 is the largest exponent to
    * the power of ten that will fit in a 64-bit integer. Not sure where the
    * break-even point is between an actual multiplication and a
diff --git a/luni/src/main/native/java_io_FileDescriptor.c b/luni/src/main/native/java_io_FileDescriptor.c
index a5ec8b7..897e688 100644
--- a/luni/src/main/native/java_io_FileDescriptor.c
+++ b/luni/src/main/native/java_io_FileDescriptor.c
@@ -103,20 +103,6 @@
     }
 }
 
-/*
- * public native boolean valid()
- */
-static jboolean fd_valid(JNIEnv* env, jobject obj) {
-    int fd = getFd(env, obj);
-    struct stat sb;
-
-    if(fstat(fd, &sb) == 0) {
-        return JNI_TRUE;
-    } else {
-        return JNI_FALSE;
-    }
-}
-
 /* checks to see if class is inited and inits if needed, returning -1
  * on fail and 0 on success
  */
@@ -205,8 +191,7 @@
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
     { "oneTimeInitialization", "()V",              nativeClassInit },
-    { "syncImpl",           "()V",                 fd_sync },
-    { "valid",          "()Z",                     fd_valid }
+    { "syncImpl",           "()V",                 fd_sync }
 };
 int register_java_io_FileDescriptor(JNIEnv* env) {
     return jniRegisterNativeMethods(env, "java/io/FileDescriptor",
diff --git a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index e105f5c..cce822a 100644
--- a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -1654,7 +1654,7 @@
 }
 
 
-static void osNetworkSystem_createSocketImpl(JNIEnv* env, jclass clazz,
+static void osNetworkSystem_createStreamSocketImpl(JNIEnv* env, jclass clazz,
         jobject fileDescriptor, jboolean preferIPv4Stack) {
     // LOGD("ENTER createSocketImpl");
     createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
@@ -2340,35 +2340,6 @@
     }
 }
 
-static jboolean osNetworkSystem_socketBindImpl2(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jint port, jboolean bindToDevice,
-        jobject inetAddress) {
-    // LOGD("ENTER socketBindImpl2");
-
-    struct sockaddr_storage sockaddress;
-    int ret;
-    int handle;
-
-    ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
-    if (ret < 0)  // Exception has already been thrown.
-        return 0;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADDESC);
-        return 0;
-    }
-
-    ret = doBind(handle, &sockaddress);
-    if (ret < 0) {
-        int err = convertError(errno);
-        jniThrowException(env, "java/net/BindException", netLookupErrorString(err));
-        return 0;
-    }
-
-    return 0;
-}
-
 static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
         jobject fd, jobject sender, jint receiveTimeout) {
     // LOGD("ENTER peekDatagramImpl");
@@ -2639,19 +2610,6 @@
     setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
 }
 
-static void osNetworkSystem_createMulticastSocketImpl(JNIEnv* env,
-        jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
-    // LOGD("ENTER createMulticastSocketImpl");
-
-    int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM);
-    if (handle < 0)
-        return;
-
-    int value = 1;
-    // setsockopt(handle, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(jbyte));
-    setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
-}
-
 /*
  * @param timeout in milliseconds.  If zero, block until data received
  */
@@ -3847,7 +3805,7 @@
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
     { "oneTimeInitializationImpl",         "(Z)V",                                                                     (void*) osNetworkSystem_oneTimeInitializationImpl          },
-    { "createSocketImpl",                  "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createSocketImpl                   },
+    { "createStreamSocketImpl",            "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createStreamSocketImpl             },
     { "createDatagramSocketImpl",          "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createDatagramSocketImpl           },
     { "readSocketImpl",                    "(Ljava/io/FileDescriptor;[BIII)I",                                         (void*) osNetworkSystem_readSocketImpl                     },
     { "readSocketDirectImpl",              "(Ljava/io/FileDescriptor;IIII)I",                                          (void*) osNetworkSystem_readSocketDirectImpl               },
@@ -3865,7 +3823,6 @@
     { "sendUrgentDataImpl",                "(Ljava/io/FileDescriptor;B)V",                                             (void*) osNetworkSystem_sendUrgentDataImpl                 },
     { "connectDatagramImpl2",              "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;)V",                      (void*) osNetworkSystem_connectDatagramImpl2               },
     { "disconnectDatagramImpl",            "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_disconnectDatagramImpl             },
-    { "socketBindImpl2",                   "(Ljava/io/FileDescriptor;IZLjava/net/InetAddress;)Z",                      (void*) osNetworkSystem_socketBindImpl2                    },
     { "peekDatagramImpl",                  "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I",                       (void*) osNetworkSystem_peekDatagramImpl                   },
     { "receiveDatagramImpl",               "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I",               (void*) osNetworkSystem_receiveDatagramImpl                },
     { "receiveDatagramDirectImpl",         "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I",                (void*) osNetworkSystem_receiveDatagramDirectImpl          },
@@ -3876,7 +3833,6 @@
     { "sendConnectedDatagramImpl",         "(Ljava/io/FileDescriptor;[BIIZ)I",                                         (void*) osNetworkSystem_sendConnectedDatagramImpl          },
     { "sendConnectedDatagramDirectImpl",   "(Ljava/io/FileDescriptor;IIIZ)I",                                          (void*) osNetworkSystem_sendConnectedDatagramDirectImpl    },
     { "createServerStreamSocketImpl",      "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createServerStreamSocketImpl       },
-    { "createMulticastSocketImpl",         "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createMulticastSocketImpl          },
     { "receiveStreamImpl",                 "(Ljava/io/FileDescriptor;[BIII)I",                                         (void*) osNetworkSystem_receiveStreamImpl                  },
     { "sendStreamImpl",                    "(Ljava/io/FileDescriptor;[BII)I",                                          (void*) osNetworkSystem_sendStreamImpl                     },
     { "shutdownInputImpl",                 "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_shutdownInputImpl                  },
diff --git a/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c b/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
index d8a1e68..e92b776 100644
--- a/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
+++ b/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
@@ -22,7 +22,7 @@
 #include "commonDblParce.h"
 #include "cbigint.h"
 
-#if defined(LINUX)
+#if defined(LINUX) || defined(FREEBSD) || defined(ZOS)
 #define USE_LL
 #endif
 
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java
index ed81162..84cddf2 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java
@@ -45,8 +45,9 @@
         File file = new File(root, "/dir/file");
         assertEquals("Assert 1: wrong path result ", path.getPath(), file
                 .getPath());
-        assertTrue("Assert 1.1: path not absolute ", new File("\\\\\\a\b").isAbsolute());
-        
+        assertFalse("Assert 1.1: path absolute ", new File("\\\\\\a\b").isAbsolute());
+        assertTrue("Assert 1.1: path absolute ", new File("///a/b").isAbsolute());
+
         // Test data used in a few places below
         String dirName = System.getProperty("java.io.tmpdir");
         String fileName = "input.tst";
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java
index 14ca1ad..3097fbe 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java
@@ -838,6 +838,8 @@
         args = {}
     )
     public void test_getClassLoader() {
+        // this fails if ClassTest.class was loaded by the regular classloader,
+        // but passes if it was loaded by the boot class loader.
 
         assertEquals(ExtendTestClass.class.getClassLoader(),
                          PublicTestClass.class.getClassLoader());
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java
index 2b03e5a..b1ad88a 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java
@@ -1091,8 +1091,6 @@
             fail("Expected Float.valueOf(null) to throw NPE.");
         } catch (NullPointerException ex) {
             // expected
-        } catch (Exception ex) {
-            fail("Expected Float.valueOf(null) to throw NPE not " + ex.getClass().getName());
         }
 
         try {
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java
index 9151068..ea71009 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java
@@ -169,6 +169,56 @@
             exception = true;
         }
         assertTrue("Failed to throw exception for 9999999999", exception);
+
+        try {
+            Integer.decode("-");
+            fail("Expected exception for -");
+        } catch (NumberFormatException e) {
+            // Expected
+        }
+
+        try {
+            Integer.decode("0x");
+            fail("Expected exception for 0x");
+        } catch (NumberFormatException e) {
+            // Expected
+        }
+
+        try {
+            Integer.decode("#");
+            fail("Expected exception for #");
+        } catch (NumberFormatException e) {
+            // Expected
+        }
+
+        try {
+            Integer.decode("x123");
+            fail("Expected exception for x123");
+        } catch (NumberFormatException e) {
+            // Expected
+        }
+
+        try {
+            Integer.decode(null);
+            fail("Expected exception for null");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+
+        try {
+            Integer.decode("");
+            fail("Expected exception for empty string");
+        } catch (NumberFormatException ex) {
+            // Expected
+        }
+
+        try {
+            Integer.decode(" ");
+            fail("Expected exception for single space");
+        } catch (NumberFormatException ex) {
+            // Expected
+        }
+
     }
 
     /**
@@ -591,6 +641,15 @@
                 -Integer.MAX_VALUE));
         assertEquals("Returned incorrect octal string", "-2147483648", Integer.toString(
                 Integer.MIN_VALUE));
+        
+        // Test for HARMONY-6068
+        assertEquals("Returned incorrect octal String", "-1000", Integer.toString(-1000));
+        assertEquals("Returned incorrect octal String", "1000", Integer.toString(1000));
+        assertEquals("Returned incorrect octal String", "0", Integer.toString(0));
+        assertEquals("Returned incorrect octal String", "708", Integer.toString(708));
+        assertEquals("Returned incorrect octal String", "-100", Integer.toString(-100));
+        assertEquals("Returned incorrect octal String", "-1000000008", Integer.toString(-1000000008));
+        assertEquals("Returned incorrect octal String", "2000000008", Integer.toString(2000000008));
     }
 
     /**
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java
index e2b72be..758428e 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java
@@ -23,6 +23,7 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.BrokenTest;
+import dalvik.annotation.SideEffect;
 
 @TestTargetClass(Object.class) 
 public class ObjectTest extends junit.framework.TestCase {
@@ -79,6 +80,7 @@
         method = "finalize",
         args = {}
     )
+    @SideEffect("Causes OutOfMemoryError to test finalization")
     public void test_finalize() {
         isCalled = false;
         class TestObject extends Object {
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java
index 93561bf..d35f50b 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java
@@ -228,6 +228,16 @@
         Process process = pb.start();
         InputStream in = process.getInputStream();
         InputStream err = process.getErrorStream();
+
+        while (true) {
+            try {
+                process.waitFor();
+                break;
+            } catch (InterruptedException e) {
+                // Ignored
+            }
+        }
+
         byte[] buf = new byte[1024];
         if (in.available() > 0) {
             assertTrue(in.read(buf) > 0);
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java
index bcb94c7..48fddfe 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java
@@ -37,11 +37,7 @@
         args = {}
     )
     public void test_Constructor() {
-        try {
-            new ThreadLocal<Object>();
-        } catch (Exception e) {
-            fail("unexpected exception: " + e.toString());
-        }
+        new ThreadLocal<Object>();
     }
     
     /**
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java
index d00968f..bdbfbd4 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java
@@ -67,8 +67,7 @@
                 assertTrue(isCreateContentHandlerCalled);
                 assertTrue(isGetContentCalled);
             } catch (Exception e) {
-                fail("Exception during test : " + e.getMessage());
-            
+                throw new RuntimeException(e);
             }
             
             isGetContentCalled = false;
@@ -77,8 +76,7 @@
                 con.getContent(new Class[] {});
                 assertTrue(isGetContentCalled);
             } catch (Exception e) {
-                fail("Exception during test : " + e.getMessage());
-            
+                throw new RuntimeException(e);
             }
             
             try {
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
index c803d3b..bcd73d8 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
@@ -1069,8 +1069,6 @@
         method = "getHeaderFieldDate",
         args = {java.lang.String.class, long.class}
     )
-    @KnownFailure("getHeaderFieldDate on Content-Length throws an exception."
-            + " The RI just returns the default value")
     public void test_getHeaderFieldDateLjava_lang_StringJ() {
         Support_TestWebData params = Support_TestWebData.testParams[0];
 
@@ -1612,7 +1610,6 @@
         method = "guessContentTypeFromStream",
         args = {java.io.InputStream.class}
     )
-    @KnownFailure("'<?xml' recognised as text/html instead of application/xml")
     public void test_guessContentTypeFromStreamLjava_io_InputStream()
             throws IOException {
         assertContentTypeEquals("ASCII", "text/html", "<html>");
diff --git a/luni/src/test/java/tests/api/java/io/FileTest.java b/luni/src/test/java/tests/api/java/io/FileTest.java
index b35e85f..9f32fef 100644
--- a/luni/src/test/java/tests/api/java/io/FileTest.java
+++ b/luni/src/test/java/tests/api/java/io/FileTest.java
@@ -217,8 +217,6 @@
         method = "File",
         args = {java.lang.String.class, java.lang.String.class}
     )
-    @AndroidOnly("Test 3 incorrectly fails on the RI; Android is more " +
-            "better at resolving path names.")
     public void test_ConstructorLjava_lang_StringLjava_lang_String_112270() {
         File ref1 = new File("/dir1/file1");
 
@@ -230,10 +228,10 @@
                 ref1.getPath()));
         File file3 = new File("\\", "\\dir1\\file1");
         assertTrue("wrong result 3: " + file3, file3.getPath().equals(
-                ref1.getPath()));
+                "\\/\\dir1\\file1"));
         File file4 = new File("\\", "\\\\dir1\\file1");
         assertTrue("wrong result 4: " + file4, file4.getPath().equals(
-                ref1.getPath()));
+                "\\/\\\\dir1\\file1"));
 
         File ref2 = new File("/lib/content-types.properties");
         File file5 = new File("/", "lib/content-types.properties");
@@ -250,8 +248,6 @@
         method = "File",
         args = {java.io.File.class, java.lang.String.class}
     )    
-    @AndroidOnly("Test 3 incorrectly fails on the RI; Android is more " +
-            "better at resolving path names.")
     public void test_ConstructorLjava_io_FileLjava_lang_String_112270() {
         File ref1 = new File("/dir1/file1");
 
@@ -264,10 +260,10 @@
                 ref1.getPath()));
         File file3 = new File(root, "\\dir1\\file1");
         assertTrue("wrong result 3: " + file3, file3.getPath().equals(
-                ref1.getPath()));
+                "/\\dir1\\file1"));
         File file4 = new File(root, "\\\\dir1\\file1");
         assertTrue("wrong result 4: " + file4, file4.getPath().equals(
-                ref1.getPath()));
+                "/\\\\dir1\\file1"));
 
         File ref2 = new File("/lib/content-types.properties");
         File file5 = new File(root, "lib/content-types.properties");
@@ -693,6 +689,8 @@
         args = {}
     )        
     public void test_delete() {
+        // this test passes in the emulator, but it fails on the device
+
         // Test for method boolean java.io.File.delete()
         try {
             File dir = new File(System.getProperty("java.io.tmpdir"), platformId
diff --git a/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java b/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java
index 3f5fc68..783478a 100644
--- a/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java
+++ b/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java
@@ -30,6 +30,7 @@
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetEncoder;
+import java.util.Arrays;
 
 import tests.support.Support_OutputStream;
 
@@ -483,6 +484,99 @@
         }
     }
 
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_US_ASCII() throws Exception {
+        testEncodeCharset("US-ASCII", 128);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_ISO_8859_1() throws Exception {
+        testEncodeCharset("ISO-8859-1", 256);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_UTF_16BE() throws Exception {
+        testEncodeCharset("UTF-16BE", 0xd800);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_UTF_16LE() throws Exception {
+        testEncodeCharset("UTF-16LE", 0xd800);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_UTF_16() throws Exception {
+        testEncodeCharset("UTF-16", 0xd800);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_UTF_8() throws Exception {
+        testEncodeCharset("UTF-8", 0xd800);
+    }
+
+    private void testEncodeCharset(String charset, int maxChar) throws Exception {
+        char[] chars = new char[maxChar];
+        for (int i = 0; i < maxChar; i++) {
+            chars[i] = (char) i;
+        }
+
+        // to byte array
+        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+        OutputStreamWriter charsOut = new OutputStreamWriter(bytesOut, charset);
+        charsOut.write(chars);
+        charsOut.flush();
+
+        // decode from byte array, one character at a time
+        ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytesOut.toByteArray());
+        InputStreamReader charsIn = new InputStreamReader(bytesIn, charset);
+        for (int i = 0; i < maxChar; i++) {
+            assertEquals(i, charsIn.read());
+        }
+        assertEquals(-1, charsIn.read());
+
+        // decode from byte array, using byte buffers
+        bytesIn = new ByteArrayInputStream(bytesOut.toByteArray());
+        charsIn = new InputStreamReader(bytesIn, charset);
+        char[] decoded = new char[maxChar];
+        for (int r = 0; r < maxChar; ) {
+            r += charsIn.read(decoded, r, maxChar - r);
+        }
+        assertEquals(-1, charsIn.read());
+        for (int i = 0; i < maxChar; i++) {
+            assertEquals(i, decoded[i]);
+        }
+    }
+
     /**
      * @tests java.io.OutputStreamWriter#getEncoding()
      */
diff --git a/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java b/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java
index 4c67241..d890f38 100644
--- a/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java
+++ b/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java
@@ -21,6 +21,7 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.BrokenTest;
+import dalvik.annotation.SideEffect;
 
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
@@ -107,6 +108,7 @@
         method = "get",
         args = {}
     )
+    @SideEffect("Causes OutOfMemoryError to test finalization")
     public void test_get_SoftReference() {
 
         class TestObject {
diff --git a/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java b/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java
index 31dfaa5..8919652 100644
--- a/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java
+++ b/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java
@@ -169,8 +169,6 @@
         )
     })
     @SuppressWarnings("unchecked")
-    @KnownFailure("Class MultipleBoundedWildcardUnEquality can not be found, "
-            + "maybe the wrong class loader is used to get the raw type?")
     public void testMultipleBoundedWildcardUnEquality() throws Exception {
         Class<? extends MultipleBoundedWildcardUnEquality> clazz = MultipleBoundedWildcardUnEquality.class;
 
@@ -240,8 +238,6 @@
         )
     })
     @SuppressWarnings("unchecked")
-    @KnownFailure("Class MultipleBoundedWildcardEquality can not be found, "
-            + "maybe the wrong class loader is used to get the raw type?")
     public void testMultipleBoundedWildcard() throws Exception {
         Class<? extends MultipleBoundedWildcardEquality> clazz = MultipleBoundedWildcardEquality.class;
 
diff --git a/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java b/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java
index c9255b2..7db5dbe 100644
--- a/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java
+++ b/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java
@@ -201,8 +201,6 @@
         args = {}
     )
     @SuppressWarnings("unchecked")
-    @KnownFailure("Class GenericType can not be found, "
-            + "maybe the wrong class loader is used to get the raw type?")
     public void testSimpleInheritance() throws Exception {
         Class<? extends SimpleInheritance> clazz = SimpleInheritance.class;
         TypeVariable<Class> subTypeVariable = getTypeParameter(clazz);
diff --git a/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java b/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java
index eaff7c8..bf3698e 100644
--- a/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java
+++ b/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java
@@ -55,8 +55,6 @@
             args = {}
         )
     })
-    @KnownFailure("Class A can not be found, "
-            + "maybe the wrong class loader is used to get the raw type?")
     public void testStringParameterizedSuperClass() {
         Class<? extends B> clazz = B.class;
         Type genericSuperclass = clazz.getGenericSuperclass();
@@ -93,8 +91,6 @@
             args = {}
         )
     })
-    @KnownFailure("Class C can not be found, "
-            + "maybe the wrong class loader is used to get the raw type?")
     public void testTypeParameterizedSuperClass() {
         Class<? extends D> clazz = D.class;
         Type genericSuperclass = clazz.getGenericSuperclass();
diff --git a/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java b/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
index f6957e2..13141f8 100644
--- a/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
+++ b/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
@@ -36,6 +36,9 @@
 import java.net.UnknownHostException;
 import java.security.Permission;
 import java.util.Enumeration;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
 
 import tests.support.Support_NetworkInterface;
 import tests.support.Support_PortManager;
@@ -64,23 +67,24 @@
 
         public MulticastSocket ms;
 
-        boolean running = true;
+        volatile boolean running = true;
 
-        volatile public byte[] rbuf = new byte[512];
-
-        volatile DatagramPacket rdp = null;
+        private final BlockingQueue<DatagramPacket> queue
+                = new ArrayBlockingQueue<DatagramPacket>(1);
 
         public void run() {
             try {
                 while (running) {
                     try {
+                        byte[] rbuf = new byte[512];
+                        rbuf[0] = -1;
+                        DatagramPacket rdp = new DatagramPacket(rbuf, rbuf.length);
                         ms.receive(rdp);
+                        queue.put(rdp);
                     } catch (java.io.InterruptedIOException e) {
-                        Thread.yield();
+                    } catch (InterruptedException e) {
                     }
-                    ;
                 }
-                ;
             } catch (java.io.IOException e) {
                 System.out.println("Multicast server failed: " + e);
             } finally {
@@ -93,15 +97,8 @@
             ms.leaveGroup(aGroup);
         }
 
-        public void stopServer() {
-            running = false;
-        }
-
         public MulticastServer(InetAddress anAddress, int aPort)
                 throws java.io.IOException {
-            rbuf = new byte[512];
-            rbuf[0] = -1;
-            rdp = new DatagramPacket(rbuf, rbuf.length);
             ms = new MulticastSocket(aPort);
             ms.setSoTimeout(2000);
             ms.joinGroup(anAddress);
@@ -109,13 +106,20 @@
 
         public MulticastServer(SocketAddress anAddress, int aPort,
                 NetworkInterface netInterface) throws java.io.IOException {
-            rbuf = new byte[512];
-            rbuf[0] = -1;
-            rdp = new DatagramPacket(rbuf, rbuf.length);
             ms = new MulticastSocket(aPort);
             ms.setSoTimeout(2000);
             ms.joinGroup(anAddress, netInterface);
         }
+
+        public DatagramPacket receive() throws InterruptedException {
+            return queue.poll(1000, TimeUnit.MILLISECONDS);
+        }
+
+        public void stopServer() throws InterruptedException {
+            running = false;
+            interrupt();
+            join();
+        }
     }
 
     /**
@@ -458,7 +462,7 @@
         method = "joinGroup",
         args = {java.net.InetAddress.class}
     )
-    public void test_joinGroupLjava_net_InetAddress() {
+    public void test_joinGroupLjava_net_InetAddress() throws InterruptedException {
         // Test for method void
         // java.net.MulticastSocket.joinGroup(java.net.InetAddress)
         String msg = null;
@@ -476,8 +480,7 @@
                     .length(), group, groupPort);
             mss.joinGroup(group);
             mss.send(sdp, (byte) 10);
-            Thread.sleep(1000);
-            
+
             SecurityManager sm = new SecurityManager() {
 
                 public void checkPermission(Permission perm) {
@@ -514,8 +517,10 @@
         } catch (Exception e) {
             fail("Exception during joinGroup test: " + e.toString());
         }
-        assertTrue("Group member did not recv data: ", new String(server.rdp
-                .getData(), 0, server.rdp.getLength()).equals(msg));
+        DatagramPacket rdb = server.receive();
+
+        assertEquals("Group member did not recv data: ", msg,
+                new String(rdb.getData(), 0, rdb.getLength()));
 
     }
 
@@ -609,11 +614,11 @@
                     .length(), group, serverPort);
             mss.setTimeToLive(2);
             mss.send(sdp);
-            Thread.sleep(1000);
+            DatagramPacket rdp = server.receive();
+
             // now vaildate that we received the data as expected
-            assertTrue("Group member did not recv data: ", new String(
-                    server.rdp.getData(), 0, server.rdp.getLength())
-                    .equals(msg));
+            assertEquals("Group member did not recv data: ", msg,
+                    new String(rdp.getData(), 0, rdp.getLength()));
             server.stopServer();
 
             // now validate that we handled the case were we join a
@@ -634,11 +639,9 @@
             sdp = new DatagramPacket(msg.getBytes(), msg.length(), group2,
                     serverPort);
             mss.send(sdp);
-            Thread.sleep(1000);
-            assertFalse(
-                    "Group member received data when sent on different group: ",
-                    new String(server.rdp.getData(), 0, server.rdp.getLength())
-                            .equals(msg));
+            rdp = server.receive();
+            assertNull("Group member received data when sent on different group",
+                    rdp);
             server.stopServer();
 
             // if there is more than one network interface then check that
@@ -718,20 +721,20 @@
                         sdp = new DatagramPacket(msg.getBytes(), msg.length(),
                                 group, serverPort);
                         mss.send(sdp);
-                        Thread.sleep(1000);
+                        rdp = server.receive();
+
                         if (thisInterface.equals(sendingInterface)) {
-                            assertTrue(
+                            assertEquals(
                                     "Group member did not recv data when " +
-                                    "bound on specific interface: ",
-                                    new String(server.rdp.getData(), 0,
-                                            server.rdp.getLength()).equals(msg));
+                                    "bound on specific interface: ", msg,
+                                    new String(rdp.getData(), 0, rdp.getLength()));
                         } else {
                             assertFalse(
                                     "Group member received data on other " +
                                     "interface when only asked for it on one " +
                                     "interface: ",
-                                    new String(server.rdp.getData(), 0,
-                                            server.rdp.getLength()).equals(msg));
+                                    new String(rdp.getData(), 0,
+                                            rdp.getLength()).equals(msg));
                         }
 
                         server.stopServer();
@@ -943,7 +946,7 @@
         method = "send",
         args = {java.net.DatagramPacket.class, byte.class}
     )
-    public void test_sendLjava_net_DatagramPacketB() {
+    public void test_sendLjava_net_DatagramPacketB() throws InterruptedException {
         // Test for method void
         // java.net.MulticastSocket.send(java.net.DatagramPacket, byte)
 
@@ -1016,11 +1019,10 @@
         } catch(IOException ioe) {
             //expected
         }
-        
-        byte[] data = server.rdp.getData();
-        int length = server.rdp.getLength();
-        assertTrue("Failed to send data. Received " + length, new String(data,
-                0, length).equals(msg));
+
+        DatagramPacket rdp = server.receive();
+        assertEquals("Failed to send data. Received " + rdp.getLength(), msg,
+                new String(rdp.getData(), 0, rdp.getLength()));
     }
 
     /**
@@ -1163,24 +1165,13 @@
                         DatagramPacket sdp = new DatagramPacket(theBytes,
                                 theBytes.length, group, serverPort);
                         mss.send(sdp);
-                        Thread.sleep(1000);
-                        String receivedMessage = new String(server.rdp
-                                .getData(), 0, server.rdp.getLength());
-                        assertTrue(
-                                "Group member did not recv data when send on " +
-                                "a specific interface: ",
-                                receivedMessage.equals(msg));
-                        assertTrue(
-                                "Datagram was not received from expected " +
-                                "interface expected["
-                                        + thisInterface
-                                        + "] got ["
-                                        + NetworkInterface
-                                                .getByInetAddress(server.rdp
-                                                        .getAddress()) + "]",
-                                NetworkInterface.getByInetAddress(
-                                        server.rdp.getAddress()).equals(
-                                        thisInterface));
+                        DatagramPacket rdp = server.receive();
+
+                        String receivedMessage = new String(rdp.getData(), 0, rdp.getLength());
+                        assertEquals("Group member did not recv data when send on "
+                                + "a specific interface: ", msg, receivedMessage);
+                        assertEquals("Datagram was not received as expected.",
+                                thisInterface, NetworkInterface.getByInetAddress(rdp.getAddress()));
 
                         // stop the server
                         server.stopServer();
@@ -1598,7 +1589,7 @@
      * Tears down the fixture, for example, close a network connection. This
      * method is called after a test is executed.
      */
-    protected void tearDown() {
+    protected void tearDown() throws InterruptedException {
 
         if (t != null)
             t.interrupt();
diff --git a/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java b/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java
index 9fc287c..463532f 100644
--- a/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java
+++ b/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java
@@ -40,7 +40,7 @@
     public void test_Constructor() {
         // Test for method java.net.UnknownServiceException()
         try {
-            new URL("file://moo.txt").openConnection().getOutputStream();
+            new URL("file:///moo.txt").openConnection().getOutputStream();
         } catch (UnknownServiceException e) {
             // correct
             return;
diff --git a/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java b/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java
index 169afe3..e2c47b8 100644
--- a/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java
+++ b/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java
@@ -85,7 +85,7 @@
         }
 
         public boolean hasNext() {
-            return false;
+            return true;
         }
 
         public boolean hasPrevious() {
diff --git a/luni/src/test/java/tests/api/java/util/BitSetTest.java b/luni/src/test/java/tests/api/java/util/BitSetTest.java
index c0e6f2a..34ec49a 100644
--- a/luni/src/test/java/tests/api/java/util/BitSetTest.java
+++ b/luni/src/test/java/tests/api/java/util/BitSetTest.java
@@ -252,7 +252,7 @@
         initialSize = bs.size();
         bs.set(0, initialSize);
         bs.clear(7, 64);
-        assertEquals("Failed to grow BitSet", 128, bs.size());
+        assertEquals("Failed to grow BitSet", 64, bs.size());
         for (int i = 0; i < 7; i++)
             assertTrue("Shouldn't have cleared bit " + i, bs.get(i));
         for (int i = 7; i < 64; i++)
@@ -624,7 +624,7 @@
         // pos1 and pos2 is in the same bitset element, boundary testing
         bs = new BitSet(16);
         bs.set(7, 64);
-        assertEquals("Failed to grow BitSet", 128, bs.size());
+        assertEquals("Failed to grow BitSet", 64, bs.size());
         for (int i = 0; i < 7; i++)
             assertTrue("Shouldn't have set bit " + i, !bs.get(i));
         for (int i = 7; i < 64; i++)
@@ -858,7 +858,7 @@
         bs.set(7);
         bs.set(10);
         bs.flip(7, 64);
-        assertEquals("Failed to grow BitSet", 128, bs.size());
+        assertEquals("Failed to grow BitSet", 64, bs.size());
         for (int i = 0; i < 7; i++)
             assertTrue("Shouldn't have flipped bit " + i, !bs.get(i));
         assertTrue("Failed to flip bit 7", !bs.get(7));
diff --git a/luni/src/test/java/tests/api/java/util/FormatterTest.java b/luni/src/test/java/tests/api/java/util/FormatterTest.java
index 636f1bd..b2030c9 100644
--- a/luni/src/test/java/tests/api/java/util/FormatterTest.java
+++ b/luni/src/test/java/tests/api/java/util/FormatterTest.java
@@ -4705,7 +4705,7 @@
         bw.close();
 
         readOnly = File.createTempFile("readonly", null);
-        readOnly.setReadOnly();
+        assertTrue(readOnly.setReadOnly());
 
         secret = File.createTempFile("secret", null);
         
diff --git a/luni/src/test/java/tests/api/java/util/TreeMapTest.java b/luni/src/test/java/tests/api/java/util/TreeMapTest.java
index 7ea4c9e..0e7f6a1 100644
--- a/luni/src/test/java/tests/api/java/util/TreeMapTest.java
+++ b/luni/src/test/java/tests/api/java/util/TreeMapTest.java
@@ -83,6 +83,9 @@
             if (null == o1) {
                 return -1;
             }
+            if (null == o2) {
+                return 1;
+            }
             return o1.compareTo(o2);
         }
     }
@@ -844,8 +847,6 @@
         method = "equals",
         args = {java.lang.Object.class}
     )
-    @KnownFailure("equals(Onject o) method throws java.lang.ClassCastException " +
-            "for TreeMap objects with different key objects.")
     public void test_equals() throws Exception {
         // comparing TreeMaps with different object types
         Map m1 = new TreeMap();
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
index ddd56e5..ac8f77b 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
@@ -15,14 +15,13 @@
  *  limitations under the License.
  */
 
-/*
- * Android Notice 
- * In this class the address length was changed from long to int.
- * This is due to performance optimizations for the device.
- */
-
 package org.apache.harmony.nio.internal;
 
+// BEGIN android-note
+// Copied from a newer version of Harmony.
+// In this class the address length was changed from long to int.
+// END android-note
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InterruptedIOException;
@@ -43,7 +42,7 @@
 import java.nio.channels.spi.SelectorProvider;
 
 import org.apache.harmony.luni.net.NetUtil;
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainDatagramSocketImpl;
 import org.apache.harmony.luni.platform.FileDescriptorHandler;
 import org.apache.harmony.luni.platform.INetworkSystem;
 import org.apache.harmony.luni.platform.Platform;
@@ -52,15 +51,10 @@
 
 /*
  * The default implementation class of java.nio.channels.DatagramChannel.
- * 
  */
 class DatagramChannelImpl extends DatagramChannel implements
         FileDescriptorHandler {
 
-    // -------------------------------------------------------------------
-    // Class variables
-    // -------------------------------------------------------------------
-
     // The singleton to do the native network operation.
     private static final INetworkSystem networkSystem = Platform
             .getNetworkSystem();
@@ -72,10 +66,6 @@
     
     private static final byte[] stubArray = new byte[0];
 
-    // -------------------------------------------------------------------
-    // Instance variables
-    // -------------------------------------------------------------------
-
     // The fd to interact with native code
     private FileDescriptor fd;
 
@@ -94,19 +84,17 @@
     // whether the socket is bound
     boolean isBound = false;
 
-    private final Object readLock = new Object();
+    private static class ReadLock {}
+    private final Object readLock = new ReadLock();
 
-    private final Object writeLock = new Object();
+    private static class WriteLock {}
+    private final Object writeLock = new WriteLock();
 
     // used to store the trafficClass value which is simply returned
     // as the value that was set. We also need it to pass it to methods
     // that specify an address packets are going to be sent to
     private int trafficClass = 0;
 
-    // -------------------------------------------------------------------
-    // Constructor
-    // -------------------------------------------------------------------
-
     /*
      * Constructor
      */
@@ -120,16 +108,13 @@
     /*
      * for native call
      */
-    private DatagramChannelImpl(){
+    @SuppressWarnings("unused")
+    private DatagramChannelImpl() {
         super(SelectorProvider.provider());
         fd = new FileDescriptor();
         connectAddress = new InetSocketAddress(0);
     }
 
-    // -------------------------------------------------------------------
-    // Methods for getting internal DatagramSocket.
-    // -------------------------------------------------------------------
-
     /*
      * Getting the internal DatagramSocket If we have not the socket, we create
      * a new one.
@@ -137,8 +122,8 @@
     @Override
     synchronized public DatagramSocket socket() {
         if (null == socket) {
-            socket = new DatagramSocketAdapter(SocketImplProvider
-                    .getDatagramSocketImpl(fd, localPort), this);
+            socket = new DatagramSocketAdapter(
+                    new PlainDatagramSocketImpl(fd, localPort), this);
         }
         return socket;
     }
@@ -155,12 +140,7 @@
                 .preferIPv6Addresses());
     }
 
-    // -------------------------------------------------------------------
-    // Methods for connect and disconnect
-    // -------------------------------------------------------------------
-
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#isConnected()
      */
     @Override
@@ -168,8 +148,7 @@
         return connected;
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#connect(java.net.SocketAddress)
      */
     @Override
@@ -214,8 +193,7 @@
         return this;
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#disconnect()
      */
     @Override
@@ -232,12 +210,7 @@
         return this;
     }
 
-    // -------------------------------------------------------------------
-    // Methods for send and receive
-    // -------------------------------------------------------------------
-
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#receive(java.nio.ByteBuffer)
      */
     @Override
@@ -284,14 +257,15 @@
                     .position()
                     + target.arrayOffset(), target.remaining());
         } else {        
-            receivePacket = new DatagramPacket(new byte[target.remaining()], target.remaining());
+            receivePacket = new DatagramPacket(new byte[target.remaining()],
+                    target.remaining());
         }
         do {
             if (isConnected()) {
-                received = networkSystem.recvConnectedDatagram(fd, receivePacket,
-                        receivePacket.getData(), receivePacket.getOffset(),
-                        receivePacket.getLength(), isBlocking() ? 0
-                                : DEFAULT_TIMEOUT, false);
+                received = networkSystem.recvConnectedDatagram(fd,
+                        receivePacket, receivePacket.getData(), receivePacket
+                                .getOffset(), receivePacket.getLength(),
+                        isBlocking() ? 0 : DEFAULT_TIMEOUT, false);
             } else {
                 received = networkSystem.receiveDatagram(fd, receivePacket,
                         receivePacket.getData(), receivePacket.getOffset(),
@@ -327,24 +301,23 @@
         return retAddr;
     }
     
-    private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop) throws IOException
-    {
-        SocketAddress retAddr = null;  
-        DatagramPacket receivePacket = new DatagramPacket(
-                stubArray, 0);
+    private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop)
+            throws IOException {
+        SocketAddress retAddr = null;
+        DatagramPacket receivePacket = new DatagramPacket(stubArray, 0);
         int oldposition = target.position();
         int received = 0;
         do {
             int address = AddressUtil.getDirectBufferAddress(target);
             if (isConnected()) {
-                received = networkSystem.recvConnectedDatagramDirect(fd, receivePacket,
-                        address, target.position(),
-                        target.remaining(), isBlocking() ? 0
+                received = networkSystem.recvConnectedDatagramDirect(fd,
+                        receivePacket, address, target.position(), target
+                                .remaining(), isBlocking() ? 0
                                 : DEFAULT_TIMEOUT, false);
             } else {
-                received = networkSystem.receiveDatagramDirect(fd, receivePacket,
-                        address, target.position(),
-                        target.remaining(), isBlocking() ? 0
+                received = networkSystem.receiveDatagramDirect(fd,
+                        receivePacket, address, target.position(), target
+                                .remaining(), isBlocking() ? 0
                                 : DEFAULT_TIMEOUT, false);
             }
 
@@ -352,15 +325,14 @@
             SecurityManager sm = System.getSecurityManager();
             if (!isConnected() && null != sm) {
                 try {
-                    sm.checkAccept(receivePacket.getAddress()
-                            .getHostAddress(), receivePacket.getPort());
+                    sm.checkAccept(receivePacket.getAddress().getHostAddress(),
+                            receivePacket.getPort());
                 } catch (SecurityException e) {
                     // do discard the datagram packet
                     receivePacket = null;
                 }
             }
-            if (null != receivePacket
-                    && null != receivePacket.getAddress()) {
+            if (null != receivePacket && null != receivePacket.getAddress()) {
                 // copy the data of received packet
                 if (received > 0) {
                     target.position(oldposition + received);
@@ -372,7 +344,7 @@
         return retAddr;
     }
 
-    /*
+    /**
      * @see java.nio.channels.DatagramChannel#send(java.nio.ByteBuffer,
      *      java.net.SocketAddress)
      */
@@ -445,12 +417,7 @@
         }
     }
 
-    // -------------------------------------------------------------------
-    // Methods for read and write.
-    // -------------------------------------------------------------------
-
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer)
      */
     @Override
@@ -467,10 +434,10 @@
             return 0;
         }
 
-        int readCount  = 0;
+        int readCount = 0;
         if (target.isDirect() || target.hasArray()) {
             readCount = readImpl(target);
-            if(readCount > 0){
+            if (readCount > 0) {
                 target.position(target.position() + readCount);
             }
 
@@ -478,15 +445,14 @@
             byte[] readArray = new byte[target.remaining()];
             ByteBuffer readBuffer = ByteBuffer.wrap(readArray);
             readCount = readImpl(readBuffer);
-            if(readCount > 0){
+            if (readCount > 0) {
                 target.put(readArray, 0, readCount);
             }
         }
         return readCount;
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer[], int,
      *      int)
      */
@@ -530,7 +496,7 @@
      * read from channel, and store the result in the target.
      */
     private int readImpl(ByteBuffer readBuffer) throws IOException {
-        synchronized(readLock){
+        synchronized (readLock) {
             int readCount = 0;
             try {
                 begin();
@@ -542,8 +508,9 @@
                 if (readBuffer.isDirect()) {
                     int address = AddressUtil.getDirectBufferAddress(readBuffer);
                     if (isConnected()) {
-                        readCount = networkSystem.recvConnectedDatagramDirect(fd,
-                                null, address, start, length, timeout, false);
+                        readCount = networkSystem.recvConnectedDatagramDirect(
+                                fd, null, address, start, length, timeout,
+                                false);
                     } else {
                         readCount = networkSystem.receiveDatagramDirect(fd,
                                 null, address, start, length, timeout, false);
@@ -553,11 +520,11 @@
                     byte[] target = readBuffer.array();
                     start += readBuffer.arrayOffset();
                     if (isConnected()) {
-                        readCount = networkSystem.recvConnectedDatagram(fd, null,
-                                target, start, length, timeout, false);
+                        readCount = networkSystem.recvConnectedDatagram(fd,
+                                null, target, start, length, timeout, false);
                     } else {
-                        readCount = networkSystem.receiveDatagram(fd, null, target,
-                                start, length, timeout, false);
+                        readCount = networkSystem.receiveDatagram(fd, null,
+                                target, start, length, timeout, false);
                     }
                 }
                 return readCount;
@@ -570,7 +537,7 @@
         }
     }
 
-    /*
+    /**
      * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer)
      */
     @Override
@@ -602,7 +569,7 @@
         return result;
     }
 
-    /*
+    /**
      * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer[], int,
      *      int)
      */
@@ -621,7 +588,7 @@
             return 0;
         }
         ByteBuffer writeBuf = ByteBuffer.allocate(count);
-        for (int val = offset; val < length+offset; val++) {
+        for (int val = offset; val < length + offset; val++) {
             ByteBuffer source = sources[val];
             int oldPosition = source.position();
             writeBuf.put(source);
@@ -642,10 +609,10 @@
     }
 
     /*
-     * write the source. return the count of bytes written.
+     * Write the source. Return the count of bytes written.
      */
     private int writeImpl(ByteBuffer buf) throws IOException {
-        synchronized(writeLock){
+        synchronized (writeLock) {
             int result = 0;
             try {
                 begin();
@@ -654,13 +621,13 @@
     
                 if (buf.isDirect()) {
                     int address = AddressUtil.getDirectBufferAddress(buf);
-                    result = networkSystem.sendConnectedDatagramDirect(fd, address,
-                            start, length, isBound);
+                    result = networkSystem.sendConnectedDatagramDirect(fd,
+                            address, start, length, isBound);
                 } else {
                     // buf is assured to have array.
                     start += buf.arrayOffset();
-                    result = networkSystem.sendConnectedDatagram(fd, buf.array(),
-                            start, length, isBound);
+                    result = networkSystem.sendConnectedDatagram(fd, buf
+                            .array(), start, length, isBound);
                 }
                 return result;
             } catch (SocketException e) {
@@ -677,12 +644,8 @@
         }
     }
 
-    // -------------------------------------------------------------------
-    // Protected Inherited methods
-    // -------------------------------------------------------------------
-
     /*
-     * do really closing action here
+     * Do really closing action here.
      */
     @Override
     synchronized protected void implCloseSelectableChannel() throws IOException {
@@ -694,8 +657,7 @@
         }
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean)
      */
     @Override
@@ -707,12 +669,8 @@
         // decided by isBlocking() method.
     }
 
-    // -------------------------------------------------------------------
-    // Share methods for checking.
-    // -------------------------------------------------------------------
-
     /*
-     * status check, must be open.
+     * Status check, must be open.
      */
     private void checkOpen() throws IOException {
         if (!isOpen()) {
@@ -721,7 +679,7 @@
     }
 
     /*
-     * status check, must be open and connected, for read and write.
+     * Status check, must be open and connected, for read and write.
      */
     private void checkOpenConnected() throws IOException {
         checkOpen();
@@ -731,7 +689,7 @@
     }
 
     /*
-     * buffer check, must not null
+     * Buffer check, must not null
      */
     private void checkNotNull(ByteBuffer source) {
         if (null == source) {
@@ -740,7 +698,7 @@
     }
 
     /*
-     * buffer check, must not null and not read only buffer, for read and
+     * Buffer check, must not null and not read only buffer, for read and
      * receive.
      */
     private void checkWritable(ByteBuffer target) {
@@ -750,12 +708,8 @@
         }
     }
 
-    // -------------------------------------------------------------------
-    // Adapter classes for internal socket.
-    // -------------------------------------------------------------------
-
     /*
-     * get the fd for internal use.
+     * Get the fd for internal use.
      */
     public FileDescriptor getFD() {
         return fd;
@@ -781,7 +735,7 @@
         private DatagramChannelImpl channelImpl;
 
         /*
-         * init the datagramSocketImpl and datagramChannelImpl
+         * Constructor initialize the datagramSocketImpl and datagramChannelImpl
          */
         DatagramSocketAdapter(DatagramSocketImpl socketimpl,
                 DatagramChannelImpl channelImpl) {
@@ -790,14 +744,14 @@
         }
 
         /*
-         * get the internal datagramChannelImpl
+         * Get the internal datagramChannelImpl
          */
         @Override
         public DatagramChannel getChannel() {
             return channelImpl;
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#isBound()
          */
         @Override
@@ -805,7 +759,7 @@
             return channelImpl.isBound;
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#isConnected()
          */
         @Override
@@ -813,7 +767,7 @@
             return channelImpl.isConnected();
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#getInetAddress()
          */
         @Override
@@ -824,7 +778,7 @@
             return channelImpl.connectAddress.getAddress();
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#getLocalAddress()
          */
         @Override
@@ -832,7 +786,7 @@
             return channelImpl.getLocalAddress();
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#getPort()
          */
         @Override
@@ -843,7 +797,7 @@
             return channelImpl.connectAddress.getPort();
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#bind(java.net.SocketAddress)
          */
         @Override
@@ -855,7 +809,7 @@
             channelImpl.isBound = true;
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#receive(java.net.DatagramPacket)
          */
         @Override
@@ -866,7 +820,7 @@
             super.receive(packet);
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#send(java.net.DatagramPacket)
          */
         @Override
@@ -877,7 +831,7 @@
             super.send(packet);
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#close()
          */
         @Override
@@ -894,7 +848,7 @@
             }
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#disconnect()
          */
         @Override
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
index 3bc368f..dbef656 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
@@ -17,6 +17,10 @@
 
 package org.apache.harmony.nio.internal;
 
+// BEGIN android-note
+// Copied from a newer version of Harmony.
+// END android-note
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.net.ServerSocket;
@@ -27,13 +31,12 @@
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.IllegalBlockingModeException;
 import java.nio.channels.NotYetBoundException;
-import java.nio.channels.SelectableChannel;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 import java.nio.channels.spi.SelectorProvider;
 
 import org.apache.harmony.luni.net.NetUtil;
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainServerSocketImpl;
 import org.apache.harmony.luni.platform.FileDescriptorHandler;
 import org.apache.harmony.luni.platform.Platform;
 
@@ -43,10 +46,6 @@
 public class ServerSocketChannelImpl extends ServerSocketChannel implements
         FileDescriptorHandler {
 
-    // ----------------------------------------------------
-    // Class variables
-    // ----------------------------------------------------
-
     // status un-init, not initialized.
     private static final int SERVER_STATUS_UNINIT = -1;
 
@@ -56,10 +55,6 @@
     // status closed.
     private static final int SERVER_STATUS_CLOSED = 1;
 
-    // -------------------------------------------------------------------
-    // Instance variables
-    // -------------------------------------------------------------------
-
     // The fd to interact with native code
     private final FileDescriptor fd;
 
@@ -74,13 +69,9 @@
     boolean isBound = false;
 
     // lock for accept
-    private class AcceptLock {}
+    private static class AcceptLock {}
     private final Object acceptLock = new AcceptLock();
 
-    // ----------------------------------------------------
-    // Constructor
-    // ----------------------------------------------------
-
     /*
      * Constructor
      */
@@ -88,26 +79,23 @@
         super(sp);
         status = SERVER_STATUS_OPEN;
         fd = new FileDescriptor();
-        Platform.getNetworkSystem().createServerStreamSocket(fd,
+        Platform.getNetworkSystem().createStreamSocket(fd,
                 NetUtil.preferIPv4Stack());
-        impl = SocketImplProvider.getServerSocketImpl(fd);
+        impl = new PlainServerSocketImpl(fd);
         socket = new ServerSocketAdapter(impl, this);
     }
     
     // for native call
+    @SuppressWarnings("unused")
     private ServerSocketChannelImpl() throws IOException {
         super(SelectorProvider.provider());
         status = SERVER_STATUS_OPEN;
         fd = new FileDescriptor();
-        impl = SocketImplProvider.getServerSocketImpl(fd);        
+        impl = new PlainServerSocketImpl(fd);
         socket = new ServerSocketAdapter(impl, this);
         isBound = false;
     }
 
-    // ----------------------------------------------------
-    // Methods
-    // ----------------------------------------------------
-
     /*
      * Getting the internal Socket If we have not the socket, we create a new
      * one.
@@ -128,7 +116,7 @@
             throw new NotYetBoundException();
         }
 
-        SocketChannel sockChannel = SocketChannel.open();
+        SocketChannel sockChannel = new SocketChannelImpl(SelectorProvider.provider(), false);
         Socket socketGot = sockChannel.socket();
 
         try {
@@ -168,10 +156,6 @@
         return sockChannel;
     }
 
-    // -------------------------------------------------------------------
-    // Protected inherited methods
-    // -------------------------------------------------------------------
-
     /*
      * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking
      * 
@@ -202,10 +186,6 @@
         return fd;
     }
 
-    // ----------------------------------------------------
-    // Adapter classes.
-    // ----------------------------------------------------
-
     /*
      * The adapter class of ServerSocket.
      */
@@ -264,10 +244,7 @@
                 synchronized (this) {
                     super.implAccept(aSocket);
                     sockChannel.setConnected();
-                    // BEGIN android-added
-                    // copied from a newer version of harmony
                     sockChannel.setBound(true);
-                    // END android-added
                 }
                 SecurityManager sm = System.getSecurityManager();
                 if (sm != null) {
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
index 8e6c52f..1affb21 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
@@ -17,6 +17,11 @@
 
 package org.apache.harmony.nio.internal;
 
+// BEGIN android-note
+// Copied from a newer version of Harmony.
+// In this class the address length was changed from long to int.
+// END android-note
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
@@ -42,25 +47,20 @@
 import java.nio.channels.UnsupportedAddressTypeException;
 import java.nio.channels.spi.SelectorProvider;
 
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainSocketImpl;
 import org.apache.harmony.luni.platform.FileDescriptorHandler;
 import org.apache.harmony.luni.platform.INetworkSystem;
 import org.apache.harmony.luni.platform.Platform;
 import org.apache.harmony.luni.util.ErrorCodeException;
+import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.nio.AddressUtil;
 import org.apache.harmony.nio.internal.nls.Messages;
 
 /*
- * 
  * The default implementation class of java.nio.channels.SocketChannel.
- * 
  */
 class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler {
 
-    // -------------------------------------------------------------------
-    // Class variables
-    // -------------------------------------------------------------------
-
     private static final int EOF = -1;
 
     private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211;
@@ -68,41 +68,37 @@
     // The singleton to do the native network operation.
     static final INetworkSystem networkSystem = Platform.getNetworkSystem();
 
-    // status un-init, not initialized.
+    // Status un-init, not initialized.
     static final int SOCKET_STATUS_UNINIT = EOF;
 
-    // status before connect.
+    // Status before connect.
     static final int SOCKET_STATUS_UNCONNECTED = 0;
 
-    // status connection pending
+    // Status connection pending.
     static final int SOCKET_STATUS_PENDING = 1;
 
-    // status after connection success
+    // Status after connection success.
     static final int SOCKET_STATUS_CONNECTED = 2;
 
-    // status closed.
+    // Status closed.
     static final int SOCKET_STATUS_CLOSED = 3;
 
-    // timeout used for non-block mode.
+    // Timeout used for non-block mode.
     private static final int TIMEOUT_NONBLOCK = 0;
 
-    // timeout used for block mode.
+    // Timeout used for block mode.
     private static final int TIMEOUT_BLOCK = EOF;
 
-    // step used for connect
+    // Step used for connect.
     private static final int HY_SOCK_STEP_START = 0;
 
-    // step used for finishConnect
+    // Step used for finishConnect.
     private static final int HY_PORT_SOCKET_STEP_CHECK = 1;
 
-    // connect success
+    // Connect success.
     private static final int CONNECT_SUCCESS = 0;
 
-    // -------------------------------------------------------------------
-    // Instance Variables
-    // -------------------------------------------------------------------
-
-    // The fd to interact with native code
+    // The descriptor to interact with native code.
     FileDescriptor fd;
 
     // Our internal Socket.
@@ -111,24 +107,23 @@
     // The address to be connected.
     InetSocketAddress connectAddress = null;
 
-    // Local address of the this socket (package private for adapter)
+    // Local address of the this socket (package private for adapter).
     InetAddress localAddress = null;
 
-    // local port
+    // Local port number.
     int localPort;
 
     // At first, uninitialized.
     int status = SOCKET_STATUS_UNINIT;
 
-    // BEGIN android-changed
-    // copied from a newer version of harmony
-    // whether the socket is bound
+    // Whether the socket is bound.
     volatile boolean isBound = false;
-    // END adroid-changed
 
-    private final Object readLock = new Object();
+    private static class ReadLock {}
+    private final Object readLock = new ReadLock();
 
-    private final Object writeLock = new Object();
+    private static class WriteLock {}
+    private final Object writeLock = new WriteLock();
 
     // BEGIN android-changed
     // this content is a struct used in connect_withtimeout().
@@ -136,30 +131,37 @@
     private byte[] connectContext = new byte[392];
     // END android-changed
 
-    // used to store the trafficClass value which is simply returned
+    // Used to store the trafficClass value which is simply returned
     // as the value that was set. We also need it to pass it to methods
-    // that specify an address packets are going to be sent to
+    // that specify an address packets are going to be sent to.
     private int trafficClass = 0;
 
-    // -------------------------------------------------------------------
-    // Constructor
-    // -------------------------------------------------------------------
-
     /*
-     * Constructor
+     * Constructor for creating a connected socket channel.
      */
     public SocketChannelImpl(SelectorProvider selectorProvider)
             throws IOException {
+        this(selectorProvider, true);
+    }
+
+    /*
+     * Constructor for creating an optionally connected socket channel.
+     */
+    public SocketChannelImpl(SelectorProvider selectorProvider, boolean connect)
+            throws IOException {
         super(selectorProvider);
         fd = new FileDescriptor();
         status = SOCKET_STATUS_UNCONNECTED;
-        networkSystem.createSocket(fd, true);
+        if (connect) {
+            networkSystem.createStreamSocket(fd, true);
+        }
     }
 
     /*
-     * for native call
+     * For native call.
      */
-    private SocketChannelImpl(){
+    @SuppressWarnings("unused")
+    private SocketChannelImpl() {
         super(SelectorProvider.provider());
         fd = new FileDescriptor();
         connectAddress = new InetSocketAddress(0);
@@ -186,10 +188,6 @@
         status = SOCKET_STATUS_UNCONNECTED;
     }
 
-    // -------------------------------------------------------------------
-    // Methods for getting internal Socket.
-    // -------------------------------------------------------------------
-
     /*
      * Getting the internal Socket If we have not the socket, we create a new
      * one.
@@ -204,8 +202,8 @@
                     addr = connectAddress.getAddress();
                     port = connectAddress.getPort();
                 }
-                socket = new SocketAdapter(SocketImplProvider.getSocketImpl(fd,
-                        localPort, addr, port), this);
+                socket = new SocketAdapter(
+                        new PlainSocketImpl(fd, localPort, addr, port), this);
             } catch (SocketException e) {
                 return null;
             }
@@ -213,11 +211,7 @@
         return socket;
     }
 
-    // -------------------------------------------------------------------
-    // Methods for connect and finishConnect
-    // -------------------------------------------------------------------
-
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#isConnected()
      */
     @Override
@@ -226,20 +220,17 @@
     }
 
     /*
-     * status setting used by other class.
+     * Status setting used by other class.
      */
     synchronized void setConnected() {
         status = SOCKET_STATUS_CONNECTED;
     }
 
-    // BEGIN android-added
-    // copied from a newer version of harmony
     void setBound(boolean flag) {
         isBound = flag;
     }
-    // END android-added
 
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#isConnectionPending()
      */
     @Override
@@ -247,7 +238,7 @@
         return status == SOCKET_STATUS_PENDING;
     }
 
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#connect(java.net.SocketAddress)
      */
     @Override
@@ -257,9 +248,15 @@
 
         // check the address
         InetSocketAddress inetSocketAddress = validateAddress(socketAddress);
+        InetAddress normalAddr = inetSocketAddress.getAddress();
+
+        // When connecting, map ANY address to Localhost
+        if (normalAddr.isAnyLocalAddress()) {
+            normalAddr = InetAddress.getLocalHost();
+        }
 
         int port = inetSocketAddress.getPort();
-        String hostName = inetSocketAddress.getAddress().getHostName();
+        String hostName = normalAddr.getHostName();
         // security check
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -271,23 +268,12 @@
         boolean finished = false;
 
         try {
-            if (!isBound) {
-                // bind
-                networkSystem.bind2(fd, 0, true, InetAddress
-                        .getByAddress(new byte[] { 0, 0, 0, 0 }));
-                isBound = true;
-            }
-
             if (isBlocking()) {
                 begin();
-                result = networkSystem.connect(fd, trafficClass,
-                        inetSocketAddress.getAddress(), inetSocketAddress
-                                .getPort());
-
+                result = networkSystem.connect(fd, trafficClass, normalAddr, port);
             } else {
                 result = networkSystem.connectWithTimeout(fd, 0, trafficClass,
-                        inetSocketAddress.getAddress(), inetSocketAddress
-                                .getPort(), HY_SOCK_STEP_START, connectContext);
+                        normalAddr, port, HY_SOCK_STEP_START, connectContext);
                 // set back to nonblocking to work around with a bug in portlib
                 if (!this.isBlocking()) {
                     networkSystem.setNonBlocking(fd, true);
@@ -328,7 +314,7 @@
         return finished;
     }
 
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#finishConnect()
      */
     @Override
@@ -372,14 +358,13 @@
         synchronized (this) {
             status = (finished ? SOCKET_STATUS_CONNECTED : status);
             isBound = finished;
+            // TPE: Workaround for bug that turns socket back to blocking
+            if (!isBlocking()) implConfigureBlocking(false);
         }
         return finished;
     }
 
-    // -------------------------------------------------------------------
-    // Methods for read and write
-    // -------------------------------------------------------------------
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer)
      */
     @Override
@@ -411,7 +396,7 @@
         return readCount;
     }
 
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer[], int,
      *      int)
      */
@@ -449,16 +434,17 @@
 
     private boolean isIndexValid(ByteBuffer[] targets, int offset, int length) {
         return (length >= 0) && (offset >= 0)
-                && ((long)length + (long)offset <= targets.length);
+                && ((long) length + (long) offset <= targets.length);
     }
 
-    /*
-     * read from channel, and store the result in the target.
+    /**
+     * Read from channel, and store the result in the target.
      * 
-     * @param target output parameter
+     * @param target
+     *            output parameter
      */
     private int readImpl(ByteBuffer target) throws IOException {
-        synchronized(readLock){
+        synchronized (readLock) {
             int readCount = 0;
             try {
                 if (isBlocking()) {
@@ -467,10 +453,13 @@
                 int offset = target.position();
                 int length = target.remaining();
                 if (target.isDirect()) {
+                    // BEGIN android-changed
+                    // changed address from long to int; split address and offset paramters
                     int address = AddressUtil.getDirectBufferAddress(target);
                     readCount = networkSystem.readDirect(fd, address, offset,
                             length, (isBlocking() ? TIMEOUT_BLOCK
                                     : TIMEOUT_NONBLOCK));
+                    // END android-changed
                 } else {
                     // target is assured to have array.
                     byte[] array = target.array();
@@ -487,8 +476,7 @@
         }
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer)
      */
     @Override
@@ -503,7 +491,7 @@
         return writeImpl(source);
     }
 
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer[], int,
      *      int)
      */
@@ -520,7 +508,7 @@
             return 0;
         }
         ByteBuffer writeBuf = ByteBuffer.allocate(count);
-        for (int val = offset; val < length+offset; val++) {
+        for (int val = offset; val < length + offset; val++) {
             ByteBuffer source = sources[val];
             int oldPosition = source.position();
             writeBuf.put(source);
@@ -550,10 +538,10 @@
     }
 
     /*
-     * write the source. return the count of bytes written.
+     * Write the source. return the count of bytes written.
      */
     private int writeImpl(ByteBuffer source) throws IOException {
-        synchronized(writeLock){
+        synchronized (writeLock) {
             if (!source.hasRemaining()) {
                 return 0;
             }
@@ -565,9 +553,12 @@
                     begin();
                 }
                 if (source.isDirect()) {
+                    // BEGIN android-changed
+                    // changed address from long to int; split address and pos parameters
                     int address = AddressUtil.getDirectBufferAddress(source);
-                    writeCount = networkSystem
-                            .writeDirect(fd, address, pos, length);
+                    writeCount = networkSystem.writeDirect(fd, address, pos,
+                            length);
+                    // END android-changed
                 } else if (source.hasArray()) {
                     pos += source.arrayOffset();
                     writeCount = networkSystem.write(fd, source.array(), pos,
@@ -595,12 +586,8 @@
         }
     }
 
-    // -------------------------------------------------------------------
-    // Shared methods
-    // -------------------------------------------------------------------
-
     /*
-     * status check, open and "connected", when read and write.
+     * Status check, open and "connected", when read and write.
      */
     synchronized private void checkOpenConnected()
             throws ClosedChannelException {
@@ -613,7 +600,7 @@
     }
 
     /*
-     * status check, open and "unconnected", before connection.
+     * Status check, open and "unconnected", before connection.
      */
     synchronized private void checkUnconnected() throws IOException {
         if (!isOpen()) {
@@ -628,7 +615,7 @@
     }
 
     /*
-     * shared by this class and DatagramChannelImpl, to do the address transfer
+     * Shared by this class and DatagramChannelImpl, to do the address transfer
      * and check.
      */
     static InetSocketAddress validateAddress(SocketAddress socketAddress) {
@@ -646,7 +633,7 @@
     }
 
     /*
-     * get local address
+     * Get local address.
      */
     public InetAddress getLocalAddress() throws UnknownHostException {
         byte[] any_bytes = { 0, 0, 0, 0 };
@@ -656,11 +643,8 @@
         return localAddress;
     }
 
-    // -------------------------------------------------------------------
-    // Protected inherited methods
-    // -------------------------------------------------------------------
     /*
-     * do really closing action here
+     * Do really closing action here.
      */
     @Override
     synchronized protected void implCloseSelectableChannel() throws IOException {
@@ -674,7 +658,7 @@
         }
     }
 
-    /*
+    /**
      * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean)
      */
     @Override
@@ -685,30 +669,21 @@
     }
 
     /*
-     * get the fd
+     * Get the fd.
      */
     public FileDescriptor getFD() {
         return fd;
     }
 
-    // -------------------------------------------------------------------
-    // Adapter classes for internal socket.
-    // -------------------------------------------------------------------
-
+    /*
+     * Adapter classes for internal socket.
+     */
     private static class SocketAdapter extends Socket {
 
-        // ----------------------------------------------------
-        // Class Variables
-        // ----------------------------------------------------
-
         SocketChannelImpl channel;
 
         SocketImpl socketImpl;
 
-        // ----------------------------------------------------
-        // Methods
-        // ----------------------------------------------------
-
         SocketAdapter(SocketImpl socketimpl, SocketChannelImpl channel)
                 throws SocketException {
             super(socketimpl);
@@ -716,8 +691,7 @@
             this.channel = channel;
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getChannel()
          */
         @Override
@@ -725,8 +699,7 @@
             return channel;
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#isBound()
          */
         @Override
@@ -734,8 +707,7 @@
             return channel.isBound;
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#isConnected()
          */
         @Override
@@ -743,8 +715,7 @@
             return channel.isConnected();
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getLocalAddress()
          */
         @Override
@@ -756,8 +727,7 @@
             }
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#connect(java.net.SocketAddress, int)
          */
         @Override
@@ -778,8 +748,7 @@
             }
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#bind(java.net.SocketAddress)
          */
         @Override
@@ -798,8 +767,7 @@
 
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#close()
          */
         @Override
@@ -849,8 +817,7 @@
                     .intValue();
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getKeepAlive()
          */
         @Override
@@ -860,8 +827,7 @@
                     .booleanValue();
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getOOBInline()
          */
         @Override
@@ -871,8 +837,7 @@
                     .booleanValue();
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getSoLinger()
          */
         @Override
@@ -882,7 +847,7 @@
                     .intValue();
         }
 
-        /*
+        /**
          * @see java.net.Socket#getTcpNoDelay()
          */
         @Override
@@ -892,7 +857,82 @@
                     .booleanValue();
         }
 
-        /*
+        @Override
+        public void setKeepAlive(boolean value) throws SocketException {
+            checkOpen();
+            socketImpl.setOption(SocketOptions.SO_KEEPALIVE, value ? Boolean.TRUE
+                    : Boolean.FALSE);
+        }
+
+        @Override
+        public void setOOBInline(boolean oobinline) throws SocketException {
+            checkOpen();
+            socketImpl.setOption(SocketOptions.SO_OOBINLINE, oobinline ? Boolean.TRUE
+                    : Boolean.FALSE);
+        }
+
+        @Override
+        public synchronized void setReceiveBufferSize(int size)
+                throws SocketException {
+            checkOpen();
+            if (size < 1) {
+                throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$
+            }
+            socketImpl
+                    .setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
+        }
+
+        @Override
+        public void setReuseAddress(boolean reuse) throws SocketException {
+            checkOpen();
+            socketImpl.setOption(SocketOptions.SO_REUSEADDR, reuse ? Boolean.TRUE
+                    : Boolean.FALSE);
+        }
+
+        @Override
+        public synchronized void setSendBufferSize(int size) throws SocketException {
+            checkOpen();
+            if (size < 1) {
+                throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$
+            }
+            socketImpl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
+        }
+
+        @Override
+        public void setSoLinger(boolean on, int timeout) throws SocketException {
+            checkOpen();
+            if (on && timeout < 0) {
+                throw new IllegalArgumentException(Msg.getString("K0045")); //$NON-NLS-1$
+            }
+            int val = on ? (65535 < timeout ? 65535 : timeout) : -1;
+            socketImpl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(val));
+        }
+
+        @Override
+        public synchronized void setSoTimeout(int timeout) throws SocketException {
+            checkOpen();
+            if (timeout < 0) {
+                throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$
+            }
+            socketImpl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
+        }
+
+        @Override
+        public void setTcpNoDelay(boolean on) throws SocketException {
+            checkOpen();
+            socketImpl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
+        }
+
+        @Override
+        public void setTrafficClass(int value) throws SocketException {
+            checkOpen();
+            if (value < 0 || value > 255) {
+                throw new IllegalArgumentException();
+            }
+            socketImpl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value));
+        }
+
+        /**
          * @see java.net.Socket#getOutputStream()
          */
         @Override
@@ -912,8 +952,7 @@
             return new SocketChannelOutputStream(channel);
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getInputStream()
          */
         @Override
@@ -934,7 +973,7 @@
         }
 
         /*
-         * Checks whether the channel is open
+         * Checks whether the channel is open.
          */
         private void checkOpen() throws SocketException {
             if (isClosed()) {
@@ -944,7 +983,7 @@
         }
 
         /*
-         * used for net and nio exchange
+         * Used for net and nio exchange.
          */
         public SocketImpl getImpl() {
             return socketImpl;
@@ -964,7 +1003,7 @@
         }
 
         /*
-         * Closes this stream and channel
+         * Closes this stream and channel.
          * 
          * @exception IOException thrown if an error occurs during the close
          */
@@ -973,7 +1012,7 @@
             channel.close();
         }
 
-        /*
+        /**
          * @see java.io.OutputStream#write(byte[], int, int)
          */
         @Override
@@ -989,7 +1028,7 @@
             channel.write(buf);
         }
 
-        /*
+        /**
          * @see java.io.OutputStream#write(int)
          */
         @Override
@@ -1023,7 +1062,7 @@
             channel.close();
         }
 
-        /*
+        /**
          * @see java.io.InputStream#read()
          */
         @Override
@@ -1038,7 +1077,7 @@
             // END android-changed
         }
 
-        /*
+        /**
          * @see java.io.InputStream#read(byte[], int, int)
          */
         @Override
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
index 6bcdaef..903c689 100644
--- a/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
@@ -266,8 +266,6 @@
         method = "charsetForName",
         args = {String.class}
     )
-    @KnownFailure("Android throws Error in case of insufficient privileges, " +
-            "RI throws SecurityException")
     public void testIsSupported_InsufficientPrivilege() throws Exception {
         SecurityManager oldMan = System.getSecurityManager();
         System.setSecurityManager(new MockSecurityManager());
@@ -301,8 +299,6 @@
         method = "charsetForName",
         args = {String.class}
     )
-    @KnownFailure("Android throws Error in case of insufficient privileges, " +
-            "RI throws SecurityException")
     public void testForName_InsufficientPrivilege() throws Exception {
         SecurityManager oldMan = System.getSecurityManager();
         System.setSecurityManager(new MockSecurityManager());
diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java
index dc2ec2e..0c61e75 100644
--- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java
+++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java
@@ -32,15 +32,25 @@
 @TestTargetClass(java.util.prefs.Preferences.class)
 public class FilePreferencesImplTest extends TestCase {
 
-    public FilePreferencesImplTest() {
-        super();
+    String oldUserHome = System.getProperty("user.home");
+    String oldJavaHome = System.getProperty("java.home");
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        System.setProperty("user.home", System.getProperty("java.io.tmpdir"));
+        System.setProperty("java.home", System.getProperty("java.io.tmpdir"));
+        Preferences.systemRoot().clear();
+        Preferences.userRoot().clear();
     }
-    
-    @Override
-    protected void setUp(){
-    }
-    @Override
-    protected void tearDown(){
+
+    protected void tearDown() throws Exception {
+        Preferences.systemRoot().clear();
+        Preferences.userRoot().clear();
+        System.setProperty("user.home", oldUserHome);
+        System.setProperty("java.home", oldJavaHome);
+
+        super.tearDown();
     }
 
     @TestTargets({
diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java
index 3260a04..eab3b14 100644
--- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java
+++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java
@@ -39,6 +39,27 @@
 
     NodeChangeEvent event;
 
+    String oldUserHome = System.getProperty("user.home");
+    String oldJavaHome = System.getProperty("java.home");
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        System.setProperty("user.home", System.getProperty("java.io.tmpdir"));
+        System.setProperty("java.home", System.getProperty("java.io.tmpdir"));
+        Preferences.systemRoot().clear();
+        Preferences.userRoot().clear();
+    }
+
+    protected void tearDown() throws Exception {
+        Preferences.systemRoot().clear();
+        Preferences.userRoot().clear();
+        System.setProperty("user.home", oldUserHome);
+        System.setProperty("java.home", oldJavaHome);
+
+        super.tearDown();
+    }
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java
index 9d526d6..0ebf6bb 100644
--- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java
+++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java
@@ -45,8 +45,8 @@
 @TestTargetClass(Preferences.class)
 public class PreferencesTest extends TestCase {
 
-    private String oldJavaHome;
-    private String oldUserHome;
+    String oldUserHome = System.getProperty("user.home");
+    String oldJavaHome = System.getProperty("java.home");
 
     MockSecurityManager manager = new MockSecurityManager();
 
@@ -81,6 +81,8 @@
                         .getBytes("UTF-8"));
         stream = new MockInputStream(in);
 
+        System.setProperty("user.home", System.getProperty("java.io.tmpdir"));
+        System.setProperty("java.home", System.getProperty("java.io.tmpdir"));
         Preferences.systemRoot().clear();
         Preferences.userRoot().clear();
 
@@ -107,6 +109,8 @@
 
         Preferences.systemRoot().clear();
         Preferences.userRoot().clear();
+        System.setProperty("user.home", oldUserHome);
+        System.setProperty("java.home", oldJavaHome);
     }
 
     @TestTargetNew(
diff --git a/run-core-tests b/run-core-tests
index 62b3c51..70ab320 100755
--- a/run-core-tests
+++ b/run-core-tests
@@ -26,5 +26,5 @@
 chmod 777 $tmp
   
 exec dalvikvm -Duser.language=en -Duser.region=US -Djava.io.tmpdir=$tmp \
-     -Xbootclasspath:$BOOTCLASSPATH:/system/framework/core-tests.jar \
+     -classpath /system/framework/core-tests.jar \
      -Xmx64M com.google.coretests.Main "$@"