am 8673ee75: am 9a35ef1b: Guarantee deflaters get cleaned up, even if subclassed.

Merge commit '8673ee75052e7398aa6f5925e968d6a0b2419be8'

* commit '8673ee75052e7398aa6f5925e968d6a0b2419be8':
  Guarantee deflaters get cleaned up, even if subclassed.
diff --git a/dalvikvm/Android.mk b/dalvikvm/Android.mk
index 216d08e..f463c85 100644
--- a/dalvikvm/Android.mk
+++ b/dalvikvm/Android.mk
@@ -14,20 +14,61 @@
 
 
 LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= \
+#
+# Common definitions.
+#
+
+dalvikvm_src_files := \
     Main.c
 
-LOCAL_C_INCLUDES := \
-	$(JNI_H_INCLUDE) \
-	dalvik/include
+dalvikvm_c_includes := \
+    $(JNI_H_INCLUDE) \
+    dalvik/include
+
+
+#
+# Build for the target (device).
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(dalvikvm_src_files)
+LOCAL_C_INCLUDES := $(dalvikvm_c_includes)
 
 LOCAL_SHARED_LIBRARIES := \
-	libdvm \
-	libssl \
-	libz
+    libdvm \
+    libssl \
+    libz
 
-LOCAL_MODULE:= dalvikvm
+LOCAL_MODULE := dalvikvm
 
 include $(BUILD_EXECUTABLE)
+
+
+#
+# Build for the host.
+#
+
+ifeq ($(WITH_HOST_DALVIK),true)
+
+    include $(CLEAR_VARS)
+
+    LOCAL_SRC_FILES := $(dalvikvm_src_files)
+    LOCAL_C_INCLUDES := $(dalvikvm_c_includes)
+
+    LOCAL_STATIC_LIBRARIES := \
+        libdvm-host
+
+    ifeq ($(HOST_OS)-$(HOST_ARCH),darwin-x86)
+        # OSX comes with libz and libssl, so there is no need to build them.
+        LOCAL_LDLIBS := -lssl -lz
+    else
+        LOCAL_STATIC_LIBRARIES += libssl libz
+    endif
+
+    LOCAL_MODULE := dalvikvm-host
+
+    include $(BUILD_HOST_EXECUTABLE)
+
+endif
diff --git a/dexopt/Android.mk b/dexopt/Android.mk
index 8e30a2c..8637073 100644
--- a/dexopt/Android.mk
+++ b/dexopt/Android.mk
@@ -29,6 +29,8 @@
 		$(JNI_H_INCLUDE)
 
 LOCAL_SHARED_LIBRARIES := \
+		libcutils \
+		liblog \
 		libz \
 		libssl \
 		libdvm
diff --git a/docs/jni-tips.html b/docs/jni-tips.html
index e85434b..56136e8 100644
--- a/docs/jni-tips.html
+++ b/docs/jni-tips.html
@@ -356,7 +356,7 @@
     <li>MonitorExit
     <li>PopLocalFrame
     <li>PushLocalFrame
-    <li>Release<PrimitiveType>ArrayElements
+    <li>Release&lt;PrimitiveType&gt;ArrayElements
     <li>ReleasePrimitiveArrayCritical
     <li>ReleaseStringChars
     <li>ReleaseStringCritical
diff --git a/libcore/archive/src/main/java/java/util/zip/Deflater.java b/libcore/archive/src/main/java/java/util/zip/Deflater.java
index ee9c3ea..48ae479 100644
--- a/libcore/archive/src/main/java/java/util/zip/Deflater.java
+++ b/libcore/archive/src/main/java/java/util/zip/Deflater.java
@@ -17,9 +17,6 @@
 
 package java.util.zip;
 
-// BEGIN android-changed
-// import org.apache.harmony.luni.platform.OSResourcesMonitor;
-// END android-changed
 
 /**
  * This class compresses data using the <i>DEFLATE</i> algorithm (see <a
@@ -149,8 +146,7 @@
             throw new IllegalArgumentException();
         }
         compressLevel = level;
-        streamHandle = createStreamWithMemoryEnsurance(compressLevel, strategy,
-                noHeader);
+        streamHandle = createStream(compressLevel, strategy, noHeader);
     }
 
     /**
@@ -502,13 +498,5 @@
         return getTotalOutImpl(streamHandle);
     }
 
-    private long createStreamWithMemoryEnsurance(int level, int strategy1,
-            boolean noHeader1) {
-        // BEGIN android-changed
-        // OSResourcesMonitor.ensurePhysicalMemoryCapacity();
-        // END android-changed
-        return createStream(level, strategy1, noHeader1);
-    }
-
     private native long createStream(int level, int strategy1, boolean noHeader1);
 }
diff --git a/libcore/archive/src/main/java/java/util/zip/ZipFile.java b/libcore/archive/src/main/java/java/util/zip/ZipFile.java
index 653b2c9..b5f3678 100644
--- a/libcore/archive/src/main/java/java/util/zip/ZipFile.java
+++ b/libcore/archive/src/main/java/java/util/zip/ZipFile.java
@@ -52,12 +52,12 @@
     File fileToDeleteOnClose;
 
     /**
-     * Open zip file for read.
+     * Open ZIP file for read.
      */
     public static final int OPEN_READ = 1;
 
     /**
-     * Delete zip file when closed.
+     * Delete ZIP file when closed.
      */
     public static final int OPEN_DELETE = 4;
 
@@ -140,7 +140,7 @@
     }
 
     /**
-     * Closes this ZIP file.
+     * Closes this ZIP file. This method is idempotent.
      *
      * @throws IOException
      *             if an IOException occurs.
@@ -166,23 +166,32 @@
         }
     }
 
+    private void checkNotClosed() {
+        if (mRaf == null) {
+            throw new IllegalStateException("Zip File closed.");
+        }
+    }
+
     /**
      * Returns an enumeration of the entries. The entries are listed in the
      * order in which they appear in the ZIP archive.
      *
      * @return the enumeration of the entries.
+     * @throws IllegalStateException if this ZIP file has been closed.
      */
     public Enumeration<? extends ZipEntry> entries() {
+        checkNotClosed();
+
         return new Enumeration<ZipEntry>() {
             private int i = 0;
 
             public boolean hasMoreElements() {
-                if (mRaf == null) throw new IllegalStateException("Zip File closed.");
+                checkNotClosed();
                 return i < mEntryList.size();
             }
 
             public ZipEntry nextElement() {
-                if (mRaf == null) throw new IllegalStateException("Zip File closed.");
+                checkNotClosed();
                 if (i >= mEntryList.size())
                     throw new NoSuchElementException();
                 return (ZipEntry) mEntryList.get(i++);
@@ -197,8 +206,10 @@
      *            the name of the entry in the ZIP file.
      * @return a {@code ZipEntry} or {@code null} if the entry name does not
      *         exist in the ZIP file.
+     * @throws IllegalStateException if this ZIP file has been closed.
      */
     public ZipEntry getEntry(String entryName) {
+        checkNotClosed();
         if (entryName != null) {
             ZipEntry ze = mFastLookup.get(entryName);
             if (ze == null) ze = mFastLookup.get(entryName + "/");
@@ -215,6 +226,7 @@
      * @return an input stream of the data contained in the {@code ZipEntry}.
      * @throws IOException
      *             if an {@code IOException} occurs.
+     * @throws IllegalStateException if this ZIP file has been closed.
      */
     public InputStream getInputStream(ZipEntry entry) throws IOException {
         /*
@@ -229,27 +241,25 @@
          * Create a ZipInputStream at the right part of the file.
          */
         RandomAccessFile raf = mRaf;
-        if (raf != null) {
-            synchronized (raf) {
-                // Unfortunately we don't know the entry data's start position.
-                // All we have is the position of the entry's local header.
-                // At position 28 we find the length of the extra data.
-                // In some cases this length differs from the one coming in
-                // the central header!!!
-                RAFStream rafstrm = new RAFStream(raf, entry.mLocalHeaderRelOffset + 28);
-                int localExtraLenOrWhatever = ler.readShortLE(rafstrm);
-                // Now we need to skip the name
-                // and this "extra" data or whatever it is:
-                rafstrm.skip(entry.nameLen + localExtraLenOrWhatever);
-                rafstrm.mLength = rafstrm.mOffset + entry.compressedSize;
-                if (entry.compressionMethod == ZipEntry.DEFLATED) {
-                    return new InflaterInputStream(rafstrm, new Inflater(true));
-                } else {
-                    return rafstrm;
-                }
+        synchronized (raf) {
+            // Unfortunately we don't know the entry data's start position.
+            // All we have is the position of the entry's local header.
+            // At position 28 we find the length of the extra data.
+            // In some cases this length differs from the one coming in
+            // the central header!!!
+            RAFStream rafstrm = new RAFStream(raf,
+                    entry.mLocalHeaderRelOffset + 28);
+            int localExtraLenOrWhatever = ler.readShortLE(rafstrm);
+            // Now we need to skip the name
+            // and this "extra" data or whatever it is:
+            rafstrm.skip(entry.nameLen + localExtraLenOrWhatever);
+            rafstrm.mLength = rafstrm.mOffset + entry.compressedSize;
+            if (entry.compressionMethod == ZipEntry.DEFLATED) {
+                return new InflaterInputStream(rafstrm, new Inflater(true));
+            } else {
+                return rafstrm;
             }
         }
-        throw new IllegalStateException("Zip File closed");
     }
 
     /**
@@ -265,8 +275,10 @@
      * Returns the number of {@code ZipEntries} in this {@code ZipFile}.
      *
      * @return the number of entries in this file.
+     * @throws IllegalStateException if this ZIP file has been closed.
      */
     public int size() {
+        checkNotClosed();
         return mEntryList.size();
     }
 
diff --git a/libcore/archive/src/main/native/java_util_zip_Adler32.c b/libcore/archive/src/main/native/java_util_zip_Adler32.c
index 1b02a11..0fcf549 100644
--- a/libcore/archive/src/main/native/java_util_zip_Adler32.c
+++ b/libcore/archive/src/main/native/java_util_zip_Adler32.c
@@ -25,16 +25,11 @@
                                        jbyteArray buf, int off, int len,
                                        jlong crc)
 {
-  jbyte *b;
-  jboolean isCopy;
-  jlong result;
-
-  b = (*env)->GetPrimitiveArrayCritical (env, buf, &isCopy);
+  jbyte* b = (*env)->GetPrimitiveArrayCritical (env, buf, NULL);
   if (b == NULL) {
-    throwNewOutOfMemoryError(env, "");
     return 0;
   }
-  result = (jlong) adler32 ((uLong) crc, (Bytef *) (b + off), (uInt) len);
+  jlong result = (jlong) adler32 ((uLong) crc, (Bytef *) (b + off), (uInt) len);
   (*env)->ReleasePrimitiveArrayCritical (env, buf, b, JNI_ABORT);
 
   return result;
diff --git a/libcore/archive/src/main/native/java_util_zip_CRC32.c b/libcore/archive/src/main/native/java_util_zip_CRC32.c
index cee25e5..fe50fca 100644
--- a/libcore/archive/src/main/native/java_util_zip_CRC32.c
+++ b/libcore/archive/src/main/native/java_util_zip_CRC32.c
@@ -25,15 +25,11 @@
                                      jbyteArray buf, int off, int len,
                                      jlong crc)
 {
-  jbyte *b;
-  jlong result;
-
-  b = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
+  jbyte* b = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
   if (b == NULL) {
-    throwNewOutOfMemoryError(env, "");
     return -1;
   }
-  result = crc32 ((uLong) crc, (Bytef *) (b + off), (uInt) len);
+  jlong result = crc32 ((uLong) crc, (Bytef *) (b + off), (uInt) len);
   ((*env)->ReleasePrimitiveArrayCritical (env, buf, b, JNI_ABORT));
   return result;
 }
diff --git a/libcore/archive/src/main/native/java_util_zip_Deflater.c b/libcore/archive/src/main/native/java_util_zip_Deflater.c
index 2e0e268..af0bfcc 100644
--- a/libcore/archive/src/main/native/java_util_zip_Deflater.c
+++ b/libcore/archive/src/main/native/java_util_zip_Deflater.c
@@ -162,29 +162,19 @@
 {
   PORT_ACCESS_FROM_ENV (env);
 
-  jbyte *in;
-  JCLZipStream *stream;
-
-  stream = (JCLZipStream *) ((IDATA) handle);
-  if (stream->inaddr != NULL)	/*Input has already been provided, free the old buffer */
+  JCLZipStream* stream = (JCLZipStream *) ((IDATA) handle);
+  if (stream->inaddr != NULL) {
+    /* Input has already been provided, free the old buffer. */
     jclmem_free_memory (env, stream->inaddr);
+  }
   stream->inaddr = jclmem_allocate_memory (env, len);
-  if (stream->inaddr == NULL)
-    {
-      throwNewOutOfMemoryError (env, "");
-      return;
-    }
-  in = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
-  if (in == NULL) {
-    throwNewOutOfMemoryError(env, "");
+  if (stream->inaddr == NULL) {
+    throwNewOutOfMemoryError (env, "");
     return;
   }
-  memcpy (stream->inaddr, (in + off), len);
-  ((*env)->ReleasePrimitiveArrayCritical (env, buf, in, JNI_ABORT));
+  (*env)->GetByteArrayRegion(env, buf, off, len, (jbyte*) stream->inaddr);
   stream->stream->next_in = (Bytef *) stream->inaddr;
   stream->stream->avail_in = len;
-
-  return;
 }
 
 JNIEXPORT jint JNICALL
@@ -209,7 +199,6 @@
   sout = stream->stream->total_out;
   out = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
   if (out == NULL) {
-    throwNewOutOfMemoryError(env, "");
     return -1;
   }
   stream->stream->next_out = (Bytef *) out + off;
diff --git a/libcore/archive/src/main/native/java_util_zip_Inflater.c b/libcore/archive/src/main/native/java_util_zip_Inflater.c
index 4b30d4e..c04a223 100644
--- a/libcore/archive/src/main/native/java_util_zip_Inflater.c
+++ b/libcore/archive/src/main/native/java_util_zip_Inflater.c
@@ -104,29 +104,20 @@
 {
   PORT_ACCESS_FROM_ENV (env);
 
-  jbyte *in;
-  U_8 *baseAddr;
   JCLZipStream *stream = (JCLZipStream *) ((IDATA) handle);
-
-  if (stream->inaddr != NULL)   /*Input has already been provided, free the old buffer */
+  if (stream->inaddr != NULL) {
+    /* Input has already been provided, free the old buffer. */
     jclmem_free_memory (env, stream->inaddr);
-  baseAddr = jclmem_allocate_memory (env, len);
-  if (baseAddr == NULL)
-    {
-      throwNewOutOfMemoryError (env, "");
-      return;
-    }
+  }
+  U_8* baseAddr = jclmem_allocate_memory (env, len);
+  if (baseAddr == NULL) {
+    throwNewOutOfMemoryError (env, "");
+    return;
+  }
   stream->inaddr = baseAddr;
   stream->stream->next_in = (Bytef *) baseAddr;
   stream->stream->avail_in = len;
-  in = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
-  if (in == NULL) {
-    throwNewOutOfMemoryError(env, "");
-    return;
-  }
-  memcpy (baseAddr, (in + off), len);
-  ((*env)->ReleasePrimitiveArrayCritical (env, buf, in, JNI_ABORT));
-  return;
+  (*env)->GetByteArrayRegion(env, buf, off, len, (jbyte*) baseAddr);
 }
 
 JNIEXPORT jint JNICALL
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java
index 77fbb15..601fe42 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java
@@ -21,10 +21,8 @@
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
-
 import junit.framework.TestCase;
-
-import tests.support.Support_Exec;
+import static tests.support.Support_Exec.execAndGetOutput;
 import tests.support.resource.Support_Resources;
 
 import java.io.ByteArrayOutputStream;
@@ -32,49 +30,47 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
-import java.util.jar.JarFile;
 
 
 @TestTargetClass(JarOutputStream.class)
 @AndroidOnly("dalvik vm specific")
 public class DalvikExecTest extends TestCase {
 
-    String execDalvik1 (String classpath, String mainClass, String arg1)
+    String execDalvik1(String classpath, String mainClass, String arg1)
             throws IOException, InterruptedException {
 
-        ArrayList<String> cmdLine = new ArrayList<String>(10);
+        ProcessBuilder builder = new ProcessBuilder();
 
         String base = System.getenv("OUT");
-        cmdLine.add(base + "/system/bin/dalvikvm");
+        builder.command().add(base + "/system/bin/dalvikvm");
 
-        cmdLine.add("-Djava.io.tmpdir=/tmp/mc");
-        cmdLine.add("-Duser.language=en");
-        cmdLine.add("-Duser.region=US");
+        builder.command().add("-Djava.io.tmpdir=/tmp/mc");
+        builder.command().add("-Duser.language=en");
+        builder.command().add("-Duser.region=US");
 
         if ("true".equals(System.getenv("TARGET_SIMULATOR"))) {
             // Test against SIMULATOR:
 //            cmdLine.add("-Xmx512M");
 //            cmdLine.add("-Xcheck:jni");
-            cmdLine.add("-Xbootclasspath:" + System.getProperty("java.boot.class.path"));
+            builder.command().add("-Xbootclasspath:" + System.getProperty("java.boot.class.path"));
         } else {
             // Test against EMULATOR:
         }
 
-        cmdLine.add("-classpath");
-        cmdLine.add(classpath);
-        cmdLine.add(mainClass);
+        builder.command().add("-classpath");
+        builder.command().add(classpath);
+        builder.command().add(mainClass);
 
-        if (arg1 != null) cmdLine.add(arg1);
+        if (arg1 != null) {
+            builder.command().add(arg1);
+        }
 
-        Object[] res = Support_Exec.execAndDigestOutput(
-                cmdLine.toArray(new String[cmdLine.size()]),
-                null );
-        return Support_Exec.getProcessOutput(res, true);
+        return execAndGetOutput(builder);
     }
 
     String execDalvik (String classpath, String mainClass)
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java
index 4c209d1..01f5a8c 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java
@@ -21,7 +21,8 @@
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
-import tests.support.Support_Exec;
+import static tests.support.Support_Exec.execAndGetOutput;
+import static tests.support.Support_Exec.javaProcessBuilder;
 import tests.support.resource.Support_Resources;
 
 import java.io.File;
@@ -73,15 +74,12 @@
 
         jout.close();
 
-
-        // set up the VM parameters
-        String[] args = new String[] {"-jar", outputJar.getAbsolutePath()};
-
         // execute the JAR and read the result
-        String res = Support_Exec.execJava(args, null, false);
-
-        assertTrue("Error executing JAR : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("-jar");
+        builder.command().add(outputJar.getAbsolutePath());
+        assertTrue("Error executing JAR",
+                execAndGetOutput(builder).startsWith("FOOBAR"));
     }
 
     /**
@@ -123,13 +121,12 @@
         joutBar.write(getResource(resources, "hyts_Bar.ser"));
         joutBar.close();
 
-        String[] args = new String[] {"-jar", fooJar.getAbsolutePath()};
-
         // execute the JAR and read the result
-        String res = Support_Exec.execJava(args, null, false);
-
-        assertTrue("Error executing JAR : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("-jar");
+        builder.command().add(fooJar.getAbsolutePath());
+        assertTrue("Error executing JAR",
+                execAndGetOutput(builder).startsWith("FOOBAR"));
 
         // rewrite manifest so it contains not only reference to bar but useless
         // entries as well
@@ -139,10 +136,8 @@
         joutFoo.write(getResource(resources, "hyts_Foo.ser"));
         joutFoo.close();
         // execute the JAR and read the result
-        res = Support_Exec.execJava(args, null, false);
-        assertTrue("Error executing JAR : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
-
+        assertTrue("Error executing JAR",
+                execAndGetOutput(builder).startsWith( "FOOBAR"));
 
         // play with relative file names - put relative path as ../<parent dir
         // name>/xx.jar
@@ -154,9 +149,8 @@
         joutFoo.write(getResource(resources, "hyts_Foo.ser"));
         joutFoo.close();
         // execute the JAR and read the result
-        res = Support_Exec.execJava(args, null, false);
-        assertTrue("Error executing JAR : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        assertTrue("Error executing JAR",
+                execAndGetOutput(builder).startsWith( "FOOBAR"));
     }
 
     /**
@@ -199,13 +193,12 @@
         joutBar.write(getResource(resources, "hyts_Bar.ser"));
         joutBar.close();
 
-        String[] args = new String[] {"-jar", barJar.getAbsolutePath()};
-
         // execute the JAR and read the result
-        String res = Support_Exec.execJava(args, null, false);
-
-        assertTrue("Error executing JAR : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("-jar");
+        builder.command().add(barJar.getAbsolutePath());
+        assertTrue("Error executing JAR",
+                execAndGetOutput(builder).startsWith("FOOBAR"));
     }
 
     @TestTargetNew(
@@ -229,15 +222,13 @@
         joutFoo.write(getResource(resources, "hyts_Bar.ser"));
         joutFoo.close();
 
-        String[] args = new String[] {"foo.bar.execjartest.Foo"};
-
         // execute the JAR and read the result
-        String res = Support_Exec.execJava(args, null,
-                new String[] {"CLASSPATH=" + fooJar.getAbsolutePath()}, false);
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.environment().put("CLASSPATH", fooJar.getAbsolutePath());
+        builder.command().add("foo.bar.execjartest.Foo");
 
-        assertTrue(
-                "Error executing class from ClassPath : result returned was incorrect.",
-                res.startsWith("FOOBAR"));
+        assertTrue("Error executing class from ClassPath",
+                execAndGetOutput(builder).startsWith("FOOBAR"));
 
         // ok - next try - add -cp to path - it should override env
         File booJar = File.createTempFile("hyts_", ".jar");
@@ -257,13 +248,14 @@
         joutBoo.write(farBody.getBytes("iso-8859-1"));
         joutBoo.close();
 
-        res = Support_Exec.execJava(args, new String[] {booJar
-                .getAbsolutePath()}, new String[] {"CLASSPATH="
-                + fooJar.getAbsolutePath()}, false);
+        builder = javaProcessBuilder();
+        builder.environment().put("CLASSPATH", fooJar.getAbsolutePath());
+        builder.command().add("-cp");
+        builder.command().add(booJar.getAbsolutePath());
+        builder.command().add("foo.bar.execjartest.Foo");
 
-        assertTrue(
-                "Error executing class specified by -cp : result returned was incorrect.",
-                res.startsWith("BOOFAR"));
+        assertTrue("Error executing class specified by -cp",
+                execAndGetOutput(builder).startsWith("BOOFAR"));
 
         // now add -jar option - it should override env and classpath
         Manifest man = new Manifest();
@@ -288,15 +280,15 @@
         joutZoo.write(zarBody.getBytes("iso-8859-1"));
         joutZoo.close();
 
-        args = new String[] {"-jar", zooJar.getAbsolutePath()};
+        builder = javaProcessBuilder();
+        builder.environment().put("CLASSPATH", fooJar.getAbsolutePath());
+        builder.command().add("-cp");
+        builder.command().add(booJar.getAbsolutePath());
+        builder.command().add("-jar");
+        builder.command().add(zooJar.getAbsolutePath());
 
-        res = Support_Exec.execJava(args, new String[] {booJar
-                .getAbsolutePath()}, new String[] {"CLASSPATH="
-                + fooJar.getAbsolutePath()}, false);
-
-        assertTrue(
-                "Error executing class specified by -cp : result returned was incorrect.",
-                res.startsWith("ZOOZAR"));
+        assertTrue("Error executing class specified by -jar",
+                execAndGetOutput(builder).startsWith("ZOOZAR"));
     }
 
     private static byte[] getResource(File tempDir, String resourceName)
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java
index acdad71..b2ecdec 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java
@@ -34,7 +34,6 @@
 import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 
-import tests.support.Support_Exec;
 import tests.support.resource.Support_Resources;
 
 @TestTargetClass(JarOutputStream.class)
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java
index c6f07de..013974c 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java
@@ -21,7 +21,8 @@
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
-import tests.support.Support_Exec;
+import static tests.support.Support_Exec.javaProcessBuilder;
+import static tests.support.Support_Exec.execAndGetOutput;
 import tests.support.resource.Support_Resources;
 
 import java.io.File;
@@ -72,15 +73,12 @@
         man.write(zout);
         zout.close();
 
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("-jar");
+        builder.command().add(outputZip.getAbsolutePath());
 
-        // set up the VM parameters
-        String[] args = new String[] {"-jar", outputZip.getAbsolutePath()};
-
-        // execute the JAR and read the result
-        String res = Support_Exec.execJava(args, null, false);
-
-        assertTrue("Error executing ZIP : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        assertTrue("Error executing ZIP",
+                execAndGetOutput(builder).startsWith("FOOBAR"));
     }
 
     /**
@@ -124,13 +122,12 @@
         zoutBar.write(getResource(resources, "hyts_Bar.ser"));
         zoutBar.close();
 
-        String[] args = new String[] {"-jar", fooZip.getAbsolutePath()};
-
         // execute the JAR and read the result
-        String res = Support_Exec.execJava(args, null, false);
-
-        assertTrue("Error executing JAR : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("-jar");
+        builder.command().add(fooZip.getAbsolutePath());
+        assertTrue("Error executing JAR",
+                execAndGetOutput(builder).startsWith( "FOOBAR"));
 
         // rewrite manifest so it contains not only reference to bar but useless
         // entries as well
@@ -142,9 +139,8 @@
         zoutFoo.write(getResource(resources, "hyts_Foo.ser"));
         zoutFoo.close();
         // execute the JAR and read the result
-        res = Support_Exec.execJava(args, null, false);
-        assertTrue("Error executing JAR : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        assertTrue("Error executing JAR",
+                execAndGetOutput(builder).startsWith("FOOBAR"));
 
 
         // play with relative file names - put relative path as ../<parent dir
@@ -159,9 +155,8 @@
         zoutFoo.write(getResource(resources, "hyts_Foo.ser"));
         zoutFoo.close();
         // execute the ZIP and read the result
-        res = Support_Exec.execJava(args, null, false);
-        assertTrue("Error executing JAR : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        assertTrue("Error executing JAR",
+                execAndGetOutput(builder).startsWith("FOOBAR"));
     }
 
 
@@ -199,13 +194,11 @@
         zoutBar.write(getResource(resources, "hyts_Bar.ser"));
         zoutBar.close();
 
-        String[] args = new String[] {"-jar", fooJar.getAbsolutePath()};
-
-        // execute the JAR and read the result
-        String res = Support_Exec.execJava(args, null, false);
-
-        assertTrue("Error executing JAR : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("-jar");
+        builder.command().add(fooJar.getAbsolutePath());
+        assertTrue("Error executing JAR",
+                execAndGetOutput(builder).startsWith("FOOBAR"));
     }
 
     @TestTargetNew(
@@ -244,13 +237,12 @@
         joutBar.write(getResource(resources, "hyts_Bar.ser"));
         joutBar.close();
 
-        String[] args = new String[] {"-jar", fooZip.getAbsolutePath()};
-
         // execute the JAR and read the result
-        String res = Support_Exec.execJava(args, null, false);
-
-        assertTrue("Error executing ZIP : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("-jar");
+        builder.command().add(fooZip.getAbsolutePath());
+        assertTrue("Error executing ZIP", 
+                execAndGetOutput(builder).startsWith("FOOBAR"));
     }
 
     /**
@@ -296,13 +288,12 @@
         zoutBar.write(getResource(resources, "hyts_Bar.ser"));
         zoutBar.close();
 
-        String[] args = new String[] {"-jar", barZip.getAbsolutePath()};
-
         // execute the JAR and read the result
-        String res = Support_Exec.execJava(args, null, false);
-
-        assertTrue("Error executing JAR : result returned was incorrect.", res
-                .startsWith("FOOBAR"));
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("-jar");
+        builder.command().add(barZip.getAbsolutePath());
+        assertTrue("Error executing JAR",
+                execAndGetOutput(builder).startsWith("FOOBAR"));
     }
 
 
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java
index b025e11..146c679 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java
@@ -271,14 +271,23 @@
 
         Enumeration<? extends ZipEntry> enumeration = zfile.entries();
         zfile.close();
-        zfile = null;
-        boolean pass = false;
+        try {
+            enumeration.nextElement();
+            fail("did not detect closed file");
+        } catch (IllegalStateException expected) {
+        }
+
         try {
             enumeration.hasMoreElements();
-        } catch (IllegalStateException e) {
-            pass = true;
+            fail("did not detect closed file");
+        } catch (IllegalStateException expected) {
         }
-        assertTrue("did not detect closed jar file", pass);
+
+        try {
+            zfile.entries();
+            fail("did not detect closed file");
+        } catch (IllegalStateException expected) {
+        }
     }
 
     /**
@@ -349,20 +358,15 @@
         method = "getEntry",
         args = {java.lang.String.class}
     )
-    @KnownFailure("Android does not throw IllegalStateException when using "
-            + "getEntry() after close().")
     public void test_getEntryLjava_lang_String_Ex() throws IOException {
         java.util.zip.ZipEntry zentry = zfile.getEntry("File1.txt");
         assertNotNull("Could not obtain ZipEntry", zentry);
-        int r;
-        InputStream in;
 
         zfile.close();
         try {
-            zentry = zfile.getEntry("File2.txt");
-            fail("IllegalStateException expected"); // Android fails here!
+            zfile.getEntry("File2.txt");
+            fail("IllegalStateException expected");
         } catch (IllegalStateException ee) {
-            // expected
         }
     }
 
@@ -435,16 +439,13 @@
         method = "size",
         args = {}
     )
-    @KnownFailure("IllegalStateException not thrown when using ZipFile.size() "
-            + "after close().")
     public void test_size() throws IOException {
         assertEquals(6, zfile.size());
         zfile.close();
         try {
             zfile.size();
-            fail("IllegalStateException expected"); // Android fails here!
-        } catch (IllegalStateException ee) {
-            // expected
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException expected) {
         }
     }
 
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
index ee21b13..312c76d 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -30,7 +30,10 @@
     private long rawIndex(int i) {
         if (i < 0 || i >= array.length)
             throw new IndexOutOfBoundsException("index " + i);
-        return base + i * scale;
+        // BEGIN android-changed
+        // avoid memory corruption
+        return base + (long) i * scale;
+        // END android-changed
     }
 
     /**
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
index d96f4c2..187acbc 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
@@ -29,7 +29,10 @@
     private long rawIndex(int i) {
         if (i < 0 || i >= array.length)
             throw new IndexOutOfBoundsException("index " + i);
-        return base + i * scale;
+        // BEGIN android-changed
+        // avoid memory corruption
+        return base + (long) i * scale;
+        // END android-changed
     }
 
     /**
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
index 9a484e6..fff6a1e 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
@@ -30,7 +30,10 @@
     private long rawIndex(int i) {
         if (i < 0 || i >= array.length)
             throw new IndexOutOfBoundsException("index " + i);
-        return base + i * scale;
+        // BEGIN android-changed
+        // avoid memory corruption
+        return base + (long) i * scale;
+        // END android-changed
     }
 
     /**
diff --git a/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java b/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java
index 73e6fe4..4a440b5 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java
@@ -114,7 +114,7 @@
 
         /* open all Zip and DEX files up front */
         for (int i = 0; i < length; i++) {
-            System.out.println("My path is: " + dexPathList[i]);
+            //System.out.println("My path is: " + dexPathList[i]);
             File pathFile = new File(dexPathList[i]);
             mFiles[i] = pathFile;
 
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java b/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
index 5bee1fd..104336e 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
@@ -48,6 +48,13 @@
     private boolean posPrefNull;
     private boolean posSuffNull;
 
+    /**
+     * Cache the BigDecimal form of the multiplier. This is null until we've
+     * formatted a BigDecimal (with a multipler that is not 1), or the user has
+     * explicitly called {@link #setMultiplier(int)} with any multiplier.
+     */
+    private transient BigDecimal multiplierBigDecimal = null;
+
     public DecimalFormat(String pattern, DecimalFormatSymbols icuSymbols) {
         this.addr = icuSymbols.getAddr();
         this.symbols = icuSymbols;
@@ -118,6 +125,14 @@
         return result;
     }
 
+    private BigDecimal applyMultiplier(BigDecimal valBigDecimal) {
+       if (multiplierBigDecimal == null) {
+           multiplierBigDecimal = BigDecimal.valueOf(getMultiplier());
+       }
+       // Get new value by multiplying multiplier.
+       return valBigDecimal.multiply(multiplierBigDecimal);
+    }
+
     @Override
     public StringBuffer format(Object value, StringBuffer buffer, FieldPosition field) {
 
@@ -139,6 +154,9 @@
             return buffer.append(result);
         } else if(number instanceof BigDecimal) {
             BigDecimal valBigDecimal = (BigDecimal) number;
+            if (getMultiplier() != 1) {
+                valBigDecimal = applyMultiplier(valBigDecimal);
+            }
             StringBuilder val = new StringBuilder();
             val.append(valBigDecimal.unscaledValue().toString(10));
             int scale = valBigDecimal.scale();
@@ -233,6 +251,9 @@
                     valBigInteger.toString(10), null, null, attributes, 0);
         } else if(number instanceof BigDecimal) {
             BigDecimal valBigDecimal = (BigDecimal) number;
+            if (getMultiplier() != 1) {
+                valBigDecimal = applyMultiplier(valBigDecimal);
+            }
             StringBuilder val = new StringBuilder();
             val.append(valBigDecimal.unscaledValue().toString(10));
             int scale = valBigDecimal.scale();
@@ -441,6 +462,8 @@
     public void setMultiplier(int value) {
         NativeDecimalFormat.setAttribute(this.addr,
                 UNumberFormatAttribute.UNUM_MULTIPLIER.ordinal(), value);
+        // Update the cached BigDecimal for multiplier.
+        multiplierBigDecimal = BigDecimal.valueOf(value);
     }
 
     public void setNegativePrefix(String value) {
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java b/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
index 0460fde..086f8d4 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
@@ -114,7 +114,7 @@
             isoLanguages = getISOLanguagesNative();
         }
 
-        return isoLanguages;
+        return isoLanguages.clone();
     }
 
     /**
@@ -128,7 +128,7 @@
             isoCountries = getISOCountriesNative();
         }
 
-        return isoCountries;
+        return isoCountries.clone();
     }
 
     /**
@@ -142,7 +142,7 @@
             availableLocales = getAvailableLocalesNative();
         }
 
-        return availableLocales;
+        return availableLocales.clone();
     }
 
     /**
@@ -157,7 +157,7 @@
             availableTimezones = TimeZone.getAvailableIDs();
         }
 
-        return availableTimezones;
+        return availableTimezones.clone();
     }
 
     /**
@@ -264,17 +264,25 @@
         if (locale == null) {
             locale = defaultLocale;
         }
-
+        
         // If locale == default and the default locale hasn't changed since
         // DefaultTimeZones loaded, return the cached names.
         // TODO: We should force a reboot if the default locale changes.
         if (defaultLocale.equals(locale) && DefaultTimeZones.locale.equals(defaultLocale)) {
-            return DefaultTimeZones.names;
+            return clone2dStringArray(DefaultTimeZones.names);
         }
         
         return createTimeZoneNamesFor(locale);
     }
 
+    private static String[][] clone2dStringArray(String[][] array) {
+        String[][] result = new String[array.length][];
+        for (int i = 0; i < array.length; ++i) {
+            result[i] = array[i].clone();
+        }
+        return result;
+    }
+
     // --- Specialized ResourceBundle subclasses ------------------------------
 
     /**
diff --git a/libcore/icu/src/main/native/BidiWrapperInterface.c b/libcore/icu/src/main/native/BidiWrapperInterface.c
index 2c6b3cd..19ac520 100644
--- a/libcore/icu/src/main/native/BidiWrapperInterface.c
+++ b/libcore/icu/src/main/native/BidiWrapperInterface.c
@@ -15,18 +15,17 @@
  * limitations under the License.
  */
 
-#include <stdlib.h>
-#include <unicode/ubidi.h>
-#include <string.h>
 #include "BidiWrapperInterface.h"
+#include "ErrorCode.h"
+#include "unicode/ubidi.h"
+#include <stdlib.h>
+#include <string.h>
 
 typedef struct {
     UBiDi *pBiDi;
     void *embeddingLevels;
 } BiDiData;
 
-void check_fail (JNIEnv * env, int err);
-
 JNIEXPORT jlong JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1open
   (JNIEnv * env, jclass clazz)
 {
@@ -43,62 +42,52 @@
 
   ubidi_close ((*data).pBiDi);
   
-  if ((*data).embeddingLevels != NULL)
-    free((*data).embeddingLevels);
-    free(data);
+  free((*data).embeddingLevels);
+  free(data);
 }
 
 JNIEXPORT void JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1setPara
   (JNIEnv * env, jclass clazz, jlong pBiDi, jcharArray text, jint length,
-   jbyte paraLevel, jbyteArray embeddingLevels)
+   jbyte paraLevel, jbyteArray newEmbeddingLevels)
 {
-  UErrorCode err = 0;
-  jchar *_text = NULL;
   BiDiData *data = (BiDiData *)pBiDi;
-  /* Remembering old embedding levels */
-  void *embLvls = (*data).embeddingLevels;
-  
-  _text = (*env)->GetCharArrayElements (env, text, NULL);
+  void *oldEmbeddingLevels = (*data).embeddingLevels;
 
-  if (embeddingLevels != NULL)
-    {        
-        jbyte *el = (*env)->GetByteArrayElements (env, embeddingLevels, NULL);
-        (*data).embeddingLevels = malloc(length);
-        memcpy(((*data).embeddingLevels), el, length);
-        (*env)->ReleaseByteArrayElements (env, embeddingLevels, el, 0);
-    } else
-    {
-        (*data).embeddingLevels = NULL;
-    }
-
-  ubidi_setPara ((*data).pBiDi, _text, length, paraLevel,
-                 ((*data).embeddingLevels), &err);
-  check_fail (env, err);
-
-  /* Freeing old embedding levels */
-  if (embLvls != NULL) {
-    free(embLvls);
+  // Copy the new embedding levels from the Java heap to the native heap.
+  if (newEmbeddingLevels != NULL) {
+    (*data).embeddingLevels = malloc(length);
+    (*env)->GetByteArrayRegion(env, newEmbeddingLevels, 0, length,
+                               (*data).embeddingLevels);
+  } else {
+    (*data).embeddingLevels = NULL;
   }
 
+  UErrorCode err = 0;
+  jchar* _text = (*env)->GetCharArrayElements(env, text, NULL);
+  ubidi_setPara ((*data).pBiDi, _text, length, paraLevel,
+                 ((*data).embeddingLevels), &err);
   (*env)->ReleaseCharArrayElements (env, text, _text, 0);
+  free(oldEmbeddingLevels);
+
+  icu4jni_error(env, err);
 }
 
 JNIEXPORT jlong JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1setLine
   (JNIEnv * env, jclass clazz, jlong pBiDi, jint start, jint limit)
 {
-  UErrorCode err = 0;
-  BiDiData *data = (BiDiData *)pBiDi;
-  BiDiData *lineData = (BiDiData *) malloc(sizeof(BiDiData));
-  (*lineData).embeddingLevels = NULL;
+    UErrorCode err = 0;
+    BiDiData *data = (BiDiData *)pBiDi;
+    BiDiData *lineData = (BiDiData *) malloc(sizeof(BiDiData));
+    (*lineData).embeddingLevels = NULL;
 
-  (*lineData).pBiDi = ubidi_openSized (limit - start, 0, &err);
-  check_fail (env, err);
+    (*lineData).pBiDi = ubidi_openSized (limit - start, 0, &err);
+    if (icu4jni_error(env, err)) {
+        return 0;
+    }
 
-  ubidi_setLine ((*data).pBiDi, start, limit, (*lineData).pBiDi,
-                 &err);
-  check_fail (env, err);
-
-  return (jlong) lineData;
+    ubidi_setLine ((*data).pBiDi, start, limit, (*lineData).pBiDi, &err);
+    icu4jni_error(env, err);
+    return (jlong) lineData;
 }
 
 JNIEXPORT jint JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getDirection
@@ -125,76 +114,57 @@
 JNIEXPORT jbyteArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getLevels
   (JNIEnv * env, jclass clazz, jlong pBiDi)
 {
-  UErrorCode err = 0;
-  const UBiDiLevel *levels = NULL;
-  jbyteArray result = NULL;
-  int len = 0;
-  BiDiData *data = (BiDiData *)pBiDi;
+    BiDiData *data = (BiDiData *)pBiDi;
 
-  levels = ubidi_getLevels ((*data).pBiDi, &err);
-  check_fail (env, err);
+    UErrorCode err = 0;
+    const UBiDiLevel* levels = ubidi_getLevels((*data).pBiDi, &err);
+    if (icu4jni_error(env, err)) {
+        return NULL;
+    }
 
-  len = ubidi_getLength ((*data).pBiDi);
-  result = (*env)->NewByteArray (env, len);
-  (*env)->SetByteArrayRegion (env, result, 0, len, (jbyte *) levels);
+    int len = ubidi_getLength((*data).pBiDi);
+    jbyteArray result = (*env)->NewByteArray(env, len);
+    (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*) levels);
 
-  return result;
+    return result;
 }
 
 JNIEXPORT jint JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1countRuns
   (JNIEnv * env, jclass clazz, jlong pBiDi)
 {
-  UErrorCode err = 0;
-  BiDiData *data = (BiDiData *)pBiDi;
+    BiDiData *data = (BiDiData *)pBiDi;
 
-  int count = ubidi_countRuns ((*data).pBiDi, &err);
-  check_fail (env, err);
-
-  return count;
+    UErrorCode err = 0;
+    int count = ubidi_countRuns ((*data).pBiDi, &err);
+    icu4jni_error(env, err);
+    return count;
 }
 
 JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getRuns
   (JNIEnv * env, jclass clz, jlong pBiDi)
 {
-  int runCount = 0;
-  int start = 0;
-  int limit = 0;
-  int i = 0;
-  UBiDiLevel level = 0;
-  jclass run_clazz = 0;
-  jmethodID initID = 0;
-  jobject run = 0;
-  jobjectArray runs;
-  UErrorCode err = 0;
-  BiDiData *data = (BiDiData *)pBiDi;
+    BiDiData* data = (BiDiData*) pBiDi;
 
-  run_clazz = (*env)->FindClass (env, "org/apache/harmony/text/BidiRun");
-  initID = (*env)->GetMethodID (env, run_clazz, "<init>", "(III)V");
-
-  runCount = ubidi_countRuns ((*data).pBiDi, &err);
-  check_fail (env, err);
-  
-  runs = (*env)->NewObjectArray(env, runCount,run_clazz, NULL);  
-  for (i = 0; i < runCount; i++) {
-      ubidi_getLogicalRun((*data).pBiDi, start, &limit, &level);
-      run = (*env)->NewObject (env, run_clazz, initID, start, limit, level);
-      (*env)->SetObjectArrayElement(env, runs, i, run);
-      start = limit;
-  }
-  return runs;
-}
-
-void
-check_fail (JNIEnv * env, int err)
-{
-  char message[] = "ICU Internal Error:                     ";
-
-  if (U_FAILURE (err))
-    {
-      sprintf (message, "ICU Internal Error: %d", err);
-      jniThrowException(env, "java/lang/RuntimeException",
-                              message);
+    UErrorCode err = 0;
+    int runCount = ubidi_countRuns((*data).pBiDi, &err);
+    if (icu4jni_error(env, err)) {
+        return 0;
     }
+
+    jclass bidiRunClass = (*env)->FindClass(env, "org/apache/harmony/text/BidiRun");
+    jmethodID bidiRunConstructor = (*env)->GetMethodID(env, bidiRunClass, "<init>", "(III)V");
+    jobjectArray runs = (*env)->NewObjectArray(env, runCount, bidiRunClass, NULL);
+    UBiDiLevel level = 0;
+    int start = 0;
+    int limit = 0;
+    int i = 0; // TODO: switch this file to C++!
+    for (i = 0; i < runCount; ++i) {
+        ubidi_getLogicalRun((*data).pBiDi, start, &limit, &level);
+        jobject run = (*env)->NewObject(env, bidiRunClass, bidiRunConstructor, start, limit, level);
+        (*env)->SetObjectArrayElement(env, runs, i, run);
+        start = limit;
+    }
+    return runs;
 }
 
 JNIEXPORT jintArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1reorderVisual
diff --git a/libcore/icu/src/main/native/CollationInterface.c b/libcore/icu/src/main/native/CollationInterface.c
index 86246ac..c669649 100644
--- a/libcore/icu/src/main/native/CollationInterface.c
+++ b/libcore/icu/src/main/native/CollationInterface.c
@@ -172,13 +172,11 @@
 static jint getNormalization(JNIEnv *env, jclass obj,
         jint address) {
 
-  UErrorCode status = U_ZERO_ERROR;
-  const UCollator *collator = (const UCollator *)(int)address;
-  if(U_FAILURE(status)){
-       icu4jni_error(env, status);
-  }
-  return (jint)ucol_getAttribute(collator,UCOL_NORMALIZATION_MODE,&status);
-
+    const UCollator* collator = (const UCollator*) address;
+    UErrorCode status = U_ZERO_ERROR;
+    jint result = ucol_getAttribute(collator, UCOL_NORMALIZATION_MODE, &status);
+    icu4jni_error(env, status);
+    return result;
 }
 
 /**
@@ -192,12 +190,10 @@
 static void setNormalization(JNIEnv *env, jclass obj, jint address, 
         jint mode) {
 
+    const UCollator* collator = (const UCollator*) address;
     UErrorCode status = U_ZERO_ERROR;
-    const UCollator *collator = (const UCollator *)(int)address;
-    if(U_FAILURE(status)){
-        icu4jni_error(env, status);
-    }
-    ucol_setAttribute(collator,UCOL_NORMALIZATION_MODE,mode,&status);
+    ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, mode, &status);
+    icu4jni_error(env, status);
 }
 
 
@@ -324,12 +320,11 @@
 *         error has occured or if the end of string has been reached
 */
 static jint next(JNIEnv *env, jclass obj, jint address) {
-  UCollationElements *iterator = (UCollationElements *)(int)address;
-  UErrorCode status = U_ZERO_ERROR;
-  jint result = ucol_next(iterator, &status);
-
-   icu4jni_error(env, status);
-  return result;
+    UCollationElements *iterator = (UCollationElements *) address;
+    UErrorCode status = U_ZERO_ERROR;
+    jint result = ucol_next(iterator, &status);
+    icu4jni_error(env, status);
+    return result;
 }
 
 /**
@@ -343,14 +338,10 @@
 * @exception thrown if creation of the UCollator fails
 */
 static jint openCollator__(JNIEnv *env, jclass obj) {
-  jint result;
-  UErrorCode status = U_ZERO_ERROR;
-
-  result = (jint)ucol_open(NULL, &status);
-  if ( icu4jni_error(env, status) != FALSE)
-    return 0;
- 
-  return result;
+    UErrorCode status = U_ZERO_ERROR;
+    jint result = ucol_open(NULL, &status);
+    icu4jni_error(env, status);
+    return result;
 }
 
 
@@ -368,19 +359,18 @@
 static jint openCollator__Ljava_lang_String_2(JNIEnv *env,
         jclass obj, jstring locale) {
 
-  /* this will be null terminated */
-  const char *localestr = (*env)->GetStringUTFChars(env, locale, 0);
-  jint result=0;
-  UErrorCode status = U_ZERO_ERROR;
+    /* this will be null terminated */
+    const char* localeStr = (*env)->GetStringUTFChars(env, locale, NULL);
+    if (localeStr == NULL) {
+        icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
+        return 0;
+    }
 
-  if(localestr){
-      result = (jint)ucol_open(localestr, &status);
-      (*env)->ReleaseStringUTFChars(env, locale, localestr);
-      icu4jni_error(env, status);
-  }else{
-      icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR);
-  }
-  return result;
+    UErrorCode status = U_ZERO_ERROR;
+    jint result = ucol_open(localeStr, &status);
+    (*env)->ReleaseStringUTFChars(env, locale, localeStr);
+    icu4jni_error(env, status);
+    return result;
 }
 
 /**
@@ -586,4 +576,3 @@
     return jniRegisterNativeMethods(_env, "com/ibm/icu4jni/text/NativeCollation",
                 gMethods, NELEM(gMethods));
 }
-
diff --git a/libcore/icu/src/main/native/DecimalFormatInterface.cpp b/libcore/icu/src/main/native/DecimalFormatInterface.cpp
index 7e37d6c..f553e0a 100644
--- a/libcore/icu/src/main/native/DecimalFormatInterface.cpp
+++ b/libcore/icu/src/main/native/DecimalFormatInterface.cpp
@@ -29,33 +29,6 @@
 #include <string.h>
 #include "cutils/log.h"
 
-
-static UBool icuError(JNIEnv *env, UErrorCode errorcode)
-{
-    const char *emsg = u_errorName(errorcode);
-    jclass  exception;
-
-    if (U_FAILURE(errorcode)) {// errorcode > U_ZERO_ERROR && errorcode < U_ERROR_LIMIT) {
-        switch (errorcode) {
-            case U_ILLEGAL_ARGUMENT_ERROR :
-                exception = env->FindClass("java/lang/IllegalArgumentException");
-                break;
-            case U_INDEX_OUTOFBOUNDS_ERROR :
-            case U_BUFFER_OVERFLOW_ERROR :
-                exception = env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-                break;
-            case U_UNSUPPORTED_ERROR :
-                exception = env->FindClass("java/lang/UnsupportedOperationException");
-                break;
-            default :
-                exception = env->FindClass("java/lang/RuntimeException");
-        }
-
-        return (env->ThrowNew(exception, emsg) != 0);
-    }
-    return 0;
-}
-
 static jint openDecimalFormatImpl(JNIEnv *env, jclass clazz, jstring locale,
         jstring pattern) {
 
@@ -78,7 +51,7 @@
     env->ReleaseStringUTFChars(locale, localeChars);
 
     // check for an error
-    if ( icuError(env, status) != FALSE) {
+    if (icu4jni_error(env, status) != FALSE) {
         return 0;
     }
 
@@ -115,8 +88,8 @@
     // release previously allocated space
     env->ReleaseStringChars(text, textChars);
 
-    // check if an error occured
-    icuError(env, status);
+    // check if an error occurred
+    icu4jni_error(env, status);
 }
 
 static jstring getSymbol(JNIEnv *env, jclass clazz, jint addr, jint symbol) {
@@ -144,7 +117,7 @@
         reslenneeded=unum_getSymbol(fmt, (UNumberFormatSymbol) symbol, result,
                 resultlength, &status);
     }
-    if (icuError(env, status) != FALSE) {
+    if (icu4jni_error(env, status) != FALSE) {
         return NULL;
     }
 
@@ -189,7 +162,7 @@
 
     env->ReleaseStringChars(text, textChars);
 
-    icuError(env, status);
+    icu4jni_error(env, status);
 }
 
 static jstring getTextAttribute(JNIEnv *env, jclass clazz, jint addr,
@@ -219,7 +192,7 @@
                 (UNumberFormatTextAttribute) symbol, result, resultlength,
                 &status);
     }
-    if (icuError(env, status) != FALSE) {
+    if (icu4jni_error(env, status) != FALSE) {
         return NULL;
     }
 
@@ -246,7 +219,7 @@
 
     env->ReleaseStringChars(pattern, pattChars);
 
-    icuError(env, status);
+    icu4jni_error(env, status);
 }
 
 static jstring toPatternImpl(JNIEnv *env, jclass clazz, jint addr,
@@ -274,7 +247,7 @@
         reslenneeded=unum_toPattern(fmt, localized, result, resultlength,
                 &status);
     }
-    if (icuError(env, status) != FALSE) {
+    if (icu4jni_error(env, status) != FALSE) {
         return NULL;
     }
 
@@ -335,7 +308,7 @@
 
         res->extract(result, reslenneeded + 1, status);
     }
-    if (icuError(env, status) != FALSE) {
+    if (icu4jni_error(env, status) != FALSE) {
         free(attrBuffer->buffer);
         free(attrBuffer);
         free(result);
@@ -444,7 +417,7 @@
         res->extract(result, reslenneeded + 1, status);
 
     }
-    if (icuError(env, status) != FALSE) {
+    if (icu4jni_error(env, status) != FALSE) {
         free(attrBuffer->buffer);
         free(attrBuffer);
         free(result);
@@ -510,7 +483,7 @@
     // env->ReleaseStringUTFChars(value, valueUTF);
 
     if (scale < 0) {
-        icuError(env, U_ILLEGAL_ARGUMENT_ERROR);
+        icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
         return NULL;
     }
 
@@ -532,6 +505,8 @@
     const char *digits = (isPositive ? valueChars : valueChars + 1);
     int length = strlen(digits);
 
+    DecimalFormat* fmt = reinterpret_cast<DecimalFormat*>(static_cast<uintptr_t>(addr));
+
     // The length of our digit list buffer must be the actual string length + 3,
     // because ICU will append some additional characters at the head and at the
     // tail of the string, in order to keep strtod() happy:
@@ -551,7 +526,8 @@
 
     digitList.fDecimalAt = digitList.fCount - scale;
     digitList.fIsPositive = isPositive;
-    digitList.fRoundingMode = DecimalFormat::kRoundHalfUp;
+    digitList.fRoundingMode = fmt->getRoundingMode();
+    digitList.round(fmt->getMaximumFractionDigits() + digitList.fDecimalAt);
 
     UChar *result = NULL;
 
@@ -567,8 +543,6 @@
     attrBuffer->bufferSize = 128;
     attrBuffer->buffer = (char *) calloc(129 * sizeof(char), 1);
 
-    DecimalFormat *fmt = (DecimalFormat *)(int)addr;
-
     UnicodeString res;
 
     fmt->subformat(res, fp, attrBuffer, digitList, isInteger);
@@ -582,7 +556,7 @@
 
         res.extract(result, reslenneeded + 1, status);
 
-        if (icuError(env, status) != FALSE) {
+        if (icu4jni_error(env, status) != FALSE) {
             if(fieldType != NULL) {
                 env->ReleaseStringUTFChars(fieldType, fieldName);
             }
@@ -671,28 +645,12 @@
 
 static jobject parse(JNIEnv *env, jclass clazz, jint addr, jstring text,
         jobject position) {
-
-    const char * textUTF = env->GetStringUTFChars(text, NULL);
-    env->ReleaseStringUTFChars(text, textUTF);
-
-    const char * parsePositionClassName = "java/text/ParsePosition";
-    const char * longClassName = "java/lang/Long";
-    const char * doubleClassName = "java/lang/Double";
-    const char * bigDecimalClassName = "java/math/BigDecimal";
-    const char * bigIntegerClassName = "java/math/BigInteger";
-
-    UErrorCode status = U_ZERO_ERROR;
-
-    UNumberFormat *fmt = (UNumberFormat *)(int)addr;
-
-    jchar *str = (UChar *)env->GetStringChars(text, NULL);
-    int strlength = env->GetStringLength(text);
-
-    jclass parsePositionClass = env->FindClass(parsePositionClassName);
-    jclass longClass =  env->FindClass(longClassName);
-    jclass doubleClass =  env->FindClass(doubleClassName);
-    jclass bigDecimalClass = env->FindClass(bigDecimalClassName);
-    jclass bigIntegerClass = env->FindClass(bigIntegerClassName);
+    // TODO: cache these?
+    jclass parsePositionClass = env->FindClass("java/text/ParsePosition");
+    jclass longClass =  env->FindClass("java/lang/Long");
+    jclass doubleClass =  env->FindClass("java/lang/Double");
+    jclass bigDecimalClass = env->FindClass("java/math/BigDecimal");
+    jclass bigIntegerClass = env->FindClass("java/math/BigInteger");
 
     jmethodID getIndexMethodID = env->GetMethodID(parsePositionClass,
             "getIndex", "()I");
@@ -707,27 +665,26 @@
     jmethodID bigIntegerInitMethodID = env->GetMethodID(bigIntegerClass, "<init>", "(Ljava/lang/String;)V");
     jmethodID doubleValueMethodID = env->GetMethodID(bigDecimalClass, "doubleValue", "()D");
 
-    bool resultAssigned;
-    int parsePos = env->CallIntMethod(position, getIndexMethodID, NULL);
-
     // make sure the ParsePosition is valid. Actually icu4c would parse a number
     // correctly even if the parsePosition is set to -1, but since the RI fails
     // for that case we have to fail too
+    int parsePos = env->CallIntMethod(position, getIndexMethodID, NULL);
+    const int strlength = env->GetStringLength(text);
     if(parsePos < 0 || parsePos > strlength) {
         return NULL;
     }
-
-    Formattable res;
-
-    const UnicodeString src((UChar*)str, strlength, strlength);
+    
     ParsePosition pp;
-
     pp.setIndex(parsePos);
 
     DigitList digits;
-
+    
+    UNumberFormat *fmt = (UNumberFormat *)(int)addr;
+    Formattable res;
+    bool resultAssigned;
+    jchar *str = (UChar *)env->GetStringChars(text, NULL);
+    const UnicodeString src((UChar*)str, strlength, strlength);
     ((const DecimalFormat*)fmt)->parse(src, resultAssigned, res, pp, FALSE, digits);
-
     env->ReleaseStringChars(text, str);
 
     if(pp.getErrorIndex() == -1) {
@@ -738,20 +695,14 @@
         return NULL;
     }
 
-    Formattable::Type numType;
-    numType = res.getType();
+    Formattable::Type numType = res.getType();
     UErrorCode fmtStatus;
 
     double resultDouble;
     long resultLong;
     int64_t resultInt64;
-    UnicodeString resultString;
     jstring resultStr;
-    int resLength;
-    const char * resultUTF;
     jobject resultObject1, resultObject2;
-    jdouble doubleTest;
-    jchar * result;
 
     if (resultAssigned)
     {
@@ -809,7 +760,7 @@
 
     UNumberFormat *result = unum_clone(fmt, &status);
 
-    if(icuError(env, status) != FALSE) {
+    if(icu4jni_error(env, status) != FALSE) {
         return 0;
     }
 
diff --git a/libcore/icu/src/main/native/ErrorCode.c b/libcore/icu/src/main/native/ErrorCode.c
index b3e43cd..94c4239 100644
--- a/libcore/icu/src/main/native/ErrorCode.c
+++ b/libcore/icu/src/main/native/ErrorCode.c
@@ -8,50 +8,32 @@
 */
 
 #include "ErrorCode.h"
-
-/* private data members ----------------------------------------------------*/
+#include "JNIHelp.h"
 
 /**
-* Name of the java runtime exception classes
-*/
-#define ILLEGALARGUMENTEXCEPTION_       "java/lang/IllegalArgumentException"
-#define ARRAYINDEXOUTOFBOUNDSEXCEPTION_ "java/lang/ArrayIndexOutOfBoundsException"
-#define UNSUPPORTEDOPERATIONEXCEPTION_  "java/lang/UnsupportedOperationException"
-#define RUNTIMEEXCEPTION_               "java/lang/RuntimeException"
-
-/* public methods ---------------------------------------------------------*/
-
-/**
-* Checks if an error has occured. 
-* Throws a generic Java RuntimeException if an error has occured.
-* @param env JNI environment variable
-* @param errorcode code to determine if it is an erro
-* @return 0 if errorcode is not an error, 1 if errorcode is an error, but the 
+* Checks if an error has occurred, throwing a suitable exception if so.
+* @param env JNI environment
+* @param errorCode code to determine if it is an error
+* @return 0 if errorCode is not an error, 1 if errorCode is an error, but the
 *         creation of the exception to be thrown fails
-* @exception thrown if errorcode represents an error
+ * @exception thrown if errorCode represents an error
 */
-UBool icu4jni_error(JNIEnv *env, UErrorCode errorcode)
+UBool icu4jni_error(JNIEnv *env, UErrorCode errorCode)
 {
-  const char   *emsg      = u_errorName(errorcode);
-        jclass  exception;
-
-  if (errorcode > U_ZERO_ERROR && errorcode < U_ERROR_LIMIT) {
-    switch (errorcode) {
-      case U_ILLEGAL_ARGUMENT_ERROR :
-        exception = (*env)->FindClass(env, ILLEGALARGUMENTEXCEPTION_);
-        break;
-      case U_INDEX_OUTOFBOUNDS_ERROR :
-      case U_BUFFER_OVERFLOW_ERROR :
-        exception = (*env)->FindClass(env, ARRAYINDEXOUTOFBOUNDSEXCEPTION_);
-        break;
-      case U_UNSUPPORTED_ERROR :
-        exception = (*env)->FindClass(env, UNSUPPORTEDOPERATIONEXCEPTION_);
-        break;
-      default :
-        exception = (*env)->FindClass(env, RUNTIMEEXCEPTION_);
+    const char* message = u_errorName(errorCode);
+    if (errorCode <= U_ZERO_ERROR || errorCode >= U_ERROR_LIMIT) {
+        return 0;
     }
-
-    return ((*env)->ThrowNew(env, exception, emsg) != 0);
-  }
-  return 0;
+    
+    switch (errorCode) {
+    case U_ILLEGAL_ARGUMENT_ERROR:
+        return jniThrowException(env, "java/lang/IllegalArgumentException", message);
+    case U_INDEX_OUTOFBOUNDS_ERROR:
+    case U_BUFFER_OVERFLOW_ERROR:
+        return jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", message);
+    case U_UNSUPPORTED_ERROR:
+        return jniThrowException(env, "java/lang/UnsupportedOperationException", message);
+    default:
+        return jniThrowException(env, "java/lang/RuntimeException", message);
+    }
 }
diff --git a/libcore/icu/src/main/native/ErrorCode.h b/libcore/icu/src/main/native/ErrorCode.h
index a5bbfc6..e42a519 100644
--- a/libcore/icu/src/main/native/ErrorCode.h
+++ b/libcore/icu/src/main/native/ErrorCode.h
@@ -13,6 +13,10 @@
 #include "unicode/utypes.h"
 #include "unicode/putil.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
 * Checks if an error has occured. 
 * Throws a generic Java RuntimeException if an error has occured.
@@ -24,4 +28,8 @@
 */
 UBool icu4jni_error(JNIEnv *env, UErrorCode errorcode);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/libcore/icu/src/main/native/RBNFInterface.cpp b/libcore/icu/src/main/native/RBNFInterface.cpp
index d9bf460..c7486e1 100644
--- a/libcore/icu/src/main/native/RBNFInterface.cpp
+++ b/libcore/icu/src/main/native/RBNFInterface.cpp
@@ -25,32 +25,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-static UBool icuError(JNIEnv *env, UErrorCode errorcode)
-{
-  const char  *emsg = u_errorName(errorcode);
-  jclass  exception;
-
-  if (errorcode > U_ZERO_ERROR && errorcode < U_ERROR_LIMIT) {
-    switch (errorcode) {
-      case U_ILLEGAL_ARGUMENT_ERROR :
-        exception = env->FindClass("java/lang/IllegalArgumentException");
-        break;
-      case U_INDEX_OUTOFBOUNDS_ERROR :
-      case U_BUFFER_OVERFLOW_ERROR :
-        exception = env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-        break;
-      case U_UNSUPPORTED_ERROR :
-        exception = env->FindClass("java/lang/UnsupportedOperationException");
-        break;
-      default :
-        exception = env->FindClass("java/lang/RuntimeException");
-    }
-
-    return (env->ThrowNew(exception, emsg) != 0);
-  }
-  return 0;
-}
-
 static jint openRBNFImpl1(JNIEnv* env, jclass clazz, 
         jint type, jstring locale) {
 
@@ -72,7 +46,7 @@
     } else if(type == 3) {
         style = URBNF_COUNT;
     } else {
-        icuError(env, U_ILLEGAL_ARGUMENT_ERROR);
+        icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
     }
     
     Locale loc = Locale::createFromName(localeChars);
@@ -84,7 +58,7 @@
     env->ReleaseStringUTFChars(locale, localeChars);
 
     // check for an error
-    if ( icuError(env, status) != FALSE) {
+    if (icu4jni_error(env, status) != FALSE) {
         return 0;
     }
 
@@ -117,7 +91,7 @@
     env->ReleaseStringUTFChars(locale, localeChars);
 
     // check for an error
-    if ( icuError(env, status) != FALSE) {
+    if (icu4jni_error(env, status) != FALSE) {
         return 0;
     }
 
@@ -183,7 +157,7 @@
 
         res.extract(result, reslenneeded + 1, status);
     }
-    if (icuError(env, status) != FALSE) {
+    if (icu4jni_error(env, status) != FALSE) {
         free(result);
         return NULL;
     }
@@ -245,7 +219,7 @@
 
         res.extract(result, reslenneeded + 1, status);
     }
-    if (icuError(env, status) != FALSE) {
+    if (icu4jni_error(env, status) != FALSE) {
         free(result);
         return NULL;
     }
@@ -265,22 +239,11 @@
         jobject position, jboolean lenient) {
 
     // LOGI("ENTER parseRBNFImpl");
-
-    const char * parsePositionClassName = "java/text/ParsePosition";
-    const char * longClassName = "java/lang/Long";
-    const char * doubleClassName = "java/lang/Double";
-
-
-    UErrorCode status = U_ZERO_ERROR;
-
-    UNumberFormat *fmt = (UNumberFormat *)(int)addr;
-
-    jchar *str = (UChar *)env->GetStringChars(text, NULL);
-    int strlength = env->GetStringLength(text);
-
-    jclass parsePositionClass = env->FindClass(parsePositionClassName);
-    jclass longClass =  env->FindClass(longClassName);
-    jclass doubleClass =  env->FindClass(doubleClassName);
+    
+    // TODO: cache these?
+    jclass parsePositionClass = env->FindClass("java/text/ParsePosition");
+    jclass longClass =  env->FindClass("java/lang/Long");
+    jclass doubleClass =  env->FindClass("java/lang/Double");
 
     jmethodID getIndexMethodID = env->GetMethodID(parsePositionClass, 
             "getIndex", "()I");
@@ -292,22 +255,25 @@
     jmethodID longInitMethodID = env->GetMethodID(longClass, "<init>", "(J)V");
     jmethodID dblInitMethodID = env->GetMethodID(doubleClass, "<init>", "(D)V");
 
-    int parsePos = env->CallIntMethod(position, getIndexMethodID, NULL);
-
     // make sure the ParsePosition is valid. Actually icu4c would parse a number 
     // correctly even if the parsePosition is set to -1, but since the RI fails 
     // for that case we have to fail too
+    int parsePos = env->CallIntMethod(position, getIndexMethodID, NULL);
+    const int strlength = env->GetStringLength(text);
     if(parsePos < 0 || parsePos > strlength) {
         return NULL;
     }
-
+    
     Formattable res;
-
+    
+    jchar *str = (UChar *)env->GetStringChars(text, NULL);
+    
     const UnicodeString src((UChar*)str, strlength, strlength);
     ParsePosition pp;
     
     pp.setIndex(parsePos);
     
+    UNumberFormat *fmt = (UNumberFormat *)(int)addr;
     if(lenient) {
         unum_setAttribute(fmt, UNUM_LENIENT_PARSE, JNI_TRUE);
     }
@@ -328,35 +294,23 @@
         return NULL;
     }
 
-    Formattable::Type numType;
-    numType = res.getType();
-    UErrorCode fmtStatus;
-
-    double resultDouble;
-    long resultLong;
-    int64_t resultInt64;
-
-    switch(numType) {
-        case Formattable::kDouble:
-            resultDouble = res.getDouble();
-            env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
-            return env->NewObject(doubleClass, dblInitMethodID, 
-                    (jdouble) resultDouble);
-        case Formattable::kLong:
-            resultLong = res.getLong();
-            env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
-            return env->NewObject(longClass, longInitMethodID, 
-                    (jlong) resultLong);
-        case Formattable::kInt64:
-            resultInt64 = res.getInt64();
-            env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
-            return env->NewObject(longClass, longInitMethodID, 
-                    (jlong) resultInt64);
-        default:
-            break;
+    Formattable::Type numType = res.getType();
+    if (numType == Formattable::kDouble) {
+        double resultDouble = res.getDouble();
+        env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
+        return env->NewObject(doubleClass, dblInitMethodID,
+                              (jdouble) resultDouble);
+    } else if (numType == Formattable::kLong) {
+        long resultLong = res.getLong();
+        env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
+        return env->NewObject(longClass, longInitMethodID, (jlong) resultLong);
+    } else if (numType == Formattable::kInt64) {
+        int64_t resultInt64 = res.getInt64();
+        env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
+        return env->NewObject(longClass, longInitMethodID, (jlong) resultInt64);
+    } else {
+        return NULL;
     }
-
-    return NULL;
 }
 
 static JNINativeMethod gMethods[] = {
diff --git a/libcore/icu/src/main/native/RegExInterface.cpp b/libcore/icu/src/main/native/RegExInterface.cpp
index afa5cc4..0ca3d06 100644
--- a/libcore/icu/src/main/native/RegExInterface.cpp
+++ b/libcore/icu/src/main/native/RegExInterface.cpp
@@ -32,12 +32,12 @@
  * character data it refers to (but does not have a copy of), so we can
  * manage memory properly.
  */
-typedef struct RegExDataStruct {
+struct RegExData {
     // A pointer to the ICU regular expression
     URegularExpression* regex;
     // A pointer to (a copy of) the input text that *we* manage
     jchar* text;
-} RegExData;
+};
 
 static void throwPatternSyntaxException(JNIEnv* env, UErrorCode status,
                                         jstring pattern, UParseError error)
@@ -63,8 +63,8 @@
         uregex_close(data->regex);
     }
 
-    if (data->text != NULL && data->text != &EMPTY_STRING) {
-        free(data->text);
+    if (data->text != &EMPTY_STRING) {
+        delete[] data->text;
     }
 
     free(data);
@@ -125,8 +125,8 @@
         return;
     }
 
-    if (data->text != NULL && data->text != &EMPTY_STRING) {
-        free(data->text);
+    if (data->text != &EMPTY_STRING) {
+        delete[] data->text;
         data->text = NULL;
     }
 
@@ -134,11 +134,9 @@
     if (textLen == 0) {
         data->text = &EMPTY_STRING;
     } else {
-        jchar const * textRaw = env->GetStringChars(text, NULL);
-        data->text = (jchar*)malloc((textLen + 1) * sizeof(jchar));
-        memcpy(data->text, textRaw, textLen * sizeof(jchar));
+        data->text = new jchar[textLen + 1];
+        env->GetStringRegion(text, 0, textLen, data->text);
         data->text[textLen] = 0;
-        env->ReleaseStringChars(text, textRaw);
     }
 
     uregex_setText(data->regex, data->text, textLen, &status);
diff --git a/libcore/icu/src/main/native/ResourceInterface.cpp b/libcore/icu/src/main/native/ResourceInterface.cpp
index a88e15c..731cf3f 100644
--- a/libcore/icu/src/main/native/ResourceInterface.cpp
+++ b/libcore/icu/src/main/native/ResourceInterface.cpp
@@ -40,32 +40,6 @@
 
 jclass string_class;
 
-static UBool icuError(JNIEnv *env, UErrorCode errorcode)
-{
-  const char   *emsg      = u_errorName(errorcode);
-        jclass  exception;
-
-  if (U_FAILURE(errorcode)) {
-    switch (errorcode) {
-      case U_ILLEGAL_ARGUMENT_ERROR :
-        exception = env->FindClass("java/lang/IllegalArgumentException");
-        break;
-      case U_INDEX_OUTOFBOUNDS_ERROR :
-      case U_BUFFER_OVERFLOW_ERROR :
-        exception = env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-        break;
-      case U_UNSUPPORTED_ERROR :
-        exception = env->FindClass("java/lang/UnsupportedOperationException");
-        break;
-      default :
-        exception = env->FindClass("java/lang/RuntimeException");
-    }
-
-    return (env->ThrowNew(exception, emsg) != 0);
-  }
-  return 0;
-}
-
 static Locale getLocale(JNIEnv *env, jstring locale) {
     const char *name = env->GetStringUTFChars(locale, NULL);
     Locale result = Locale::createFromName(name);
diff --git a/libcore/icu/src/test/java/com/ibm/icu4jni/util/AllTests.java b/libcore/icu/src/test/java/com/ibm/icu4jni/util/AllTests.java
new file mode 100644
index 0000000..1b95075
--- /dev/null
+++ b/libcore/icu/src/test/java/com/ibm/icu4jni/util/AllTests.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.icu4jni.util;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+    public static final Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+        suite.addTestSuite(com.ibm.icu4jni.util.ResourcesTest.class);
+        return suite;
+    }
+}
diff --git a/libcore/icu/src/test/java/com/ibm/icu4jni/util/ResourcesTest.java b/libcore/icu/src/test/java/com/ibm/icu4jni/util/ResourcesTest.java
new file mode 100644
index 0000000..4112d0b
--- /dev/null
+++ b/libcore/icu/src/test/java/com/ibm/icu4jni/util/ResourcesTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.icu4jni.util;
+
+public class ResourcesTest extends junit.framework.TestCase {
+    public void test_getISOLanguages() throws Exception {
+        // Check that corrupting our array doesn't affect other callers.
+        assertNotNull(Resources.getISOLanguages()[0]);
+        Resources.getISOLanguages()[0] = null;
+        assertNotNull(Resources.getISOLanguages()[0]);
+    }
+
+    public void test_getISOCountries() throws Exception {
+        // Check that corrupting our array doesn't affect other callers.
+        assertNotNull(Resources.getISOCountries()[0]);
+        Resources.getISOCountries()[0] = null;
+        assertNotNull(Resources.getISOCountries()[0]);
+    }
+
+    public void test_getAvailableLocales() throws Exception {
+        // Check that corrupting our array doesn't affect other callers.
+        assertNotNull(Resources.getAvailableLocales()[0]);
+        Resources.getAvailableLocales()[0] = null;
+        assertNotNull(Resources.getAvailableLocales()[0]);
+    }
+
+    public void test_getKnownTimezones() throws Exception {
+        // Check that corrupting our array doesn't affect other callers.
+        assertNotNull(Resources.getKnownTimezones()[0]);
+        Resources.getKnownTimezones()[0] = null;
+        assertNotNull(Resources.getKnownTimezones()[0]);
+    }
+
+    public void test_getDisplayTimeZones() throws Exception {
+        // Check that corrupting our array doesn't affect other callers.
+        assertNotNull(Resources.getDisplayTimeZones(null)[0]);
+        Resources.getDisplayTimeZones(null)[0] = null;
+        assertNotNull(Resources.getDisplayTimeZones(null)[0]);
+        // getDisplayTimezones actually returns a String[][] rather than a String[].
+        assertNotNull(Resources.getDisplayTimeZones(null)[0][0]);
+        Resources.getDisplayTimeZones(null)[0][0] = null;
+        assertNotNull(Resources.getDisplayTimeZones(null)[0][0]);
+    }
+}
diff --git a/libcore/luni-kernel/src/main/java/java/lang/Package.java b/libcore/luni-kernel/src/main/java/java/lang/Package.java
index 2817404..4d98959 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/Package.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/Package.java
@@ -268,8 +268,8 @@
      */
     public boolean isCompatibleWith(String version)
             throws NumberFormatException {
-        String[] requested = version.split("."); 
-        String[] provided = specVersion.split("."); 
+        String[] requested = version.split("\\."); 
+        String[] provided = specVersion.split("\\."); 
         
         for (int i = 0; i < Math.min(requested.length, provided.length); i++) {
             int reqNum = Integer.parseInt(requested[i]);
@@ -318,4 +318,3 @@
         return "package " + name;
     }
 }
-
diff --git a/libcore/luni-kernel/src/main/java/java/lang/ref/Reference.java b/libcore/luni-kernel/src/main/java/java/lang/ref/Reference.java
index ca7290b..c695830 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/ref/Reference.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/ref/Reference.java
@@ -49,7 +49,7 @@
      * VM requirement: this field <em>must</em> be called "referent"
      * and be an object.
      */
-    T referent;
+    volatile T referent;
 
     /**
      * If non-null, the queue on which this reference will be enqueued
@@ -58,7 +58,7 @@
      * and be a java.lang.ref.ReferenceQueue.
      */
     @SuppressWarnings("unchecked")
-    ReferenceQueue queue;
+    volatile ReferenceQueue queue;
 
     /**
      * Used internally by java.lang.ref.ReferenceQueue.
@@ -66,7 +66,7 @@
      * and be a java.lang.ref.Reference.
      */
     @SuppressWarnings("unchecked")
-    Reference queueNext;
+    volatile Reference queueNext;
 
     /**
      * Used internally by Dalvik.
@@ -74,7 +74,7 @@
      * and be an int.
      */
     @SuppressWarnings("unused")
-    private int vmData;
+    volatile private int vmData;
 
     /**
      * Constructs a new instance of this class.
diff --git a/libcore/luni-kernel/src/main/java/java/lang/reflect/Constructor.java b/libcore/luni-kernel/src/main/java/java/lang/reflect/Constructor.java
index c6927eb..3918d7e 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/reflect/Constructor.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/reflect/Constructor.java
@@ -161,12 +161,12 @@
         appendArrayGenericType(sb, 
                 Types.getClonedTypeArray(genericParameterTypes));
         sb.append(')');
-        // append exeptions if any
-        Type[] genericEceptionTypeArray = 
+        // append exceptions if any
+        Type[] genericExceptionTypeArray = 
                 Types.getClonedTypeArray(genericExceptionTypes);
-        if (genericEceptionTypeArray.length > 0) {
+        if (genericExceptionTypeArray.length > 0) {
             sb.append(" throws ");
-            appendArrayGenericType(sb, genericEceptionTypeArray);
+            appendArrayGenericType(sb, genericExceptionTypeArray);
         }
         return sb.toString();
     }
@@ -314,7 +314,7 @@
     public Class<?>[] getExceptionTypes() {
         if (exceptionTypes == null)
             return new Class[0];
-        return exceptionTypes;
+        return exceptionTypes.clone();
     }
 
     /**
@@ -354,7 +354,7 @@
      * @since Android 1.0
      */
     public Class<?>[] getParameterTypes() {
-        return parameterTypes;
+        return parameterTypes.clone();
     }
 
     /**
diff --git a/libcore/luni-kernel/src/main/java/java/lang/reflect/Method.java b/libcore/luni-kernel/src/main/java/java/lang/reflect/Method.java
index 473726d..dabf9a4 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/reflect/Method.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/reflect/Method.java
@@ -383,7 +383,7 @@
             return new Class[0];
         }
 
-        return exceptionTypes;
+        return exceptionTypes.clone();
     }
 
     /**
@@ -424,7 +424,7 @@
      * @since Android 1.0
      */
     public Class<?>[] getParameterTypes() {
-        return parameterTypes;
+        return parameterTypes.clone();
     }
 
     /**
@@ -521,7 +521,7 @@
         return invokeNative (receiver, args, declaringClass, parameterTypes, returnType, slot, flag);
     }
 
-    private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass, Class<?>[] parameterTYpes, Class<?> returnType, int slot, boolean noAccessCheck)
+    private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass, Class<?>[] parameterTypes, Class<?> returnType, int slot, boolean noAccessCheck)
     throws IllegalAccessException,
              IllegalArgumentException,
              InvocationTargetException;
diff --git a/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c b/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
index eaefc9f..46e78f5 100644
--- a/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
+++ b/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
@@ -64,8 +64,7 @@
         jclass clazz, jobject javaDescriptor) {
     int fd = (*env)->GetIntField(env, javaDescriptor, descriptorField);
     if (closeNow(fd) == -1) {
-        jclass ioException = (*env)->FindClass(env, "java/io/IOException");
-        (*env)->ThrowNew(env, ioException, strerror(errno));
+        jniThrowIOException(env, errno);
     }
 }
 
diff --git a/libcore/luni-kernel/src/test/java/java/lang/reflect/AllTests.java b/libcore/luni-kernel/src/test/java/java/lang/reflect/AllTests.java
new file mode 100644
index 0000000..7cf1475
--- /dev/null
+++ b/libcore/luni-kernel/src/test/java/java/lang/reflect/AllTests.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang.reflect;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+    public static final Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+        suite.addTestSuite(java.lang.reflect.ConstructorTest.class);
+        suite.addTestSuite(java.lang.reflect.MethodTest.class);
+        return suite;
+    }
+}
diff --git a/libcore/luni-kernel/src/test/java/java/lang/reflect/ConstructorTest.java b/libcore/luni-kernel/src/test/java/java/lang/reflect/ConstructorTest.java
new file mode 100644
index 0000000..e2672a8
--- /dev/null
+++ b/libcore/luni-kernel/src/test/java/java/lang/reflect/ConstructorTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang.reflect;
+
+public class ConstructorTest extends junit.framework.TestCase {
+    public void test_getExceptionTypes() throws Exception {
+        Constructor<?> constructor = ConstructorTestHelper.class.getConstructor(new Class[0]);
+        Class[] exceptions = constructor.getExceptionTypes();
+        assertEquals(1, exceptions.length);
+        assertEquals(IndexOutOfBoundsException.class, exceptions[0]);
+        // Check that corrupting our array doesn't affect other callers.
+        exceptions[0] = NullPointerException.class;
+        exceptions = constructor.getExceptionTypes();
+        assertEquals(1, exceptions.length);
+        assertEquals(IndexOutOfBoundsException.class, exceptions[0]);
+    }
+
+    public void test_getParameterTypes() throws Exception {
+        Class[] expectedParameters = new Class[] { Object.class };
+        Constructor<?> constructor = ConstructorTestHelper.class.getConstructor(expectedParameters);
+        Class[] parameters = constructor.getParameterTypes();
+        assertEquals(1, parameters.length);
+        assertEquals(expectedParameters[0], parameters[0]);
+        // Check that corrupting our array doesn't affect other callers.
+        parameters[0] = String.class;
+        parameters = constructor.getParameterTypes();
+        assertEquals(1, parameters.length);
+        assertEquals(expectedParameters[0], parameters[0]);
+    }
+
+    static class ConstructorTestHelper {
+        public ConstructorTestHelper() throws IndexOutOfBoundsException { }
+        public ConstructorTestHelper(Object o) { }
+    }
+}
diff --git a/libcore/luni-kernel/src/test/java/java/lang/reflect/MethodTest.java b/libcore/luni-kernel/src/test/java/java/lang/reflect/MethodTest.java
new file mode 100644
index 0000000..ed41de9
--- /dev/null
+++ b/libcore/luni-kernel/src/test/java/java/lang/reflect/MethodTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang.reflect;
+
+public class MethodTest extends junit.framework.TestCase {
+    public void test_getExceptionTypes() throws Exception {
+        Method method = MethodTestHelper.class.getMethod("m1", new Class[0]);
+        Class[] exceptions = method.getExceptionTypes();
+        assertEquals(1, exceptions.length);
+        assertEquals(IndexOutOfBoundsException.class, exceptions[0]);
+        // Check that corrupting our array doesn't affect other callers.
+        exceptions[0] = NullPointerException.class;
+        exceptions = method.getExceptionTypes();
+        assertEquals(1, exceptions.length);
+        assertEquals(IndexOutOfBoundsException.class, exceptions[0]);
+    }
+
+    public void test_getParameterTypes() throws Exception {
+        Class[] expectedParameters = new Class[] { Object.class };
+        Method method = MethodTestHelper.class.getMethod("m2", expectedParameters);
+        Class[] parameters = method.getParameterTypes();
+        assertEquals(1, parameters.length);
+        assertEquals(expectedParameters[0], parameters[0]);
+        // Check that corrupting our array doesn't affect other callers.
+        parameters[0] = String.class;
+        parameters = method.getParameterTypes();
+        assertEquals(1, parameters.length);
+        assertEquals(expectedParameters[0], parameters[0]);
+    }
+
+    static class MethodTestHelper {
+        public void m1() throws IndexOutOfBoundsException { }
+        public void m2(Object o) { }
+    }
+}
diff --git a/libcore/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/AllTests.java b/libcore/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/AllTests.java
new file mode 100644
index 0000000..a59cc3e
--- /dev/null
+++ b/libcore/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/AllTests.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.org.apache.harmony.kernel.dalvik;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+    public static final Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+        suite.addTestSuite(tests.api.org.apache.harmony.kernel.dalvik.ThreadsTest.class);
+        return suite;
+    }
+}
diff --git a/libcore/luni/src/main/java/java/io/BufferedOutputStream.java b/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
index 6d52dee..8b7c4f5 100644
--- a/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
@@ -148,17 +148,16 @@
             out.write(buffer, offset, length);
             return;
         }
-
-        // BEGIN android-changed
-        // Exception priorities (in case of multiple errors) differ from
-        // RI, but are spec-compliant.
-        // used (offset | length) < 0 instead of (offset < 0) || (length < 0)
-        // to safe one operation
-        if ((offset | length) < 0 || offset > buffer.length - length) {
-            // K002f=Arguments out of bounds
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+        
+        if (offset < 0 || offset > buffer.length - length) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
+        
         }
-        // END android-changed
+        if (length < 0) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
+        }
 
         // flush the internal buffer first if we have not enough space left
         if (length >= (buf.length - count)) {
diff --git a/libcore/luni/src/main/java/java/io/CharArrayReader.java b/libcore/luni/src/main/java/java/io/CharArrayReader.java
index d2757f6..6753faa 100644
--- a/libcore/luni/src/main/java/java/io/CharArrayReader.java
+++ b/libcore/luni/src/main/java/java/io/CharArrayReader.java
@@ -213,20 +213,16 @@
         // 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.
-        // made implicit null check explicit,
-        // removed redundant check, used (offset | len) < 0 instead of
-        // (offset < 0) || (len < 0) to safe one operation
-        if (buffer == null) {
-            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+        if (offset < 0 || offset > buffer.length) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(
+                    Msg.getString("K002e", offset)); //$NON-NLS-1$
         }
-        if ((offset | len) < 0 || len > buffer.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+        if (len < 0 || len > buffer.length - offset) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(
+                    Msg.getString("K0031", len)); //$NON-NLS-1$
         }
-        // END android-changed
         synchronized (lock) {
             if (isClosed()) {
                 throw new IOException(Msg.getString("K0060")); //$NON-NLS-1$
diff --git a/libcore/luni/src/main/java/java/io/DataOutputStream.java b/libcore/luni/src/main/java/java/io/DataOutputStream.java
index 18e04a5..4152173 100644
--- a/libcore/luni/src/main/java/java/io/DataOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/DataOutputStream.java
@@ -280,6 +280,19 @@
         written += 8;
     }
 
+    int writeLongToBuffer(long val,
+                          byte[] buffer, int offset) throws IOException {
+        buffer[offset++] = (byte) (val >> 56);
+        buffer[offset++] = (byte) (val >> 48);
+        buffer[offset++] = (byte) (val >> 40);
+        buffer[offset++] = (byte) (val >> 32);
+        buffer[offset++] = (byte) (val >> 24);
+        buffer[offset++] = (byte) (val >> 16);
+        buffer[offset++] = (byte) (val >> 8);
+        buffer[offset++] = (byte) val;
+        return offset;
+    }
+
     /**
      * 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
@@ -299,6 +312,13 @@
         written += 2;
     }
 
+    int writeShortToBuffer(int val,
+                           byte[] buffer, int offset) throws IOException {
+        buffer[offset++] = (byte) (val >> 8);
+        buffer[offset++] = (byte) val;
+        return offset;
+    }
+
     /**
      * Writes the specified encoded in {@link DataInput modified UTF-8} to this
      * stream.
@@ -317,8 +337,14 @@
         if (utfCount > 65535) {
             throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
         }
-        writeShort((int) utfCount);
-        writeUTFBytes(str, utfCount);
+        byte[] buffer = new byte[(int)utfCount + 2];
+        int offset = 0;
+        offset = writeShortToBuffer((int) utfCount, buffer, offset);
+        // BEGIN android-changed
+        // removed unused parameter count
+        offset = writeUTFBytesToBuffer(str, buffer, offset);
+        // BEGIN android-changed
+        write(buffer, 0, offset);
     }
 
     long countUTFBytes(String str) {
@@ -336,24 +362,25 @@
         return utfCount;
     }
 
-    void writeUTFBytes(String str, long count) throws IOException {
-        int size = (int) count;
+    int writeUTFBytesToBuffer(String str,
+            byte[] buffer, int offset) throws IOException {
+        // BEGIN android-note
+        // removed unused parameter count
+        // END android-note
         int length = str.length();
-        byte[] utfBytes = new byte[size];
-        int utfIndex = 0;
         for (int i = 0; i < length; i++) {
             int charValue = str.charAt(i);
             if (charValue > 0 && charValue <= 127) {
-                utfBytes[utfIndex++] = (byte) charValue;
+                buffer[offset++] = (byte) charValue;
             } else if (charValue <= 2047) {
-                utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
-                utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
+                buffer[offset++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
+                buffer[offset++] = (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));
+                buffer[offset++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
+                buffer[offset++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
+                buffer[offset++] = (byte) (0x80 | (0x3f & charValue));
              }
         }
-        write(utfBytes, 0, utfIndex);
+        return offset;
     }
 }
diff --git a/libcore/luni/src/main/java/java/io/EmulatedFieldsForDumping.java b/libcore/luni/src/main/java/java/io/EmulatedFieldsForDumping.java
index 16c7986..c3743dd 100644
--- a/libcore/luni/src/main/java/java/io/EmulatedFieldsForDumping.java
+++ b/libcore/luni/src/main/java/java/io/EmulatedFieldsForDumping.java
@@ -192,7 +192,6 @@
      */
     @Override
     @Deprecated
-    @SuppressWarnings("deprecation")
     public void write(ObjectOutput output) throws IOException {
         EmulatedFields.ObjectSlot[] slots = emulatedFields.slots();
         for (int i = 0; i < slots.length; i++) {
diff --git a/libcore/luni/src/main/java/java/io/File.java b/libcore/luni/src/main/java/java/io/File.java
index c802995..cde9fcc 100644
--- a/libcore/luni/src/main/java/java/io/File.java
+++ b/libcore/luni/src/main/java/java/io/File.java
@@ -761,9 +761,8 @@
      * Indicates if this file's pathname is absolute. Whether a pathname is
      * absolute is platform specific. On UNIX, absolute paths must start with
      * the character '/'; on Windows it is absolute if either it starts with
-     * '\', '/', '\\' (to represent a file server), or a letter followed by a
-     * colon.
-     *
+     * '\\' (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
@@ -775,10 +774,6 @@
         // END android-changed
     }
 
-    // BEGIN android-removed
-    // private native boolean isAbsoluteImpl(byte[] filePath);
-    // END android-removed
-
     /**
      * Indicates if this file represents a <em>directory</em> on the
      * underlying file system.
@@ -1358,8 +1353,10 @@
         if (properPath != null) {
             return properPath;
         }
-        if(path.length() > 0 && path.charAt(0) == separatorChar) {
-            return properPath = Util.getBytes(path);
+
+        if (isAbsolute()) {
+            byte[] pathBytes = Util.getUTF8Bytes(path);
+            return properPath = pathBytes;
         }
         // Check security by getting user.dir when the path is not absolute
         String userdir;
@@ -1380,10 +1377,6 @@
     }
     // END android-changed
 
-    // BEGIN android-removed
-    // private static native byte[] properPathImpl(byte[] path);
-    // END android-removed
-
     /**
      * Renames this file to the name represented by the {@code dest} file. This
      * works for both normal files and directories.
diff --git a/libcore/luni/src/main/java/java/io/FileInputStream.java b/libcore/luni/src/main/java/java/io/FileInputStream.java
index 1243262..077cd23 100644
--- a/libcore/luni/src/main/java/java/io/FileInputStream.java
+++ b/libcore/luni/src/main/java/java/io/FileInputStream.java
@@ -69,9 +69,14 @@
         super();
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
+            // For compatibility, nulls are passed to the manager.
             String filePath = (null == file ? null : file.getPath());
             security.checkRead(filePath);
         }
+        if (file == null) {
+            // KA001=Argument must not be null
+            throw new NullPointerException(Msg.getString("KA001")); //$NON-NLS-1$
+        }
         fd = new FileDescriptor();
         fd.readOnly = true;
         fd.descriptor = fileSystem.open(file.properPath(true),
@@ -312,25 +317,24 @@
         }
         openCheck();
         synchronized (repositioningLock) {
-            // stdin requires special handling
-            if (fd == FileDescriptor.in) {
-                return (int) fileSystem.ttyRead(buffer, offset, count);
-            }
+            // BEGIN android-changed
+            // If you only support Linux, there's nothing special about stdin.
             return (int) fileSystem.read(fd.descriptor, buffer, offset, count);
+            // END android-changed
         }
     }
 
     /**
      * 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.
+     * {@code read()}s will not return these bytes unless {@code reset()} is
+     * used. If the underlying stream is unseekable, an IOException is thrown.
      *
      * @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.
+     *             if {@code count < 0}, this stream is closed or unseekable,
+     *             or another IOException occurs.
      */
     @Override
     public long skip(long count) throws IOException {
@@ -344,29 +348,18 @@
             throw new IOException(Msg.getString("KA013")); //$NON-NLS-1$
         }
 
-        // stdin requires special handling
-        if (fd == FileDescriptor.in) {
-            // Read and discard count bytes in 8k chunks
-            long skipped = 0, numRead;
-            int chunk = count < 8192 ? (int) count : 8192;
-            byte[] buffer = new byte[chunk];
-            for (long i = count / chunk; i >= 0; i--) {
-                numRead = fileSystem.ttyRead(buffer, 0, chunk);
-                skipped += numRead;
-                if (numRead < chunk) {
-                    return skipped;
-                }
-            }
-            return skipped;
-        }
-
+        // BEGIN android-changed
+        // The RI doesn't treat stdin as special. It throws IOException for
+        // all non-seekable streams, so we do too. If you did want to support
+        // non-seekable streams, the best way to do it would be to recognize
+        // when lseek(2) fails with ESPIPE and call super.skip(count).
         synchronized (repositioningLock) {
-            final long currentPosition = fileSystem.seek(fd.descriptor, 0L,
-                    IFileSystem.SEEK_CUR);
-            final long newPosition = fileSystem.seek(fd.descriptor,
-                    currentPosition + count, IFileSystem.SEEK_SET);
-            return newPosition - currentPosition;
+            // Our seek returns the new offset, but we know it will throw an
+            // exception if it couldn't perform exactly the seek we asked for.
+            fileSystem.seek(fd.descriptor, count, IFileSystem.SEEK_CUR);
+            return count;
         }
+        // END android-changed
     }
 
     private synchronized void openCheck() throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/FilterOutputStream.java b/libcore/luni/src/main/java/java/io/FilterOutputStream.java
index 66765f9..fa837ee 100644
--- a/libcore/luni/src/main/java/java/io/FilterOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/FilterOutputStream.java
@@ -102,7 +102,7 @@
      *            the buffer to write.
      * @param offset
      *            the index of the first byte in {@code buffer} to write.
-     * @param count
+     * @param length
      *            the number of bytes in {@code buffer} to write.
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if
@@ -112,25 +112,20 @@
      *             if an I/O error occurs while writing to this stream.
      */
     @Override
-    public void write(byte[] buffer, int offset, int count) throws IOException {
+    public void write(byte[] buffer, int offset, int length) throws IOException {
         // BEGIN android-note
         // changed array notation to be consistent with the rest of harmony
         // END android-note
-        // avoid int overflow, force null buffer check first
-        // BEGIN android-changed
-        // Exception priorities (in case of multiple errors) differ from
-        // RI, but are spec-compliant.
-        // removed redundant check, made implicit null check explicit,
-        // used (offset | count) < 0 instead of (offset < 0) || (count < 0)
-        // to safe one operation
-        if (buffer == null) {
-            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+        // Force null buffer check first!
+        if (offset > buffer.length || offset < 0) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
         }
-        if ((offset | count) < 0 || count > buffer.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+        if (length < 0 || length > buffer.length - offset) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
         }
-        // END android-changed
-        for (int i = 0; i < count; i++) {
+        for (int i = 0; i < length; i++) {
             // Call write() instead of out.write() since subclasses could
             // override the write() method.
             write(buffer[offset + i]);
diff --git a/libcore/luni/src/main/java/java/io/InputStream.java b/libcore/luni/src/main/java/java/io/InputStream.java
index f20ce7d..33a5cfd 100644
--- a/libcore/luni/src/main/java/java/io/InputStream.java
+++ b/libcore/luni/src/main/java/java/io/InputStream.java
@@ -17,9 +17,7 @@
 
 package java.io;
 
-// BEGIN android-added
 import org.apache.harmony.luni.util.Msg;
-// END android-added
 
 /**
  * The base class for all input streams. An input stream is a means of reading
@@ -157,20 +155,15 @@
         // BEGIN android-note
         // changed array notation to be consistent with the rest of harmony
         // END android-note
-        // avoid int overflow, check null b
-        // BEGIN android-changed
-        // Exception priorities (in case of multiple errors) differ from
-        // RI, but are spec-compliant.
-        // removed redundant check, made implicit null check explicit,
-        // used (offset | length) < 0 instead of (offset < 0) || (length < 0)
-        // to safe one operation
-        if (b == null) {
-            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+        // Force null check for b first!
+        if (offset > b.length || offset < 0) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
+        } 
+        if (length < 0 || length > b.length - offset) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
         }
-        if ((offset | length) < 0 || length > b.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
-        }
-        // END android-changed
         for (int i = 0; i < length; i++) {
             int c;
             try {
@@ -224,11 +217,16 @@
         }
         long skipped = 0;
         int toRead = n < 4096 ? (int) n : 4096;
-        if (skipBuf == null || skipBuf.length < toRead) {
-            skipBuf = new byte[toRead];
+        // We are unsynchronized, so take a local copy of the skipBuf at some
+        // point in time.
+        byte[] localBuf = skipBuf;
+        if (localBuf == null || localBuf.length < toRead) {
+            // May be lazily written back to the static. No matter if it
+            // overwrites somebody else's store.
+            skipBuf = localBuf = new byte[toRead];
         }
         while (skipped < n) {
-            int read = read(skipBuf, 0, toRead);
+            int read = read(localBuf, 0, toRead);
             if (read == -1) {
                 return skipped;
             }
diff --git a/libcore/luni/src/main/java/java/io/LineNumberInputStream.java b/libcore/luni/src/main/java/java/io/LineNumberInputStream.java
index 1a40177..3df3a05 100644
--- a/libcore/luni/src/main/java/java/io/LineNumberInputStream.java
+++ b/libcore/luni/src/main/java/java/io/LineNumberInputStream.java
@@ -17,9 +17,7 @@
 
 package java.io;
 
-// BEGIN android-added
 import org.apache.harmony.luni.util.Msg;
-// END android-added
 
 /**
  * Wraps an existing {@link InputStream} and counts the line terminators
@@ -171,19 +169,15 @@
      */
     @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
-        // BEGIN android-changed
-        if (buffer == null) {
-            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+        // Force buffer null check first!
+        if (offset > buffer.length || offset < 0) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
+        } 
+        if (length < 0 || length > buffer.length - offset) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
         }
-        // avoid int overflow
-        // Exception priorities (in case of multiple errors) differ from
-        // RI, but are spec-compliant.
-        // removed redundant check, used (offset | length) < 0
-        // instead of (offset < 0) || (length < 0) to safe one operation
-        if ((offset | length) < 0 || length > buffer.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
-        }
-        // END android-changed
 
         for (int i = 0; i < length; i++) {
             int currentChar;
diff --git a/libcore/luni/src/main/java/java/io/NotSerializableException.java b/libcore/luni/src/main/java/java/io/NotSerializableException.java
index f6e93a7..d85586a 100644
--- a/libcore/luni/src/main/java/java/io/NotSerializableException.java
+++ b/libcore/luni/src/main/java/java/io/NotSerializableException.java
@@ -19,9 +19,9 @@
 
 /**
  * Signals that an object that is not serializable has been passed into the
- * {@code ObjectOutput.writeObject()} mthod. This can happen if the object does
- * not implement {@code Serializable} or {@code Externalizable}, or if it is
- * serializable but it overrides {@code writeObject(ObjectOutputStream)} and
+ * {@code ObjectOutput.writeObject()} method. This can happen if the object
+ * does not implement {@code Serializable} or {@code Externalizable}, or if it
+ * is serializable but it overrides {@code writeObject(ObjectOutputStream)} and
  * explicitly prevents serialization by throwing this type of exception.
  * 
  * @see ObjectOutput#writeObject(Object)
diff --git a/libcore/luni/src/main/java/java/io/ObjectInputStream.java b/libcore/luni/src/main/java/java/io/ObjectInputStream.java
index 6d24eb2..df6d9a2 100644
--- a/libcore/luni/src/main/java/java/io/ObjectInputStream.java
+++ b/libcore/luni/src/main/java/java/io/ObjectInputStream.java
@@ -701,19 +701,15 @@
      */
     @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
-        // BEGIN android-changed
-        if (buffer == null) {
-            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+        // Force buffer null check first!
+        if (offset > buffer.length || offset < 0) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
         }
-        // avoid int overflow
-        // Exception priorities (in case of multiple errors) differ from
-        // RI, but are spec-compliant.
-        // removed redundant check, used (offset | length) < 0 instead of
-        // (offset < 0) || (length < 0) to safe one operation
-        if ((offset | length) < 0 || length > buffer.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+        if (length < 0 || length > buffer.length - offset) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
         }
-        // END android-changed
         if (length == 0) {
             return 0;
         }
diff --git a/libcore/luni/src/main/java/java/io/ObjectOutputStream.java b/libcore/luni/src/main/java/java/io/ObjectOutputStream.java
index e3c1471..7c85d4b 100644
--- a/libcore/luni/src/main/java/java/io/ObjectOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/ObjectOutputStream.java
@@ -1617,14 +1617,19 @@
     private Integer writeNewString(String object, boolean unshared)
             throws IOException {
         long count = output.countUTFBytes(object);
+        byte[] buffer;
+        int offset = 0;
         if (count <= 0xffff) {
-            output.writeByte(TC_STRING);
-            output.writeShort((short) count);
+            buffer = new byte[(int)count+3];
+            buffer[offset++] = TC_STRING;
+            offset = output.writeShortToBuffer((short) count, buffer, offset);
         } else {
-            output.writeByte(TC_LONGSTRING);
-            output.writeLong(count);
+            buffer = new byte[(int)count+9];
+            buffer[offset++] = TC_LONGSTRING;
+            offset = output.writeLongToBuffer(count, buffer, offset);
         }
-        output.writeUTFBytes(object, count);
+        offset = output.writeUTFBytesToBuffer(object, buffer, offset);
+        output.write(buffer, 0, offset);
 
         Integer handle = nextHandle();
 
diff --git a/libcore/luni/src/main/java/java/io/PrintStream.java b/libcore/luni/src/main/java/java/io/PrintStream.java
index 29d460e..8b6464b 100644
--- a/libcore/luni/src/main/java/java/io/PrintStream.java
+++ b/libcore/luni/src/main/java/java/io/PrintStream.java
@@ -658,7 +658,7 @@
      *            the buffer to be written.
      * @param offset
      *            the index of the first byte in {@code buffer} to write.
-     * @param count
+     * @param length
      *            the number of bytes in {@code buffer} to write.
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
@@ -666,27 +666,23 @@
      * @see #flush()
      */
     @Override
-    public void write(byte[] buffer, int offset, int count) {
-        // BEGIN android-changed
-        if (buffer == null) {
-            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+    public void write(byte[] buffer, int offset, int length) {
+        // Force buffer null check first!
+        if (offset > buffer.length || offset < 0) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
         }
-        // avoid int overflow
-        // Exception priorities (in case of multiple errors) differ from
-        // RI, but are spec-compliant.
-        // removed redundant check, used (offset | count) < 0
-        // instead of (offset < 0) || (count < 0) to safe one operation
-        if ((offset | count) < 0 || count > buffer.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+        if (length < 0 || length > buffer.length - offset) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
         }
-        // END android-changed
         synchronized (this) {
             if (out == null) {
                 setError();
                 return;
             }
             try {
-                out.write(buffer, offset, count);
+                out.write(buffer, offset, length);
                 if (autoflush) {
                     flush();
                 }
diff --git a/libcore/luni/src/main/java/java/io/PushbackInputStream.java b/libcore/luni/src/main/java/java/io/PushbackInputStream.java
index 4600fa2..932a896 100644
--- a/libcore/luni/src/main/java/java/io/PushbackInputStream.java
+++ b/libcore/luni/src/main/java/java/io/PushbackInputStream.java
@@ -177,21 +177,18 @@
     @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
         if (buf == null) {
-            throw new IOException();
+            // K0059=Stream is closed
+            throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
-        // BEGIN android-changed
-        if (buffer == null) {
-            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+        // Force buffer null check first!
+        if (offset > buffer.length || offset < 0) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
         }
-        // avoid int overflow
-        // Exception priorities (in case of multiple errors) differ from
-        // RI, but are spec-compliant.
-        // removed redundant check, used (offset | length) < 0
-        // instead of (offset < 0) || (length < 0) to safe one operation
-        if ((offset | length) < 0 || length > buffer.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+        if (length < 0 || length > buffer.length - offset) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
         }
-        // END android-changed
 
         int copiedBytes = 0, copyLength = 0, newOffset = offset;
         // Are there pushback bytes available?
@@ -296,27 +293,22 @@
     public void unread(byte[] buffer, int offset, int length)
             throws IOException {
         if (length > pos) {
-            // Pushback buffer full
+            // K007e=Pushback buffer full
             throw new IOException(Msg.getString("K007e")); //$NON-NLS-1$
         }
-        // avoid int overflow
-        // BEGIN android-changed
-        // Exception priorities (in case of multiple errors) differ from
-        // RI, but are spec-compliant.
-        // removed redundant check, made implicit null check explicit
-        // used (offset | length) < 0 instead of (offset < 0) || (length < 0)
-        // to safe one operation
-        if (buffer == null) {
-            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+        if (offset > buffer.length || offset < 0) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
         }
-        if ((offset | length) < 0 || length > buffer.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+        if (length < 0 || length > buffer.length - offset) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
         }
-        // END android-changed
-
         if (buf == null) {
-            throw new IOException();
+            // K0059=Stream is closed
+            throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
+
         System.arraycopy(buffer, offset, buf, pos - length, length);
         pos = pos - length;
     }
diff --git a/libcore/luni/src/main/java/java/io/PushbackReader.java b/libcore/luni/src/main/java/java/io/PushbackReader.java
index 606ecb4..016cd2f 100644
--- a/libcore/luni/src/main/java/java/io/PushbackReader.java
+++ b/libcore/luni/src/main/java/java/io/PushbackReader.java
@@ -298,7 +298,7 @@
      *            reader.
      * @param offset
      *            the index of the first byte in {@code buffer} to push back.
-     * @param count
+     * @param length
      *            the number of bytes to push back.
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if
@@ -311,29 +311,27 @@
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
      */
-    public void unread(char[] buffer, int offset, int count) throws IOException {
+    public void unread(char[] buffer, int offset, int length) throws IOException {
         synchronized (lock) {
             if (buf == null) {
+                // K0059=Stream is closed
                 throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
             }
-            if (count > pos) {
-                // Pushback buffer full
+            if (length > pos) {
+                // K007e=Pushback buffer full
                 throw new IOException(Msg.getString("K007e")); //$NON-NLS-1$
             }
-            // BEGIN android-changed
-            if (buffer == null) {
-                throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+            // Force buffer null check first!
+            if (offset > buffer.length - length || offset < 0) {
+                // K002e=Offset out of bounds \: {0}
+                throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
             }
-            // avoid int overflow
-            // Exception priorities (in case of multiple errors) differ from
-            // RI, but are spec-compliant.
-            // used (offset | count) < 0 instead of (offset < 0) || (count < 0)
-            // to safe one operation
-            if ((offset | count) < 0 || offset > buffer.length - count) {
-                throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+            if (length < 0) {
+                // K0031=Length out of bounds \: {0}
+                throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
             }
-            // END android-changed
-            for (int i = offset + count - 1; i >= offset; i--) {
+
+            for (int i = offset + length - 1; i >= offset; i--) {
                 unread(buffer[i]);
             }
         }
diff --git a/libcore/luni/src/main/java/java/io/StringBufferInputStream.java b/libcore/luni/src/main/java/java/io/StringBufferInputStream.java
index cc4ab81..037cc60 100644
--- a/libcore/luni/src/main/java/java/io/StringBufferInputStream.java
+++ b/libcore/luni/src/main/java/java/io/StringBufferInputStream.java
@@ -115,18 +115,19 @@
             return -1;
         }
         if (b == null) {
+            // K0047=buffer is null
             throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
         }
         // avoid int overflow
-        // BEGIN android-changed
-        // Exception priorities (in case of multiple errors) differ from
-        // RI, but are spec-compliant.
-        // removed redundant check, used (offset | length) < 0
-        // instead of (offset < 0) || (length < 0) to safe one operation
-        if ((offset | length) < 0 || length > b.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+        if (offset < 0 || offset > b.length) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
         }
-        // END android-changed
+        if (length < 0 || length > b.length - offset) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
+        }
+
         if (length == 0) {
             return 0;
         }
diff --git a/libcore/luni/src/main/java/java/io/StringReader.java b/libcore/luni/src/main/java/java/io/StringReader.java
index 0a9e9bb..9f8671a 100644
--- a/libcore/luni/src/main/java/java/io/StringReader.java
+++ b/libcore/luni/src/main/java/java/io/StringReader.java
@@ -155,23 +155,19 @@
         // BEGIN android-note
         // changed array notation to be consistent with the rest of harmony
         // END android-note
-        // BEGIN android-changed
-        // Exception priorities (in case of multiple errors) differ from
-        // RI, but are spec-compliant.
-        // removed redundant check, added null check, used (offset | len) < 0
-        // instead of (offset < 0) || (len < 0) to safe one operation
-        if (buf == null) {
-            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
-        }
         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()) {
+                // K0083=StringReader is closed.
                 throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
             }
+            if (offset < 0 || offset > buf.length) {
+                // K002e=Offset out of bounds \: {0}
+                throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
+            }
+            if (len < 0 || len > buf.length - offset) {
+                // K0031=Length out of bounds \: {0}
+                throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", len)); //$NON-NLS-1$
+            }
             if (len == 0) {
                 return 0;
             }
diff --git a/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java b/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java
index c481e11..869c694 100644
--- a/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -120,21 +120,23 @@
         count = newSize;
     }
 
-    final void append0(char chars[], int start, int length) {
-        if (chars == null) {
-            throw new NullPointerException();
+    final void append0(char[] chars, int offset, int length) {
+        // Force null check of chars first!
+        if (offset > chars.length || offset < 0) {
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
         }
-        // start + length could overflow, start/length maybe MaxInt
-        if (start >= 0 && 0 <= length && length <= chars.length - start) {
-            int newSize = count + length;
-            if (newSize > value.length) {
-                enlargeBuffer(newSize);
-            }
-            System.arraycopy(chars, start, value, count, length);
-            count = newSize;
-        } else {
-            throw new ArrayIndexOutOfBoundsException();
+        if (length < 0 || chars.length - offset < length) {
+            // K0031=Length out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
         }
+
+        int newSize = count + length;
+        if (newSize > value.length) {
+            enlargeBuffer(newSize);
+        }
+        System.arraycopy(chars, offset, value, count, length);
+        count = newSize;
     }
 
     final void append0(char ch) {
diff --git a/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java b/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
index d43a7e6..6bb67fc 100644
--- a/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
+++ b/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
@@ -44,6 +44,7 @@
      *            the invalid index.
      */
     public ArrayIndexOutOfBoundsException(int index) {
+        // K0052=Array index out of range\: {0}
         super(Msg.getString("K0052", index)); //$NON-NLS-1$
     }
 
diff --git a/libcore/luni/src/main/java/java/lang/Enum.java b/libcore/luni/src/main/java/java/lang/Enum.java
index 395c825..e2ee32a 100644
--- a/libcore/luni/src/main/java/java/lang/Enum.java
+++ b/libcore/luni/src/main/java/java/lang/Enum.java
@@ -25,7 +25,7 @@
 
 /**
  * The superclass of all enumerated types. Actual enumeration types inherit from
- * this class, but extending this class does not make a class an enumration
+ * this class, but extending this class does not make a class an enumeration
  * type, since the compiler needs to generate special information for it.
  */
 public abstract class Enum<E extends Enum<E>> implements Serializable,
diff --git a/libcore/luni/src/main/java/java/lang/Integer.java b/libcore/luni/src/main/java/java/lang/Integer.java
index 570120b..5dcf217 100644
--- a/libcore/luni/src/main/java/java/lang/Integer.java
+++ b/libcore/luni/src/main/java/java/lang/Integer.java
@@ -526,7 +526,7 @@
             int quot = positive_value;
             do {
                 int res = quot / 10;
-                int digit_value = quot - (res * 10);
+                int digit_value = quot - ((res << 3) + (res << 1));
                 digit_value += '0';
                 buffer[last_digit++] = (char) digit_value;
                 quot = res;
diff --git a/libcore/luni/src/main/java/java/lang/Math.java b/libcore/luni/src/main/java/java/lang/Math.java
index d06e6e4..f7b49b2 100644
--- a/libcore/luni/src/main/java/java/lang/Math.java
+++ b/libcore/luni/src/main/java/java/lang/Math.java
@@ -246,9 +246,7 @@
      *            the value whose closest integer value has to be computed.
      * @return the ceiling of the argument.
      */
-    // BEGIN android-changed
     public static native double ceil(double d);
-    // END android-changed
 
     /**
      * Returns the closest double approximation of the cosine of the argument.
@@ -348,9 +346,7 @@
      *            the value whose closest integer value has to be computed.
      * @return the floor of the argument.
      */
-    // BEGIN android-changed
     public static native double floor(double d);
-    // END android-changed
 
     /**
      * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i>
@@ -731,9 +727,7 @@
      *            the value to be rounded.
      * @return the closest integer to the argument (as a double).
      */
-    // BEGIN android-changed
     public static native double rint(double d);
-    // END android-changed
 
     /**
      * Returns the result of rounding the argument to an integer. The result is
diff --git a/libcore/luni/src/main/java/java/lang/SecurityManager.java b/libcore/luni/src/main/java/java/lang/SecurityManager.java
index 9125850..8a04e92 100644
--- a/libcore/luni/src/main/java/java/lang/SecurityManager.java
+++ b/libcore/luni/src/main/java/java/lang/SecurityManager.java
@@ -414,9 +414,8 @@
                 .getSecurityProperty(property));
         if (list != null) {
             int plen = pkg.length();
-            StringTokenizer tokenizer = new StringTokenizer(list, ", "); //$NON-NLS-1$
-            while (tokenizer.hasMoreTokens()) {
-                String token = tokenizer.nextToken();
+            String[] tokens = list.split(", *"); //$NON-NLS-1$
+            for (String token : tokens) {
                 int tlen = token.length();
                 if (plen > tlen
                         && pkg.startsWith(token)
diff --git a/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java b/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java
index db3b9ec..12b2079 100644
--- a/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java
@@ -104,17 +104,6 @@
     }
 
     /**
-     * Gets the value for the specified socket option.
-     * 
-     * @param optID
-     *            the ID of the socket option to be retrieved.
-     * @return the requested option value.
-     * @throws SocketException
-     *                if an error occurs while accessing the option.
-     */
-    public abstract Object getOption(int optID) throws SocketException;
-
-    /**
      * Gets the time-to-live (TTL) for multicast packets sent on this socket.
      * 
      * @return the time-to-live option as a byte value.
@@ -232,19 +221,6 @@
     protected abstract void send(DatagramPacket pack) throws IOException;
 
     /**
-     * Sets the value for the specified socket option.
-     * 
-     * @param optID
-     *            the ID of the socket option to be set.
-     * @param val
-     *            the value of the option.
-     * @throws SocketException
-     *                if an error occurs while setting the option.
-     */
-    public abstract void setOption(int optID, Object val)
-            throws SocketException;
-
-    /**
      * Sets the time-to-live (TTL) option for multicast packets sent on this
      * socket.
      * 
diff --git a/libcore/luni/src/main/java/java/net/InetAddress.java b/libcore/luni/src/main/java/java/net/InetAddress.java
index 33c25f3..c844d54 100644
--- a/libcore/luni/src/main/java/java/net/InetAddress.java
+++ b/libcore/luni/src/main/java/java/net/InetAddress.java
@@ -1320,6 +1320,10 @@
         family = fields.get("family", 2); //$NON-NLS-1$
     }
 
+    /*
+     * The spec requires that if we encounter a generic InetAddress in
+     * serialized form then we should interpret it as an Inet4 address.
+     */
     private Object readResolve() throws ObjectStreamException {
         return new Inet4Address(ipaddress, hostName);
     }
diff --git a/libcore/luni/src/main/java/java/net/JarURLConnection.java b/libcore/luni/src/main/java/java/net/JarURLConnection.java
index da39d9c..f41ef64 100644
--- a/libcore/luni/src/main/java/java/net/JarURLConnection.java
+++ b/libcore/luni/src/main/java/java/net/JarURLConnection.java
@@ -69,7 +69,7 @@
         if ((sepIdx = file.indexOf("!/")) < 0) { //$NON-NLS-1$
             throw new MalformedURLException();
         }
-        fileURL = new URL(url.getFile().substring(0,sepIdx)); //$NON-NLS-1$
+        fileURL = new URL(url.getFile().substring(0,sepIdx));
         sepIdx += 2;
         if (file.length() == sepIdx) {
             return;
diff --git a/libcore/luni/src/main/java/java/net/NetworkInterface.java b/libcore/luni/src/main/java/java/net/NetworkInterface.java
index 091eb9f..f921b07 100644
--- a/libcore/luni/src/main/java/java/net/NetworkInterface.java
+++ b/libcore/luni/src/main/java/java/net/NetworkInterface.java
@@ -334,67 +334,66 @@
      *            the object to compare with this instance.
      * @return {@code true} if the specified object is equal to this {@code
      *         NetworkInterface}, {@code false} otherwise.
-     * @see #hashCode
+     * @see #hashCode()
      */
     @Override
     public boolean equals(Object obj) {
-        // just return true if it is the exact same object
+        // Return true if it is the exact same object.
         if (obj == this) {
             return true;
         }
 
-        if (obj instanceof NetworkInterface) {
-            /*
-             * make sure that some simple checks pass. If the name is not the
-             * same then we are sure it is not the same one. We don't check the
-             * hashcode as it is generated from the name which we check
-             */
-            NetworkInterface netif = (NetworkInterface) obj;
-
-            if (netif.getIndex() != interfaceIndex) {
-                return false;
-            }
-
-            if (!(name.equals("")) && (!netif.getName().equals(name))) { //$NON-NLS-1$
-                return false;
-            }
-
-            if ((name.equals("")) && (!netif.getName().equals(displayName))) { //$NON-NLS-1$
-                return false;
-            }
-
-            // now check that the internet addresses are the same
-            Enumeration<InetAddress> netifAddresses = netif.getInetAddresses();
-            Enumeration<InetAddress> localifAddresses = getInetAddresses();
-            if ((netifAddresses == null) && (localifAddresses != null)) {
-                return false;
-            }
-
-            if ((netifAddresses == null) && (localifAddresses == null)) {
-                // neither have any addresses so they are the same
-                return true;
-            }
-
-            if (netifAddresses != null) {
-                while (netifAddresses.hasMoreElements()
-                        && localifAddresses.hasMoreElements()) {
-                    if (!(localifAddresses.nextElement()).equals(netifAddresses
-                            .nextElement())) {
-                        return false;
-                    }
-                }
-                /*
-                 * now make sure that they had the same number of internet
-                 * addresses, if not they are not the same interface
-                 */
-                if (netifAddresses.hasMoreElements()
-                        || localifAddresses.hasMoreElements()) {
-                    return false;
-                }
-            }
-            return true;
+        // Ensure it is the right type.
+        if (!(obj instanceof NetworkInterface)) {
+            return false;
         }
-        return false;
+
+        /*
+         * Make sure that some simple checks pass. If the name is not the same
+         * then we are sure it is not the same one. We don't check the hashcode
+         * as it is generated from the name which we check
+         */
+        NetworkInterface netif = (NetworkInterface) obj;
+
+        if (netif.getIndex() != interfaceIndex) {
+            return false;
+        }
+
+        if (!(name.equals("")) && (!netif.getName().equals(name))) { //$NON-NLS-1$
+            return false;
+        }
+
+        if ((name.equals("")) && (!netif.getName().equals(displayName))) { //$NON-NLS-1$
+            return false;
+        }
+
+        // Now check that the collection of internet addresses are equal.
+        Enumeration<InetAddress> netifAddresses = netif.getInetAddresses();
+        Enumeration<InetAddress> localifAddresses = getInetAddresses();
+
+        // Check for both null (same), or one null (not same).
+        if (netifAddresses == null) {
+            return localifAddresses == null;
+        }
+        if (localifAddresses == null) {
+            return false;
+        }
+
+        // Both are not null, check InetAddress elements.
+        while (netifAddresses.hasMoreElements()
+                && localifAddresses.hasMoreElements()) {
+            if (!(localifAddresses.nextElement()).equals(
+                    netifAddresses.nextElement())) {
+                return false;
+            }
+        }
+
+        /*
+         * Now make sure that they had the same number of addresses, if not they
+         * are not the same interface.
+         */
+        return !netifAddresses.hasMoreElements()
+                && !localifAddresses.hasMoreElements();
     }
 
     /**
diff --git a/libcore/luni/src/main/java/java/net/SocketAddress.java b/libcore/luni/src/main/java/java/net/SocketAddress.java
index 32a4c36..e84ebfd 100644
--- a/libcore/luni/src/main/java/java/net/SocketAddress.java
+++ b/libcore/luni/src/main/java/java/net/SocketAddress.java
@@ -26,6 +26,8 @@
  */
 public abstract class SocketAddress implements Serializable {
 
+    private static final long serialVersionUID = 5215720748342549866L;
+
     /**
      * Creates a new {@code SocketAddress} instance.
      */
diff --git a/libcore/luni/src/main/java/java/net/URL.java b/libcore/luni/src/main/java/java/net/URL.java
index 9b0fdc4..b9e657d 100644
--- a/libcore/luni/src/main/java/java/net/URL.java
+++ b/libcore/luni/src/main/java/java/net/URL.java
@@ -889,15 +889,15 @@
     protected void set(String protocol, String host, int port,
             String authority, String userInfo, String path, String query,
             String ref) {
-        String file = path;
+        String filePart = path;
         if (query != null && !query.equals("")) { //$NON-NLS-1$
-            if (file != null) {
-                file = file + "?" + query; //$NON-NLS-1$
+            if (filePart != null) {
+                filePart = filePart + "?" + query; //$NON-NLS-1$
             } else {
-                file = "?" + query; //$NON-NLS-1$
+                filePart = "?" + query; //$NON-NLS-1$
             }
         }
-        set(protocol, host, port, file, ref);
+        set(protocol, host, port, filePart, ref);
         this.authority = authority;
         this.userInfo = userInfo;
         this.path = path;
diff --git a/libcore/luni/src/main/java/java/net/URLClassLoader.java b/libcore/luni/src/main/java/java/net/URLClassLoader.java
index 6dfa385..61841e6 100644
--- a/libcore/luni/src/main/java/java/net/URLClassLoader.java
+++ b/libcore/luni/src/main/java/java/net/URLClassLoader.java
@@ -1167,7 +1167,7 @@
      */
     private ArrayList<URL> getInternalURLs(URL root, String classpath) {
         // Class-path attribute is composed of space-separated values.
-        StringTokenizer tokenizer = new java.util.StringTokenizer(classpath);
+        StringTokenizer tokenizer = new StringTokenizer(classpath);
         ArrayList<URL> addedURLs = new ArrayList<URL>();
         String file = root.getFile();
         int jarIndex = file.lastIndexOf("!/") - 1; //$NON-NLS-1$
@@ -1177,9 +1177,6 @@
                     System.getProperty("file.separator"), jarIndex) + 1; //$NON-NLS-1$
         }
         file = file.substring(0, index);
-        String protocol = root.getProtocol();
-        String host = root.getHost();
-        int port = root.getPort();
         while (tokenizer.hasMoreElements()) {
             String element = tokenizer.nextToken();
             if (!element.equals("")) { //$NON-NLS-1$
diff --git a/libcore/luni/src/main/java/java/util/ArrayList.java b/libcore/luni/src/main/java/java/util/ArrayList.java
index b8c7056..7c46e89 100644
--- a/libcore/luni/src/main/java/java/util/ArrayList.java
+++ b/libcore/luni/src/main/java/java/util/ArrayList.java
@@ -15,12 +15,16 @@
  *  limitations under the License.
  */
 
+// BEGIN android-note
+// New implementation: simpler and faster than Harmony implementation.
+// BEGIN android-note
+
 package java.util;
 
 import java.io.IOException;
+import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.io.ObjectStreamField;
 import java.io.Serializable;
 import java.lang.reflect.Array;
 
@@ -29,37 +33,38 @@
  * optional operations adding, removing, and replacing are supported. The
  * elements can be any objects.
  *
+ * @param <E> The element type of this list.
  * @since 1.2
  */
-public class ArrayList<E> extends AbstractList<E> implements List<E>,
-        Cloneable, Serializable, RandomAccess {
-
-    private static final long serialVersionUID = 8683452581122892189L;
-
-    // BEGIN android-added
-    /** zero-element array */
-    private static final Object[] emptyArray = new Object[0];
-    // END android-added
-
-    private transient int firstIndex;
-
-    private transient int lastIndex;
-
-    private transient E[] array;
+public class ArrayList<E> extends AbstractList<E>
+        implements Cloneable, Serializable, RandomAccess {
+    /**
+     * An empty array of objects (to be shared among all empty lists).
+     */
+    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
 
     /**
-     * Constructs a new instance of {@code ArrayList} with zero capacity.
+     * The minimum amount by which the capacity of an ArrayList will increase.
+     * This tuning parameter controls a time-space tradeoff. This value (12)
+     * gives empirically good results and is arguably consistent with the
+     * RI's specified default initial capacity of 10: instead of 10, we start
+     * with 0 (sans allocation) and jump to 12.
      */
-    public ArrayList() {
-        // BEGIN android-changed
-        // default capacity is zero, not ten
-        this(0);
-        // END android-changed
-    }
+    private static final int MIN_CAPACITY_INCREMENT = 12;
+
+    /**
+     * The number of elements in this list.
+     */
+    int size;
+
+    /**
+     * The elements in this list, followed by nulls.
+     */
+    transient Object[] array;
 
     /**
      * Constructs a new instance of {@code ArrayList} with the specified
-     * capacity.
+     * initial capacity.
      *
      * @param capacity
      *            the initial capacity of this {@code ArrayList}.
@@ -68,84 +73,32 @@
         if (capacity < 0) {
             throw new IllegalArgumentException();
         }
-        firstIndex = lastIndex = 0;
-        array = newElementArray(capacity);
+        array = (capacity == 0 ? EMPTY_OBJECT_ARRAY : new Object[capacity]);
+    }
+
+    /**
+     * Constructs a new {@code ArrayList} instance with zero initial capacity.
+     */
+    public ArrayList() {
+        array = EMPTY_OBJECT_ARRAY;
     }
 
     /**
      * 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.
+     * the specified collection.
      *
      * @param collection
      *            the collection of elements to add.
      */
     public ArrayList(Collection<? extends E> collection) {
-        firstIndex = 0;
-        Object[] objects = collection.toArray();
-        int size = objects.length;
-        array = newElementArray(size + (size / 10));
-        System.arraycopy(objects, 0, array, 0, size);
-        lastIndex = size;
-        modCount = 1;
-    }
-
-    @SuppressWarnings("unchecked")
-    private E[] newElementArray(int size) {
-        // BEGIN android-added
-        if (size == 0) {
-            return (E[])emptyArray;
+        Object[] a = collection.toArray();
+        if (a.getClass() != Object[].class) {
+            Object[] newArray = new Object[a.length];
+            System.arraycopy(a, 0, newArray, 0, a.length);
+            a = newArray;
         }
-        // END android-added
-
-        return (E[]) new Object[size];
-    }
-
-    /**
-     * Inserts the specified object into this {@code ArrayList} at the 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 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()}
-     */
-    @Override
-    public void add(int location, E object) {
-        int size = lastIndex - firstIndex;
-        if (0 < location && location < size) {
-            if (firstIndex == 0 && lastIndex == array.length) {
-                growForInsert(location, 1);
-            } else if ((location < size / 2 && firstIndex > 0)
-                    || lastIndex == array.length) {
-                System.arraycopy(array, firstIndex, array, --firstIndex,
-                        location);
-            } else {
-                int index = location + firstIndex;
-                System.arraycopy(array, index, array, index + 1, size
-                        - location);
-                lastIndex++;
-            }
-            array[location + firstIndex] = object;
-        } else if (location == 0) {
-            if (firstIndex == 0) {
-                growAtFront(1);
-            }
-            array[--firstIndex] = object;
-        } else if (location == size) {
-            if (lastIndex == array.length) {
-                growAtEnd(1);
-            }
-            array[lastIndex++] = object;
-        } else {
-            throw new IndexOutOfBoundsException();
-        }
-
-        modCount++;
+        array = a;
+        size = a.length;
     }
 
     /**
@@ -155,80 +108,69 @@
      *            the object to add.
      * @return always true
      */
-    @Override
-    public boolean add(E object) {
-        if (lastIndex == array.length) {
-            growAtEnd(1);
+    @Override public boolean add(E object) {
+        Object[] a = array;
+        int s = size;
+        if (s == a.length) {
+            Object[] newArray = new Object[s +
+                    (s < (MIN_CAPACITY_INCREMENT / 2) ?
+                     MIN_CAPACITY_INCREMENT : s >> 1)];
+            System.arraycopy(a, 0, newArray, 0, s);
+            array = a = newArray;
         }
-        array[lastIndex++] = object;
+        a[s] = object;
+        size = s + 1;
         modCount++;
         return true;
     }
 
     /**
-     * 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.
+     * Inserts the specified object into this {@code ArrayList} at the 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 ArrayList}, the object is added at the end.
      *
-     * @param location
-     *            the index at which to insert.
-     * @param collection
-     *            the collection of objects.
-     * @return {@code true} if this {@code ArrayList} is modified, {@code false}
-     *         otherwise.
+     * @param index
+     *            the index at which to insert the object.
+     * @param object
+     *            the object to add.
      * @throws IndexOutOfBoundsException
      *             when {@code location < 0 || > size()}
      */
-    @Override
-    public boolean addAll(int location, Collection<? extends E> collection) {
-        int size = lastIndex - firstIndex;
-        if (location < 0 || location > size) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (this == collection) {
-            collection = (ArrayList)clone();
-        }
-        Object[] dumparray = collection.toArray();
-        int growSize = dumparray.length;
-        if (growSize == 0) {
-            return false;
+    @Override public void add(int index, E object) {
+        Object[] a = array;
+        int s = size;
+        if (index > s) {
+            throwIndexOutOfBoundsException(index, s);
         }
 
-        if (0 < location && location < size) {
-            if (array.length - size < growSize) {
-                growForInsert(location, growSize);
-            } else if ((location < size / 2 && firstIndex > 0)
-                    || lastIndex > array.length - growSize) {
-                int newFirst = firstIndex - growSize;
-                if (newFirst < 0) {
-                    int index = location + firstIndex;
-                    System.arraycopy(array, index, array, index - newFirst,
-                            size - location);
-                    lastIndex -= newFirst;
-                    newFirst = 0;
-                }
-                System.arraycopy(array, firstIndex, array, newFirst, location);
-                firstIndex = newFirst;
-            } else {
-                int index = location + firstIndex;
-                System.arraycopy(array, index, array, index + growSize, size
-                        - location);
-                lastIndex += growSize;
-            }
-        } else if (location == 0) {
-            growAtFront(growSize);
-            firstIndex -= growSize;
-        } else if (location == size) {
-            if (lastIndex > array.length - growSize) {
-                growAtEnd(growSize);
-            }
-            lastIndex += growSize;
+        if (s < a.length) {
+            System.arraycopy(a, index, a, index + 1, s - index);
+        } else {
+            // assert s == a.length;
+            Object[] newArray = new Object[newCapacity(s)];
+            System.arraycopy(a, 0, newArray, 0, index);
+            System.arraycopy(a, index, newArray, index + 1, s - index);
+            array = a = newArray;
         }
-
-        System.arraycopy(dumparray, 0, this.array, location + firstIndex,
-                growSize);
+        a[index] = object;
+        size = s + 1;
         modCount++;
-        return true;
+    }
+
+    /**
+     * This method controls the growth of ArrayList capacities.  It represents
+     * a time-space tradeoff: we don't want to grow lists too frequently
+     * (which wastes time and fragments storage), but we don't want to waste
+     * too much space in unused excess capacity.
+     *
+     * NOTE: This method is inlined into {@link #add(Object)} for performance.
+     * If you change the method, change it there too!
+     */
+    private static int newCapacity(int currentCapacity) {
+        int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?
+                MIN_CAPACITY_INCREMENT : currentCapacity >> 1);
+        return currentCapacity + increment;
     }
 
     /**
@@ -239,32 +181,85 @@
      * @return {@code true} if this {@code ArrayList} is modified, {@code false}
      *         otherwise.
      */
-    @Override
-    public boolean addAll(Collection<? extends E> collection) {
-        Object[] dumpArray = collection.toArray();
-        if (dumpArray.length == 0) {
+    @Override public boolean addAll(Collection<? extends E> collection) {
+        Object[] newPart = collection.toArray();
+        int newPartSize = newPart.length;
+        if (newPartSize == 0) {
             return false;
         }
-        if (dumpArray.length > array.length - lastIndex) {
-            growAtEnd(dumpArray.length);
+        Object[] a = array;
+        int s = size;
+        int newSize = s + newPartSize; // If add overflows, arraycopy will fail
+        if (newSize > a.length) {
+            int newCapacity = newCapacity(newSize - 1);  // ~33% growth room
+            Object[] newArray = new Object[newCapacity];
+            System.arraycopy(a, 0, newArray, 0, s);
+            array = a = newArray;
         }
-        System.arraycopy(dumpArray, 0, this.array, lastIndex, dumpArray.length);
-        lastIndex += dumpArray.length;
+        System.arraycopy(newPart, 0, a, s, newPartSize);
+        size = newSize;
         modCount++;
         return true;
     }
 
     /**
+     * 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 index
+     *            the index at which to insert.
+     * @param collection
+     *            the collection of objects.
+     * @return {@code true} if this {@code ArrayList} is modified, {@code false}
+     *         otherwise.
+     * @throws IndexOutOfBoundsException
+     *             when {@code location < 0 || > size()}
+     */
+    @Override
+    public boolean addAll(int index, Collection<? extends E> collection) {
+        Object[] newPart = collection.toArray();
+        int newPartSize = newPart.length;
+        if (newPartSize == 0) {
+            return false;
+        }
+        Object[] a = array;
+        int s = size;
+        if (index > s) {
+            throwIndexOutOfBoundsException(index, s);
+        }
+        int newSize = s + newPartSize; // If add overflows, arraycopy will fail
+        if (newSize <= a.length) {
+             System.arraycopy(a, index, a, index + newPartSize, s - index);
+        } else {
+            int newCapacity = newCapacity(newSize - 1);  // ~33% growth room
+            Object[] newArray = new Object[newCapacity];
+            System.arraycopy(a, 0, newArray, 0, index);
+            System.arraycopy(a, index, newArray, index + newPartSize, s-index);
+            array = a = newArray;
+        }
+        System.arraycopy(newPart, 0, a, index, newPartSize);
+        size = newSize;
+        modCount++;
+        return true;
+    }
+
+    /** This method was extracted to encourage VM to inline callers. */
+    private static void throwIndexOutOfBoundsException(int index, int size) {
+        throw new IndexOutOfBoundsException("Invalid index " + index
+                + ", size is " + size);
+    }
+
+    /**
      * Removes all elements from this {@code ArrayList}, leaving it empty.
      *
      * @see #isEmpty
      * @see #size
      */
-    @Override
-    public void clear() {
-        if (firstIndex != lastIndex) {
-            Arrays.fill(array, firstIndex, lastIndex, null);
-            firstIndex = lastIndex = 0;
+    @Override public void clear() {
+        if (size != 0) {
+            Arrays.fill(array, 0, size, null);
+            size = 0;
             modCount++;
         }
     }
@@ -276,45 +271,17 @@
      * @return a shallow copy of this {@code ArrayList}
      * @see java.lang.Cloneable
      */
-    @Override
-    @SuppressWarnings("unchecked")
-    public Object clone() {
+    @Override public Object clone() {
         try {
-            ArrayList<E> newList = (ArrayList<E>) super.clone();
-            newList.array = array.clone();
-            return newList;
+            ArrayList<?> result = (ArrayList<?>) super.clone();
+            result.array = array.clone();
+            return result;
         } catch (CloneNotSupportedException e) {
-            return null;
+           throw new AssertionError();
         }
     }
 
     /**
-     * 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
-     */
-    @Override
-    public boolean contains(Object object) {
-        if (object != null) {
-            for (int i = firstIndex; i < lastIndex; i++) {
-                if (object.equals(array[i])) {
-                    return true;
-                }
-            }
-        } else {
-            for (int i = firstIndex; i < lastIndex; i++) {
-                if (array[i] == null) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
      * Ensures that after this operation the {@code ArrayList} can hold the
      * specified number of elements without further growing.
      *
@@ -322,145 +289,93 @@
      *            the minimum capacity asked for.
      */
     public void ensureCapacity(int minimumCapacity) {
-        if (array.length < minimumCapacity) {
-            if (firstIndex > 0) {
-                growAtFront(minimumCapacity - array.length);
-            } else {
-                growAtEnd(minimumCapacity - array.length);
-            }
-        }
-    }
-
-    @Override
-    public E get(int location) {
-        // BEGIN android-changed: slight performance improvement
-        int _firstIndex = firstIndex;
-        if (0 <= location && location < lastIndex - _firstIndex) {
-            return array[_firstIndex + location];
-        }
-        throw new IndexOutOfBoundsException("Invalid location " + location
-                + ", size is " + (lastIndex - _firstIndex));
-        // END android-changed
-    }
-
-    private void growAtEnd(int required) {
-        int size = lastIndex - firstIndex;
-        if (firstIndex >= required - (array.length - lastIndex)) {
-            int newLast = lastIndex - firstIndex;
-            if (size > 0) {
-                System.arraycopy(array, firstIndex, array, 0, size);
-                int start = newLast < firstIndex ? firstIndex : newLast;
-                Arrays.fill(array, start, array.length, null);
-            }
-            firstIndex = 0;
-            lastIndex = newLast;
-        } else {
-            int increment = size / 2;
-            if (required > increment) {
-                increment = required;
-            }
-            if (increment < 12) {
-                increment = 12;
-            }
-            E[] newArray = newElementArray(size + increment);
-            if (size > 0) {
-                System.arraycopy(array, firstIndex, newArray, 0, size);
-                firstIndex = 0;
-                lastIndex = size;
-            }
+        Object[] a = array;
+        if (a.length < minimumCapacity) {
+            Object[] newArray = new Object[minimumCapacity];
+            System.arraycopy(a, 0, newArray, 0, size);
             array = newArray;
+            modCount++;
         }
     }
 
-    private void growAtFront(int 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);
-                int length = firstIndex + size > newFirst ? newFirst
-                        : firstIndex + size;
-                Arrays.fill(array, firstIndex, length, null);
-            }
-            firstIndex = newFirst;
-            lastIndex = array.length;
-        } else {
-            int increment = size / 2;
-            if (required > increment) {
-                increment = required;
-            }
-            if (increment < 12) {
-                increment = 12;
-            }
-            E[] newArray = newElementArray(size + increment);
-            if (size > 0) {
-                System.arraycopy(array, firstIndex, newArray, newArray.length
-                        - size, size);
-            }
-            firstIndex = newArray.length - size;
-            lastIndex = newArray.length;
-            array = newArray;
+    @SuppressWarnings("unchecked") @Override public E get(int index) {
+        if (index >= size) {
+            throwIndexOutOfBoundsException(index, size);
         }
+        return (E) array[index];
     }
 
-    private void growForInsert(int location, int required) {
-        int size = lastIndex - firstIndex;
-        int increment = size / 2;
-        if (required > increment) {
-            increment = required;
-        }
-        if (increment < 12) {
-            increment = 12;
-        }
-        E[] newArray = newElementArray(size + increment);
-        int newFirst = increment - required;
-        // Copy elements after location to the new array skipping inserted
-        // elements
-        System.arraycopy(array, location + firstIndex, newArray, newFirst
-                + location + required, size - location);
-        // Copy elements before location to the new array from firstIndex
-        System.arraycopy(array, firstIndex, newArray, newFirst, location);
-        firstIndex = newFirst;
-        lastIndex = size + increment;
-
-        array = newArray;
+    /**
+     * Returns the number of elements in this {@code ArrayList}.
+     *
+     * @return the number of elements in this {@code ArrayList}.
+     */
+    @Override public int size() {
+        return size;
     }
 
-    @Override
-    public int indexOf(Object object) {
+    @Override public boolean isEmpty() {
+        return size == 0;
+    }
+
+    /**
+     * 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
+     */
+    @Override public boolean contains(Object object) {
+        Object[] a = array;
+        int s = size;
         if (object != null) {
-            for (int i = firstIndex; i < lastIndex; i++) {
-                if (object.equals(array[i])) {
-                    return i - firstIndex;
+            for (int i = 0; i < s; i++) {
+                if (object.equals(a[i])) {
+                    return true;
                 }
             }
         } else {
-            for (int i = firstIndex; i < lastIndex; i++) {
-                if (array[i] == null) {
-                    return i - firstIndex;
+            for (int i = 0; i < s; i++) {
+                if (a[i] == null) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override public int indexOf(Object object) {
+        Object[] a = array;
+        int s = size;
+        if (object != null) {
+            for (int i = 0; i < s; i++) {
+                if (object.equals(a[i])) {
+                    return i;
+                }
+            }
+        } else {
+            for (int i = 0; i < s; i++) {
+                if (a[i] == null) {
+                    return i;
                 }
             }
         }
         return -1;
     }
 
-    @Override
-    public boolean isEmpty() {
-        return lastIndex == firstIndex;
-    }
-
-    @Override
-    public int lastIndexOf(Object object) {
+    @Override public int lastIndexOf(Object object) {
+        Object[] a = array;
         if (object != null) {
-            for (int i = lastIndex - 1; i >= firstIndex; i--) {
-                if (object.equals(array[i])) {
-                    return i - firstIndex;
+            for (int i = size - 1; i >= 0; i--) {
+                if (object.equals(a[i])) {
+                    return i;
                 }
             }
         } else {
-            for (int i = lastIndex - 1; i >= firstIndex; i--) {
-                if (array[i] == null) {
-                    return i - firstIndex;
+            for (int i = size - 1; i >= 0; i--) {
+                if (a[i] == null) {
+                    return i;
                 }
             }
         }
@@ -470,99 +385,81 @@
     /**
      * Removes the object at the specified location from this list.
      *
-     * @param location
+     * @param index
      *            the index of the object to remove.
      * @return the removed object.
      * @throws IndexOutOfBoundsException
      *             when {@code location < 0 || >= size()}
      */
-    @Override
-    public E remove(int location) {
-        E result;
-        int size = lastIndex - firstIndex;
-        if (0 <= location && location < size) {
-            if (location == size - 1) {
-                result = array[--lastIndex];
-                array[lastIndex] = null;
-            } else if (location == 0) {
-                result = array[firstIndex];
-                array[firstIndex++] = null;
-            } else {
-                int elementIndex = firstIndex + location;
-                result = array[elementIndex];
-                if (location < size / 2) {
-                    System.arraycopy(array, firstIndex, array, firstIndex + 1,
-                            location);
-                    array[firstIndex++] = null;
-                } else {
-                    System.arraycopy(array, elementIndex + 1, array,
-                            elementIndex, size - location - 1);
-                    array[--lastIndex] = null;
-                }
-            }
-            if (firstIndex == lastIndex) {
-                firstIndex = lastIndex = 0;
-            }
-        } else {
-            throw new IndexOutOfBoundsException();
+    @Override public E remove(int index) {
+        Object[] a = array;
+        int s = size;
+        if (index >= s) {
+            throwIndexOutOfBoundsException(index, s);
         }
-
+        @SuppressWarnings("unchecked") E result = (E) a[index];
+        System.arraycopy(a, index + 1, a, index, --s - index);
+        a[s] = null;  // Prevent memory leak
+        size = s;
         modCount++;
         return result;
     }
 
-    @Override
-    public boolean remove(Object object) {
-        int location = indexOf(object);
-        if (location >= 0) {
-            remove(location);
-            return true;
+    @Override public boolean remove(Object object) {
+        Object[] a = array;
+        int s = size;
+        if (object != null) {
+            for (int i = 0; i < s; i++) {
+                if (object.equals(a[i])) {
+                    System.arraycopy(a, i + 1, a, i, --s - i);
+                    a[s] = null;  // Prevent memory leak
+                    size = s;
+                    modCount++;
+                    return true;
+                }
+            }
+        } else {
+            for (int i = 0; i < s; i++) {
+                if (a[i] == null) {
+                    System.arraycopy(a, i + 1, a, i, --s - i);
+                    a[s] = null;  // Prevent memory leak
+                    size = s;
+                    modCount++;
+                    return true;
+                }
+            }
         }
         return false;
     }
 
-    /**
-     * 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()}
-     */
-    @Override
-    protected void removeRange(int start, int end) {
-        if (start >= 0 && start <= end && end <= (lastIndex - firstIndex)) {
-            if (start == end) {
-                return;
-            }
-            int size = lastIndex - firstIndex;
-            if (end == size) {
-                Arrays.fill(array, firstIndex + start, lastIndex, null);
-                lastIndex = firstIndex + start;
-            } else if (start == 0) {
-                Arrays.fill(array, firstIndex, firstIndex + end, null);
-                firstIndex += end;
-            } else {
-                System.arraycopy(array, firstIndex + end, array, firstIndex
-                        + start, size - end);
-                int newLast = lastIndex + start - end;
-                Arrays.fill(array, newLast, lastIndex, null);
-                lastIndex = newLast;
-            }
-            modCount++;
-        } else {
-            throw new IndexOutOfBoundsException();
+    @Override protected void removeRange(int fromIndex, int toIndex) {
+        Object[] a = array;
+        int s = size;
+        if (fromIndex >= s) {
+            throw new IndexOutOfBoundsException("fromIndex " + fromIndex
+                    + " >= size " + size);
         }
+        if (toIndex > s) {
+            throw new IndexOutOfBoundsException("toIndex " + toIndex
+                    + " > size " + size);
+        }
+        if (fromIndex > toIndex) {
+            throw new IndexOutOfBoundsException("fromIndex " + fromIndex
+                    + " > toIndex " + toIndex);
+        }
+
+        System.arraycopy(a, toIndex, a, fromIndex, s - toIndex);
+        int rangeSize = toIndex - fromIndex;
+        Arrays.fill(a, s - rangeSize, s, null);
+        size = s - rangeSize;
+        modCount++;
     }
 
     /**
      * Replaces the element at the specified location in this {@code ArrayList}
      * with the specified object.
      *
-     * @param location
+     * @param index
      *            the index at which to put the specified object.
      * @param object
      *            the object to add.
@@ -570,24 +467,14 @@
      * @throws IndexOutOfBoundsException
      *             when {@code location < 0 || >= size()}
      */
-    @Override
-    public E set(int location, E object) {
-        if (0 <= location && location < (lastIndex - firstIndex)) {
-            E result = array[firstIndex + location];
-            array[firstIndex + location] = object;
-            return result;
+    @Override public E set(int index, E object) {
+        Object[] a = array;
+        if (index >= size) {
+            throwIndexOutOfBoundsException(index, size);
         }
-        throw new IndexOutOfBoundsException();
-    }
-
-    /**
-     * Returns the number of elements in this {@code ArrayList}.
-     *
-     * @return the number of elements in this {@code ArrayList}.
-     */
-    @Override
-    public int size() {
-        return lastIndex - firstIndex;
+        @SuppressWarnings("unchecked") E result = (E) a[index];
+        a[index] = object;
+        return result;
     }
 
     /**
@@ -596,11 +483,10 @@
      *
      * @return an array of the elements from this {@code ArrayList}
      */
-    @Override
-    public Object[] toArray() {
-        int size = lastIndex - firstIndex;
-        Object[] result = new Object[size];
-        System.arraycopy(array, firstIndex, result, 0, size);
+    @Override public Object[] toArray() {
+        int s = size;
+        Object[] result = new Object[s];
+        System.arraycopy(array, 0, result, 0, s);
         return result;
     }
 
@@ -619,17 +505,16 @@
      *             when the type of an element in this {@code ArrayList} cannot
      *             be stored in the type of the specified array.
      */
-    @Override
-    @SuppressWarnings("unchecked")
-    public <T> T[] toArray(T[] contents) {
-        int size = lastIndex - firstIndex;
-        if (size > contents.length) {
-            Class<?> ct = contents.getClass().getComponentType();
-            contents = (T[]) Array.newInstance(ct, size);
+    @Override public <T> T[] toArray(T[] contents) {
+        int s = size;
+        if (contents.length < s) {
+            @SuppressWarnings("unchecked") T[] newArray
+                = (T[]) Array.newInstance(contents.getClass().getComponentType(), s);
+            contents = newArray;
         }
-        System.arraycopy(array, firstIndex, contents, 0, size);
-        if (size < contents.length) {
-            contents[size] = null;
+        System.arraycopy(this.array, 0, contents, 0, s);
+        if (contents.length > s) {
+            contents[s] = null;
         }
         return contents;
     }
@@ -641,37 +526,132 @@
      * @see #size
      */
     public void trimToSize() {
-        int size = lastIndex - firstIndex;
-        E[] newArray = newElementArray(size);
-        System.arraycopy(array, firstIndex, newArray, 0, size);
-        array = newArray;
-        firstIndex = 0;
-        lastIndex = array.length;
-        modCount = 0;
+        int s = size;
+        if (s == array.length) {
+            return;
+        }
+        if (s == 0) {
+            array = EMPTY_OBJECT_ARRAY;
+        } else {
+            Object[] newArray = new Object[s];
+            System.arraycopy(array, 0, newArray, 0, s);
+            array = newArray;
+        }
+        modCount++;
     }
 
-    private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
-            "size", Integer.TYPE) }; //$NON-NLS-1$
+    @Override public Iterator<E> iterator() {
+        return new ArrayListIterator();
+    }
+
+    private class ArrayListIterator implements Iterator<E> {
+        /** Number of elements remaining in this iteration */
+        private int remaining = size;
+
+        /** Index of element that remove() would remove, or -1 if no such elt */
+        private int removalIndex = -1;
+
+        /** The expected modCount value */
+        private int expectedModCount = modCount;
+
+        public boolean hasNext() {
+            return remaining != 0;
+        }
+
+        @SuppressWarnings("unchecked") public E next() {
+            ArrayList<E> ourList = ArrayList.this;
+            int rem = remaining;
+            if (ourList.modCount != expectedModCount) {
+                throw new ConcurrentModificationException();
+            }
+            if (rem == 0) {
+                throw new NoSuchElementException();
+            }
+            remaining = rem - 1;
+            return (E) ourList.array[removalIndex = ourList.size - rem];
+        }
+
+        public void remove() {
+            Object[] a = array;
+            int removalIdx = removalIndex;
+            if (modCount != expectedModCount) {
+                throw new ConcurrentModificationException();
+            }
+            if (removalIdx < 0) {
+                throw new IllegalStateException();
+            }
+            System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining);
+            a[--size] = null;  // Prevent memory leak
+            removalIndex = -1;
+            expectedModCount = ++modCount;
+        }
+    }
+
+    @Override public int hashCode() {
+        Object[] a = array;
+        int hashCode = 1;
+        for (int i = 0, s = size; i < s; i++) {
+            Object e = a[i];
+            hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
+        }
+        return hashCode;
+    }
+
+    @Override public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof List)) {
+            return false;
+        }
+        List<?> that = (List<?>) o;
+        int s = size;
+        if (that.size() != s) {
+            return false;
+        }
+        Object[] a = array;
+        if (that instanceof RandomAccess) {
+            for (int i = 0; i < s; i++) {
+                Object eThis = a[i];
+                Object ethat = that.get(i);
+                if (eThis == null ? ethat != null : !eThis.equals(ethat)) {
+                    return false;
+                }
+            }
+        } else {  // Argument list is not random access; use its iterator
+            Iterator<?> it = that.iterator();
+            for (int i = 0; i < s; i++) {
+                Object eThis = a[i];
+                Object eThat = it.next();
+                if (eThis == null ? eThat != null : !eThis.equals(eThat)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private static final long serialVersionUID = 8683452581122892189L;
 
     private void writeObject(ObjectOutputStream stream) throws IOException {
-        ObjectOutputStream.PutField fields = stream.putFields();
-        fields.put("size", lastIndex - firstIndex); //$NON-NLS-1$
-        stream.writeFields();
+        stream.defaultWriteObject();
         stream.writeInt(array.length);
-        Iterator<?> it = iterator();
-        while (it.hasNext()) {
-            stream.writeObject(it.next());
+        for (int i = 0; i < size; i++) {
+            stream.writeObject(array[i]);
         }
     }
 
-    @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
-        ObjectInputStream.GetField fields = stream.readFields();
-        lastIndex = fields.get("size", 0); //$NON-NLS-1$
-        array = newElementArray(stream.readInt());
-        for (int i = 0; i < lastIndex; i++) {
-            array[i] = (E) stream.readObject();
+        stream.defaultReadObject();
+        int cap = stream.readInt();
+        if (cap < size) {
+            throw new InvalidObjectException(
+                    "Capacity: " + cap + " < size: " + size);
+        }
+        array = (cap == 0 ? EMPTY_OBJECT_ARRAY : new Object[cap]);
+        for (int i = 0; i < size; i++) {
+            array[i] = stream.readObject();
         }
     }
-}
+ }
diff --git a/libcore/luni/src/main/java/java/util/Arrays.java b/libcore/luni/src/main/java/java/util/Arrays.java
index 4fc1e85..ba03251 100644
--- a/libcore/luni/src/main/java/java/util/Arrays.java
+++ b/libcore/luni/src/main/java/java/util/Arrays.java
@@ -20,6 +20,8 @@
 import java.io.Serializable;
 import java.lang.reflect.Array;
 
+import org.apache.harmony.luni.util.Msg;
+
 /**
  * {@code Arrays} contains static methods which operate on arrays.
  *
@@ -492,14 +494,7 @@
      *                if {@code start < 0} or {@code end > array.length}.
      */
     public static void fill(byte[] array, int start, int end, byte value) {
-        // Check for null first
-        int length = array.length;
-        if (start > end) {
-            throw new IllegalArgumentException();
-        }
-        if (start < 0 || end > length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+        checkBounds(array.length, start, end);
         for (int i = start; i < end; i++) {
             array[i] = value;
         }
@@ -536,14 +531,7 @@
      *                if {@code start < 0} or {@code end > array.length}.
      */
     public static void fill(short[] array, int start, int end, short value) {
-        // Check for null first
-        int length = array.length;
-        if (start > end) {
-            throw new IllegalArgumentException();
-        }
-        if (start < 0 || end > length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+        checkBounds(array.length, start, end);
         for (int i = start; i < end; i++) {
             array[i] = value;
         }
@@ -580,14 +568,7 @@
      *                if {@code start < 0} or {@code end > array.length}.
      */
     public static void fill(char[] array, int start, int end, char value) {
-        // Check for null first
-        int length = array.length;
-        if (start > end) {
-            throw new IllegalArgumentException();
-        }
-        if (start < 0 || end > length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+        checkBounds(array.length, start, end);
         for (int i = start; i < end; i++) {
             array[i] = value;
         }
@@ -624,14 +605,7 @@
      *                if {@code start < 0} or {@code end > array.length}.
      */
     public static void fill(int[] array, int start, int end, int value) {
-        // Check for null first
-        int length = array.length;
-        if (start > end) {
-            throw new IllegalArgumentException();
-        }
-        if (start < 0 || end > length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+        checkBounds(array.length, start, end);
         for (int i = start; i < end; i++) {
             array[i] = value;
         }
@@ -668,14 +642,7 @@
      *                if {@code start < 0} or {@code end > array.length}.
      */
     public static void fill(long[] array, int start, int end, long value) {
-        // Check for null first
-        int length = array.length;
-        if (start > end) {
-            throw new IllegalArgumentException();
-        }
-        if (start < 0 || end > length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+        checkBounds(array.length, start, end);
         for (int i = start; i < end; i++) {
             array[i] = value;
         }
@@ -712,14 +679,7 @@
      *                if {@code start < 0} or {@code end > array.length}.
      */
     public static void fill(float[] array, int start, int end, float value) {
-        // Check for null first
-        int length = array.length;
-        if (start > end) {
-            throw new IllegalArgumentException();
-        }
-        if (start < 0 || end > length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+        checkBounds(array.length, start, end);
         for (int i = start; i < end; i++) {
             array[i] = value;
         }
@@ -756,14 +716,7 @@
      *                if {@code start < 0} or {@code end > array.length}.
      */
     public static void fill(double[] array, int start, int end, double value) {
-        // Check for null first
-        int length = array.length;
-        if (start > end) {
-            throw new IllegalArgumentException();
-        }
-        if (start < 0 || end > length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+        checkBounds(array.length, start, end);
         for (int i = start; i < end; i++) {
             array[i] = value;
         }
@@ -800,14 +753,7 @@
      *                if {@code start < 0} or {@code end > array.length}.
      */
     public static void fill(boolean[] array, int start, int end, boolean value) {
-        // Check for null first
-        int length = array.length;
-        if (start > end) {
-            throw new IllegalArgumentException();
-        }
-        if (start < 0 || end > length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+        checkBounds(array.length, start, end);
         for (int i = start; i < end; i++) {
             array[i] = value;
         }
@@ -844,14 +790,7 @@
      *                if {@code start < 0} or {@code end > array.length}.
      */
     public static void fill(Object[] array, int start, int end, Object value) {
-        // Check for null first
-        int length = array.length;
-        if (start > end) {
-            throw new IllegalArgumentException();
-        }
-        if (start < 0 || end > length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+        checkBounds(array.length, start, end);
         for (int i = start; i < end; i++) {
             array[i] = value;
         }
@@ -1690,11 +1629,17 @@
 
     private static void checkBounds(int arrLength, int start, int end) {
         if (start > end) {
-            throw new IllegalArgumentException("start(" + start //$NON-NLS-1$
-                    + ") > end(" + end + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+            // K0033=Start index ({0}) is greater than end index ({1})
+            throw new IllegalArgumentException(Msg.getString("K0033", //$NON-NLS-1$
+                    Integer.valueOf(start), Integer.valueOf(end)));
         }
-        if (start < 0 || end > arrLength) {
-            throw new ArrayIndexOutOfBoundsException();
+        if (start < 0) {
+            // K0052=Array index out of range\: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0052", start)); //$NON-NLS-1$
+        }
+        if (end > arrLength) {
+            // K0052=Array index out of range\: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0052", end)); //$NON-NLS-1$
         }
     }
 
diff --git a/libcore/luni/src/main/java/java/util/Collection.java b/libcore/luni/src/main/java/java/util/Collection.java
index 6447e39..1b5cff5 100644
--- a/libcore/luni/src/main/java/java/util/Collection.java
+++ b/libcore/luni/src/main/java/java/util/Collection.java
@@ -24,7 +24,7 @@
  * 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
+ * least two constructors. One with no parameters which creates an empty
  * collection and one with a parameter of type {@code Collection}. This second
  * constructor can be used to create a collection of different type as the
  * initial collection but with the same elements. Implementations of {@code Collection}
@@ -138,7 +138,7 @@
 
     /**
      * Tests whether this {@code Collection} contains all objects contained in the
-     * specified {@code Collection}. If an elemenet {@code elem} is contained several
+     * specified {@code Collection}. If an element {@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}.
      *
diff --git a/libcore/luni/src/main/java/java/util/Collections.java b/libcore/luni/src/main/java/java/util/Collections.java
index 767d98b..77cafea 100644
--- a/libcore/luni/src/main/java/java/util/Collections.java
+++ b/libcore/luni/src/main/java/java/util/Collections.java
@@ -23,6 +23,7 @@
 import java.lang.reflect.Array;
 
 import org.apache.harmony.luni.internal.nls.Messages;
+import org.apache.harmony.luni.util.Msg;
 
 /**
  * {@code Collections} contains static methods which operate on
@@ -1590,7 +1591,8 @@
     public static <T> void copy(List<? super T> destination,
             List<? extends T> source) {
         if (destination.size() < source.size()) {
-            throw new ArrayIndexOutOfBoundsException();
+            // K0032=Source size {0} does not fit into destination
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0032", source.size())); //$NON-NLS-1$
         }
         Iterator<? extends T> srcIt = source.iterator();
         ListIterator<? super T> destIt = destination.listIterator();
@@ -1598,7 +1600,8 @@
             try {
                 destIt.next();
             } catch (NoSuchElementException e) {
-                throw new ArrayIndexOutOfBoundsException();
+                // K0032=Source size {0} does not fit into destination
+                throw new ArrayIndexOutOfBoundsException(Msg.getString("K0032", source.size())); //$NON-NLS-1$
             }
             destIt.set(srcIt.next());
         }
@@ -1841,36 +1844,30 @@
      * @throws UnsupportedOperationException
      *             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();
+        @SuppressWarnings("unchecked") // we won't put foreign objects in
+        final List<Object> objectList = (List<Object>) list;
+
+        if (list instanceof RandomAccess) {
+            for (int i = objectList.size() - 1; i > 0; i--) {
+                int index = random.nextInt(i + 1);
+                objectList.set(index, objectList.set(i, objectList.get(index)));
+            }
+        } else {
+            Object[] array = objectList.toArray();
             for (int i = array.length - 1; i > 0; i--) {
                 int index = random.nextInt(i + 1);
-                if (index < 0) {
-                    index = -index;
-                }
                 Object temp = array[i];
                 array[i] = array[index];
                 array[index] = temp;
             }
 
             int i = 0;
-            ListIterator<Object> it = (ListIterator<Object>) list
-                    .listIterator();
+            ListIterator<Object> it = objectList.listIterator();
             while (it.hasNext()) {
                 it.next();
                 it.set(array[i++]);
             }
-        } else {
-            List<Object> rawList = (List<Object>) list;
-            for (int i = rawList.size() - 1; i > 0; i--) {
-                int index = random.nextInt(i + 1);
-                if (index < 0) {
-                    index = -index;
-                }
-                rawList.set(index, rawList.set(i, rawList.get(index)));
-            }
         }
     }
 
diff --git a/libcore/luni/src/main/java/java/util/Formatter.java b/libcore/luni/src/main/java/java/util/Formatter.java
index d1dd417..912a15e 100644
--- a/libcore/luni/src/main/java/java/util/Formatter.java
+++ b/libcore/luni/src/main/java/java/util/Formatter.java
@@ -885,7 +885,6 @@
         if (transformer == null || ! transformer.locale.equals(l)) {
             transformer = new Transformer(this, l);
         }
-        // END android-changed
 
         int currentObjectIndex = 0;
         Object lastArgument = null;
@@ -893,12 +892,13 @@
         while (formatBuffer.hasRemaining()) {
             parser.reset();
             FormatToken token = parser.getNextFormatToken();
-            String result;
             String plainText = token.getPlainText();
             if (token.getConversionType() == (char) FormatToken.UNSET) {
-                result = plainText;
+                outputCharSequence(plainText);
             } else {
                 plainText = plainText.substring(0, plainText.indexOf('%'));
+                outputCharSequence(plainText);
+
                 Object argument = null;
                 if (token.requireArgument()) {
                     int index = token.getArgIndex() == FormatToken.UNSET ? currentObjectIndex++
@@ -908,21 +908,26 @@
                     lastArgument = argument;
                     hasLastArgumentSet = true;
                 }
-                result = transformer.transform(token, argument);
-                result = (null == result ? plainText : plainText + result);
-            }
-            // if output is made by formattable callback
-            if (null != result) {
-                try {
-                    out.append(result);
-                } catch (IOException e) {
-                    lastIOException = e;
-                }
+                outputCharSequence(transformer.transform(token, argument));
             }
         }
+        // END android-changed
         return this;
     }
 
+    // BEGIN android-added
+    // Fixes http://code.google.com/p/android/issues/detail?id=1767.
+    private void outputCharSequence(CharSequence cs) {
+        if (cs != null) {
+            try {
+                out.append(cs);
+            } catch (IOException e) {
+                lastIOException = e;
+            }
+        }
+    }
+    // END android-added
+
     private Object getArgument(Object[] args, int index, FormatToken token,
             Object lastArgument, boolean hasLastArgumentSet) {
         if (index == FormatToken.LAST_ARGUMENT_INDEX && !hasLastArgumentSet) {
@@ -1184,13 +1189,13 @@
          * Gets the formatted string according to the format token and the
          * argument.
          */
-        String transform(FormatToken token, Object argument) {
+        CharSequence transform(FormatToken token, Object argument) {
 
             /* init data member to print */
             this.formatToken = token;
             this.arg = argument;
 
-            String result;
+            CharSequence result;
             switch (token.getConversionType()) {
                 case 'B':
                 case 'b': {
@@ -1254,7 +1259,7 @@
 
             if (Character.isUpperCase(token.getConversionType())) {
                 if (null != result) {
-                    result = result.toUpperCase(Locale.US);
+                    result = result.toString().toUpperCase(Locale.US);
                 }
             }
             return result;
@@ -1263,7 +1268,7 @@
         /*
          * Transforms the Boolean argument to a formatted string.
          */
-        private String transformFromBoolean() {
+        private CharSequence transformFromBoolean() {
             StringBuilder result = new StringBuilder();
             int startIndex = 0;
             int flags = formatToken.getFlags();
@@ -1294,7 +1299,7 @@
         /*
          * Transforms the hashcode of the argument to a formatted string.
          */
-        private String transformFromHashCode() {
+        private CharSequence transformFromHashCode() {
             StringBuilder result = new StringBuilder();
 
             int startIndex = 0;
@@ -1324,7 +1329,7 @@
         /*
          * Transforms the String to a formatted string.
          */
-        private String transformFromString() {
+        private CharSequence transformFromString() {
             StringBuilder result = new StringBuilder();
             int startIndex = 0;
             int flags = formatToken.getFlags();
@@ -1374,7 +1379,7 @@
         /*
          * Transforms the Character to a formatted string.
          */
-        private String transformFromCharacter() {
+        private CharSequence transformFromCharacter() {
             StringBuilder result = new StringBuilder();
 
             int startIndex = 0;
@@ -1434,7 +1439,7 @@
          * Transforms percent to a formatted string. Only '-' is legal flag.
          * Precision is illegal.
          */
-        private String transformFromPercent() {
+        private CharSequence transformFromPercent() {
             StringBuilder result = new StringBuilder("%"); //$NON-NLS-1$
 
             int startIndex = 0;
@@ -1462,7 +1467,7 @@
          * Transforms line separator to a formatted string. Any flag, the width
          * or the precision is illegal.
          */
-        private String transformFromLineSeparator() {
+        private CharSequence transformFromLineSeparator() {
             if (formatToken.isPrecisionSet()) {
                 throw new IllegalFormatPrecisionException(formatToken
                         .getPrecision());
@@ -1492,7 +1497,7 @@
         /*
          * Pads characters to the formatted string.
          */
-        private String padding(StringBuilder source, int startIndex) {
+        private CharSequence padding(StringBuilder source, int startIndex) {
             int start = startIndex;
             boolean paddingRight = formatToken
                     .isFlagSet(FormatToken.FLAG_MINUS);
@@ -1520,7 +1525,7 @@
                 width = Math.max(source.length(), width);
             }
             if (length >= width) {
-                return source.toString();
+                return source;
             }
 
             char[] paddings = new char[width - length];
@@ -1532,13 +1537,13 @@
             } else {
                 source.insert(start, insertString);
             }
-            return source.toString();
+            return source;
         }
 
         /*
          * Transforms the Integer to a formatted string.
          */
-        private String transformFromInteger() {
+        private CharSequence transformFromInteger() {
             int startIndex = 0;
             boolean isNegative = false;
             StringBuilder result = new StringBuilder();
@@ -1651,7 +1656,7 @@
             if (isNegative
                     && formatToken.isFlagSet(FormatToken.FLAG_PARENTHESIS)) {
                 result = wrapParentheses(result);
-                return result.toString();
+                return result;
 
             }
             if (isNegative && formatToken.isFlagSet(FormatToken.FLAG_ZERO)) {
@@ -1680,7 +1685,7 @@
             return result;
         }
 
-        private String transformFromSpecialNumber() {
+        private CharSequence transformFromSpecialNumber() {
             String source = null;
 
             if (!(arg instanceof Number) || arg instanceof BigDecimal) {
@@ -1713,12 +1718,12 @@
                 formatToken.setPrecision(FormatToken.UNSET);
                 formatToken.setFlags(formatToken.getFlags()
                         & (~FormatToken.FLAG_ZERO));
-                source = padding(new StringBuilder(source), 0);
+                return padding(new StringBuilder(source), 0);
             }
             return source;
         }
 
-        private String transformFromNull() {
+        private CharSequence transformFromNull() {
             formatToken.setFlags(formatToken.getFlags()
                     & (~FormatToken.FLAG_ZERO));
             return padding(new StringBuilder("null"), 0); //$NON-NLS-1$
@@ -1727,7 +1732,7 @@
         /*
          * Transforms a BigInteger to a formatted string.
          */
-        private String transformFromBigInteger() {
+        private CharSequence transformFromBigInteger() {
             int startIndex = 0;
             boolean isNegative = false;
             StringBuilder result = new StringBuilder();
@@ -1817,7 +1822,7 @@
             if (isNegative
                     && formatToken.isFlagSet(FormatToken.FLAG_PARENTHESIS)) {
                 result = wrapParentheses(result);
-                return result.toString();
+                return result;
 
             }
             if (isNegative && formatToken.isFlagSet(FormatToken.FLAG_ZERO)) {
@@ -1829,7 +1834,7 @@
         /*
          * Transforms a Float,Double or BigDecimal to a formatted string.
          */
-        private String transformFromFloat() {
+        private CharSequence transformFromFloat() {
             StringBuilder result = new StringBuilder();
             int startIndex = 0;
             char currentConversionType = formatToken.getConversionType();
@@ -1883,7 +1888,7 @@
                         currentConversionType, arg.getClass());
             }
 
-            String specialNumberResult = transformFromSpecialNumber();
+            CharSequence specialNumberResult = transformFromSpecialNumber();
             if (null != specialNumberResult) {
                 return specialNumberResult;
             }
@@ -1896,7 +1901,7 @@
             }
             // output result
             FloatUtil floatUtil = new FloatUtil(result, formatToken,
-                    (DecimalFormat) NumberFormat.getInstance(locale), arg);
+                    (DecimalFormat) getNumberFormat(), arg);
             floatUtil.transform(formatToken, result);
 
             formatToken.setPrecision(FormatToken.UNSET);
@@ -1904,7 +1909,7 @@
             if (getDecimalFormatSymbols().getMinusSign() == result.charAt(0)) {
                 if (formatToken.isFlagSet(FormatToken.FLAG_PARENTHESIS)) {
                     result = wrapParentheses(result);
-                    return result.toString();
+                    return result;
                 }
             } else {
                 if (formatToken.isFlagSet(FormatToken.FLAG_SPACE)) {
@@ -1933,7 +1938,7 @@
         /*
          * Transforms a Date to a formatted string.
          */
-        private String transformFromDateTime() {
+        private CharSequence transformFromDateTime() {
             int startIndex = 0;
             char currentConversionType = formatToken.getConversionType();
 
@@ -2110,18 +2115,15 @@
 
             } else {
                 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 = b.movePointRight(precision + 1).longValue();
-                    b.movePointLeft(precision + 1);
                     if (String.valueOf(l).length() <= formatToken
                             .getPrecision()) {
                         precision++;
                     }
                     l = b.movePointRight(precision).longValue();
-                    b.movePointLeft(precision);
                     if (l >= Math.pow(10, precision - 4)) {
                         formatToken.setPrecision(precision);
                     }
diff --git a/libcore/luni/src/main/java/java/util/GregorianCalendar.java b/libcore/luni/src/main/java/java/util/GregorianCalendar.java
index d8cd556..7339151 100644
--- a/libcore/luni/src/main/java/java/util/GregorianCalendar.java
+++ b/libcore/luni/src/main/java/java/util/GregorianCalendar.java
@@ -533,7 +533,6 @@
         fields[MINUTE] = (millis % 60);
         millis /= 60;
         fields[HOUR_OF_DAY] = (millis % 24);
-        millis /= 24;
         fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
         fields[HOUR] = fields[HOUR_OF_DAY] % 12;
 
diff --git a/libcore/luni/src/main/java/java/util/HashMap.java b/libcore/luni/src/main/java/java/util/HashMap.java
index 28978d4..f79601f 100644
--- a/libcore/luni/src/main/java/java/util/HashMap.java
+++ b/libcore/luni/src/main/java/java/util/HashMap.java
@@ -36,7 +36,7 @@
  * @param <V> the type of mapped values
  */
 public class HashMap<K, V> extends AbstractMap<K, V>
-        implements Cloneable, Serializable, Map<K, V> {
+        implements Cloneable, Serializable {
     /**
      * Min capacity (other than zero) for a HashMap. Must be a power of two
      * greater than 1 (and less than 1 << 30).
diff --git a/libcore/luni/src/main/java/java/util/Locale.java b/libcore/luni/src/main/java/java/util/Locale.java
index b1a1821..3d724d0 100644
--- a/libcore/luni/src/main/java/java/util/Locale.java
+++ b/libcore/luni/src/main/java/java/util/Locale.java
@@ -48,7 +48,9 @@
 
     private static final long serialVersionUID = 9149081749638150636L;
 
+    // BEGIN android-added
     private static volatile Locale[] availableLocales;
+    // END android-added
 
     // Initialize a default which is used during static
     // initialization of the default for the platform.
@@ -304,93 +306,6 @@
         return false;
     }
 
-    // BEGIN android-removed
-    // static Locale[] find(String prefix) {
-    //     int last = prefix.lastIndexOf('/');
-    //     final String thePackage = prefix.substring(0, last + 1);
-    //     int length = prefix.length();
-    //     final String classPrefix = prefix.substring(last + 1, length);
-    //     Set<String> result = new HashSet<String>();
-    //     StringTokenizer paths = new StringTokenizer(System.getProperty(
-    //             "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);
-    //         if (directory.exists()) {
-    //             if (directory.isDirectory()) {
-    //                 String path;
-    //                 try {
-    //                     path = directory.getCanonicalPath();
-    //                 } catch (IOException e) {
-    //                     continue;
-    //                 }
-    //                 File newDir;
-    //                 if (path.charAt(path.length() - 1) == File.separatorChar) {
-    //                     newDir = new File(path + thePackage);
-    //                 } else {
-    //                     newDir = new File(path + File.separatorChar
-    //                             + thePackage);
-    //                 }
-    //                 if (newDir.isDirectory()) {
-    //                     String[] list = newDir.list();
-    //                     for (int i = 0; i < list.length; i++) {
-    //                         String name = list[i];
-    //                         if (name.startsWith(classPrefix)
-    //                                 && name.endsWith(".class")) { //$NON-NLS-1$
-    //                             result
-    //                                     .add(name.substring(0,
-    //                                             name.length() - 6));
-    //                         }
-    //                     }
-    //                 }
-    //
-    //             } else {
-    //                 // Handle ZIP/JAR files.
-    //                 try {
-    //                     ZipFile zip = new ZipFile(directory);
-    //                     Enumeration<? extends ZipEntry> entries = zip.entries();
-    //                     while (entries.hasMoreElements()) {
-    //                         ZipEntry e = entries.nextElement();
-    //                         String name = e.getName();
-    //                         if (name.startsWith(prefix)
-    //                                 && name.endsWith(".class")) {//$NON-NLS-1$
-    //                             result.add(name.substring(last + 1, name
-    //                                     .length() - 6));
-    //                         }
-    //                     }
-    //                     zip.close();
-    //                 } catch (IOException e) {
-    //                     // Empty
-    //                 }
-    //             }
-    //         }
-    //     }
-    //     Locale[] locales = new Locale[result.size()];
-    //     int i = 0;
-    //     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 {
-    //             String language = name.substring(index + 1, nextIndex);
-    //             String variant;
-    //             if ((index = name.indexOf('_', nextIndex + 1)) == -1) {
-    //                 variant = ""; //$NON-NLS-1$
-    //                 index = name.length();
-    //             } else {
-    //                 variant = name.substring(index + 1, name.length());
-    //             }
-    //             String country = name.substring(nextIndex + 1, index);
-    //             locales[i++] = new Locale(language, country, variant);
-    //         }
-    //     }
-    //     return locales;
-    // }
-    // END android-removed
-
     // BEGIN android-added
     static Locale[] find() {
         String[] locales = Resources.getAvailableLocales();
diff --git a/libcore/luni/src/main/java/java/util/Random.java b/libcore/luni/src/main/java/java/util/Random.java
index be27258..f893020 100644
--- a/libcore/luni/src/main/java/java/util/Random.java
+++ b/libcore/luni/src/main/java/java/util/Random.java
@@ -52,15 +52,22 @@
      */
     private double nextNextGaussian;
 
+    // BEGIN android-changed
     /**
-     * Construct a random generator with the current time of day in milliseconds
-     * as the initial state.
+     * Constructs a random generator with an initial state that is
+     * unlikely to be duplicated by a subsequent instantiation.
+     *
+     * <p>The initial state (that is, the seed) is <i>partially</i> based
+     * on the current time of day in milliseconds.</p>
      * 
      * @see #setSeed
      */
     public Random() {
-        setSeed(System.currentTimeMillis() + hashCode());
+        // Note: Using identityHashCode() to be hermetic wrt subclasses.
+        internalSetSeed(
+                System.currentTimeMillis() + System.identityHashCode(this));
     }
+    // END android-changed
 
     /**
      * Construct a random generator with the given {@code seed} as the
@@ -72,7 +79,9 @@
      * @see #setSeed
      */
     public Random(long seed) {
-        setSeed(seed);
+        // BEGIN android-changed
+        internalSetSeed(seed);
+        // END android-changed
     }
 
     /**
@@ -236,6 +245,7 @@
         return ((long) next(32) << 32) + next(32);
     }
 
+    // BEGIN android-changed
     /**
      * Modifies the seed a using linear congruential formula presented in <i>The
      * Art of Computer Programming, Volume 2</i>, Section 3.2.1.
@@ -247,7 +257,20 @@
      * @see #Random(long)
      */
     public synchronized void setSeed(long seed) {
+        internalSetSeed(seed);
+    }
+
+    /**
+     * Sets the seed. This is used both in the constructor and in the
+     * default implementation of {@link #setSeed}.
+     *
+     * @param seed
+     *            the seed that alters the state of the random number
+     *            generator.
+     */
+    private void internalSetSeed(long seed) {
         this.seed = (seed ^ multiplier) & ((1L << 48) - 1);
         haveNextNextGaussian = false;
     }
+    // END android-changed
 }
diff --git a/libcore/luni/src/main/java/java/util/Scanner.java b/libcore/luni/src/main/java/java/util/Scanner.java
index dd5c024..f1ca423 100644
--- a/libcore/luni/src/main/java/java/util/Scanner.java
+++ b/libcore/luni/src/main/java/java/util/Scanner.java
@@ -1039,7 +1039,7 @@
      * Returns the next token if it matches the specified pattern. 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. Calling this methos is equivalent to
+     * if input is being read. Calling this method is equivalent to
      * {@code next(Pattern.compile(pattern))}.
      *
      * @param pattern
@@ -1638,7 +1638,7 @@
      * 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}.
+     * @return a string representation of this {@code Scanner}.
      */
     @Override
     public String toString() {
diff --git a/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java b/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java
index 2a1b075..66d9076 100644
--- a/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java
+++ b/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java
@@ -60,6 +60,7 @@
      */
     @Override
     public String getMessage() {
-        return Msg.getString("K034a", flags);
+        // K034a=The flags are {0}
+        return Msg.getString("K034a", flags); //$NON-NLS-1$
     }
 }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java
index e3ea7b5..c1ffef9 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java
@@ -40,7 +40,7 @@
     }
 
     /**
-     * Max elemnts could be hold in the cache.
+     * Max elements could be hold in the cache.
      */
     public static final int CACHE_SIZE = 256;
 
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java
index 25d1e69..94719fe 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java
@@ -44,7 +44,7 @@
      */
     @Override
     protected URLConnection openConnection(URL u) throws IOException {
-        return new HttpURLConnection(u, getDefaultPort());
+        return new HttpURLConnectionImpl(u, getDefaultPort());
     }
 
     /**
@@ -72,7 +72,7 @@
         if (null == u || null == proxy) {
             throw new IllegalArgumentException(Msg.getString("K034b")); //$NON-NLS-1$
         }
-        return new HttpURLConnection(u, getDefaultPort(), proxy);
+        return new HttpURLConnectionImpl(u, getDefaultPort(), proxy);
     }
 
     /**
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
similarity index 97%
rename from libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
rename to libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
index 2dea92b..1ba7d8c 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
@@ -25,6 +25,7 @@
 import java.net.Authenticator;
 import java.net.CacheRequest;
 import java.net.CacheResponse;
+import java.net.HttpURLConnection;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.PasswordAuthentication;
@@ -58,7 +59,7 @@
  * such as connecting, sending request and getting the content from the remote
  * server.
  */
-public class HttpURLConnection extends java.net.HttpURLConnection {
+public class HttpURLConnectionImpl extends HttpURLConnection {
     private static final String POST = "POST"; //$NON-NLS-1$
 
     private static final String GET = "GET"; //$NON-NLS-1$
@@ -280,13 +281,14 @@
 
         @Override
         public int read(byte[] buf, int offset, int length) throws IOException {
-            if (buf == null) {
-                throw new NullPointerException();
+            // Force buf null check first, and avoid int overflow
+            if (offset < 0 || offset > buf.length) {
+                // K002e=Offset out of bounds \: {0}
+                throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
             }
-            // avoid int overflow
-            if (offset < 0 || length < 0 || offset > buf.length
-                    || buf.length - offset < length) {
-                throw new ArrayIndexOutOfBoundsException();
+            if (length < 0 || buf.length - offset < length) {
+                // K0031=Length out of bounds \: {0}
+                throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
             }
             if (bytesRemaining <= 0) {
                 disconnect(false);
@@ -421,13 +423,14 @@
 
         @Override
         public int read(byte[] buf, int offset, int length) throws IOException {
-            if (buf == null) {
-                throw new NullPointerException();
+            // Force buf null check first, and avoid int overflow
+            if (offset > buf.length || offset < 0) {
+                // K002e=Offset out of bounds \: {0}
+                throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
             }
-            // avoid int overflow
-            if (offset < 0 || length < 0 || offset > buf.length
-                    || buf.length - offset < length) {
-                throw new ArrayIndexOutOfBoundsException();
+            if (length < 0 || buf.length - offset < length) {
+                // K0031=Length out of bounds \: {0}
+                throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
             }
             if (bytesRemaining <= 0) {
                 readChunkSize();
@@ -690,7 +693,7 @@
      * @param url
      *            URL The URL this connection is connecting
      */
-    protected HttpURLConnection(URL url) {
+    protected HttpURLConnectionImpl(URL url) {
         this(url, 80);
     }
 
@@ -702,7 +705,7 @@
      * @param port
      *            int The default connection port
      */
-    protected HttpURLConnection(URL url, int port) {
+    protected HttpURLConnectionImpl(URL url, int port) {
         super(url);
         defaultPort = port;
         reqHeader = (Header) defaultReqHeader.clone();
@@ -730,7 +733,7 @@
      * @param proxy
      *            Proxy The proxy which is used to make the connection
      */
-    protected HttpURLConnection(URL url, int port, Proxy proxy) {
+    protected HttpURLConnectionImpl(URL url, int port, Proxy proxy) {
         this(url, port);
         this.proxy = proxy;
     }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java
index ef68a71..c6bf994 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java
@@ -32,7 +32,7 @@
 
     @Override
     protected URLConnection openConnection(URL url) throws IOException {
-        return new HttpsURLConnection(url, getDefaultPort());
+        return new HttpsURLConnectionImpl(url, getDefaultPort());
     }
 
     @Override
@@ -42,7 +42,7 @@
             // K034b=url and proxy can not be null
             throw new IllegalArgumentException(Msg.getString("K034b")); //$NON-NLS-1$
         }
-        return new HttpsURLConnection(url, getDefaultPort(), proxy);
+        return new HttpsURLConnectionImpl(url, getDefaultPort(), proxy);
     }
 
     @Override
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnectionImpl.java
similarity index 96%
rename from libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java
rename to libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnectionImpl.java
index 4d0aff7..2ad5b13 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnectionImpl.java
@@ -28,16 +28,17 @@
 import java.util.List;
 import java.util.Map;
 
+import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLPeerUnverifiedException;
 import javax.net.ssl.SSLSocket;
 
-import org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection;
+import org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl;
 import org.apache.harmony.luni.internal.nls.Messages;
 
 /**
  * HttpsURLConnection implementation.
  */
-public class HttpsURLConnection extends javax.net.ssl.HttpsURLConnection {
+public class HttpsURLConnectionImpl extends HttpsURLConnection {
 
     // Https engine to be wrapped
     private final HttpsEngine httpsEngine;
@@ -45,12 +46,12 @@
     // SSLSocket to be used for connection
     private SSLSocket sslSocket;
 
-    protected HttpsURLConnection(URL url, int port) {
+    protected HttpsURLConnectionImpl(URL url, int port) {
         super(url);
         httpsEngine = new HttpsEngine(url, port);
     }
 
-    protected HttpsURLConnection(URL url, int port, Proxy proxy) {
+    protected HttpsURLConnectionImpl(URL url, int port, Proxy proxy) {
         super(url);
         httpsEngine = new HttpsEngine(url, port, proxy);
     }
@@ -345,7 +346,7 @@
     /**
      * HttpsEngine
      */
-    private class HttpsEngine extends HttpURLConnection {
+    private class HttpsEngine extends HttpURLConnectionImpl {
 
         // In case of using proxy this field indicates
         // if it is a SSL Tunnel establishing stage
@@ -364,7 +365,7 @@
             if (connected) {
                 return;
             }
-            if (usingProxy() && !makingSSLTunnel) {
+            if (super.usingProxy() && !makingSSLTunnel) {
                 // SSL Tunnel through the proxy was not established yet, do so
                 makingSSLTunnel = true;
                 // first - make the connection
@@ -402,7 +403,7 @@
 
         @Override
         protected String requestString() {
-            if (usingProxy()) {
+            if (super.usingProxy()) {
                 if (makingSSLTunnel) {
                     // we are making the SSL Tunneling, return remotehost:port
                     int port = url.getPort();
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
index 4db9910..b31cb39 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
@@ -42,7 +42,7 @@
      */
     @Override
     protected URLConnection openConnection(URL u) throws IOException {
-        return new JarURLConnection(u);
+        return new JarURLConnectionImpl(u);
     }
 
     /**
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnectionImpl.java
similarity index 70%
rename from libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java
rename to libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnectionImpl.java
index 34e7d07..493b768 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnectionImpl.java
@@ -25,6 +25,7 @@
 import java.io.InputStream;
 import java.net.ContentHandler;
 import java.net.ContentHandlerFactory;
+import java.net.JarURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.AccessController;
@@ -42,13 +43,13 @@
 import org.apache.harmony.luni.util.Util;
 
 /**
- * This subclass extends <code>URLConnection</code>.
+ * This subclass extends {@code URLConnection}.
  * <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.
+ * file which can be anywhere that can be referred to by an URL.
  */
-public class JarURLConnection extends java.net.JarURLConnection {
+public class JarURLConnectionImpl extends JarURLConnection {
 
     static HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>();
 
@@ -62,14 +63,16 @@
 
     private boolean closed;
 
-
     /**
      * @param url
      *            the URL of the JAR
      * @throws MalformedURLException
      *             if the URL is malformed
+     * @throws IOException
+     *             if there is a problem opening the connection.
      */
-    public JarURLConnection(java.net.URL url) throws MalformedURLException, IOException {
+    public JarURLConnectionImpl(URL url) throws MalformedURLException,
+            IOException {
         super(url);
         jarFileURL = getJarFileURL();
         jarFileURLConnection = jarFileURL.openConnection();
@@ -88,8 +91,8 @@
     }
 
     /**
-     * Returns the Jar file refered by this <code>URLConnection</code>
-     *
+     * Returns the Jar file referred by this {@code URLConnection}.
+     * 
      * @return the JAR file referenced by this connection
      *
      * @throws IOException
@@ -103,30 +106,30 @@
     }
 
     /**
-     * Returns the Jar file refered by this <code>URLConnection</code>
-     *
+     * Returns the Jar file referred by this {@code URLConnection}
+     * 
      * @throws IOException
      *             if an IO error occurs while connecting to the resource.
      */
     private void findJarFile() throws IOException {
         JarFile jar = null;
         if (getUseCaches()) {
-            synchronized(jarCache){
+            synchronized (jarCache) {
                 jarFile = jarCache.get(jarFileURL);
             }
             if (jarFile == null) {
                 jar = openJarFile();
-                synchronized(jarCache){
+                synchronized (jarCache) {
                     jarFile = jarCache.get(jarFileURL);
-                    if (jarFile == null){
+                    if (jarFile == null) {
                         jarCache.put(jarFileURL, jar);
                         jarFile = jar;
-                    }else{
+                    } else {
                         jar.close();
                     }
                 }
             }
-        }else{
+        } else {
             jarFile = openJarFile();
         }
 
@@ -135,38 +138,42 @@
         }
     }
 
+    @SuppressWarnings("nls")
     JarFile openJarFile() throws IOException {
         JarFile jar = null;
-        if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$
+        if (jarFileURL.getProtocol().equals("file")) {
             jar = new JarFile(new File(Util.decode(jarFileURL.getFile(), false,
                     "UTF-8")), 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];
-                                int nbytes = 0;
-                                while ((nbytes = is.read(buf)) > -1) {
-                                    fos.write(buf, 0, nbytes);
+                        .doPrivileged(new PrivilegedAction<JarFile>() {
+                            public JarFile run() {
+                                try {
+                                    File tempJar = File.createTempFile(
+                                            "hyjar_", ".tmp", null);
+                                    tempJar.deleteOnExit();
+                                    FileOutputStream fos = new FileOutputStream(
+                                            tempJar);
+                                    byte[] buf = new byte[4096];
+                                    int nbytes = 0;
+                                    while ((nbytes = is.read(buf)) > -1) {
+                                        fos.write(buf, 0, nbytes);
+                                    }
+                                    fos.close();
+                                    return new JarFile(tempJar, true,
+                                            ZipFile.OPEN_READ
+                                                    | ZipFile.OPEN_DELETE);
+                                } catch (IOException e) {
+                                    return null;
                                 }
-                                fos.close();
-                                return new JarFile(tempJar,
-                                        true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
-                            } catch (IOException e) {
-                                return null;
                             }
-                        }
-                    });
+                        });
             } finally {
-                if (is != null) is.close();
+                if (is != null) {
+                    is.close();
+                }
             }
         }
 
@@ -174,11 +181,11 @@
     }
 
     /**
-     * Returns the JarEntry of the entry referenced by this
-     * <code>URLConnection</code>.
-     *
-     * @return java.util.jar.JarEntry the JarEntry referenced
-     *
+     * Returns the JarEntry of the entry referenced by this {@code
+     * URLConnection}.
+     * 
+     * @return the JarEntry referenced
+     * 
      * @throws IOException
      *             if an IO error occurs while getting the entry
      */
@@ -190,8 +197,8 @@
     }
 
     /**
-     * Look up the JarEntry of the entry referenced by this
-     * <code>URLConnection</code>.
+     * Look up the JarEntry of the entry referenced by this {@code
+     * URLConnection}.
      */
     private void findJarEntry() throws IOException {
         if (getEntryName() == null) {
@@ -213,15 +220,16 @@
      */
     @Override
     public InputStream getInputStream() throws IOException {
-
         if (closed) {
-            throw new IllegalStateException(Msg.getString("KA027"));
+            // KA027=Inputstream of the JarURLConnection has been closed
+            throw new IllegalStateException(Msg.getString("KA027")); //$NON-NLS-1$
         }
         connect();
         if (jarInput != null) {
             return jarInput;
         }
         if (jarEntry == null) {
+            // K00fc=Jar entry not specified
             throw new IOException(Msg.getString("K00fc")); //$NON-NLS-1$
         }
         return jarInput = new JarURLConnectionInputStream(jarFile
@@ -229,11 +237,11 @@
     }
 
     /**
-     * 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).
-     *
+     * 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
@@ -241,31 +249,30 @@
         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
-                }
-            }
-            if (cType == null) {
-                cType = "content/unknown"; //$NON-NLS-1$
-            }
-            return cType;
         }
+        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
+            }
+        }
+        if (cType == null) {
+            cType = "content/unknown"; //$NON-NLS-1$
+        }
+        return cType;
     }
 
     /**
      * 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
+     * URL is referring to a Jar file, this method answers a content-length
      * returned by URLConnection. For jar entry it should return it's size.
      * Otherwise, it will return -1.
      *
@@ -277,26 +284,25 @@
             connect();
             if (jarEntry == null) {
                 return jarFileURLConnection.getContentLength();
-            } else {
-                return (int) getJarEntry().getSize();
             }
+            return (int) getJarEntry().getSize();
         } catch (IOException e) {
-            //Ignored
+            // Ignored
         }
         return -1;
     }
 
     /**
-     * Returns the object pointed by this <code>URL</code>. If this
-     * 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.
-     *
+     * Returns the object pointed by this {@code URL}. If this URLConnection is
+     * pointing to a Jar File (no Jar Entry), this method will return a {@code
+     * JarFile} 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
-     *
+     *             if an IO error occurred
+     * 
      * @see ContentHandler
      * @see ContentHandlerFactory
      * @see java.io.IOException
@@ -354,9 +360,9 @@
      */
     public static void closeCachedFiles() {
         Set<Map.Entry<URL, JarFile>> s = jarCache.entrySet();
-        synchronized(jarCache){
+        synchronized (jarCache) {
             Iterator<Map.Entry<URL, JarFile>> i = s.iterator();
-            while(i.hasNext()){
+            while (i.hasNext()) {
                 try {
                     ZipFile zip = i.next().getValue();
                     if (zip != null) {
@@ -366,7 +372,7 @@
                     // Ignored
                 }
             }
-       }
+        }
     }
 
     private class JarURLConnectionInputStream extends FilterInputStream {
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java
index 110a0fd..01319e1 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java
@@ -111,12 +111,23 @@
 
         // Subtract the raw offset from all offsets so it can be changed
         // and affect them too.
-        // Find whether there exist any observances of DST.
-
         for (int i = 0; i < mGmtOffs.length; i++) {
             mGmtOffs[i] -= mRawOffset;
+        }
 
-            if (mIsDsts[i] != 0) {
+        // Is this zone still observing DST?
+        // We don't care if they've historically used it: most places have at least once.
+        // We want to know whether the last "schedule info" (the unix times in the mTransitions
+        // array) is in the future. If it is, DST is still relevant.
+        // See http://code.google.com/p/android/issues/detail?id=877.
+        // This test means that for somewhere like Morocco, which tried DST in 2009 but has
+        // no future plans (and thus no future schedule info) will report "true" from
+        // useDaylightTime at the start of 2009 but "false" at the end. This seems appropriate.
+        long currentUnixTime = System.currentTimeMillis() / 1000;
+        if (mTransitions.length > 0) {
+            // (We're really dealing with uint32_t values, so long is most convenient in Java.)
+            long latestScheduleTime = mTransitions[mTransitions.length - 1] & 0xffffffff;
+            if (currentUnixTime < latestScheduleTime) {
                 mUseDst = true;
             }
         }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
index ac0c877..7ae9de6 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
@@ -154,7 +154,6 @@
         close();
     }
 
-    @Override
     public Object getOption(int optID) throws SocketException {
         if (optID == SocketOptions.SO_TIMEOUT) {
             return Integer.valueOf(receiveTimeout);
@@ -285,7 +284,6 @@
      * @throws SocketException thrown if the option value is unsupported or
      *         invalid
      */
-    @Override
     public void setOption(int optID, Object val) throws SocketException {
         /*
          * for datagram sockets on some platforms we have to set both the
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java b/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java
index 4b0b4b4..d19206d 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java
@@ -78,7 +78,8 @@
         }
 
         if (0 > offset || offset >= buffer.length) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e"));//$NON-NLS-1$
+            // K002e=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset));//$NON-NLS-1$
         }
         if (0 > count || offset + count > buffer.length) {
             throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f"));//$NON-NLS-1$
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
index 7613f0e..bee1557 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
@@ -108,10 +108,9 @@
 
     // BEGIN android-deleted
     // public long ttyAvailable() throws IOException;
+    // public long ttyRead(byte[] bytes, int offset, int length) throws IOException;
     // END android-deleted
     
-    public long ttyRead(byte[] bytes, int offset, int length) throws IOException;
-    
     // BEGIN android-added
     public int ioctlAvailable(int fileDescriptor) throws IOException;
     // END android-added
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
index fb47f0d..3577451 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
@@ -66,6 +66,11 @@
     public int writeDirect(FileDescriptor fd, int address, int offset, int count)
             throws IOException;
 
+    // BEGIN android-removed
+    // public int writev(FileDescriptor fd, Object[] buffers, int[] offsets,
+    //         int[] counts, int length) throws IOException;
+    // END android-removed
+
     public void setNonBlocking(FileDescriptor aFD, boolean block)
             throws IOException;
 
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
index 08bdac6..b7a62e2 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
@@ -69,7 +69,7 @@
      * Note that this value for Windows differs from the one for the
      * page size (64K and 4K respectively).
      */
-    public native int getAllocGranularity() throws IOException;
+    public native int getAllocGranularity();
 
     public boolean lock(int fileDescriptor, long start, long length, int type,
             boolean waitFlag) throws IOException {
@@ -79,160 +79,71 @@
         return result != -1;
     }
 
-    private native int unlockImpl(int fileDescriptor, long start, long length);
+    // BEGIN android-changed
+    private native void unlockImpl(int fileDescriptor, long start, long length) throws IOException;
 
     public void unlock(int fileDescriptor, long start, long length)
             throws IOException {
         // Validate arguments
         validateLockArgs(IFileSystem.SHARED_LOCK_TYPE, start, length);
-        int result = unlockImpl(fileDescriptor, start, length);
-        if (result == -1) {
-            throw new IOException();
-        }
+        unlockImpl(fileDescriptor, start, length);
     }
 
-    private native int fflushImpl(int fd, boolean metadata);
-
-    public void fflush(int fileDescriptor, boolean metadata)
-            throws IOException {
-        int result = fflushImpl(fileDescriptor, metadata);
-        if (result == -1) {
-            throw new IOException();
-        }
-    }
+    public native void fflush(int fileDescriptor, boolean metadata) throws IOException;
 
     /*
      * File position seeking.
      */
-
-    private native long seekImpl(int fd, long offset, int whence);
-
-    public long seek(int fileDescriptor, long offset, int whence)
-            throws IOException {
-        long pos = seekImpl(fileDescriptor, offset, whence);
-        if (pos == -1) {
-            throw new IOException();
-        }
-        return pos;
-    }
+    public native long seek(int fd, long offset, int whence) throws IOException;
 
     /*
      * Direct read/write APIs work on addresses.
      */
-    private native long readDirectImpl(int fileDescriptor, int address,
-            int offset, int length);
+    public native long readDirect(int fileDescriptor, int address, int offset, int length);
 
-    public long readDirect(int fileDescriptor, int address, int offset,
-            int length) throws IOException {
-        long bytesRead = readDirectImpl(fileDescriptor, address, offset, length);
-        if (bytesRead < -1) {
-            throw new IOException();
-        }
-        return bytesRead;
-    }
-
-    private native long writeDirectImpl(int fileDescriptor, int address,
-            int offset, int length);
-
-    public long writeDirect(int fileDescriptor, int address, int offset,
-            int length) throws IOException {
-        long bytesWritten = writeDirectImpl(fileDescriptor, address, offset,
-                length);
-        if (bytesWritten < 0) {
-            throw new IOException();
-        }
-        return bytesWritten;
-    }
+    public native long writeDirect(int fileDescriptor, int address, int offset, int length)
+            throws IOException;
 
     /*
      * Indirect read/writes work on byte[]'s
      */
     private native long readImpl(int fileDescriptor, byte[] bytes, int offset,
-            int length);
+            int length) throws IOException;
 
     public long read(int fileDescriptor, byte[] bytes, int offset, int length)
             throws IOException {
         if (bytes == null) {
             throw new NullPointerException();
         }
-        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;
+        return readImpl(fileDescriptor, bytes, offset, length);
     }
 
     private native long writeImpl(int fileDescriptor, byte[] bytes,
-            int offset, int length);
+            int offset, int length) throws IOException;
 
     public long write(int fileDescriptor, byte[] bytes, int offset, int length)
             throws IOException {
-        long bytesWritten = writeImpl(fileDescriptor, bytes, offset, length);
-        if (bytesWritten < 0) {
-            throw new IOException();
+        if (bytes == null) {
+            throw new NullPointerException();
         }
-        return bytesWritten;
+        return writeImpl(fileDescriptor, bytes, offset, length);
     }
+    // END android-changed
 
     /*
      * Scatter/gather calls.
      */
-    public long readv(int fileDescriptor, int[] addresses, int[] offsets,
-            int[] lengths, int size) throws IOException {
-        long bytesRead = readvImpl(fileDescriptor, addresses, offsets, lengths,
-                size);
-        if (bytesRead < -1) {
-            throw new IOException();
-        }
-        return bytesRead;
-    }
+    public native long readv(int fileDescriptor, int[] addresses,
+            int[] offsets, int[] lengths, int size) throws IOException;
 
-    private native long readvImpl(int fileDescriptor, int[] addresses,
-            int[] offsets, int[] lengths, int size);
+    public native long writev(int fileDescriptor, int[] addresses, int[] offsets,
+            int[] lengths, int size) throws IOException;
 
-    public long writev(int fileDescriptor, int[] addresses, int[] offsets,
-            int[] lengths, int size) throws IOException {
-        long bytesWritten = writevImpl(fileDescriptor, addresses, offsets,
-                lengths, size);
-        if (bytesWritten < 0) {
-            throw new IOException();
-        }
-        return bytesWritten;
-    }
+    // BEGIN android-changed
+    public native void close(int fileDescriptor) throws IOException;
 
-    private native long writevImpl(int fileDescriptor, int[] addresses,
-            int[] offsets, int[] lengths, int size);
-
-    private native int closeImpl(int fileDescriptor);
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.harmony.luni.platform.IFileSystem#close(long)
-     */
-    public void close(int fileDescriptor) throws IOException {
-        int rc = closeImpl(fileDescriptor);
-        if (rc == -1) {
-            throw new IOException();
-        }
-    }
-
-    public void truncate(int fileDescriptor, long size) throws IOException {
-        int rc = truncateImpl(fileDescriptor, size);
-        if (rc < 0) {
-            throw new IOException();
-        }
-    }
-
-    private native int truncateImpl(int fileDescriptor, long size);
+    public native void truncate(int fileDescriptor, long size) throws IOException;
+    // END android-changed
 
     public int open(byte[] fileName, int mode) throws FileNotFoundException {
         if (fileName == null) {
@@ -254,16 +165,10 @@
 
     private native int openImpl(byte[] fileName, int mode);
 
-    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();
-        return result;
-    }
-
-    private native long transferImpl(int fileHandler,
-            FileDescriptor socketDescriptor, long offset, long count);
+    // BEGIN android-changed
+    public native long transfer(int fd, FileDescriptor sd, long offset, long count)
+            throws IOException;
+    // END android-changed
 
     // BEGIN android-deleted
     // public long ttyAvailable() throws IOException {
@@ -277,17 +182,15 @@
     // private native long ttyAvailableImpl();
     // END android-deleted
 
-    public long ttyRead(byte[] bytes, int offset, int length) throws IOException {
-        long nChar = ttyReadImpl(bytes, offset, length);
-        // BEGIN android-changed
-        if (nChar < -1) {
-            throw new IOException();
-        }
-        // END android-changed
-        return nChar;
-    }
-
-    private native long ttyReadImpl(byte[] bytes, int offset, int length);
+    // BEGIN android-deleted
+    // public long ttyRead(byte[] bytes, int offset, int length) throws IOException {
+    //    if (bytes == null) {
+    //        throw new NullPointerException();
+    //    }
+    //    return ttyReadImpl(bytes, offset, length);
+    // }
+    // private native long ttyReadImpl(byte[] bytes, int offset, int length) throws IOException;
+    // END android-deleted
 
     // BEGIN android-added
     public native int ioctlAvailable(int fileDescriptor) throws IOException;
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
index 0061d2a..8d06b1c 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
@@ -73,29 +73,33 @@
         return singleton;
     }
 
-    /**
-     * This class is not designed to be publicly instantiated.
-     *
-     * @see #getOSMemory()
+    /*
+     * Native method to determine whether the underlying platform is little
+     * endian.
+     * 
+     * @return <code>true</code> if the platform is little endian or
+     * <code>false</code> if it is big endian.
      */
-    private OSMemory() {
-        super();
-    }
-
-    /**
-     * 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.
-     */
-    // BEGIN android-changed
-    /*public*/
     private static native boolean isLittleEndianImpl();
-    // END android-changed
 
-    public boolean isLittleEndian() {
-        return isLittleEndianImpl();
-    }
+	/**
+	 * This class is not designed to be publicly instantiated.
+	 * 
+	 * @see #getOSMemory()
+	 */
+	private OSMemory() {
+		super();
+	}
+
+    /**
+     * 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.
+     */
+	public boolean isLittleEndian() {
+		return NATIVE_ORDER == Endianness.LITTLE_ENDIAN;
+	}
 
 	/**
 	 * Returns the natural byte order for this machine.
@@ -128,16 +132,8 @@
      * @return the address of the start of the memory block.
 	 * @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
@@ -620,10 +616,8 @@
 
     public int mmap(int fileDescriptor, long alignment, long size,
             int mapMode) throws IOException {
+        // No need to check mmapImpl return as it throws IOException in error cases
         int address = mmapImpl(fileDescriptor, alignment, size, mapMode);
-        if (address == -1) {
-            throw new IOException();
-        }
         return address;
     }
 
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
index bd6a609..a3eae58 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
@@ -829,4 +829,28 @@
 
     static native int writeSocketDirectImpl(FileDescriptor fd, int address, int offset, int count)
             throws IOException;
+
+    // BEGIN android-removed
+    // /**
+    //  * Write given buffers to a socket. The given buffers is a Object array, the
+    //  * element of array must be direct buffer or a byte array to be written.
+    //  *
+    //  * @param fd
+    //  *            the socket on which to write the bytes
+    //  * @param buffers
+    //  *            the element of array must be direct buffer or a byte array to
+    //  *            be written
+    //  * @param offsets
+    //  *            the index of the first byte to be write
+    //  * @param counts
+    //  *            the maximum number of bytes to be written
+    //  * @param length
+    //  *            the size of buffer array
+    //  * @return the actual number of bytes written
+    //  * @throws IOException
+    //  *             if there is an underlying socket problem
+    //  */
+    // public native int writev(FileDescriptor fd, Object[] buffers,
+    //         int[] offsets, int[] counts, int length) throws IOException;
+    // END android-removed
 }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java
index 43702b2..0149cac 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java
@@ -21,14 +21,17 @@
 
 package org.apache.harmony.luni.platform;
 
-
 /**
  * The platform address class is an unsafe virtualization of an OS memory block.
- * 
  */
 public class PlatformAddress implements ICommonDataTypes, Comparable {
 
     /**
+     * This final field defines the sentinel for an unknown address value.
+     */
+    static final int UNKNOWN = -1;
+
+    /**
      * This final field defines the size of an address on this platform.
      */
     static final int SIZEOF = Platform.getMemorySystem().getPointerSize();
@@ -38,12 +41,17 @@
      */
     public static final PlatformAddress NULL = new PlatformAddress(0, 0);
 
+    /**
+     * INVALID is the canonical address with an invalid value
+     * (i.e. a non-address).
+     */
+    public static final PlatformAddress INVALID =
+            new PlatformAddress(UNKNOWN, UNKNOWN);
+
     public static final IMemorySpy memorySpy = new RuntimeMemorySpy();
 
     static final IMemorySystem osMemory = Platform.getMemorySystem();
 
-    static final long UNKNOWN = -1;
-
     final int osaddr;
     
     final long size;
@@ -65,7 +73,7 @@
         memorySpy.autoFree(this);
     }
     
-    public PlatformAddress duplicate(){
+    public PlatformAddress duplicate() {
         return PlatformAddressFactory.on(osaddr, size);
     }
 
@@ -264,7 +272,7 @@
         return "PlatformAddress[" + osaddr + "]"; //$NON-NLS-1$ //$NON-NLS-2$
     }
     
-    public final long getSize(){
+    public final long getSize() {
         return size;
     }
 
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java
index 9ac8064..3590604 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java
@@ -103,7 +103,12 @@
         return addr;
     }
     
-    public static PlatformAddress allocMap(int fd, long start, long size, int mode) throws IOException{
+    public static PlatformAddress allocMap(int fd, long start, long size, int mode) throws IOException {
+        if (size == 0) {
+            // if size is 0, call to mmap has incorrect behaviour on 
+            // unix and windows, so return empty address
+            return mapOn(0, 0);
+        }
         int osAddress = PlatformAddress.osMemory.mmap(fd, start, size, mode);
         PlatformAddress newMemory = mapOn(osAddress, size);
         PlatformAddress.memorySpy.alloc(newMemory);
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties b/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
index 280a8f5..b6cbcef 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
@@ -38,7 +38,7 @@
 K0020=Unknown format
 K002b=Unknown pattern character - '{0}'
 K002c=Access denied {0}
-K002e=Offset out of bounds
+K002e=Offset out of bounds \: {0}
 K002f=Arguments out of bounds
 K0032=Address null or destination port out of range
 K0033=Unknown socket type
@@ -326,3 +326,6 @@
 KA028=Cannot set protocol version when stream in use
 KA029=Can't find resource for bundle {0}, key {1}
 KA030=Write end dead
+K0031=Length out of bounds \: {0}
+K0032=Source size {0} does not fit into destination
+K0033=Start index ({0}) is greater than end index ({1})
diff --git a/libcore/luni/src/main/native/cbigint.c b/libcore/luni/src/main/native/cbigint.c
index d327940..92b2992 100644
--- a/libcore/luni/src/main/native/cbigint.c
+++ b/libcore/luni/src/main/native/cbigint.c
@@ -253,6 +253,34 @@
     }
 }
 
+#ifndef HY_LITTLE_ENDIAN
+void simpleMultiplyAddHighPrecisionBigEndianFix(U_64 *arg1, IDATA length, U_64 arg2, U_32 *result) {
+	/* Assumes result can hold the product and arg2 only holds 32 bits
+	   of information */
+	U_64 product;
+	IDATA index, resultIndex;
+
+	index = resultIndex = 0;
+	product = 0;
+
+	do {
+		product = HIGH_IN_U64(product) + result[halfAt(resultIndex)] + arg2 * LOW_U32_FROM_PTR(arg1 + index);
+		result[halfAt(resultIndex)] = LOW_U32_FROM_VAR(product);
+		++resultIndex;
+		product = HIGH_IN_U64(product) + result[halfAt(resultIndex)] + arg2 * HIGH_U32_FROM_PTR(arg1 + index);
+		result[halfAt(resultIndex)] = LOW_U32_FROM_VAR(product);
+		++resultIndex;
+	} while (++index < length);
+
+	result[halfAt(resultIndex)] += HIGH_U32_FROM_VAR(product);
+	if (result[halfAt(resultIndex)] < HIGH_U32_FROM_VAR(product)) {
+		/* must be careful with ++ operator and macro expansion */
+		++resultIndex;
+		while (++result[halfAt(resultIndex)] == 0) ++resultIndex;
+	}
+}
+#endif
+
 void
 multiplyHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2,
                        U_64 * result, IDATA length)
@@ -281,10 +309,11 @@
     {
       simpleMultiplyAddHighPrecision (arg1, length1, LOW_IN_U64 (arg2[count]),
                                       resultIn32 + (++index));
-      simpleMultiplyAddHighPrecision (arg1, length1,
-                                      HIGH_IN_U64 (arg2[count]),
-                                      resultIn32 + (++index));
-
+#ifdef HY_LITTLE_ENDIAN
+      simpleMultiplyAddHighPrecision(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index));
+#else
+      simpleMultiplyAddHighPrecisionBigEndianFix(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index));
+#endif
     }
 }
 
diff --git a/libcore/luni/src/main/native/fltconst.h b/libcore/luni/src/main/native/fltconst.h
index 03a97cd..940d5fc 100644
--- a/libcore/luni/src/main/native/fltconst.h
+++ b/libcore/luni/src/main/native/fltconst.h
@@ -140,16 +140,23 @@
 #define SET_PINF_SNGL_PTR(fltptr)  *U32P((fltptr)) = SINGLE_EXPONENT_MASK
 #define SET_NINF_SNGL_PTR(fltptr)  *U32P((fltptr)) = (SINGLE_EXPONENT_MASK | SINGLE_SIGN_MASK)
 
-/* on some platforms (HP720) we cannot reference an unaligned float.  Build them by hand, one U_32 at a time. */
-#if defined(ATOMIC_FLOAT_ACCESS)
-#define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) HIGH_U32_FROM_DBL_PTR(dstPtr) = HIGH_U32_FROM_DBL_PTR(aDoublePtr); LOW_U32_FROM_DBL_PTR(dstPtr) = LOW_U32_FROM_DBL_PTR(aDoublePtr)
-#define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) HIGH_U32_FROM_DBL_PTR(aDoublePtr) = HIGH_U32_FROM_DBL_PTR(dstPtr); LOW_U32_FROM_DBL_PTR(aDoublePtr) = LOW_U32_FROM_DBL_PTR(dstPtr)
+#if defined(HY_WORD64)
+ #define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) ((U64U32DBL *)(aDoublePtr))->u64val = ((U64U32DBL *)(dstPtr))->u64val
+ #define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) ((U64U32DBL *)(dstPtr))->u64val = ((U64U32DBL *)(aDoublePtr))->u64val
+ #define STORE_LONG(dstPtr, hi, lo) ((U64U32DBL *)(dstPtr))->u64val = (((U_64)(hi)) << 32) | (lo)
 #else
-#define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) (*(dstPtr) = *(aDoublePtr))
-#define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) (*(aDoublePtr) = *(dstPtr))
-#endif
+ /* on some platforms (HP720) we cannot reference an unaligned float.  Build them by hand, one U_32 at a time. */
+ #if defined(ATOMIC_FLOAT_ACCESS)
+ #define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) HIGH_U32_FROM_DBL_PTR(dstPtr) = HIGH_U32_FROM_DBL_PTR(aDoublePtr); LOW_U32_FROM_DBL_PTR(dstPtr) = LOW_U32_FROM_DBL_PTR(aDoublePtr)
+ #define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) HIGH_U32_FROM_DBL_PTR(aDoublePtr) = HIGH_U32_FROM_DBL_PTR(dstPtr); LOW_U32_FROM_DBL_PTR(aDoublePtr) = LOW_U32_FROM_DBL_PTR(dstPtr)
+ #else
+ #define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) (*(dstPtr) = *(aDoublePtr))
+ #define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) (*(aDoublePtr) = *(dstPtr))
+ #endif
 
-#define STORE_LONG(dstPtr, hi, lo) HIGH_U32_FROM_LONG64_PTR(dstPtr) = (hi); LOW_U32_FROM_LONG64_PTR(dstPtr) = (lo)
+ #define STORE_LONG(dstPtr, hi, lo) HIGH_U32_FROM_LONG64_PTR(dstPtr) = (hi); LOW_U32_FROM_LONG64_PTR(dstPtr) = (lo)
+#endif /* HY_WORD64 */
+
 #define PTR_SINGLE_VALUE(dstPtr, aSinglePtr) (*U32P(aSinglePtr) = *U32P(dstPtr))
 #define PTR_SINGLE_STORE(dstPtr, aSinglePtr) *((U_32 *)(dstPtr)) = (*U32P(aSinglePtr))
 
diff --git a/libcore/luni/src/main/native/java_net_InetAddress.cpp b/libcore/luni/src/main/native/java_net_InetAddress.cpp
index d7b4931..2af493c 100644
--- a/libcore/luni/src/main/native/java_net_InetAddress.cpp
+++ b/libcore/luni/src/main/native/java_net_InetAddress.cpp
@@ -24,12 +24,9 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <netdb.h>
 #include <errno.h>
 
-#include <cutils/properties.h>
-#include <cutils/adb_networking.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <sys/socket.h>
@@ -48,19 +45,6 @@
     }
 }
 
-static void throwNullPointerException(JNIEnv* env)
-{
-    const char* className = "java/lang/NullPointerException";
-
-    jclass exClass = env->FindClass(className);
-
-    if (exClass == NULL) {
-        LOGE("Unable to find class %s", className);
-    } else {
-        env->ThrowNew(exClass, NULL);
-    }
-}
-
 #if LOG_DNS
 static void logIpString(struct addrinfo* ai, const char* name)
 {
@@ -80,33 +64,6 @@
 }
 #endif
 
-static jobjectArray getAllByNameUsingAdb(JNIEnv* env, const char* name)
-{
-    struct in_addr outaddr;
-    jobjectArray addressArray = NULL;
-    jbyteArray byteArray;
-
-#if 0
-    LOGI("ADB networking: -gethostbyname err %d addr 0x%08x %u.%u.%u.%u",
-            err, (unsigned int)outaddr.a.s_addr,
-            outaddr.j[0],outaddr.j[1],
-            outaddr.j[2],outaddr.j[3]);
-#endif
-
-    if (adb_networking_gethostbyname(name, &outaddr) >= 0) {
-        addressArray = env->NewObjectArray(1, byteArrayClass, NULL);
-        byteArray = env->NewByteArray(4);
-        if (addressArray && byteArray) {
-            env->SetByteArrayRegion(byteArray, 0, 4, (jbyte*) &outaddr.s_addr);
-            env->SetObjectArrayElement(addressArray, 1, byteArray);
-        }
-    } else {
-        jniThrowException(env, "java/net/UnknownHostException", "adb error");
-    }
-
-    return addressArray;
-}
-
 static jobjectArray getAllByNameUsingDns(JNIEnv* env, const char* name, 
                                          jboolean preferIPv4Stack)
 {
@@ -208,28 +165,12 @@
                                       jboolean preferIPv4Stack)
 {
     if (javaName == NULL) {
-        throwNullPointerException(env);
+        jniThrowException(env, "java/lang/NullPointerException", NULL);
         return NULL;
     }
 
     const char* name = env->GetStringUTFChars(javaName, NULL);
-    jobjectArray out = NULL;
-
-    char useAdbNetworkingProperty[PROPERTY_VALUE_MAX];
-    char adbConnected[PROPERTY_VALUE_MAX];
-    property_get("android.net.use-adb-networking",
-            useAdbNetworkingProperty, "");
-    property_get("adb.connected",
-            adbConnected, "");
-
-    // Any non-empty string value for use-adb-networking is considered "set"
-    if ((strlen(useAdbNetworkingProperty) > 0)
-            && (strlen(adbConnected) > 0) ) {
-        out = getAllByNameUsingAdb(env, name);
-    } else {
-        out = getAllByNameUsingDns(env, name, preferIPv4Stack);
-    }
-
+    jobjectArray out = getAllByNameUsingDns(env, name, preferIPv4Stack);
     env->ReleaseStringUTFChars(javaName, name);
     return out;
 }
@@ -247,57 +188,44 @@
                                          jbyteArray javaAddress)
 {
     if (javaAddress == NULL) {
-        throwNullPointerException(env);
-        return NULL;
-    }
-
-    size_t addrlen = env->GetArrayLength(javaAddress);
-    jbyte* rawAddress = env->GetByteArrayElements(javaAddress, NULL);
-    if (rawAddress == NULL) {
-        throwNullPointerException(env);
+        jniThrowException(env, "java/lang/NullPointerException", NULL);
         return NULL;
     }
 
     // Convert the raw address bytes into a socket address structure.
-    int ret = 0;
     struct sockaddr_storage ss;
-    struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
-    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
-    size_t socklen;
     memset(&ss, 0, sizeof(ss));
-    switch (addrlen) {
-        case 4:
-            socklen = sizeof(struct sockaddr_in);
-            sin->sin_family = AF_INET;
-            memcpy(&sin->sin_addr.s_addr, rawAddress, addrlen);
-            env->ReleaseByteArrayElements(javaAddress, rawAddress, JNI_ABORT);
-            break;
-        case 16:
-            socklen = sizeof(struct sockaddr_in6);
-            sin6->sin6_family = AF_INET6;
-            memcpy(&sin6->sin6_addr.s6_addr, rawAddress, addrlen);
-            env->ReleaseByteArrayElements(javaAddress, rawAddress, JNI_ABORT);
-            break;
-        default:
-            // The caller already throws an exception in this case. Don't worry
-            // about it here.
-            env->ReleaseByteArrayElements(javaAddress, rawAddress, JNI_ABORT);
-            return NULL;
+
+    size_t socklen;
+    const size_t addressLength = env->GetArrayLength(javaAddress);
+    if (addressLength == 4) {
+        struct sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(&ss);
+        sin->sin_family = AF_INET;
+        socklen = sizeof(struct sockaddr_in);
+        jbyte* dst = reinterpret_cast<jbyte*>(&sin->sin_addr.s_addr);
+        env->GetByteArrayRegion(javaAddress, 0, 4, dst);
+    } else if (addressLength == 16) {
+        struct sockaddr_in6 *sin6 = reinterpret_cast<sockaddr_in6*>(&ss);
+        sin6->sin6_family = AF_INET6;
+        socklen = sizeof(struct sockaddr_in6);
+        jbyte* dst = reinterpret_cast<jbyte*>(&sin6->sin6_addr.s6_addr);
+        env->GetByteArrayRegion(javaAddress, 0, 16, dst);
+    } else {
+        // The caller already throws an exception in this case. Don't worry
+        // about it here.
+        return NULL;
     }
 
     // Look up the host name from the IP address.
     char name[NI_MAXHOST];
-    if (ret == 0) {
-        ret = getnameinfo((struct sockaddr *) &ss, socklen, name, sizeof(name),
-                          NULL, 0, NI_NAMEREQD);
+    int ret = getnameinfo(reinterpret_cast<sockaddr*>(&ss), socklen,
+                          name, sizeof(name), NULL, 0, NI_NAMEREQD);
+    if (ret != 0) {
+        jniThrowException(env, "java/net/UnknownHostException", gai_strerror(ret));
+        return NULL;
     }
 
-    if (ret == 0) {
-        return env->NewStringUTF(name);
-    }
-
-    jniThrowException(env, "java/net/UnknownHostException", gai_strerror(ret));
-    return NULL;
+    return env->NewStringUTF(name);
 }
 
 /*
diff --git a/libcore/luni/src/main/native/java_net_NetworkInterface.c b/libcore/luni/src/main/native/java_net_NetworkInterface.c
deleted file mode 100644
index db6d503..0000000
--- a/libcore/luni/src/main/native/java_net_NetworkInterface.c
+++ /dev/null
@@ -1,845 +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.
- */
-
-#include "JNIHelp.h"
-#include "jni.h"
-#include "errno.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <sys/ioctl.h>
-
-//--------------------------------------------------------------------
-// TODO copied from OSNetworkSystem. Might get into a separate .h file
-/**
- * Throws an IOException with the given message.
- */
-static void throwSocketException(JNIEnv *env, const char *message) {
-    jclass exClass = (*env)->FindClass(env, "java/net/SocketException");
-
-    if(exClass == NULL) {
-        LOGE("Unable to find class java/net/SocketException");
-    } else {
-        (*env)->ThrowNew(env, exClass, message);
-    }
-}
-
-
-/**
- * Throws a NullPointerException.
- */
-static void throwNullPointerException(JNIEnv *env) {
-    jclass exClass = (*env)->FindClass(env, "java/lang/NullPointerException");
-
-    if(exClass == NULL) {
-        LOGE("Unable to find class java/lang/NullPointerException");
-    } else {
-        (*env)->ThrowNew(env, exClass, NULL);
-    }
-}
-
-/**
- * @name Socket Errors
- * Error codes for socket operations
- *
- * @internal SOCKERR* range from -200 to -299 avoid overlap
- */
-#define SOCKERR_BADSOCKET          -200 /* generic error */
-#define SOCKERR_NOTINITIALIZED     -201 /* socket library uninitialized */
-#define SOCKERR_BADAF              -202 /* bad address family */
-#define SOCKERR_BADPROTO           -203 /* bad protocol */
-#define SOCKERR_BADTYPE            -204 /* bad type */
-#define SOCKERR_SYSTEMBUSY         -205 /* system busy handling requests */
-#define SOCKERR_SYSTEMFULL         -206 /* too many sockets */
-#define SOCKERR_NOTCONNECTED       -207 /* socket is not connected */
-#define SOCKERR_INTERRUPTED        -208 /* the call was cancelled */
-#define SOCKERR_TIMEOUT            -209 /* the operation timed out */
-#define SOCKERR_CONNRESET          -210 /* the connection was reset */
-#define SOCKERR_WOULDBLOCK         -211 /* the socket is marked as nonblocking operation would block */
-#define SOCKERR_ADDRNOTAVAIL       -212 /* address not available */
-#define SOCKERR_ADDRINUSE          -213 /* address already in use */
-#define SOCKERR_NOTBOUND           -214 /* the socket is not bound */
-#define SOCKERR_UNKNOWNSOCKET      -215 /* resolution of fileDescriptor to socket failed */
-#define SOCKERR_INVALIDTIMEOUT     -216 /* the specified timeout is invalid */
-#define SOCKERR_FDSETFULL          -217 /* Unable to create an FDSET */
-#define SOCKERR_TIMEVALFULL        -218 /* Unable to create a TIMEVAL */
-#define SOCKERR_REMSOCKSHUTDOWN    -219 /* The remote socket has shutdown gracefully */
-#define SOCKERR_NOTLISTENING       -220 /* listen() was not invoked prior to accept() */
-#define SOCKERR_NOTSTREAMSOCK      -221 /* The socket does not support connection-oriented service */
-#define SOCKERR_ALREADYBOUND       -222 /* The socket is already bound to an address */
-#define SOCKERR_NBWITHLINGER       -223 /* The socket is marked non-blocking & SO_LINGER is non-zero */
-#define SOCKERR_ISCONNECTED        -224 /* The socket is already connected */
-#define SOCKERR_NOBUFFERS          -225 /* No buffer space is available */
-#define SOCKERR_HOSTNOTFOUND       -226 /* Authoritative Answer Host not found */
-#define SOCKERR_NODATA             -227 /* Valid name, no data record of requested type */
-#define SOCKERR_BOUNDORCONN        -228 /* The socket has not been bound or is already connected */
-#define SOCKERR_OPNOTSUPP          -229 /* The socket does not support the operation */
-#define SOCKERR_OPTUNSUPP          -230 /* The socket option is not supported */
-#define SOCKERR_OPTARGSINVALID     -231 /* The socket option arguments are invalid */
-#define SOCKERR_SOCKLEVELINVALID   -232 /* The socket level is invalid */
-#define SOCKERR_TIMEOUTFAILURE     -233
-#define SOCKERR_SOCKADDRALLOCFAIL  -234 /* Unable to allocate the sockaddr structure */
-#define SOCKERR_FDSET_SIZEBAD      -235 /* The calculated maximum size of the file descriptor set is bad */
-#define SOCKERR_UNKNOWNFLAG        -236 /* The flag is unknown */
-#define SOCKERR_MSGSIZE            -237 /* The datagram was too big to fit the specified buffer & was truncated. */
-#define SOCKERR_NORECOVERY         -238 /* The operation failed with no recovery possible */
-#define SOCKERR_ARGSINVALID        -239 /* The arguments are invalid */
-#define SOCKERR_BADDESC            -240 /* The socket argument is not a valid file descriptor */
-#define SOCKERR_NOTSOCK            -241 /* The socket argument is not a socket */
-#define SOCKERR_HOSTENTALLOCFAIL   -242 /* Unable to allocate the hostent structure */
-#define SOCKERR_TIMEVALALLOCFAIL   -243 /* Unable to allocate the timeval structure */
-#define SOCKERR_LINGERALLOCFAIL    -244 /* Unable to allocate the linger structure */
-#define SOCKERR_IPMREQALLOCFAIL    -245 /* Unable to allocate the ipmreq structure */
-#define SOCKERR_FDSETALLOCFAIL     -246 /* Unable to allocate the fdset structure */
-#define SOCKERR_OPFAILED           -247
-#define SOCKERR_VALUE_NULL         -248 /* The value indexed was NULL */
-#define SOCKERR_CONNECTION_REFUSED -249 /* connection was refused */
-#define SOCKERR_ENETUNREACH        -250 /* network is not reachable */
-#define SOCKERR_EACCES             -251 /* permissions do not allow action on socket */
-
-/**
- * Answer the errorString corresponding to the errorNumber, if available.
- * This function will answer a default error string, if the errorNumber is not
- * recognized.
- *
- * This function will have to be reworked to handle internationalization properly, removing
- * the explicit strings.
- *
- * @param anErrorNum    the error code to resolve to a human readable string
- *
- * @return  a human readable error string
- */
-
-static char * netLookupErrorString(int anErrorNum) {
-    switch(anErrorNum) {
-        case SOCKERR_BADSOCKET:
-            return "Bad socket";
-        case SOCKERR_NOTINITIALIZED:
-            return "Socket library uninitialized";
-        case SOCKERR_BADAF:
-            return "Bad address family";
-        case SOCKERR_BADPROTO:
-            return "Bad protocol";
-        case SOCKERR_BADTYPE:
-            return "Bad type";
-        case SOCKERR_SYSTEMBUSY:
-            return "System busy handling requests";
-        case SOCKERR_SYSTEMFULL:
-            return "Too many sockets allocated";
-        case SOCKERR_NOTCONNECTED:
-            return "Socket is not connected";
-        case SOCKERR_INTERRUPTED:
-            return "The call was cancelled";
-        case SOCKERR_TIMEOUT:
-            return "The operation timed out";
-        case SOCKERR_CONNRESET:
-            return "The connection was reset";
-        case SOCKERR_WOULDBLOCK:
-            return "The socket is marked as nonblocking operation would block";
-        case SOCKERR_ADDRNOTAVAIL:
-            return "The address is not available";
-        case SOCKERR_ADDRINUSE:
-            return "The address is already in use";
-        case SOCKERR_NOTBOUND:
-            return "The socket is not bound";
-        case SOCKERR_UNKNOWNSOCKET:
-            return "Resolution of the FileDescriptor to socket failed";
-        case SOCKERR_INVALIDTIMEOUT:
-            return "The specified timeout is invalid";
-        case SOCKERR_FDSETFULL:
-            return "Unable to create an FDSET";
-        case SOCKERR_TIMEVALFULL:
-            return "Unable to create a TIMEVAL";
-        case SOCKERR_REMSOCKSHUTDOWN:
-            return "The remote socket has shutdown gracefully";
-        case SOCKERR_NOTLISTENING:
-            return "Listen() was not invoked prior to accept()";
-        case SOCKERR_NOTSTREAMSOCK:
-            return "The socket does not support connection-oriented service";
-        case SOCKERR_ALREADYBOUND:
-            return "The socket is already bound to an address";
-        case SOCKERR_NBWITHLINGER:
-            return "The socket is marked non-blocking & SO_LINGER is non-zero";
-        case SOCKERR_ISCONNECTED:
-            return "The socket is already connected";
-        case SOCKERR_NOBUFFERS:
-            return "No buffer space is available";
-        case SOCKERR_HOSTNOTFOUND:
-            return "Authoritative Answer Host not found";
-        case SOCKERR_NODATA:
-            return "Valid name, no data record of requested type";
-        case SOCKERR_BOUNDORCONN:
-            return "The socket has not been bound or is already connected";
-        case SOCKERR_OPNOTSUPP:
-            return "The socket does not support the operation";
-        case SOCKERR_OPTUNSUPP:
-            return "The socket option is not supported";
-        case SOCKERR_OPTARGSINVALID:
-            return "The socket option arguments are invalid";
-        case SOCKERR_SOCKLEVELINVALID:
-            return "The socket level is invalid";
-        case SOCKERR_TIMEOUTFAILURE:
-            return "The timeout operation failed";
-        case SOCKERR_SOCKADDRALLOCFAIL:
-            return "Failed to allocate address structure";
-        case SOCKERR_FDSET_SIZEBAD:
-            return "The calculated maximum size of the file descriptor set is bad";
-        case SOCKERR_UNKNOWNFLAG:
-            return "The flag is unknown";
-        case SOCKERR_MSGSIZE:
-            return "The datagram was too big to fit the specified buffer, so truncated";
-        case SOCKERR_NORECOVERY:
-            return "The operation failed with no recovery possible";
-        case SOCKERR_ARGSINVALID:
-            return "The arguments are invalid";
-        case SOCKERR_BADDESC:
-            return "The socket argument is not a valid file descriptor";
-        case SOCKERR_NOTSOCK:
-            return "The socket argument is not a socket";
-        case SOCKERR_HOSTENTALLOCFAIL:
-            return "Unable to allocate the hostent structure";
-        case SOCKERR_TIMEVALALLOCFAIL:
-            return "Unable to allocate the timeval structure";
-        case SOCKERR_LINGERALLOCFAIL:
-            return "Unable to allocate the linger structure";
-        case SOCKERR_IPMREQALLOCFAIL:
-            return "Unable to allocate the ipmreq structure";
-        case SOCKERR_FDSETALLOCFAIL:
-            return "Unable to allocate the fdset structure";
-        case SOCKERR_CONNECTION_REFUSED:
-            return "Connection refused";
-
-        default:
-            return "unkown error";
-    }
-}
-
-/**
- * Converts a native address structure to a 4-byte array. Throws a
- * NullPointerException or an IOException in case of error. This is
- * signaled by a return value of -1. The normal return value is 0.
- */
-static int structInToJavaAddress(
-        JNIEnv *env, struct in_addr *address, jbyteArray java_address) {
-
-    if(java_address == NULL) {
-        throwNullPointerException(env);
-        return -1;
-    }
-
-    if((*env)->GetArrayLength(env, java_address) != sizeof(address->s_addr)) {
-        jniThrowIOException(env, errno);
-        return -1;
-    }
-
-    jbyte *java_address_bytes;
-
-    java_address_bytes = (*env)->GetByteArrayElements(env, java_address, NULL);
-
-    memcpy(java_address_bytes, &(address->s_addr), sizeof(address->s_addr));
-
-    (*env)->ReleaseByteArrayElements(env, java_address, java_address_bytes, 0);
-
-    return 0;
-}
-
-static jobject structInToInetAddress(JNIEnv *env, struct in_addr *address) {
-    jbyteArray bytes;
-    int success;
-
-    bytes = (*env)->NewByteArray(env, 4);
-
-    if(bytes == NULL) {
-        return NULL;
-    }
-
-    success = structInToJavaAddress(env, address, bytes);
-
-    if(success < 0) {
-        return NULL;
-    }
-
-    jclass iaddrclass = (*env)->FindClass(env, "java/net/InetAddress");
-
-    if(iaddrclass == NULL) {
-        LOGE("Can't find java/net/InetAddress");
-        jniThrowException(env, "java/lang/ClassNotFoundException", "java.net.InetAddress");
-        return NULL;
-    }
-
-    jmethodID iaddrgetbyaddress = (*env)->GetStaticMethodID(env, iaddrclass, "getByAddress", "([B)Ljava/net/InetAddress;");
-
-    if(iaddrgetbyaddress == NULL) {
-        LOGE("Can't find method InetAddress.getByAddress(byte[] val)");
-        jniThrowException(env, "java/lang/NoSuchMethodError", "InetAddress.getByAddress(byte[] val)");
-        return NULL;
-    }
-
-    return (*env)->CallStaticObjectMethod(env, iaddrclass, iaddrgetbyaddress, bytes);
-}
-//--------------------------------------------------------------------
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* structure for returning either and IPV4 or IPV6 ip address */
-typedef struct ipAddress_struct {
-    union {
-        char bytes[sizeof(struct in_addr)];
-        struct in_addr inAddr;
-    } addr;
-    unsigned int length;
-    unsigned int  scope;
-} ipAddress_struct;
-
-/* structure for returning network interface information */
-typedef struct NetworkInterface_struct {
-    char *name;
-    char *displayName;
-    unsigned int  numberAddresses;
-    unsigned int  index;
-    struct ipAddress_struct *addresses;
-} NetworkInterface_struct;
-
-/* array of network interface structures */
-typedef struct NetworkInterfaceArray_struct {
-    unsigned int  length;
-    struct NetworkInterface_struct *elements;
-} NetworkInterfaceArray_struct;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**
- * Frees the memory allocated for the hyNetworkInterface_struct array passed in
- *
- * @param[in] portLibrary The port library.
- * @param[in] handle Pointer to array of network interface structures to be freed
- *
- * @return 0 on success
-*/
-int sock_free_network_interface_struct (struct NetworkInterfaceArray_struct *array) {
-    unsigned int i = 0;
-
-    if((array != NULL) && (array->elements != NULL)) {
-
-        /* free the allocated memory in each of the structures */
-        for(i = 0; i < array->length; i++) {
-
-            /* free the name, displayName and addresses */
-            if(array->elements[i].name != NULL) {
-                free(array->elements[i].name);
-            }
-
-            if(array->elements[i].displayName != NULL) {
-                free(array->elements[i].displayName);
-            }
-
-            if(array->elements[i].addresses != NULL) {
-                free(array->elements[i].addresses);
-            }
-        }
-
-        /* now free the array itself */
-        free(array->elements);
-    }
-
-    return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**
- * Queries and returns the information for the network interfaces that are currently active within the system.
- * Applications are responsible for freeing the memory returned via the handle.
- *
- * @param[in] portLibrary The port library.
- * @param[in,out] array Pointer to structure with array of network interface entries
- * @param[in] boolean which indicates if we should prefer the IPv4 stack or not
- *
- * @return The number of elements in handle on success, negatvie portable error code on failure.
-                               -WSANO_RECOVERY if system calls required to get the info fail, -WSAENOBUFS if memory allocation fails
- * @note A return value of 0 indicates no interfaces exist
-*/
-int sockGetNetworkInterfaces(struct NetworkInterfaceArray_struct * array) {
-
-    struct NetworkInterface_struct *interfaces = NULL;
-    unsigned int nameLength = 0;
-    unsigned int currentAdapterIndex = 0;
-    unsigned int counter = 0;
-    unsigned int result = 0;
-    unsigned int numAddresses = 0;
-    unsigned int currentIPAddressIndex = 0;
-    unsigned int numAdapters = 0;
-    int err = 0;
-
-    struct ifconf ifc;
-    int len = 32 * sizeof(struct ifreq);
-    int socketP = 0;
-    unsigned int totalInterfaces = 0;
-    struct ifreq reqCopy;
-    unsigned int counter2 = 0;
-    char *lastName = NULL;
-
-    int ifconfCommand = SIOCGIFCONF;
-
-    /* this method is not guarranteed to return the IPV6 addresses.  Code is include so that if the platform returns IPV6 addresses
-       in reply to the SIOCGIFCONF they will be included.  Howerver, it is not guarranteed or even expected that many platforms will
-       include the IPV6 addresses.  For this reason there are other specific implementations that will return the IPV6 addresses */
-    /* first get the list of interfaces.  We do not know how long the buffer needs to be so we try with one that allows for
-       32 interfaces.  If this turns out not to be big enough then we expand the buffer to be able to support another
-       32 interfaces and try again.  We do this until the result indicates that the result fit into the buffer provided */
-    /* we need  socket to do the ioctl so create one */
-    socketP = socket(PF_INET, SOCK_DGRAM, 0);
-    if(socketP < 0) {
-        return socketP;
-    }
-    for(;;) {
-        char *data = (char *)malloc(len * sizeof(char));
-        if(data == NULL) {
-          close(socketP);
-          return SOCKERR_NOBUFFERS;
-        }
-        ifc.ifc_len = len;
-        ifc.ifc_buf = data;
-        errno = 0;
-        if(ioctl(socketP, ifconfCommand, &ifc) != 0) {
-          err = errno;
-          free(ifc.ifc_buf);
-          close(socketP);
-          return SOCKERR_NORECOVERY;
-        }
-        if(ifc.ifc_len < len)
-        break;
-        /* the returned data was likely truncated, expand the buffer and try again */
-        free(ifc.ifc_buf);
-        len += 32 * sizeof(struct ifreq);
-    }
-
-    /* get the number of distinct interfaces */
-    if(ifc.ifc_len != 0) {
-        totalInterfaces = ifc.ifc_len / sizeof(struct ifreq);
-    }
-    lastName = NULL;
-    for(counter = 0; counter < totalInterfaces; counter++) {
-        if((NULL == lastName) || (strncmp(lastName, ifc.ifc_req[counter].ifr_name, IFNAMSIZ) != 0)) {
-            /* make sure the interface is up */
-            reqCopy = ifc.ifc_req[counter];
-            ioctl(socketP, SIOCGIFFLAGS, &reqCopy);
-            if((reqCopy.ifr_flags) & (IFF_UP == IFF_UP)) {
-                numAdapters++;
-            }
-        }
-        lastName = ifc.ifc_req[counter].ifr_name;
-    }
-
-    /* now allocate the space for the hyNetworkInterface structs and fill it in */
-    interfaces = malloc(numAdapters * sizeof(NetworkInterface_struct));
-    if(NULL == interfaces) {
-        free(ifc.ifc_buf);
-        close(socketP);
-        return SOCKERR_NOBUFFERS;
-    }
-
-    /* initialize the structure so that we can free allocated if a failure occurs */
-    for(counter = 0; counter < numAdapters; counter++) {
-        interfaces[counter].name = NULL;
-        interfaces[counter].displayName = NULL;
-        interfaces[counter].addresses = NULL;
-    }
-
-    /* set up the return stucture */
-    array->elements = interfaces;
-    array->length = numAdapters;
-    lastName = NULL;
-    for(counter = 0; counter < totalInterfaces; counter++) {
-        /* make sure the interface is still up */
-        reqCopy = ifc.ifc_req[counter];
-        ioctl(socketP, SIOCGIFFLAGS, &reqCopy);
-        if((reqCopy.ifr_flags) & (IFF_UP == IFF_UP)) {
-            /* since this function can return multiple entries for the same name, only do it for the first one with any given name */
-            if((NULL == lastName) || (strncmp(lastName, ifc.ifc_req[counter].ifr_name, IFNAMSIZ) != 0)) {
-
-                /* get the index for the interface */
-                interfaces[currentAdapterIndex].index =
-                        ifc.ifc_req[counter].ifr_ifindex;
-                /* get the name and display name for the adapter */
-                /* there only seems to be one name so use it for both the name and the display name */
-                nameLength = strlen(ifc.ifc_req[counter].ifr_name);
-                interfaces[currentAdapterIndex].name = malloc(nameLength + 1);
-
-                if(NULL == interfaces[currentAdapterIndex].name) {
-                    free(ifc.ifc_buf);
-                    sock_free_network_interface_struct(array);
-                    close(socketP);
-                    return SOCKERR_NOBUFFERS;
-                }
-                strncpy(interfaces[currentAdapterIndex].name, ifc.ifc_req[counter].ifr_name, nameLength);
-                interfaces[currentAdapterIndex].name[nameLength] = 0;
-                nameLength = strlen(ifc.ifc_req[counter].ifr_name);
-                interfaces[currentAdapterIndex].displayName = malloc(nameLength + 1);
-                if(NULL == interfaces[currentAdapterIndex].displayName) {
-                    free(ifc.ifc_buf);
-                    sock_free_network_interface_struct(array);
-                    close(socketP);
-                    return SOCKERR_NOBUFFERS;
-                }
-                strncpy(interfaces[currentAdapterIndex].displayName, ifc.ifc_req[counter].ifr_name, nameLength);
-                interfaces[currentAdapterIndex].displayName[nameLength] = 0;
-
-                /* check how many addresses/aliases this adapter has.  aliases show up as adaptors with the same name */
-                numAddresses = 0;
-                for(counter2 = counter; counter2 < totalInterfaces; counter2++) {
-                    if(strncmp(ifc.ifc_req[counter].ifr_name, ifc.ifc_req[counter2].ifr_name, IFNAMSIZ) == 0) {
-                        if(ifc.ifc_req[counter2].ifr_addr.sa_family == AF_INET) {
-                            numAddresses++;
-                        }
-                    } else {
-                      break;
-                    }
-                }
-
-                /* allocate space for the addresses */
-                interfaces[currentAdapterIndex].numberAddresses = numAddresses;
-                interfaces[currentAdapterIndex].addresses = malloc(numAddresses * sizeof(ipAddress_struct));
-                if(NULL == interfaces[currentAdapterIndex].addresses) {
-                    free(ifc.ifc_buf);
-                    sock_free_network_interface_struct(array);
-                    close(socketP);
-                    return SOCKERR_NOBUFFERS;
-                }
-
-                /* now get the addresses */
-                currentIPAddressIndex = 0;
-                lastName = ifc.ifc_req[counter].ifr_name;
-
-                for(;;) {
-                    if(ifc.ifc_req[counter].ifr_addr.sa_family == AF_INET) {
-                        interfaces[currentAdapterIndex].addresses[currentIPAddressIndex].addr.inAddr.s_addr = ((struct sockaddr_in *) (&ifc.ifc_req[counter].ifr_addr))->sin_addr.s_addr;
-                        interfaces[currentAdapterIndex].addresses[currentIPAddressIndex].length = sizeof(struct in_addr);
-                        interfaces[currentAdapterIndex].addresses[currentIPAddressIndex].scope = 0;
-                        currentIPAddressIndex++;
-                    }
-
-                    /* we mean to increment the outside counter here as we want to skip the next entry as it is for the same interface
-                                          as we are currently working on */
-                    if((counter + 1 < totalInterfaces) && (strncmp(ifc.ifc_req[counter + 1].ifr_name, lastName, IFNAMSIZ) == 0)) {
-                        counter++;
-                    } else {
-                        break;
-                    }
-
-                }
-                currentAdapterIndex++;
-            }
-        }
-    }          /* for over all interfaces */
-    /* now an interface might have been taken down since we first counted them */
-    array->length = currentAdapterIndex;
-    /* free the memory now that we are done with it */
-    free(ifc.ifc_buf);
-    close(socketP);
-
-    return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**
- * Answer an array of NetworkInterface objects.  One for each network interface within the system
- *
- * @param      env     pointer to the JNI library
- * @param      clazz   the class of the object invoking the JNI function
- *
- * @return                     an array of NetworkInterface objects of length 0 or more
- */
-
-static jobjectArray getNetworkInterfacesImpl(JNIEnv * env, jclass clazz) {
-
-    /* variables to store network interfac edata returned by call to port library */
-    struct NetworkInterfaceArray_struct networkInterfaceArray;
-    int result = 0;
-
-    /* variables for class and method objects needed to create bridge to java */
-    jclass networkInterfaceClass = NULL;
-    jclass inetAddressClass = NULL;
-    jclass utilClass = NULL;
-    jmethodID methodID = NULL;
-    jmethodID utilMid = NULL;
-
-    /* JNI objects used to return values from native call */
-    jstring name = NULL;
-    jstring displayName = NULL;
-    jobjectArray addresses = NULL;
-    jobjectArray networkInterfaces = NULL;
-    jbyteArray bytearray = NULL;
-
-    /* jobjects used to build the object arrays returned */
-    jobject currentInterface = NULL;
-    jobject element = NULL;
-
-    /* misc variables needed for looping and determining inetAddress info */
-    unsigned int i = 0;
-    unsigned int j = 0;
-    unsigned int nameLength = 0;
-
-    /* get the classes and methods that we need for later calls */
-    networkInterfaceClass = (*env)->FindClass(env, "java/net/NetworkInterface");
-    if(networkInterfaceClass == NULL) {
-        throwSocketException(env, netLookupErrorString(SOCKERR_NORECOVERY));
-        return NULL;
-    }
-
-    inetAddressClass = (*env)->FindClass(env, "java/net/InetAddress");
-    if(inetAddressClass == NULL) {
-        throwSocketException(env, netLookupErrorString(SOCKERR_NORECOVERY));
-        return NULL;
-    }
-
-    methodID = (*env)->GetMethodID(env, networkInterfaceClass, "<init>",
-            "(Ljava/lang/String;Ljava/lang/String;[Ljava/net/InetAddress;I)V");
-    if(methodID == NULL) {
-        throwSocketException(env, netLookupErrorString(SOCKERR_NORECOVERY));
-        return NULL;
-    }
-
-    utilClass = (*env)->FindClass(env, "org/apache/harmony/luni/util/Util");
-    if(!utilClass) {
-        return NULL;
-    }
-
-    utilMid = ((*env)->GetStaticMethodID(env, utilClass, "toString",
-            "([BII)Ljava/lang/String;"));
-    if(!utilMid) {
-        return NULL;
-    }
-
-    result = sockGetNetworkInterfaces(&networkInterfaceArray);
-
-    if(result < 0) {
-        /* this means an error occured.  The value returned is the socket error that should be returned */
-        throwSocketException(env, netLookupErrorString(result));
-        return NULL;
-    }
-
-    /* now loop through the interfaces and extract the information to be returned */
-    for(j = 0; j < networkInterfaceArray.length; j++) {
-        /* set the name and display name and reset the addresses object array */
-        addresses = NULL;
-        name = NULL;
-        displayName = NULL;
-
-        if(networkInterfaceArray.elements[j].name != NULL) {
-            nameLength = strlen(networkInterfaceArray.elements[j].name);
-            bytearray = (*env)->NewByteArray(env, nameLength);
-            if(bytearray == NULL) {
-                /* NewByteArray should have thrown an exception */
-                return NULL;
-            }
-            (*env)->SetByteArrayRegion(env, bytearray, (jint) 0, nameLength,
-                    (jbyte *)networkInterfaceArray.elements[j].name);
-            name = (*env)->CallStaticObjectMethod(env, utilClass, utilMid,
-                    bytearray, (jint) 0, nameLength);
-            if((*env)->ExceptionCheck(env)) {
-                return NULL;
-            }
-        }
-
-        if(networkInterfaceArray.elements[j].displayName != NULL) {
-            nameLength = strlen(networkInterfaceArray.elements[j].displayName);
-            bytearray = (*env)->NewByteArray(env, nameLength);
-            if(bytearray == NULL) {
-                /* NewByteArray should have thrown an exception */
-                return NULL;
-            }
-            (*env)->SetByteArrayRegion(env, bytearray, (jint) 0, nameLength,
-                    (jbyte *)networkInterfaceArray.elements[j].displayName);
-            displayName = (*env)->CallStaticObjectMethod(env, utilClass, utilMid,
-                    bytearray, (jint) 0, nameLength);
-            if((*env)->ExceptionCheck(env)) {
-                return NULL;
-            }
-        }
-
-        /* generate the object with the inet addresses for the itnerface       */
-        for(i = 0; i < networkInterfaceArray.elements[j].numberAddresses; i++) {
-            element = structInToInetAddress(env, (struct in_addr *) &(networkInterfaceArray.elements[j].addresses[i].addr.inAddr));
-            if(i == 0) {
-                addresses = (*env)->NewObjectArray(env,
-                        networkInterfaceArray.elements[j].numberAddresses,
-                        inetAddressClass, element);
-            } else {
-                (*env)->SetObjectArrayElement(env, addresses, i, element);
-            }
-        }
-
-        /* now  create the NetworkInterface object for this interface and then add it it ot the arrary that will be returned */
-        currentInterface = (*env)->NewObject(env, networkInterfaceClass,
-                methodID, name, displayName, addresses,
-                networkInterfaceArray.elements[j].index);
-
-        if(j == 0) {
-            networkInterfaces = (*env)->NewObjectArray(env,
-                    networkInterfaceArray.length, networkInterfaceClass,
-                    currentInterface);
-        } else {
-            (*env)->SetObjectArrayElement(env, networkInterfaces, j, currentInterface);
-        }
-    }
-
-    /* free the memory for the interfaces struct and return the new NetworkInterface List */
-    sock_free_network_interface_struct(&networkInterfaceArray);
-    return networkInterfaces;
-}
-
-
-/*
- * JNI registration
- */
-static JNINativeMethod gMethods[] = {
-    /* name, signature, funcPtr */
-    { "getNetworkInterfacesImpl", "()[Ljava/net/NetworkInterface;", getNetworkInterfacesImpl }
-};
-int register_java_net_NetworkInterface(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "java/net/NetworkInterface",
-        gMethods, NELEM(gMethods));
-
-}
diff --git a/libcore/luni/src/main/native/java_net_NetworkInterface.cpp b/libcore/luni/src/main/native/java_net_NetworkInterface.cpp
new file mode 100644
index 0000000..7d27056
--- /dev/null
+++ b/libcore/luni/src/main/native/java_net_NetworkInterface.cpp
@@ -0,0 +1,252 @@
+/*
+ *  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.
+ */
+
+#include "AndroidSystemNatives.h"
+#include "JNIHelp.h"
+#include "jni.h"
+
+#include <errno.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+// A smart pointer that closes the given fd on going out of scope.
+// TODO: make this generally available.
+class scoped_fd {
+public:
+    explicit scoped_fd(int fd) : fd(fd) {
+    }
+
+    ~scoped_fd() {
+        close(fd);
+    }
+
+    int get() const {
+        return fd;
+    }
+
+private:
+    int fd;
+};
+
+// TODO: add a header file for shared utilities like this.
+extern jobject socketAddressToInetAddress(JNIEnv* env, sockaddr_storage* sockAddress);
+
+class NetworkInterfaceGetter {
+public:
+    NetworkInterfaceGetter() : interfaces(NULL) {
+        // Initialize this so we can be responsible for deleting it.
+        ifc.ifc_buf = NULL;
+    }
+
+    ~NetworkInterfaceGetter() {
+        delete[] ifc.ifc_buf;
+    }
+
+    jobjectArray getNetworkInterfaces(JNIEnv* env);
+
+private:
+    jobjectArray interfaces;
+    ifconf ifc;
+};
+
+// TODO: move to JNIHelp?
+static void jniThrowOutOfMemoryError(JNIEnv* env) {
+    jniThrowException(env, "java/lang/OutOfMemoryError", "native heap");
+}
+
+static void jniThrowSocketException(JNIEnv* env) {
+    jniThrowException(env, "java/net/SocketException", strerror(errno));
+}
+
+// Creates an InetAddress[] of size 'addressCount' from the ifc_req structs
+// starting at index 'startIndex' in 'ifc.ifc_req'.
+static jobjectArray MakeInetAddressArray(JNIEnv* env,
+        const ifconf& ifc, size_t startIndex, size_t addressCount) {
+    jclass inetAddressClass = env->FindClass("java/net/InetAddress");
+    if (inetAddressClass == NULL) {
+        return NULL;
+    }
+    jobjectArray addresses = env->NewObjectArray(addressCount, inetAddressClass, NULL);
+    if (addresses == NULL) {
+        return NULL;
+    }
+    for (size_t i = startIndex; i < startIndex + addressCount; ++i) {
+        sockaddr_storage* sockAddress =
+                reinterpret_cast<sockaddr_storage*>(&ifc.ifc_req[i].ifr_addr);
+        jobject element = socketAddressToInetAddress(env, sockAddress);
+        if (element == NULL) {
+            return NULL;
+        }
+        env->SetObjectArrayElement(addresses, i - startIndex, element);
+        if (env->ExceptionCheck()) {
+            return NULL;
+        }
+    }
+    return addresses;
+}
+
+// Creates a NetworkInterface with the given 'name', array of 'addresses',
+// and 'id'.
+static jobject MakeNetworkInterface(JNIEnv* env,
+        jstring name, jobjectArray addresses, jint id) {
+    jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
+    if (networkInterfaceClass == NULL) {
+        return NULL;
+    }
+    jmethodID networkInterfaceConstructor =
+            env->GetMethodID(networkInterfaceClass, "<init>",
+                    "(Ljava/lang/String;Ljava/lang/String;[Ljava/net/InetAddress;I)V");
+    if (networkInterfaceConstructor == NULL) {
+        return NULL;
+    }
+    return env->NewObject(networkInterfaceClass, networkInterfaceConstructor,
+                          name, name, addresses, id);
+}
+
+jobjectArray NetworkInterfaceGetter::getNetworkInterfaces(JNIEnv* env) {
+    scoped_fd fd(socket(PF_INET, SOCK_DGRAM, 0));
+    if (fd.get() < 0) {
+        jniThrowSocketException(env);
+        return NULL;
+    }
+
+    // Get the list of interfaces.
+    // Keep trying larger buffers until the result fits.
+    int len = 32 * sizeof(ifreq);
+    for (;;) {
+        // TODO: std::vector or boost::scoped_array would make this less awful.
+        if (ifc.ifc_buf != NULL) {
+            delete[] ifc.ifc_buf;
+            ifc.ifc_buf = NULL;
+        }
+        char* data = new char[len];
+        if (data == NULL) {
+            jniThrowOutOfMemoryError(env);
+            return NULL;
+        }
+        ifc.ifc_len = len;
+        ifc.ifc_buf = data;
+        if (ioctl(fd.get(), SIOCGIFCONF, &ifc) != 0) {
+            jniThrowSocketException(env);
+            return NULL;
+        }
+        if (ifc.ifc_len < len) {
+            break;
+        }
+        // The returned data was likely truncated.
+        // Expand the buffer and try again.
+        len += 32 * sizeof(ifreq);
+    }
+
+    // Count the number of distinct interfaces.
+    // Multiple addresses for a given interface have the same interface name.
+    // This whole function assumes that all an interface's addresses will be
+    // listed adjacent to one another.
+    size_t totalAddressCount = ifc.ifc_len / sizeof(ifreq);
+    size_t interfaceCount = 0;
+    const char* lastName = NULL;
+    for (size_t i = 0; i < totalAddressCount; ++i) {
+        const char* name = ifc.ifc_req[i].ifr_name;
+        if (lastName == NULL || strncmp(lastName, name, IFNAMSIZ) != 0) {
+            ++interfaceCount;
+        }
+        lastName = name;
+    }
+
+    // Build the NetworkInterface[]...
+    jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
+    if (networkInterfaceClass == NULL) {
+        return NULL;
+    }
+    interfaces = env->NewObjectArray(interfaceCount, networkInterfaceClass, NULL);
+    if (interfaces == NULL) {
+        return NULL;
+    }
+
+    // Fill in the NetworkInterface[].
+    size_t arrayIndex = 0;
+    for (size_t i = 0; i < totalAddressCount; ++i) {
+        // Get the index for this interface.
+        // (This is an id the kernel uses, unrelated to our array indexes.)
+        int id = ifc.ifc_req[i].ifr_ifindex;
+
+        // Get the name for this interface. There only seems to be one name so
+        // we use it for both name and the display name (as does the RI).
+        jstring name = env->NewStringUTF(ifc.ifc_req[i].ifr_name);
+        if (name == NULL) {
+            return NULL;
+        }
+
+        // Check how many addresses this interface has.
+        size_t addressCount = 0;
+        for (size_t j = i; j < totalAddressCount; ++j) {
+            if (strncmp(ifc.ifc_req[i].ifr_name, ifc.ifc_req[j].ifr_name, IFNAMSIZ) == 0) {
+                if (ifc.ifc_req[j].ifr_addr.sa_family == AF_INET) {
+                    ++addressCount;
+                }
+            } else {
+                break;
+            }
+        }
+
+        // Get this interface's addresses as an InetAddress[].
+        jobjectArray addresses = MakeInetAddressArray(env, ifc, i, addressCount);
+        if (addresses == NULL) {
+            return NULL;
+        }
+        // Create the NetworkInterface object and add it to the NetworkInterface[].
+        jobject interface = MakeNetworkInterface(env, name, addresses, id);
+        if (interface == NULL) {
+            return NULL;
+        }
+        env->SetObjectArrayElement(interfaces, arrayIndex++, interface);
+        if (env->ExceptionCheck()) {
+            return NULL;
+        }
+
+        // Skip over this interface's addresses to the next *interface*.
+        i += addressCount - 1;
+    }
+    return interfaces;
+}
+
+/**
+ * Returns an array of zero or more NetworkInterface objects, one for each
+ * network interface.
+ */
+static jobjectArray getNetworkInterfacesImpl(JNIEnv* env, jclass) {
+    NetworkInterfaceGetter getter;
+    return getter.getNetworkInterfaces(env);
+}
+
+/*
+ * JNI registration
+ */
+static JNINativeMethod gMethods[] = {
+    /* name, signature, funcPtr */
+    { "getNetworkInterfacesImpl", "()[Ljava/net/NetworkInterface;", (void*) getNetworkInterfacesImpl },
+};
+int register_java_net_NetworkInterface(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "java/net/NetworkInterface",
+            gMethods, NELEM(gMethods));
+}
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
index 38f3d36..aaa10d3 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
@@ -14,401 +14,305 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
+
+// BEGIN android-note
+// This file corresponds to harmony's OSFileSystem.c and OSFileSystemLinux32.c.
+// It has been greatly simplified by the assumption that the underlying
+// platform is always Linux.
+// END android-note
+
 /*
  * Common natives supporting the file system interface.
  */
 
 #define HyMaxPath 1024
-#define HyOpenRead    1       /* Values for HyFileOpen */
+
+/* Values for HyFileOpen */
+#define HyOpenRead    1
 #define HyOpenWrite   2
 #define HyOpenCreate  4
 #define HyOpenTruncate  8
 #define HyOpenAppend  16
 #define HyOpenText    32
-
 /* Use this flag with HyOpenCreate, if this flag is specified then
- * trying to create an existing file will fail 
+ * trying to create an existing file will fail
  */
 #define HyOpenCreateNew 64
-#define HyOpenSync		128
+#define HyOpenSync      128
 #define SHARED_LOCK_TYPE 1L
 
 #include "JNIHelp.h"
 #include "AndroidSystemNatives.h"
-#include <string.h>
-#include <stdio.h>
+#include <assert.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
 #include <sys/sendfile.h>
 #include <sys/uio.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-typedef struct socket_struct {
-    int sock;
-    unsigned short family;
-} socket_struct;
 
 static void convertToPlatform(char *path) {
     char *pathIndex;
 
     pathIndex = path;
     while (*pathIndex != '\0') {
-        if(*pathIndex == '\\') {
+        if (*pathIndex == '\\') {
             *pathIndex = '/';
         }
         pathIndex++;
     }
 }
 
-static int
-EsTranslateOpenFlags(int flags) {
+static int EsTranslateOpenFlags(int flags) {
     int realFlags = 0;
 
-    if(flags & HyOpenAppend) {
+    if (flags & HyOpenAppend) {
         realFlags |= O_APPEND;
     }
-    if(flags & HyOpenTruncate) {
+    if (flags & HyOpenTruncate) {
         realFlags |= O_TRUNC;
     }
-    if(flags & HyOpenCreate) {
+    if (flags & HyOpenCreate) {
         realFlags |= O_CREAT;
     }
-    if(flags & HyOpenCreateNew) {
+    if (flags & HyOpenCreateNew) {
         realFlags |= O_EXCL | O_CREAT;
     }
 #ifdef O_SYNC
-	if(flags & HyOpenSync) {
-		realFlags |= O_SYNC;
-	}
-#endif    
-    if(flags & HyOpenRead) {
-        if(flags & HyOpenWrite) {
+    if (flags & HyOpenSync) {
+        realFlags |= O_SYNC;
+    }
+#endif
+    if (flags & HyOpenRead) {
+        if (flags & HyOpenWrite) {
             return (O_RDWR | realFlags);
         }
         return (O_RDONLY | realFlags);
     }
-    if(flags & HyOpenWrite) {
+    if (flags & HyOpenWrite) {
         return (O_WRONLY | realFlags);
     }
     return -1;
 }
 
-/**
- * Lock the file identified by the given handle.
- * The range and lock type are given.
- */
-static jint harmony_io_lockImpl(JNIEnv * env, jobject thiz, jint handle, 
-        jlong start, jlong length, jint typeFlag, jboolean waitFlag) {
+// Checks whether we can safely treat the given jlong as an off_t without
+// accidental loss of precision.
+// TODO: this is bogus; we should use _FILE_OFFSET_BITS=64.
+static bool offsetTooLarge(JNIEnv* env, jlong longOffset) {
+    if (sizeof(off_t) >= sizeof(jlong)) {
+        // We're only concerned about the possibility that off_t is
+        // smaller than jlong. off_t is signed, so we don't need to
+        // worry about signed/unsigned.
+        return false;
+    }
 
-    int rc;
-    int waitMode = (waitFlag) ? F_SETLKW : F_SETLK;
+    // TODO: use std::numeric_limits<off_t>::max() and min() when we have them.
+    assert(sizeof(off_t) == sizeof(int));
+    static const off_t off_t_max = INT_MAX;
+    static const off_t off_t_min = INT_MIN;
+
+    if (longOffset > off_t_max || longOffset < off_t_min) {
+        // "Value too large for defined data type".
+        jniThrowIOException(env, EOVERFLOW);
+        return true;
+    }
+    return false;
+}
+
+static jlong translateLockLength(jlong length) {
+    // FileChannel.tryLock uses Long.MAX_VALUE to mean "lock the whole
+    // file", where POSIX would use 0. We can support that special case,
+    // even for files whose actual length we can't represent. For other
+    // out of range lengths, though, we want our range checking to fire.
+    return (length == 0x7fffffffffffffffLL) ? 0 : length;
+}
+
+static struct flock flockFromStartAndLength(jlong start, jlong length) {
     struct flock lock;
-
     memset(&lock, 0, sizeof(lock));
 
-    // If start or length overflow the max values we can represent, then max them out.
-    if(start > 0x7fffffffL) {
-        start = 0x7fffffffL;
-    }
-    if(length > 0x7fffffffL) {
-        length = 0x7fffffffL;
-    }
-
     lock.l_whence = SEEK_SET;
     lock.l_start = start;
     lock.l_len = length;
 
-    if((typeFlag & SHARED_LOCK_TYPE) == SHARED_LOCK_TYPE) {
+    return lock;
+}
+
+static jint harmony_io_lockImpl(JNIEnv* env, jobject, jint handle,
+        jlong start, jlong length, jint typeFlag, jboolean waitFlag) {
+
+    length = translateLockLength(length);
+    if (offsetTooLarge(env, start) || offsetTooLarge(env, length)) {
+        return -1;
+    }
+
+    struct flock lock(flockFromStartAndLength(start, length));
+
+    if ((typeFlag & SHARED_LOCK_TYPE) == SHARED_LOCK_TYPE) {
         lock.l_type = F_RDLCK;
     } else {
         lock.l_type = F_WRLCK;
     }
 
-    do {
-        rc = fcntl(handle, waitMode, &lock);
-    } while ((rc < 0) && (errno == EINTR));
-
-    return (rc == -1) ? -1 : 0;
+    int waitMode = (waitFlag) ? F_SETLKW : F_SETLK;
+    return TEMP_FAILURE_RETRY(fcntl(handle, waitMode, &lock));
 }
 
-/**
- * Unlocks the specified region of the file.
- */
-static jint harmony_io_unlockImpl(JNIEnv * env, jobject thiz, jint handle, 
+static void harmony_io_unlockImpl(JNIEnv* env, jobject, jint handle,
         jlong start, jlong length) {
 
-    int rc;
-    struct flock lock;
-
-    memset(&lock, 0, sizeof(lock));
-
-    // If start or length overflow the max values we can represent, then max them out.
-    if(start > 0x7fffffffL) {
-        start = 0x7fffffffL;
-    }
-    if(length > 0x7fffffffL) {
-        length = 0x7fffffffL;
+    length = translateLockLength(length);
+    if (offsetTooLarge(env, start) || offsetTooLarge(env, length)) {
+        return;
     }
 
-    lock.l_whence = SEEK_SET;
-    lock.l_start = start;
-    lock.l_len = length;
+    struct flock lock(flockFromStartAndLength(start, length));
     lock.l_type = F_UNLCK;
 
-    do {
-        rc = fcntl(handle, F_SETLKW, &lock);
-    } while ((rc < 0) && (errno == EINTR));
-
-    return (rc == -1) ? -1 : 0;
+    int rc = TEMP_FAILURE_RETRY(fcntl(handle, F_SETLKW, &lock));
+    if (rc == -1) {
+        jniThrowIOException(env, errno);
+    }
 }
 
 /**
  * Returns the granularity of the starting address for virtual memory allocation.
  * (It's the same as the page size.)
- * Class:     org_apache_harmony_luni_platform_OSFileSystem
- * Method:    getAllocGranularity
- * Signature: ()I
  */
-static jint harmony_io_getAllocGranularity(JNIEnv * env, jobject thiz) {
-    static int allocGranularity = 0;
-    if(allocGranularity == 0) {
-        allocGranularity = getpagesize();
-    }
+static jint harmony_io_getAllocGranularity(JNIEnv* env, jobject) {
+    static int allocGranularity = getpagesize();
     return allocGranularity;
 }
 
-/*
- * Class:     org_apache_harmony_luni_platform_OSFileSystem
- * Method:    readvImpl
- * Signature: (I[J[I[I)J
- */
-static jlong harmony_io_readvImpl(JNIEnv *env, jobject thiz, jint fd, 
-        jintArray jbuffers, jintArray joffsets, jintArray jlengths, jint size) {
-
-    jboolean bufsCopied = JNI_FALSE;
-    jboolean offsetsCopied = JNI_FALSE;
-    jboolean lengthsCopied = JNI_FALSE;
-    jint *bufs; 
-    jint *offsets;
-    jint *lengths;
-    int i = 0;
-    long totalRead = 0;  
-    struct iovec *vectors = (struct iovec *)malloc(size * sizeof(struct iovec));
-    if(vectors == NULL) {
-        return -1;
+// Translate three Java int[]s to a native iovec[] for readv and writev.
+static iovec* initIoVec(JNIEnv* env,
+        jintArray jBuffers, jintArray jOffsets, jintArray jLengths, jint size) {
+    iovec* vectors = new iovec[size];
+    if (vectors == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", "native heap");
+        return NULL;
     }
-    bufs = env->GetIntArrayElements(jbuffers, &bufsCopied);
-    offsets = env->GetIntArrayElements(joffsets, &offsetsCopied);
-    lengths = env->GetIntArrayElements(jlengths, &lengthsCopied);
-    while(i < size) {
-        vectors[i].iov_base = (void *)((int)(bufs[i]+offsets[i]));
+    jint *buffers = env->GetIntArrayElements(jBuffers, NULL);
+    jint *offsets = env->GetIntArrayElements(jOffsets, NULL);
+    jint *lengths = env->GetIntArrayElements(jLengths, NULL);
+    for (int i = 0; i < size; ++i) {
+        vectors[i].iov_base = reinterpret_cast<void*>(buffers[i] + offsets[i]);
         vectors[i].iov_len = lengths[i];
-        i++;
     }
-    totalRead = readv(fd, vectors, size);
-    if(bufsCopied) {
-        env->ReleaseIntArrayElements(jbuffers, bufs, JNI_ABORT);
-    }
-    if(offsetsCopied) {
-        env->ReleaseIntArrayElements(joffsets, offsets, JNI_ABORT);
-    }
-    if(lengthsCopied) {
-        env->ReleaseIntArrayElements(jlengths, lengths, JNI_ABORT);
-    }
-    free(vectors);
-    return totalRead;
+    env->ReleaseIntArrayElements(jBuffers, buffers, JNI_ABORT);
+    env->ReleaseIntArrayElements(jOffsets, offsets, JNI_ABORT);
+    env->ReleaseIntArrayElements(jLengths, lengths, JNI_ABORT);
+    return vectors;
 }
 
-/*
- * Class:     org_apache_harmony_luni_platform_OSFileSystem
- * Method:    writevImpl
- * Signature: (I[J[I[I)J
- */
-static jlong harmony_io_writevImpl(JNIEnv *env, jobject thiz, jint fd, 
-        jintArray jbuffers, jintArray joffsets, jintArray jlengths, jint size) {
-
-    jboolean bufsCopied = JNI_FALSE;
-    jboolean offsetsCopied = JNI_FALSE;
-    jboolean lengthsCopied = JNI_FALSE;
-    jint *bufs; 
-    jint *offsets;
-    jint *lengths;
-    int i = 0;
-    long totalRead = 0;  
-    struct iovec *vectors = (struct iovec *)malloc(size * sizeof(struct iovec));
-    if(vectors == NULL) {
+static jlong harmony_io_readv(JNIEnv* env, jobject, jint fd,
+        jintArray jBuffers, jintArray jOffsets, jintArray jLengths, jint size) {
+    iovec* vectors = initIoVec(env, jBuffers, jOffsets, jLengths, size);
+    if (vectors == NULL) {
         return -1;
     }
-    bufs = env->GetIntArrayElements(jbuffers, &bufsCopied);
-    offsets = env->GetIntArrayElements(joffsets, &offsetsCopied);
-    lengths = env->GetIntArrayElements(jlengths, &lengthsCopied);
-    while(i < size) {
-        vectors[i].iov_base = (void *)((int)(bufs[i]+offsets[i]));
-        vectors[i].iov_len = lengths[i];
-        i++;
+    long result = readv(fd, vectors, size);
+    if (result == -1) {
+        jniThrowIOException(env, errno);
     }
-    totalRead = writev(fd, vectors, size);
-    if(bufsCopied) {
-        env->ReleaseIntArrayElements(jbuffers, bufs, JNI_ABORT);
-    }
-    if(offsetsCopied) {
-        env->ReleaseIntArrayElements(joffsets, offsets, JNI_ABORT);
-    }
-    if(lengthsCopied) {
-        env->ReleaseIntArrayElements(jlengths, lengths, JNI_ABORT);
-    }
-    free(vectors);
-    return totalRead;
+    delete[] vectors;
+    return result;
 }
 
-/*
- * Class:     org_apache_harmony_luni_platform_OSFileSystem
- * Method:    transferImpl
- * Signature: (IJJ)J
- */
-static jlong harmony_io_transferImpl(JNIEnv *env, jobject thiz, jint fd, 
-        jobject sd, jlong offset, jlong count) {
+static jlong harmony_io_writev(JNIEnv* env, jobject, jint fd,
+        jintArray jBuffers, jintArray jOffsets, jintArray jLengths, jint size) {
+    iovec* vectors = initIoVec(env, jBuffers, jOffsets, jLengths, size);
+    if (vectors == NULL) {
+        return -1;
+    }
+    long result = writev(fd, vectors, size);
+    if (result == -1) {
+        jniThrowIOException(env, errno);
+    }
+    delete[] vectors;
+    return result;
+}
 
-    int socket;
-    off_t off;
+static jlong harmony_io_transfer(JNIEnv* env, jobject, jint fd, jobject sd,
+        jlong offset, jlong count) {
 
-    socket = jniGetFDFromFileDescriptor(env, sd);
-    if(socket == 0 || socket == -1) {
+    int socket = jniGetFDFromFileDescriptor(env, sd);
+    if (socket == -1) {
         return -1;
     }
 
     /* Value of offset is checked in jint scope (checked in java layer)
        The conversion here is to guarantee no value lost when converting offset to off_t
      */
-    off = offset;
+    off_t off = offset;
 
-    return sendfile(socket,(int)fd,(off_t *)&off,(size_t)count);
+    ssize_t rc = sendfile(socket, fd, &off, count);
+    if (rc == -1) {
+        jniThrowIOException(env, errno);
+    }
+    return rc;
 }
 
-/*
- * Class:     org_apache_harmony_io
- * Method:    readDirectImpl
- * Signature: (IJI)J
- */
-static jlong harmony_io_readDirectImpl(JNIEnv * env, jobject thiz, jint fd, 
+static jlong harmony_io_readDirect(JNIEnv* env, jobject, jint fd,
         jint buf, jint offset, jint nbytes) {
-    jint result;
-    if(nbytes == 0) {
-        return (jlong) 0;
+    if (nbytes == 0) {
+        return 0;
     }
 
-    result = read(fd, (void *) ((jint *)(buf+offset)), (int) nbytes);
-    if(result == 0) {
-        return (jlong) -1;
-    } else {
-        return (jlong) result;
+    jbyte* dst = reinterpret_cast<jbyte*>(buf + offset);
+    jlong rc = TEMP_FAILURE_RETRY(read(fd, dst, nbytes));
+    if (rc == 0) {
+        return -1;
     }
+    if (rc == -1) {
+        jniThrowIOException(env, errno);
+    }
+    return rc;
 }
 
-/*
- * Class:     org_apache_harmony_io
- * Method:    writeDirectImpl
- * Signature: (IJI)J
- */
-static jlong harmony_io_writeDirectImpl(JNIEnv * env, jobject thiz, jint fd, 
+static jlong harmony_io_writeDirect(JNIEnv* env, jobject, jint fd,
         jint buf, jint offset, jint nbytes) {
-
-
-    int rc = 0;
-
-    /* write will just do the right thing for HYPORT_TTY_OUT and HYPORT_TTY_ERR */
-    rc = write (fd, (const void *) ((jint *)(buf+offset)), (int) nbytes);
-
-    if(rc == -1) {
-        jniThrowException(env, "java/io/IOException", strerror(errno));
-        return -2;
+    jbyte* src = reinterpret_cast<jbyte*>(buf + offset);
+    jlong rc = TEMP_FAILURE_RETRY(write(fd, src, nbytes));
+    if (rc == -1) {
+        jniThrowIOException(env, errno);
     }
-    return (jlong) rc;
-
+    return rc;
 }
 
-// BEGIN android-changed
-/*
- * Class:     org_apache_harmony_io
- * Method:    readImpl
- * Signature: (I[BII)J
- */
-static jlong harmony_io_readImpl(JNIEnv * env, jobject thiz, jint fd, 
+static jlong harmony_io_readImpl(JNIEnv* env, jobject, jint fd,
         jbyteArray byteArray, jint offset, jint nbytes) {
 
-    jboolean isCopy;
-    jbyte *bytes;
-    jlong result;
-
     if (nbytes == 0) {
         return 0;
     }
 
-    bytes = env->GetByteArrayElements(byteArray, &isCopy);
-
-    for (;;) {
-        result = read(fd, (void *) (bytes + offset), (int) nbytes);
-
-        if ((result != -1) || (errno != EINTR)) {
-            break;
-        }
-
-        /*
-         * If we didn't break above, that means that the read() call
-         * returned due to EINTR. We shield Java code from this
-         * possibility by trying again. Note that this is different
-         * from EAGAIN, which should result in this code throwing
-         * an InterruptedIOException.
-         */
-    }
-
+    jbyte* bytes = env->GetByteArrayElements(byteArray, NULL);
+    jlong rc = TEMP_FAILURE_RETRY(read(fd, bytes + offset, nbytes));
     env->ReleaseByteArrayElements(byteArray, bytes, 0);
 
-    if (result == 0) {
+    if (rc == 0) {
         return -1;
     }
-    
-    if (result == -1) {
+    if (rc == -1) {
         if (errno == EAGAIN) {
             jniThrowException(env, "java/io/InterruptedIOException",
                     "Read timed out");
         } else {
-        jniThrowException(env, "java/io/IOException", strerror(errno));
+            jniThrowIOException(env, errno);
         }
     }
-
-    return result;
+    return rc;
 }
 
-/*
- * Class:     org_apache_harmony_io
- * Method:    writeImpl
- * Signature: (I[BII)J
- */
-static jlong harmony_io_writeImpl(JNIEnv * env, jobject thiz, jint fd, 
+static jlong harmony_io_writeImpl(JNIEnv* env, jobject, jint fd,
         jbyteArray byteArray, jint offset, jint nbytes) {
 
-    jboolean isCopy;
-    jbyte *bytes = env->GetByteArrayElements(byteArray, &isCopy);
-    jlong result;
-
-    for (;;) {
-        result = write(fd, (const char *) bytes + offset, (int) nbytes);
-        
-        if ((result != -1) || (errno != EINTR)) {
-            break;
-        }
-
-        /*
-         * If we didn't break above, that means that the read() call
-         * returned due to EINTR. We shield Java code from this
-         * possibility by trying again. Note that this is different
-         * from EAGAIN, which should result in this code throwing
-         * an InterruptedIOException.
-         */
-    }
-
+    jbyte* bytes = env->GetByteArrayElements(byteArray, NULL);
+    jlong result = TEMP_FAILURE_RETRY(write(fd, bytes + offset, nbytes));
     env->ReleaseByteArrayElements(byteArray, bytes, JNI_ABORT);
 
     if (result == -1) {
@@ -416,157 +320,77 @@
             jniThrowException(env, "java/io/InterruptedIOException",
                     "Write timed out");
         } else {
-        jniThrowException(env, "java/io/IOException", strerror(errno));
+            jniThrowIOException(env, errno);
         }
     }
-
     return result;
 }
-// END android-changed
 
-/**
- * Seeks a file descriptor to a given file position.
- * 
- * @param env pointer to Java environment
- * @param thiz pointer to object receiving the message
- * @param fd handle of file to be seeked
- * @param offset distance of movement in bytes relative to whence arg
- * @param whence enum value indicating from where the offset is relative
- * The valid values are defined in fsconstants.h.
- * @return the new file position from the beginning of the file, in bytes;
- * or -1 if a problem occurs.
- */
-static jlong harmony_io_seekImpl(JNIEnv * env, jobject thiz, jint fd, 
-        jlong offset, jint whence) {
-
-    int mywhence = 0;
-
+static jlong harmony_io_seek(JNIEnv* env, jobject, jint fd, jlong offset,
+        jint javaWhence) {
     /* Convert whence argument */
-    switch (whence) {
-        case 1:
-                mywhence = 0;
-                break;
-        case 2:
-                mywhence = 1;
-                break;
-        case 4:
-                mywhence = 2;
-                break;
-        default:
-                return -1;
-    }
-
-
-    off_t localOffset = (int) offset;
-
-    if((mywhence < 0) || (mywhence > 2)) {
+    int nativeWhence = 0;
+    switch (javaWhence) {
+    case 1:
+        nativeWhence = SEEK_SET;
+        break;
+    case 2:
+        nativeWhence = SEEK_CUR;
+        break;
+    case 4:
+        nativeWhence = SEEK_END;
+        break;
+    default:
         return -1;
     }
 
-    /* If file offsets are 32 bit, truncate the seek to that range */
-    if(sizeof (off_t) < sizeof (jlong)) {
-        if(offset > 0x7FFFFFFF) {
-            localOffset = 0x7FFFFFFF;
-        } else if(offset < -0x7FFFFFFF) {
-            localOffset = -0x7FFFFFFF;
-        }
+    // If the offset is relative, lseek(2) will tell us whether it's too large.
+    // We're just worried about too large an absolute offset, which would cause
+    // us to lie to lseek(2).
+    if (offsetTooLarge(env, offset)) {
+        return -1;
     }
 
-    return (jlong) lseek(fd, localOffset, mywhence);
-}
-
-/**
- * Flushes a file state to disk.
- *
- * @param env pointer to Java environment
- * @param thiz pointer to object receiving the message
- * @param fd handle of file to be flushed
- * @param metadata if true also flush metadata, 
- *         otherwise just flush data is possible.
- * @return zero on success and -1 on failure
- *
- * Method:    fflushImpl
- * Signature: (IZ)I
- */
-static jint harmony_io_fflushImpl(JNIEnv * env, jobject thiz, jint fd, 
-        jboolean metadata) {
-    return (jint) fsync(fd);
-}
-
-// BEGIN android-changed
-/**
- * Closes the given file handle
- * 
- * @param env pointer to Java environment
- * @param thiz pointer to object receiving the message
- * @param fd handle of file to be closed
- * @return zero on success and -1 on failure
- *
- * Class:     org_apache_harmony_io
- * Method:    closeImpl
- * Signature: (I)I
- */
-static jint harmony_io_closeImpl(JNIEnv * env, jobject thiz, jint fd) {
-    jint result;
-
-    for (;;) {
-        result = (jint) close(fd);
-        
-        if ((result != -1) || (errno != EINTR)) {
-            break;
-        }
-
-        /*
-         * If we didn't break above, that means that the close() call
-         * returned due to EINTR. We shield Java code from this
-         * possibility by trying again.
-         */
+    jlong result = lseek(fd, offset, nativeWhence);
+    if (result == -1) {
+        jniThrowIOException(env, errno);
     }
-
     return result;
 }
-// END android-changed
 
-
-/*
- * Class:     org_apache_harmony_io
- * Method:    truncateImpl
- * Signature: (IJ)I
- */
-static jint harmony_io_truncateImpl(JNIEnv * env, jobject thiz, jint fd, 
-        jlong size) {
-
-    int rc;
-    off_t length = (off_t) size;
-
-    // If file offsets are 32 bit, truncate the newLength to that range
-    if(sizeof (off_t) < sizeof (jlong)) {
-        if(length > 0x7FFFFFFF) {
-            length = 0x7FFFFFFF;
-        } else if(length < -0x7FFFFFFF) {
-            length = -0x7FFFFFFF;
-        }
+// TODO: are we supposed to support the 'metadata' flag? (false => fdatasync.)
+static void harmony_io_fflush(JNIEnv* env, jobject, jint fd,
+        jboolean metadata) {
+    int rc = fsync(fd);
+    if (rc == -1) {
+        jniThrowIOException(env, errno);
     }
-
-  rc = ftruncate((int)fd, length);
-
-  return (jint) rc;
-
 }
 
-/*
- * Class:     org_apache_harmony_io
- * Method:    openImpl
- * Signature: ([BI)I
- */
-static jint harmony_io_openImpl(JNIEnv * env, jobject obj, jbyteArray path, 
+static jint harmony_io_close(JNIEnv* env, jobject, jint fd) {
+    jint rc = TEMP_FAILURE_RETRY(close(fd));
+    if (rc == -1) {
+        jniThrowIOException(env, errno);
+    }
+    return rc;
+}
+
+static jint harmony_io_truncate(JNIEnv* env, jobject, jint fd, jlong length) {
+    if (offsetTooLarge(env, length)) {
+        return -1;
+    }
+
+    int rc = ftruncate(fd, length);
+    if (rc == -1) {
+        jniThrowIOException(env, errno);
+    }
+    return rc;
+}
+
+static jint harmony_io_openImpl(JNIEnv* env, jobject, jbyteArray path,
         jint jflags) {
-    
     int flags = 0;
-    int mode = 0; 
-    jint * portFD;
-    jsize length;
-    char pathCopy[HyMaxPath];
+    int mode = 0;
 
 // BEGIN android-changed
 // don't want default permissions to allow global access.
@@ -588,7 +412,7 @@
               mode = 0600;
               break;
       case 256:
-              flags = HyOpenWrite | HyOpenCreate | HyOpenAppend; 
+              flags = HyOpenWrite | HyOpenCreate | HyOpenAppend;
               mode = 0600;
               break;
     }
@@ -596,116 +420,56 @@
 
     flags = EsTranslateOpenFlags(flags);
 
-    length = env->GetArrayLength (path);
+    // TODO: clean this up when we clean up the java.io.File equivalent.
+    jsize length = env->GetArrayLength (path);
     length = length < HyMaxPath - 1 ? length : HyMaxPath - 1;
+    char pathCopy[HyMaxPath];
     env->GetByteArrayRegion (path, 0, length, (jbyte *)pathCopy);
     pathCopy[length] = '\0';
     convertToPlatform (pathCopy);
 
-    int cc;
-    
-    if(pathCopy == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
-        return -1;
-    }
-
-    do {
-        cc = open(pathCopy, flags, mode);
-    } while(cc < 0 && errno == EINTR);
-
-    if(cc < 0 && errno > 0) {
+    jint cc = TEMP_FAILURE_RETRY(open(pathCopy, flags, mode));
+    // TODO: chase up the callers of this and check they wouldn't rather
+    // have us throw a meaningful IOException right here.
+    if (cc < 0 && errno > 0) {
         cc = -errno;
     }
-
     return cc;
-
-
 }
 
-// BEGIN android-deleted
-#if 0
-/*
- * Answers the number of remaining chars in the stdin.
- *
- * Class:     org_apache_harmony_io
- * Method:    ttyAvailableImpl
- * Signature: ()J
- */
-static jlong harmony_io_ttyAvailableImpl(JNIEnv *env, jobject thiz) {
-  
-    int rc;
-    off_t curr, end;
-
-    int avail = 0;
-
-    // when redirected from a file
-    curr = lseek(STDIN_FILENO, 0L, 2);    /* don't use tell(), it doesn't exist on all platforms, i.e. linux */
-    if(curr != -1) {
-        end = lseek(STDIN_FILENO, 0L, 4);
-        lseek(STDIN_FILENO, curr, 1);
-        if(end >= curr) {
-            return (jlong) (end - curr);
-        }
-    }
-
-    /* ioctl doesn't work for files on all platforms (i.e. SOLARIS) */
-
-    rc = ioctl (STDIN_FILENO, FIONREAD, &avail);
-
-    /* 64 bit platforms use a 32 bit value, using IDATA fails on big endian */
-    /* Pass in IDATA because ioctl() is device dependent, some devices may write 64 bits */
-    if(rc != -1) {
-        return (jlong) *(jint *) & avail;
-    }
-    return (jlong) 0;
-}
-#endif
-// END android-deleted
-
-// BEGIN android-added
-/*
- * Answers the number of remaining bytes in a file descriptor
- * using IOCTL.
- *
- * Class:     org_apache_harmony_io
- * Method:    ioctlAvailable
- * Signature: ()I
- */
-static jint harmony_io_ioctlAvailable(JNIEnv *env, jobject thiz, jint fd) {
-    int avail = 0;
-    int rc = ioctl(fd, FIONREAD, &avail);
-
+static jint harmony_io_ioctlAvailable(JNIEnv*env, jobject, jint fd) {
     /*
      * On underlying platforms Android cares about (read "Linux"),
      * ioctl(fd, FIONREAD, &avail) is supposed to do the following:
-     * 
+     *
      * If the fd refers to a regular file, avail is set to
      * the difference between the file size and the current cursor.
      * This may be negative if the cursor is past the end of the file.
-     * 
+     *
      * If the fd refers to an open socket or the read end of a
      * pipe, then avail will be set to a number of bytes that are
      * available to be read without blocking.
-     * 
+     *
      * If the fd refers to a special file/device that has some concept
      * of buffering, then avail will be set in a corresponding way.
-     * 
+     *
      * If the fd refers to a special device that does not have any
      * concept of buffering, then the ioctl call will return a negative
      * number, and errno will be set to ENOTTY.
-     * 
+     *
      * If the fd refers to a special file masquerading as a regular file,
      * then avail may be returned as negative, in that the special file
      * may appear to have zero size and yet a previous read call may have
      * actually read some amount of data and caused the cursor to be
      * advanced.
      */
-
+    int avail = 0;
+    int rc = ioctl(fd, FIONREAD, &avail);
     if (rc >= 0) {
         /*
          * Success, but make sure not to return a negative number (see
          * above).
-         */ 
+         */
         if (avail < 0) {
             avail = 0;
         }
@@ -714,94 +478,37 @@
         avail = 0;
     } else {
         /* Something strange is happening. */
-        jniThrowException(env, "java/io/IOException", strerror(errno));
-        avail = 0;
-    }  
+        jniThrowIOException(env, errno);
+    }
 
     return (jint) avail;
 }
-// END android-added
-
-/*
- * Reads the number of bytes from stdin.
- *
- * Class:     org_apache_harmony_io
- * Method:    ttyReadImpl
- * Signature: ([BII)J
- */
-static jlong harmony_io_ttyReadImpl(JNIEnv *env, jobject thiz, 
-        jbyteArray byteArray, jint offset, jint nbytes) {
-  
-    jboolean isCopy;
-    jbyte *bytes = env->GetByteArrayElements(byteArray, &isCopy);
-    jlong result;
-
-    for(;;) {
-
-        result = (jlong) read(STDIN_FILENO, (char *)(bytes + offset), (int) nbytes);
-
-        if ((result != -1) || (errno != EINTR)) {
-            break;
-        }
-
-        /*
-         * If we didn't break above, that means that the read() call
-         * returned due to EINTR. We shield Java code from this
-         * possibility by trying again. Note that this is different
-         * from EAGAIN, which should result in this code throwing
-         * an InterruptedIOException.
-         */
-    }
-
-    env->ReleaseByteArrayElements(byteArray, bytes, 0);
-
-    if (result == 0) {
-        return -1;
-    }
-    
-    if (result == -1) {
-        if (errno == EAGAIN) {
-            jniThrowException(env, "java/io/InterruptedIOException",
-                    "Read timed out");
-        } else {
-            jniThrowException(env, "java/io/IOException", strerror(errno));
-        }
-    }
-
-    return result;
-}
 
 /*
  * JNI registration
  */
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
-    { "lockImpl",           "(IJJIZ)I",   (void*) harmony_io_lockImpl },
-    { "getAllocGranularity","()I",     (void*) harmony_io_getAllocGranularity },
-    { "unlockImpl",         "(IJJ)I",     (void*) harmony_io_unlockImpl },
-    { "fflushImpl",         "(IZ)I",      (void*) harmony_io_fflushImpl },
-    { "seekImpl",           "(IJI)J",     (void*) harmony_io_seekImpl },
-    { "readDirectImpl",     "(IIII)J",    (void*) harmony_io_readDirectImpl },
-    { "writeDirectImpl",    "(IIII)J",    (void*) harmony_io_writeDirectImpl },
-    { "readImpl",           "(I[BII)J",   (void*) harmony_io_readImpl },
-    { "writeImpl",          "(I[BII)J",   (void*) harmony_io_writeImpl },
-    { "readvImpl",          "(I[I[I[II)J",(void*) harmony_io_readvImpl },
-    { "writevImpl",         "(I[I[I[II)J",(void*) harmony_io_writevImpl },
-    { "closeImpl",          "(I)I",       (void*) harmony_io_closeImpl },
-    { "truncateImpl",       "(IJ)I",      (void*) harmony_io_truncateImpl },
-    { "openImpl",           "([BI)I",     (void*) harmony_io_openImpl },
-    { "transferImpl",       "(ILjava/io/FileDescriptor;JJ)J", 
-    	    (void*) harmony_io_transferImpl },
-    // BEGIN android-deleted
-    //{ "ttyAvailableImpl",   "()J",        (void*) harmony_io_ttyAvailableImpl },
-    // END android-deleted
-    // BEGIN android-added
+    { "close",              "(I)V",       (void*) harmony_io_close },
+    { "fflush",             "(IZ)V",      (void*) harmony_io_fflush },
+    { "getAllocGranularity","()I",        (void*) harmony_io_getAllocGranularity },
     { "ioctlAvailable",     "(I)I",       (void*) harmony_io_ioctlAvailable },
-    // END android added
-    { "ttyReadImpl",        "([BII)J",    (void*) harmony_io_ttyReadImpl }
+    { "lockImpl",           "(IJJIZ)I",   (void*) harmony_io_lockImpl },
+    { "openImpl",           "([BI)I",     (void*) harmony_io_openImpl },
+    { "readDirect",         "(IIII)J",    (void*) harmony_io_readDirect },
+    { "readImpl",           "(I[BII)J",   (void*) harmony_io_readImpl },
+    { "readv",              "(I[I[I[II)J",(void*) harmony_io_readv },
+    { "seek",               "(IJI)J",     (void*) harmony_io_seek },
+    { "transfer",           "(ILjava/io/FileDescriptor;JJ)J",
+                                          (void*) harmony_io_transfer },
+    { "truncate",           "(IJ)V",      (void*) harmony_io_truncate },
+    { "unlockImpl",         "(IJJ)V",     (void*) harmony_io_unlockImpl },
+    { "writeDirect",        "(IIII)J",    (void*) harmony_io_writeDirect },
+    { "writeImpl",          "(I[BII)J",   (void*) harmony_io_writeImpl },
+    { "writev",             "(I[I[I[II)J",(void*) harmony_io_writev },
 };
-int register_org_apache_harmony_luni_platform_OSFileSystem(JNIEnv *_env) {
-	return jniRegisterNativeMethods(_env, 
-	        "org/apache/harmony/luni/platform/OSFileSystem", gMethods, 
-	        NELEM(gMethods));
+int register_org_apache_harmony_luni_platform_OSFileSystem(JNIEnv* _env) {
+    return jniRegisterNativeMethods(_env,
+            "org/apache/harmony/luni/platform/OSFileSystem", gMethods,
+            NELEM(gMethods));
 }
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
index 2e814cc..b1493f8 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
@@ -144,9 +144,8 @@
  */
 static void harmony_nio_getBytesImpl(JNIEnv *_env, jobject _this, jint pointer, 
         jbyteArray dst, jint offset, jint length) {
-    jbyte *dst_ = (jbyte *)_env->GetPrimitiveArrayCritical(dst, (jboolean *)0);
-    memcpy(dst_ + offset, (jbyte *)pointer, length);
-    _env->ReleasePrimitiveArrayCritical(dst, dst_, 0);
+    jbyte* src = reinterpret_cast<jbyte*>(static_cast<uintptr_t>(pointer));
+    _env->SetByteArrayRegion(dst, offset, length, src);
 }
 
 /*
@@ -166,9 +165,8 @@
  */
 static void harmony_nio_putBytesImpl(JNIEnv *_env, jobject _this,
         jint pointer, jbyteArray src, jint offset, jint length) {
-    jbyte *src_ = (jbyte *)_env->GetPrimitiveArrayCritical(src, (jboolean *)0);
-    memcpy((jbyte *)pointer, src_ + offset, length);
-    _env->ReleasePrimitiveArrayCritical(src, src_, JNI_ABORT);
+    jbyte* dst = reinterpret_cast<jbyte*>(static_cast<uintptr_t>(pointer));
+    _env->GetByteArrayRegion(src, offset, length, dst);
 }
 
 static void
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index 635e1af..3dc4e21 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -39,8 +39,6 @@
 #include <sys/ioctl.h>
 #include <sys/un.h>
 
-#include <cutils/properties.h>
-#include <cutils/adb_networking.h>
 #include "AndroidSystemNatives.h"
 
 // Temporary hack to build on systems that don't have up-to-date libc headers.
@@ -178,8 +176,6 @@
     jclass byte_class;
     jmethodID byte_class_init;
     jfieldID byte_class_value;
-    jclass string_class;
-    jmethodID string_class_init;
     jclass socketimpl_class;
     jfieldID socketimpl_address;
     jfieldID socketimpl_port;
@@ -189,16 +185,14 @@
     jfieldID dpack_length;
 } gCachedFields;
 
-static int useAdbNetworking = 0;
-
 /* needed for connecting with timeout */
-typedef struct selectFDSet {
+struct selectFDSet {
   int nfds;
   int sock;
   fd_set writeSet;
   fd_set readSet;
   fd_set exceptionSet;
-} selectFDSet;
+};
 
 static const char * netLookupErrorString(int anErrorNum);
 
@@ -211,13 +205,6 @@
 }
 
 /**
- * Throws an IOException with the given message.
- */
-static void throwIOExceptionStr(JNIEnv *env, const char *message) {
-    jniThrowException(env, "java/io/IOException", message);
-}
-
-/**
  * Throws a NullPointerException.
  */
 static void throwNullPointerException(JNIEnv *env) {
@@ -297,34 +284,19 @@
 }
 
 /**
- * Checks whether a 16-byte array represents an IPv4-mapped IPv6 address.
- *
- * @param addressBytes the address to check. Must be 16 bytes long.
- * @return true if address contains an IPv4-mapped address, false otherwise.
- */
-static bool isJavaMappedAddress(jbyte *addressBytes) {
-    static const unsigned char mappedBytes[] = {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff};
-    return !memcmp(mappedBytes, addressBytes, sizeof(mappedBytes));
-}
-
-/**
  * Converts a native address structure to an InetAddress object.
  * Throws a NullPointerException or an IOException in case of
- * error. This is signaled by a return value of -1. The normal
- * return value is 0.
+ * error.
  *
  * @param sockaddress the sockaddr_storage structure to convert
  *
  * @return a jobject representing an InetAddress
  */
-static jobject socketAddressToInetAddress(JNIEnv *env,
-        struct sockaddr_storage *sockaddress) {
-
-    jbyteArray byteArray = socketAddressToByteArray(env, sockaddress);
-    if (byteArray == NULL)  // Exception has already been thrown.
+jobject socketAddressToInetAddress(JNIEnv* env, sockaddr_storage* sockAddress) {
+    jbyteArray byteArray = socketAddressToByteArray(env, sockAddress);
+    if (byteArray == NULL) {
         return NULL;
-
+    }
     return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
             gCachedFields.iaddr_getbyaddress, byteArray);
 }
@@ -377,30 +349,30 @@
  * @exception SocketError if the address family is unknown
  */
 static int byteArrayToSocketAddress(JNIEnv *env,
-        jbyteArray addressByteArray, int port, sockaddr_storage *sockaddress) {
-    if (addressByteArray == NULL) {
-      throwNullPointerException(env);
-      return EFAULT;
+        jbyteArray addressBytes, int port, sockaddr_storage *sockaddress) {
+    if (addressBytes == NULL) {
+        throwNullPointerException(env);
+        return EFAULT;
     }
-    size_t addressLength = env->GetArrayLength(addressByteArray);
+    size_t addressLength = env->GetArrayLength(addressBytes);
 
     // Convert the IP address bytes to the proper IP address type.
     if (addressLength == 4) {
         // IPv4 address.
-        sockaddr_in *sin = (sockaddr_in *) sockaddress;
+        sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(sockaddress);
         memset(sin, 0, sizeof(sockaddr_in));
         sin->sin_family = AF_INET;
         sin->sin_port = htons(port);
-        jbyte *rawBytes = (jbyte *) &sin->sin_addr.s_addr;
-        env->GetByteArrayRegion(addressByteArray, 0, 4, rawBytes);
+        jbyte* dst = reinterpret_cast<jbyte*>(&sin->sin_addr.s_addr);
+        env->GetByteArrayRegion(addressBytes, 0, 4, dst);
     } else if (addressLength == 16) {
         // IPv6 address.
-        sockaddr_in6 *sin6 = (sockaddr_in6 *) sockaddress;
+        sockaddr_in6 *sin6 = reinterpret_cast<sockaddr_in6*>(sockaddress);
         memset(sin6, 0, sizeof(sockaddr_in6));
         sin6->sin6_family = AF_INET6;
         sin6->sin6_port = htons(port);
-        jbyte *rawBytes = (jbyte *) &sin6->sin6_addr.s6_addr;
-        env->GetByteArrayRegion(addressByteArray, 0, 16, rawBytes);
+        jbyte* dst = reinterpret_cast<jbyte*>(&sin6->sin6_addr.s6_addr);
+        env->GetByteArrayRegion(addressBytes, 0, 16, dst);
     } else {
         // Unknown address family.
         throwSocketException(env, SOCKERR_BADAF);
@@ -419,20 +391,23 @@
  * @param port the port number
  * @param sockaddress the sockaddr_storage structure to write to
  *
- * @return 0 on success, -1 on failure
+ * @return 0 on success, a system error code on failure
  * @throw UnknownHostException if any error occurs
  *
  * @exception SocketError if the address family is unknown
  */
-static int inetAddressToSocketAddress(JNIEnv *env,
-        jobject inetaddress, int port, sockaddr_storage *sockaddress) {
-
+static int inetAddressToSocketAddress(JNIEnv *env, jobject inetaddress,
+        int port, sockaddr_storage *sockaddress) {
     // Get the byte array that stores the IP address bytes in the InetAddress.
-    jbyteArray addressByteArray;
-    addressByteArray = (jbyteArray)env->GetObjectField(inetaddress,
-            gCachedFields.iaddr_ipaddress);
+    if (inetaddress == NULL) {
+        throwNullPointerException(env);
+        return EFAULT;
+    }
+    jbyteArray addressBytes =
+        reinterpret_cast<jbyteArray>(env->GetObjectField(inetaddress,
+            gCachedFields.iaddr_ipaddress));
 
-    return byteArrayToSocketAddress(env, addressByteArray, port, sockaddress);
+    return byteArrayToSocketAddress(env, addressBytes, port, sockaddress);
 }
 
 /**
@@ -609,8 +584,7 @@
  *
  * @return  the new Boolean
  */
-
-jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
+static jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
     jclass tempClass;
     jmethodID tempMethod;
 
@@ -627,8 +601,7 @@
  *
  * @return  the new Byte
  */
-
-jobject newJavaLangByte(JNIEnv * env, jbyte val) {
+static jobject newJavaLangByte(JNIEnv * env, jbyte val) {
     jclass tempClass;
     jmethodID tempMethod;
 
@@ -645,8 +618,7 @@
  *
  * @return  the new Integer
  */
-
-jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
+static jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
     jclass tempClass;
     jmethodID tempMethod;
 
@@ -655,22 +627,17 @@
     return env->NewObject(tempClass, tempMethod, anInt);
 }
 
-/**
- * Answer a new java.lang.String object.
- *
- * @param env   pointer to the JNI library
- * @param anInt the byte[] constructor argument
- *
- * @return  the new String
- */
+// Converts a number of milliseconds to a timeval.
+static timeval toTimeval(long ms) {
+    timeval tv;
+    tv.tv_sec = ms / 1000;
+    tv.tv_usec = (ms - tv.tv_sec*1000) * 1000;
+    return tv;
+}
 
-jobject newJavaLangString(JNIEnv * env, jbyteArray bytes) {
-    jclass tempClass;
-    jmethodID tempMethod;
-
-    tempClass = gCachedFields.string_class;
-    tempMethod = gCachedFields.string_class_init;
-    return env->NewObject(tempClass, tempMethod, (jbyteArray) bytes);
+// Converts a timeval to a number of milliseconds.
+static long toMs(const timeval& tv) {
+    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
 }
 
 /**
@@ -687,42 +654,10 @@
  */
 
 static int time_msec_clock() {
-    struct timeval tp;
+    timeval tp;
     struct timezone tzp;
-
     gettimeofday(&tp, &tzp);
-    return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
-}
-
-/**
- * Check if the passed sockaddr_storage struct contains a localhost address
- *
- * @param address address pointer to the address to check
- *
- * @return 0 if the passed address isn't a localhost address
- */
-static int isLocalHost(struct sockaddr_storage *address) {
-    if (address->ss_family == AF_INET) {
-        struct sockaddr_in *sin = (struct sockaddr_in *) address;
-        return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK));
-    } else if (address->ss_family == AF_INET6) {
-        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
-        return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr);
-    } else {
-        return 0;
-    }
-}
-
-/**
- * Decide whether to use ADB networking for the given socket address.
- *
- * @param address pointer to sockaddr_storage structure to check
- *
- * @return true if ADB networking should be used, false otherwise.
- */
-static bool useAdbNetworkingForAddress(struct sockaddr_storage *address) {
-    return useAdbNetworking && !isLocalHost(address) &&
-           address->ss_family == AF_INET;
+    return toMs(tp);
 }
 
 /**
@@ -1059,54 +994,6 @@
 }
 
 /**
- * A helper method, to set the connect context to a Long object.
- *
- * @param env  pointer to the JNI library
- * @param longclass Java Long Object
- */
-void setConnectContext(JNIEnv *env,jobject longclass,jbyte * context) {
-    jclass descriptorCLS;
-    jfieldID descriptorFID;
-    descriptorCLS = env->FindClass("java/lang/Long");
-    descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
-    env->SetLongField(longclass, descriptorFID, (jlong)((jint)context));
-};
-
-/**
- * A helper method, to get the connect context.
- *
- * @param env  pointer to the JNI library
- * @param longclass Java Long Object
- */
-jbyte *getConnectContext(JNIEnv *env, jobject longclass) {
-    jclass descriptorCLS;
-    jfieldID descriptorFID;
-    descriptorCLS = env->FindClass("java/lang/Long");
-    descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
-    return (jbyte*) ((jint)env->GetLongField(longclass, descriptorFID));
-};
-
-// typical ip checksum
-unsigned short ip_checksum(unsigned short* buffer, int size) {
-    register unsigned short * buf = buffer;
-    register int bufleft = size;
-    register unsigned long sum = 0;
-
-    while (bufleft > 1) {
-        sum = sum + (*buf++);
-        bufleft = bufleft - sizeof(unsigned short );
-    }
-    if (bufleft) {
-        sum = sum + (*(unsigned char*)buf);
-    }
-    sum = (sum >> 16) + (sum & 0xffff);
-    sum += (sum >> 16);
-
-    return (unsigned short )(~sum);
-}
-
-
-/**
  * Wrapper for connect() that converts IPv4 addresses to IPv4-mapped IPv6
  * addresses if necessary.
  *
@@ -1180,42 +1067,28 @@
  * @return 0, if no errors occurred, otherwise the (negative) error code.
  */
 static int sockConnectWithTimeout(int handle, struct sockaddr_storage addr,
-        unsigned int timeout, unsigned int step, jbyte *ctxt) {
+                                  int timeout, unsigned int step, jbyte *ctxt) {
     int rc = 0;
-    struct timeval passedTimeout;
     int errorVal;
     socklen_t errorValLen = sizeof(int);
-    struct selectFDSet *context = NULL;
+    selectFDSet* context = reinterpret_cast<selectFDSet*>(ctxt);
 
     if (SOCKET_STEP_START == step) {
-
-        context = (struct selectFDSet *) ctxt;
-
         context->sock = handle;
         context->nfds = handle + 1;
 
-        if (useAdbNetworkingForAddress(&addr)) {
-
-            // LOGD("+connect to address 0x%08x (via adb)",
-            //         addr.sin_addr.s_addr);
-            rc = adb_networking_connect_fd(handle, (struct sockaddr_in *) &addr);
-            // LOGD("-connect ret %d errno %d (via adb)", rc, errno);
-
-        } else {
-            /* set the socket to non-blocking */
-            int block = JNI_TRUE;
-            rc = ioctl(handle, FIONBIO, &block);
-            if (0 != rc) {
-                return convertError(rc);
-            }
-
-            // LOGD("+connect to address 0x%08x (via normal) on handle %d",
-            //         addr.sin_addr.s_addr, handle);
-            rc = doConnect(handle, &addr);
-            // LOGD("-connect to address 0x%08x (via normal) returned %d",
-            //         addr.sin_addr.s_addr, (int) rc);
-
+        /* set the socket to non-blocking */
+        int block = JNI_TRUE;
+        rc = ioctl(handle, FIONBIO, &block);
+        if (rc != 0) {
+            return convertError(rc);
         }
+        
+        // LOGD("+connect to address 0x%08x (via normal) on handle %d",
+        //         addr.sin_addr.s_addr, handle);
+        rc = doConnect(handle, &addr);
+        // LOGD("-connect to address 0x%08x (via normal) returned %d",
+        //         addr.sin_addr.s_addr, (int) rc);
 
         if (rc == -1) {
             rc = errno;
@@ -1236,19 +1109,17 @@
     } else if (SOCKET_STEP_CHECK == step) {
         /* now check if we have connected yet */
 
-        context = (struct selectFDSet *) ctxt;
-
         /*
          * set the timeout value to be used. Because on some unix platforms we
          * don't get notified when a socket is closed we only sleep for 100ms
          * at a time
+         * 
+         * TODO: is this relevant for Android?
          */
-        passedTimeout.tv_sec = 0;
         if (timeout > 100) {
-            passedTimeout.tv_usec = 100 * 1000;
-        } else if ((int)timeout >= 0) {
-          passedTimeout.tv_usec = timeout * 1000;
+            timeout = 100;
         }
+        timeval passedTimeout(toTimeval(timeout));
 
         /* initialize the FD sets for the select */
         FD_ZERO(&(context->exceptionSet));
@@ -1262,7 +1133,7 @@
                    &(context->readSet),
                    &(context->writeSet),
                    &(context->exceptionSet),
-                   (int)timeout >= 0 ? &passedTimeout : NULL);
+                   timeout >= 0 ? &passedTimeout : NULL);
 
         /* if there is at least one descriptor ready to be checked */
         if (0 < rc) {
@@ -1592,17 +1463,6 @@
         jboolean jcl_supports_ipv6) {
     // LOGD("ENTER oneTimeInitializationImpl of OSNetworkSystem");
 
-    char useAdbNetworkingProperty[PROPERTY_VALUE_MAX];
-    char adbConnectedProperty[PROPERTY_VALUE_MAX];
-
-    property_get("android.net.use-adb-networking", useAdbNetworkingProperty, "");
-    property_get("adb.connected", adbConnectedProperty, "");
-
-    if (strlen((char *)useAdbNetworkingProperty) > 0
-            && strlen((char *)adbConnectedProperty) > 0) {
-        useAdbNetworking = 1;
-    }
-
     memset(&gCachedFields, 0, sizeof(gCachedFields));
     struct CachedFields *c = &gCachedFields;
 
@@ -1616,7 +1476,6 @@
         {&c->integer_class, "java/lang/Integer"},
         {&c->boolean_class, "java/lang/Boolean"},
         {&c->byte_class, "java/lang/Byte"},
-        {&c->string_class, "java/lang/String"},
         {&c->socketimpl_class, "java/net/SocketImpl"},
         {&c->dpack_class, "java/net/DatagramPacket"}
     };
@@ -1638,7 +1497,6 @@
         {&c->integer_class_init, c->integer_class, "<init>", "(I)V", false},
         {&c->boolean_class_init, c->boolean_class, "<init>", "(Z)V", false},
         {&c->byte_class_init, c->byte_class, "<init>", "(B)V", false},
-        {&c->string_class_init, c->string_class, "<init>", "([B)V", false},
         {&c->iaddr_getbyaddress, c->iaddr_class, "getByAddress",
                     "([B)Ljava/net/InetAddress;", true}
     };
@@ -1925,29 +1783,19 @@
         jobject inetAddr, jint port, jint step, jbyteArray passContext) {
     // LOGD("ENTER connectWithTimeoutSocketImpl");
 
-    int handle;
-    int result = 0;
-    struct sockaddr_storage address;
-    jbyte *context = NULL;
-
-    result = inetAddressToSocketAddress(env, inetAddr, port, &address);
-    if (result < 0)
+    sockaddr_storage address;
+    int result = inetAddressToSocketAddress(env, inetAddr, port, &address);
+    if (result < 0) {
         return result;
-
-    // Check if we're using adb networking and redirect in case it is used.
-    if (useAdbNetworkingForAddress(&address)) {
-        return osNetworkSystem_connectSocketImpl(env, clazz, fileDescriptor,
-                trafficClass, inetAddr, port);
     }
 
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
+    int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
+    if (handle == -1) {
         throwSocketException(env, SOCKERR_BADDESC);
         return -1;
     }
 
-    context = (jbyte *)env->GetPrimitiveArrayCritical(passContext, NULL);
-
+    jbyte* context = env->GetByteArrayElements(passContext, NULL);
     switch (step) {
         case SOCKET_CONNECT_STEP_START:
             result = sockConnectWithTimeout(handle, address, 0,
@@ -1958,10 +1806,9 @@
                     SOCKET_STEP_CHECK, context);
             break;
     }
+    env->ReleaseByteArrayElements(passContext, context, 0);
 
-    env->ReleasePrimitiveArrayCritical(passContext, context, JNI_ABORT);
-
-    if (0 == result) {
+    if (result == 0) {
         /* connected , so stop here */
         sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
     } else if (result != SOCKERR_NOTCONNECTED) {
@@ -2009,16 +1856,6 @@
     if (result < 0)  // Exception has already been thrown.
         return;
 
-    // Check if we're using adb networking and redirect in case it is used.
-    if (useAdbNetworkingForAddress(&address)) {
-        int retVal = osNetworkSystem_connectSocketImpl(env, clazz,
-                fileDescriptor, trafficClass, inetAddr, remotePort);
-        if (retVal != 0) {
-            throwSocketException(env, SOCKERR_BADSOCKET);
-        }
-        return;
-    }
-
     /*
      * we will be looping checking for when we are connected so allocate
      * the descriptor sets that we will use
@@ -2145,26 +1982,17 @@
         return -1;
     }
 
-    if (useAdbNetworkingForAddress(&address)) {
-
-        // LOGD("+connect to address 0x%08x port %d (via adb)",
-        //         address.sin_addr.s_addr, (int) port);
-        ret = adb_networking_connect_fd(handle, (struct sockaddr_in *) &address);
-        // LOGD("-connect ret %d errno %d (via adb)", ret, errno);
-
+    // call this method with a timeout of zero
+    osNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz,
+            fileDescriptor, port, 0, trafficClass, inetAddr);
+    if (env->ExceptionOccurred() != 0) {
+        return -1;
     } else {
-
-        // call this method with a timeout of zero
-        osNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz,
-                fileDescriptor, port, 0, trafficClass, inetAddr);
-        if (env->ExceptionOccurred() != 0) {
-            return -1;
-        } else {
-            return 0;
-        }
-
+        return 0;
     }
-
+    
+    // TODO: unreachable code!
+    
     if (ret < 0) {
         jniThrowException(env, "java/net/ConnectException",
                 netLookupErrorString(convertError(errno)));
@@ -2687,13 +2515,10 @@
     int spaceAvailable = env->GetArrayLength(data) - offset;
     int localCount = count < spaceAvailable? count : spaceAvailable;
 
-    jboolean isCopy;
-    jbyte *body = env->GetByteArrayElements(data, &isCopy);
+    jbyte* body = env->GetByteArrayElements(data, NULL);
 
     // set timeout
-    struct timeval tv;
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
+    timeval tv(toTimeval(timeout));
     setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
                sizeof(struct timeval));
 
@@ -2731,8 +2556,7 @@
     int handle = 0;
     int result = 0, sent = 0;
 
-    jboolean isCopy;
-    jbyte *message = env->GetByteArrayElements(data, &isCopy);
+    jbyte *message = env->GetByteArrayElements(data, NULL);
 
     // Cap write length to available buf size
     int spaceAvailable = env->GetArrayLength(data) - offset;
@@ -2878,111 +2702,87 @@
     return sent;
 }
 
+static bool initFdSet(JNIEnv* env, jobjectArray fdArray, jint count, fd_set* fdSet, int* maxFd) {
+    for (int i = 0; i < count; ++i) {
+        jobject fileDescriptor = env->GetObjectArrayElement(fdArray, i);
+        if (fileDescriptor == NULL) {
+            return false;
+        }
+        
+        const int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+        if (fd < 0 || fd > 1024) {
+            LOGE("selectImpl: invalid fd %i", fd);
+            continue;
+        }
+        
+        FD_SET(fd, fdSet);
+        
+        if (fd > *maxFd) {
+            *maxFd = fd;
+        }
+    }
+    return true;
+}
+
+static bool translateFdSet(JNIEnv* env, jobjectArray fdArray, jint count, const fd_set& fdSet, jint* flagArray, size_t offset, jint op) {
+    for (int i = 0; i < count; ++i) {
+        jobject fileDescriptor = env->GetObjectArrayElement(fdArray, i);
+        if (fileDescriptor == NULL) {
+            return false;
+        }
+        
+        const int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+        const bool valid = fd >= 0 && fd < 1024;
+        
+        if (valid && FD_ISSET(fd, &fdSet)) {
+            flagArray[i + offset] = op;
+        } else {
+            flagArray[i + offset] = SOCKET_OP_NONE;
+        }
+    }
+    return true;
+}
+
 static jint osNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
         jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
-        jint countWriteC, jintArray outFlags, jlong timeout) {
+        jint countWriteC, jintArray outFlags, jlong timeoutMs) {
     // LOGD("ENTER selectImpl");
-
-    struct timeval timeP;
-    int result = 0;
-    int size = 0;
-    jobject gotFD;
-    fd_set *fdset_read,*fdset_write;
-    int handle;
-    jboolean isCopy ;
-    jint *flagArray;
-    int val;
-    unsigned int time_sec = (unsigned int)timeout/1000;
-    unsigned int time_msec = (unsigned int)(timeout%1000);
-
-    fdset_read = (fd_set *)malloc(sizeof(fd_set));
-    fdset_write = (fd_set *)malloc(sizeof(fd_set));
-
-    FD_ZERO(fdset_read);
-    FD_ZERO(fdset_write);
-
-    for (val = 0; val<countReadC; val++) {
-
-        gotFD = env->GetObjectArrayElement(readFDArray,val);
-
-        handle = jniGetFDFromFileDescriptor(env, gotFD);
-
-        FD_SET(handle, fdset_read);
-
-        if (0 > (size - handle)) {
-            size = handle;
-        }
+    
+    // Initialize the fd_sets.
+    int maxFd = -1;
+    fd_set readFds;
+    fd_set writeFds;
+    FD_ZERO(&readFds);
+    FD_ZERO(&writeFds);
+    bool initialized = initFdSet(env, readFDArray, countReadC, &readFds, &maxFd) &&
+                       initFdSet(env, writeFDArray, countWriteC, &writeFds, &maxFd);
+    if (!initialized) {
+        return -1;
     }
-
-    for (val = 0; val<countWriteC; val++) {
-
-        gotFD = env->GetObjectArrayElement(writeFDArray,val);
-
-        handle = jniGetFDFromFileDescriptor(env, gotFD);
-
-        FD_SET(handle, fdset_write);
-
-        if (0 > (size - handle)) {
-            size = handle;
-        }
+    
+    // Initialize the timeout, if any.
+    timeval tv;
+    timeval* tvp = NULL;
+    if (timeoutMs >= 0) {
+        tv = toTimeval(timeoutMs);
+        tvp = &tv;
     }
-
-    /* the size is the max_fd + 1 */
-    size =size + 1;
-
-    if (0 > size) {
-        result = SOCKERR_FDSET_SIZEBAD;
-    } else {
-      /* only set when timeout >= 0 (non-block)*/
-        if (0 <= timeout) {
-
-            timeP.tv_sec = time_sec;
-            timeP.tv_usec = time_msec*1000;
-
-            result = sockSelect(size, fdset_read, fdset_write, NULL, &timeP);
-
-        } else {
-            result = sockSelect(size, fdset_read, fdset_write, NULL, NULL);
-        }
+    
+    // Perform the select.
+    int result = sockSelect(maxFd + 1, &readFds, &writeFds, NULL, tvp);
+    if (result < 0) {
+        return result;
     }
-
-    if (0 < result) {
-        /*output the result to a int array*/
-        flagArray = env->GetIntArrayElements(outFlags, &isCopy);
-
-        for (val=0; val<countReadC; val++) {
-            gotFD = env->GetObjectArrayElement(readFDArray,val);
-
-            handle = jniGetFDFromFileDescriptor(env, gotFD);
-
-            if (FD_ISSET(handle,fdset_read)) {
-                flagArray[val] = SOCKET_OP_READ;
-            } else {
-                flagArray[val] = SOCKET_OP_NONE;
-            }
-        }
-
-        for (val=0; val<countWriteC; val++) {
-
-            gotFD = env->GetObjectArrayElement(writeFDArray,val);
-
-            handle = jniGetFDFromFileDescriptor(env, gotFD);
-
-            if (FD_ISSET(handle,fdset_write)) {
-                flagArray[val+countReadC] = SOCKET_OP_WRITE;
-            } else {
-                flagArray[val+countReadC] = SOCKET_OP_NONE;
-            }
-        }
-
-        env->ReleaseIntArrayElements(outFlags, flagArray, 0);
+    
+    // Translate the result into the int[] we're supposed to fill in.
+    jint* flagArray = env->GetIntArrayElements(outFlags, NULL);
+    if (flagArray == NULL) {
+        return -1;
     }
-
-    free(fdset_write);
-    free(fdset_read);
-
-    /* return both correct and error result, let java handle the exception*/
-    return result;
+    bool okay = translateFdSet(env, readFDArray, countReadC, readFds, flagArray, 0, SOCKET_OP_READ) &&
+                translateFdSet(env, writeFDArray, countWriteC, writeFds, flagArray, countReadC, SOCKET_OP_WRITE);
+    env->ReleaseIntArrayElements(outFlags, flagArray, 0);
+    return okay ? 0 : -1;
 }
 
 static jobject osNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env,
@@ -3215,7 +3015,7 @@
                 throwSocketException(env, convertError(errno));
                 return NULL;
             }
-            return newJavaLangInteger(env, timeout.tv_sec * 1000 + timeout.tv_usec/1000);
+            return newJavaLangInteger(env, toMs(timeout));
         }
         default: {
             throwSocketException(env, SOCKERR_OPTUNSUPP);
@@ -3460,9 +3260,7 @@
         }
 
         case JAVASOCKOPT_SO_RCVTIMEOUT: {
-            struct timeval timeout;
-            timeout.tv_sec = intVal / 1000;
-            timeout.tv_usec = (intVal % 1000) * 1000;
+            timeval timeout(toTimeval(intVal));
             result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
                     sizeof(struct timeval));
             if (0 != result) {
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c b/libcore/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
index e92b776..ebbd6de 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
@@ -240,7 +240,7 @@
     }
   else if (e >= 0 && e < 39)
     {
-      result = (jfloat) (toDoubleHighPrecision (f, length) * pow (10.0, e));
+      result = (jfloat) (toDoubleHighPrecision (f, length) * pow (10.0, (double) e));
     }
   else if (e >= 39)
     {
@@ -260,7 +260,7 @@
       int dexp;
       U_32 fmant, fovfl;
       U_64 dmant;
-      dresult = toDoubleHighPrecision (f, length) / pow (10.0, -e);
+      dresult = toDoubleHighPrecision (f, length) / pow (10.0, (double) -e);
       if (IS_DENORMAL_DBL (dresult))
         {
           FLOAT_TO_INTBITS (result) = 0;
diff --git a/libcore/luni/src/main/native/sub.mk b/libcore/luni/src/main/native/sub.mk
index d277f82..184a13d 100644
--- a/libcore/luni/src/main/native/sub.mk
+++ b/libcore/luni/src/main/native/sub.mk
@@ -13,7 +13,7 @@
 	java_lang_Math.c \
 	java_lang_StrictMath.c \
 	java_net_InetAddress.cpp \
-	java_net_NetworkInterface.c \
+	java_net_NetworkInterface.cpp \
 	cbigint.c \
 	commonDblParce.c \
 	org_apache_harmony_luni_util_fltparse.c \
diff --git a/libcore/luni/src/test/java/com/google/coretests/CoreTestRunner.java b/libcore/luni/src/test/java/com/google/coretests/CoreTestRunner.java
index d469c86..ad766aa 100644
--- a/libcore/luni/src/test/java/com/google/coretests/CoreTestRunner.java
+++ b/libcore/luni/src/test/java/com/google/coretests/CoreTestRunner.java
@@ -15,6 +15,8 @@
  */
 package com.google.coretests;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -67,6 +69,11 @@
     private int fTimeout; 
 
     private int fStep = 1;
+
+    /**
+     * The path to write XML reports to, or {@code null} for no reports.
+     */
+    private String xmlReportsDirectory;
     
     /**
      * Creates a new instance of our CoreTestRunner.
@@ -125,19 +132,32 @@
          * Make sure the original suite is unreachable after we have
          * created the new one, so GC can dispose terminated tests.
          */
-        suite = new CoreTestSuite(suite, fFlags, fStep, null);
-        
-        return super.doRun(suite, wait);
+        CoreTestSuite coreTestSuite = new CoreTestSuite(suite, fFlags, fStep, null);
+
+        XmlReportPrinter xmlReportPrinter = xmlReportsDirectory != null
+                ? new XmlReportPrinter(coreTestSuite)
+                : null;
+
+        TestResult result = super.doRun(coreTestSuite, wait);
+
+        if (xmlReportPrinter != null) {
+            System.out.print("Printing XML Reports... ");
+            xmlReportPrinter.setResults(result);
+            int numFiles = xmlReportPrinter.generateReports(xmlReportsDirectory);
+            System.out.println(numFiles + " files written.");
+        }
+
+        return result;
     }
-    
+
     /**
      * Prints a help screen on the console.
      */
     private void showHelp() {
-        System.out.println("Usage: run-core-tests {<param>} <test>");
+        System.out.println("Usage: run-core-tests [OPTION]... [TEST]...");
         System.out.println();
-        System.out.println("Where <test> is a class name, optionally followed");
-        System.out.println("by \"#\" and a method name, and <param> is one of");
+        System.out.println("Where each TEST is a class name, optionally followed");
+        System.out.println("by \"#\" and a method name, and each OPTION is one of");
         System.out.println("the following:");
         System.out.println();
         System.out.println("    --include-all");
@@ -160,6 +180,7 @@
         System.out.println("    --isolate-all");
         System.out.println("    --isolate-none");
         System.out.println("    --verbose");
+        System.out.println("    --xml-reports-directory <path>");
         System.out.println("    --help");
         System.out.println();
         System.out.println("Default parameters are:");
@@ -185,26 +206,29 @@
     }
 
     /**
-     * Tries to create a Test instance from a given string. The string might
+     * Tries to create a Test instance from the given strings. The strings might
      * either specify a class only or a class plus a method name, separated by
      * a "#".
      */
-    private Test createTest(String testCase) throws Exception {
-        int p = testCase.indexOf("#");
-        if (p != -1) {
-            String testName = testCase.substring(p + 1);
-            testCase = testCase.substring(0, p);
-
-            return TestSuite.createTest(Class.forName(testCase), testName);
-        } else {
-            return getTest(testCase);
+    private Test createTest(List<String> testCases) throws Exception {
+        TestSuite result = new TestSuite();
+        for (String testCase : testCases) {
+            int p = testCase.indexOf("#");
+            if (p != -1) {
+                String testName = testCase.substring(p + 1);
+                testCase = testCase.substring(0, p);
+                
+                result.addTest(TestSuite.createTest(Class.forName(testCase), testName));
+            } else {
+                result.addTest(getTest(testCase));
+            }
         }
-        
+        return result;
     }
     
     @Override
     protected TestResult start(String args[]) throws Exception {
-        String testName = null;
+        List<String> testNames = new ArrayList<String>();
         // String victimName = null;
         
         boolean wait = false;
@@ -265,16 +289,18 @@
                 //    victimName = args[++i];
                 } else if (args[i].equals("--dry-run")) {
                     fFlags = fFlags | CoreTestSuite.DRY_RUN;
+                } else if (args[i].equals("--xml-reports-directory")) {
+                    xmlReportsDirectory = args[++i];
                 } else if (args[i].equals("--help")) {
                     showHelp();
                     System.exit(1);
                 } else {
-                    System.err.println("Unknown argument " + args[i] + 
-                            ", try --help");
-                    System.exit(1);
+                    unknownArgument(args[i]);
                 }
+            } else if (args[i].startsWith("-")) {
+                unknownArgument(args[i]);
             } else {
-                testName = args[i];
+                testNames.add(args[i]);
             }
         }
         
@@ -288,7 +314,7 @@
         System.out.println();
 
         try {
-            return doRun(createTest(testName), wait);
+            return doRun(createTest(testNames), wait);
         }
         catch(Exception e) {
             e.printStackTrace();
@@ -296,4 +322,8 @@
         }
     }
     
+    private static void unknownArgument(String arg) {
+        System.err.println("Unknown argument " + arg + ", try --help");
+        System.exit(1);
+    }
 }
diff --git a/libcore/luni/src/test/java/com/google/coretests/CoreTestSuite.java b/libcore/luni/src/test/java/com/google/coretests/CoreTestSuite.java
index 3c9e7fa..fd7531f 100644
--- a/libcore/luni/src/test/java/com/google/coretests/CoreTestSuite.java
+++ b/libcore/luni/src/test/java/com/google/coretests/CoreTestSuite.java
@@ -98,6 +98,8 @@
     public static final int REVERSE = 512;
 
     public static final int DRY_RUN = 1024;
+
+    private final String name;
     
     /**
      * The total number of tests in the original suite.
@@ -154,7 +156,8 @@
      */
     public CoreTestSuite(Test suite, int flags, int step, TestCase victim) {
         super();
-        
+
+        name = suite.toString();
         fStep = step;
         addAndFlatten(suite, flags);
         fVictim = victim;
@@ -180,17 +183,13 @@
                 }
             }
         } else if (test instanceof TestCase) {
-            TestCase caze = (TestCase)test;
+            TestCase testCase = (TestCase)test;
             boolean ignoreMe = false;
 
-            boolean isAndroidOnly = hasAnnotation(caze, 
-                    AndroidOnly.class);
-            boolean isBrokenTest = hasAnnotation(caze, 
-                    BrokenTest.class);
-            boolean isKnownFailure = hasAnnotation(caze, 
-                    KnownFailure.class);
-            boolean isSideEffect = hasAnnotation(caze, 
-                    SideEffect.class);
+            boolean isAndroidOnly = hasAnnotation(testCase, AndroidOnly.class);
+            boolean isBrokenTest = hasAnnotation(testCase, BrokenTest.class);
+            boolean isKnownFailure = hasAnnotation(testCase, KnownFailure.class);
+            boolean isSideEffect = hasAnnotation(testCase, SideEffect.class);
             boolean isNormalTest = 
                     !(isAndroidOnly || isBrokenTest || isKnownFailure ||
                       isSideEffect);
@@ -269,27 +268,27 @@
     public void run(TestResult result) {
         // Run tests
         int i = 0;
-        
+
         while (fTests.size() != 0 && !result.shouldStop()) {
             TestCase test = (TestCase)fTests.elementAt(i);
             
             Thread.currentThread().setContextClassLoader(
                     test.getClass().getClassLoader());
-            
+
             test.run(result);
 
             /*
             if (fVictim != null) {
                 TestResult dummy = fVictim.run();
-                
+
                 if (dummy.failureCount() != 0) {
                     result.addError(fTests.elementAt(i), new RuntimeException(
-                            "Probable side effect",  
+                            "Probable side effect",
                             ((TestFailure)dummy.failures().nextElement()).
                             thrownException()));
                 } else if (dummy.errorCount() != 0) {
                     result.addError(fTests.elementAt(i), new RuntimeException(
-                            "Probable side effect",  
+                            "Probable side effect",
                             ((TestFailure)dummy.errors().nextElement()).
                             thrownException()));
                 }
@@ -352,4 +351,7 @@
         return fTests.size();
     }
 
+    @Override public String toString() {
+        return name;
+    }
 }
diff --git a/libcore/luni/src/test/java/com/google/coretests/XmlReportPrinter.java b/libcore/luni/src/test/java/com/google/coretests/XmlReportPrinter.java
new file mode 100644
index 0000000..315371f
--- /dev/null
+++ b/libcore/luni/src/test/java/com/google/coretests/XmlReportPrinter.java
@@ -0,0 +1,249 @@
+/*
+ *  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 com.google.coretests;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestFailure;
+import junit.framework.TestResult;
+import junit.runner.BaseTestRunner;
+import org.kxml2.io.KXmlSerializer;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+
+/**
+ * Writes JUnit results to a series of XML files in a format consistent with
+ * Ant's XMLJUnitResultFormatter.
+ *
+ * <p>Unlike Ant's formatter, this class does not report the execution time of
+ * tests.
+ */
+public class XmlReportPrinter {
+
+    private static final String TESTSUITE = "testsuite";
+    private static final String TESTCASE = "testcase";
+    private static final String ERROR = "error";
+    private static final String FAILURE = "failure";
+    private static final String ATTR_NAME = "name";
+    private static final String ATTR_TIME = "time";
+    private static final String ATTR_ERRORS = "errors";
+    private static final String ATTR_FAILURES = "failures";
+    private static final String ATTR_TESTS = "tests";
+    private static final String ATTR_TYPE = "type";
+    private static final String ATTR_MESSAGE = "message";
+    private static final String PROPERTIES = "properties";
+    private static final String ATTR_CLASSNAME = "classname";
+    private static final String TIMESTAMP = "timestamp";
+    private static final String HOSTNAME = "hostname";
+
+    /** the XML namespace */
+    private static final String ns = null;
+
+    /** the test suites, which each contain tests */
+    private final Map<String, Suite> suites = new LinkedHashMap<String, Suite>();
+
+    /**
+     * Create a report printer that prints the specified test suite. Since the
+     * CoreTestSuite nulls-out tests after they're run (to limit memory
+     * consumption), it is necessary to create the report printer prior to test
+     * execution.
+     */
+    public XmlReportPrinter(CoreTestSuite allTests) {
+        // partition the tests by suite to be consistent with Ant's printer
+        for (Enumeration<Test> e = allTests.tests(); e.hasMoreElements(); ) {
+            TestId test = new TestId(e.nextElement());
+
+            // create the suite's entry in the map if necessary
+            Suite suite = suites.get(test.className);
+            if (suite == null) {
+                suite = new Suite(test.className);
+                suites.put(test.className, suite);
+            }
+
+            suite.tests.add(test);
+        }
+    }
+
+    public void setResults(TestResult result) {
+        populateFailures(true, result.errors());
+        populateFailures(false, result.failures());
+    }
+
+    /**
+     * Populate the list of failures in each of the suites.
+     */
+    private void populateFailures(boolean errors, Enumeration<TestFailure> failures) {
+        while (failures.hasMoreElements()) {
+            TestFailure failure = failures.nextElement();
+            TestId test = new TestId(failure.failedTest());
+            Suite suite = suites.get(test.className);
+
+            if (suite == null) {
+                throw new IllegalStateException( "received a failure for a "
+                        + "test that wasn't in the original test suite!");
+            }
+
+            if (errors) {
+                suite.errors.put(test, failure);
+            } else {
+                suite.failures.put(test, failure);
+            }
+        }
+    }
+
+    public int generateReports(String directory) {
+        File parent = new File(directory);
+        parent.mkdirs();
+
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+        TimeZone gmt = TimeZone.getTimeZone("GMT");
+        dateFormat.setTimeZone(gmt);
+        dateFormat.setLenient(true);
+        String timestamp = dateFormat.format(new Date());
+
+        for (Suite suite : suites.values()) {
+            FileOutputStream stream = null;
+            try {
+                stream = new FileOutputStream(new File(parent, "TEST-" + suite.name + ".xml"));
+
+                KXmlSerializer serializer = new KXmlSerializer();
+                serializer.setOutput(stream, "UTF-8");
+                serializer.startDocument("UTF-8", null);
+                serializer.setFeature(
+                        "http://xmlpull.org/v1/doc/features.html#indent-output", true);
+                suite.print(serializer, timestamp);
+                serializer.endDocument();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            } finally {
+                if (stream != null) {
+                    try {
+                        stream.close();
+                    } catch (IOException ignored) {
+                    }
+                }
+            }
+        }
+
+        return suites.size();
+    }
+
+    static class Suite {
+        private final String name;
+        private final List<TestId> tests = new ArrayList<TestId>();
+        private final Map<TestId, TestFailure> failures = new HashMap<TestId, TestFailure>();
+        private final Map<TestId, TestFailure> errors = new HashMap<TestId, TestFailure>();
+
+        Suite(String name) {
+            this.name = name;
+        }
+
+        void print(KXmlSerializer serializer, String timestamp) throws IOException {
+            serializer.startTag(ns, TESTSUITE);
+            serializer.attribute(ns, ATTR_NAME, name);
+            serializer.attribute(ns, ATTR_TESTS, Integer.toString(tests.size()));
+            serializer.attribute(ns, ATTR_FAILURES, Integer.toString(failures.size()));
+            serializer.attribute(ns, ATTR_ERRORS, Integer.toString(errors.size()));
+            serializer.attribute(ns, ATTR_TIME, "0");
+
+            serializer.attribute(ns, TIMESTAMP, timestamp);
+            serializer.attribute(ns, HOSTNAME, "localhost");
+            serializer.startTag(ns, PROPERTIES);
+            serializer.endTag(ns, PROPERTIES);
+
+            for (TestId testId : tests) {
+                TestFailure error = errors.get(testId);
+                TestFailure failure = failures.get(testId);
+
+                if (error != null) {
+                    testId.printFailure(serializer, ERROR, error.thrownException());
+                } else if (failure != null) {
+                    testId.printFailure(serializer, FAILURE, failure.thrownException());
+                } else {
+                    testId.printSuccess(serializer);
+                }
+            }
+
+            serializer.endTag(ns, TESTSUITE);
+        }
+    }
+
+    private static class TestId {
+        private final String name;
+        private final String className;
+
+        TestId(Test test) {
+            this.name = test instanceof TestCase
+                    ? ((TestCase) test).getName()
+                    : test.toString();
+            this.className = test.getClass().getName();
+        }
+
+        void printSuccess(KXmlSerializer serializer) throws IOException {
+            serializer.startTag(ns, TESTCASE);
+            printAttributes(serializer);
+            serializer.endTag(ns, TESTCASE);
+        }
+
+        void printFailure(KXmlSerializer serializer, String type, Throwable t)
+                throws IOException {
+            serializer.startTag(ns, TESTCASE);
+            printAttributes(serializer);
+
+            serializer.startTag(ns, type);
+            String message = t.getMessage();
+            if (message != null && message.length() > 0) {
+                serializer.attribute(ns, ATTR_MESSAGE, t.getMessage());
+            }
+            serializer.attribute(ns, ATTR_TYPE, t.getClass().getName());
+            serializer.text(BaseTestRunner.getFilteredTrace(t));
+            serializer.endTag(ns, type);
+
+            serializer.endTag(ns, TESTCASE);
+        }
+
+        void printAttributes(KXmlSerializer serializer) throws IOException {
+            serializer.attribute(ns, ATTR_NAME, name);
+            serializer.attribute(ns, ATTR_CLASSNAME, className);
+            serializer.attribute(ns, ATTR_TIME, "0");
+        }
+
+        @Override public boolean equals(Object o) {
+            return o instanceof TestId
+                    && ((TestId) o).name.equals(name)
+                    && ((TestId) o).className.equals(className);
+        }
+
+        @Override public int hashCode() {
+            return name.hashCode() ^ className.hashCode();
+        }
+    }
+}
\ No newline at end of file
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
index c99a0c1..275ea9d 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
@@ -20,11 +20,21 @@
 import dalvik.annotation.AndroidOnly;
 import dalvik.annotation.BrokenTest;
 import dalvik.annotation.KnownFailure;
-import dalvik.annotation.TestTargetClass; 
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import junit.framework.TestCase;
 
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
 import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -41,22 +51,16 @@
 import java.net.Proxy;
 import java.net.ServerSocket;
 import java.net.Socket;
-import java.net.SocketTimeoutException;
 import java.net.URL;
 import java.security.KeyStore;
 import java.security.cert.Certificate;
 import java.util.Arrays;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManagerFactory;
-
-import junit.framework.TestCase;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Implementation independent test for HttpsURLConnection.
@@ -994,7 +998,7 @@
      * Returns the file name of the key/trust store. The key store file 
      * (named as "key_store." + extension equals to the default KeyStore
      * type installed in the system in lower case) is searched in classpath.
-     * @throws AssertionFailedError if property was not set 
+     * @throws junit.framework.AssertionFailedError if property was not set
      * or file does not exist.
      */
     private static String getKeyStoreFileName() {
@@ -1145,28 +1149,19 @@
 
         ClientConnectionWork client = new ClientConnectionWork(clientConnection);
 
-        server.start();
-        client.start();
+        ExecutorService executorService = Executors.newFixedThreadPool(2);
+        try {
+            Future<Void> serverFuture = executorService.submit(server);
+            Future<Void> clientFuture = executorService.submit(client);
 
-        client.join();
-        server.join();
+            serverFuture.get(30, TimeUnit.SECONDS);
+            clientFuture.get(30, TimeUnit.SECONDS);
+        } catch (ExecutionException e) {
+            throw e.getCause();
+        } finally {
+            executorService.shutdown();
+        }
 
-        if (client.thrown != null) {
-            if (responseCode != OK_CODE) { // not OK response expected
-                // it is probably expected exception, keep it as is
-                throw client.thrown;
-            }
-            if ((client.thrown instanceof SocketTimeoutException)
-                    && (server.thrown != null)) {
-                // server's exception is more informative in this case
-                throw new Exception(server.thrown);
-            } else {
-                throw new Exception(client.thrown);
-            }
-        }
-        if (server.thrown != null) {
-            throw server.thrown;
-        }
         return server.peerSocket;
     }
 
@@ -1190,7 +1185,7 @@
     /**
      * The base class for mock Client and Server.
      */
-    static class Work extends Thread {
+    static class Work {
 
         /**
          * The header of OK HTTP response.
@@ -1242,11 +1237,6 @@
         static final String clientsData = "_.-^ Client's Data ^-._";
 
         /**
-         * The exception thrown during peers interaction.
-         */
-        protected Throwable thrown;
-
-        /**
          * The print stream used for debug log.
          * If it is null debug info will not be printed.
          */
@@ -1257,7 +1247,7 @@
          */
         public synchronized void log(String message) {
             if (DO_LOG && (out != null)) {
-                System.out.println("[" + getName() + "]: " + message);
+                out.println("[" + this + "]: " + message);
             }
         }
     }
@@ -1265,7 +1255,7 @@
     /**
      * The class used for server side works.
      */
-    static class ServerWork extends Work {
+    static class ServerWork extends Work implements Callable<Void> {
 
         // the server socket used for connection
         private ServerSocket serverSocket;
@@ -1314,7 +1304,6 @@
                 this.actAsProxy = true;
             }
             this.actAsProxy = !(serverSocket instanceof SSLServerSocket);
-            setName(this.actAsProxy ? "Proxy Server" : "Server");
         }
 
         /**
@@ -1337,7 +1326,7 @@
          * If some exception occurs during the work it will be
          * stored in the <code>thrown</code> field.
          */
-        public void run() {
+        public Void call() throws Exception {
             // the buffer used for reading the messages
             byte[] buff = new byte[2048];
             // the number of bytes read into the buffer
@@ -1371,14 +1360,13 @@
                         assertEquals(clientsData, message);
                     }
                     // just send the response
-                    os
-                            .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail)
-                                    .getBytes());
+                    os.write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail)
+                            .getBytes());
                     os.flush();
                     os.close();
                     // and return
                     log("Work is DONE !actAsProxy");
-                    return;
+                    return null;
                 }
 
                 // Do proxy work
@@ -1389,7 +1377,7 @@
                     // read response
                     num = is.read(buff);
                     if (num == -1) {
-                        // this connection was closed, 
+                        // this connection was closed,
                         // do clean up and create new one:
                         closeSocket(peerSocket);
                         peerSocket = serverSocket.accept();
@@ -1455,11 +1443,7 @@
                                     .getBytes());
                 }
                 log("Work is DONE actAsProxy");
-            } catch (Throwable e) {
-                if (DO_LOG) {
-                    e.printStackTrace();
-                }
-                thrown = e;
+                return null;
             } finally {
                 closeSocket(peerSocket);
                 try {
@@ -1467,13 +1451,17 @@
                 } catch (IOException e) {}
             }
         }
+
+        @Override public String toString() {
+            return actAsProxy ? "Proxy Server" : "Server";
+        }
     }
 
     /**
      * The class used for client side works. It could be used to test
      * both HttpURLConnection and HttpsURLConnection.
      */
-    static class ClientConnectionWork extends Work {
+    static class ClientConnectionWork extends Work implements Callable<Void> {
 
         // connection to be used to contact the server side
         private HttpURLConnection connection;
@@ -1484,7 +1472,6 @@
          */
         public ClientConnectionWork(HttpURLConnection connection) {
             this.connection = connection;
-            setName("Client Connection");
             log("Created over connection: " + connection.getClass());
         }
 
@@ -1493,42 +1480,41 @@
          * If some exception occurs during the work it will be
          * stored in the <code>thrown<code> field.
          */
-        public void run() {
-            try {
-                log("Opening the connection..");
-                connection.connect();
-                log("Connection has been ESTABLISHED, using proxy: "
-                        + connection.usingProxy());
-                if (connection.getDoOutput()) {
-                    // connection configured to post data, do so
-                    connection.getOutputStream().write(clientsData.getBytes());
-                }
-                // read the content of HTTP(s) response
-                InputStream is = connection.getInputStream();
-                log("Input Stream obtained");
-                byte[] buff = new byte[2048];
-                int num = 0;
-                int byt = 0;
-                while ((num < buff.length) && (is.available() > 0)
-                        && ((byt = is.read()) != -1)) {
-                    buff[num++] = (byte) byt;
-                }
-                String message = new String(buff, 0, num);
-                log("Got content:\n" + message);
-                log("------------------");
-                log("Response code: " + connection.getResponseCode());
-
-                if (connection instanceof HttpsURLConnection) {
-                    assertEquals(httpsResponseContent, message);
-                } else {
-                    assertEquals(plainResponseContent, message);
-                }
-            } catch (Throwable e) {
-                if (DO_LOG) {
-                    e.printStackTrace();
-                }
-                thrown = e;
+        public Void call() throws Exception {
+            log("Opening the connection..");
+            connection.connect();
+            log("Connection has been ESTABLISHED, using proxy: "
+                    + connection.usingProxy());
+            if (connection.getDoOutput()) {
+                // connection configured to post data, do so
+                connection.getOutputStream().write(clientsData.getBytes());
             }
+            // read the content of HTTP(s) response
+            InputStream is = connection.getInputStream();
+            log("Input Stream obtained");
+            byte[] buff = new byte[2048];
+            int num = 0;
+            int byt = 0;
+            while ((num < buff.length) && (is.available() > 0)
+                    && ((byt = is.read()) != -1)) {
+                buff[num++] = (byte) byt;
+            }
+            String message = new String(buff, 0, num);
+            log("Got content:\n" + message);
+            log("------------------");
+            log("Response code: " + connection.getResponseCode());
+
+            if (connection instanceof HttpsURLConnection) {
+                assertEquals(httpsResponseContent, message);
+            } else {
+                assertEquals(plainResponseContent, message);
+            }
+
+            return null;
+        }
+
+        @Override public String toString() {
+            return "Client Connection";
         }
     }
 }
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java
index cb35324..283c1db 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java
@@ -312,7 +312,7 @@
         method = "isCompatibleWith",
         args = {java.lang.String.class}
     )
-    @KnownFailure("isCompatibleWith returns incorrect value.")
+    @KnownFailure("Dalvik packages are always version '0.0'.")
     public void test_isCompatibleWithLjava_lang_String() throws Exception {
         Package p = getTestPackage("hyts_c.jar", "p.C");
 
diff --git a/libcore/luni/src/test/java/tests/AllTests.java b/libcore/luni/src/test/java/tests/AllTests.java
index 893cdf0..7533eea 100644
--- a/libcore/luni/src/test/java/tests/AllTests.java
+++ b/libcore/luni/src/test/java/tests/AllTests.java
@@ -32,6 +32,7 @@
     public static final Test suite() {
         TestSuite suite = tests.TestSuiteFactory.createTestSuite();
         
+        // Harmony-written test suites (often with Android tests added in).
         suite.addTest(tests.annotation.AllTests.suite());
         suite.addTest(tests.archive.AllTests.suite());
         suite.addTest(tests.concurrent.AllTests.suite());
@@ -53,8 +54,12 @@
         suite.addTest(tests.text.AllTests.suite());
         suite.addTest(tests.xml.AllTests.suite());
         suite.addTest(tests.xnet.AllTests.suite());
-
+        
+        // Android-written test suites.
+        suite.addTest(com.ibm.icu4jni.util.AllTests.suite());
+        suite.addTest(java.lang.reflect.AllTests.suite());
         suite.addTest(org.apache.harmony.luni.platform.AllTests.suite());
+        suite.addTest(tests.api.org.apache.harmony.kernel.dalvik.AllTests.suite());
         
         return suite;
     }
diff --git a/libcore/luni/src/test/java/tests/api/java/io/FileTest.java b/libcore/luni/src/test/java/tests/api/java/io/FileTest.java
index 81f14e0..3063b89 100644
--- a/libcore/luni/src/test/java/tests/api/java/io/FileTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/io/FileTest.java
@@ -31,13 +31,14 @@
 import java.net.URISyntaxException;
 import java.net.URL;
 
-import tests.support.Support_Exec;
 import dalvik.annotation.AndroidOnly;
 import dalvik.annotation.KnownFailure;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
+import static tests.support.Support_Exec.javaProcessBuilder;
+import static tests.support.Support_Exec.execAndGetOutput;
 
 @TestTargetClass(File.class) 
 public class FileTest extends junit.framework.TestCase {
@@ -689,8 +690,6 @@
         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
@@ -2467,12 +2466,14 @@
         assertTrue("could not find the path of the test jar/apk", idx > 0);
         classPath = classPath.substring(9, idx); // cutting off jar:file:
 
-        Support_Exec.execJava(new String[] {
-                "tests.support.Support_DeleteOnExitTest",
-                dir.getAbsolutePath(), subDir.getAbsolutePath() },
-                new String[] { System.getProperty("java.class.path"),
-                classPath }, false);
-        Thread.sleep(2000);
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("-cp");
+        builder.command().add(System.getProperty("java.class.path"));
+        builder.command().add("tests.support.Support_DeleteOnExitTest");
+        builder.command().add(dir.getAbsolutePath());
+        builder.command().add(subDir.getAbsolutePath());
+        execAndGetOutput(builder);
+
         assertFalse(dir.exists());
         assertFalse(subDir.exists());
     }
diff --git a/libcore/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java b/libcore/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java
index 3b545e3..dc35610 100644
--- a/libcore/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java
@@ -1200,16 +1200,25 @@
         } catch (IOException e) {
             // Expected.
         }
+        // BEGIN android-added
+        try {
+            // Android uses 32-bit off_t, so anything larger than a signed 32-bit int won't work.
+            raf.seek(((long) Integer.MAX_VALUE) + 1);
+            fail("Test 2: IOException expected.");
+        } catch (IOException e) {
+            // Expected.
+        }
+        // END android-added
 
         raf.write(testString.getBytes(), 0, testLength);
         raf.seek(12);
-        assertEquals("Test 2: Seek failed to set file pointer.", 12, 
+        assertEquals("Test 3: Seek failed to set file pointer.", 12,
                 raf.getFilePointer());
         
         raf.close();
         try {
             raf.seek(1);
-            fail("Test 1: IOException expected.");
+            fail("Test 4: IOException expected.");
         } catch (IOException e) {
             // Expected.
         }
@@ -1296,10 +1305,21 @@
         assertEquals("Test 7: Incorrect file length;", 
                 testLength + 2, raf.length());
         
+        // BEGIN android-added
+        // Exception testing.
+        try {
+            // Android uses 32-bit off_t, so anything larger than a signed 32-bit int won't work.
+            raf.setLength(((long) Integer.MAX_VALUE) + 1);
+            fail("Test 8: IOException expected.");
+        } catch (IOException e) {
+            // Expected.
+        }
+        // END android-added
+
         // Exception testing.
         try {
             raf.setLength(-1);
-            fail("Test 8: IllegalArgumentException expected.");
+            fail("Test 9: IllegalArgumentException expected.");
         } catch (IllegalArgumentException e) {
             // Expected.
         }
@@ -1307,7 +1327,7 @@
         raf.close();
         try {
             raf.setLength(truncLength);
-            fail("Test 9: IOException expected.");
+            fail("Test 10: IOException expected.");
         } catch (IOException e) {
             // Expected.
         }
@@ -1501,4 +1521,4 @@
         super.tearDown();
     }
 
-}
\ No newline at end of file
+}
diff --git a/libcore/luni/src/test/java/tests/api/java/lang/Process2Test.java b/libcore/luni/src/test/java/tests/api/java/lang/Process2Test.java
index 51b29d8..2e60e77 100644
--- a/libcore/luni/src/test/java/tests/api/java/lang/Process2Test.java
+++ b/libcore/luni/src/test/java/tests/api/java/lang/Process2Test.java
@@ -30,6 +30,7 @@
 import java.io.OutputStream;
 
 import tests.support.Support_Exec;
+import static tests.support.Support_Exec.javaProcessBuilder;
 
 @TestTargetClass(Process.class) 
 public class Process2Test extends junit.framework.TestCase {
@@ -60,23 +61,12 @@
         )
     })
     @AndroidOnly("dalvikvm specific")
-    public void test_isBufferedStreams() {
-        // Regression test for HARMONY-2735.
-        try {
-            Object[] execArgs = Support_Exec.execJava2(new String[0], null, true);
-            Process p = (Process) execArgs[0];
-            InputStream in = p.getInputStream();
-                  assertNotNull(in);
-                  in = p.getErrorStream();
-                  assertNotNull(in);
-                  OutputStream out = p.getOutputStream();
-                  assertNotNull(out);
-                  in.close();
-                  out.close();
-                  p.destroy();
-        } catch (Exception ex) {
-            fail("Unexpected exception got: " + ex);
-        }
+    public void test_streams()
+            throws IOException, InterruptedException {
+        Process p = javaProcessBuilder().start();
+        assertNotNull(p.getInputStream());
+        assertNotNull(p.getErrorStream());
+        assertNotNull(p.getOutputStream());
     }
     
     @TestTargetNew(
diff --git a/libcore/luni/src/test/java/tests/api/java/util/ArrayListTest.java b/libcore/luni/src/test/java/tests/api/java/util/ArrayListTest.java
index 8aa77cc..0356731 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/ArrayListTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/ArrayListTest.java
@@ -19,7 +19,7 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass; 
+import dalvik.annotation.TestTargetClass;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -33,13 +33,13 @@
 
 import tests.support.Support_ListTest;
 
-@TestTargetClass(ArrayList.class) 
+@TestTargetClass(ArrayList.class)
 public class ArrayListTest extends junit.framework.TestCase {
 
     List alist;
 
     Object[] objArray;
-    
+
     /**
      * @tests java.util.ArrayList#ArrayList()
      */
@@ -72,7 +72,7 @@
         // Test for method java.util.ArrayList(int)
         ArrayList al = new ArrayList(5);
         assertEquals("Incorrect arrayList created", 0, al.size());
-        
+
         try {
             new ArrayList(-10);
             fail("IllegalArgumentException expected");
@@ -130,14 +130,14 @@
         assertNull("Should have returned null", alist.get(25));
         assertTrue("Should have returned the old item from slot 25", alist
                 .get(26) == oldItem);
-        
+
         try {
             alist.add(-1, null);
             fail("IndexOutOfBoundsException expected");
         } catch (IndexOutOfBoundsException e) {
             //expected
         }
-        
+
         try {
             alist.add(alist.size() + 1, null);
             fail("IndexOutOfBoundsException expected");
@@ -198,9 +198,9 @@
         assertTrue("Incorrect size: " + alist.size(), alist.size() == 205);
         assertNull("Item at slot 100 should be null", alist.get(100));
         assertNull("Item at slot 101 should be null", alist.get(101));
-        assertEquals("Item at slot 102 should be 'yoink'", 
+        assertEquals("Item at slot 102 should be 'yoink'",
                 "yoink", alist.get(102));
-        assertEquals("Item at slot 103 should be 'kazoo'", 
+        assertEquals("Item at slot 103 should be 'kazoo'",
                 "kazoo", alist.get(103));
         assertNull("Item at slot 104 should be null", alist.get(104));
         alist.addAll(205, listWithNulls);
@@ -228,24 +228,29 @@
         }
     }
 
-    /**
-     * @tests java.util.ArrayList#addAll(int, java.util.Collection)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "Verifies IndexOutOfBoundsException.",
-        method = "addAll",
-        args = {int.class, java.util.Collection.class}
-    )
-    public void test_addAllILjava_util_Collection_2() {
-        // Regression for HARMONY-467
-        ArrayList obj = new ArrayList();
-        try {
-            obj.addAll((int) -1, (Collection) null);
-            fail("IndexOutOfBoundsException expected");
-        } catch (IndexOutOfBoundsException e) {
-        }
-    }
+// BEGIN android-removed
+// The spec does not mandate that IndexOutOfBoundsException be thrown in
+// preference to NullPointerException when the caller desserves both.
+//
+//    /**
+//     * @tests java.util.ArrayList#addAll(int, java.util.Collection)
+//     */
+//    @TestTargetNew(
+//        level = TestLevel.PARTIAL_COMPLETE,
+//        notes = "Verifies IndexOutOfBoundsException.",
+//        method = "addAll",
+//        args = {int.class, java.util.Collection.class}
+//    )
+//    public void test_addAllILjava_util_Collection_2() {
+//        // Regression for HARMONY-467
+//        ArrayList obj = new ArrayList();
+//        try {
+//            obj.addAll((int) -1, (Collection) null);
+//            fail("IndexOutOfBoundsException expected");
+//        } catch (IndexOutOfBoundsException e) {
+//        }
+//    }
+// END android-removed
 
     /**
      * @tests java.util.ArrayList#addAll(java.util.Collection)
@@ -287,17 +292,17 @@
                 .get(101) == i.next());
         assertTrue("Item at slot 103 is wrong: " + alist.get(102), alist
                 .get(102) == i.next());
-        
-        
+
+
         // Regression test for Harmony-3481
         ArrayList<Integer> originalList = new ArrayList<Integer>(12);
         for (int j = 0; j < 12; j++) {
             originalList.add(j);
         }
-        
+
         originalList.remove(0);
         originalList.remove(0);
-        
+
         ArrayList<Integer> additionalList = new ArrayList<Integer>(11);
         for (int j = 0; j < 11; j++) {
             additionalList.add(j);
@@ -672,7 +677,7 @@
                 assertTrue("Returned incorrect array: " + i,
                         retArray[i] == objArray[i]);
         }
-        
+
         String[] strArray = new String[100];
         try {
             alist.toArray(strArray);
@@ -746,16 +751,16 @@
 
         list.remove(0);
         assertEquals(1, list.size());
-        
+
         ArrayList collection = new ArrayList();
         collection.add("1");
         collection.add("2");
         collection.add("3");
         assertEquals(3, collection.size());
-        
+
         list.addAll(0, collection);
         assertEquals(4, list.size());
-        
+
         list.remove(0);
         list.remove(0);
         assertEquals(2, list.size());
@@ -769,13 +774,13 @@
         collection.add("10");
         collection.add("11");
         collection.add("12");
-        
+
         assertEquals(12, collection.size());
-        
+
         list.addAll(0, collection);
         assertEquals(14, list.size());
     }
-    
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
@@ -818,7 +823,7 @@
         mal.add("f");
         mal.add("g");
         mal.add("h");
-        
+
         mal.removeRange(2, 4);
 
         String[] result = new String[6];
@@ -827,30 +832,30 @@
                 new String[] { "a", "b", "e", "f", "g", "h"}));
     }
 
-    
+
     /**
      * Sets up the fixture, for example, open a network connection. This method
      * is called before a test is executed.
      */
     protected void setUp() throws Exception {
         super.setUp();
-        
+
         objArray = new Object[100];
         for (int i = 0; i < objArray.length; i++) {
             objArray[i] = new Integer(i);
         }
-        
+
         alist = new ArrayList();
         for (int i = 0; i < objArray.length; i++) {
             alist.add(objArray[i]);
         }
     }
-    
+
     @Override
     protected void tearDown() throws Exception {
         objArray = null;
         alist = null;
-        
+
         super.tearDown();
     }
 }
diff --git a/libcore/luni/src/test/java/tests/api/java/util/CollectionsTest.java b/libcore/luni/src/test/java/tests/api/java/util/CollectionsTest.java
index 2b1b47e..7fc60d8 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/CollectionsTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/CollectionsTest.java
@@ -41,6 +41,7 @@
 import java.util.SortedSet;
 import java.util.TreeMap;
 import java.util.TreeSet;
+import java.util.Arrays;
 
 import org.apache.harmony.luni.internal.nls.Messages;
 
@@ -807,18 +808,19 @@
         LinkedList ll2 = new LinkedList();
         ll2.addAll(ll);
         testShuffle(ll2, "Random Access", false);
+    }
 
-        Mock_ArrayList mal = new Mock_ArrayList();
-        
-        mal.add("First");
-        mal.add("Second");
-        
-        try {
-            Collections.shuffle(mal);
-            fail("UnsupportedOperationException expected");
-        } catch (UnsupportedOperationException e) {
-            //expected
-        }
+    public void testShuffleRandomAccessWithSeededRandom() {
+        List<String> list = Arrays.asList("A", "B", "C", "D", "E", "F", "G");
+        Collections.shuffle(list, new Random(0));
+        assertEquals(Arrays.asList("B", "A", "D", "C", "G", "E", "F"), list);
+    }
+
+    public void testShuffleWithSeededRandom() {
+        List<String> list = new LinkedList<String>(Arrays.asList(
+                "A", "B", "C", "D", "E", "F", "G"));
+        Collections.shuffle(list, new Random(0));
+        assertEquals(Arrays.asList("B", "A", "D", "C", "G", "E", "F"), list);
     }
 
     private void testShuffle(List list, String type, boolean random) {
@@ -837,15 +839,15 @@
                 sorted = false;
             }
         }
-        assertTrue("Shuffling sorted " + type
-                + " list resulted in sorted list (should be unlikely)", !sorted);
+        assertFalse("Shuffling sorted " + type
+                + " list resulted in sorted list (should be unlikely)", sorted);
         for (int counter = 0; counter < 20; counter++) {
             index = 30031 * counter % (size + 1); // 30031 is a large prime
             if (list.get(index) != ll.get(index))
                 allMatch = false;
         }
-        assertTrue("Too many element positions match in shuffled " + type
-                + " list", !allMatch);
+        assertFalse("Too many element positions match in shuffled " + type
+                + " list", allMatch);
     }
 
     /**
diff --git a/libcore/luni/src/test/java/tests/api/java/util/FormatterTest.java b/libcore/luni/src/test/java/tests/api/java/util/FormatterTest.java
index b2030c9..6f86818 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/FormatterTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/FormatterTest.java
@@ -800,6 +800,36 @@
         }
     }
 
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Tests that supplying a Formattable works. See http://code.google.com/p/android/issues/detail?id=1767.",
+        method = "format",
+        args = {}
+    )
+    public void test_Formattable() {
+        Formattable ones = new Formattable() {
+            public void formatTo(Formatter formatter, int flags, int width, int precision) throws IllegalFormatException {
+                try {
+                    formatter.out().append("111");
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        };
+        Formattable twos = new Formattable() {
+            public void formatTo(Formatter formatter, int flags, int width, int precision) throws IllegalFormatException {
+                try {
+                    formatter.out().append("222");
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        };
+
+        assertEquals("aaa 111?", new Formatter().format("aaa %s?", ones).toString());
+        assertEquals("aaa 111 bbb 222?", new Formatter().format("aaa %s bbb %s?", ones, twos).toString());
+    }
+
     /**
      * @tests java.util.Formatter#out()
      */
diff --git a/libcore/luni/src/test/java/tests/api/java/util/TimeZoneTest.java b/libcore/luni/src/test/java/tests/api/java/util/TimeZoneTest.java
index efdb8a1..75e9ae3 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/TimeZoneTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/TimeZoneTest.java
@@ -383,6 +383,19 @@
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
+        method = "useDaylightTime",
+        args = {}
+    )
+    public void test_useDaylightTime() {
+        // http://code.google.com/p/android/issues/detail?id=877
+        
+        TimeZone asiaTaipei = TimeZone.getTimeZone("Asia/Taipei");
+        assertFalse("Taiwan doesn't use DST", asiaTaipei.useDaylightTime());
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
         method = "setID",
         args = {java.lang.String.class}
     )
diff --git a/libcore/math/src/main/java/java/math/BigInt.java b/libcore/math/src/main/java/java/math/BigInt.java
index cb7990a..581c22f 100644
--- a/libcore/math/src/main/java/java/math/BigInt.java
+++ b/libcore/math/src/main/java/java/math/BigInt.java
@@ -225,12 +225,6 @@
         return a;
     }
 
-    public byte[] bigEndianTwosComplement() {
-        byte[] a = NativeBN.bn2twosComp(this.bignum, null);
-        return a;
-    }
-
-
     public int sign() {
         return NativeBN.sign(this.bignum);
     }
diff --git a/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java b/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
index 36e0082..49c5faa 100644
--- a/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
+++ b/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
@@ -768,7 +768,7 @@
         assertFalse(s.getBroadcast());
         assertFalse(s.getReuseAddress());
         assertNull(s.getInetAddress());
-        assertEquals(s.getLocalAddress().getHostAddress(), "0.0.0.0");
+        assertTrue(s.getLocalAddress().isAnyLocalAddress());
         assertEquals(s.getLocalPort(), 0);
         assertNull(s.getLocalSocketAddress());
         assertEquals(s.getPort(), -1);
diff --git a/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java b/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
index 91d6d06..a846e70 100644
--- a/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
+++ b/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
@@ -1155,6 +1155,25 @@
         } catch (IllegalArgumentException e) {
             // expected
         }
+
+        // BEGIN android-added
+        // Android uses 32-bit off_t, so anything larger than a signed 32-bit int won't work...
+        // ...except for the special case of length == Long.MAX_VALUE, which is used to mean "the
+        // whole file". The special case is tested elsewhere.
+        long tooBig = ((long) Integer.MAX_VALUE) + 1;
+        try {
+            readWriteFileChannel.tryLock(tooBig, 1, false);
+            fail("should throw IOException");
+        } catch (IOException e) {
+            // expected
+        }
+        try {
+            readWriteFileChannel.tryLock(0, tooBig, false);
+            fail("should throw IOException");
+        } catch (IOException e) {
+            // expected
+        }
+        // END android-added
     }
 
     /**
diff --git a/libcore/openssl/src/main/java/org/openssl/NativeBN.java b/libcore/openssl/src/main/java/org/openssl/NativeBN.java
index 44464e0..3597e3c 100644
--- a/libcore/openssl/src/main/java/org/openssl/NativeBN.java
+++ b/libcore/openssl/src/main/java/org/openssl/NativeBN.java
@@ -79,9 +79,6 @@
 
     public static native int[] bn2litEndInts(int a, int[] to);
 
-    public static native byte[] bn2twosComp(int a, byte[] to);
-
-
     public static native int sign(int a);
     // Returns -1, 0, 1 AND NOT boolean.
     // #define BN_is_negative(a) ((a)->neg != 0)
diff --git a/libcore/openssl/src/main/native/BNInterface.c b/libcore/openssl/src/main/native/BNInterface.c
index 4132e4f..1a3eb16 100644
--- a/libcore/openssl/src/main/native/BNInterface.c
+++ b/libcore/openssl/src/main/native/BNInterface.c
@@ -33,12 +33,6 @@
 
 
 static void
-throwOutOfMemoryException(JNIEnv* env, const char* message)
-{
-    jniThrowException(env, "java/lang/OutOfMemoryError", message);
-}
-
-static void
 throwNewNullPointerException (JNIEnv* env, const char* message)
 {
     jniThrowException(env, "java/lang/NullPointerException", message);
@@ -456,27 +450,6 @@
     }
 }
 
-/**
- * public static native byte[] bn2twosComp(int, byte[])
- */
-static jbyteArray NativeBN_bn2twosComp(JNIEnv* env, jclass cls, BIGNUM* a, jbyteArray to) {
-    if (!oneValidHandle(env, a)) return NULL;
-    jbyteArray returnJBytes = to;
-    unsigned char * tmpBytes;
-    int len, byteCnt;
-    byteCnt = BN_num_bytes(a);
-// FIXME: Currently ignoring array passed in to:
-    returnJBytes = (*env)->NewByteArray(env, byteCnt);
-// FIXME: is it neccessary to check for returnJBytes != NULL?
-    tmpBytes = (unsigned char *)((*env)->GetPrimitiveArrayCritical(env, returnJBytes, NULL));
-    if (tmpBytes != NULL) {
-        len = BN_bn2bin(a, tmpBytes);
-        (*env)->ReleasePrimitiveArrayCritical(env, returnJBytes, tmpBytes, 0);
-        return returnJBytes;
-    }
-    else return NULL;
-}
-
 
 /**
  * public static native int sign(int)
@@ -833,7 +806,6 @@
    { "BN_bn2hex", "(I)Ljava/lang/String;", (void*)NativeBN_BN_bn2hex },
    { "BN_bn2bin", "(I[B)[B", (void*)NativeBN_BN_bn2bin },
    { "bn2litEndInts", "(I[I)[I", (void*)NativeBN_bn2litEndInts },
-   { "bn2twosComp", "(I[B)[B", (void*)NativeBN_bn2twosComp },
    { "sign", "(I)I", (void*)NativeBN_sign },
    { "BN_set_negative", "(II)V", (void*)NativeBN_BN_set_negative },
    { "twosCompFitsIntoBytes", "(II)Z", (void*)NativeBN_twosCompFitsIntoBytes },
diff --git a/libcore/regex/src/main/java/java/util/regex/MatchResult.java b/libcore/regex/src/main/java/java/util/regex/MatchResult.java
index fa67ba6..76c17a8 100644
--- a/libcore/regex/src/main/java/java/util/regex/MatchResult.java
+++ b/libcore/regex/src/main/java/java/util/regex/MatchResult.java
@@ -1,17 +1,18 @@
 /*
- * 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,
- * 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.util.regex;
@@ -22,91 +23,75 @@
  * pair of parentheses in the regular expression and an additional group for
  * the whole regular expression. The start, end, and contents of each group
  * can be queried.
- * 
+ *
  * @see Matcher
  * @see Matcher#toMatchResult()
- * 
- * @since Android 1.0
  */
 public interface MatchResult {
 
     /**
      * Returns the index of the first character following the text that matched
-     * the whole regular expression. 
-     * 
+     * the whole regular expression.
+     *
      * @return the character index.
-     * 
-     * @since Android 1.0
      */
     int end();
 
     /**
      * Returns the index of the first character following the text that matched
      * a given group.
-     * 
+     *
      * @param group
      *            the group, ranging from 0 to groupCount() - 1, with 0
      *            representing the whole pattern.
-     * 
+     *
      * @return the character index.
-     * 
-     * @since Android 1.0
      */
     int end(int group);
 
     /**
-     * Returns the text that matched the whole regular expression. 
-     * 
+     * Returns the text that matched the whole regular expression.
+     *
      * @return the text.
-     * 
-     * @since Android 1.0
      */
     String group();
 
     /**
      * Returns the text that matched a given group of the regular expression.
-     * 
+     *
      * @param group
      *            the group, ranging from 0 to groupCount() - 1, with 0
      *            representing the whole pattern.
-     * 
+     *
      * @return the text that matched the group.
-     * 
-     * @since Android 1.0
      */
     String group(int group);
 
     /**
      * Returns the number of groups in the result, which is always equal to
      * the number of groups in the original regular expression.
-     * 
+     *
      * @return the number of groups.
-     * 
-     * @since Android 1.0
      */
     int groupCount();
 
     /**
      * Returns the index of the first character of the text that matched
-     * the whole regular expression. 
-     * 
+     * the whole regular expression.
+     *
      * @return the character index.
-     * 
-     * @since Android 1.0
      */
     int start();
 
     /**
      * Returns the index of the first character of the text that matched a given
      * group.
-     * 
+     *
      * @param group
      *            the group, ranging from 0 to groupCount() - 1, with 0
      *            representing the whole pattern.
-     * 
+     *
      * @return the character index.
-     * 
-     * @since Android 1.0
      */
     int start(int group);
 }
diff --git a/libcore/regex/src/main/java/java/util/regex/Matcher.java b/libcore/regex/src/main/java/java/util/regex/Matcher.java
index e3e4874..be5c782 100644
--- a/libcore/regex/src/main/java/java/util/regex/Matcher.java
+++ b/libcore/regex/src/main/java/java/util/regex/Matcher.java
@@ -44,8 +44,6 @@
  * {@code Pattern} was successful and at which position the next attempt would
  * resume the search. Depending on the application's needs, it may become
  * necessary to explicitly {@link #reset()} this state from time to time.
- * 
- * @since Android 1.0
  */
 public final class Matcher implements MatchResult {
 
@@ -128,39 +126,99 @@
     }
 
     /**
+     * Appends a literal part of the input plus a replacement for the current
+     * match to a given {@link StringBuffer}. The literal part is exactly the
+     * part of the input between the previous match and the current match. The
+     * method can be used in conjunction with {@link #find()} and
+     * {@link #appendTail(StringBuffer)} to walk through the input and replace
+     * all occurrences of the {@code Pattern} with something else.
+     *
+     * @param buffer
+     *            the {@code StringBuffer} to append to.
+     * @param replacement
+     *            the replacement text.
+     * @return the {@code Matcher} itself.
+     * @throws IllegalStateException
+     *             if no successful match has been made.
+     */
+    public Matcher appendReplacement(StringBuffer buffer, String replacement) {
+        buffer.append(input.substring(appendPos, start()));
+        appendEvaluated(buffer, replacement);
+        appendPos = end();
+
+        return this;
+    }
+
+    /**
+     * Internal helper method to append a given string to a given string buffer.
+     * If the string contains any references to groups, these are replaced by
+     * the corresponding group's contents.
+     *
+     * @param buffer
+     *            the string buffer.
+     * @param s
+     *            the string to append.
+     */
+    private void appendEvaluated(StringBuffer buffer, String s) {
+        boolean escape = false;
+        boolean dollar = false;
+
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+            if (c == '\\' && !escape) {
+                escape = true;
+            } else if (c == '$' && !escape) {
+                dollar = true;
+            } else if (c >= '0' && c <= '9' && dollar) {
+                buffer.append(group(c - '0'));
+                dollar = false;
+            } else {
+                buffer.append(c);
+                dollar = false;
+                escape = false;
+            }
+        }
+
+        // This seemingly stupid piece of code reproduces a JDK bug.
+        if (escape) {
+            throw new ArrayIndexOutOfBoundsException(s.length());
+        }
+    }
+
+    /**
      * Resets the Matcher. A new input sequence and a new region can be
      * specified. Results of a previous find get lost. The next attempt to find
      * an occurrence of the Pattern in the string will start at the beginning of
      * the region. This is the internal version of reset() to which the several
      * public versions delegate.
-     * 
+     *
      * @param input
      *            the input sequence.
      * @param start
      *            the start of the region.
      * @param end
      *            the end of the region.
-     * 
+     *
      * @return the matcher itself.
      */
     private Matcher reset(CharSequence input, int start, int end) {
         if (input == null) {
             throw new IllegalArgumentException();
         }
-        
-        if (start < 0 || end < 0 || start > input.length() || 
+
+        if (start < 0 || end < 0 || start > input.length() ||
                 end > input.length() || start > end) {
             throw new IllegalArgumentException();
         }
 
         // Maybe should have a reset() here, but it makes thing worse...
         // NativeRegEx.reset(nativePattern, 0);
-        
+
         if (!input.equals(this.input)) {
             this.input = input.toString();
-            
+
             NativeRegEx.setText(nativePattern, this.input);
-            
+
             regionStart = 0;
             regionEnd = input.length();
         }
@@ -176,22 +234,8 @@
         matchFound = false;
         findPos = regionStart;
         appendPos = 0;
-        
-        return this;
-    }
 
-    /**
-     * Resets the {@code Matcher}. This results in the region being set to the
-     * whole input. Results of a previous find get lost. The next attempt to
-     * find an occurrence of the {@link Pattern} in the string will start at the
-     * beginning of the input.
-     * 
-     * @return the {@code Matcher} itself.
-     * 
-     * @since Android 1.0
-     */
-    public Matcher reset() {
-        return reset(input, 0, input.length());
+        return this;
     }
 
     /**
@@ -204,73 +248,24 @@
      *            the new input sequence.
      * 
      * @return the {@code Matcher} itself.
-     * 
-     * @since Android 1.0
      */
     public Matcher reset(CharSequence input) {
         return reset(input, 0, input.length());
     }
 
     /**
-     * Sets a new pattern for the {@code Matcher}. Results of a previous find
-     * get lost. The next attempt to find an occurrence of the {@link Pattern}
-     * in the string will start at the beginning of the input.
-     * 
-     * @param pattern
-     *            the new {@code Pattern}.
-     * 
+     * Resets the {@code Matcher}. This results in the region being set to the
+     * whole input. Results of a previous find get lost. The next attempt to
+     * find an occurrence of the {@link Pattern} in the string will start at the
+     * beginning of the input.
+     *
      * @return the {@code Matcher} itself.
-     * 
-     * @since Android 1.0
      */
-    public Matcher usePattern(Pattern pattern) {
-        if (pattern == null) {
-            throw new IllegalArgumentException();
-        }
-        
-        this.pattern = pattern;
-        
-        if (nativePattern != 0) {
-            NativeRegEx.close(nativePattern);
-        }
-        nativePattern = NativeRegEx.clone(pattern.mNativePattern);
-
-        if (input != null) {
-            NativeRegEx.setText(nativePattern, input);
-            NativeRegEx.setRegion(nativePattern, regionStart, regionEnd);
-            NativeRegEx.useAnchoringBounds(nativePattern, anchoringBounds);
-            NativeRegEx.useTransparentBounds(nativePattern, transparentBounds);
-        }
-        
-        matchOffsets = new int[(this.pattern.mGroupCount + 1) * 2];
-        matchFound = false;
-        return this;
+    public Matcher reset() {
+        return reset(input, 0, input.length());
     }
 
     /**
-     * Returns the {@link Pattern} instance used inside this matcher.
-     * 
-     * @return the {@code Pattern} instance.
-     * 
-     * @since Android 1.0
-     */
-    public Pattern pattern() {
-        return pattern;
-    }
-
-    /**
-     * Returns the number of groups in the results, which is always equal to
-     * the number of groups in the original regular expression.
-     * 
-     * @return the number of groups.
-     * 
-     * @since Android 1.0
-     */
-    public int groupCount() {
-        return pattern.mGroupCount;
-    }
-    
-    /**
      * Resets this matcher and sets a region. Only characters inside the region
      * are considered for a match.
      * 
@@ -279,109 +274,150 @@
      * @param end
      *            the first character after the end of the region.
      * @return the {@code Matcher} itself.
-     * @since Android 1.0
      */
     public Matcher region(int start, int end) {
         return reset(input, start, end);
     }
 
-    /**
-     * Returns this matcher's region start, that is, the first character that is
-     * considered for a match.
-     * 
-     * @return the start of the region.
-     * @since Android 1.0
-     */
-    public int regionStart() {
-        return regionStart;
-    }
 
     /**
-     * Returns this matcher's region end, that is, the first character that is
-     * not considered for a match.
-     * 
-     * @return the end of the region.
-     * @since Android 1.0
-     */
-    public int regionEnd() {
-        return regionEnd;
-    }
-
-    /**
-     * Determines whether this matcher has anchoring bounds enabled or not. When
-     * anchoring bounds are enabled, the start and end of the input match the
-     * '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
-     * by default.
-     * 
-     * @param value
-     *            the new value for anchoring bounds.
-     * @return the {@code Matcher} itself.
-     * @since Android 1.0
-     */
-    public Matcher useAnchoringBounds(boolean value) {
-        anchoringBounds = value;
-        NativeRegEx.useAnchoringBounds(nativePattern, value);
-        return this;
-    }
-    
-    /**
-     * Indicates whether this matcher has anchoring bounds enabled. When
-     * anchoring bounds are enabled, the start and end of the input match the
-     * '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
-     * by default.
-     * 
-     * @return true if (and only if) the {@code Matcher} uses anchoring bounds.
-     * @since Android 1.0
-     */
-    public boolean hasAnchoringBounds() {
-        return anchoringBounds;
-    }
-
-    /**
-     * Determines whether this matcher has transparent bounds enabled or not.
-     * When transparent bounds are enabled, the parts of the input outside the
-     * region are subject to lookahead and lookbehind, otherwise they are not.
-     * Transparent bounds are disabled by default.
-     * 
-     * @param value
-     *            the new value for transparent bounds.
-     * @return the {@code Matcher} itself.
-     * @since Android 1.0
-     */
-    public Matcher useTransparentBounds(boolean value) {
-        transparentBounds = value;
-        NativeRegEx.useTransparentBounds(nativePattern, value);
-        return this;
-    }
-    
-    /**
-     * Indicates whether this matcher has transparent bounds enabled. When
-     * transparent bounds are enabled, the parts of the input outside the region
-     * are subject to lookahead and lookbehind, otherwise they are not.
-     * Transparent bounds are disabled by default.
-     * 
-     * @return true if (and only if) the {@code Matcher} uses anchoring bounds.
-     * @since Android 1.0
-     */
-    public boolean hasTransparentBounds() {
-        return transparentBounds;
-    }
-    
-    /**
-     * Makes sure that a successful match has been made. Is invoked internally
-     * from various places in the class.
-     * 
+     * Appends the (unmatched) remainder of the input to the given
+     * {@link StringBuffer}. The method can be used in conjunction with
+     * {@link #find()} and {@link #appendReplacement(StringBuffer, String)} to
+     * walk through the input and replace all matches of the {@code Pattern}
+     * with something else.
+     *
+     * @param buffer
+     *            the {@code StringBuffer} to append to.
+     * @return the {@code StringBuffer}.
      * @throws IllegalStateException
      *             if no successful match has been made.
-     * 
-     * @since Android 1.0
      */
-    private void ensureMatch() throws IllegalStateException {
-        if (!matchFound) {
-            throw new IllegalStateException("No successful match so far");
+    public StringBuffer appendTail(StringBuffer buffer) {
+        if (appendPos < regionEnd) {
+            buffer.append(input.substring(appendPos, regionEnd));
+        }
+
+        return buffer;
+    }
+
+    /**
+     * Replaces the first occurrence of this matcher's pattern in the input with
+     * a given string.
+     *
+     * @param replacement
+     *            the replacement text.
+     * @return the modified input string.
+     */
+    public String replaceFirst(String replacement) {
+        StringBuffer buffer = new StringBuffer(input.length());
+
+        findPos = 0;
+        appendPos = 0;
+        matchFound = false;
+        searching = false;
+
+        if (find()) {
+            appendReplacement(buffer, replacement);
+        }
+
+        return appendTail(buffer).toString();
+    }
+
+    /**
+     * Replaces all occurrences of this matcher's pattern in the input with a
+     * given string.
+     *
+     * @param replacement
+     *            the replacement text.
+     * @return the modified input string.
+     */
+    public String replaceAll(String replacement) {
+        StringBuffer buffer = new StringBuffer(input.length());
+
+        findPos = 0;
+        appendPos = 0;
+        matchFound = false;
+        searching = false;
+
+        while (find()) {
+            appendReplacement(buffer, replacement);
+        }
+
+        return appendTail(buffer).toString();
+    }
+
+    /**
+     * Returns the {@link Pattern} instance used inside this matcher.
+     *
+     * @return the {@code Pattern} instance.
+     */
+    public Pattern pattern() {
+        return pattern;
+    }
+
+    /**
+     * Returns the text that matched a given group of the regular expression.
+     *
+     * @param group
+     *            the group, ranging from 0 to groupCount() - 1, with 0
+     *            representing the whole pattern.
+     * @return the text that matched the group.
+     * @throws IllegalStateException
+     *             if no successful match has been made.
+     */
+    public String group(int group) {
+        ensureMatch();
+        int from = matchOffsets[group * 2];
+        int to = matchOffsets[(group * 2) + 1];
+        if (from == -1 || to == -1) {
+            return null;
+        } else {
+            return input.substring(from, to);
         }
     }
-    
+
+    /**
+     * Returns the text that matched the whole regular expression.
+     *
+     * @return the text.
+     * @throws IllegalStateException
+     *             if no successful match has been made.
+     */
+    public String group() {
+        return group(0);
+    }
+
+    /**
+     * Returns the next occurrence of the {@link Pattern} in the input. The
+     * method starts the search from the given character in the input.
+     *
+     * @param start
+     *            The index in the input at which the find operation is to
+     *            begin. If this is less than the start of the region, it is
+     *            automatically adjusted to that value. If it is beyond the end
+     *            of the region, the method will fail.
+     * @return true if (and only if) a match has been found.
+     */
+    public boolean find(int start) {
+        findPos = start;
+
+        if (findPos < regionStart) {
+            findPos = regionStart;
+        } else if (findPos >= regionEnd) {
+            matchFound = false;
+            return false;
+        }
+
+        matchFound = NativeRegEx.find(nativePattern, findPos);
+        if (matchFound) {
+            NativeRegEx.startEnd(nativePattern, matchOffsets);
+            findPos = matchOffsets[1];
+        }
+
+        return matchFound;
+    }
+
     /**
      * Returns the next occurrence of the {@link Pattern} in the input. If a
      * previous match was successful, the method continues the search from the
@@ -389,7 +425,6 @@
      * either from the region start (if one has been set), or from position 0.
      * 
      * @return true if (and only if) a match has been found.
-     * @since Android 1.0
      */
     public boolean find() {
         if (!searching) {
@@ -408,34 +443,35 @@
     }
 
     /**
-     * Returns the next occurrence of the {@link Pattern} in the input. The
-     * method starts the search from the given character in the input.
-     * 
-     * @param start
-     *            The index in the input at which the find operation is to
-     *            begin. If this is less than the start of the region, it is
-     *            automatically adjusted to that value. If it is beyond the end
-     *            of the region, the method will fail.
-     * @return true if (and only if) a match has been found.
-     * @since Android 1.0
+     * Returns the index of the first character of the text that matched a given
+     * group.
+     *
+     * @param group
+     *            the group, ranging from 0 to groupCount() - 1, with 0
+     *            representing the whole pattern.
+     * @return the character index.
+     * @throws IllegalStateException
+     *             if no successful match has been made.
      */
-    public boolean find(int start) {
-        findPos = start;
-        
-        if (findPos < regionStart) {
-            findPos = regionStart;
-        } else if (findPos >= regionEnd) {
-            matchFound = false;
-            return false;
-        }
-        
-        matchFound = NativeRegEx.find(nativePattern, findPos); 
-        if (matchFound) {
-            NativeRegEx.startEnd(nativePattern, matchOffsets);
-            findPos = matchOffsets[1];
-        }
-        
-        return matchFound;
+    public int start(int group) throws IllegalStateException {
+        ensureMatch();
+        return matchOffsets[group * 2];
+    }
+
+    /**
+     * Returns the index of the first character following the text that matched
+     * a given group.
+     *
+     * @param group
+     *            the group, ranging from 0 to groupCount() - 1, with 0
+     *            representing the whole pattern.
+     * @return the character index.
+     * @throws IllegalStateException
+     *             if no successful match has been made.
+     */
+    public int end(int group) {
+        ensureMatch();
+        return matchOffsets[(group * 2) + 1];
     }
 
     /**
@@ -444,8 +480,6 @@
      * 
      * @return true if (and only if) the {@code Pattern} matches the entire
      *         region.
-     * 
-     * @since Android 1.0
      */
     public boolean matches() {
         matchFound = NativeRegEx.matches(nativePattern, -1); 
@@ -458,13 +492,34 @@
     }
 
     /**
+     * Returns a replacement string for the given one that has all backslashes
+     * and dollar signs escaped.
+     *
+     * @param s
+     *            the input string.
+     * @return the input string, with all backslashes and dollar signs having
+     *         been escaped.
+     */
+    public static String quoteReplacement(String s) {
+        StringBuffer buffer = new StringBuffer(s.length());
+
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+            if (c == '\\' || c == '$') {
+                buffer.append('\\');
+            }
+            buffer.append(c);
+        }
+
+        return buffer.toString();
+    }
+
+    /**
      * Tries to match the {@link Pattern}, starting from the beginning of the
      * region (or the beginning of the input, if no region has been set).
      * Doesn't require the {@code Pattern} to match against the whole region.
      * 
      * @return true if (and only if) the {@code Pattern} matches.
-     * 
-     * @since Android 1.0
      */
     public boolean lookingAt() {
         matchFound = NativeRegEx.lookingAt(nativePattern, -1); 
@@ -483,27 +538,19 @@
      * @return the character index.
      * @throws IllegalStateException
      *             if no successful match has been made.
-     * @since Android 1.0
      */
-    public int start() throws IllegalStateException {
+    public int start() {
         return start(0);
     }
 
     /**
-     * Returns the index of the first character of the text that matched a given
-     * group.
-     * 
-     * @param group
-     *            the group, ranging from 0 to groupCount() - 1, with 0
-     *            representing the whole pattern.
-     * @return the character index.
-     * @throws IllegalStateException
-     *             if no successful match has been made.
-     * @since Android 1.0
+     * Returns the number of groups in the results, which is always equal to
+     * the number of groups in the original regular expression.
+     *
+     * @return the number of groups.
      */
-    public int start(int group) throws IllegalStateException {
-        ensureMatch();
-        return matchOffsets[group * 2];
+    public int groupCount() {
+        return pattern.mGroupCount;
     }
 
     /**
@@ -513,94 +560,19 @@
      * @return the character index.
      * @throws IllegalStateException
      *             if no successful match has been made.
-     * @since Android 1.0
      */
     public int end() {
         return end(0);
     }
 
     /**
-     * Returns the index of the first character following the text that matched
-     * a given group.
-     * 
-     * @param group
-     *            the group, ranging from 0 to groupCount() - 1, with 0
-     *            representing the whole pattern.
-     * @return the character index.
-     * @throws IllegalStateException
-     *             if no successful match has been made.
-     * @since Android 1.0
-     */
-    public int end(int group) {
-        ensureMatch();
-        return matchOffsets[(group * 2) + 1];
-    }
-
-    /**
-     * Returns the text that matched the whole regular expression.
-     * 
-     * @return the text.
-     * @throws IllegalStateException
-     *             if no successful match has been made.
-     * @since Android 1.0
-     */
-    public String group() {
-        return group(0);
-    }
-
-    /**
-     * Returns the text that matched a given group of the regular expression.
-     * 
-     * @param group
-     *            the group, ranging from 0 to groupCount() - 1, with 0
-     *            representing the whole pattern.
-     * @return the text that matched the group.
-     * @throws IllegalStateException
-     *             if no successful match has been made.
-     * @since Android 1.0
-     */
-    public String group(int group) {
-        ensureMatch();
-        int from = matchOffsets[group * 2];
-        int to = matchOffsets[(group * 2) + 1];
-        if (from == -1 || to == -1) {
-            return null;
-        } else {
-            return input.substring(from, to);
-        }
-    }
-
-    /**
-     * Indicates whether the last match hit the end of the input.
-     * 
-     * @return true if (and only if) the last match hit the end of the input.
-     * @since Android 1.0
-     */
-    public boolean hitEnd() {
-        return NativeRegEx.hitEnd(nativePattern);
-    }
-    
-    /**
-     * Indicates whether more input might change a successful match into an
-     * unsuccessful one.
-     * 
-     * @return true if (and only if) more input might change a successful match
-     *         into an unsuccessful one.
-     * @since Android 1.0
-     */
-    public boolean requireEnd() {
-        return NativeRegEx.requireEnd(nativePattern);
-    }
-    
-    /**
      * Converts the current match into a separate {@link MatchResult} instance
      * that is independent from this matcher. The new object is unaffected when
      * the state of this matcher changes.
-     * 
+     *
      * @return the new {@code MatchResult}.
      * @throws IllegalStateException
      *             if no successful match has been made.
-     * @since Android 1.0
      */
     public MatchResult toMatchResult() {
         ensureMatch();
@@ -608,160 +580,146 @@
     }
 
     /**
-     * Appends a literal part of the input plus a replacement for the current
-     * match to a given {@link StringBuffer}. The literal part is exactly the
-     * part of the input between the previous match and the current match. The
-     * method can be used in conjunction with {@link #find()} and
-     * {@link #appendTail(StringBuffer)} to walk through the input and replace
-     * all occurrences of the {@code Pattern} with something else.
-     * 
-     * @param buffer
-     *            the {@code StringBuffer} to append to.
-     * @param replacement
-     *            the replacement text.
+     * Determines whether this matcher has anchoring bounds enabled or not. When
+     * anchoring bounds are enabled, the start and end of the input match the
+     * '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
+     * by default.
+     *
+     * @param value
+     *            the new value for anchoring bounds.
      * @return the {@code Matcher} itself.
-     * @throws IllegalStateException
-     *             if no successful match has been made.
-     * @since Android 1.0
      */
-    public Matcher appendReplacement(StringBuffer buffer, String replacement)
-            throws IllegalStateException {
-        
-        buffer.append(input.substring(appendPos, start()));
-        appendEvaluated(buffer, replacement);
-        appendPos = end();
-        
+    public Matcher useAnchoringBounds(boolean value) {
+        anchoringBounds = value;
+        NativeRegEx.useAnchoringBounds(nativePattern, value);
         return this;
     }
 
     /**
-     * Appends the (unmatched) remainder of the input to the given
-     * {@link StringBuffer}. The method can be used in conjunction with
-     * {@link #find()} and {@link #appendReplacement(StringBuffer, String)} to
-     * walk through the input and replace all matches of the {@code Pattern}
-     * with something else.
-     * 
-     * @param buffer
-     *            the {@code StringBuffer} to append to.
-     * @return the {@code StringBuffer}.
+     * Indicates whether this matcher has anchoring bounds enabled. When
+     * anchoring bounds are enabled, the start and end of the input match the
+     * '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
+     * by default.
+     *
+     * @return true if (and only if) the {@code Matcher} uses anchoring bounds.
+     */
+    public boolean hasAnchoringBounds() {
+        return anchoringBounds;
+    }
+
+    /**
+     * Determines whether this matcher has transparent bounds enabled or not.
+     * When transparent bounds are enabled, the parts of the input outside the
+     * region are subject to lookahead and lookbehind, otherwise they are not.
+     * Transparent bounds are disabled by default.
+     *
+     * @param value
+     *            the new value for transparent bounds.
+     * @return the {@code Matcher} itself.
+     */
+    public Matcher useTransparentBounds(boolean value) {
+        transparentBounds = value;
+        NativeRegEx.useTransparentBounds(nativePattern, value);
+        return this;
+    }
+
+    /**
+     * Makes sure that a successful match has been made. Is invoked internally
+     * from various places in the class.
+     *
      * @throws IllegalStateException
      *             if no successful match has been made.
-     * @since Android 1.0
      */
-    public StringBuffer appendTail(StringBuffer buffer) {
-        if (appendPos < regionEnd) {
-            buffer.append(input.substring(appendPos, regionEnd));
+    private void ensureMatch() {
+        if (!matchFound) {
+            throw new IllegalStateException("No successful match so far");
         }
-        
-        return buffer;
     }
 
     /**
-     * Internal helper method to append a given string to a given string buffer.
-     * If the string contains any references to groups, these are replaced by
-     * the corresponding group's contents.
-     * 
-     * @param buffer
-     *            the string buffer.
-     * @param s
-     *            the string to append.
+     * Indicates whether this matcher has transparent bounds enabled. When
+     * transparent bounds are enabled, the parts of the input outside the region
+     * are subject to lookahead and lookbehind, otherwise they are not.
+     * Transparent bounds are disabled by default.
+     *
+     * @return true if (and only if) the {@code Matcher} uses anchoring bounds.
      */
-    private void appendEvaluated(StringBuffer buffer, String s) {
-        boolean escape = false;
-        boolean dollar = false;
-        
-        for (int i = 0; i < s.length(); i++) {
-            char c = s.charAt(i);
-            if (c == '\\' && !escape) {
-                escape = true;
-            } else if (c == '$' && !escape) {
-                dollar = true;
-            } else if (c >= '0' && c <= '9' && dollar) {
-                buffer.append(group(c - '0'));
-                dollar = false;
-            } else {
-                buffer.append(c);
-                dollar = false;
-                escape = false;
-            }
-        }
-        
-        // This seemingly stupid piece of code reproduces a JDK bug. 
-        if (escape) {
-            throw new ArrayIndexOutOfBoundsException(s.length());
-        }
+    public boolean hasTransparentBounds() {
+        return transparentBounds;
     }
-    
+
     /**
-     * Replaces all occurrences of this matcher's pattern in the input with a
-     * given string.
-     * 
-     * @param replacement
-     *            the replacement text.
-     * @return the modified input string.
-     * @since Android 1.0
+     * Returns this matcher's region start, that is, the first character that is
+     * considered for a match.
+     *
+     * @return the start of the region.
      */
-    public String replaceAll(String replacement) {
-        StringBuffer buffer = new StringBuffer(input.length());
-        
-        findPos = 0;
-        appendPos = 0;
+    public int regionStart() {
+        return regionStart;
+    }
+
+    /**
+     * Returns this matcher's region end, that is, the first character that is
+     * not considered for a match.
+     *
+     * @return the end of the region.
+     */
+    public int regionEnd() {
+        return regionEnd;
+    }
+
+    /**
+     * Indicates whether more input might change a successful match into an
+     * unsuccessful one.
+     * 
+     * @return true if (and only if) more input might change a successful match
+     *         into an unsuccessful one.
+     */
+    public boolean requireEnd() {
+        return NativeRegEx.requireEnd(nativePattern);
+    }
+
+    /**
+     * Indicates whether the last match hit the end of the input.
+     *
+     * @return true if (and only if) the last match hit the end of the input.
+     */
+    public boolean hitEnd() {
+        return NativeRegEx.hitEnd(nativePattern);
+    }
+
+    /**
+     * Sets a new pattern for the {@code Matcher}. Results of a previous find
+     * get lost. The next attempt to find an occurrence of the {@link Pattern}
+     * in the string will start at the beginning of the input.
+     *
+     * @param pattern
+     *            the new {@code Pattern}.
+     *
+     * @return the {@code Matcher} itself.
+     */
+    public Matcher usePattern(Pattern pattern) {
+        if (pattern == null) {
+            throw new IllegalArgumentException();
+        }
+
+        this.pattern = pattern;
+
+        if (nativePattern != 0) {
+            NativeRegEx.close(nativePattern);
+        }
+        nativePattern = NativeRegEx.clone(pattern.mNativePattern);
+
+        if (input != null) {
+            NativeRegEx.setText(nativePattern, input);
+            NativeRegEx.setRegion(nativePattern, regionStart, regionEnd);
+            NativeRegEx.useAnchoringBounds(nativePattern, anchoringBounds);
+            NativeRegEx.useTransparentBounds(nativePattern, transparentBounds);
+        }
+
+        matchOffsets = new int[(this.pattern.mGroupCount + 1) * 2];
         matchFound = false;
-        searching = false;
-        
-        while (find()) {
-            appendReplacement(buffer, replacement);
-        }
-        
-        return appendTail(buffer).toString();
-    }
-
-    /**
-     * Replaces the first occurrence of this matcher's pattern in the input with
-     * a given string.
-     * 
-     * @param replacement
-     *            the replacement text.
-     * @return the modified input string.
-     * @since Android 1.0
-     */
-    public String replaceFirst(String replacement) {
-        StringBuffer buffer = new StringBuffer(input.length());
-
-        findPos = 0;
-        appendPos = 0;
-        matchFound = false;
-        searching = false;
-        
-        if (find()) {
-            appendReplacement(buffer, replacement);
-        }
-        
-        return appendTail(buffer).toString();
-    }
-
-    /**
-     * Returns a replacement string for the given one that has all backslashes
-     * and dollar signs escaped.
-     * 
-     * @param s
-     *            the input string.
-     * @return the input string, with all backslashes and dollar signs having
-     *         been escaped.
-     * @since Android 1.0
-     */
-    public static String quoteReplacement(String s) {
-        StringBuffer buffer = new StringBuffer(s.length());
-        
-        for (int i = 0; i < s.length(); i++) {
-            char c = s.charAt(i);
-            if (c == '\\' || c == '$') {
-                buffer.append('\\');
-            }
-            buffer.append(c);
-        }
-        
-        return buffer.toString();
+        return this;
     }
 
     @Override
diff --git a/libcore/regex/src/main/java/java/util/regex/Pattern.java b/libcore/regex/src/main/java/java/util/regex/Pattern.java
index 2c71de1..db3bc21 100644
--- a/libcore/regex/src/main/java/java/util/regex/Pattern.java
+++ b/libcore/regex/src/main/java/java/util/regex/Pattern.java
@@ -47,7 +47,7 @@
  *     boolean b2 = Pattern.matches("Hello, A[a-z]*!", "Hello, Robot!");   // false
  * </pre>
  * <p/>
- * Please consult the <a href="package-summary.html">package documentation</a> for an
+ * Please consult the <a href="package.html">package documentation</a> for an
  * overview of the regular expression syntax used in this class as well as
  * Android-specific implementation details.
  * 
@@ -61,8 +61,6 @@
     /**
      * This constant specifies that a pattern matches Unix line endings ('\n')
      * only against the '.', '^', and '$' meta characters.
-     * 
-     * @since Android 1.0
      */
     public static final int UNIX_LINES = 0x01;
 
@@ -76,8 +74,6 @@
      * constant. So if case insensitivity is enabled, this automatically extends
      * to all Unicode characters. The {@code UNICODE_CASE} constant itself has
      * no special consequences.
-     * 
-     * @since Android 1.0
      */
     public static final int CASE_INSENSITIVE = 0x02;
 
@@ -85,8 +81,6 @@
      * This constant specifies that a {@code Pattern} may contain whitespace or
      * comments. Otherwise comments and whitespace are taken as literal
      * characters.
-     * 
-     * @since Android 1.0
      */
     public static final int COMMENTS = 0x04;
 
@@ -94,24 +88,18 @@
      * This constant specifies that the meta characters '^' and '$' match only
      * the beginning and end end of an input line, respectively. Normally, they
      * match the beginning and the end of the complete input.
-     * 
-     * @since Android 1.0
      */
     public static final int MULTILINE = 0x08;
 
     /**
      * This constant specifies that the whole {@code Pattern} is to be taken
      * literally, that is, all meta characters lose their meanings.
-     * 
-     * @since Android 1.0
      */
     public static final int LITERAL = 0x10;
 
     /**
      * This constant specifies that the '.' meta character matches arbitrary
      * characters, including line endings, which is normally not the case.
-     * 
-     * @since Android 1.0
      */
     public static final int DOTALL = 0x20;
 
@@ -126,8 +114,6 @@
      * constant. So if case insensitivity is enabled, this automatically extends
      * to all Unicode characters. The {@code UNICODE_CASE} constant then has no
      * special consequences.
-     * 
-     * @since Android 1.0
      */
     public static final int UNICODE_CASE = 0x40;
 
@@ -135,8 +121,6 @@
      * This constant specifies that a character in a {@code Pattern} and a
      * character in the input string only match if they are canonically
      * equivalent. It is (currently) not supported in Android.
-     * 
-     * @since Android 1.0
      */
     public static final int CANON_EQ = 0x80;
 
@@ -159,24 +143,144 @@
      * Holds the number of groups in the pattern.
      */
     transient int mGroupCount;
-    
+
+
     /**
-     * Compiles a regular expression, creating a new Pattern instance in the
-     * process. This is actually a convenience method that calls {@link
-     * #compile(String, int)} with a {@code flags} value of zero.
-     * 
-     * @param pattern
-     *            the regular expression.
-     * 
-     * @return the new {@code Pattern} instance.
-     * 
-     * @throws PatternSyntaxException
-     *             if the regular expression is syntactically incorrect.
-     * 
-     * @since Android 1.0
+     * Returns a {@link Matcher} for the {@code Pattern} and a given input. The
+     * {@code Matcher} can be used to match the {@code Pattern} against the
+     * whole input, find occurrences of the {@code Pattern} in the input, or
+     * replace parts of the input.
+     *
+     * @param input
+     *            the input to process.
+     *
+     * @return the resulting {@code Matcher}.
      */
-    public static Pattern compile(String pattern) throws PatternSyntaxException {
-        return new Pattern(pattern, 0);
+    public Matcher matcher(CharSequence input) {
+        return new Matcher(this, input);
+    }
+
+    /**
+     * Splits the given input sequence at occurrences of this {@code Pattern}.
+     *
+     * <p>If this {@code Pattern} does not occur in the input, the result is an
+     * array containing the input (converted from a {@code CharSequence} to
+     * a {@code String}).
+     *
+     * <p>Otherwise, the {@code limit} parameter controls the contents of the
+     * returned array as described below.
+     *
+     * @param inputSeq
+     *            the input sequence.
+     * @param limit
+     *            Determines the maximum number of entries in the resulting
+     *            array, and the treatment of trailing empty strings.
+     *            <ul>
+     *            <li>For n &gt; 0, the resulting array contains at most n
+     *            entries. If this is fewer than the number of matches, the
+     *            final entry will contain all remaining input.
+     *            <li>For n &lt; 0, the length of the resulting array is
+     *            exactly the number of occurrences of the {@code Pattern}
+     *            plus one for the text after the final separator.
+     *            All entries are included.
+     *            <li>For n == 0, the result is as for n &lt; 0, except
+     *            trailing empty strings will not be returned. (Note that
+     *            the case where the input is itself an empty string is
+     *            special, as described above, and the limit parameter does
+     *            not apply there.)
+     *            </ul>
+     *
+     * @return the resulting array.
+     */
+    public String[] split(CharSequence inputSeq, int limit) {
+        if (inputSeq.length() == 0) {
+            // Unlike Perl, which considers the result of splitting the empty
+            // string to be the empty array, Java returns an array containing
+            // the empty string.
+            return new String[] { "" };
+        }
+
+        int maxLength = limit <= 0 ? Integer.MAX_VALUE : limit;
+
+        String input = inputSeq.toString();
+        ArrayList<String> list = new ArrayList<String>();
+
+        Matcher matcher = new Matcher(this, inputSeq);
+        int savedPos = 0;
+
+        // Add text preceding each occurrence, if enough space.
+        while(matcher.find() && list.size() + 1 < maxLength) {
+            list.add(input.substring(savedPos, matcher.start()));
+            savedPos = matcher.end();
+        }
+
+        // Add trailing text if enough space.
+        if (list.size() < maxLength) {
+            if (savedPos < input.length()) {
+                list.add(input.substring(savedPos));
+            } else {
+                list.add("");
+            }
+        }
+
+        // Remove trailing empty matches in the limit == 0 case.
+        if (limit == 0) {
+            int i = list.size() - 1;
+            while (i >= 0 && "".equals(list.get(i))) {
+                list.remove(i);
+                i--;
+            }
+        }
+
+        return list.toArray(new String[list.size()]);
+    }
+
+    /**
+     * Splits a given input around occurrences of a regular expression. This is
+     * a convenience method that is equivalent to calling the method
+     * {@link #split(java.lang.CharSequence, int)} with a limit of 0.
+     *
+     * @param input
+     *            the input sequence.
+     *
+     * @return the resulting array.
+     */
+    public String[] split(CharSequence input) {
+        return split(input, 0);
+    }
+
+    /**
+     * Returns the regular expression that was compiled into this
+     * {@code Pattern}.
+     *
+     * @return the regular expression.
+     */
+    public String pattern() {
+        return pattern;
+    }
+
+    @Override
+    public String toString() {
+        return pattern;
+    }
+
+    /**
+     * Returns the flags that have been set for this {@code Pattern}.
+     *
+     * @return the flags that have been set. A combination of the constants
+     *         defined in this class.
+     *
+     * @see #CANON_EQ
+     * @see #CASE_INSENSITIVE
+     * @see #COMMENTS
+     * @see #DOTALL
+     * @see #LITERAL
+     * @see #MULTILINE
+     * @see #UNICODE_CASE
+     * @see #UNIX_LINES
+     */
+    public int flags() {
+        return flags;
     }
 
     /**
@@ -208,8 +312,6 @@
      * @see #MULTILINE
      * @see #UNICODE_CASE
      * @see #UNIX_LINES
-     * 
-     * @since Android 1.0
      */
     public static Pattern compile(String pattern, int flags) throws PatternSyntaxException {
         return new Pattern(pattern, flags);
@@ -238,7 +340,24 @@
         
         compileImpl(pattern, flags);
     }
-    
+
+    /**
+     * Compiles a regular expression, creating a new Pattern instance in the
+     * process. This is actually a convenience method that calls {@link
+     * #compile(String, int)} with a {@code flags} value of zero.
+     *
+     * @param pattern
+     *            the regular expression.
+     *
+     * @return the new {@code Pattern} instance.
+     *
+     * @throws PatternSyntaxException
+     *             if the regular expression is syntactically incorrect.
+     */
+    public static Pattern compile(String pattern) {
+        return new Pattern(pattern, 0);
+    }
+
     /**
      * Compiles the given regular expression using the given flags. Used
      * internally only.
@@ -266,56 +385,6 @@
     }
 
     /**
-     * Returns the regular expression that was compiled into this
-     * {@code Pattern}.
-     * 
-     * @return the regular expression.
-     * 
-     * @since Android 1.0
-     */
-    public String pattern() {
-        return pattern;
-    }
-    
-    /**
-     * Returns the flags that have been set for this {@code Pattern}.
-     *  
-     * @return the flags that have been set. A combination of the constants
-     *         defined in this class.
-     *         
-     * @see #CANON_EQ
-     * @see #CASE_INSENSITIVE
-     * @see #COMMENTS
-     * @see #DOTALL
-     * @see #LITERAL
-     * @see #MULTILINE
-     * @see #UNICODE_CASE
-     * @see #UNIX_LINES
-     *         
-     * @since Android 1.0
-     */
-    public int flags() {
-        return flags;
-    }
-
-    /**
-     * Returns a {@link Matcher} for the {@code Pattern} and a given input. The
-     * {@code Matcher} can be used to match the {@code Pattern} against the
-     * whole input, find occurrences of the {@code Pattern} in the input, or
-     * replace parts of the input.
-     * 
-     * @param input
-     *            the input to process.
-     * 
-     * @return the resulting {@code Matcher}.
-     * 
-     * @since Android 1.0
-     */
-    public Matcher matcher(CharSequence input) {
-        return new Matcher(this, input);
-    }
-
-    /**
      * Tries to match a given regular expression against a given input. This is
      * actually nothing but a convenience method that compiles the regular
      * expression into a {@code Pattern}, builds a {@link Matcher} for it, and
@@ -332,107 +401,12 @@
      * 
      * @see Pattern#compile(java.lang.String, int)
      * @see Matcher#matches()
-     * 
-     * @since Android 1.0
      */
-    static public boolean matches(String regex, CharSequence input) {
+    public static boolean matches(String regex, CharSequence input) {
         return new Matcher(new Pattern(regex, 0), input).matches();
     }
 
     /**
-     * Splits a given input around occurrences of a regular expression. This is
-     * a convenience method that is equivalent to calling the method
-     * {@link #split(java.lang.CharSequence, int)} with a limit of 0.
-     * 
-     * @param input
-     *            the input sequence.
-     * 
-     * @return the resulting array.
-     * 
-     * @since Android 1.0
-     */
-    public String[] split(CharSequence input) {
-        return split(input, 0);
-    }
-
-    /**
-     * Splits the given input sequence at occurrences of this {@code Pattern}.
-     * 
-     * If this {@code Pattern} does not occur in the input, the result is an
-     * array containing the input (converted from a {@code CharSequence} to
-     * a {@code String}).
-     * 
-     * Otherwise, the {@code limit} parameter controls the contents of the
-     * returned array as described below.
-     * 
-     * @param inputSeq
-     *            the input sequence.
-     * @param limit
-     *            Determines the maximum number of entries in the resulting
-     *            array, and the treatment of trailing empty strings.
-     *            <ul>
-     *            <li>For n &gt; 0, the resulting array contains at most n
-     *            entries. If this is fewer than the number of matches, the
-     *            final entry will contain all remaining input.
-     *            <li>For n &lt; 0, the length of the resulting array is
-     *            exactly the number of occurrences of the {@code Pattern}
-     *            plus one for the text after the final separator.
-     *            All entries are included.
-     *            <li>For n == 0, the result is as for n &lt; 0, except
-     *            trailing empty strings will not be returned. (Note that
-     *            the case where the input is itself an empty string is
-     *            special, as described above, and the limit parameter does
-     *            not apply there.)
-     *            </ul>
-     * 
-     * @return the resulting array.
-     * 
-     * @since Android 1.0
-     */
-    public String[] split(CharSequence inputSeq, int limit) {
-        if (inputSeq.length() == 0) {
-            // Unlike Perl, which considers the result of splitting the empty
-            // string to be the empty array, Java returns an array containing
-            // the empty string.
-            return new String[] { "" };
-        }
-        
-        int maxLength = limit <= 0 ? Integer.MAX_VALUE : limit;
-
-        String input = inputSeq.toString();
-        ArrayList<String> list = new ArrayList<String>();
-
-        Matcher matcher = new Matcher(this, inputSeq);
-        int savedPos = 0;
-        
-        // Add text preceding each occurrence, if enough space.
-        while(matcher.find() && list.size() + 1 < maxLength) {
-            list.add(input.substring(savedPos, matcher.start()));
-            savedPos = matcher.end();
-        }
-        
-        // Add trailing text if enough space.
-        if (list.size() < maxLength) {
-            if (savedPos < input.length()) {
-                list.add(input.substring(savedPos));
-            } else {
-                list.add("");
-            }
-        }
-        
-        // Remove trailing empty matches in the limit == 0 case.
-        if (limit == 0) {
-            int i = list.size() - 1;
-            while (i >= 0 && "".equals(list.get(i))) {
-                list.remove(i);
-                i--;
-            }
-        }
-        
-        return list.toArray(new String[list.size()]);
-    }
-
-    /**
      * Quotes a given string using "\Q" and "\E", so that all other
      * meta-characters lose their special meaning. If the string is used for a
      * {@code Pattern} afterwards, it can only be matched literally.
@@ -441,27 +415,20 @@
      *            the string to quote.
      * 
      * @return the quoted string.
-     * 
-     * @since Android 1.0
      */
     public static String quote(String s) {
-        StringBuffer sb = new StringBuffer().append("\\Q");
+        StringBuilder sb = new StringBuilder().append("\\Q"); //$NON-NLS-1$
         int apos = 0;
         int k;
-        while ((k = s.indexOf("\\E", apos)) >= 0) {
-            sb.append(s.substring(apos, k + 2)).append("\\\\E\\Q");
+        while ((k = s.indexOf("\\E", apos)) >= 0) { //$NON-NLS-1$
+            sb.append(s.substring(apos, k + 2)).append("\\\\E\\Q"); //$NON-NLS-1$
             apos = k + 2;
         }
 
-        return sb.append(s.substring(apos)).append("\\E").toString();
+        return sb.append(s.substring(apos)).append("\\E").toString(); //$NON-NLS-1$
     }
     
     @Override
-    public String toString() {
-        return pattern;
-    }
-
-    @Override
     protected void finalize() throws Throwable {
         try {
             if (mNativePattern != 0) {
@@ -474,7 +441,7 @@
     }
 
     /**
-     * Provides serialization support
+     * Serialization support
      */
     private void readObject(java.io.ObjectInputStream s)
             throws java.io.IOException, ClassNotFoundException {
diff --git a/libcore/regex/src/main/java/java/util/regex/PatternSyntaxException.java b/libcore/regex/src/main/java/java/util/regex/PatternSyntaxException.java
index e4d5abd..d59bdd4 100644
--- a/libcore/regex/src/main/java/java/util/regex/PatternSyntaxException.java
+++ b/libcore/regex/src/main/java/java/util/regex/PatternSyntaxException.java
@@ -1,17 +1,18 @@
 /*
- * 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,
- * 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.util.regex;
@@ -25,24 +26,22 @@
  * 
  * @see Pattern#compile(String)
  * @see Pattern#compile(java.lang.String,int)
- * 
- * @since Android 1.0
  */
 public class PatternSyntaxException extends IllegalArgumentException {
     
     private static final long serialVersionUID = -3864639126226059218L;
-    
-    /**
-     * Holds the syntactically incorrect regular expression, or null if the
-     * regular expression is not known.
-     */
-    private String pattern;
 
     /**
      * Holds the description of the syntax error, or null if the description is
      * not known.
      */
-    private String description;
+    private String desc;
+
+    /**
+     * Holds the syntactically incorrect regular expression, or null if the
+     * regular expression is not known.
+     */
+    private String pattern;
 
     /**
      * Holds the index around which the error occured, or -1, in case it is
@@ -63,11 +62,10 @@
      * @param index
      *            the character index around which the error occurred, or -1 if
      *            the index is not known.
-     * @since Android 1.0
      */
     public PatternSyntaxException(String description, String pattern, int index) {
+        this.desc = description;
         this.pattern = pattern;
-        this.description = description;
         this.index = index;
     }
 
@@ -76,7 +74,6 @@
      * 
      * @return the regular expression.
      * 
-     * @since Android 1.0
      */
     public String getPattern() {
         return pattern;
@@ -88,16 +85,15 @@
      * original regular expression, and the index at which the error occured.
      * 
      * @return the error message.
-     * 
-     * @since Android 1.0
      */
     @Override
     public String getMessage() {
+        // BEGIN android-changed
         StringBuilder builder = new StringBuilder("Syntax error");
         
-        if (description != null) {
+        if (desc != null) {
             builder.append(' ');
-            builder.append(description);
+            builder.append(desc);
         }
 
         if (index >= 0) {
@@ -118,6 +114,7 @@
         }
         
         return builder.toString();
+        // END android-changed
     }
 
     /**
@@ -125,10 +122,9 @@
      * description is not known.
      * 
      * @return the description.
-     * @since Android 1.0
      */
     public String getDescription() {
-        return description;
+        return desc;
     }
 
     /**
@@ -137,10 +133,8 @@
      * 
      * @return the index.
      * 
-     * @since Android 1.0
      */
     public int getIndex() {
         return index;
     }
-
 }
diff --git a/libcore/security/src/main/java/java/security/AccessControlException.java b/libcore/security/src/main/java/java/security/AccessControlException.java
index 1710e77..ae23ab1 100644
--- a/libcore/security/src/main/java/java/security/AccessControlException.java
+++ b/libcore/security/src/main/java/java/security/AccessControlException.java
@@ -15,18 +15,11 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code AccessControlException} is thrown if the access control infrastructure
  * denies protected access due to missing permissions.
- * 
- * @since Android 1.0
  */
 public class AccessControlException extends SecurityException {
 
@@ -37,10 +30,9 @@
     /**
      * Constructs a new instance of {@code AccessControlException} with the
      * given message.
-     * 
+     *
      * @param message
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public AccessControlException(String message) {
         super(message);
@@ -49,12 +41,11 @@
     /**
      * Constructs a new instance of {@code AccessControlException} with the
      * given message and the requested {@code Permission} which was not granted.
-     * 
+     *
      * @param message
      *            the detail message for the exception.
      * @param perm
      *            the requested {@code Permission} which was not granted.
-     * @since Android 1.0
      */
     public AccessControlException(String message, Permission perm) {
         super(message);
@@ -64,9 +55,8 @@
     /**
      * Returns the requested permission that caused this Exception or {@code
      * null} if there is no corresponding {@code Permission}.
-     * 
+     *
      * @return the requested permission that caused this Exception, maybe {@code null}.
-     * @since Android 1.0
      */
     public Permission getPermission() {
         return perm;
diff --git a/libcore/security/src/main/java/java/security/AlgorithmParameterGenerator.java b/libcore/security/src/main/java/java/security/AlgorithmParameterGenerator.java
index 199efa1..6814813 100644
--- a/libcore/security/src/main/java/java/security/AlgorithmParameterGenerator.java
+++ b/libcore/security/src/main/java/java/security/AlgorithmParameterGenerator.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.security.spec.AlgorithmParameterSpec;
@@ -30,8 +25,6 @@
 /**
  * {@code AlgorithmParameterGenerator} is an engine class which is capable of
  * generating parameters for the algorithm it was initialized with.
- * 
- * @since Android 1.0
  */
 public class AlgorithmParameterGenerator {
 
@@ -56,14 +49,13 @@
     /**
      * Constructs a new instance of {@code AlgorithmParameterGenerator} with the
      * given arguments.
-     * 
+     *
      * @param paramGenSpi
      *            a concrete implementation, this engine instance delegates to.
      * @param provider
      *            the provider.
      * @param algorithm
      *            the name of the algorithm.
-     * @since Android 1.0
      */
     protected AlgorithmParameterGenerator(
             AlgorithmParameterGeneratorSpi paramGenSpi, Provider provider,
@@ -75,9 +67,8 @@
 
     /**
      * Returns the name of the algorithm.
-     * 
+     *
      * @return the name of the algorithm.
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -95,7 +86,6 @@
      *             if the specified algorithm is not available.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static AlgorithmParameterGenerator getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -127,7 +117,6 @@
      *             if the specified provider is not available.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static AlgorithmParameterGenerator getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
@@ -157,7 +146,6 @@
      *             if the specified algorithm is not available.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static AlgorithmParameterGenerator getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
@@ -178,10 +166,9 @@
     /**
      * Returns the provider associated with this {@code
      * AlgorithmParameterGenerator}.
-     * 
+     *
      * @return the provider associated with this {@code
      *         AlgorithmParameterGenerator}.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -191,10 +178,9 @@
      * Initializes this {@code AlgorithmParameterGenerator} with the given size.
      * The default parameter set and a default {@code SecureRandom} instance
      * will be used.
-     * 
+     *
      * @param size
      *            the size (in number of bits).
-     * @since Android 1.0
      */
     public final void init(int size) {
         spiImpl.engineInit(size, randm);
@@ -204,12 +190,11 @@
      * Initializes this {@code AlgorithmParameterGenerator} with the given size
      * and the given {@code SecureRandom}. The default parameter set will be
      * used.
-     * 
+     *
      * @param size
      *            the size (in number of bits).
      * @param random
      *            the source of randomness.
-     * @since Android 1.0
      */
     public final void init(int size, SecureRandom random) {
         spiImpl.engineInit(size, random);
@@ -219,12 +204,11 @@
      * Initializes this {@code AlgorithmParameterGenerator} with the given {@code
      * AlgorithmParameterSpec}. A default {@code SecureRandom} instance will be
      * used.
-     * 
+     *
      * @param genParamSpec
      *            the parameters to use.
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters are not supported.
-     * @since Android 1.0
      */
     public final void init(AlgorithmParameterSpec genParamSpec)
             throws InvalidAlgorithmParameterException {
@@ -234,14 +218,13 @@
     /**
      * Initializes this {@code AlgorithmParameterGenerator} with the given
      * {@code AlgorithmParameterSpec} and the given {@code SecureRandom}.
-     * 
+     *
      * @param genParamSpec
      *            the parameters to use.
      * @param random
      *            the source of randomness.
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters are not supported.
-     * @since Android 1.0
      */
     public final void init(AlgorithmParameterSpec genParamSpec,
             SecureRandom random) throws InvalidAlgorithmParameterException {
@@ -251,11 +234,10 @@
     /**
      * Computes and returns {@code AlgorithmParameters} for this generator's
      * algorithm.
-     * 
+     *
      * @return {@code AlgorithmParameters} for this generator's algorithm.
-     * @since Android 1.0
      */
     public final AlgorithmParameters generateParameters() {
         return spiImpl.engineGenerateParameters();
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java b/libcore/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java
index 9ddff23..44b3def 100644
--- a/libcore/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java
+++ b/libcore/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.security.spec.AlgorithmParameterSpec;
@@ -29,14 +24,11 @@
  * (SPI) definition for {@code AlgorithmParameterGenerator}.
  * 
  * @see AlgorithmParameterGenerator
- * @since Android 1.0
  */
 public abstract class AlgorithmParameterGeneratorSpi {
 
     /**
      * Constructs a new instance of {@code AlgorithmParameterGeneratorSpi} .
-     * 
-     * @since Android 1.0
      */
     public AlgorithmParameterGeneratorSpi() {
     }
@@ -45,26 +37,24 @@
      * Initializes this {@code AlgorithmParameterGeneratorSpi} with the given
      * size and the given {@code SecureRandom}. The default parameter set
      * will be used.
-     * 
+     *
      * @param size
      *            the size (in number of bits).
      * @param random
      *            the source of randomness.
-     * @since Android 1.0
      */
     protected abstract void engineInit(int size, SecureRandom random);
 
     /**
      * Initializes this {@code AlgorithmParameterGeneratorSpi} with the given
      * {@code AlgorithmParameterSpec} and the given {@code SecureRandom}.
-     * 
+     *
      * @param genParamSpec
      *            the parameters to use.
      * @param random
      *            the source of randomness.
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters are not supported.
-     * @since Android 1.0
      */
     protected abstract void engineInit(AlgorithmParameterSpec genParamSpec,
             SecureRandom random) throws InvalidAlgorithmParameterException;
@@ -72,9 +62,8 @@
     /**
      * Computes and returns {@code AlgorithmParameters} for this generator's
      * algorithm.
-     * 
+     *
      * @return {@code AlgorithmParameters} for this generator's algorithm.
-     * @since Android 1.0
      */
     protected abstract AlgorithmParameters engineGenerateParameters();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/AlgorithmParameters.java b/libcore/security/src/main/java/java/security/AlgorithmParameters.java
index aaefe1b..d659200 100644
--- a/libcore/security/src/main/java/java/security/AlgorithmParameters.java
+++ b/libcore/security/src/main/java/java/security/AlgorithmParameters.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.IOException;
@@ -33,8 +28,6 @@
 /**
  * {@code AlgorithmParameters} is an engine class which provides algorithm
  * parameters.
- * 
- * @since Android 1.0
  */
 public class AlgorithmParameters {
     /**
@@ -70,20 +63,16 @@
     /**
      * Constructs a new instance of {@code AlgorithmParameters} with the given
      * arguments.
-     * 
+     *
      * @param algPramSpi
      *            the concrete implementation.
      * @param provider
      *            the security provider.
      * @param algorithm
      *            the name of the algorithm.
-     * @since Android 1.0
      */
     protected AlgorithmParameters(AlgorithmParametersSpi algPramSpi,
             Provider provider, String algorithm) {
-        // BEGIN android-note
-        // renamed parameter
-        // END android-note
         this.provider = provider;
         this.algorithm = algorithm;
         this.spiImpl = algPramSpi;
@@ -92,7 +81,7 @@
     /**
      * Returns a new instance of {@code AlgorithmParameters} for the specified
      * algorithm.
-     * 
+     *
      * @param algorithm
      *            the name of the algorithm to use.
      * @return a new instance of {@code AlgorithmParameters} for the specified
@@ -101,7 +90,6 @@
      *             if the specified algorithm is not available.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static AlgorithmParameters getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -118,7 +106,7 @@
     /**
      * Returns a new instance of {@code AlgorithmParameters} from the specified
      * provider for the specified algorithm.
-     * 
+     *
      * @param algorithm
      *            the name of the algorithm to use.
      * @param provider
@@ -133,7 +121,6 @@
      *             if {@code provider} is {@code null} or of length zero.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static AlgorithmParameters getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
@@ -152,7 +139,7 @@
     /**
      * Returns a new instance of {@code AlgorithmParameters} from the specified
      * provider for the specified algorithm.
-     * 
+     *
      * @param algorithm
      *            the name of the algorithm to use.
      * @param provider
@@ -165,7 +152,6 @@
      *             if {@code algorithm} is {@code null}.
      * @throws IllegalArgumentException
      *             if {@code provider} is {@code null}.
-     * @since Android 1.0
      */
     public static AlgorithmParameters getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
@@ -184,9 +170,8 @@
 
     /**
      * Returns the provider associated with this {@code AlgorithmParameters}.
-     * 
+     *
      * @return the provider associated with this {@code AlgorithmParameters}.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -194,9 +179,8 @@
 
     /**
      * Returns the name of the algorithm.
-     * 
+     *
      * @return the name of the algorithm.
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -205,14 +189,13 @@
     /**
      * Initializes this {@code AlgorithmParameters} with the specified {@code
      * AlgorithmParameterSpec}.
-     * 
+     *
      * @param paramSpec
      *            the parameter specification.
      * @throws InvalidParameterSpecException
      *             if this {@code AlgorithmParameters} has already been
      *             initialized or the given {@code paramSpec} is not appropriate
      *             for initializing this {@code AlgorithmParameters}.
-     * @since Android 1.0
      */
     public final void init(AlgorithmParameterSpec paramSpec)
             throws InvalidParameterSpecException {
@@ -228,13 +211,12 @@
      * Initializes this {@code AlgorithmParameters} with the specified {@code
      * byte[]} using the default decoding format for parameters. The default
      * encoding format is ASN.1.
-     * 
+     *
      * @param params
      *            the encoded parameters.
      * @throws IOException
      *             if this {@code AlgorithmParameters} has already been
      *             initialized, or the parameter could not be encoded.
-     * @since Android 1.0
      */
     public final void init(byte[] params) throws IOException {
         if (initialized) {
@@ -247,7 +229,7 @@
     /**
      * Initializes this {@code AlgorithmParameters} with the specified {@code
      * byte[]} using the specified decoding format.
-     * 
+     *
      * @param params
      *            the encoded parameters.
      * @param format
@@ -255,7 +237,6 @@
      * @throws IOException
      *             if this {@code AlgorithmParameters} has already been
      *             initialized, or the parameter could not be encoded.
-     * @since Android 1.0
      */
     public final void init(byte[] params, String format) throws IOException {
         if (initialized) {
@@ -268,7 +249,7 @@
     /**
      * Returns the {@code AlgorithmParameterSpec} for this {@code
      * AlgorithmParameters}.
-     * 
+     *
      * @param paramSpec
      *            the type of the parameter specification in which this
      *            parameters should be converted.
@@ -278,7 +259,6 @@
      *             if this {@code AlgorithmParameters} has already been
      *             initialized, or if this parameters could not be converted to
      *             the specified class.
-     * @since Android 1.0
      */
     public final <T extends AlgorithmParameterSpec> T getParameterSpec(Class<T> paramSpec)
             throws InvalidParameterSpecException {
@@ -292,12 +272,11 @@
     /**
      * Returns this {@code AlgorithmParameters} in their default encoding
      * format. The default encoding format is ASN.1.
-     * 
+     *
      * @return the encoded parameters.
      * @throws IOException
      *             if this {@code AlgorithmParameters} has already been
      *             initialized, or if this parameters could not be encoded.
-     * @since Android 1.0
      */
     public final byte[] getEncoded() throws IOException {
         if (!initialized) {
@@ -309,14 +288,13 @@
     /**
      * Returns this {@code AlgorithmParameters} in the specified encoding
      * format.
-     * 
+     *
      * @param format
      *            the name of the encoding format.
      * @return the encoded parameters.
      * @throws IOException
      *             if this {@code AlgorithmParameters} has already been
      *             initialized, or if this parameters could not be encoded.
-     * @since Android 1.0
      */
     public final byte[] getEncoded(String format) throws IOException {
         if (!initialized) {
@@ -328,10 +306,10 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * {@code AlgorithmParameters}.
-     * 
+     *
      * @return a printable representation for this {@code AlgorithmParameters}.
-     * @since Android 1.0
      */
+    @Override
     public final String toString() {
         if (!initialized) {
             return null;
diff --git a/libcore/security/src/main/java/java/security/AlgorithmParametersSpi.java b/libcore/security/src/main/java/java/security/AlgorithmParametersSpi.java
index 3bc8891..41b30bc 100644
--- a/libcore/security/src/main/java/java/security/AlgorithmParametersSpi.java
+++ b/libcore/security/src/main/java/java/security/AlgorithmParametersSpi.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.IOException;
@@ -37,14 +32,13 @@
     /**
      * Initializes this {@code AlgorithmParametersSpi} with the specified
      * {@code AlgorithmParameterSpec}.
-     * 
+     *
      * @param paramSpec
      *            the parameter specification.
      * @throws InvalidParameterSpecException
      *             if this {@code AlgorithmParametersSpi} has already been
      *             initialized or the given {@code paramSpec} is not appropriate
      *             for initializing this {@code AlgorithmParametersSpi}.
-     * @since Android 1.0
      */
     protected abstract void engineInit(AlgorithmParameterSpec paramSpec)
             throws InvalidParameterSpecException;
@@ -53,20 +47,19 @@
      * Initializes this {@code AlgorithmParametersSpi} with the specified
      * {@code byte[]} using the default decoding format for parameters. The
      * default encoding format is ASN.1.
-     * 
+     *
      * @param params
      *            the encoded parameters.
      * @throws IOException
      *             if this {@code AlgorithmParametersSpi} has already been
      *             initialized, or the parameter could not be encoded.
-     * @since Android 1.0
      */
     protected abstract void engineInit(byte[] params) throws IOException;
 
     /**
      * Initializes this {@code AlgorithmParametersSpi} with the specified
      * {@code byte[]} using the specified decoding format.
-     * 
+     *
      * @param params
      *            the encoded parameters.
      * @param format
@@ -74,7 +67,6 @@
      * @throws IOException
      *             if this {@code AlgorithmParametersSpi} has already been
      *             initialized, or the parameter could not be encoded.
-     * @since Android 1.0
      */
     protected abstract void engineInit(byte[] params, String format)
             throws IOException;
@@ -82,7 +74,7 @@
     /**
      * Returns the {@code AlgorithmParameterSpec} for this {@code
      * AlgorithmParametersSpi}.
-     * 
+     *
      * @param paramSpec
      *            the type of the parameter specification in which this
      *            parameters should be converted.
@@ -92,7 +84,6 @@
      *             if this {@code AlgorithmParametersSpi} has already been
      *             initialized, or if this parameters could not be converted to
      *             the specified class.
-     * @since Android 1.0
      */
     protected abstract <T extends AlgorithmParameterSpec> T engineGetParameterSpec(
             Class<T> paramSpec) throws InvalidParameterSpecException;
@@ -100,25 +91,23 @@
     /**
      * Returns the parameters in their default encoding format. The default
      * encoding format is ASN.1.
-     * 
+     *
      * @return the encoded parameters.
      * @throws IOException
      *             if this {@code AlgorithmParametersSpi} has already been
      *             initialized, or if this parameters could not be encoded.
-     * @since Android 1.0
      */
     protected abstract byte[] engineGetEncoded() throws IOException;
 
     /**
      * Returns the parameters in the specified encoding format.
-     * 
+     *
      * @param format
      *            the name of the encoding format.
      * @return the encoded parameters.
      * @throws IOException
      *             if this {@code AlgorithmParametersSpi} has already been
      *             initialized, or if this parameters could not be encoded.
-     * @since Android 1.0
      */
     protected abstract byte[] engineGetEncoded(String format)
             throws IOException;
@@ -126,11 +115,10 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * {@code AlgorithmParametersSpi}.
-     * 
+     *
      * @return a printable representation for this {@code
      *         AlgorithmParametersSpi}.
-     * @since Android 1.0
      */
     protected abstract String engineToString();
 
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/AllPermission.java b/libcore/security/src/main/java/java/security/AllPermission.java
index f4b8aad..c12bb27 100644
--- a/libcore/security/src/main/java/java/security/AllPermission.java
+++ b/libcore/security/src/main/java/java/security/AllPermission.java
@@ -22,11 +22,12 @@
  * {@code AllPermission} represents the permission to perform any operation.
  * Since its {@link #implies(Permission)} method always returns {@code true},
  * granting this permission is equivalent to disabling security.
- * 
- * @since Android 1.0
  */
 public final class AllPermission extends Permission {
 
+    /**
+     * @serial
+     */
     private static final long serialVersionUID = -2916474571451318075L;
 
     // Permission name
@@ -40,12 +41,11 @@
      * version is provided for class {@code Policy} so that it has a consistent
      * call pattern across all permissions. The name and action list are both
      * ignored.
-     * 
+     *
      * @param name
      *            ignored.
      * @param actions
      *            ignored.
-     * @since Android 1.0
      */
     public AllPermission(String name, String actions) {
         super(ALL_PERMISSIONS);
@@ -53,8 +53,6 @@
 
     /**
      * Constructs a new instance of {@code AllPermission}.
-     * 
-     * @since Android 1.0
      */
     public AllPermission() {
         super(ALL_PERMISSIONS);
@@ -65,15 +63,15 @@
      * equality and returns {@code true} if the specified object is equal,
      * {@code false} otherwise. To be equal, the given object needs to be an
      * instance of {@code AllPermission}.
-     * 
+     *
      * @param obj
      *            object to be compared for equality with this {@code
      *            AllPermission}.
      * @return {@code true} if the specified object is equal to this {@code
      *         AllPermission}, otherwise {@code false}.
-     * @since Android 1.0
      * @see #hashCode
      */
+    @Override
     public boolean equals(Object obj) {
         return (obj instanceof AllPermission);
     }
@@ -82,12 +80,12 @@
      * Returns the hash code value for this {@code AllPermission}. Returns the
      * same hash code for {@code AllPermission}s that are equal to each other as
      * required by the general contract of {@link Object#hashCode}.
-     * 
+     *
      * @return the hash code value for this {@code AllPermission}.
      * @see Object#equals(Object)
      * @see AllPermission#equals(Object)
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         return 1;
     }
@@ -96,10 +94,10 @@
      * Returns the actions associated with this {@code AllPermission}. Since
      * {@code AllPermission} objects allow all actions, this method returns
      * always the string "&lt;all actions&gt;".
-     * 
+     *
      * @return the actions associated with this {@code AllPermission}.
-     * @since Android 1.0
      */
+    @Override
     public String getActions() {
         return ALL_ACTIONS;
     }
@@ -107,12 +105,12 @@
     /**
      * Indicates whether the given permission is implied by this permission.
      * {@code AllPermission} objects imply all other permissions.
-     * 
+     *
      * @return always {@code true}.
      * @param permission
      *            the permission to check.
-     * @since Android 1.0
      */
+    @Override
     public boolean implies(Permission permission) {
         return true;
     }
@@ -120,10 +118,10 @@
     /**
      * Returns a new {@code PermissionCollection} for holding permissions of
      * this class.
-     * 
+     *
      * @return a new {@code PermissionCollection}.
-     * @since Android 1.0
      */
+    @Override
     public PermissionCollection newPermissionCollection() {
         return new AllPermissionCollection();
     }
diff --git a/libcore/security/src/main/java/java/security/AllPermissionCollection.java b/libcore/security/src/main/java/java/security/AllPermissionCollection.java
index 000365d..5b28420 100644
--- a/libcore/security/src/main/java/java/security/AllPermissionCollection.java
+++ b/libcore/security/src/main/java/java/security/AllPermissionCollection.java
@@ -32,13 +32,9 @@
  * single added instance.
  * 
  * @see AllPermission
- * @since Android 1.0
  */
 final class AllPermissionCollection extends PermissionCollection {
 
-    /**
-     * @com.intel.drl.spec_ref
-     */
     private static final long serialVersionUID = -4023755556366636806L;
 
     private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
@@ -50,6 +46,7 @@
     /**
      * Adds an {@code AllPermission} to the collection.
      */
+    @Override
     public void add(Permission permission) {
         if (isReadOnly()) {
             throw new SecurityException(Messages.getString("security.15")); //$NON-NLS-1$
@@ -64,6 +61,7 @@
     /**
      * Returns the enumeration of the collection.
      */
+    @Override
     public Enumeration<Permission> elements() {
         return new SingletonEnumeration<Permission>(all);
     }
@@ -78,6 +76,7 @@
 
         /**
          * Constructor taking the single element.
+         * @param single the element
          */
         public SingletonEnumeration(E single) {
             element = single;
@@ -112,6 +111,7 @@
      * @param permission
      *            the permission to check.
      */
+    @Override
     public boolean implies(Permission permission) {
         return all != null;
     }
@@ -137,4 +137,4 @@
             all = new AllPermission();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/AuthProvider.java b/libcore/security/src/main/java/java/security/AuthProvider.java
index 5a3be77..15324b3 100644
--- a/libcore/security/src/main/java/java/security/AuthProvider.java
+++ b/libcore/security/src/main/java/java/security/AuthProvider.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import javax.security.auth.Subject;
@@ -29,11 +24,12 @@
 /**
  * {@code AuthProvider} is an abstract superclass for Java Security {@code
  * Provider} which provide login and logout.
- * 
- * @since Android 1.0
  */
 public abstract class AuthProvider extends Provider {
 
+    /**
+     * @serial
+     */
     private static final long serialVersionUID = 4197859053084546461L;
 
     /**
@@ -46,7 +42,6 @@
      *            the version of the provider.
      * @param info
      *            a description of the provider.
-     * @since Android 1.0
      */
     protected AuthProvider(String name, double version, String info) {
         super(name, version, info); 
@@ -71,7 +66,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public abstract void login(Subject subject, CallbackHandler handler) throws LoginException;
     
@@ -82,14 +76,12 @@
      * the {@code SecurityPermission} {@code authProvider.NAME} (where NAME is
      * the provider name) to be granted, otherwise a {@code SecurityException}
      * will be thrown.
-     * </p>
-     * 
+     *
      * @throws LoginException
      *             if the logout fails.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public abstract void logout() throws LoginException;
     
@@ -101,20 +93,18 @@
      * If no handler is set, this {@code AuthProvider} uses the {@code
      * CallbackHandler} specified by the {@code
      * auth.login.defaultCallbackHandler} security property.
-     * </p><p>
+     * <p>
      * If a {@code SecurityManager} is installed, code calling this method needs
      * the {@code SecurityPermission} {@code authProvider.NAME} (where NAME is
      * the provider name) to be granted, otherwise a {@code SecurityException}
      * will be thrown.
-     * </p>
-     * 
+     *
      * @param handler
      *            the handler to obtain authentication information from the
      *            caller.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public abstract void setCallbackHandler(CallbackHandler handler);
 }
diff --git a/libcore/security/src/main/java/java/security/BasicPermission.java b/libcore/security/src/main/java/java/security/BasicPermission.java
index 1d566ec..aa49cba 100644
--- a/libcore/security/src/main/java/java/security/BasicPermission.java
+++ b/libcore/security/src/main/java/java/security/BasicPermission.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.IOException;
@@ -38,14 +33,13 @@
  * For example:
  * 
  * <pre>
- * com.google.android.*  grants all permissions under the com.google.android permission hierarchy
- * *                     grants all permissions
+ * java.io.*  grants all permissions under the java.io permission hierarchy
+ * *          grants all permissions
  * </pre>
- * </p><p>
+ * <p>
  * While this class ignores the action list in the
  * {@link #BasicPermission(String, String)} constructor, subclasses may
  * implement actions on top of this class.
- * </p>
  */
 public abstract class BasicPermission extends Permission implements
     Serializable {
@@ -55,12 +49,11 @@
     /**
      * Constructs a new instance of {@code BasicPermission} with the specified
      * name.
-     * 
+     *
      * @param name
      *            the name of the permission.
      * @throws NullPointerException if {@code name} is {@code null}.
      * @throws IllegalArgumentException if {@code name.length() == 0}.
-     * @since Android 1.0
      */
     public BasicPermission(String name) {
         super(name);
@@ -70,7 +63,7 @@
     /**
      * Constructs a new instance of {@code BasicPermission} with the specified
      * name. The {@code action} parameter is ignored.
-     * 
+     *
      * @param name
      *            the name of the permission.
      * @param action
@@ -79,7 +72,6 @@
      *             if {@code name} is {@code null}.
      * @throws IllegalArgumentException
      *             if {@code name.length() == 0}.
-     * @since Android 1.0
      */
     public BasicPermission(String name, String action) {
         super(name);
@@ -105,15 +97,14 @@
      * <p>
      * The {@link #implies(Permission)} method should be used for making access
      * control checks.
-     * </p>
-     * 
+     *
      * @param obj
      *            object to be compared for equality with this {@code
      *            BasicPermission}.
      * @return {@code true} if the specified object is equal to this {@code
      *         BasicPermission}, otherwise {@code false}.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj == this) {
             return true;
@@ -129,12 +120,12 @@
      * Returns the hash code value for this {@code BasicPermission}. Returns the
      * same hash code for {@code BasicPermission}s that are equal to each other
      * as required by the general contract of {@link Object#hashCode}.
-     * 
+     *
      * @return the hash code value for this {@code BasicPermission}.
      * @see Object#equals(Object)
      * @see BasicPermission#equals(Object)
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         return getName().hashCode();
     }
@@ -142,23 +133,23 @@
     /**
      * Returns the actions associated with this permission. Since {@code
      * BasicPermission} instances have no actions, an empty string is returned.
-     * 
+     *
      * @return an empty string.
-     * @since Android 1.0
      */
+    @Override
     public String getActions() {
         return ""; //$NON-NLS-1$
     }
 
     /**
      * Indicates whether the specified permission is implied by this permission.
-     * 
+     *
      * @param permission
      *            the permission to check against this permission.
      * @return {@code true} if the specified permission is implied by this
      *         permission, {@code false} otherwise.
-     * @since Android 1.0
      */
+    @Override
     public boolean implies(Permission permission) {
         if (permission != null && permission.getClass() == this.getClass()) {
             return nameImplies(getName(), permission.getName());
@@ -204,12 +195,11 @@
      * stored in it when checking if the collection implies a permission.
      * Instead, it assumes that if the type of the permission is correct, and
      * the name of the permission is correct, there is a match.
-     * </p>
-     * 
+     *
      * @return an empty {@link PermissionCollection} for holding permissions.
      * @see BasicPermissionCollection
-     * @since Android 1.0
      */
+    @Override
     public PermissionCollection newPermissionCollection() {
         return new BasicPermissionCollection();
     }
@@ -222,4 +212,4 @@
         in.defaultReadObject();
         checkName(this.getName());
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/BasicPermissionCollection.java b/libcore/security/src/main/java/java/security/BasicPermissionCollection.java
index eb80503..820ae7f 100644
--- a/libcore/security/src/main/java/java/security/BasicPermissionCollection.java
+++ b/libcore/security/src/main/java/java/security/BasicPermissionCollection.java
@@ -37,7 +37,6 @@
  * 
  * @see BasicPermission
  * @see PermissionCollection
- * @since Android 1.0
  */
 final class BasicPermissionCollection extends PermissionCollection {
 
@@ -63,6 +62,7 @@
      * 
      * @see java.security.PermissionCollection#add(java.security.Permission)
      */
+    @Override
     public void add(Permission permission) {
         if (isReadOnly()) {
             throw new SecurityException(Messages.getString("security.15")); //$NON-NLS-1$
@@ -82,8 +82,6 @@
                 permission));
         } else { 
             // this is the first element provided that another thread did not add
-            // BEGIN android-changed
-            // copied from a newer version of harmony
             synchronized (this) {
                 if (permClass != null && inClass != permClass) {
                     throw new IllegalArgumentException(Messages.getString("security.16", //$NON-NLS-1$
@@ -91,7 +89,6 @@
                 }
                 permClass = inClass;
             }
-            // END android-changed
         }
 
         String name = permission.getName();
@@ -102,6 +99,7 @@
     /**
      * Returns enumeration of contained elements.
      */
+    @Override
     public Enumeration<Permission> elements() {
         return Collections.enumeration(items.values());
     }
@@ -115,6 +113,7 @@
      *            the permission to check.
      * @see Permission
      */
+    @Override
     public boolean implies(Permission permission) {
         if (permission == null || permission.getClass() != permClass) {
             return false;
@@ -162,16 +161,10 @@
      * <dd>The class to which all {@code BasicPermission}s in this
      * BasicPermissionCollection belongs.
      * <dt>Hashtable&lt;K,V&gt; permissions
-     * <dd>The
-     * 
-     * <pre>
-     * BasicPermission
-     * </pre>
-     * 
-     * s in this {@code BasicPermissionCollection}. All {@code BasicPermission}s
-     * in the collection must belong to the same class. The Hashtable is indexed
-     * by the {@code BasicPermission} name; the value of the Hashtable entry is
-     * the permission.
+     * <dd>The {@code BasicPermission}s in this collection. All {@code
+     * BasicPermission}s in the collection must belong to the same class. The
+     * Hashtable is indexed by the {@code BasicPermission} name; the value of
+     * the Hashtable entry is the permission.
      * </dl>
      */
     private void writeObject(java.io.ObjectOutputStream out) throws IOException {
@@ -191,8 +184,6 @@
         ObjectInputStream.GetField fields = in.readFields();
 
         items = new HashMap<String, Permission>();
-        // BEGIN android-changed
-        // copied from a newer version of harmony
         synchronized (this) {
             permClass = (Class<? extends Permission>)fields.get("permClass", null); //$NON-NLS-1$
             items.putAll((Hashtable<String, Permission>) fields.get(
@@ -207,6 +198,5 @@
                 throw new InvalidObjectException(Messages.getString("security.25")); //$NON-NLS-1$
             }
         }
-        // END android-changed
     }
 }
diff --git a/libcore/security/src/main/java/java/security/Certificate.java b/libcore/security/src/main/java/java/security/Certificate.java
index bf9a1ae..b30352d 100644
--- a/libcore/security/src/main/java/java/security/Certificate.java
+++ b/libcore/security/src/main/java/java/security/Certificate.java
@@ -15,15 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
-// BEGIN android-note
-// Added Deprecated annotation.
-// END android-note
-
 package java.security;
 
 import java.io.IOException;
@@ -36,9 +27,8 @@
  * validity of itself. It's in the responsibility of the application to verify
  * the validity of its certificates.
  * 
- * @deprecated Replaced by behavior in {@link javax.security.cert}
+ * @deprecated Replaced by behavior in {@link java.security.cert}
  * @see java.security.cert.Certificate
- * @since Android 1.0
  */
 @Deprecated
 public interface Certificate {
@@ -47,7 +37,7 @@
      * Decodes a certificate from the given {@code InputStream}. The format of
      * the data to encode must be that identified by {@link #getFormat()} and
      * encoded by {@link #encode(OutputStream)}.
-     * 
+     *
      * @param stream
      *            the {@code InputStream} to read from.
      * @throws KeyException
@@ -56,7 +46,6 @@
      *             if an exception is thrown by accessing the provided stream.
      * @see #encode(OutputStream)
      * @see #getFormat()
-     * @since Android 1.0
      */
     public void decode(InputStream stream) throws KeyException, IOException;
 
@@ -64,7 +53,7 @@
      * Encodes this certificate to an output stream. The
      * {@link #decode(InputStream)} method must be able to decode the format
      * written by this method.
-     * 
+     *
      * @param stream
      *            the {@code OutputStream} to encode this certificate to.
      * @throws KeyException
@@ -72,15 +61,13 @@
      * @throws IOException
      *             if an exception is thrown by accessing the provided stream.
      * @see #decode(InputStream)
-     * @since Android 1.0
      */
     public void encode(OutputStream stream) throws KeyException, IOException;
 
     /**
      * Returns a string identifying the format of this certificate.
-     * 
+     *
      * @return a string identifying the format of this certificate.
-     * @since Android 1.0
      */
     public String getFormat();
 
@@ -88,42 +75,38 @@
      * Returns the guarantor of this certificate. That guarantor guarantees,
      * that the public key of this certificate is from the principal returned by
      * {@link #getPrincipal()}.
-     * 
+     *
      * @return the guarantor of this certificate.
      * @see #getPrincipal()
-     * @since Android 1.0
      */
     public Principal getGuarantor();
 
     /**
      * Returns the principal of this certificate. The principal is guaranteed by
      * the guarantor returned by {@link #getGuarantor()}.
-     * 
+     *
      * @return the principal of this certificate.
      * @see #getGuarantor()
-     * @since Android 1.0
      */
     public Principal getPrincipal();
 
     /**
      * Returns the public key of this certificate. The public key is guaranteed
      * by the guarantor to belong to the principal.
-     * 
+     *
      * @return the public key of this certificate.
      * @see #getGuarantor()
      * @see Certificate#getPrincipal()
-     * @since Android 1.0
      */
     public PublicKey getPublicKey();
 
     /**
      * Returns a string containing a concise, human-readable description of the
      * this {@code Certificate}.
-     * 
+     *
      * @param detailed
      *            whether or not this method should return detailed information.
      * @return a string representation of this certificate.
-     * @since Android 1.0
      */
     public String toString(boolean detailed);
 }
diff --git a/libcore/security/src/main/java/java/security/CodeSigner.java b/libcore/security/src/main/java/java/security/CodeSigner.java
index 0719e8f..24d2b55 100644
--- a/libcore/security/src/main/java/java/security/CodeSigner.java
+++ b/libcore/security/src/main/java/java/security/CodeSigner.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.Serializable;
@@ -29,8 +24,6 @@
 
 /**
  * {@code CodeSigner} represents a signer of code. Instances are immutable.
- * 
- * @since Android 1.0
  */
 public final class CodeSigner implements Serializable {
 
@@ -45,7 +38,7 @@
 
     /**
      * Constructs a new instance of {@code CodeSigner}.
-     * 
+     *
      * @param signerCertPath
      *            the certificate path associated with this code signer.
      * @param timestamp
@@ -53,7 +46,6 @@
      *            null}.
      * @throws NullPointerException
      *             if {@code signerCertPath} is {@code null}.
-     * @since Android 1.0
      */
     public CodeSigner(CertPath signerCertPath, Timestamp timestamp) {
         if (signerCertPath == null) {
@@ -68,14 +60,14 @@
      * Returns {@code true} if the specified object is also an instance of
      * {@code CodeSigner}, the two {@code CodeSigner} encapsulate the same
      * certificate path and the same time stamp, if present in both.
-     * 
+     *
      * @param obj
      *            object to be compared for equality with this {@code
      *            CodeSigner}.
      * @return {@code true} if the specified object is equal to this {@code
      *         CodeSigner}, otherwise {@code false}.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj == this) {
             return true;
@@ -93,9 +85,8 @@
 
     /**
      * Returns the certificate path associated with this {@code CodeSigner}.
-     * 
+     *
      * @return the certificate path associated with this {@code CodeSigner}.
-     * @since Android 1.0
      */
     public CertPath getSignerCertPath() {
         return signerCertPath;
@@ -103,10 +94,9 @@
 
     /**
      * Returns the time stamp associated with this {@code CodeSigner}.
-     * 
+     *
      * @return the time stamp associated with this {@code CodeSigner}, maybe
      *         {@code null}.
-     * @since Android 1.0
      */
     public Timestamp getTimestamp() {
         return timestamp;
@@ -116,12 +106,12 @@
      * Returns the hash code value for this {@code CodeSigner}. Returns the same
      * hash code for {@code CodeSigner}s that are equal to each other as
      * required by the general contract of {@link Object#hashCode}.
-     * 
+     *
      * @return the hash code value for this {@code CodeSigner}.
      * @see Object#equals(Object)
      * @see CodeSigner#equals(Object)
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         if (hash == 0) {
             hash = signerCertPath.hashCode()
@@ -134,14 +124,13 @@
      * Returns a string containing a concise, human-readable description of the
      * this {@code CodeSigner} including its first certificate and its time
      * stamp, if present.
-     * 
+     *
      * @return a printable representation for this {@code CodeSigner}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         // There is no any special reason for '256' here, it's taken abruptly
-        // FIXME: 1.5 StringBuffer => StringBuilder
-        StringBuffer buf = new StringBuffer(256);
+        StringBuilder buf = new StringBuilder(256);
         // The javadoc says nothing, and the others implementations behavior seems as 
         // dumping only the first certificate. Well, let's do the same.
         buf.append("CodeSigner [").append(signerCertPath.getCertificates().get(0)); //$NON-NLS-1$
@@ -151,4 +140,4 @@
         buf.append("]"); //$NON-NLS-1$
         return buf.toString();
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/CodeSource.java b/libcore/security/src/main/java/java/security/CodeSource.java
index f4da89c..96a4b8c5 100644
--- a/libcore/security/src/main/java/java/security/CodeSource.java
+++ b/libcore/security/src/main/java/java/security/CodeSource.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.ByteArrayInputStream;
@@ -48,10 +43,9 @@
  * {@code CodeSource} encapsulates the location from where code is loaded and
  * the certificates that were used to verify that code. This information is used
  * by {@code SecureClassLoader} to define protection domains for loaded classes.
- * 
+ *
  * @see SecureClassLoader
  * @see ProtectionDomain
- * @since Android 1.0
  */
 public class CodeSource implements Serializable {
 
@@ -76,14 +70,13 @@
     /**
      * Constructs a new instance of {@code CodeSource} with the specified
      * {@code URL} and the {@code Certificate}s.
-     * 
+     *
      * @param location
      *            the {@code URL} representing the location from where code is
      *            loaded, maybe {@code null}.
      * @param certs
      *            the {@code Certificate} used to verify the code, loaded from
      *            the specified {@code location}, maybe {@code null}.
-     * @since Android 1.0
      */
     public CodeSource(URL location, Certificate[] certs) {
         this.location = location;
@@ -96,14 +89,13 @@
     /**
      * Constructs a new instance of {@code CodeSource} with the specified
      * {@code URL} and the {@code CodeSigner}s.
-     * 
+     *
      * @param location
      *            the {@code URL} representing the location from where code is
      *            loaded, maybe {@code null}.
      * @param signers
      *            the {@code CodeSigner}s of the code, loaded from the specified
      *            {@code location}. Maybe {@code null}.
-     * @since Android 1.0
      */
     public CodeSource(URL location, CodeSigner[] signers) {
         this.location = location;
@@ -119,14 +111,14 @@
      * {@code CodeSource}, points to the same {@code URL} location and the two
      * code sources encapsulate the same {@code Certificate}s. The order of the
      * {@code Certificate}s is ignored by this method.
-     * 
+     *
      * @param obj
      *            object to be compared for equality with this {@code
      *            CodeSource}.
      * @return {@code true} if the specified object is equal to this {@code
      *         CodeSource}, otherwise {@code false}.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj == this) {
             return true;
@@ -169,11 +161,9 @@
      * <p>
      * External modifications of the returned {@code Certificate[]} has no
      * impact on this {@code CodeSource}.
-     * </p>
-     * 
+     *
      * @return the certificates of this {@code CodeSource} or {@code null} if
      *         there is none.
-     * @since Android 1.0
      */
     public final Certificate[] getCertificates() {
         getCertificatesNoClone();
@@ -213,10 +203,9 @@
      * {@link #CodeSource(URL, Certificate[])} constructor was used to create
      * this instance, the signers are obtained from the supplied certificates.
      * Only X.509 certificates are analyzed.
-     * 
+     *
      * @return the signers of this {@code CodeSource}, or {@code null} if there
      *         is none.
-     * @since Android 1.0
      */
     public final CodeSigner[] getCodeSigners() {
         if (signers != null) {
@@ -308,9 +297,8 @@
 
     /**
      * Returns the location of this {@code CodeSource}.
-     * 
+     *
      * @return the location of this {@code CodeSource}, maybe {@code null}.
-     * @since Android 1.0
      */
     public final URL getLocation() {
         return location;
@@ -321,12 +309,12 @@
      * Returns the same hash code for {@code CodeSource}s that are
      * equal to each other as required by the general contract of
      * {@link Object#hashCode}.
-     * 
+     *
      * @return the hash code value for this {@code CodeSource}.
      * @see Object#equals(Object)
      * @see CodeSource#equals(Object)
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         //
         // hashCode() is undocumented there. Should we also use certs[i] to
@@ -385,21 +373,20 @@
      * location file with the '/' appended to it.
      * </ul>
      * Examples for locations that imply the location
-     * "http://code.google.com/android/security.apk":
-     * 
+     * "http://harmony.apache.org/milestones/M9/apache-harmony.jar":
+     *
      * <pre>
      * http:
-     * http://&#42;/android/*
-     * http://*.google.com/android/*
-     * http://code.google.com/android/-
-     * http://code.google.com/android/security.apk
+     * http://&#42;/milestones/M9/*
+     * http://*.apache.org/milestones/M9/*
+     * http://harmony.apache.org/milestones/-
+     * http://harmony.apache.org/milestones/M9/apache-harmony.jar
      * </pre>
-     * 
+     *
      * @param cs
      *            the code source to check.
      * @return {@code true} if the argument code source is implied by this
      *         {@code CodeSource}, otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean implies(CodeSource cs) {
         //
@@ -551,10 +538,10 @@
      * Returns a string containing a concise, human-readable description of the
      * this {@code CodeSource} including its location, its certificates and its
      * signers.
-     * 
+     *
      * @return a printable representation for this {@code CodeSource}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         StringBuilder buf = new StringBuilder();
         buf.append("CodeSource, url="); //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/DigestException.java b/libcore/security/src/main/java/java/security/DigestException.java
index d579885..0d0a1ee 100644
--- a/libcore/security/src/main/java/java/security/DigestException.java
+++ b/libcore/security/src/main/java/java/security/DigestException.java
@@ -15,17 +15,10 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  *{@code DigestException} is a general message digest exception.
- *
- *@since Android 1.0
  */
 public class DigestException extends GeneralSecurityException {
 
@@ -34,10 +27,9 @@
     /**
      * Constructs a new instance of {@code DigestException} with the
      * given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public DigestException(String msg) {
         super(msg);
@@ -45,8 +37,6 @@
 
     /**
      * Constructs a new instance of {@code DigestException}.
-     * 
-     * @since Android 1.0
      */
     public DigestException() {
     }
@@ -54,12 +44,11 @@
     /**
      * Constructs a new instance of {@code DigestException} with the
      * given message and the cause.
-     * 
+     *
      * @param message
      *            the detail message for this exception.
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public DigestException(String message, Throwable cause) {
         super(message, cause);
@@ -68,10 +57,9 @@
     /**
      * Constructs a new instance of {@code DigestException} with the
      * cause.
-     * 
+     *
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public DigestException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/DigestInputStream.java b/libcore/security/src/main/java/java/security/DigestInputStream.java
index 0db7613..26433fa 100644
--- a/libcore/security/src/main/java/java/security/DigestInputStream.java
+++ b/libcore/security/src/main/java/java/security/DigestInputStream.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vladimir N. Molotkov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.FilterInputStream;
@@ -29,15 +24,11 @@
 /**
  * {@code DigestInputStream} is a {@code FilterInputStream} which maintains an
  * associated message digest.
- * 
- * @since Android 1.0
  */
 public class DigestInputStream extends FilterInputStream {
 
     /**
      * The message digest for this stream.
-     * 
-     * @since Android 1.0
      */
     protected MessageDigest digest;
 
@@ -47,12 +38,11 @@
     /**
      * Constructs a new instance of this {@code DigestInputStream}, using the
      * given {@code stream} and the {@code digest}.
-     * 
+     *
      * @param stream
      *            the input stream.
      * @param digest
      *            the message digest.
-     * @since Android 1.0
      */
     public DigestInputStream(InputStream stream, MessageDigest digest) {
         super(stream);
@@ -61,9 +51,8 @@
 
     /**
      * Returns the message digest for this stream.
-     * 
+     *
      * @return the message digest for this stream.
-     * @since Android 1.0
      */
     public MessageDigest getMessageDigest() {
         return digest;
@@ -71,10 +60,9 @@
 
     /**
      * Sets the message digest which this stream will use.
-     * 
+     *
      * @param digest
      *            the message digest which this stream will use.
-     * @since Android 1.0
      */
     public void setMessageDigest(MessageDigest digest) {
         this.digest = digest;
@@ -85,13 +73,12 @@
      * for the byte if this function is {@link #on(boolean)}.
      * <p>
      * This operation is blocking.
-     * </p>
-     * 
+     *
      * @return the byte which was read or -1 at end of stream.
      * @throws IOException
      *             if reading the source stream causes an {@code IOException}.
-     * @since Android 1.0
      */
+    @Override
     public int read() throws IOException {
         // read the next byte
         int byteRead = in.read();
@@ -111,8 +98,7 @@
      * {@link #on(boolean)}.
      * <p>
      * This operation is blocking.
-     * </p>
-     * 
+     *
      * @param b
      *            the byte array in which to store the bytes
      * @param off
@@ -124,8 +110,8 @@
      *         filtered stream has been reached while reading
      * @throws IOException
      *             if reading the source stream causes an {@code IOException}
-     * @since Android 1.0
      */
+    @Override
     public int read(byte[] b, int off, int len) throws IOException {
         // read next up to len bytes
         int bytesRead = in.read(b, off, len);
@@ -141,11 +127,11 @@
 
     /**
      * Enables or disables the digest function (default is on).
-     * 
+     *
      * @param on
      *            {@code true} if the digest should be computed, {@code false}
      *            otherwise.
-     * @since Android 1.0
+	 * @see MessageDigest
      */
     public void on(boolean on) {
         isOn = on;
@@ -154,10 +140,10 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * {@code DigestInputStream} including the digest.
-     * 
+     *
      * @return a printable representation for this {@code DigestInputStream}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         return super.toString() + ", " + digest.toString() + //$NON-NLS-1$
             (isOn ? ", is on" : ", is off"); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/libcore/security/src/main/java/java/security/DigestOutputStream.java b/libcore/security/src/main/java/java/security/DigestOutputStream.java
index 858f8dd..f4cd659 100644
--- a/libcore/security/src/main/java/java/security/DigestOutputStream.java
+++ b/libcore/security/src/main/java/java/security/DigestOutputStream.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vladimir N. Molotkov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.FilterOutputStream;
@@ -34,8 +29,6 @@
 
     /**
      * The message digest for this stream.
-     * 
-     * @since Android 1.0
      */
     protected MessageDigest digest;
 
@@ -45,12 +38,11 @@
     /**
      * Constructs a new instance of this {@code DigestOutputStream}, using the
      * given {@code stream} and the {@code digest}.
-     * 
+     *
      * @param stream
      *            the output stream.
      * @param digest
      *            the message digest.
-     * @since Android 1.0
      */
     public DigestOutputStream(OutputStream stream, MessageDigest digest) {
         super(stream);
@@ -59,9 +51,8 @@
 
     /**
      * Returns the message digest for this stream.
-     * 
+     *
      * @return the message digest for this stream.
-     * @since Android 1.0
      */
     public MessageDigest getMessageDigest() {
         return digest;
@@ -69,10 +60,9 @@
 
     /**
      * Sets the message digest which this stream will use.
-     * 
+     *
      * @param digest
      *            the message digest which this stream will use.
-     * @since Android 1.0
      */
     public void setMessageDigest(MessageDigest digest) {
         this.digest = digest;
@@ -81,13 +71,13 @@
     /**
      * Writes the specified {@code int} to the stream. Updates the digest if
      * this function is {@link #on(boolean)}.
-     * 
+     *
      * @param b
      *            the byte to be written.
      * @throws IOException
      *             if writing to the stream causes a {@code IOException}
-     * @since Android 1.0
      */
+    @Override
     public void write(int b) throws IOException {
         // update digest only if digest functionality is on
         if (isOn) {
@@ -100,7 +90,7 @@
     /**
      * Writes {@code len} bytes into the stream, starting from the specified
      * offset. Updates the digest if this function is {@link #on(boolean)}.
-     * 
+     *
      * @param b
      *            the buffer to write to.
      * @param off
@@ -109,8 +99,8 @@
      *            the number of bytes in {@code b} to write.
      * @throws IOException
      *             if writing to the stream causes an {@code IOException}.
-     * @since Android 1.0
      */
+    @Override
     public void write(byte[] b, int off, int len) throws IOException {
         // update digest only if digest functionality is on
         if (isOn) {
@@ -122,11 +112,11 @@
 
     /**
      * Enables or disables the digest function (default is on).
-     * 
+     *
      * @param on
      *            {@code true} if the digest should be computed, {@code false}
      *            otherwise.
-     * @since Android 1.0
+	 * @see MessageDigest
      */
     public void on(boolean on) {
         isOn = on;
@@ -135,10 +125,10 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * {@code DigestOutputStream} including the digest.
-     * 
+     *
      * @return a printable representation for this {@code DigestOutputStream}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         return super.toString() + ", " + digest.toString() + //$NON-NLS-1$
             (isOn ? ", is on" : ", is off"); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/libcore/security/src/main/java/java/security/DomainCombiner.java b/libcore/security/src/main/java/java/security/DomainCombiner.java
index 501c419..36433b3 100644
--- a/libcore/security/src/main/java/java/security/DomainCombiner.java
+++ b/libcore/security/src/main/java/java/security/DomainCombiner.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
@@ -29,7 +24,6 @@
  * @see AccessControlContext
  * @see AccessControlContext#AccessControlContext(AccessControlContext,
  *      DomainCombiner)
- * @since Android 1.0
  */
 public interface DomainCombiner {
 
@@ -37,7 +31,7 @@
      * Returns a combination of the two provided {@code ProtectionDomain}
      * arrays. Implementers can simply merge the two arrays into one, remove
      * duplicates and perform other optimizations.
-     * 
+     *
      * @param current
      *            the protection domains of the current execution thread (since
      *            the most recent call to {@link AccessController#doPrivileged}
@@ -47,7 +41,6 @@
      *            null}.
      * @return a single {@code ProtectionDomain} array computed from the two
      *         provided arrays.
-     * @since Android 1.0
      */
     ProtectionDomain[] combine(ProtectionDomain[] current,
             ProtectionDomain[] assigned);
diff --git a/libcore/security/src/main/java/java/security/GeneralSecurityException.java b/libcore/security/src/main/java/java/security/GeneralSecurityException.java
index 2a1cacb..78fca29 100644
--- a/libcore/security/src/main/java/java/security/GeneralSecurityException.java
+++ b/libcore/security/src/main/java/java/security/GeneralSecurityException.java
@@ -15,18 +15,11 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code GeneralSecurityException} is a general security exception and the
  * superclass for all security specific exceptions.
- * 
- * @since Android 1.0
  */
 public class GeneralSecurityException extends Exception {
 
@@ -35,10 +28,9 @@
     /**
      * Constructs a new instance of {@code GeneralSecurityException} with the
      * given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public GeneralSecurityException(String msg) {
         super(msg);
@@ -46,8 +38,6 @@
 
     /**
      * Constructs a new instance of {@code GeneralSecurityException}.
-     * 
-     * @since Android 1.0
      */
     public GeneralSecurityException() {
     }
@@ -55,12 +45,11 @@
     /**
      * Constructs a new instance of {@code GeneralSecurityException} with the
      * given message and the cause.
-     * 
+     *
      * @param message
      *            the detail message for this exception.
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public GeneralSecurityException(String message, Throwable cause) {
         super(message, cause);
@@ -69,10 +58,9 @@
     /**
      * Constructs a new instance of {@code GeneralSecurityException} with the
      * cause.
-     * 
+     *
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public GeneralSecurityException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/Guard.java b/libcore/security/src/main/java/java/security/Guard.java
index 1e4d270..b652054 100644
--- a/libcore/security/src/main/java/java/security/Guard.java
+++ b/libcore/security/src/main/java/java/security/Guard.java
@@ -15,17 +15,10 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code Guard} implementors protect access to other objects.
- * 
- * @since Android 1.0
  */
 public interface Guard {
 
@@ -33,12 +26,11 @@
      * Checks whether access to the specified {@code Object} should be granted.
      * This method returns silently if access is granted, otherwise a {@code
      * SecurityException} is thrown.
-     * 
+     *
      * @param object
      *            the object to be protected by this {@code Guard}.
      * @throws SecurityException
      *             if access is not granted.
-     * @since Android 1.0
      */
     public void checkGuard(Object object) throws SecurityException;
 }
diff --git a/libcore/security/src/main/java/java/security/GuardedObject.java b/libcore/security/src/main/java/java/security/GuardedObject.java
index a64d634..34a5113 100644
--- a/libcore/security/src/main/java/java/security/GuardedObject.java
+++ b/libcore/security/src/main/java/java/security/GuardedObject.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.IOException;
@@ -28,8 +23,6 @@
 /**
  * {@code GuardedObject} controls access to an object, by checking all requests
  * for the object with a {@code Guard}.
- * 
- * @since Android 1.0
  */
 public class GuardedObject implements Serializable {
 
@@ -42,13 +35,12 @@
     /**
      * Constructs a new instance of {@code GuardedObject} which protects access
      * to the specified {@code Object} using the specified {@code Guard}.
-     * 
+     *
      * @param object
      *            the {@code Object} to protect.
      * @param guard
      *            the {@code Guard} which protects the specified {@code Object},
      *            maybe {@code null}.
-     * @since Android 1.0
      */
     public GuardedObject(Object object, Guard guard) {
         this.object = object;
@@ -59,11 +51,10 @@
      * Returns the guarded {@code Object} if the associated {@code Guard}
      * permits access. If access is not granted, then a {@code
      * SecurityException} is thrown.
-     * 
+     *
      * @return the guarded object.
      * @exception SecurityException
      *                if access is not granted to the guarded object.
-     * @since Android 1.0
      */
     public Object getObject() throws SecurityException {
         if (guard != null) {
diff --git a/libcore/security/src/main/java/java/security/Identity.java b/libcore/security/src/main/java/java/security/Identity.java
index 7111029..d55cd3a 100644
--- a/libcore/security/src/main/java/java/security/Identity.java
+++ b/libcore/security/src/main/java/java/security/Identity.java
@@ -15,15 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
-// BEGIN android-note
-// Added Deprecated annotation.
-// END android-note
-
 package java.security;
 
 import java.io.Serializable;
@@ -34,11 +25,10 @@
 
 /**
  * {@code Identity} represents an identity like a person or a company.
- * 
+ *
  * @deprecated The functionality of this class has been replace by
  *             {@link Principal}, {@link KeyStore} and the {@code
  *             java.security.cert} package.
- * @since Android 1.0
  */
 @Deprecated
 public abstract class Identity implements Principal, Serializable {
@@ -56,18 +46,15 @@
 
     /**
      * Constructs a new instance of {@code Identity}.
-     * 
-     * @since Android 1.0
      */
     protected Identity() {
     }
 
     /**
      * Creates a new instance of {@code Identity} with the specified name.
-     * 
+     *
      * @param name
      *            the name of this {@code Identity}.
-     * @since Android 1.0
      */
     public Identity(String name) {
         this.name = name;
@@ -76,7 +63,7 @@
     /**
      * Creates a new instance of {@code Identity} with the specified name and
      * the scope of this {@code Identity}.
-     * 
+     *
      * @param name
      *            the name of this {@code Identity}.
      * @param scope
@@ -84,7 +71,6 @@
      * @throws KeyManagementException
      *             if an {@code Identity} with the same name is already present
      *             in the specified scope.
-     * @since Android 1.0
      */
     public Identity(String name, IdentityScope scope)
             throws KeyManagementException {
@@ -101,8 +87,7 @@
      * If a {@code SecurityManager} is installed, code calling this method needs
      * the {@code SecurityPermission} {@code addIdentityCertificate} to be
      * granted, otherwise a {@code SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @param certificate
      *            the {@code Certificate} to be added to this {@code Identity}.
      * @throws KeyManagementException
@@ -110,7 +95,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public void addCertificate(Certificate certificate)
             throws KeyManagementException {
@@ -163,7 +147,7 @@
      * the {@code SecurityPermission} {@code "removeIdentityCertificate"} to be
      * granted, otherwise a {@code SecurityException} will be thrown.
      * <p>
-     * 
+     *
      * @param certificate
      *            the {@code Certificate} to be removed.
      * @throws KeyManagementException
@@ -171,7 +155,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public void removeCertificate(Certificate certificate)
             throws KeyManagementException {
@@ -196,9 +179,8 @@
      * Returns the certificates for this {@code Identity}. External
      * modifications of the returned array has no impact on this {@code
      * Identity}.
-     * 
+     *
      * @return the {@code Certificates} for this {@code Identity}
-     * @since Android 1.0
      */
     public Certificate[] certificates() {
         if (certificates == null) {
@@ -219,13 +201,11 @@
      * <p>
      * To be equal, two {@code Identity} objects need to have the same name and
      * the same public keys.
-     * </p>
-     * 
+     *
      * @param identity
      *            the identity to check for equality.
      * @return {@code true} if the {@code Identity} objects are equal, {@code
      *         false} otherwise.
-     * @since Android 1.0
      */
     protected boolean identityEquals(Identity identity) {
         if (!name.equals(identity.name)) {
@@ -245,12 +225,11 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * this {@code Identity}.
-     * 
+     *
      * @param detailed
      *            whether or not this method should return detailed information.
      * @return a printable representation for this {@code Permission}.
-     * @since Android 1.0
-     */  
+     */
     public String toString(boolean detailed) {
         String s = toString();
         if (detailed) {
@@ -264,9 +243,8 @@
 
     /**
      * Returns the {@code IdentityScope} of this {@code Identity}.
-     * 
+     *
      * @return the {@code IdentityScope} of this {@code Identity}.
-     * @since Android 1.0
      */
     public final IdentityScope getScope() {
         return scope;
@@ -281,8 +259,7 @@
      * If a {@code SecurityManager} is installed, code calling this method needs
      * the {@code SecurityPermission} {@code setIdentityPublicKey} to be
      * granted, otherwise a {@code SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @param key
      *            the {@code PublicKey} to be set.
      * @throws KeyManagementException
@@ -291,7 +268,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public void setPublicKey(PublicKey key) throws KeyManagementException {
         SecurityManager sm = System.getSecurityManager();
@@ -315,9 +291,8 @@
 
     /**
      * Returns the {@code PublicKey} associated with this {@code Identity}.
-     * 
+     *
      * @return the {@code PublicKey} associated with this {@code Identity}.
-     * @since Android 1.0
      */
     public PublicKey getPublicKey() {
         return publicKey;
@@ -332,13 +307,12 @@
      * If a {@code SecurityManager} is installed, code calling this method needs
      * the {@code SecurityPermission} {@code setIdentityInfo} to be granted,
      * otherwise a {@code SecurityException} will be thrown.
-     * 
+     *
      * @param info
      *            the information to be set.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public void setInfo(String info) {
         SecurityManager sm = System.getSecurityManager();
@@ -353,9 +327,8 @@
 
     /**
      * Returns the information string of this {@code Identity}.
-     * 
+     *
      * @return the information string of this {@code Identity}.
-     * @since Android 1.0
      */
     public String getInfo() {
         return info;
@@ -369,14 +342,14 @@
      * returns {@code true} if the specified object is equal, {@code false}
      * otherwise. {@code Identity} objects are considered equal, if they have
      * the same name and are in the same scope.
-     * 
+     *
      * @param obj
      *            object to be compared for equality with this {@code
      *            Identity}.
      * @return {@code true} if the specified object is equal to this {@code
      *         Identity}, otherwise {@code false}.
-     * @since Android 1.0
      */
+    @Override
     public final boolean equals(Object obj) {
         if (this == obj) {
             return true;
@@ -397,9 +370,8 @@
 
     /**
      * Returns the name of this {@code Identity}.
-     * 
+     *
      * @return the name of this {@code Identity}.
-     * @since Android 1.0
      */
     public final String getName() {
         return name;
@@ -412,12 +384,12 @@
      * Returns the hash code value for this {@code Identity}. Returns the same
      * hash code for {@code Identity}s that are equal to each other as required
      * by the general contract of {@link Object#hashCode}.
-     * 
+     *
      * @return the hash code value for this {@code Identity}.
      * @see Object#equals(Object)
      * @see Identity#equals(Object)
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         int hash = 0;
         if (name != null) {
@@ -439,22 +411,22 @@
      * If a {@code SecurityManager} is installed, code calling this method
      * needs the {@code SecurityPermission} {@code printIdentity} to be granted,
      * otherwise a {@code SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @return a printable representation for this {@code Identity}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
+    @Override
+    @SuppressWarnings("nls")
     public String toString() {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
-            sm.checkSecurityAccess("printIdentity"); //$NON-NLS-1$
+            sm.checkSecurityAccess("printIdentity");
         }
-        String s = (this.name == null? "" : this.name);
+        String s = (this.name == null ? "" : this.name);
         if (scope != null) {
-            s += " [" + scope.getName() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+            s += " [" + scope.getName() + "]";
         }
         return s;
     }
diff --git a/libcore/security/src/main/java/java/security/IdentityScope.java b/libcore/security/src/main/java/java/security/IdentityScope.java
index 93729dc..60ab3e8c 100644
--- a/libcore/security/src/main/java/java/security/IdentityScope.java
+++ b/libcore/security/src/main/java/java/security/IdentityScope.java
@@ -15,29 +15,17 @@
  *  limitations under the License.
  */
 
-/**
-* @author Aleksei Y. Semenov
-* @version $Revision$
-*/
-
-// BEGIN android-note
-// Added Deprecated annotation.
-// END android-note
-
 package java.security;
 
 import java.util.Enumeration;
 
-import org.apache.harmony.security.SystemScope;
-
 
 /**
  * {@code IdentityScope} represents a scope for {@link Identity} objects.
- * 
+ *
  * @deprecated The functionality of this class has been replace by
  *             {@link Principal}, {@link KeyStore} and the {@code
  *             java.security.cert} package.
- * @since Android 1.0
  */
 @Deprecated
 public abstract class IdentityScope extends Identity {
@@ -49,8 +37,6 @@
 
     /**
      * Constructs a new instance of {@code IdentityScope}.
-     * 
-     * @since Android 1.0
      */
     protected IdentityScope() {
         super();
@@ -59,10 +45,9 @@
     /**
      * Constructs a new instance of {@code IdentityScope} with the specified
      * name.
-     * 
+     *
      * @param name
      *            the name of this {@code IdentityScope}.
-     * @since Android 1.0
      */
     public IdentityScope(String name) {
         super(name);
@@ -71,14 +56,13 @@
     /**
      * Constructs a new instance of {@code IdentityScope} with the specified
      * name and the specified scope.
-     * 
+     *
      * @param name
      *            the name of this {@code IdentityScope}.
      * @param scope
      *            the scope of this {@code IdentityScope}.
      * @throws KeyManagementException
      *             if an identity with the same key already exists.
-     * @since Android 1.0
      */
     public IdentityScope(String name, IdentityScope scope)
             throws KeyManagementException {
@@ -87,9 +71,8 @@
 
     /**
      * Returns the system's scope.
-     * 
+     *
      * @return the system's scope.
-     * @since Android 1.0
      */
     public static IdentityScope getSystemScope() {
         /* 
@@ -116,10 +99,9 @@
 
     /**
      * Sets the system's scope.
-     * 
+     *
      * @param scope
      *            the scope to set.
-     * @since Android 1.0
      */
     protected static void setSystemScope(IdentityScope scope) {
         SecurityManager sm = System.getSecurityManager();
@@ -131,21 +113,19 @@
 
     /**
      * Returns the number of {@code Identity} objects in this scope.
-     * 
+     *
      * @return the number of {@code Identity} objects in this scope.
-     * @since Android 1.0
      */
     public abstract int size();
 
     /**
      * Returns the {@code Identity} with the specified name or {@code null} if
      * no {@code Identity} with the specified name is present in this scope.
-     * 
+     *
      * @param name
      *            the name of the {@code Identity} to be returned.
      * @return the {@code Identity} with the specified name or {@code null} if
      *         not present.
-     * @since Android 1.0
      */
     public abstract Identity getIdentity(String name);
 
@@ -153,13 +133,12 @@
      * Returns the {@code Identity} with the name of the specified principal or
      * {@code null} if no {@code Identity} with the name of the specified
      * principal is present in this scope.
-     * 
+     *
      * @param principal
      *            the {@code Principal} whose name is used to lookup the {@code
      *            Identity} to be returned.
      * @return the {@code Identity} with the specified name or {@code null} if
      *         not present.
-     * @since Android 1.0
      */
     public Identity getIdentity(Principal principal) {
         return getIdentity(principal.getName());
@@ -169,36 +148,33 @@
      * Returns the {@code Identity} which is associated with the specified key
      * or {@code null} if no {@code Identity} associated with the specified key
      * is present in this scope.
-     * 
+     *
      * @param key
      *            the {@code PublicKey} of the {@code Identity} to be returned.
      * @return the {@code Identity} associated with the specified key or {@code
      *         null} if not present.
-     * @since Android 1.0
      */
     public abstract Identity getIdentity(PublicKey key);
 
     /**
      * Adds an {@code Identity} to this {@code IdentityScope}.
-     * 
+     *
      * @param identity
      *            the {@code Identity} to be added.
      * @throws KeyManagementException
      *             if the specified {@code Identity} is invalid or an identity
      *             with the same key already exists.
-     * @since Android 1.0
      */
     public abstract void addIdentity(Identity identity)
             throws KeyManagementException;
 
     /**
      * Removes an {@code Identity} from this {@code IdentityScope}.
-     * 
+     *
      * @param identity
      *            the {@code Identity} to be removed.
      * @throws KeyManagementException
      *             if the {@code Identity} is not present in this scope.
-     * @since Android 1.0
      */
     public abstract void removeIdentity(Identity identity)
             throws KeyManagementException;
@@ -206,22 +182,21 @@
     /**
      * Returns an {@code Enumeration} over the {@code Identity} objects in this
      * {@code IdentityScope}.
-     * 
+     *
      * @return an {@code Enumeration} over the {@code Identity} objects in this
      *         {@code IdentityScope}.
-     * @since Android 1.0
      */
     public abstract Enumeration<Identity> identities();
 
     /**
      * Returns a string containing a concise, human-readable description of this
      * {@code IdentityScope}.
-     * 
+     *
      * @return a printable representation for this {@code IdentityScope}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        return new StringBuffer(super.toString())
+        return new StringBuilder(super.toString())
                 .append("[").append(size()).append("]").toString(); //$NON-NLS-1$ //$NON-NLS-2$
     }
 }
diff --git a/libcore/security/src/main/java/java/security/InvalidAlgorithmParameterException.java b/libcore/security/src/main/java/java/security/InvalidAlgorithmParameterException.java
index 0d8a607..26d9f97 100644
--- a/libcore/security/src/main/java/java/security/InvalidAlgorithmParameterException.java
+++ b/libcore/security/src/main/java/java/security/InvalidAlgorithmParameterException.java
@@ -15,31 +15,22 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code InvalidAlgorithmParameterException} indicates the occurrence of
  * invalid algorithm parameters.
- * 
- * @since Android 1.0
  */
 public class InvalidAlgorithmParameterException extends
         GeneralSecurityException {
-    
     private static final long serialVersionUID = 2864672297499471472L;
 
     /**
      * Constructs a new instance of {@code InvalidAlgorithmParameterException}
      * with the given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InvalidAlgorithmParameterException(String msg) {
         super(msg);
@@ -47,8 +38,6 @@
 
     /**
      * Constructs a new instance of {@code InvalidAlgorithmParameterException}.
-     * 
-     * @since Android 1.0
      */
     public InvalidAlgorithmParameterException() {
     }
@@ -56,12 +45,11 @@
     /**
      * Constructs a new instance of {@code InvalidAlgorithmParameterException} with the
      * given message and the cause.
-     * 
+     *
      * @param message
      *            the detail message for this exception.
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public InvalidAlgorithmParameterException(String message, Throwable cause) {
         super(message, cause);
@@ -70,10 +58,9 @@
     /**
      * Constructs a new instance of {@code InvalidAlgorithmParameterException}
      * with the cause.
-     * 
+     *
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public InvalidAlgorithmParameterException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/InvalidKeyException.java b/libcore/security/src/main/java/java/security/InvalidKeyException.java
index 95d864e..f08fc51 100644
--- a/libcore/security/src/main/java/java/security/InvalidKeyException.java
+++ b/libcore/security/src/main/java/java/security/InvalidKeyException.java
@@ -15,18 +15,11 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code InvalidKeyException} indicates exceptional conditions, caused by an
  * invalid key.
- * 
- * @since Android 1.0
  */
 public class InvalidKeyException extends KeyException {
 
@@ -35,10 +28,9 @@
     /**
      * Constructs a new instance of {@code InvalidKeyException} with the given
      * message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InvalidKeyException(String msg) {
         super(msg);
@@ -46,8 +38,6 @@
 
     /**
      * Constructs a new instance of {@code InvalidKeyException}.
-     * 
-     * @since Android 1.0
      */
     public InvalidKeyException() {
     }
@@ -55,12 +45,11 @@
     /**
      * Constructs a new instance of {@code InvalidKeyException} with the given
      * message and the cause.
-     * 
+     *
      * @param message
      *            the detail message for this exception.
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public InvalidKeyException(String message, Throwable cause) {
         super(message, cause);
@@ -68,10 +57,9 @@
 
     /**
      * Constructs a new instance of {@code InvalidKeyException} with the cause.
-     * 
+     *
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public InvalidKeyException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/InvalidParameterException.java b/libcore/security/src/main/java/java/security/InvalidParameterException.java
index ac10448..6ad4645 100644
--- a/libcore/security/src/main/java/java/security/InvalidParameterException.java
+++ b/libcore/security/src/main/java/java/security/InvalidParameterException.java
@@ -15,18 +15,11 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code InvalidParameterException} indicates exceptional conditions, caused by
  * invalid parameters.
- * 
- * @since Android 1.0
  */
 public class InvalidParameterException extends IllegalArgumentException {
 
@@ -35,10 +28,9 @@
     /**
      * Constructs a new instance of {@code InvalidParameterException} with the
      * given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InvalidParameterException(String msg) {
         super(msg);
@@ -46,8 +38,6 @@
 
     /**
      * Constructs a new instance of {@code InvalidParameterException}.
-     * 
-     * @since Android 1.0
      */
     public InvalidParameterException() {
     }
diff --git a/libcore/security/src/main/java/java/security/Key.java b/libcore/security/src/main/java/java/security/Key.java
index 1359ab2..28d24ff 100644
--- a/libcore/security/src/main/java/java/security/Key.java
+++ b/libcore/security/src/main/java/java/security/Key.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.Serializable;
@@ -29,14 +24,11 @@
  * 
  * @see PublicKey
  * @see PrivateKey
- * @since Android 1.0
  */
 public interface Key extends Serializable {
 
     /**
      * The {@code serialVersionUID} to be compatible with JDK1.1.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = 6603384152749567654L;
 
@@ -46,7 +38,6 @@
      * 
      * @return the name of the algorithm of this key or {@code null} if the
      *         algorithm is unknown.
-     * @since Android 1.0
      */
     public String getAlgorithm();
 
@@ -56,7 +47,6 @@
      * 
      * @return the name of the format used to encode this key, or {@code null}
      *         if it can not be encoded.
-     * @since Android 1.0
      */
     public String getFormat();
 
@@ -66,7 +56,6 @@
      * 
      * @return the encoded form of this key, or {@code null} if encoding is not
      *         supported by this key.
-     * @since Android 1.0
      */
     public byte[] getEncoded();
 }
diff --git a/libcore/security/src/main/java/java/security/KeyException.java b/libcore/security/src/main/java/java/security/KeyException.java
index b01f75b..721c896 100644
--- a/libcore/security/src/main/java/java/security/KeyException.java
+++ b/libcore/security/src/main/java/java/security/KeyException.java
@@ -15,17 +15,10 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code KeyException} is the common superclass of all key related exceptions.
- * 
- * @since Android 1.0
  */
 public class KeyException extends GeneralSecurityException {
 
@@ -33,10 +26,9 @@
 
     /**
      * Constructs a new instance of {@code KeyException} with the given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public KeyException(String msg) {
         super(msg);
@@ -44,8 +36,6 @@
 
     /**
      * Constructs a new instance of {@code KeyException}.
-     * 
-     * @since Android 1.0
      */
     public KeyException() {
     }
@@ -53,12 +43,11 @@
     /**
      * Constructs a new instance of {@code KeyException} with the given message
      * and the cause.
-     * 
+     *
      * @param message
      *            the detail message for this exception.
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public KeyException(String message, Throwable cause) {
         super(message, cause);
@@ -66,10 +55,9 @@
 
     /**
      * Constructs a new instance of {@code KeyException} with the cause.
-     * 
+     *
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public KeyException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/KeyFactory.java b/libcore/security/src/main/java/java/security/KeyFactory.java
index 7c4966f..7484a31 100644
--- a/libcore/security/src/main/java/java/security/KeyFactory.java
+++ b/libcore/security/src/main/java/java/security/KeyFactory.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.security.spec.InvalidKeySpecException;
@@ -33,8 +28,6 @@
  * public and private key objects and convert keys between their external
  * representation, that can be easily transported and their internal
  * representation.
- * 
- * @since Android 1.0
  */
 public class KeyFactory {
     // The service name.
@@ -63,7 +56,6 @@
      *            the provider.
      * @param algorithm
      *            the algorithm to use.
-     * @since Android 1.0
      */
     protected KeyFactory(KeyFactorySpi keyFacSpi, 
                          Provider provider,
@@ -83,7 +75,6 @@
      *         algorithm.
      * @throws NoSuchAlgorithmException
      *             if no provider provides the requested algorithm.
-     * @since Android 1.0
      */
     public static KeyFactory getInstance(String algorithm)
                                 throws NoSuchAlgorithmException {
@@ -112,16 +103,16 @@
      *             if the requested provider is not available.
      * @throws IllegalArgumentException
      *             if {@code provider} is {@code null} or empty.
-     * @since Android 1.0
      */
+    @SuppressWarnings("nls")
     public static KeyFactory getInstance(String algorithm, String provider)
                                 throws NoSuchAlgorithmException, NoSuchProviderException {
         if ((provider == null) || (provider.length() == 0)) {
-            throw new IllegalArgumentException(Messages.getString("security.02")); //$NON-NLS-1$
+            throw new IllegalArgumentException(Messages.getString("security.02"));
         }
         Provider p = Security.getProvider(provider);
         if (p == null) {
-            throw new NoSuchProviderException(Messages.getString("security.03", provider));  //$NON-NLS-1$ //$NON-NLS-2$
+            throw new NoSuchProviderException(Messages.getString("security.03", provider));
         }
         return getInstance(algorithm, p);    
     }
@@ -138,7 +129,6 @@
      *         algorithm from the specified provider.
      * @throws NoSuchAlgorithmException
      *             if the provider does not provide the requested algorithm.
-     * @since Android 1.0
      */
     public static KeyFactory getInstance(String algorithm, Provider provider)
                                  throws NoSuchAlgorithmException {
@@ -158,19 +148,17 @@
      * Returns the provider associated with this {@code KeyFactory}.
      * 
      * @return the provider associated with this {@code KeyFactory}.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
     }
 
     /**
-     * Returns the name of the algorithm associated with this {@code KeyFactory}
-     * .
+     * Returns the name of the algorithm associated with this {@code
+     * KeyFactory}.
      * 
-     * @return the name of the algorithm associated with this {@code KeyFactory}
-     *         .
-     * @since Android 1.0
+     * @return the name of the algorithm associated with this {@code
+     *         KeyFactory}.
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -185,7 +173,6 @@
      * @return the public key
      * @throws InvalidKeySpecException
      *             if the specified {@code keySpec} is invalid
-     * @since Android 1.0
      */
     public final PublicKey generatePublic(KeySpec keySpec)
                                 throws InvalidKeySpecException {
@@ -201,7 +188,6 @@
      * @return the private key.
      * @throws InvalidKeySpecException
      *             if the specified {@code keySpec} is invalid.
-     * @since Android 1.0
      */
     public final PrivateKey generatePrivate(KeySpec keySpec)
                                 throws InvalidKeySpecException {
@@ -219,7 +205,6 @@
      * @throws InvalidKeySpecException
      *             if the key can not be processed, or the requested requested
      *             {@code KeySpec} is inappropriate for the given key.
-     * @since Android 1.0
      */
     public final <T extends KeySpec> T getKeySpec(Key key,
                                     Class<T> keySpec)
@@ -236,7 +221,6 @@
      * @throws InvalidKeyException
      *             if the specified key can not be translated by this key
      *             factory.
-     * @since Android 1.0
      */
     public final Key translateKey(Key key)
                         throws InvalidKeyException {
diff --git a/libcore/security/src/main/java/java/security/KeyFactorySpi.java b/libcore/security/src/main/java/java/security/KeyFactorySpi.java
index 7d3154e..0de00b2 100644
--- a/libcore/security/src/main/java/java/security/KeyFactorySpi.java
+++ b/libcore/security/src/main/java/java/security/KeyFactorySpi.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.security.spec.InvalidKeySpecException;
@@ -30,7 +25,6 @@
  * {@link KeyFactory}.
  * 
  * @see KeyFactory
- * @since Android 1.0
  */
 public abstract class KeyFactorySpi {
     
@@ -43,7 +37,6 @@
      * @return the public key.
      * @throws InvalidKeySpecException
      *             if the specified {@code keySpec} is invalid.
-     * @since Android 1.0
      */
     protected abstract PublicKey engineGeneratePublic(KeySpec keySpec) 
                                     throws InvalidKeySpecException;
@@ -57,7 +50,6 @@
      * @return the private key.
      * @throws InvalidKeySpecException
      *             if the specified {@code keySpec} is invalid.
-     * @since Android 1.0
      */
     protected abstract PrivateKey engineGeneratePrivate(KeySpec keySpec)
                                     throws InvalidKeySpecException;
@@ -73,7 +65,6 @@
      * @throws InvalidKeySpecException
      *             if the key can not be processed, or the requested requested
      *             {@code KeySpec} is inappropriate for the given key.
-     * @since Android 1.0
      */
     protected abstract <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
                                     throws InvalidKeySpecException;
@@ -88,7 +79,6 @@
      * @throws InvalidKeyException
      *             if the specified key can not be translated by this key
      *             factory.
-     * @since Android 1.0
      */
     protected abstract Key engineTranslateKey(Key key) throws InvalidKeyException;
 
diff --git a/libcore/security/src/main/java/java/security/KeyManagementException.java b/libcore/security/src/main/java/java/security/KeyManagementException.java
index 295ec03..00a5b3c 100644
--- a/libcore/security/src/main/java/java/security/KeyManagementException.java
+++ b/libcore/security/src/main/java/java/security/KeyManagementException.java
@@ -15,18 +15,11 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code KeyManagementException} is a general exception, thrown to indicate an
  * exception during processing an operation concerning key management.
- * 
- * @since Android 1.0
  */
 public class KeyManagementException extends KeyException {
 
@@ -35,10 +28,9 @@
     /**
      * Constructs a new instance of {@code KeyManagementException} with the
      * given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public KeyManagementException(String msg) {
         super(msg);
@@ -46,8 +38,6 @@
 
     /**
      * Constructs a new instance of {@code KeyManagementException}.
-     * 
-     * @since Android 1.0
      */
     public KeyManagementException() {
     }
@@ -55,12 +45,11 @@
     /**
      * Constructs a new instance of {@code KeyManagementException} with the
      * given message and the cause.
-     * 
+     *
      * @param message
      *            the detail message for this exception.
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public KeyManagementException(String message, Throwable cause) {
         super(message, cause);
@@ -69,13 +58,12 @@
     /**
      * Constructs a new instance of {@code KeyManagementException} with the
      * cause.
-     * 
+     *
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public KeyManagementException(Throwable cause) {
         super(cause);
     }
 
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/KeyPair.java b/libcore/security/src/main/java/java/security/KeyPair.java
index 6399427..b86593b 100644
--- a/libcore/security/src/main/java/java/security/KeyPair.java
+++ b/libcore/security/src/main/java/java/security/KeyPair.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vladimir N. Molotkov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.Serializable;
@@ -30,7 +25,6 @@
  * 
  * @see PrivateKey
  * @see PublicKey
- * @since Android 1.0
  */
 public final class KeyPair implements Serializable {
 
@@ -41,12 +35,11 @@
     /**
      * Constructs a new instance of {@code KeyPair} with a public key and the
      * corresponding private key.
-     * 
+     *
      * @param publicKey
      *            the public key.
      * @param privateKey
      *            the private key.
-     * @since Android 1.0
      */
     public KeyPair(PublicKey publicKey, PrivateKey privateKey) {
         this.privateKey = privateKey;
@@ -55,9 +48,8 @@
 
     /**
      * Returns the private key.
-     * 
+     *
      * @return the private key.
-     * @since Android 1.0
      */
     public PrivateKey getPrivate() {
         return privateKey;
@@ -65,9 +57,8 @@
 
     /**
      * Returns the public key.
-     * 
+     *
      * @return the public key.
-     * @since Android 1.0
      */
     public PublicKey getPublic() {
         return publicKey;
diff --git a/libcore/security/src/main/java/java/security/KeyPairGenerator.java b/libcore/security/src/main/java/java/security/KeyPairGenerator.java
index 5682aa2..2a17e98 100644
--- a/libcore/security/src/main/java/java/security/KeyPairGenerator.java
+++ b/libcore/security/src/main/java/java/security/KeyPairGenerator.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.security.spec.AlgorithmParameterSpec;
@@ -32,9 +27,8 @@
  * {@code KeyPairGenerator} is an engine class which is capable of generating a
  * private key and its related public key utilizing the algorithm it was
  * initialized with.
- * 
+ *
  * @see KeyPairGeneratorSpi
- * @since Android 1.0
  */
 public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
 
@@ -56,10 +50,9 @@
     /**
      * Constructs a new instance of {@code KeyPairGenerator} with the name of
      * the algorithm to use.
-     * 
+     *
      * @param algorithm
      *            the name of algorithm to use
-     * @since Android 1.0
      */
     protected KeyPairGenerator(String algorithm) {
         this.algorithm = algorithm;
@@ -67,9 +60,8 @@
 
     /**
      * Returns the name of the algorithm of this {@code KeyPairGenerator}.
-     * 
+     *
      * @return the name of the algorithm of this {@code KeyPairGenerator}
-     * @since Android 1.0
      */
     public String getAlgorithm() {
         return algorithm;
@@ -86,7 +78,6 @@
      * @throws NoSuchAlgorithmException if the specified algorithm is not available
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}
-     * @since Android 1.0
      */
     public static KeyPairGenerator getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -101,11 +92,10 @@
                 result.algorithm = algorithm;
                 result.provider = engine.provider;
                 return result;
-            } else {
-                result = new KeyPairGeneratorImpl((KeyPairGeneratorSpi) engine.spi,
-                        engine.provider, algorithm);
-                return result;
             }
+            result = new KeyPairGeneratorImpl((KeyPairGeneratorSpi) engine.spi,
+                    engine.provider, algorithm);
+            return result;
         }
     }
 
@@ -123,7 +113,6 @@
      * @throws NoSuchProviderException if the specified provider is not available
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}
-     * @since Android 1.0
      */
     public static KeyPairGenerator getInstance(String algorithm, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
@@ -151,7 +140,6 @@
      * @throws NoSuchAlgorithmException if the specified algorithm is not available
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}
-     * @since Android 1.0
      */
     public static KeyPairGenerator getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
@@ -169,19 +157,17 @@
                 result.algorithm = algorithm;
                 result.provider = provider;
                 return result;
-            } else {
-                result = new KeyPairGeneratorImpl((KeyPairGeneratorSpi) engine.spi,
-                        provider, algorithm);
-                return result;
             }
+            result = new KeyPairGeneratorImpl((KeyPairGeneratorSpi) engine.spi,
+                    provider, algorithm);
+            return result;
         }
     }
 
     /**
      * Returns the provider associated with this {@code KeyPairGenerator}.
-     * 
+     *
      * @return the provider associated with this {@code KeyPairGenerator}
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -191,10 +177,9 @@
      * Initializes this {@code KeyPairGenerator} with the given key size. The
      * default parameter set and a default {@code SecureRandom} instance will be
      * used.
-     * 
+     *
      * @param keysize
      *            the size of the key (number of bits)
-     * @since Android 1.0
      */
     public void initialize(int keysize) {
         initialize(keysize, random);
@@ -204,12 +189,11 @@
      * Initializes this {@code KeyPairGenerator} with the given {@code
      * AlgorithmParameterSpec}. A default {@code SecureRandom} instance will be
      * used.
-     * 
+     *
      * @param param
      *            the parameters to use
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters are not supported
-     * @since Android 1.0
      */
     public void initialize(AlgorithmParameterSpec param)
             throws InvalidAlgorithmParameterException {
@@ -221,9 +205,8 @@
      * is called.
      * <p>
      * This does exactly the same as {@link #generateKeyPair()}.
-     * 
+     *
      * @return a new unique {@code KeyPair} each time this method is called
-     * @since Android 1.0
      */
     public final KeyPair genKeyPair() {
         return generateKeyPair();
@@ -234,10 +217,10 @@
      * is called.
      * <p>
      * This does exactly the same as {@link #genKeyPair()}.
-     * 
+     *
      * @return a new unique {@code KeyPair} each time this method is called
-     * @since Android 1.0
      */
+    @Override
     public KeyPair generateKeyPair() {
         return null;
     }
@@ -245,28 +228,28 @@
     /**
      * Initializes this {@code KeyPairGenerator} with the given key size and the
      * given {@code SecureRandom}. The default parameter set will be used.
-     * 
+     *
      * @param keysize
      *            the key size
      * @param random
      *            the source of randomness
-     * @since Android 1.0
      */
+    @Override
     public void initialize(int keysize, SecureRandom random) {
     }
 
     /**
      * Initializes this {@code KeyPairGenerator} with the given {@code
      * AlgorithmParameterSpec} and the given {@code SecureRandom}.
-     * 
+     *
      * @param param
      *            the parameters to use
      * @param random
      *            the source of randomness
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters are not supported
-     * @since Android 1.0
      */
+    @Override
     public void initialize(AlgorithmParameterSpec param, SecureRandom random)
             throws InvalidAlgorithmParameterException {
     }
@@ -294,18 +277,21 @@
 
         // implementation of initialize(int keysize, SecureRandom random)
         // using corresponding spi initialize() method
+        @Override
         public void initialize(int keysize, SecureRandom random) {
             spiImpl.initialize(keysize, random);
         }
 
         // implementation of generateKeyPair()
         // using corresponding spi generateKeyPair() method
+        @Override
         public KeyPair generateKeyPair() {
             return spiImpl.generateKeyPair();
         }
 
         // implementation of initialize(int keysize, SecureRandom random)
         // using corresponding spi initialize() method
+        @Override
         public void initialize(AlgorithmParameterSpec param, SecureRandom random)
                 throws InvalidAlgorithmParameterException {
             spiImpl.initialize(param, random);
@@ -313,4 +299,4 @@
 
     }
 
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/KeyPairGeneratorSpi.java b/libcore/security/src/main/java/java/security/KeyPairGeneratorSpi.java
index 272c305..e2e22c1 100644
--- a/libcore/security/src/main/java/java/security/KeyPairGeneratorSpi.java
+++ b/libcore/security/src/main/java/java/security/KeyPairGeneratorSpi.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.security.spec.AlgorithmParameterSpec;
@@ -31,14 +26,10 @@
  * definition for {@link KeyPairGenerator}.
  * 
  * @see KeyPairGenerator
- * @since Android 1.0
  */
 public abstract class KeyPairGeneratorSpi {
-    
     /**
      * Constructs a new instance of {@code KeyPairGeneratorSpi}.
-     * 
-     * @since Android 1.0
      */
     public KeyPairGeneratorSpi() {
     }
@@ -46,38 +37,35 @@
     /**
      * Computes and returns a new unique {@code KeyPair} each time this method
      * is called.
-     * 
+     *
      * @return a new unique {@code KeyPair} each time this method is called.
-     * @since Android 1.0
      */
     public abstract KeyPair generateKeyPair();
 
     /**
      * Initializes this {@code KeyPairGeneratorSpi} with the given key size and
      * the given {@code SecureRandom}. The default parameter set will be used.
-     * 
+     *
      * @param keysize
      *            the key size (number of bits).
      * @param random
      *            the source of randomness.
-     * @since Android 1.0
      */
     public abstract void initialize(int keysize, SecureRandom random);
 
     /**
      * Initializes this {@code KeyPairGeneratorSpi} with the given {@code
      * AlgorithmParameterSpec} and the given {@code SecureRandom}.
-     * 
+     *
      * @param params
      *            the parameters to use.
      * @param random
      *            the source of randomness.
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters are not supported.
-     * @since Android 1.0
      */
     public void initialize(AlgorithmParameterSpec params, SecureRandom random)
             throws InvalidAlgorithmParameterException {
         throw new UnsupportedOperationException(Messages.getString("security.2E")); //$NON-NLS-1$
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/KeyRep.java b/libcore/security/src/main/java/java/security/KeyRep.java
index ec1d364..29ccd22 100644
--- a/libcore/security/src/main/java/java/security/KeyRep.java
+++ b/libcore/security/src/main/java/java/security/KeyRep.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vladimir N. Molotkov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.IOException;
@@ -38,8 +33,6 @@
 /**
  * {@code KeyRep} is a standardized representation for serialized {@link Key}
  * objects.
- * 
- * @since Android 1.0
  */
 public class KeyRep implements Serializable {
 
@@ -57,7 +50,7 @@
      * Constructs a new instance of {@code KeyRep} with the specified arguments.
      * The arguments should be obtained from the {@code Key} object that has to
      * be serialized.
-     * 
+     *
      * @param type
      *            the type of the key.
      * @param algorithm
@@ -70,7 +63,6 @@
      * @throws NullPointerException
      *             if {@code type, algorithm, format or encoded} is {@code null}
      *             .
-     * @since Android 1.0
      */
     public KeyRep(Type type,
             String algorithm, String format, byte[] encoded) {
@@ -107,12 +99,11 @@
      * initialized with a {@link X509EncodedKeySpec} using the encoded key
      * bytes.
      * </ul>
-     * 
+     *
      * @return the resolved {@code Key} object.
      * @throws ObjectStreamException
      *             if the {@code Type}|format combination is not recognized, or
      *             the resolution of any key parameter fails.
-     * @since Android 1.0
      */
     protected Object readResolve() throws ObjectStreamException {
         switch (type) {
@@ -174,10 +165,8 @@
 
     /**
      * {@code Type} enumerates the supported key types.
-     * @since Android 1.0
      */
     public static enum Type {
-        
         /**
          * Type for secret keys.
          */
diff --git a/libcore/security/src/main/java/java/security/KeyStore.java b/libcore/security/src/main/java/java/security/KeyStore.java
index 699a9df..02ac01d 100644
--- a/libcore/security/src/main/java/java/security/KeyStore.java
+++ b/libcore/security/src/main/java/java/security/KeyStore.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.File;
@@ -29,6 +24,7 @@
 import java.io.OutputStream;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.Enumeration;
@@ -46,14 +42,12 @@
  * {@code KeyStore} is responsible for maintaining cryptographic keys and their
  * owners.
  * <p>
- * The type of the system key store can be changed by setting the {@code 
+ * The type of the system key store can be changed by setting the {@code
  * 'keystore.type'} property in the file named {@code
  * JAVA_HOME/lib/security/java.security}.
- * </p>
- * 
+ *
  * @see Certificate
  * @see PrivateKey
- * @since Android 1.0
  */
 public class KeyStore {
 
@@ -88,14 +82,13 @@
 
     /**
      * Constructs a new instance of {@code KeyStore} with the given arguments.
-     * 
+     *
      * @param keyStoreSpi
      *            the concrete key store.
      * @param provider
      *            the provider.
      * @param type
      *            the type of the {@code KeyStore} to be constructed.
-     * @since Android 1.0
      */
     protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type) {
         this.type = type;
@@ -118,7 +111,7 @@
 
     /**
      * Returns a new instance of {@code KeyStore} with the specified type.
-     * 
+     *
      * @param type
      *            the type of the returned {@code KeyStore}.
      * @return a new instance of {@code KeyStore} with the specified type.
@@ -128,7 +121,6 @@
      * @throws NullPointerException
      *             if {@code type} is {@code null}.
      * @see #getDefaultType
-     * @since Android 1.0
      */
     public static KeyStore getInstance(String type) throws KeyStoreException {
         if (type == null) {
@@ -147,7 +139,7 @@
     /**
      * Returns a new instance of {@code KeyStore} from the specified provider
      * with the given type.
-     * 
+     *
      * @param type
      *            the type of the returned {@code KeyStore}.
      * @param provider
@@ -161,8 +153,10 @@
      *             if the specified provider is not available.
      * @throws IllegalArgumentException
      *             if {@code provider} is {@code null} or the empty string.
+     * @throws NullPointerException
+     *             if {@code type} is {@code null} (instead of
+     *             NoSuchAlgorithmException) as in 1.4 release
      * @see #getDefaultType
-     * @since Android 1.0
      */
     public static KeyStore getInstance(String type, String provider)
             throws KeyStoreException, NoSuchProviderException {
@@ -183,7 +177,7 @@
     /**
      * Returns a new instance of {@code KeyStore} from the specified provider
      * with the given type.
-     * 
+     *
      * @param type
      *            the type of the returned {@code KeyStore}.
      * @param provider
@@ -195,8 +189,10 @@
      *             KeyStore}.
      * @throws IllegalArgumentException
      *             if {@code provider} is {@code null} or the empty string.
+     * @throws NullPointerException
+     *             if {@code type} is {@code null} (instead of
+     *             NoSuchAlgorithmException) as in 1.4 release
      * @see #getDefaultType
-     * @since Android 1.0
      */
     public static KeyStore getInstance(String type, Provider provider)
             throws KeyStoreException {
@@ -225,10 +221,8 @@
      * The default is specified in the {@code 'keystore.type'} property in the
      * file named {@code JAVA_HOME/lib/security/java.security}. If this property
      * is not set, {@code "jks"} will be used.
-     * </p>
-     * 
+     *
      * @return the default type for {@code KeyStore} instances
-     * @since Android 1.0
      */
     public static final String getDefaultType() {
         String dt = AccessController.doPrivileged(
@@ -243,9 +237,8 @@
 
     /**
      * Returns the provider associated with this {@code KeyStore}.
-     * 
+     *
      * @return the provider associated with this {@code KeyStore}.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -253,9 +246,8 @@
 
     /**
      * Returns the type of this {@code KeyStore}.
-     * 
+     *
      * @return the type of this {@code KeyStore}.
-     * @since Android 1.0
      */
     public final String getType() {
         return type;
@@ -264,7 +256,7 @@
     /**
      * Returns the key with the given alias, using the password to recover the
      * key from the store.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @param password
@@ -277,7 +269,6 @@
      *             if the algorithm for recovering the key is not available.
      * @throws UnrecoverableKeyException
      *             if the key can not be recovered.
-     * @since Android 1.0
      */
     public final Key getKey(String alias, char[] password)
             throws KeyStoreException, NoSuchAlgorithmException,
@@ -292,14 +283,13 @@
 
     /**
      * Returns the certificate chain for the entry with the given alias.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @return the certificate chain for the entry with the given alias, or
      *         {@code null} if the specified alias is not bound to an entry.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
      */
     public final Certificate[] getCertificateChain(String alias)
             throws KeyStoreException {
@@ -313,14 +303,13 @@
 
     /**
      * Returns the trusted certificate for the entry with the given alias.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @return the trusted certificate for the entry with the given alias, or
      *         {@code null} if the specified alias is not bound to an entry.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
      */
     public final Certificate getCertificate(String alias)
             throws KeyStoreException {
@@ -334,14 +323,13 @@
 
     /**
      * Returns the creation date of the entry with the given alias.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @return the creation date, or {@code null} if the specified alias is not
      *         bound to an entry.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
      */
     public final Date getCreationDate(String alias) throws KeyStoreException {
         if (!isInit) {
@@ -356,8 +344,7 @@
      * Associates the given alias with the key, password and certificate chain.
      * <p>
      * If the specified alias already exists, it will be reassigned.
-     * </p>
-     * 
+     *
      * @param alias
      *            the alias for the key.
      * @param key
@@ -371,7 +358,8 @@
      * @throws IllegalArgumentException
      *             if {@code key} is a {@code PrivateKey} and {@code chain} does
      *             not contain any certificates.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code alias} is {@code null}.
      */
     public final void setKeyEntry(String alias, Key key, char[] password,
             Certificate[] chain) throws KeyStoreException {
@@ -394,13 +382,11 @@
      * Associates the given alias with a key and a certificate chain.
      * <p>
      * If the specified alias already exists, it will be reassigned.
-     * </p>
      * <p>
      * If this {@code KeyStore} is of type {@code "jks"}, {@code key} must be
      * encoded conform to the PKS#8 standard as an
      * {@link javax.crypto.EncryptedPrivateKeyInfo}.
-     * </p>
-     * 
+     *
      * @param alias
      *            the alias for the key.
      * @param key
@@ -408,11 +394,13 @@
      * @param chain
      *            the certificate chain.
      * @throws KeyStoreException
-     *             if this {@code KeyStore} is not initialized.
+     *             if this {@code KeyStore} is not initialized or if {@code key}
+     *             is null.
      * @throws IllegalArgumentException
      *             if {@code key} is a {@code PrivateKey} and {@code chain}
      *             does.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code alias} is {@code null}.
      */
     public final void setKeyEntry(String alias, byte[] key, Certificate[] chain)
             throws KeyStoreException {
@@ -428,8 +416,7 @@
      * Associates the given alias with a certificate.
      * <p>
      * If the specified alias already exists, it will be reassigned.
-     * </p>
-     * 
+     *
      * @param alias
      *            the alias for the certificate.
      * @param cert
@@ -438,7 +425,8 @@
      *             if this {@code KeyStore} is not initialized, or an existing
      *             alias is not associated to an entry containing a trusted
      *             certificate, or this method fails for any other reason.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code alias} is {@code null}.
      */
     public final void setCertificateEntry(String alias, Certificate cert)
             throws KeyStoreException {
@@ -453,32 +441,35 @@
     /**
      * Deletes the entry identified with the given alias from this {@code
      * KeyStore}.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized, or if the entry
      *             can not be deleted.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code alias} is {@code null}.
      */
     public final void deleteEntry(String alias) throws KeyStoreException {
-        // BEGIN android-changed
         if (!isInit) {
+            // BEGIN android-changed
             throwNotInitialized();
+            // END android-changed
         }
-        // END android-changed
+        if (alias == null) {
+            throw new NullPointerException(Messages.getString("security.3F")); //$NON-NLS-1$
+        }
         implSpi.engineDeleteEntry(alias);
     }
 
     /**
      * Returns an {@code Enumeration} over all alias names stored in this
      * {@code KeyStore}.
-     * 
+     *
      * @return an {@code Enumeration} over all alias names stored in this
      *         {@code KeyStore}.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
      */
     public final Enumeration<String> aliases() throws KeyStoreException {
         if (!isInit) {
@@ -491,13 +482,14 @@
 
     /**
      * Indicates whether the given alias is present in this {@code KeyStore}.
-     * 
+     *
      * @param alias
      *            the alias of an entry.
      * @return {@code true} if the alias exists, {@code false} otherwise.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code alias} is {@code null}.
      */
     public final boolean containsAlias(String alias) throws KeyStoreException {
         if (!isInit) {
@@ -513,11 +505,10 @@
 
     /**
      * Returns the number of entries stored in this {@code KeyStore}.
-     * 
+     *
      * @return the number of entries stored in this {@code KeyStore}.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
      */
     public final int size() throws KeyStoreException {
         if (!isInit) {
@@ -531,56 +522,63 @@
     /**
      * Indicates whether the specified alias is associated with either a
      * {@link PrivateKeyEntry} or a {@link SecretKeyEntry}.
-     * 
+     *
      * @param alias
      *            the alias of an entry.
      * @return {@code true} if the given alias is associated with a key entry.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code alias} is {@code null}.
      */
     public final boolean isKeyEntry(String alias) throws KeyStoreException {
-        // BEGIN android-changed
         if (!isInit) {
+            // BEGIN android-changed
             throwNotInitialized();
+            // END android-changed
         }
-        // END android-changed
+        if (alias == null) {
+            throw new NullPointerException(Messages.getString("security.3F")); //$NON-NLS-1$
+        }
         return implSpi.engineIsKeyEntry(alias);
     }
 
     /**
      * Indicates whether the specified alias is associated with a
      * {@link TrustedCertificateEntry}.
-     * 
+     *
      * @param alias
      *            the alias of an entry.
      * @return {@code true} if the given alias is associated with a certificate
      *         entry.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code alias} is {@code null}.
      */
     public final boolean isCertificateEntry(String alias)
             throws KeyStoreException {
-        // BEGIN android-changed
         if (!isInit) {
+            // BEGIN android-changed
             throwNotInitialized();
+            // END android-changed
         }
-        // END android-changed
+        if (alias == null) {
+            throw new NullPointerException(Messages.getString("security.3F")); //$NON-NLS-1$
+        }
         return implSpi.engineIsCertificateEntry(alias);
     }
 
     /**
      * Returns the alias associated with the first entry whose certificate
      * matches the specified certificate.
-     * 
+     *
      * @param cert
      *            the certificate to find the associated entry's alias for.
      * @return the alias or {@code null} if no entry with the specified
      *         certificate can be found.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
      */
     public final String getCertificateAlias(Certificate cert)
             throws KeyStoreException {
@@ -596,7 +594,7 @@
      * Writes this {@code KeyStore} to the specified {@code OutputStream}. The
      * data written to the {@code OutputStream} is protected by the specified
      * password.
-     * 
+     *
      * @param stream
      *            the {@code OutputStream} to write the store's data to.
      * @param password
@@ -610,7 +608,6 @@
      * @throws CertificateException
      *             if an exception occurred while storing the certificates of
      *             this {@code KeyStore}.
-     * @since Android 1.0
      */
     public final void store(OutputStream stream, char[] password)
             throws KeyStoreException, IOException, NoSuchAlgorithmException,
@@ -620,23 +617,15 @@
             throwNotInitialized();
             // END android-changed
         }
-        // BEGIN android-removed
-        // copied from a newer version of harmony
-        // Just delegate stream and password to implSpi
-        // if (stream == null) {
-        //     throw new IOException(Messages.getString("security.51")); //$NON-NLS-1$
-        // }
-        // if (password == null) {
-        //     throw new IOException(Messages.getString("security.50")); //$NON-NLS-1$
-        // }
-        // END android-removed
+
+        //Just delegate stream and password to implSpi
         implSpi.engineStore(stream, password);
     }
 
     /**
      * Stores this {@code KeyStore} using the specified {@code
      * LoadStoreParameter}.
-     * 
+     *
      * @param param
      *            the {@code LoadStoreParameter} that specifies how to store
      *            this {@code KeyStore}, maybe {@code null}.
@@ -651,7 +640,6 @@
      *             this {@code KeyStore}.
      * @throws IllegalArgumentException
      *             if the given {@link LoadStoreParameter} is not recognized.
-     * @since Android 1.0
      */
     public final void store(LoadStoreParameter param) throws KeyStoreException,
             IOException, NoSuchAlgorithmException, CertificateException {
@@ -669,7 +657,7 @@
      * {@code KeyStore} or to initialize a {@code KeyStore} which does not rely
      * on an {@code InputStream}. This {@code KeyStore} utilizes the given
      * password to verify the stored data.
-     * 
+     *
      * @param stream
      *            the {@code InputStream} to load this {@code KeyStore}'s data
      *            from or {@code null}.
@@ -682,7 +670,6 @@
      * @throws CertificateException
      *             if an exception occurred while loading the certificates of
      *             this {@code KeyStore}.
-     * @since Android 1.0
      */
     public final void load(InputStream stream, char[] password)
             throws IOException, NoSuchAlgorithmException, CertificateException {
@@ -693,7 +680,7 @@
     /**
      * Loads this {@code KeyStore} using the specified {@code
      * LoadStoreParameter}.
-     * 
+     *
      * @param param
      *            the {@code LoadStoreParameter} that specifies how to load this
      *            {@code KeyStore}, maybe {@code null}.
@@ -706,7 +693,6 @@
      *             this {@code KeyStore}.
      * @throws IllegalArgumentException
      *             if the given {@link LoadStoreParameter} is not recognized.
-     * @since Android 1.0
      */
     public final void load(LoadStoreParameter param) throws IOException,
             NoSuchAlgorithmException, CertificateException {
@@ -717,7 +703,7 @@
     /**
      * Returns the {@code Entry} with the given alias, using the specified
      * {@code ProtectionParameter}.
-     * 
+     *
      * @param alias
      *            the alias of the requested entry.
      * @param param
@@ -731,7 +717,8 @@
      *             if the entry can not be recovered.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code alias} is {@code null}.
      */
     public final Entry getEntry(String alias, ProtectionParameter param)
             throws NoSuchAlgorithmException, UnrecoverableEntryException,
@@ -753,8 +740,7 @@
      * specified {@code ProtectionParameter}.
      * <p>
      * If the specified alias already exists, it will be reassigned.
-     * </p>
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @param entry
@@ -763,7 +749,9 @@
      *            the {@code ProtectionParameter} to protect the entry.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code alias} is {@code null} or {@code entry} is {@code
+     *             null}.
      */
     public final void setEntry(String alias, Entry entry,
             ProtectionParameter param) throws KeyStoreException {
@@ -784,7 +772,7 @@
     /**
      * Indicates whether the entry for the given alias is assignable to the
      * provided {@code Class}.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @param entryClass
@@ -793,7 +781,6 @@
      *         the specified {@code entryClass}.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @since Android 1.0
      */
     public final boolean entryInstanceOf(String alias, 
             Class<? extends KeyStore.Entry> entryClass)
@@ -815,25 +802,20 @@
 
     /**
      * {@code Builder} is used to construct new instances of {@code KeyStore}.
-     * 
-     * @since Android 1.0
      */
     public abstract static class Builder {
         /**
          * Constructs a new instance of {@code Builder}.
-         * 
-         * @since Android 1.0
          */
         protected Builder() {
         }
 
         /**
          * Returns the {@code KeyStore} created by this {@code Builder}.
-         * 
+         *
          * @return the {@code KeyStore} created by this {@code Builder}.
          * @throws KeyStoreException
          *             if an error occurred during construction.
-         * @since Android 1.0
          */
         public abstract KeyStore getKeyStore() throws KeyStoreException;
 
@@ -841,7 +823,7 @@
          * Returns the {@code ProtectionParameter} to be used when a {@code
          * Entry} with the specified alias is requested. Before this method is
          * invoked, {@link #getKeyStore()} must be called.
-         * 
+         *
          * @param alias
          *            the alias for the entry.
          * @return the {@code ProtectionParameter} to be used when a {@code
@@ -854,18 +836,14 @@
          *             invocation of this method.
          * @throws NullPointerException
          *             if {@code alias} is {@code null}.
-         * @since Android 1.0
          */
         public abstract ProtectionParameter getProtectionParameter(String alias)
                 throws KeyStoreException;
-        // BEGIN android-note
-        // renamed parameter
-        // END android-note
 
         /**
          * Returns a new {@code Builder} that holds the given {@code KeyStore}
          * and the given {@code ProtectionParameter}.
-         * 
+         *
          * @param keyStore
          *            the {@code KeyStore} to be held.
          * @param protectionParameter
@@ -878,7 +856,6 @@
          *             {@code null}.
          * @throws IllegalArgumentException
          *             if the given {@code KeyStore} is not initialized.
-         * @since Android 1.0
          */
         public static Builder newInstance(KeyStore keyStore,
                 ProtectionParameter protectionParameter) {
@@ -903,8 +880,7 @@
          * If {@code provider} is {@code null}, all installed providers are
          * searched, otherwise the key store from the specified provider is
          * used.
-         * </p>
-         * 
+         *
          * @param type
          *            the type of the {@code KeyStore} to be constructed.
          * @param provider
@@ -926,7 +902,6 @@
          *             {@code PasswordProtection} or {@code
          *             CallbackHandlerProtection}, {@code file} is not a file or
          *             does not exist at all.
-         * @since Android 1.0
          */
         public static Builder newInstance(String type, Provider provider,
                 File file, ProtectionParameter protectionParameter) {
@@ -965,8 +940,7 @@
          * If {@code provider} is {@code null}, all installed providers are
          * searched, otherwise the key store from the specified provider is
          * used.
-         * </p>
-         * 
+         *
          * @param type
          *            the type of the {@code KeyStore} to be constructed.
          * @param provider
@@ -985,7 +959,6 @@
          *             {@code PasswordProtection} or {@code
          *             CallbackHandlerProtection}, {@code file} is not a file or
          *             does not exist at all.
-         * @since Android 1.0
          */
         public static Builder newInstance(String type, Provider provider,
                 ProtectionParameter protectionParameter) {
@@ -1062,6 +1035,7 @@
             // 
             // Result KeyStore object is returned.
             //
+            @Override
             public synchronized KeyStore getKeyStore() throws KeyStoreException {
                 // If KeyStore was created but in final block some exception was
                 // thrown
@@ -1121,8 +1095,7 @@
 
                     
                     isGetKeyStore = true;
-                    keyStore = ks;
-                    return keyStore;
+                    return ks;
                 } catch (KeyStoreException e) {
                     // Store exception
                     throw lastException = e;
@@ -1139,6 +1112,7 @@
             // Return: ProtectionParameter to get Entry which was saved in
             // KeyStore with defined alias
             //
+            @Override
             public synchronized ProtectionParameter getProtectionParameter(
                     String alias) throws KeyStoreException {
                 if (alias == null) {
@@ -1151,13 +1125,8 @@
             }
         }
 
-        // BEGIN android-note
-        // Added "static" to the class declaration below.
-        // END android-note
         /*
          * Implementation of LoadStoreParameter interface
-         * 
-         * @author Vera Petrashkova
          */
         private static class TmpLSParameter implements LoadStoreParameter {
 
@@ -1166,6 +1135,7 @@
 
             /**
              * Creates TmpLoadStoreParameter object
+             * @param protPar protection parameter
              */
             public TmpLSParameter(ProtectionParameter protPar) {
                 this.protPar = protPar;
@@ -1183,8 +1153,6 @@
     /**
      * {@code CallbackHandlerProtection} is a {@code ProtectionParameter} that
      * encapsulates a {@link CallbackHandler}.
-     * 
-     * @since Android 1.0
      */
     public static class CallbackHandlerProtection implements
             ProtectionParameter {
@@ -1194,12 +1162,11 @@
         /**
          * Constructs a new instance of {@code CallbackHandlerProtection} with
          * the {@code CallbackHandler}.
-         * 
+         *
          * @param handler
          *            the {@code CallbackHandler}.
          * @throws NullPointerException
          *             if {@code handler} is {@code null}.
-         * @since Android 1.0
          */
         public CallbackHandlerProtection(CallbackHandler handler) {
             if (handler == null) {
@@ -1210,9 +1177,8 @@
 
         /**
          * Returns the {@code CallbackHandler}.
-         * 
+         *
          * @return the {@code CallbackHandler}.
-         * @since Android 1.0
          */
         public CallbackHandler getCallbackHandler() {
             return callbackHandler;
@@ -1222,8 +1188,6 @@
     /**
      * {@code Entry} is the common marker interface for a {@code KeyStore}
      * entry.
-     * 
-     * @since Android 1.0
      */
     public static interface Entry {
     }
@@ -1231,19 +1195,17 @@
     /**
      * {@code LoadStoreParameter} represents a parameter that specifies how a
      * {@code KeyStore} can be loaded and stored.
-     * 
+     *
      * @see KeyStore#load(LoadStoreParameter)
      * @see KeyStore#store(LoadStoreParameter)
-     * @since Android 1.0
      */
     public static interface LoadStoreParameter {
         /**
          * Returns the {@code ProtectionParameter} which is used to protect data
          * in the {@code KeyStore}.
-         * 
+         *
          * @return the {@code ProtectionParameter} which is used to protect data
          *         in the {@code KeyStore}, maybe {@code null}.
-         * @since Android 1.0
          */
         public ProtectionParameter getProtectionParameter();
     }
@@ -1251,8 +1213,6 @@
     /**
      * {@code PasswordProtection} is a {@code ProtectionParameter} that protects
      * a {@code KeyStore} using a password.
-     * 
-     * @since Android 1.0
      */
     public static class PasswordProtection implements ProtectionParameter,
             Destroyable {
@@ -1266,27 +1226,22 @@
          * Constructs a new instance of {@code PasswordProtection} with a
          * password. A copy of the password is stored in the new {@code
          * PasswordProtection} object.
-         * 
+         *
          * @param password
          *            the password, maybe {@code null}.
-         * @since Android 1.0
          */
         public PasswordProtection(char[] password) {
-            // BEGIN android-changed
-            // copied from a newer version of harmony
-            if (password != null) {
-                this.password = password.clone();
-            }
-            // END android-changed
+        	if (password != null) {
+        		this.password = password.clone();
+        	}
         }
 
         /**
          * Returns the password.
-         * 
+         *
          * @return the password.
          * @throws IllegalStateException
          *             if the password has been destroyed.
-         * @since Android 1.0
          */
         public synchronized char[] getPassword() {
             if (isDestroyed) {
@@ -1297,10 +1252,9 @@
 
         /**
          * Destroys / invalidates the password.
-         * 
+         *
          * @throws DestroyFailedException
          *             if the password could not be invalidated.
-         * @since Android 1.0
          */
         public synchronized void destroy() throws DestroyFailedException {
             isDestroyed = true;
@@ -1312,10 +1266,9 @@
 
         /**
          * Indicates whether the password is invalidated.
-         * 
+         *
          * @return {@code true} if the password is invalidated, {@code false}
          *         otherwise.
-         * @since Android 1.0
          */
         public synchronized boolean isDestroyed() {
             return isDestroyed;
@@ -1326,8 +1279,6 @@
      * {@code ProtectionParameter} is a marker interface for protection
      * parameters. A protection parameter is used to protect the content of a
      * {@code KeyStore}.
-     * 
-     * @since Android 1.0
      */
     public static interface ProtectionParameter {
     }
@@ -1335,8 +1286,6 @@
     /**
      * {@code PrivateKeyEntry} represents a {@code KeyStore} entry that
      * holds a private key.
-     * 
-     * @since Android 1.0
      */
     public static final class PrivateKeyEntry implements Entry {
         // Store Certificate chain
@@ -1348,7 +1297,7 @@
         /**
          * Constructs a new instance of {@code PrivateKeyEntry} with the given
          * {@code PrivateKey} and the provided certificate chain.
-         * 
+         *
          * @param privateKey
          *            the private key.
          * @param chain
@@ -1361,7 +1310,6 @@
          *             private key does not match the algorithm of the public
          *             key of the first certificate or the certificates are not
          *             all of the same type.
-         * @since Android 1.0
          */
         public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain) {
             if (privateKey == null) {
@@ -1389,18 +1337,29 @@
                 }
             }
             // clone chain - this.chain = (Certificate[])chain.clone();
-            // BEGIN android-changed
-            this.chain = new Certificate[chain.length];
-            // END android-changed
+            boolean isAllX509Certificates = true;
+            // assert chain length > 0
+            for(Certificate cert: chain){
+                if(!(cert instanceof X509Certificate)){
+                    isAllX509Certificates = false;
+                    break;
+                }
+            }
+            
+            if(isAllX509Certificates){
+                this.chain = new X509Certificate[chain.length];
+            }
+            else{
+                this.chain = new Certificate[chain.length];
+            }
             System.arraycopy(chain, 0, this.chain, 0, chain.length);
             this.privateKey = privateKey;
         }
 
         /**
          * Returns the private key.
-         * 
+         *
          * @return the private key.
-         * @since Android 1.0
          */
         public PrivateKey getPrivateKey() {
             return privateKey;
@@ -1408,22 +1367,17 @@
 
         /**
          * Returns the certificate chain.
-         * 
+         *
          * @return the certificate chain.
-         * @since Android 1.0
          */
         public Certificate[] getCertificateChain() {
-            // BEGIN android-changed
-            // copied from a newer version of harmony
             return chain.clone();
-            // END android-changed
         }
 
         /**
          * Returns the certificate corresponding to the private key.
-         * 
+         *
          * @return the certificate corresponding to the private key.
-         * @since Android 1.0
          */
         public Certificate getCertificate() {
             return chain[0];
@@ -1432,12 +1386,12 @@
         /**
          * Returns a string containing a concise, human-readable description of
          * this {@code PrivateKeyEntry}.
-         * 
+         *
          * @return a printable representation for this {@code PrivateKeyEntry}.
-         * @since Android 1.0
          */
+        @Override
         public String toString() {
-            StringBuffer sb = new StringBuffer(
+            StringBuilder sb = new StringBuilder(
                     "PrivateKeyEntry: number of elements in certificate chain is "); //$NON-NLS-1$
             sb.append(Integer.toString(chain.length));
             sb.append("\n"); //$NON-NLS-1$
@@ -1452,8 +1406,6 @@
     /**
      * {@code SecretKeyEntry} represents a {@code KeyStore} entry that
      * holds a secret key.
-     * 
-     * @since Android 1.0
      */
     public static final class SecretKeyEntry implements Entry {
 
@@ -1463,12 +1415,11 @@
         /**
          * Constructs a new instance of {@code SecretKeyEntry} with the given
          * {@code SecretKey}.
-         * 
+         *
          * @param secretKey
          *            the secret key.
          * @throws NullPointerException
          *             if {@code secretKey} is {@code null}.
-         * @since Android 1.0
          */
         public SecretKeyEntry(SecretKey secretKey) {
             if (secretKey == null) {
@@ -1479,9 +1430,8 @@
 
         /**
          * Returns the secret key.
-         * 
+         *
          * @return the secret key.
-         * @since Android 1.0
          */
         public SecretKey getSecretKey() {
             return secretKey;
@@ -1490,13 +1440,13 @@
         /**
          * Returns a string containing a concise, human-readable description of
          * this {@code SecretKeyEntry}.
-         * 
+         *
          * @return a printable representation for this {@code
          *         SecretKeyEntry}.
-         * @since Android 1.0
          */
+        @Override
         public String toString() {
-            StringBuffer sb = new StringBuffer("SecretKeyEntry: algorithm - "); //$NON-NLS-1$
+            StringBuilder sb = new StringBuilder("SecretKeyEntry: algorithm - "); //$NON-NLS-1$
             sb.append(secretKey.getAlgorithm());
             return sb.toString();
         }
@@ -1505,8 +1455,6 @@
     /**
      * {@code TrustedCertificateEntry} represents a {@code KeyStore} entry that
      * holds a trusted certificate.
-     * 
-     * @since Android 1.0
      */
     public static final class TrustedCertificateEntry implements Entry {
 
@@ -1516,12 +1464,11 @@
         /**
          * Constructs a new instance of {@code TrustedCertificateEntry} with the
          * given {@code Certificate}.
-         * 
+         *
          * @param trustCertificate
          *            the trusted certificate.
          * @throws NullPointerException
          *             if {@code trustCertificate} is {@code null}.
-         * @since Android 1.0
          */
         public TrustedCertificateEntry(Certificate trustCertificate) {
             if (trustCertificate == null) {
@@ -1532,9 +1479,8 @@
 
         /**
          * Returns the trusted certificate.
-         * 
+         *
          * @return the trusted certificate.
-         * @since Android 1.0
          */
         public Certificate getTrustedCertificate() {
             return trustCertificate;
@@ -1543,11 +1489,11 @@
         /**
          * Returns a string containing a concise, human-readable description of
          * this {@code TrustedCertificateEntry}.
-         * 
+         *
          * @return a printable representation for this {@code
          *         TrustedCertificateEntry}.
-         * @since Android 1.0
          */
+        @Override
         public String toString() {
             return "Trusted certificate entry:\n" + trustCertificate; //$NON-NLS-1$
         }
diff --git a/libcore/security/src/main/java/java/security/KeyStoreException.java b/libcore/security/src/main/java/java/security/KeyStoreException.java
index 7c697f7..4327f7f 100644
--- a/libcore/security/src/main/java/java/security/KeyStoreException.java
+++ b/libcore/security/src/main/java/java/security/KeyStoreException.java
@@ -15,18 +15,12 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code KeyStoreException} is a general {@code KeyStore} exception.
  * 
  * @see KeyStore
- * @since Android 1.0
  */
 public class KeyStoreException extends GeneralSecurityException {
 
@@ -35,10 +29,9 @@
     /**
      * Constructs a new instance of {@code KeyStoreException} with the
      * given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public KeyStoreException(String msg) {
         super(msg);
@@ -46,8 +39,6 @@
 
     /**
      * Constructs a new instance of {@code KeyStoreException}.
-     * 
-     * @since Android 1.0
      */
     public KeyStoreException() {
     }
@@ -55,12 +46,11 @@
     /**
      * Constructs a new instance of {@code KeyStoreException} with the
      * given message and the cause.
-     * 
+     *
      * @param message
      *            the detail message for this exception.
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public KeyStoreException(String message, Throwable cause) {
         super(message, cause);
@@ -69,10 +59,9 @@
     /**
      * Constructs a new instance of {@code KeyStoreException} with the
      * cause.
-     * 
+     *
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public KeyStoreException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/KeyStoreSpi.java b/libcore/security/src/main/java/java/security/KeyStoreSpi.java
index b02f264..e884123 100644
--- a/libcore/security/src/main/java/java/security/KeyStoreSpi.java
+++ b/libcore/security/src/main/java/java/security/KeyStoreSpi.java
@@ -33,16 +33,15 @@
 /**
  * {@code KeyStoreSpi} is the Service Provider Interface (SPI) definition for
  * {@link KeyStore}.
- * 
+ *
  * @see KeyStore
- * @since Android 1.0
  */
 public abstract class KeyStoreSpi {
 
     /**
      * Returns the key with the given alias, using the password to recover the
      * key from the store.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @param password
@@ -53,41 +52,37 @@
      *             if the algorithm for recovering the key is not available.
      * @throws UnrecoverableKeyException
      *             if the key can not be recovered.
-     * @since Android 1.0
      */
     public abstract Key engineGetKey(String alias, char[] password)
             throws NoSuchAlgorithmException, UnrecoverableKeyException;
 
     /**
      * Returns the certificate chain for the entry with the given alias.
-     * 
+     *
      * @param alias
      *            the alias for the entry
      * @return the certificate chain for the entry with the given alias, or
      *         {@code null} if the specified alias is not bound to an entry.
-     * @since Android 1.0
      */
     public abstract Certificate[] engineGetCertificateChain(String alias);
 
     /**
      * Returns the trusted certificate for the entry with the given alias.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @return the trusted certificate for the entry with the given alias, or
      *         {@code null} if the specified alias is not bound to an entry.
-     * @since Android 1.0
      */
     public abstract Certificate engineGetCertificate(String alias);
 
     /**
      * Returns the creation date of the entry with the given alias.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @return the creation date, or {@code null} if the specified alias is not
      *         bound to an entry.
-     * @since Android 1.0
      */
     public abstract Date engineGetCreationDate(String alias);
 
@@ -95,8 +90,7 @@
      * Associates the given alias with the key, password and certificate chain.
      * <p>
      * If the specified alias already exists, it will be reassigned.
-     * </p>
-     * 
+     *
      * @param alias
      *            the alias for the key.
      * @param key
@@ -111,7 +105,6 @@
      * @throws IllegalArgumentException
      *             if {@code key} is a {@code PrivateKey} and {@code chain} does
      *             not contain any certificates.
-     * @since Android 1.0
      */
     public abstract void engineSetKeyEntry(String alias, Key key,
             char[] password, Certificate[] chain) throws KeyStoreException;
@@ -120,8 +113,7 @@
      * Associates the given alias with a key and a certificate chain.
      * <p>
      * If the specified alias already exists, it will be reassigned.
-     * </p>
-     * 
+     *
      * @param alias
      *            the alias for the key.
      * @param key
@@ -133,7 +125,6 @@
      * @throws IllegalArgumentException
      *             if {@code key} is a {@code PrivateKey} and {@code chain}
      *             does.
-     * @since Android 1.0
      */
     public abstract void engineSetKeyEntry(String alias, byte[] key,
             Certificate[] chain) throws KeyStoreException;
@@ -142,8 +133,7 @@
      * Associates the given alias with a certificate.
      * <p>
      * If the specified alias already exists, it will be reassigned.
-     * </p>
-     * 
+     *
      * @param alias
      *            the alias for the certificate.
      * @param cert
@@ -152,7 +142,6 @@
      *             if an existing alias is not associated to an entry containing
      *             a trusted certificate, or this method fails for any other
      *             reason.
-     * @since Android 1.0
      */
     public abstract void engineSetCertificateEntry(String alias,
             Certificate cert) throws KeyStoreException;
@@ -160,12 +149,11 @@
     /**
      * Deletes the entry identified with the given alias from this {@code
      * KeyStoreSpi}.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @throws KeyStoreException
      *             if the entry can not be deleted.
-     * @since Android 1.0
      */
     public abstract void engineDeleteEntry(String alias)
             throws KeyStoreException;
@@ -173,63 +161,57 @@
     /**
      * Returns an {@code Enumeration} over all alias names stored in this
      * {@code KeyStoreSpi}.
-     * 
+     *
      * @return an {@code Enumeration} over all alias names stored in this
      *         {@code KeyStoreSpi}.
-     * @since Android 1.0
      */
     public abstract Enumeration<String> engineAliases();
 
     /**
      * Indicates whether the given alias is present in this {@code KeyStoreSpi}.
-     * 
+     *
      * @param alias
      *            the alias of an entry.
      * @return {@code true} if the alias exists, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean engineContainsAlias(String alias);
 
     /**
      * Returns the number of entries stored in this {@code KeyStoreSpi}.
-     * 
+     *
      * @return the number of entries stored in this {@code KeyStoreSpi}.
-     * @since Android 1.0
      */
     public abstract int engineSize();
 
     /**
      * Indicates whether the specified alias is associated with either a
      * {@link KeyStore.PrivateKeyEntry} or a {@link KeyStore.SecretKeyEntry}.
-     * 
+     *
      * @param alias
      *            the alias of an entry.
      * @return {@code true} if the given alias is associated with a key entry.
-     * @since Android 1.0
      */
     public abstract boolean engineIsKeyEntry(String alias);
 
     /**
      * Indicates whether the specified alias is associated with a
      * {@link KeyStore.TrustedCertificateEntry}.
-     * 
+     *
      * @param alias
      *            the alias of an entry.
      * @return {@code true} if the given alias is associated with a certificate
      *         entry.
-     * @since Android 1.0
      */
     public abstract boolean engineIsCertificateEntry(String alias);
 
     /**
      * Returns the alias associated with the first entry whose certificate
      * matches the specified certificate.
-     * 
+     *
      * @param cert
      *            the certificate to find the associated entry's alias for.
      * @return the alias or {@code null} if no entry with the specified
      *         certificate can be found.
-     * @since Android 1.0
      */
     public abstract String engineGetCertificateAlias(Certificate cert);
 
@@ -237,7 +219,7 @@
      * Writes this {@code KeyStoreSpi} to the specified {@code OutputStream}.
      * The data written to the {@code OutputStream} is protected by the
      * specified password.
-     * 
+     *
      * @param stream
      *            the {@code OutputStream} to write the store's data to.
      * @param password
@@ -249,7 +231,6 @@
      * @throws CertificateException
      *             if the an exception occurred while storing the certificates
      *             of this code {@code KeyStoreSpi}.
-     * @since Android 1.0
      */
     public abstract void engineStore(OutputStream stream, char[] password)
             throws IOException, NoSuchAlgorithmException, CertificateException;
@@ -257,7 +238,7 @@
     /**
      * Stores this {@code KeyStoreSpi} using the specified {@code
      * LoadStoreParameter}.
-     * 
+     *
      * @param param
      *            the {@code LoadStoreParameter} that specifies how to store
      *            this {@code KeyStoreSpi}, maybe {@code null}.
@@ -271,7 +252,6 @@
      * @throws IllegalArgumentException
      *             if the given {@link KeyStore.LoadStoreParameter} is not
      *             recognized.
-     * @since Android 1.0
      */
     public void engineStore(KeyStore.LoadStoreParameter param)
             throws IOException, NoSuchAlgorithmException, CertificateException {
@@ -281,7 +261,7 @@
     /**
      * Loads this {@code KeyStoreSpi} from the given {@code InputStream}.
      * Utilizes the given password to verify the stored data.
-     * 
+     *
      * @param stream
      *            the {@code InputStream} to load this {@code KeyStoreSpi}'s
      *            data from.
@@ -294,7 +274,6 @@
      * @throws CertificateException
      *             if the an exception occurred while loading the certificates
      *             of this code {@code KeyStoreSpi}.
-     * @since Android 1.0
      */
     public abstract void engineLoad(InputStream stream, char[] password)
             throws IOException, NoSuchAlgorithmException, CertificateException;
@@ -302,7 +281,7 @@
     /**
      * Loads this {@code KeyStoreSpi} using the specified {@code
      * LoadStoreParameter}.
-     * 
+     *
      * @param param
      *            the {@code LoadStoreParameter} that specifies how to load this
      *            {@code KeyStoreSpi}, maybe {@code null}.
@@ -316,7 +295,6 @@
      * @throws IllegalArgumentException
      *             if the given {@link KeyStore.LoadStoreParameter} is not
      *             recognized.
-     * @since Android 1.0
      */
     public void engineLoad(KeyStore.LoadStoreParameter param)
             throws IOException, NoSuchAlgorithmException, CertificateException {
@@ -351,7 +329,7 @@
     /**
      * Returns the {@code Entry} with the given alias, using the specified
      * {@code ProtectionParameter}.
-     * 
+     *
      * @param alias
      *            the alias of the requested entry.
      * @param protParam
@@ -365,7 +343,6 @@
      *             if the entry can not be recovered.
      * @throws KeyStoreException
      *             if this operation fails
-     * @since Android 1.0
      */
     public KeyStore.Entry engineGetEntry(String alias,
             KeyStore.ProtectionParameter protParam) throws KeyStoreException,
@@ -417,8 +394,7 @@
      * specified {@code ProtectionParameter}.
      * <p>
      * If the specified alias already exists, it will be reassigned.
-     * </p>
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @param entry
@@ -427,7 +403,6 @@
      *            the {@code ProtectionParameter} to protect the entry.
      * @throws KeyStoreException
      *             if this operation fails.
-     * @since Android 1.0
      */
     public void engineSetEntry(String alias, KeyStore.Entry entry,
             KeyStore.ProtectionParameter protParam) throws KeyStoreException {
@@ -486,14 +461,13 @@
     /**
      * Indicates whether the entry for the given alias is assignable to the
      * provided {@code Class}.
-     * 
+     *
      * @param alias
      *            the alias for the entry.
      * @param entryClass
      *            the type of the entry.
      * @return {@code true} if the {@code Entry} for the alias is assignable to
      *         the specified {@code entryClass}.
-     * @since Android 1.0
      */
     public boolean engineEntryInstanceOf(String alias,
             Class<? extends KeyStore.Entry> entryClass) {
diff --git a/libcore/security/src/main/java/java/security/MessageDigest.java b/libcore/security/src/main/java/java/security/MessageDigest.java
index 97cbdcc..cb8fc08 100644
--- a/libcore/security/src/main/java/java/security/MessageDigest.java
+++ b/libcore/security/src/main/java/java/security/MessageDigest.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.nio.ByteBuffer;
@@ -31,12 +26,11 @@
  * {@code MessageDigest} is an engine class which is capable of generating one
  * way hash values for arbitrary input, utilizing the algorithm it was
  * initialized with.
- * 
+ *
  * @see MessageDigestSpi
- * @since Android 1.0
  */
 public abstract class MessageDigest extends MessageDigestSpi {
-    
+
     // The service name
     private static final String SERVICE = "MessageDigest"; //$NON-NLS-1$
 
@@ -55,7 +49,6 @@
      * 
      * @param algorithm
      *            the name of algorithm to use
-     * @since Android 1.0
      */
     protected MessageDigest(String algorithm) {
         this.algorithm = algorithm;
@@ -73,7 +66,6 @@
      *             if the specified algorithm is not available
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}
-     * @since Android 1.0
      */
     public static MessageDigest getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -88,11 +80,9 @@
                 result.algorithm = algorithm;
                 result.provider = engine.provider;
                 return result;
-            } else {
-                result = new MessageDigestImpl((MessageDigestSpi) engine.spi,
-                        engine.provider, algorithm);
-                return result;
             }
+            return new MessageDigestImpl((MessageDigestSpi) engine.spi,
+                    engine.provider, algorithm);
         }
     }
 
@@ -112,16 +102,17 @@
      *             if the specified provider is not available
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}
-     * @since Android 1.0
      */
     public static MessageDigest getInstance(String algorithm, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
         if ((provider == null) || (provider.length() == 0)) {
-            throw new IllegalArgumentException(Messages.getString("security.02")); //$NON-NLS-1$
+            throw new IllegalArgumentException(Messages
+                    .getString("security.02")); //$NON-NLS-1$
         }
         Provider p = Security.getProvider(provider);
         if (p == null) {
-            throw new NoSuchProviderException(Messages.getString("security.03", provider)); //$NON-NLS-1$
+            throw new NoSuchProviderException(Messages.getString(
+                    "security.03", provider)); //$NON-NLS-1$
         }
         return getInstance(algorithm, p);
     }
@@ -140,12 +131,12 @@
      *             if the specified algorithm is not available
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}
-     * @since Android 1.0
      */
     public static MessageDigest getInstance(String algorithm, Provider provider)
             throws NoSuchAlgorithmException {
         if (provider == null) {
-            throw new IllegalArgumentException(Messages.getString("security.04")); //$NON-NLS-1$
+            throw new IllegalArgumentException(Messages
+                    .getString("security.04")); //$NON-NLS-1$
         }
         if (algorithm == null) {
             throw new NullPointerException(Messages.getString("security.01")); //$NON-NLS-1$
@@ -158,19 +149,16 @@
                 result.algorithm = algorithm;
                 result.provider = provider;
                 return result;
-            } else {
-                result = new MessageDigestImpl((MessageDigestSpi) engine.spi,
-                        provider, algorithm);
-                return result;
             }
+            result = new MessageDigestImpl((MessageDigestSpi) engine.spi,
+                    provider, algorithm);
+            return result;
         }
     }
 
     /**
      * Puts this {@code MessageDigest} back in an initial state, such that it is
      * ready to compute a one way hash value.
-     * 
-     * @since Android 1.0
      */
     public void reset() {
         engineReset();
@@ -200,11 +188,10 @@
      * @throws IllegalArgumentException
      *             if {@code offset} or {@code len} are not valid in respect to
      *             {@code input}
-     * @since Android 1.0
      */
     public void update(byte[] input, int offset, int len) {
         if (input == null ||
-                // offset < 0 || len < 0 ||
+        // offset < 0 || len < 0 ||
                 // checks for negative values are commented out intentionally
                 // see HARMONY-1120 for details
                 (long) offset + (long) len > input.length) {
@@ -221,7 +208,6 @@
      *            the {@code byte} array
      * @throws NullPointerException
      *             if {@code input} is {@code null}
-     * @since Android 1.0
      */
     public void update(byte[] input) {
         if (input == null) {
@@ -259,11 +245,10 @@
      *             if {@code offset} or {@code len} are not valid in respect to
      *             {@code buf}
      * @see #reset()
-     * @since Android 1.0
      */
     public int digest(byte[] buf, int offset, int len) throws DigestException {
         if (buf == null ||
-                // offset < 0 || len < 0 ||
+        // offset < 0 || len < 0 ||
                 // checks for negative values are commented out intentionally
                 // see HARMONY-1148 for details
                 (long) offset + (long) len > buf.length) {
@@ -282,7 +267,6 @@
      *            the {@code byte} array
      * @return the computed one way hash value
      * @see #reset()
-     * @since Android 1.0
      */
     public byte[] digest(byte[] input) {
         update(input);
@@ -294,8 +278,8 @@
      * {@code MessageDigest} including the name of its algorithm.
      * 
      * @return a printable representation for this {@code MessageDigest}
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         return "MESSAGE DIGEST " + algorithm; //$NON-NLS-1$
     }
@@ -309,7 +293,6 @@
      * @param digestb
      *            the second digest to be compared
      * @return {@code true} if the two hashes are equal, {@code false} otherwise
-     * @since Android 1.0
      */
     public static boolean isEqual(byte[] digesta, byte[] digestb) {
         if (digesta.length != digestb.length) {
@@ -327,7 +310,6 @@
      * Returns the name of the algorithm of this {@code MessageDigest}.
      * 
      * @return the name of the algorithm of this {@code MessageDigest}
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -337,7 +319,6 @@
      * Returns the provider associated with this {@code MessageDigest}.
      * 
      * @return the provider associated with this {@code MessageDigest}
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -349,7 +330,6 @@
      * {@code 0} is returned.
      * 
      * @return the digest length in bytes, or {@code 0}
-     * @since Android 1.0
      */
     public final int getDigestLength() {
         int l = engineGetDigestLength();
@@ -367,12 +347,12 @@
         }
     }
 
+    @Override
     public Object clone() throws CloneNotSupportedException {
         if (this instanceof Cloneable) {
             return super.clone();
-        } else {
-            throw new CloneNotSupportedException();
         }
+        throw new CloneNotSupportedException();
     }
 
     /**
@@ -380,7 +360,6 @@
      * 
      * @param input
      *            the {@code ByteBuffer}
-     * @since Android 1.0
      */
     public final void update(ByteBuffer input) {
         engineUpdate(input);
@@ -392,7 +371,7 @@
      * 
      */
     private static class MessageDigestImpl extends MessageDigest {
-        
+
         // MessageDigestSpi implementation
         private MessageDigestSpi spiImpl;
 
@@ -405,38 +384,44 @@
         }
 
         // engineReset() implementation
+        @Override
         protected void engineReset() {
             spiImpl.engineReset();
         }
 
         // engineDigest() implementation
+        @Override
         protected byte[] engineDigest() {
             return spiImpl.engineDigest();
         }
 
         // engineGetDigestLength() implementation
+        @Override
         protected int engineGetDigestLength() {
             return spiImpl.engineGetDigestLength();
         }
 
         // engineUpdate() implementation
+        @Override
         protected void engineUpdate(byte arg0) {
             spiImpl.engineUpdate(arg0);
         }
 
         // engineUpdate() implementation
+        @Override
         protected void engineUpdate(byte[] arg0, int arg1, int arg2) {
             spiImpl.engineUpdate(arg0, arg1, arg2);
         }
 
         // Returns a clone if the spiImpl is cloneable
+        @Override
         public Object clone() throws CloneNotSupportedException {
             if (spiImpl instanceof Cloneable) {
                 MessageDigestSpi spi = (MessageDigestSpi) spiImpl.clone();
                 return new MessageDigestImpl(spi, getProvider(), getAlgorithm());
-            } else {
-                throw new CloneNotSupportedException();
             }
+            
+            throw new CloneNotSupportedException();
         }
     }
 }
diff --git a/libcore/security/src/main/java/java/security/MessageDigestSpi.java b/libcore/security/src/main/java/java/security/MessageDigestSpi.java
index ae5ed32..52ad3cd 100644
--- a/libcore/security/src/main/java/java/security/MessageDigestSpi.java
+++ b/libcore/security/src/main/java/java/security/MessageDigestSpi.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.nio.ByteBuffer;
@@ -33,7 +28,6 @@
  * a fingerprint for a stream of bytes.
  * 
  * @see MessageDigest
- * @since Android 1.0
  */
 public abstract class MessageDigestSpi {
     
@@ -42,7 +36,6 @@
      * implement this function {@code 0} is returned.
      * 
      * @return the digest length in bytes, or {@code 0}.
-     * @since Android 1.0
      */
     protected int engineGetDigestLength() {
         return 0;
@@ -54,10 +47,9 @@
      * @param input
      *            the {@code byte} to update this {@code MessageDigestSpi} with.
      * @see #engineReset()
-     * @since Android 1.0
      */
     protected abstract void engineUpdate(byte input);
-
+    
     /**
      * Updates this {@code MessageDigestSpi} using the given {@code byte[]}.
      * 
@@ -70,7 +62,6 @@
      * @throws IllegalArgumentException
      *             if {@code offset} or {@code len} are not valid in respect to
      *             {@code input}.
-     * @since Android 1.0
      */
     protected abstract void engineUpdate(byte[] input, int offset, int len);
     
@@ -79,7 +70,6 @@
      * 
      * @param input
      *            the {@code ByteBuffer}.
-     * @since Android 1.0
      */
     protected void engineUpdate(ByteBuffer input) {
         if (!input.hasRemaining()) {
@@ -107,7 +97,6 @@
      * 
      * @return the computed one way hash value.
      * @see #engineReset()
-     * @since Android 1.0
      */
     protected abstract byte[] engineDigest();
     
@@ -129,7 +118,6 @@
      *             if {@code offset} or {@code len} are not valid in respect to
      *             {@code buf}.
      * @see #engineReset()
-     * @since Android 1.0
      */
     protected int engineDigest(byte[] buf, int offset, int len)
                     throws DigestException {
@@ -156,11 +144,10 @@
     /**
      * Puts this {@code MessageDigestSpi} back in an initial state, such that it
      * is ready to compute a one way hash value.
-     * 
-     * @since Android 1.0
      */
     protected abstract void engineReset();
     
+    @Override
     public Object clone() throws CloneNotSupportedException {
         return super.clone();
     }
diff --git a/libcore/security/src/main/java/java/security/NoSuchAlgorithmException.java b/libcore/security/src/main/java/java/security/NoSuchAlgorithmException.java
index 3324076..8ef2e3f 100644
--- a/libcore/security/src/main/java/java/security/NoSuchAlgorithmException.java
+++ b/libcore/security/src/main/java/java/security/NoSuchAlgorithmException.java
@@ -15,18 +15,11 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code NoSuchAlgorithmException} indicates that a requested algorithm could
  * not be found.
- * 
- * @since Android 1.0
  */
 public class NoSuchAlgorithmException extends GeneralSecurityException {
 
@@ -35,10 +28,9 @@
     /**
      * Constructs a new instance of {@code NoSuchAlgorithmException} with the
      * given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NoSuchAlgorithmException(String msg) {
         super(msg);
@@ -46,8 +38,6 @@
 
     /**
      * Constructs a new instance of {@code NoSuchAlgorithmException}.
-     * 
-     * @since Android 1.0
      */
     public NoSuchAlgorithmException() {
     }
@@ -55,12 +45,11 @@
     /**
      * Constructs a new instance of {@code NoSuchAlgorithmException} with the
      * given message and the cause.
-     * 
+     *
      * @param message
      *            the detail message for this exception.
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public NoSuchAlgorithmException(String message, Throwable cause) {
         super(message, cause);
@@ -69,10 +58,9 @@
     /**
      * Constructs a new instance of {@code NoSuchAlgorithmException} with the
      * cause.
-     * 
+     *
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public NoSuchAlgorithmException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/NoSuchProviderException.java b/libcore/security/src/main/java/java/security/NoSuchProviderException.java
index f016ce6..57cda40 100644
--- a/libcore/security/src/main/java/java/security/NoSuchProviderException.java
+++ b/libcore/security/src/main/java/java/security/NoSuchProviderException.java
@@ -15,18 +15,11 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code NoSuchProviderException} indicates that a requested security provider
  * could not be found.
- * 
- * @since Android 1.0
  */
 public class NoSuchProviderException extends GeneralSecurityException {
 
@@ -35,10 +28,9 @@
     /**
      * Constructs a new instance of {@code NoSuchProviderException} with the
      * given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NoSuchProviderException(String msg) {
         super(msg);
@@ -46,8 +38,6 @@
 
     /**
      * Constructs a new instance of {@code NoSuchProviderException}.
-     * 
-     * @since Android 1.0
      */
     public NoSuchProviderException() {
     }
diff --git a/libcore/security/src/main/java/java/security/Permission.java b/libcore/security/src/main/java/java/security/Permission.java
index 93e769c..26bdfcd 100644
--- a/libcore/security/src/main/java/java/security/Permission.java
+++ b/libcore/security/src/main/java/java/security/Permission.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.Serializable;
@@ -29,8 +24,6 @@
  * participate in the access control security framework around
  * {@link AccessController} and {@link AccessControlContext}. A permission
  * constitutes of a name and associated actions.
- * 
- * @since Android 1.0
  */
 public abstract class Permission implements Guard, Serializable {
 
@@ -45,46 +38,44 @@
      * <p>
      * The {@link #implies(Permission)} method should be used for making access
      * control checks.
-     * </p>
-     * 
+     *
      * @param obj
      *            object to be compared for equality with this {@code
      *            Permission}.
      * @return {@code true} if the specified object is equal to this {@code
      *         Permission}, otherwise {@code false}.
-     * @since Android 1.0
      */
+    @Override
     public abstract boolean equals(Object obj);
 
     /**
      * Returns the hash code value for this {@code Permission}. Returns the same
      * hash code for {@code Permission}s that are equal to each other as
      * required by the general contract of {@link Object#hashCode}.
-     * 
+     *
      * @return the hash code value for this {@code Permission}.
      * @see Object#equals(Object)
      * @see Permission#equals(Object)
-     * @since Android 1.0
      */
+    @Override
     public abstract int hashCode();
 
     /**
      * Returns a comma separated string identifying the actions associated with
      * this permission. The returned actions are in canonical form. For example:
-     * 
+     *
      * <pre>
-     * sp0 = new SocketPermission(&quot;www.google.com&quot;, &quot;connect,resolve&quot;)
-     * sp1 = new SocketPermission(&quot;www.google.com&quot;, &quot;resolve,connect&quot;)
+     * sp0 = new SocketPermission(&quot;www.example.com&quot;, &quot;connect,resolve&quot;)
+     * sp1 = new SocketPermission(&quot;www.example.com&quot;, &quot;resolve,connect&quot;)
      * sp0.getActions().equals(sp1.getActions()) //yields true
      * </pre>
-     * 
+     *
      * Both permissions return "connect,resolve" (in that order) if {@code
      * #getActions()} is invoked. Returns an empty String, if no actions are
      * associated with this permission.
-     * 
+     *
      * @return the actions associated with this permission or an empty string if
      *         no actions are associated with this permission.
-     * @since Android 1.0
      */
     public abstract String getActions();
 
@@ -92,21 +83,19 @@
      * Indicates whether the specified permission is implied by this permission.
      * The {@link AccessController} uses this method to check whether permission
      * protected access is allowed with the present policy.
-     * 
+     *
      * @param permission
      *            the permission to check against this permission.
      * @return {@code true} if the specified permission is implied by this
      *         permission, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean implies(Permission permission);
 
     /**
      * Constructs a new instance of {@code Permission} with its name.
-     * 
+     *
      * @param name
      *            the name of the permission.
-     * @since Android 1.0
      */
     public Permission(String name) {
         this.name = name;
@@ -114,9 +103,8 @@
 
     /**
      * Returns the name of this permission.
-     * 
+     *
      * @return the name of this permission.
-     * @since Android 1.0
      */
     public final String getName() {
         return name;
@@ -126,7 +114,7 @@
      * Invokes {@link SecurityManager#checkPermission(Permission)} with this
      * permission as its argument. This method implements the {@link Guard}
      * interface.
-     * 
+     *
      * @param obj
      *            as specified in {@link Guard#checkGuard(Object)} but ignored
      *            in this implementation.
@@ -134,7 +122,6 @@
      *             if this permission is not granted.
      * @see Guard
      * @see SecurityManager#checkPermission(Permission)
-     * @since Android 1.0
      */
     public void checkGuard(Object obj) throws SecurityException {
         SecurityManager sm = System.getSecurityManager();
@@ -150,11 +137,9 @@
      * <p>
      * Subclasses may override this method to return an appropriate collection
      * for the specific permissions they implement.
-     * </p>
-     * 
+     *
      * @return an empty {@link PermissionCollection} or {@code null} if any
      *         permission collection can be used.
-     * @since Android 1.0
      */
     public PermissionCollection newPermissionCollection() {
         return null;
@@ -163,10 +148,10 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * this {@code Permission} including its name and its actions.
-     * 
+     *
      * @return a printable representation for this {@code Permission}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         String actions = getActions();
         actions = (actions == null || actions.length() == 0) ? "" : " " //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/libcore/security/src/main/java/java/security/PermissionCollection.java b/libcore/security/src/main/java/java/security/PermissionCollection.java
index 2502123..56b6cd0 100644
--- a/libcore/security/src/main/java/java/security/PermissionCollection.java
+++ b/libcore/security/src/main/java/java/security/PermissionCollection.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.Serializable;
@@ -37,12 +32,8 @@
  * method returns {@code null}, then a {@code PermissionCollection} of any type
  * can be used. If a collection is returned, it must be used for holding several
  * permissions of the particular type.
- * </p>
  * <p>
  * Subclasses must be implemented thread save.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class PermissionCollection implements Serializable {
 
@@ -57,7 +48,6 @@
      *            the {@code Permission} to add.
      * @throws IllegalStateException
      *             if the collection is read only.
-     * @since Android 1.0
      */
     public abstract void add(Permission permission);
 
@@ -66,7 +56,6 @@
      * {@code PermissionCollection}.
      * 
      * @return an enumeration over all {@link Permission}s.
-     * @since Android 1.0
      */
     public abstract Enumeration<Permission> elements();
 
@@ -78,7 +67,6 @@
      *            the permission to check.
      * @return {@code true} if the given permission is implied by the
      *         permissions in this collection, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean implies(Permission permission);
 
@@ -88,7 +76,6 @@
      * 
      * @return {@code true} if the receiver is read only, {@code false} if new
      *         elements can still be added to this {@code PermissionCollection}.
-     * @since Android 1.0
      */
     public boolean isReadOnly() {
         return readOnly;
@@ -97,8 +84,6 @@
     /**
      * Marks this {@code PermissionCollection} as read only, so that no new
      * permissions can be added to it.
-     * 
-     * @since Android 1.0
      */
     public void setReadOnly() {
         readOnly = true;
@@ -109,11 +94,11 @@
      * {@code PermissionCollection}.
      * 
      * @return a printable representation for this {@code PermissionCollection}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        List elist = new ArrayList(100);
-        Enumeration elenum = elements();
+        List<String> elist = new ArrayList<String>(100);
+        Enumeration<Permission> elenum = elements();
         String superStr = super.toString();
         int totalLength = superStr.length() + 5;
         if (elenum != null) {
@@ -125,12 +110,11 @@
         }
         int esize = elist.size();
         totalLength += esize * 4;
-        //FIXME StringBuffer --> StringBuilder
-        StringBuffer result = new StringBuffer(totalLength).append(superStr)
+        StringBuilder result = new StringBuilder(totalLength).append(superStr)
             .append(" ("); //$NON-NLS-1$
         for (int i = 0; i < esize; i++) {
-            result.append("\n  ").append(elist.get(i).toString()); //$NON-NLS-1$
+            result.append("\n ").append(elist.get(i).toString()); //$NON-NLS-1$
         }
-        return result.append("\n)").toString(); //$NON-NLS-1$
+        return result.append("\n)\n").toString(); //$NON-NLS-1$
     }
 }
diff --git a/libcore/security/src/main/java/java/security/Permissions.java b/libcore/security/src/main/java/java/security/Permissions.java
index b9b13c6..e8d3375 100644
--- a/libcore/security/src/main/java/java/security/Permissions.java
+++ b/libcore/security/src/main/java/java/security/Permissions.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.IOException;
@@ -44,8 +39,6 @@
  * {@link Permission#newPermissionCollection()}. For permissions which do not
  * provide a dedicated {@code PermissionCollection}, a default permission
  * collection, based on a hash table, will be used.
- * 
- * @since Android 1.0
  */
 public final class Permissions extends PermissionCollection implements
     Serializable {
@@ -65,7 +58,7 @@
      * Adds the given {@code Permission} to this heterogeneous {@code
      * PermissionCollection}. The {@code permission} is stored in its
      * appropriate {@code PermissionCollection}.
-     * 
+     *
      * @param permission
      *            the {@code Permission} to be added.
      * @throws SecurityException
@@ -73,7 +66,6 @@
      *             {@code true}.
      * @throws NullPointerException
      *             if {@code permission} is {@code null}.
-     * @since Android 1.0
      */
     public void add(Permission permission) {
         if (isReadOnly()) {
@@ -223,9 +215,10 @@
         Map perms = (Map)fields.get("perms", null); //$NON-NLS-1$
         klasses = new HashMap();
         synchronized (klasses) {
-            for (Iterator iter = perms.keySet().iterator(); iter.hasNext();) {
-                Class key = (Class)iter.next();
-                PermissionCollection pc = (PermissionCollection)perms.get(key);
+            for (Iterator iter = perms.entrySet().iterator(); iter.hasNext();) {
+                Map.Entry entry = (Map.Entry)  iter.next();
+                Class key = (Class) entry.getKey();
+                PermissionCollection pc = (PermissionCollection) entry.getValue();
                 if (key != pc.elements().nextElement().getClass()) {
                     throw new InvalidObjectException(Messages.getString("security.22")); //$NON-NLS-1$
                 }
diff --git a/libcore/security/src/main/java/java/security/PermissionsHash.java b/libcore/security/src/main/java/java/security/PermissionsHash.java
index 69d2b07..4c9e0c9 100644
--- a/libcore/security/src/main/java/java/security/PermissionsHash.java
+++ b/libcore/security/src/main/java/java/security/PermissionsHash.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.util.Enumeration;
@@ -30,28 +25,21 @@
 /**
  * A default {@code PermissionCollection} implementation that uses a hashtable.
  * Each hashtable entry stores a Permission object as both the key and the
- * value. <br>
+ * value.
+ * <p>
  * This {@code PermissionCollection} is intended for storing &quot;neutral&quot;
- * permissions which do not require special collection. </br>
- * 
- * @since Android 1.0
+ * permissions which do not require special collection.
  */
 
 final class PermissionsHash extends PermissionCollection {
 
-    /**
-     * @com.intel.drl.spec_ref
-     */
     private static final long serialVersionUID = -8491988220802933440L;
 
-    /**
-     * @com.intel.drl.spec_ref
-     */
     private final Hashtable perms = new Hashtable();
 
     /**
      * Adds the argument to the collection.
-     * 
+     *
      * @param permission
      *            the permission to add to the collection.
      */
@@ -61,8 +49,7 @@
 
     /**
      * Returns an enumeration of the permissions in the receiver.
-     * 
-     * 
+     *
      * @return Enumeration the permissions in the receiver.
      */
     public Enumeration elements() {
@@ -72,8 +59,7 @@
     /**
      * Indicates whether the argument permission is implied by the permissions
      * contained in the receiver.
-     * 
-     * 
+     *
      * @return boolean <code>true</code> if the argument permission is implied
      *         by the permissions in the receiver, and <code>false</code> if
      *         it is not.
diff --git a/libcore/security/src/main/java/java/security/Policy.java b/libcore/security/src/main/java/java/security/Policy.java
index 21b13b0..d5719a3 100644
--- a/libcore/security/src/main/java/java/security/Policy.java
+++ b/libcore/security/src/main/java/java/security/Policy.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.util.Enumeration;
@@ -36,12 +31,8 @@
  * The system policy can be changed by setting the {@code 'policy.provider'}
  * property in the file named {@code JAVA_HOME/lib/security/java.security} to
  * the fully qualified class name of the desired {@code Policy}.
- * </p>
  * <p>
  * Only one instance of a {@code Policy} is active at any time.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class Policy {
     
@@ -68,20 +59,16 @@
      * domain (i.e. system classes). System classes are always given
      * full permissions (i.e. AllPermission). This can not be changed by
      * installing a new policy.
-     * </p>
-     * 
+     *
      * @param cs
      *            the {@code CodeSource} to compute the permissions for.
      * @return the permissions that are granted to the specified {@code
      *         CodeSource}.
-     * @since Android 1.0
      */
     public abstract PermissionCollection getPermissions(CodeSource cs);
 
     /**
      * Reloads the policy configuration for this {@code Policy} instance.
-     * 
-     * @since Android 1.0
      */
     public abstract void refresh();
 
@@ -94,13 +81,11 @@
      * system domain (i.e. system classes). System classes are always
      * given full permissions (i.e. AllPermission). This can not be changed by
      * installing a new policy.
-     * </p>
-     * 
+     *
      * @param domain
      *            the {@code ProtectionDomain} to compute the permissions for.
      * @return the permissions that are granted to the specified {@code
      *         CodeSource}.
-     * @since Android 1.0
      */
     public PermissionCollection getPermissions(ProtectionDomain domain) {
         if (domain != null) {
@@ -112,7 +97,7 @@
     /**
      * Indicates whether the specified {@code Permission} is implied by the
      * {@code PermissionCollection} of the specified {@code ProtectionDomain}.
-     * 
+     *
      * @param domain
      *            the {@code ProtectionDomain} for which the permission should
      *            be granted.
@@ -121,7 +106,6 @@
      *            verified.
      * @return {@code true} if the {@code Permission} is implied by the {@code
      *         ProtectionDomain}, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean implies(ProtectionDomain domain, Permission permission) {
         if (domain != null) {
@@ -130,8 +114,8 @@
             if (total == null) {
                 total = inherent;
             } else if (inherent != null) {
-                for (Enumeration en = inherent.elements(); en.hasMoreElements();) {
-                    total.add((Permission)en.nextElement());
+                for (Enumeration<Permission> en = inherent.elements(); en.hasMoreElements();) {
+                    total.add(en.nextElement());
                 }
             }
             if (total != null && total.implies(permission)) {
@@ -149,13 +133,11 @@
      * If a {@code SecurityManager} is installed, code calling this method needs
      * the {@code SecurityPermission} {@code getPolicy} to be granted, otherwise
      * a {@code SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @return the current system security policy.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public static Policy getPolicy() {
         SecurityManager sm = System.getSecurityManager();
@@ -170,7 +152,7 @@
      // In case of any error, including undefined provider name, 
      // returns new instance of org.apache.harmony.security.FilePolicy provider. 
     private static Policy getDefaultProvider() {
-        final String defaultClass = (String) AccessController
+        final String defaultClass = AccessController
                 .doPrivileged(new PolicyUtils.SecurityPropertyAccessor(
                         POLICY_PROVIDER));
         if (defaultClass == null) {
@@ -235,14 +217,12 @@
      * If a {@code SecurityManager} is installed, code calling this method needs
      * the {@code SecurityPermission} {@code setPolicy} to be granted, otherwise
      * a {@code SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @param policy
      *            the {@code Policy} to set.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public static void setPolicy(Policy policy) {
         SecurityManager sm = System.getSecurityManager();
diff --git a/libcore/security/src/main/java/java/security/Principal.java b/libcore/security/src/main/java/java/security/Principal.java
index 0716681..f86bc87 100644
--- a/libcore/security/src/main/java/java/security/Principal.java
+++ b/libcore/security/src/main/java/java/security/Principal.java
@@ -15,40 +15,31 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 
 /**
  * {@code Principal}s are objects which have identities. These can be
  * individuals, groups, corporations, unique program executions, etc.
- * 
- * @since Android 1.0
  */
 public interface Principal {
     /**
      * Compares the specified object with this {@code Principal} for equality
      * and returns {@code true} if the specified object is equal, {@code false}
      * otherwise.
-     * 
+     *
      * @param obj
      *            object to be compared for equality with this {@code
      *            Principal}.
      * @return {@code true} if the specified object is equal to this {@code
      *         Principal}, otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean equals( Object obj );
 
     /**
      * Returns the name of this {@code Principal}.
-     * 
+     *
      * @return the name of this {@code Principal}.
-     * @since Android 1.0
      */
     public String getName();
 
@@ -60,16 +51,14 @@
      * @return the hash code value for this {@code Principal}.
      * @see Object#equals(Object)
      * @see Principal#equals(Object)
-     * @since Android 1.0
      */
     public int hashCode();
-   
-    /** 
+
+    /**
      * Returns a string containing a concise, human-readable description of
      * this {@code Principal}.
      *
      * @return a printable representation for this {@code Principal}.
-     * @since Android 1.0
      */
     public String toString();
 }
diff --git a/libcore/security/src/main/java/java/security/PrivateKey.java b/libcore/security/src/main/java/java/security/PrivateKey.java
index 8513b75..246f286 100644
--- a/libcore/security/src/main/java/java/security/PrivateKey.java
+++ b/libcore/security/src/main/java/java/security/PrivateKey.java
@@ -15,25 +15,17 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code PrivateKey} is the common interface for private keys.
  * 
  * @see PublicKey
- * @since Android 1.0
  */
 public interface PrivateKey extends Key {
-    
+
     /**
      * The {@code serialVersionUID} to be compatible with JDK1.1.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = 6034044314589513430L;
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/PrivilegedAction.java b/libcore/security/src/main/java/java/security/PrivilegedAction.java
index 5912cdc..1dbbe65 100644
--- a/libcore/security/src/main/java/java/security/PrivilegedAction.java
+++ b/libcore/security/src/main/java/java/security/PrivilegedAction.java
@@ -15,31 +15,23 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code PrivilegedAction} represents an action that can be executed privileged
  * regarding access control. Instances of {@code PrivilegedAction} can be
  * executed on {@code AccessController.doPrivileged()}.
- * 
+ *
  * @see AccessController
  * @see AccessController#doPrivileged(PrivilegedAction)
  * @see AccessController#doPrivileged(PrivilegedAction, AccessControlContext)
  * @see PrivilegedExceptionAction
- * @since Android 1.0
  */
 public interface PrivilegedAction<T> {
-
     /**
      * Returns the result of running the action.
-     * 
+     *
      * @return the result of running the action.
-     * @since Android 1.0
      */
     public T run();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/PrivilegedActionException.java b/libcore/security/src/main/java/java/security/PrivilegedActionException.java
index eaca2b2..a1f5b15 100644
--- a/libcore/security/src/main/java/java/security/PrivilegedActionException.java
+++ b/libcore/security/src/main/java/java/security/PrivilegedActionException.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
@@ -33,13 +28,11 @@
  * {@code AccessController#doPrivileged(PrivilegedExceptionAction,
  * AccessControlContext)} </br>
  * </ul>
- * </p>
- * 
+ *
  * @see PrivilegedExceptionAction
  * @see AccessController#doPrivileged(PrivilegedExceptionAction)
  * @see AccessController#doPrivileged(PrivilegedExceptionAction,
  *      AccessControlContext)
- * @since Android 1.0
  */
 public class PrivilegedActionException extends Exception {
 
@@ -50,10 +43,9 @@
     /**
      * Constructs a new instance of {@code PrivilegedActionException} with the
      * cause.
-     * 
+     *
      * @param ex
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public PrivilegedActionException(Exception ex) {
         super(ex);
@@ -63,10 +55,9 @@
     /**
      * Returns the exception that was thrown by a
      * {@code PrivilegedExceptionAction}.
-     * 
+     *
      * @return the exception that was thrown by a
      *         {@code PrivilegedExceptionAction}.
-     * @since Android 1.0
      */
     public Exception getException() {
         return exception; // return ( getCause() instanceof Exception ) ?
@@ -76,11 +67,11 @@
     /**
      * Returns the exception that was thrown by a
      * {@code PrivilegedExceptionAction}.
-     * 
+     *
      * @return the exception that was thrown by a
      *         {@code PrivilegedExceptionAction}.
-     * @since Android 1.0
      */
+    @Override
     public Throwable getCause() {
         return exception;
     }
@@ -88,11 +79,11 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * {@code PrivilegedActionException}.
-     * 
+     *
      * @return a printable representation for this {@code
      *         PrivilegedActionException}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         String s = getClass().getName();
         return exception == null ? s : s + ": " + exception; //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/PrivilegedExceptionAction.java b/libcore/security/src/main/java/java/security/PrivilegedExceptionAction.java
index dd3ae8d..bc072d5 100644
--- a/libcore/security/src/main/java/java/security/PrivilegedExceptionAction.java
+++ b/libcore/security/src/main/java/java/security/PrivilegedExceptionAction.java
@@ -15,34 +15,26 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code PrivilegedAction} represents an action, that can be executed
  * privileged regarding access control. Instances of {@code PrivilegedAction}
  * can be executed invoking {@code AccessController.doPrivileged()}.
- * 
+ *
  * @see AccessController
  * @see AccessController#doPrivileged(PrivilegedExceptionAction)
  * @see AccessController#doPrivileged(PrivilegedExceptionAction,
  *      AccessControlContext)
  * @see PrivilegedAction
- * @since Android 1.0
  */
 public interface PrivilegedExceptionAction<T> {
-    
     /**
      * Returns the result of running the action.
-     * 
+     *
      * @return the result of running the action
      * @throws Exception
      *             if an exception occurred.
-     * @since Android 1.0
      */
     T run() throws Exception;
 }
diff --git a/libcore/security/src/main/java/java/security/ProtectionDomain.java b/libcore/security/src/main/java/java/security/ProtectionDomain.java
index d41f4a8..1e85c4a 100644
--- a/libcore/security/src/main/java/java/security/ProtectionDomain.java
+++ b/libcore/security/src/main/java/java/security/ProtectionDomain.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
@@ -30,9 +25,6 @@
  * <p>
  * A class belongs to exactly one protection domain and the protection domain
  * can not be changed during the lifetime of the class.
- * </p>
- * 
- * @since Android 1.0
  */
 public class ProtectionDomain {
 
@@ -60,17 +52,13 @@
      * collection is made immutable by calling
      * {@link PermissionCollection#setReadOnly()} and it is considered as
      * granted statically to this {@code ProtectionDomain}.
-     * </p>
      * <p>
      * The policy will not be consulted by access checks against this {@code
      * ProtectionDomain}.
-     * </p>
      * <p>
-     * If {@code permissions} is {@code null}, the method
-     * {@link ProtectionDomain#implies(Permission)} always returns {@code false}
-     * .
-     * </p>
-     * 
+     * If {@code permissions} is {@code null}, the method {@link
+     * ProtectionDomain#implies(Permission)} always returns {@code false}.
+     *
      * @param cs
      *            the code source associated with this domain, maybe {@code
      *            null}.
@@ -78,7 +66,6 @@
      *            the {@code PermissionCollection} containing all permissions to
      *            be statically granted to this {@code ProtectionDomain}, maybe
      *            {@code null}.
-     * @since Android 1.0
      */
     public ProtectionDomain(CodeSource cs, PermissionCollection permissions) {
         this.codeSource = cs;
@@ -91,7 +78,6 @@
         //dynamicPerms = false;
     }
 
-
     /**
      * Constructs a new instance of {@code ProtectionDomain} with the specified
      * code source, the permissions, the class loader and the principals.
@@ -102,12 +88,10 @@
      * permissions} collection is made immutable by calling
      * {@link PermissionCollection#setReadOnly()}. If access checks are
      * performed, the policy and the provided permission collection are checked.
-     * </p>
      * <p>
      * External modifications of the provided {@code principals} array has no
      * impact on this {@code ProtectionDomain}.
-     * </p>
-     * 
+     *
      * @param cs
      *            the code source associated with this domain, maybe {@code
      *            null}.
@@ -118,9 +102,8 @@
      *            the class loader associated with this domain, maybe {@code
      *            null}.
      * @param principals
-     *            the principals associated with this domain, maybe {@code null}
-     *            .
-     * @since Android 1.0
+     *            the principals associated with this domain, maybe {@code
+     *            null}.
      */
     public ProtectionDomain(CodeSource cs, PermissionCollection permissions,
             ClassLoader cl, Principal[] principals) {
@@ -141,10 +124,9 @@
     /**
      * Returns the {@code ClassLoader} associated with this {@code
      * ProtectionDomain}.
-     * 
+     *
      * @return the {@code ClassLoader} associated with this {@code
      *         ProtectionDomain}, maybe {@code null}.
-     * @since Android 1.0
      */
     public final ClassLoader getClassLoader() {
         return classLoader;
@@ -152,10 +134,9 @@
 
     /**
      * Returns the {@code CodeSource} of this {@code ProtectionDomain}.
-     * 
+     *
      * @return the {@code CodeSource} of this {@code ProtectionDomain}, maybe
      *         {@code null}.
-     * @since Android 1.0
      */
     public final CodeSource getCodeSource() {
         return codeSource;
@@ -164,10 +145,9 @@
     /**
      * Returns the static permissions that are granted to this {@code
      * ProtectionDomain}.
-     * 
+     *
      * @return the static permissions that are granted to this {@code
      *         ProtectionDomain}, maybe {@code null}.
-     * @since Android 1.0
      */
     public final PermissionCollection getPermissions() {
         return permissions;
@@ -177,9 +157,8 @@
      * Returns the principals associated with this {@code ProtectionDomain}.
      * Modifications of the returned {@code Principal} array has no impact on
      * this {@code ProtectionDomain}.
-     * 
+     *
      * @return the principals associated with this {@code ProtectionDomain}.
-     * @since Android 1.0
      */
     public final Principal[] getPrincipals() {
         if( principals == null ) {
@@ -199,19 +178,16 @@
      * specified permission is only checked against the permission collection
      * provided in the constructor. If {@code null} was provided, {@code false}
      * is returned.
-     * </p>
      * <p>
      * If this {@code ProtectionDomain} was constructed with
      * {@link #ProtectionDomain(CodeSource, PermissionCollection, ClassLoader, Principal[])}
      * , the specified permission is checked against the policy and the
      * permission collection provided in the constructor.
-     * </p>
-     * 
+     *
      * @param permission
      *            the permission to check against the domain.
      * @return {@code true} if the specified {@code permission} is implied by
      *         this {@code ProtectionDomain}, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean implies(Permission permission) {
         // First, test with the Policy, as the default Policy.implies() 
@@ -232,13 +208,12 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * this {@code ProtectionDomain}.
-     * 
+     *
      * @return a printable representation for this {@code ProtectionDomain}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        //FIXME: 1.5 use StreamBuilder here
-        StringBuffer buf = new StringBuffer(200);
+        StringBuilder buf = new StringBuilder(200);
         buf.append("ProtectionDomain\n"); //$NON-NLS-1$
         buf.append("CodeSource=").append( //$NON-NLS-1$
                 codeSource == null ? "<null>" : codeSource.toString()).append( //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/Provider.java b/libcore/security/src/main/java/java/security/Provider.java
index 491470f..cf9c94d 100644
--- a/libcore/security/src/main/java/java/security/Provider.java
+++ b/libcore/security/src/main/java/java/security/Provider.java
@@ -15,15 +15,11 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.NotActiveException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -37,14 +33,13 @@
 import java.util.Set;
 
 import org.apache.harmony.luni.util.TwoKeyHashMap;
+import org.apache.harmony.security.Util;
 import org.apache.harmony.security.fortress.Services;
 import org.apache.harmony.security.internal.nls.Messages;
 
 /**
  * {@code Provider} is the abstract superclass for all security providers in the
  * Java security infrastructure.
- * 
- * @since Android 1.0
  */
 public abstract class Provider extends Properties {
     private static final long serialVersionUID = -4298000515446427739L;
@@ -99,14 +94,13 @@
     /**
      * Constructs a new instance of {@code Provider} with its name, version and
      * description.
-     * 
+     *
      * @param name
      *            the name of the provider.
      * @param version
      *            the version of the provider.
      * @param info
      *            a description of the provider.
-     * @since Android 1.0
      */
     protected Provider(String name, double version, String info) {
         this.name = name;
@@ -118,9 +112,8 @@
 
     /**
      * Returns the name of this provider.
-     * 
+     *
      * @return the name of this provider.
-     * @since Android 1.0
      */
     public String getName() {
         return name;
@@ -128,9 +121,8 @@
 
     /**
      * Returns the version number for the services being provided.
-     * 
+     *
      * @return the version number for the services being provided.
-     * @since Android 1.0
      */
     public double getVersion() {
         return version;
@@ -138,9 +130,8 @@
 
     /**
      * Returns a description of the services being provided.
-     * 
+     *
      * @return a description of the services being provided.
-     * @since Android 1.0
      */
     public String getInfo() {
         return info;
@@ -151,12 +142,10 @@
      * this {@code Provider} including its name and its version.
      *
      * @return a printable representation for this {@code Provider}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        // BEGIN android-changed
         return name + " version " + version; //$NON-NLS-1$
-        // END android-changed
     }
 
     /**
@@ -167,13 +156,12 @@
      * the {@code SecurityPermission} {@code clearProviderProperties.NAME}
      * (where NAME is the provider name) to be granted, otherwise a {@code
      * SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
+    @Override
     public synchronized void clear() {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -203,6 +191,7 @@
         servicesChanged();
     }
 
+    @Override
     public synchronized void load(InputStream inStream) throws IOException {
         Properties tmp = new Properties();
         tmp.load(inStream);
@@ -216,15 +205,14 @@
      * the {@code SecurityPermission} {@code putProviderProperty.NAME} (where
      * NAME is the provider name) to be granted, otherwise a {@code
      * SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @param t
      *            the mappings to copy to this provider.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
+    @Override
     public synchronized void putAll(Map<?,?> t) {
 
         // Implementation note:
@@ -265,14 +253,17 @@
         }
     }
 
+    @Override
     public synchronized Set<Map.Entry<Object,Object>> entrySet() {
         return Collections.unmodifiableSet(super.entrySet());
     }
 
+    @Override
     public Set<Object> keySet() {
         return Collections.unmodifiableSet(super.keySet());
     }
 
+    @Override
     public Collection<Object> values() {
         return Collections.unmodifiableCollection(super.values());
     }
@@ -285,8 +276,7 @@
      * the {@code SecurityPermission} {@code putProviderProperty.NAME} (where
      * NAME is the provider name) to be granted, otherwise a {@code
      * SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @param key
      *            the name of the property.
      * @param value
@@ -296,8 +286,8 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
+    @Override
     public synchronized Object put(Object key, Object value) {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -329,8 +319,7 @@
      * the {@code SecurityPermission} {@code removeProviderProperty.NAME} (where
      * NAME is the provider name) to be granted, otherwise a {@code
      * SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @param key
      *            the name of the property
      * @return the value that was mapped to the specified {@code key} ,or
@@ -338,8 +327,8 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have the permission to invoke this method.
-     * @since Android 1.0
      */
+    @Override
     public synchronized Object remove(Object key) {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -365,9 +354,9 @@
     }
 
     /**
-     * returns true if the provider implements the specified algorithm. Caller
+     * Returns true if this provider implements the given algorithm. Caller
      * must specify the cryptographic service and specify constraints via the
-     * attribute name the attribute value
+     * attribute name and value.
      * 
      * @param serv
      *            Crypto service.
@@ -386,33 +375,32 @@
             alg = getPropertyIgnoreCase("Alg.Alias." + servAlg); //$NON-NLS-1$
             if (alg != null) {
                 servAlg = serv + "." + alg; //$NON-NLS-1$
-                prop = getPropertyIgnoreCase(serv + "." + alg); //$NON-NLS-1$
+                prop = getPropertyIgnoreCase(servAlg);
             }
         }
         if (prop != null) {
             if (attribute == null) {
                 return true;
-            } else {
-                return checkAttribute(serv + "." + alg, attribute, val); //$NON-NLS-1$
             }
+            return checkAttribute(servAlg, attribute, val);
         }
         return false;
     }
 
-    // returns true if the implementation meets the constraint expressed by the
-    // specified attribute name/value pair.
+    // Returns true if this provider has the same value as is given for the
+    // given attribute
     private boolean checkAttribute(String servAlg, String attribute, String val) {
         
         String attributeValue = getPropertyIgnoreCase(servAlg + ' ' + attribute);
         if (attributeValue != null) {
-            if (attribute.equalsIgnoreCase("KeySize")) { //$NON-NLS-1$
+            if (Util.equalsIgnoreCase(attribute,"KeySize")) { //$NON-NLS-1$
                 // BEGIN android-changed
                 if (Integer.parseInt(attributeValue) >= Integer.parseInt(val)) {
                     return true;
                 }
                 // END android-changed
             } else { // other attributes
-                if (attributeValue.equalsIgnoreCase(val)) {
+                if (Util.equalsIgnoreCase(attributeValue, val)) {
                     return true;
                 }
             }
@@ -469,14 +457,13 @@
      * If two services match the requested type and algorithm, the one added
      * with the {@link #putService(Service)} is returned (as opposed to the one
      * added via {@link #put(Object, Object)}.
-     * 
+     *
      * @param type
      *            the type of the service (for example {@code KeyPairGenerator})
      * @param algorithm
      *            the algorithm name (case insensitive)
      * @return the requested service, or {@code null} if no such implementation
      *         exists
-     * @since Android 1.0
      */
     public synchronized Provider.Service getService(String type,
             String algorithm) {
@@ -485,11 +472,11 @@
         }
 
         if (type.equals(lastServiceName)
-                && algorithm.equalsIgnoreCase(lastAlgorithm)) {
+                && Util.equalsIgnoreCase(algorithm, lastAlgorithm)) {
             return returnedService;
         }
 
-        String alg = algorithm.toUpperCase();
+        String alg = Util.toUpperCase(algorithm);
         Object o = null;
         if (serviceTable != null) {
             o = serviceTable.get(type, alg);
@@ -519,10 +506,9 @@
     /**
      * Returns an unmodifiable {@code Set} of all services registered by this
      * provider.
-     * 
+     *
      * @return an unmodifiable {@code Set} of all services registered by this
      *         provider
-     * @since Android 1.0
      */
     public synchronized Set<Provider.Service> getServices() {
         updatePropertyServiceTable();
@@ -549,13 +535,12 @@
      * the {@code SecurityPermission} {@code putProviderProperty.NAME} (where
      * NAME is the provider name) to be granted, otherwise a {@code
      * SecurityException} will be thrown.
-     * 
+     *
      * @param s
      *            the {@code Service} to register
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method
-     * @since Android 1.0
      */
     protected synchronized void putService(Provider.Service s) {
         if (s == null) {
@@ -573,13 +558,13 @@
         if (serviceTable == null) {
             serviceTable = new TwoKeyHashMap<String, String, Service>(128);
         }
-        serviceTable.put(s.type, s.algorithm.toUpperCase(), s);
+        serviceTable.put(s.type, Util.toUpperCase(s.algorithm), s);
         if (s.aliases != null) {
             if (aliasTable == null) {
                 aliasTable = new TwoKeyHashMap<String, String, Service>(256);
             }
             for (Iterator<String> it = s.getAliases(); it.hasNext();) {
-                aliasTable.put(s.type, (it.next()).toUpperCase(), s);
+                aliasTable.put(s.type, Util.toUpperCase(it.next()), s);
             }
         }
         serviceInfoToProperties(s);
@@ -593,7 +578,7 @@
      * the {@code SecurityPermission} {@code removeProviderProperty.NAME} (where
      * NAME is the provider name) to be granted, otherwise a {@code
      * SecurityException} will be thrown.
-     * 
+     *
      * @param s
      *            the {@code Service} to remove
      * @throws SecurityException
@@ -601,7 +586,6 @@
      *             not have permission to invoke this method
      * @throws NullPointerException
      *             if {@code s} is {@code null}
-     * @since Android 1.0
      */
     protected synchronized void removeService(Provider.Service s) {
         if (s == null) {
@@ -613,11 +597,11 @@
         }
         servicesChanged();
         if (serviceTable != null) {
-            serviceTable.remove(s.type, s.algorithm.toUpperCase());
+            serviceTable.remove(s.type, Util.toUpperCase(s.algorithm));
         }
         if (aliasTable != null && s.aliases != null) {
             for (Iterator<String> it = s.getAliases(); it.hasNext();) {
-                aliasTable.remove(s.type, (it.next()).toUpperCase());
+                aliasTable.remove(s.type, Util.toUpperCase(it.next()));
             }
         }
         serviceInfoFromProperties(s);
@@ -678,14 +662,14 @@
         String algorithm = null;
         String attribute = null;
         int i;
-        if (k.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<stanbdardName> //$NON-NLS-1$
+        if (k.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<standardName> //$NON-NLS-1$
             String aliasName;
             String service_alias = k.substring(10);
-            i = service_alias.indexOf("."); //$NON-NLS-1$
+            i = service_alias.indexOf('.');
             serviceName = service_alias.substring(0, i);
             aliasName = service_alias.substring(i + 1);
             if (propertyAliasTable != null) {
-                propertyAliasTable.remove(serviceName, aliasName.toUpperCase());
+                propertyAliasTable.remove(serviceName, Util.toUpperCase(aliasName));
             }
             if (propertyServiceTable != null) {
                 for (Iterator<Service> it = propertyServiceTable.values().iterator(); it
@@ -699,22 +683,22 @@
             }
             return;
         }
-        int j = k.indexOf("."); //$NON-NLS-1$
+        int j = k.indexOf('.');
         if (j == -1) { // unknown format
             return;
         }
 
-        i = k.indexOf(" "); //$NON-NLS-1$
+        i = k.indexOf(' ');
         if (i == -1) { // <crypto_service>.<algorithm_or_type>=<className>
             serviceName = k.substring(0, j);
             algorithm = k.substring(j + 1);
             if (propertyServiceTable != null) {
-                Provider.Service ser = propertyServiceTable.remove(serviceName, algorithm.toUpperCase());
+                Provider.Service ser = propertyServiceTable.remove(serviceName, Util.toUpperCase(algorithm));
                 if (ser != null && propertyAliasTable != null
                         && ser.aliases != null) {
                     for (Iterator<String> it = ser.aliases.iterator(); it.hasNext();) {
-                        propertyAliasTable.remove(serviceName, (it
-                                .next()).toUpperCase());
+                        propertyAliasTable.remove(serviceName, Util.toUpperCase(it
+                                .next()));
                     }
                 }
             }
@@ -724,8 +708,7 @@
             serviceName = k.substring(0, j);
             algorithm = k.substring(j + 1, i);
             if (propertyServiceTable != null) {
-                Object o = propertyServiceTable.get(serviceName, algorithm
-                        .toUpperCase());
+                Object o = propertyServiceTable.get(serviceName, Util.toUpperCase(algorithm));
                 if (o != null) {
                     s = (Provider.Service) o;
                     s.attributes.remove(attribute);
@@ -759,14 +742,14 @@
                 continue;
             }
             int i;
-            if (key.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<stanbdardName> //$NON-NLS-1$
+            if (key.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<standardName> //$NON-NLS-1$
                 String aliasName;
                 String service_alias = key.substring(10);
-                i = service_alias.indexOf("."); //$NON-NLS-1$
+                i = service_alias.indexOf('.');
                 serviceName = service_alias.substring(0, i);
                 aliasName = service_alias.substring(i + 1);
                 algorithm = value;
-                String algUp = algorithm.toUpperCase();
+                String algUp = Util.toUpperCase(algorithm);
                 Object o = null;
                 if (propertyServiceTable == null) {
                     propertyServiceTable = new TwoKeyHashMap<String, String, Service>(128);
@@ -782,7 +765,7 @@
                         propertyAliasTable = new TwoKeyHashMap<String, String, Service>(256);
                     }
                     propertyAliasTable.put(serviceName,
-                            aliasName.toUpperCase(), s);
+                            Util.toUpperCase(aliasName), s);
                 } else {
                     String className = (String) changedProperties
                             .get(serviceName + "." + algorithm); //$NON-NLS-1$
@@ -795,21 +778,21 @@
                         if (propertyAliasTable == null) {
                             propertyAliasTable = new TwoKeyHashMap<String, String, Service>(256);
                         }
-                        propertyAliasTable.put(serviceName, aliasName
-                                .toUpperCase(), s);
+                        propertyAliasTable.put(serviceName, Util.toUpperCase(aliasName
+                                ), s);
                     }
                 }
                 continue;
             }
-            int j = key.indexOf("."); //$NON-NLS-1$
+            int j = key.indexOf('.');
             if (j == -1) { // unknown format
                 continue;
             }
-            i = key.indexOf(" "); //$NON-NLS-1$
+            i = key.indexOf(' ');
             if (i == -1) { // <crypto_service>.<algorithm_or_type>=<className>
                 serviceName = key.substring(0, j);
                 algorithm = key.substring(j + 1);
-                String alg = algorithm.toUpperCase();
+                String alg = Util.toUpperCase(algorithm);
                 Object o = null;
                 if (propertyServiceTable != null) {
                     o = propertyServiceTable.get(serviceName, alg);
@@ -834,7 +817,7 @@
                 serviceName = key.substring(0, j);
                 algorithm = key.substring(j + 1, i);
                 String attribute = key.substring(i + 1);
-                String alg = algorithm.toUpperCase();
+                String alg = Util.toUpperCase(algorithm);
                 Object o = null;
                 if (propertyServiceTable != null) {
                     o = propertyServiceTable.get(serviceName, alg);
@@ -875,11 +858,12 @@
     // These attributes should be placed in each Provider object: 
     // Provider.id name, Provider.id version, Provider.id info, 
     // Provider.id className
+    @SuppressWarnings("nls")
     private void putProviderInfo() {
-        super.put("Provider.id name", null != name ? name : "null"); //$NON-NLS-1$
-        super.put("Provider.id version", versionString); //$NON-NLS-1$
-        super.put("Provider.id info", null != info ? info : "null"); //$NON-NLS-1$
-        super.put("Provider.id className", this.getClass().getName()); //$NON-NLS-1$
+        super.put("Provider.id name", null != name ? name : "null");
+		super.put("Provider.id version", versionString);
+		super.put("Provider.id info", null != info ? info : "null");
+        super.put("Provider.id className", this.getClass().getName());
     }
 
     // Searches for the property with the specified key in the provider
@@ -894,7 +878,7 @@
         }
         for (Enumeration<?> e = propertyNames(); e.hasMoreElements();) {
             String pname = (String) e.nextElement();
-            if (key.equalsIgnoreCase(pname)) {
+            if (Util.equalsIgnoreCase(key, pname)) {
                 return getProperty(pname);
             }
         }
@@ -905,8 +889,6 @@
      * {@code Service} represents a service in the Java Security infrastructure.
      * Each service describes its type, the algorithm it implements, to which
      * provider it belongs and other properties.
-     * 
-     * @since Android 1.0
      */
     public static class Service {
         // The provider
@@ -936,7 +918,7 @@
         /**
          * Constructs a new instance of {@code Service} with the given
          * attributes.
-         * 
+         *
          * @param provider
          *            the provider to which this service belongs.
          * @param type
@@ -955,7 +937,6 @@
          * @throws NullPointerException
          *             if {@code provider, type, algorithm} or {@code className}
          *             is {@code null}.
-         * @since Android 1.0
          */
         public Service(Provider provider, String type, String algorithm,
                 String className, List<String> aliases, Map<String, String> attributes) {
@@ -1006,21 +987,19 @@
         /**
          * Returns the type of this {@code Service}. For example {@code
          * KeyPairGenerator}.
-         * 
+         *
          * @return the type of this {@code Service}.
-         * @since Android 1.0
          */
         public final String getType() {
             return type;
         }
 
         /**
-         * Returns the name of the algorithm implemented by this {@code Service}
-         * .
-         * 
-         * @return the name of the algorithm implemented by this {@code Service}
-         *         .
-         * @since Android 1.0
+         * Returns the name of the algorithm implemented by this {@code
+         * Service}.
+         *
+         * @return the name of the algorithm implemented by this {@code
+         *         Service}.
          */
         public final String getAlgorithm() {
             return algorithm;
@@ -1028,9 +1007,8 @@
 
         /**
          * Returns the {@code Provider} this {@code Service} belongs to.
-         * 
+         *
          * @return the {@code Provider} this {@code Service} belongs to.
-         * @since Android 1.0
          */
         public final Provider getProvider() {
             return provider;
@@ -1038,9 +1016,8 @@
 
         /**
          * Returns the name of the class implementing this {@code Service}.
-         * 
+         *
          * @return the name of the class implementing this {@code Service}.
-         * @since Android 1.0
          */
         public final String getClassName() {
             return className;
@@ -1048,14 +1025,13 @@
 
         /**
          * Returns the value of the attribute with the specified {@code name}.
-         * 
+         *
          * @param name
          *            the name of the attribute.
          * @return the value of the attribute, or {@code null} if no attribute
          *         with the given name is set.
          * @throws NullPointerException
          *             if {@code name} is {@code null}.
-         * @since Android 1.0
          */
         public final String getAttribute(String name) {
             if (name == null) {
@@ -1068,13 +1044,16 @@
         }
 
         Iterator<String> getAliases() {
+            if(aliases == null){
+                aliases = new ArrayList<String>(0);
+            }
             return aliases.iterator();
         }
 
         /**
          * Creates and returns a new instance of the implementation described by
          * this {@code Service}.
-         * 
+         *
          * @param constructorParameter
          *            the parameter that is used by the constructor, or {@code
          *            null} if the implementation does not declare a constructor
@@ -1086,7 +1065,6 @@
          * @throws InvalidParameterException
          *             if the implementation does not support the specified
          *             {@code constructorParameter}.
-         * @since Android 1.0
          */
         public Object newInstance(Object constructorParameter)
                 throws NoSuchAlgorithmException {
@@ -1122,39 +1100,37 @@
                     throw new NoSuchAlgorithmException(Messages.getString("security.199", //$NON-NLS-1$
                             type, algorithm), e);
                 }
-            } else {
-                if (!supportsParameter(constructorParameter)) {
-                    throw new InvalidParameterException(
-                            Messages.getString("security.12", type)); //$NON-NLS-1$
-                }
+            }
+            if (!supportsParameter(constructorParameter)) {
+                throw new InvalidParameterException(
+                        Messages.getString("security.12", type)); //$NON-NLS-1$
+            }
 
-                Class[] parameterTypes = new Class[1];
-                Object[] initargs = { constructorParameter };
-                try {
-                    if (type.equalsIgnoreCase("CertStore")) { //$NON-NLS-1$
-                        parameterTypes[0] = Class
-                                .forName("java.security.cert.CertStoreParameters"); //$NON-NLS-1$
-                    } else {
-                        parameterTypes[0] = constructorParameter.getClass();
-                    }
-                    return implementation.getConstructor(parameterTypes)
-                            .newInstance(initargs);
-                } catch (Exception e) {
-                    throw new NoSuchAlgorithmException(Messages.getString("security.199", //$NON-NLS-1$
-                            type, algorithm), e);
+            Class[] parameterTypes = new Class[1];
+            Object[] initargs = { constructorParameter };
+            try {
+                if (Util.equalsIgnoreCase(type,"CertStore")) { //$NON-NLS-1$
+                    parameterTypes[0] = Class
+                            .forName("java.security.cert.CertStoreParameters"); //$NON-NLS-1$
+                } else {
+                    parameterTypes[0] = constructorParameter.getClass();
                 }
+                return implementation.getConstructor(parameterTypes)
+                        .newInstance(initargs);
+            } catch (Exception e) {
+                throw new NoSuchAlgorithmException(Messages.getString("security.199", //$NON-NLS-1$
+                        type, algorithm), e);
             }
         }
 
         /**
          * Indicates whether this {@code Service} supports the specified
          * constructor parameter.
-         * 
+         *
          * @param parameter
          *            the parameter to test.
          * @return {@code true} if this {@code Service} supports the specified
          *         constructor parameter, {@code false} otherwise.
-         * @since Android 1.0
          */
         public boolean supportsParameter(Object parameter) {
             return true;
@@ -1163,10 +1139,10 @@
         /**
          * Returns a string containing a concise, human-readable description of
          * this {@code Service}.
-         * 
+         *
          * @return a printable representation for this {@code Service}.
-         * @since Android 1.0
          */
+        @Override
         public String toString() {
             String result = "Provider " + provider.getName() + " Service " //$NON-NLS-1$ //$NON-NLS-2$
                     + type + "." + algorithm + " " + className; //$NON-NLS-1$ //$NON-NLS-2$
@@ -1179,4 +1155,10 @@
             return result;
         }
     }
+    
+    private void readObject(java.io.ObjectInputStream in) throws NotActiveException, IOException, ClassNotFoundException {
+    	in.defaultReadObject();
+        versionString = String.valueOf(version);
+        providerNumber = -1;
+    }
 }
diff --git a/libcore/security/src/main/java/java/security/ProviderException.java b/libcore/security/src/main/java/java/security/ProviderException.java
index d4def5b..22950f5 100644
--- a/libcore/security/src/main/java/java/security/ProviderException.java
+++ b/libcore/security/src/main/java/java/security/ProviderException.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
@@ -27,7 +22,6 @@
  * Providers}.
  * 
  * @see Provider
- * @since Android 1.0
  */
 public class ProviderException extends RuntimeException {
 
@@ -36,10 +30,9 @@
     /**
      * Constructs a new instance of {@code ProviderException} with the given
      * message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ProviderException(String msg) {
         super(msg);
@@ -47,8 +40,6 @@
 
     /**
      * Constructs a new instance of {@code ProviderException}.
-     * 
-     * @since Android 1.0
      */
     public ProviderException() {
     }
@@ -56,12 +47,11 @@
     /**
      * Constructs a new instance of {@code ProviderException} with the given
      * message and the cause.
-     * 
+     *
      * @param message
      *            the detail message for this exception.
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public ProviderException(String message, Throwable cause) {
         super(message, cause);
@@ -69,12 +59,11 @@
 
     /**
      * Constructs a new instance of {@code ProviderException} with the cause.
-     * 
+     *
      * @param cause
      *            the exception which is the cause for this exception.
-     * @since Android 1.0
      */
     public ProviderException(Throwable cause) {
         super(cause);
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/PublicKey.java b/libcore/security/src/main/java/java/security/PublicKey.java
index 4888a64..c197840 100644
--- a/libcore/security/src/main/java/java/security/PublicKey.java
+++ b/libcore/security/src/main/java/java/security/PublicKey.java
@@ -15,25 +15,16 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code PublicKey} is the common interface for public keys.
  * 
  * @see PrivateKey
- * @since Android 1.0
  */
 public interface PublicKey extends Key {
-    
     /**
      * The {@code serialVersionUID} to be compatible with JDK1.1.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = 7187392471159151072L;
 }
diff --git a/libcore/security/src/main/java/java/security/SecureClassLoader.java b/libcore/security/src/main/java/java/security/SecureClassLoader.java
index 7d08fc8..07bebc9 100644
--- a/libcore/security/src/main/java/java/security/SecureClassLoader.java
+++ b/libcore/security/src/main/java/java/security/SecureClassLoader.java
@@ -15,28 +15,20 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.nio.ByteBuffer;
 import java.util.HashMap;
 
-
 /**
  * {@code SecureClassLoader} represents a {@code ClassLoader} which associates
  * the classes it loads with a code source and provide mechanisms to allow the
  * relevant permissions to be retrieved.
- * 
- * @since Android 1.0
  */
 public class SecureClassLoader extends ClassLoader {
 
     // A cache of ProtectionDomains for a given CodeSource
-    private HashMap pds = new HashMap();
+    private HashMap<CodeSource, ProtectionDomain> pds = new HashMap<CodeSource, ProtectionDomain>();
 
     /**
      * Constructs a new instance of {@code SecureClassLoader}. The default
@@ -45,12 +37,10 @@
      * If a {@code SecurityManager} is installed, code calling this constructor
      * needs the {@code SecurityPermission} {@code checkCreateClassLoader} to be
      * granted, otherwise a {@code SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this constructor.
-     * @since Android 1.0
      */
     protected SecureClassLoader() {
         super();
@@ -63,14 +53,12 @@
      * If a {@code SecurityManager} is installed, code calling this constructor
      * needs the {@code SecurityPermission} {@code checkCreateClassLoader} to be
      * granted, otherwise a {@code SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @param parent
      *            the parent {@code ClassLoader}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this constructor.
-     * @since Android 1.0
      */
     protected SecureClassLoader(ClassLoader parent) {
         super(parent);
@@ -79,12 +67,11 @@
     /**
      * Returns the {@code PermissionCollection} for the specified {@code
      * CodeSource}.
-     * 
+     *
      * @param codesource
      *            the code source.
      * @return the {@code PermissionCollection} for the specified {@code
      *         CodeSource}.
-     * @since Android 1.0
      */
     protected PermissionCollection getPermissions(CodeSource codesource) {
         // Do nothing by default, ProtectionDomain will take care about
@@ -95,7 +82,7 @@
     /**
      * Constructs a new class from an array of bytes containing a class
      * definition in class file format with an optional {@code CodeSource}.
-     * 
+     *
      * @param name
      *            the name of the new class.
      * @param b
@@ -116,7 +103,6 @@
      *             if the package to which this class is to be added, already
      *             contains classes which were signed by different certificates,
      *             or if the class name begins with "java."
-     * @since Android 1.0
      */
     protected final Class<?> defineClass(String name, byte[] b, int off, int len,
             CodeSource cs) {
@@ -127,7 +113,7 @@
     /**
      * Constructs a new class from an array of bytes containing a class
      * definition in class file format with an optional {@code CodeSource}.
-     * 
+     *
      * @param name
      *            the name of the new class.
      * @param b
@@ -141,7 +127,6 @@
      *             if the package to which this class is to be added, already
      *             contains classes which were signed by different certificates,
      *             or if the class name begins with "java."
-     * @since Android 1.0
      */
     protected final Class<?> defineClass(String name, ByteBuffer b, CodeSource cs) {
         //FIXME 1.5 - remove b.array(), call super.defineClass(,ByteBuffer,)
@@ -165,7 +150,7 @@
         // will have it's own ProtectionDomain, which does not look right.
         ProtectionDomain pd;
         synchronized (pds) {
-            if ((pd = (ProtectionDomain) pds.get(cs)) != null) {
+            if ((pd = pds.get(cs)) != null) {
                 return pd;
             }
             PermissionCollection perms = getPermissions(cs);
diff --git a/libcore/security/src/main/java/java/security/SecureRandom.java b/libcore/security/src/main/java/java/security/SecureRandom.java
index e1d99e9..c697504 100644
--- a/libcore/security/src/main/java/java/security/SecureRandom.java
+++ b/libcore/security/src/main/java/java/security/SecureRandom.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.util.Iterator;
@@ -35,8 +30,6 @@
 /**
  * {@code SecureRandom} is an engine class which is capable of generating
  * cryptographically secure pseudo-random numbers.
- * 
- * @since Android 1.0
  */
 public class SecureRandom extends Random {
     
@@ -50,7 +43,7 @@
     
     private Provider provider;
     
-    private SecureRandomSpi secureRandomSpi; 
+    private SecureRandomSpi secureRandomSpi;
     
     private String algorithm;
     
@@ -69,8 +62,6 @@
      * Constructs a new instance of {@code SecureRandom}. An implementation for
      * the highest-priority provider is returned. The constructed instance will
      * not have been seeded.
-     * 
-     * @since Android 1.0
      */
     public SecureRandom() {
         super(0);
@@ -97,7 +88,6 @@
      * 
      * @param seed
      *            the seed for this generator.
-     * @since Android 1.0
      */
     public SecureRandom(byte[] seed) {
         this();
@@ -125,7 +115,6 @@
      *            the implementation.
      * @param provider
      *            the security provider.
-     * @since Android 1.0
      */
     protected SecureRandom(SecureRandomSpi secureRandomSpi,
                            Provider provider) {
@@ -154,7 +143,6 @@
      *             if the specified algorithm is not available.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static SecureRandom getInstance(String algorithm)
                                 throws NoSuchAlgorithmException {
@@ -183,7 +171,6 @@
      *             if the specified provider is not available.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static SecureRandom getInstance(String algorithm, String provider)
                                 throws NoSuchAlgorithmException, NoSuchProviderException {
@@ -212,7 +199,6 @@
      *             if the specified algorithm is not available.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static SecureRandom getInstance(String algorithm, Provider provider)
                                 throws NoSuchAlgorithmException {
@@ -232,7 +218,6 @@
      * Returns the provider associated with this {@code SecureRandom}.
      * 
      * @return the provider associated with this {@code SecureRandom}.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -242,7 +227,6 @@
      * Returns the name of the algorithm of this {@code SecureRandom}.
      * 
      * @return the name of the algorithm of this {@code SecureRandom}.
-     * @since Android 1.0
      */
     public String getAlgorithm() {
         return algorithm;
@@ -255,7 +239,6 @@
      * 
      * @param seed
      *            the new seed.
-     * @since Android 1.0
      */
     public synchronized void setSeed(byte[] seed) {
         secureRandomSpi.engineSetSeed(seed);
@@ -268,8 +251,8 @@
      * 
      * @param seed
      *            the new seed.
-     * @since Android 1.0
      */
+    @Override
     public void setSeed(long seed) {
         if (seed == 0) {    // skip call from Random
             return;
@@ -293,8 +276,8 @@
      * 
      * @param bytes
      *            the {@code byte[]} to be filled with random bytes.
-     * @since Android 1.0
      */
+    @Override
     public synchronized void nextBytes(byte[] bytes) {
         secureRandomSpi.engineNextBytes(bytes);
     }
@@ -307,8 +290,8 @@
      *            number of bits to be generated. An input value should be in
      *            the range [0, 32].
      * @return an {@code int} containing the specified number of random bits.
-     * @since Android 1.0
      */
+    @Override
     protected final int next(int numBits) {
         if (numBits < 0) {
             numBits = 0;
@@ -336,7 +319,6 @@
      * @param numBytes
      *            the number of seed bytes.
      * @return the seed bytes
-     * @since Android 1.0
      */
     public static byte[] getSeed(int numBytes) {
         if (internalSecureRandom == null) {
@@ -352,7 +334,6 @@
      * @param numBytes
      *            the number of seed bytes.
      * @return the seed bytes.
-     * @since Android 1.0
      */
     public byte[] generateSeed(int numBytes) {
         return secureRandomSpi.engineGenerateSeed(numBytes);
diff --git a/libcore/security/src/main/java/java/security/SecureRandomSpi.java b/libcore/security/src/main/java/java/security/SecureRandomSpi.java
index 7ce880c..829464f 100644
--- a/libcore/security/src/main/java/java/security/SecureRandomSpi.java
+++ b/libcore/security/src/main/java/java/security/SecureRandomSpi.java
@@ -15,21 +15,15 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.Serializable;
 
 /**
  * {@code SecureRandomSpi} is the <i>Service Provider Interface</i> (<b>SPI</b>) definition
- * for {@link SecureRandom}. 
+ * for {@link SecureRandom}.
  * 
  * @see SecureRandom
- * @since Android 1.0
  */
 public abstract class SecureRandomSpi implements Serializable {
     
@@ -42,7 +36,6 @@
      * 
      * @param seed
      *            the new seed.
-     * @since Android 1.0
      */
     protected abstract void engineSetSeed(byte[] seed);
     
@@ -52,7 +45,6 @@
      * 
      * @param bytes
      *            the {@code byte[]} to be filled with random bytes.
-     * @since Android 1.0
      */
     protected abstract void engineNextBytes(byte[] bytes);
     
@@ -63,7 +55,6 @@
      * @param numBytes
      *            the number of seed bytes.
      * @return the seed bytes
-     * @since Android 1.0
      */
     protected abstract byte[] engineGenerateSeed(int numBytes);
 }
diff --git a/libcore/security/src/main/java/java/security/Security.java b/libcore/security/src/main/java/java/security/Security.java
index 505a557..6ff38ad 100644
--- a/libcore/security/src/main/java/java/security/Security.java
+++ b/libcore/security/src/main/java/java/security/Security.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.BufferedInputStream;
@@ -39,7 +34,9 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.Map.Entry;
 
+import org.apache.harmony.security.Util;
 import org.apache.harmony.security.fortress.Engine;
 import org.apache.harmony.security.fortress.PolicyUtils;
 import org.apache.harmony.security.fortress.SecurityAccess;
@@ -50,8 +47,6 @@
  * {@code Security} is the central class in the Java Security API. It manages
  * the list of security {@code Provider} that have been installed into this
  * runtime environment.
- * 
- * @since Android 1.0
  */
 public final class Security {
 
@@ -87,57 +82,40 @@
                 // END android-added
 
                 // BEGIN android-removed
-                // File f = new File(System.getProperty("java.home") //$NON-NLS-1$
-                //         + File.separator + "lib" + File.separator //$NON-NLS-1$
-                //         + "security" + File.separator + "java.security"); //$NON-NLS-1$ //$NON-NLS-2$
-                // if (f.exists()) {
-                //     try {
-                //         FileInputStream fis = new FileInputStream(f);
-                //         InputStream is = new BufferedInputStream(fis);
-                //         secprops.load(is);
-                //         loaded = true;
-                //         is.close();
-                //     } catch (IOException e) {
-                ////         System.err.println("Could not load Security properties file: "
-                ////                         + e);
-                //     }
-                // }
-                //
-                // if ("true".equalsIgnoreCase(secprops.getProperty("security.allowCustomPropertiesFile", "true"))) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-                //     String securityFile = System.getProperty("java.security.properties"); //$NON-NLS-1$
-                //     if (securityFile != null) {
-                //         if (securityFile.startsWith("=")) { // overwrite //$NON-NLS-1$
-                //            secprops = new Properties();
-                //            loaded = false;
-                //            securityFile = securityFile.substring(1);
-                //         }
-                //         try {
-                //             securityFile = PolicyUtils.expand(securityFile, System.getProperties());
-                //         } catch (PolicyUtils.ExpansionFailedException e) {
-                ////            System.err.println("Could not load custom Security properties file "
-                ////                     + securityFile +": " + e);
-                //         }
-                //         f = new File(securityFile);
-                //         InputStream is;
-                //         try {
-                //             if (f.exists()) {
-                //                 FileInputStream fis = new FileInputStream(f);
-                //                 is = new BufferedInputStream(fis);
-                //             } else {
-                //                 URL url = new URL(securityFile);
-                //                 is = new BufferedInputStream(url.openStream());
-                //             }
-                //             secprops.load(is);
-                //             loaded = true;
-                //             is.close();
-                //         } catch (IOException e) {
-                // //             System.err.println("Could not load custom Security properties file "
-                // //                    + securityFile +": " + e);
-                //         }
-                //     }
-                // }
+//                if (Util.equalsIgnoreCase("true", secprops.getProperty("security.allowCustomPropertiesFile", "true"))) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+//                    String securityFile = System.getProperty("java.security.properties"); //$NON-NLS-1$
+//                    if (securityFile != null) {
+//                        if (securityFile.startsWith("=")) { // overwrite //$NON-NLS-1$
+//                            secprops = new Properties();
+//                            loaded = false;
+//                            securityFile = securityFile.substring(1);
+//                        }
+//                        try {
+//                            securityFile = PolicyUtils.expand(securityFile, System.getProperties());
+//                        } catch (PolicyUtils.ExpansionFailedException e) {
+////                            System.err.println("Could not load custom Security properties file "
+////                                    + securityFile +": " + e);
+//                        }
+//                        f = new File(securityFile);
+//                        InputStream is;
+//                        try {
+//                            if (f.exists()) {
+//                                FileInputStream fis = new FileInputStream(f);
+//                                is = new BufferedInputStream(fis);
+//                            } else {
+//                                URL url = new URL(securityFile);
+//                                is = new BufferedInputStream(url.openStream());
+//                            }
+//                            secprops.load(is);
+//                            loaded = true;
+//                            is.close();
+//                        } catch (IOException e) {
+// //                           System.err.println("Could not load custom Security properties file "
+// //                                   + securityFile +": " + e);
+//                        }
+//                    }
+//                }
                 // END android-removed
-
                 if (!loaded) {
                     registerDefaultProviders();
                 }
@@ -161,12 +139,9 @@
         secprops.put("security.provider.4", "org.bouncycastle.jce.provider.BouncyCastleProvider");  //$NON-NLS-1$ //$NON-NLS-2$
     }
 
-    // BEGIN android-note
-    // added Deprecated annotation
-    // END android-note
     /**
      * Returns value for the specified algorithm with the specified name.
-     * 
+     *
      * @param algName
      *            the name of the algorithm.
      * @param propName
@@ -174,7 +149,6 @@
      * @return value of the property.
      * @deprecated Use {@link AlgorithmParameters} and {@link KeyFactory}
      *             instead.
-     * @since Android 1.0
      */
     @Deprecated
     public static String getAlgorithmProperty(String algName, String propName) {
@@ -189,7 +163,7 @@
             for (Enumeration e = providers[i].propertyNames(); e
                     .hasMoreElements();) {
                 String pname = (String) e.nextElement();
-                if (prop.equalsIgnoreCase(pname)) {
+                if (Util.equalsIgnoreCase(prop, pname)) {
                     return providers[i].getProperty(pname);
                 }
             }
@@ -206,8 +180,7 @@
      * the {@code SecurityPermission} {@code insertProvider.NAME} (where NAME is
      * the provider name) to be granted, otherwise a {@code SecurityException}
      * will be thrown.
-     * </p>
-     * 
+     *
      * @param provider
      *            the provider to insert.
      * @param position
@@ -218,7 +191,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public static synchronized int insertProviderAt(Provider provider,
             int position) {
@@ -246,8 +218,7 @@
      * the {@code SecurityPermission} {@code insertProvider.NAME} (where NAME is
      * the provider name) to be granted, otherwise a {@code SecurityException}
      * will be thrown.
-     * </p>
-     * 
+     *
      * @param provider
      *            the provider to be added.
      * @return the actual position or {@code -1} if the given {@code provider}
@@ -255,7 +226,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public static int addProvider(Provider provider) {
         return insertProviderAt(provider, 0);
@@ -269,20 +239,17 @@
      * <p>
      * Returns silently if {@code name} is {@code null} or no provider with the
      * specified name is installed.
-     * </p>
      * <p>
      * If a {@code SecurityManager} is installed, code calling this method needs
      * the {@code SecurityPermission} {@code removeProvider.NAME} (where NAME is
      * the provider name) to be granted, otherwise a {@code SecurityException}
      * will be thrown.
-     * </p>
-     * 
+     *
      * @param name
      *            the name of the provider to remove.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public static synchronized void removeProvider(String name) {
         // It is not clear from spec.:
@@ -311,9 +278,8 @@
     /**
      * Returns an array containing all installed providers. The providers are
      * ordered according their preference order.
-     * 
+     *
      * @return an array containing all installed providers.
-     * @since Android 1.0
      */
     public static synchronized Provider[] getProviders() {
         return Services.getProviders();
@@ -323,11 +289,10 @@
      * Returns the {@code Provider} with the specified name. Returns {@code
      * null} if name is {@code null} or no provider with the specified name is
      * installed.
-     * 
+     *
      * @param name
      *            the name of the requested provider.
      * @return the provider with the specified name, maybe {@code null}.
-     * @since Android 1.0
      */
     public static synchronized Provider getProvider(String name) {
         return Services.getProvider(name);
@@ -337,15 +302,15 @@
      * Returns the array of providers which meet the user supplied string
      * filter. The specified filter must be supplied in one of two formats:
      * <nl>
-     * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE 
+     * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
      * <p>
-     * (for example: "MessageDigest.SHA") 
+     * (for example: "MessageDigest.SHA")
      * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
      * ATTR_NAME:ATTR_VALUE
      * <p>
-     * (for example: "Signature.MD5withRSA KeySize:512")
+     * (for example: "Signature.MD2withRSA KeySize:512")
      * </nl>
-     * 
+     *
      * @param filter
      *            case-insensitive filter.
      * @return the providers which meet the user supplied string filter {@code
@@ -355,7 +320,6 @@
      *             if an unusable filter is supplied.
      * @throws NullPointerException
      *             if {@code filter} is {@code null}.
-     * @since Android 1.0
      */
     public static Provider[] getProviders(String filter) {
         if (filter == null) {
@@ -366,7 +330,7 @@
                     Messages.getString("security.2B")); //$NON-NLS-1$
         }
         HashMap<String, String> hm = new HashMap<String, String>();
-        int i = filter.indexOf(":"); //$NON-NLS-1$
+        int i = filter.indexOf(':');
         if ((i == filter.length() - 1) || (i == 0)) {
             throw new InvalidParameterException(
                     Messages.getString("security.2B")); //$NON-NLS-1$
@@ -389,10 +353,10 @@
      * be an empty string. <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
      * ATTR_NAME:ATTR_VALUE
      * <p>
-     * for example: "Signature.MD5withRSA KeySize:512" where "KeySize:512" is
+     * for example: "Signature.MD2withRSA KeySize:512" where "KeySize:512" is
      * the value of the filter map entry.
      * </nl>
-     * 
+     *
      * @param filter
      *            case-insensitive filter.
      * @return the providers which meet the user supplied string filter {@code
@@ -402,7 +366,6 @@
      *             if an unusable filter is supplied.
      * @throws NullPointerException
      *             if {@code filter} is {@code null}.
-     * @since Android 1.0
      */
     public static synchronized Provider[] getProviders(Map<String,String> filter) {
         if (filter == null) {
@@ -412,15 +375,15 @@
             return null;
         }
         java.util.List<Provider> result = Services.getProvidersList();
-        Set keys = filter.entrySet();
-        Map.Entry entry;
-        for (Iterator it = keys.iterator(); it.hasNext();) {
-            entry = (Map.Entry) it.next();
-            String key = (String) entry.getKey();
-            String val = (String) entry.getValue();
+        Set<Entry<String, String>> keys = filter.entrySet();
+        Map.Entry<String, String> entry;
+        for (Iterator<Entry<String, String>> it = keys.iterator(); it.hasNext();) {
+            entry = it.next();
+            String key = entry.getKey();
+            String val = entry.getValue();
             String attribute = null;
-            int i = key.indexOf(" "); //$NON-NLS-1$
-            int j = key.indexOf("."); //$NON-NLS-1$
+            int i = key.indexOf(' ');
+            int j = key.indexOf('.');
             if (j == -1) {
                 throw new InvalidParameterException(
                         Messages.getString("security.2B")); //$NON-NLS-1$
@@ -451,7 +414,7 @@
             Provider p;
             for (int k = 0; k < result.size(); k++) {
                 try {
-                    p = (Provider) result.get(k);
+                    p = result.get(k);
                 } catch (IndexOutOfBoundsException e) {
                     break;
                 }
@@ -463,9 +426,8 @@
         }
         if (result.size() > 0) {
             return result.toArray(new Provider[result.size()]);
-        } else {
-            return null;
         }
+        return null;
     }
 
     /**
@@ -475,15 +437,13 @@
      * the {@code SecurityPermission} {@code getProperty.KEY} (where KEY is the
      * specified {@code key}) to be granted, otherwise a {@code
      * SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @param key
      *            the name of the requested security property.
      * @return the value of the security property.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public static String getProperty(String key) {
         if (key == null) {
@@ -493,7 +453,11 @@
         if (sm != null) {
             sm.checkSecurityAccess("getProperty." + key); //$NON-NLS-1$
         }
-        return secprops.getProperty(key);
+        String property = secprops.getProperty(key);
+        if (property != null) {
+            property = property.trim();
+        }
+        return property;
     }
 
     /**
@@ -503,8 +467,7 @@
      * the {@code SecurityPermission} {@code setProperty.KEY} (where KEY is the
      * specified {@code key}) to be granted, otherwise a {@code
      * SecurityException} will be thrown.
-     * </p>
-     * 
+     *
      * @param key
      *            the name of the security property.
      * @param datnum
@@ -512,7 +475,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public static void setProperty(String key, String datnum) {
         SecurityManager sm = System.getSecurityManager();
@@ -526,22 +488,27 @@
      * Returns a {@code Set} of all registered algorithms for the specified
      * cryptographic service. {@code "Signature"}, {@code "Cipher"} and {@code
      * "KeyStore"} are examples for such kind of services.
-     * 
+     *
      * @param serviceName
      *            the case-insensitive name of the service.
      * @return a {@code Set} of all registered algorithms for the specified
      *         cryptographic service, or an empty {@code Set} if {@code
      *         serviceName} is {@code null} or if no registered provider
      *         provides the requested service.
-     * @since Android 1.0
      */
     public static Set<String> getAlgorithms(String serviceName) {
         Set<String> result = new HashSet<String>();
+        // BEGIN android-added
+        // compatibility with RI
+        if (serviceName == null) {
+            return result;
+        }
+        // END android-added
         Provider[] p = getProviders();
         for (int i = 0; i < p.length; i++) {
             for (Iterator it = p[i].getServices().iterator(); it.hasNext();) {
                 Provider.Service s = (Provider.Service) it.next();
-                if (s.getType().equalsIgnoreCase(serviceName)) {
+                if (Util.equalsIgnoreCase(s.getType(),serviceName)) {
                     result.add(s.getAlgorithm());
                 }
             }
diff --git a/libcore/security/src/main/java/java/security/SecurityPermission.java b/libcore/security/src/main/java/java/security/SecurityPermission.java
index 87f3aaa..599ec6f 100644
--- a/libcore/security/src/main/java/java/security/SecurityPermission.java
+++ b/libcore/security/src/main/java/java/security/SecurityPermission.java
@@ -15,18 +15,11 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  * {@code SecurityPermission} objects guard access to the mechanisms which
  * implement security. Security permissions have names, but not actions.
- * 
- * @since Android 1.0
  */
 public final class SecurityPermission extends BasicPermission {
 
@@ -35,10 +28,9 @@
     /**
      * Constructs a new instance of {@code SecurityPermission} with the given
      * name.
-     * 
+     *
      * @param name
      *            the name of the permission.
-     * @since Android 1.0
      */
     public SecurityPermission(String name) {
         super(name);
@@ -48,12 +40,11 @@
      * Constructs a new instance of {@code SecurityPermission} with the given
      * {@code name} and {@code action} list. The action list is ignored - it is
      * existing for compatibility reasons only.
-     * 
+     *
      * @param name
      *            the name of the permission.
      * @param action
      *            ignored.
-     * @since Android 1.0
      */
     public SecurityPermission(String name, String action) {
         super(name, action);
diff --git a/libcore/security/src/main/java/java/security/Signature.java b/libcore/security/src/main/java/java/security/Signature.java
index e5d488e..4e3fe14 100644
--- a/libcore/security/src/main/java/java/security/Signature.java
+++ b/libcore/security/src/main/java/java/security/Signature.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.nio.ByteBuffer;
@@ -39,7 +34,6 @@
  * registered with the {@link Security} class.
  * 
  * @see SignatureSpi
- * @since Android 1.0
  */
 public abstract class Signature extends SignatureSpi {
     
@@ -58,24 +52,18 @@
     /**
      * Constant that indicates that this {@code Signature} instance has not yet
      * been initialized.
-     * 
-     * @since Android 1.0
      */
     protected static final int UNINITIALIZED = 0;
 
     /**
      * Constant that indicates that this {@code Signature} instance has been
      * initialized for signing.
-     * 
-     * @since Android 1.0
      */
     protected static final int SIGN = 2;
 
     /**
      * Constant that indicates that this {@code Signature} instance has been
      * initialized for verification.
-     * 
-     * @since Android 1.0
      */
     protected static final int VERIFY = 3;
 
@@ -83,18 +71,15 @@
      * Represents the current state of this {@code Signature}. The three
      * possible states are {@link #UNINITIALIZED}, {@link #SIGN} or
      * {@link #VERIFY}.
-     * 
-     * @since Android 1.0
      */
     protected int state = UNINITIALIZED;
 
     /**
      * Constructs a new instance of {@code Signature} with the name of
      * the algorithm to use.
-     * 
+     *
      * @param algorithm
      *            the name of algorithm to use.
-     * @since Android 1.0
      */
     protected Signature(String algorithm) {
         this.algorithm = algorithm;
@@ -103,7 +88,7 @@
     /**
      * Returns a new instance of {@code Signature} that utilizes the specified
      * algorithm.
-     * 
+     *
      * @param algorithm
      *            the name of the algorithm to use.
      * @return a new instance of {@code Signature} that utilizes the specified
@@ -112,7 +97,6 @@
      *             if the specified algorithm is not available.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static Signature getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -137,7 +121,7 @@
     /**
      * Returns a new instance of {@code Signature} that utilizes the specified
      * algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the algorithm to use.
      * @param provider
@@ -150,7 +134,6 @@
      *             if the specified provider is not available.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static Signature getInstance(String algorithm, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
@@ -171,7 +154,7 @@
     /**
      * Returns a new instance of {@code Signature} that utilizes the specified
      * algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the algorithm to use.
      * @param provider
@@ -182,7 +165,6 @@
      *             if the specified algorithm is not available.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static Signature getInstance(String algorithm, Provider provider)
             throws NoSuchAlgorithmException {
@@ -214,9 +196,8 @@
 
     /**
      * Returns the provider associated with this {@code Signature}.
-     * 
+     *
      * @return the provider associated with this {@code Signature}.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -224,9 +205,8 @@
 
     /**
      * Returns the name of the algorithm of this {@code Signature}.
-     * 
+     *
      * @return the name of the algorithm of this {@code Signature}.
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -236,12 +216,11 @@
      * Initializes this {@code Signature} instance for signature verification,
      * using the public key of the identity whose signature is going to be
      * verified.
-     * 
+     *
      * @param publicKey
      *            the public key.
      * @throws InvalidKeyException
      *             if {@code publicKey} is not valid.
-     * @since Android 1.0
      */
     public final void initVerify(PublicKey publicKey)
             throws InvalidKeyException {
@@ -257,14 +236,12 @@
      * If the given certificate is an instance of {@link X509Certificate} and
      * has a key usage parameter that indicates, that this certificate is not to
      * be used for signing, an {@code InvalidKeyException} is thrown.
-     * </p>
-     * 
+     *
      * @param certificate
      *            the certificate used to verify a signature.
      * @throws InvalidKeyException
      *             if the publicKey in the certificate is not valid or not to be
      *             used for signing.
-     * @since Android 1.0
      */
     public final void initVerify(Certificate certificate)
             throws InvalidKeyException {
@@ -302,12 +279,11 @@
     /**
      * Initializes this {@code Signature} instance for signing, using the
      * private key of the identity whose signature is going to be generated.
-     * 
+     *
      * @param privateKey
      *            the private key.
      * @throws InvalidKeyException
      *             if {@code privateKey} is not valid.
-     * @since Android 1.0
      */
     public final void initSign(PrivateKey privateKey)
             throws InvalidKeyException {
@@ -319,14 +295,13 @@
      * Initializes this {@code Signature} instance for signing, using the
      * private key of the identity whose signature is going to be generated and
      * the specified source of randomness.
-     * 
+     *
      * @param privateKey
      *            the private key.
      * @param random
      *            the {@code SecureRandom} to use.
      * @throws InvalidKeyException
      *             if {@code privateKey} is not valid.
-     * @since Android 1.0
      */
     public final void initSign(PrivateKey privateKey, SecureRandom random)
             throws InvalidKeyException {
@@ -340,13 +315,11 @@
      * This {@code Signature} instance is reset to the state of its last
      * initialization for signing and thus can be used for another signature
      * from the same identity.
-     * </p>
-     * 
+     *
      * @return the signature of all updated data.
      * @throws SignatureException
      *             if this {@code Signature} instance is not initialized
      *             properly.
-     * @since Android 1.0
      */
     public final byte[] sign() throws SignatureException {
         if (state != SIGN) {
@@ -363,8 +336,7 @@
      * This {@code Signature} instance is reset to the state of its last
      * initialization for signing and thus can be used for another signature
      * from the same identity.
-     * </p>
-     * 
+     *
      * @param outbuf
      *            the buffer to store the signature.
      * @param offset
@@ -378,7 +350,6 @@
      * @throws IllegalArgumentException
      *             if {@code offset} or {@code len} are not valid in respect to
      *             {@code outbuf}.
-     * @since Android 1.0
      */
     public final int sign(byte[] outbuf, int offset, int len)
             throws SignatureException {       
@@ -401,8 +372,7 @@
      * This {@code Signature} instance is reset to the state of its last
      * initialization for verifying and thus can be used to verify another
      * signature of the same signer.
-     * </p>
-     * 
+     *
      * @param signature
      *            the signature to verify.
      * @return {@code true} if the signature was verified, {@code false}
@@ -410,7 +380,6 @@
      * @throws SignatureException
      *             if this {@code Signature} instance is not initialized
      *             properly.
-     * @since Android 1.0
      */
     public final boolean verify(byte[] signature) throws SignatureException {
         if (state != VERIFY) {
@@ -428,8 +397,7 @@
      * This {@code Signature} instance is reset to the state of its last
      * initialization for verifying and thus can be used to verify another
      * signature of the same signer.
-     * </p>
-     * 
+     *
      * @param signature
      *            the {@code byte[]} containing the signature to verify.
      * @param offset
@@ -444,7 +412,6 @@
      * @throws IllegalArgumentException
      *             if {@code offset} or {@code length} are not valid in respect
      *             to {@code signature}.
-     * @since Android 1.0
      */
     public final boolean verify(byte[] signature, int offset, int length)
             throws SignatureException {
@@ -463,13 +430,12 @@
     /**
      * Updates the data to be verified or to be signed, using the specified
      * {@code byte}.
-     * 
+     *
      * @param b
      *            the byte to update with.
      * @throws SignatureException
      *             if this {@code Signature} instance is not initialized
      *             properly.
-     * @since Android 1.0
      */
     public final void update(byte b) throws SignatureException {
         if (state == UNINITIALIZED) {
@@ -482,13 +448,12 @@
     /**
      * Updates the data to be verified or to be signed, using the specified
      * {@code byte[]}.
-     * 
+     *
      * @param data
      *            the byte array to update with.
      * @throws SignatureException
      *             if this {@code Signature} instance is not initialized
      *             properly.
-     * @since Android 1.0
      */
     public final void update(byte[] data) throws SignatureException {
         if (state == UNINITIALIZED) {
@@ -501,7 +466,7 @@
     /**
      * Updates the data to be verified or to be signed, using the given {@code
      * byte[]}, starting form the specified index for the specified length.
-     * 
+     *
      * @param data
      *            the byte array to update with.
      * @param off
@@ -511,7 +476,6 @@
      * @throws SignatureException
      *             if this {@code Signature} instance is not initialized
      *             properly.
-     * @since Android 1.0
      */
     public final void update(byte[] data, int off, int len)
             throws SignatureException {
@@ -530,13 +494,12 @@
     /**
      * Updates the data to be verified or to be signed, using the specified
      * {@code ByteBuffer}.
-     * 
+     *
      * @param data
      *            the {@code ByteBuffer} to update with.
      * @throws SignatureException
      *             if this {@code Signature} instance is not initialized
      *             properly.
-     * @since Android 1.0
      */
     public final void update(ByteBuffer data) throws SignatureException {
         if (state == UNINITIALIZED) {
@@ -549,10 +512,10 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * {@code Signature} including its algorithm and its state.
-     * 
+     *
      * @return a printable representation for this {@code Signature}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         return "SIGNATURE " + algorithm + " state: " + stateToString(state); //$NON-NLS-1$ //$NON-NLS-2$
     }
@@ -571,12 +534,9 @@
         }
     }
 
-    // BEGIN android-note
-    // added Deprecated annotation
-    // END android-note
     /**
      * Sets the specified parameter to the given value.
-     * 
+     *
      * @param param
      *            the name of the parameter.
      * @param value
@@ -585,7 +545,6 @@
      *             if the parameter is invalid, already set or is not allowed to
      *             be changed.
      * @deprecated Use {@link #setParameter(AlgorithmParameterSpec)}
-     * @since Android 1.0
      */
     @Deprecated
     public final void setParameter(String param, Object value)
@@ -595,13 +554,12 @@
 
     /**
      * Sets the specified {@code AlgorithmParameterSpec}.
-     * 
+     *
      * @param params
      *            the parameter to set.
      * @throws InvalidAlgorithmParameterException
      *             if the parameter is invalid, already set or is not allowed to
      *             be changed.
-     * @since Android 1.0
      */
     public final void setParameter(AlgorithmParameterSpec params)
             throws InvalidAlgorithmParameterException {
@@ -611,18 +569,14 @@
     /**
      * Returns the {@code AlgorithmParameters} of this {@link Signature}
      * instance.
-     * 
+     *
      * @return the {@code AlgorithmParameters} of this {@link Signature}
      *         instance, maybe {@code null}.
-     * @since Android 1.0
      */
     public final AlgorithmParameters getParameters() {
         return engineGetParameters();
     }
 
-    // BEGIN android-note
-    // added Deprecated annotation
-    // END android-note
     /**
      * Returns the value of the parameter with the specified name.
      * 
@@ -634,7 +588,6 @@
      *             if {@code param} is not a valid parameter for this {@code
      *             Signature} or an other error occures.
      * @deprecated There is no generally accepted parameter naming convention.
-     * @since Android 1.0
      */
     @Deprecated
     public final Object getParameter(String param)
@@ -642,12 +595,12 @@
         return engineGetParameter(param);
     }
 
+    @Override
     public Object clone() throws CloneNotSupportedException {
         if (this instanceof Cloneable) {
             return super.clone();
-        } else {
-            throw new CloneNotSupportedException();
         }
+        throw new CloneNotSupportedException();
     }
 
     /**
@@ -668,58 +621,66 @@
         }
 
         // engineSign() implementation
+        @Override
         protected byte[] engineSign() throws SignatureException {
             return spiImpl.engineSign();
         }
 
         //  engineUpdate() implementation
+        @Override
         protected void engineUpdate(byte arg0) throws SignatureException {
             spiImpl.engineUpdate(arg0);
         }
 
         // engineVerify() implementation
+        @Override
         protected boolean engineVerify(byte[] arg0) throws SignatureException {
             return spiImpl.engineVerify(arg0);
         }
 
         // engineUpdate() implementation
+        @Override
         protected void engineUpdate(byte[] arg0, int arg1, int arg2)
                 throws SignatureException {
             spiImpl.engineUpdate(arg0, arg1, arg2);
         }
 
         // engineInitSign() implementation
+        @Override
         protected void engineInitSign(PrivateKey arg0)
                 throws InvalidKeyException {
             spiImpl.engineInitSign(arg0);
         }
 
         // engineInitVerify() implementation
+        @Override
         protected void engineInitVerify(PublicKey arg0)
                 throws InvalidKeyException {
             spiImpl.engineInitVerify(arg0);
         }
 
         // engineGetParameter() implementation
+        @Override
         protected Object engineGetParameter(String arg0)
                 throws InvalidParameterException {
             return spiImpl.engineGetParameter(arg0);
         }
 
         // engineSetParameter() implementation
+        @Override
         protected void engineSetParameter(String arg0, Object arg1)
                 throws InvalidParameterException {
             spiImpl.engineSetParameter(arg0, arg1);
         }
 
         // Returns a clone if the spiImpl is cloneable
+        @Override
         public Object clone() throws CloneNotSupportedException {
             if (spiImpl instanceof Cloneable) {
                 SignatureSpi spi = (SignatureSpi) spiImpl.clone();
                 return new SignatureImpl(spi, getProvider(), getAlgorithm());
-            } else {
-                throw new CloneNotSupportedException();
             }
+            throw new CloneNotSupportedException();
         }
     }
 }
diff --git a/libcore/security/src/main/java/java/security/SignatureException.java b/libcore/security/src/main/java/java/security/SignatureException.java
index f07c34b..f8909d1 100644
--- a/libcore/security/src/main/java/java/security/SignatureException.java
+++ b/libcore/security/src/main/java/java/security/SignatureException.java
@@ -15,18 +15,12 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
  *{@code SignatureException} is a general {@code Signature} exception.
  * 
  * @see Signature
- * @since Android 1.0
  */
 public class SignatureException extends GeneralSecurityException {
 
@@ -35,10 +29,9 @@
     /**
      * Constructs a new instance of {@code SignatureException} with the
      * given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public SignatureException(String msg) {
         super(msg);
@@ -46,8 +39,6 @@
 
     /**
      * Constructs a new instance of {@code SignatureException}.
-     * 
-     * @since Android 1.0
      */
     public SignatureException() {
     }
@@ -55,12 +46,11 @@
     /**
      * Constructs a new instance of {@code SignatureException} with the
      * given message and the cause.
-     * 
+     *
      * @param message
      *            the detail message for this exception
      * @param cause
      *            the exception which is the cause for this exception
-     * @since Android 1.0
      */
     public SignatureException(String message, Throwable cause) {
         super(message, cause);
@@ -69,10 +59,9 @@
     /**
      * Constructs a new instance of {@code SignatureException} with the
      * cause.
-     * 
+     *
      * @param cause
      *            the exception which is the cause for this exception
-     * @since Android 1.0
      */
     public SignatureException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/SignatureSpi.java b/libcore/security/src/main/java/java/security/SignatureSpi.java
index 738d489..93c9e8c 100644
--- a/libcore/security/src/main/java/java/security/SignatureSpi.java
+++ b/libcore/security/src/main/java/java/security/SignatureSpi.java
@@ -14,10 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
 
 package java.security;
 
@@ -31,14 +27,11 @@
  * definition for {@link Signature}.
  * 
  * @see Signature
- * @since Android 1.0
  */
 public abstract class SignatureSpi {
 
     /**
      * Implementation specific source of randomness.
-     * 
-     * @since Android 1.0
      */
     protected SecureRandom appRandom;
 
@@ -46,12 +39,11 @@
      * Initializes this {@code SignatureSpi} instance for signature
      * verification, using the public key of the identity whose signature is
      * going to be verified.
-     * 
+     *
      * @param publicKey
      *            the public key.
      * @throws InvalidKeyException
      *             if {@code publicKey} is not valid.
-     * @since Android 1.0
      */
     protected abstract void engineInitVerify(PublicKey publicKey)
             throws InvalidKeyException;
@@ -59,12 +51,11 @@
     /**
      * Initializes this {@code SignatureSpi} instance for signing, using the
      * private key of the identity whose signature is going to be generated.
-     * 
+     *
      * @param privateKey
      *            the private key.
      * @throws InvalidKeyException
      *             if {@code privateKey} is not valid.
-     * @since Android 1.0
      */
     protected abstract void engineInitSign(PrivateKey privateKey)
             throws InvalidKeyException;
@@ -73,14 +64,13 @@
      * Initializes this {@code SignatureSpi} instance for signing, using the
      * private key of the identity whose signature is going to be generated and
      * the specified source of randomness.
-     * 
+     *
      * @param privateKey
      *            the private key.
      * @param random
      *            the {@code SecureRandom} to use.
      * @throws InvalidKeyException
      *             if {@code privateKey} is not valid.
-     * @since Android 1.0
      */
     protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
             throws InvalidKeyException {
@@ -91,20 +81,19 @@
     /**
      * Updates the data to be verified or to be signed, using the specified
      * {@code byte}.
-     * 
+     *
      * @param b
      *            the byte to update with.
      * @throws SignatureException
      *             if this {@code SignatureSpi} instance is not initialized
      *             properly.
-     * @since Android 1.0
      */
     protected abstract void engineUpdate(byte b) throws SignatureException;
 
     /**
      * Updates the data to be verified or to be signed, using the given {@code
      * byte[]}, starting form the specified index for the specified length.
-     * 
+     *
      * @param b
      *            the byte array to update with.
      * @param off
@@ -114,7 +103,6 @@
      * @throws SignatureException
      *             if this {@code SignatureSpi} instance is not initialized
      *             properly.
-     * @since Android 1.0
      */
     protected abstract void engineUpdate(byte[] b, int off, int len)
             throws SignatureException;
@@ -130,7 +118,6 @@
      *             method it throws a {@code RuntimeException} if underlying
      *             {@link #engineUpdate(byte[], int, int)} throws {@code
      *             SignatureException}.
-     * @since Android 1.0
      */
     protected void engineUpdate(ByteBuffer input) {
         if (!input.hasRemaining()) {
@@ -165,13 +152,11 @@
      * This {@code SignatureSpi} instance is reset to the state of its last
      * initialization for signing and thus can be used for another signature
      * from the same identity.
-     * </p>
-     * 
+     *
      * @return the signature of all updated data.
      * @throws SignatureException
      *             if this {@code SignatureSpi} instance is not initialized
      *             properly.
-     * @since Android 1.0
      */
     protected abstract byte[] engineSign() throws SignatureException;
 
@@ -182,8 +167,7 @@
      * This {@code SignatureSpi} instance is reset to the state of its last
      * initialization for signing and thus can be used for another signature
      * from the same identity.
-     * </p>
-     * 
+     *
      * @param outbuf
      *            the buffer to store the signature.
      * @param offset
@@ -197,7 +181,6 @@
      * @throws IllegalArgumentException
      *             if {@code offset} or {@code len} are not valid in respect to
      *             {@code outbuf}.
-     * @since Android 1.0
      */
     protected int engineSign(byte[] outbuf, int offset, int len)
             throws SignatureException {
@@ -225,8 +208,7 @@
      * This {@code SignatureSpi} instance is reset to the state of its last
      * initialization for verifying and thus can be used to verify another
      * signature of the same signer.
-     * </p>
-     * 
+     *
      * @param sigBytes
      *            the signature to verify.
      * @return {@code true} if the signature was verified, {@code false}
@@ -234,7 +216,6 @@
      * @throws SignatureException
      *             if this {@code SignatureSpi} instance is not initialized
      *             properly.
-     * @since Android 1.0
      */
     protected abstract boolean engineVerify(byte[] sigBytes)
             throws SignatureException;
@@ -247,8 +228,7 @@
      * This {@code SignatureSpi} instance is reset to the state of its last
      * initialization for verifying and thus can be used to verify another
      * signature of the same signer.
-     * </p>
-     * 
+     *
      * @param sigBytes
      *            the {@code byte[]} containing the signature to verify.
      * @param offset
@@ -263,7 +243,6 @@
      * @throws IllegalArgumentException
      *             if {@code offset} or {@code length} are not valid in respect
      *             to {@code sigBytes}.
-     * @since Android 1.0
      */
     protected boolean engineVerify(byte[] sigBytes, int offset, int length)
             throws SignatureException {
@@ -274,7 +253,7 @@
 
     /**
      * Sets the specified parameter to the given value.
-     * 
+     *
      * @param param
      *            the name of the parameter.
      * @param value
@@ -283,7 +262,6 @@
      *             if the parameter is invalid, already set or is not allowed to
      *             be changed.
      * @deprecated Use {@link #engineSetParameter(AlgorithmParameterSpec)}
-     * @since Android 1.0
      */
     @Deprecated
     protected abstract void engineSetParameter(String param, Object value)
@@ -291,13 +269,12 @@
 
     /**
      * Sets the specified {@code AlgorithmParameterSpec}.
-     * 
+     *
      * @param params
      *            the parameter to set.
      * @throws InvalidAlgorithmParameterException
      *             if the parameter is invalid, already set or is not allowed to
      *             be changed.
-     * @since Android 1.0
      */
     protected void engineSetParameter(AlgorithmParameterSpec params)
             throws InvalidAlgorithmParameterException {
@@ -307,21 +284,17 @@
     /**
      * Returns the {@code AlgorithmParameters} of this {@link SignatureSpi}
      * instance.
-     * 
+     *
      * @return the {@code AlgorithmParameters} of this {@link SignatureSpi}
      *         instance, maybe {@code null}.
-     * @since Android 1.0
      */
     protected AlgorithmParameters engineGetParameters() {
         throw new UnsupportedOperationException();
     }
 
-    // BEGIN android-note
-    // added Deprecated annotation
-    // END android-note
     /**
      * Returns the value of the parameter with the specified name.
-     * 
+     *
      * @param param
      *            the name of the requested parameter value.
      * @return the value of the parameter with the specified name, maybe {@code
@@ -330,17 +303,16 @@
      *             if {@code param} is not a valid parameter for this {@code
      *             SignatureSpi} or an other error occurs.
      * @deprecated There is no generally accepted parameter naming convention.
-     * @since Android 1.0
      */
     @Deprecated
     protected abstract Object engineGetParameter(String param)
             throws InvalidParameterException;
 
+    @Override
     public Object clone() throws CloneNotSupportedException {
         if (this instanceof Cloneable) {
             return super.clone();
-        } else {
-            throw new CloneNotSupportedException();
         }
+        throw new CloneNotSupportedException();
     }
 }
diff --git a/libcore/security/src/main/java/java/security/SignedObject.java b/libcore/security/src/main/java/java/security/SignedObject.java
index d2022c8..3347cf3 100644
--- a/libcore/security/src/main/java/java/security/SignedObject.java
+++ b/libcore/security/src/main/java/java/security/SignedObject.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.ByteArrayInputStream;
@@ -33,8 +28,6 @@
  * A {@code SignedObject} instance acts as a container for another object. The
  * {@code SignedObject} contains the target in serialized form along with a
  * digital signature of the serialized data.
- * 
- * @since Android 1.0
  */
 public final class SignedObject implements Serializable {
 
@@ -75,7 +68,6 @@
      *             if the private key is not valid.
      * @throws SignatureException
      *             if signature generation failed.
-     * @since Android 1.0
      */
     public SignedObject(Serializable object, PrivateKey signingKey,
             Signature signingEngine) throws IOException, InvalidKeyException,
@@ -106,7 +98,6 @@
      *             if deserialization failed.
      * @throws ClassNotFoundException
      *             if the class of the encapsulated object can not be found.
-     * @since Android 1.0
      */
     public Object getObject() throws IOException, ClassNotFoundException {
         // deserialize our object
@@ -123,7 +114,6 @@
      * Returns the signature data of the encapsulated serialized object.
      * 
      * @return the signature data of the encapsulated serialized object.
-     * @since Android 1.0
      */
     public byte[] getSignature() {
         byte[] sig = new byte[signature.length];
@@ -135,7 +125,6 @@
      * Returns the name of the algorithm of this {@code SignedObject}.
      * 
      * @return the name of the algorithm of this {@code SignedObject}.
-     * @since Android 1.0
      */
     public String getAlgorithm() {
         return thealgorithm;
@@ -155,7 +144,6 @@
      *             if the public key is invalid.
      * @throws SignatureException
      *             if signature verification failed.
-     * @since Android 1.0
      */
     public boolean verify(PublicKey verificationKey,
             Signature verificationEngine) throws InvalidKeyException,
@@ -166,4 +154,4 @@
         return verificationEngine.verify(signature);
     }
 
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/Signer.java b/libcore/security/src/main/java/java/security/Signer.java
index 9e48226..64996bf 100644
--- a/libcore/security/src/main/java/java/security/Signer.java
+++ b/libcore/security/src/main/java/java/security/Signer.java
@@ -15,16 +15,8 @@
  *  limitations under the License.
  */
 
-/**
- * @author Aleksei Y. Semenov
- * @version $Revision$
- */
-
 package java.security;
 
-// BEGIN android-note
-// added Deprecated annotation
-// END android-note
 /**
  * {@link Signer} represents an identity (individual or corporation) that owns a
  * private key and the corresponding public key.
@@ -32,7 +24,6 @@
  * @deprecated Replaced by behavior in {@link java.security.cert
  *             java.security.cert} package and {@link java.security.Principal
  *             Principal}
- * @since Android 1.0
  */
 @Deprecated
 public abstract class Signer extends Identity {
@@ -43,8 +34,6 @@
 
     /**
      * Constructs a new instance of {@code Signer}.
-     * 
-     * @since Android 1.0
      */
     protected Signer() {
         super();
@@ -52,10 +41,9 @@
 
     /**
      * Constructs a new instance of {@code Signer} with the given name.
-     * 
+     *
      * @param name
      *            the name of the signer.
-     * @since Android 1.0
      */
     public Signer(String name) {
         super(name);
@@ -64,7 +52,7 @@
     /**
      * Constructs a new instance of {@code Signer} with the given name in the
      * given scope.
-     * 
+     *
      * @param name
      *            the name of the signer.
      * @param scope
@@ -72,7 +60,6 @@
      * @throws KeyManagementException
      *             if a signer with the specified name already exists in the
      *             provided scope.
-     * @since Android 1.0
      */
     public Signer(String name, IdentityScope scope)
             throws KeyManagementException {
@@ -84,12 +71,11 @@
      * SecurityManager} is installed, code calling this method needs the {@code
      * SecurityPermission} {@code "getSignerPrivateKey"} to be granted, otherwise
      * a {@code SecurityException} will be thrown.
-     * 
+     *
      * @return the private key of this {@code Signer}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public PrivateKey getPrivateKey() {
         SecurityManager sm = System.getSecurityManager();
@@ -105,7 +91,7 @@
      * SecurityManager} is installed, code calling this method needs the {@code
      * SecurityPermission} {@code getSignerPrivateKey} to be granted, otherwise
      * a {@code SecurityException} will be thrown.
-     * 
+     *
      * @param pair
      *            the key pair to associate with this {@code Signer}.
      * @throws InvalidParameterException
@@ -115,7 +101,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and the caller does
      *             not have permission to invoke this method.
-     * @since Android 1.0
      */
     public final void setKeyPair(KeyPair pair)
             throws InvalidParameterException, KeyException {
@@ -148,10 +133,10 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * {@code Signer} including its name and its scope if present.
-     * 
+     *
      * @return a printable representation for this {@code Signer}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         String s = "[Signer]" + getName(); //$NON-NLS-1$
         if (getScope() != null) {
diff --git a/libcore/security/src/main/java/java/security/Timestamp.java b/libcore/security/src/main/java/java/security/Timestamp.java
index 1d31e6f..5a2930a 100644
--- a/libcore/security/src/main/java/java/security/Timestamp.java
+++ b/libcore/security/src/main/java/java/security/Timestamp.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.Serializable;
@@ -31,8 +26,6 @@
 /**
  * {@code Timestamp} represents a signed time stamp. {@code Timestamp} is
  * immutable.
- * 
- * @since Android 1.0
  */
 public final class Timestamp implements Serializable {
 
@@ -48,7 +41,7 @@
     /**
      * Constructs a new instance of {@code Timestamp} with the specified {@code
      * timestamp} and the given certificate path.
-     * 
+     *
      * @param timestamp
      *            date and time.
      * @param signerCertPath
@@ -56,7 +49,6 @@
      * @throws NullPointerException
      *             if {@code timestamp} is {@code null} or if {@code
      *             signerCertPath} is {@code null}.
-     * @since Android 1.0
      */
     public Timestamp(Date timestamp, CertPath signerCertPath) {
         if (timestamp == null) {
@@ -76,15 +68,15 @@
      * otherwise. The given object is equal to this {@code Timestamp}, if it is
      * an instance of {@code Timestamp}, the two timestamps have an equal date
      * and time and their certificate paths are equal.
-     * 
+     *
      * @param obj
      *            object to be compared for equality with this {@code
      *            Timestamp}.
      * @return {@code true} if the specified object is equal to this {@code
      *         Timestamp}, otherwise {@code false}.
      * @see #hashCode
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj == this) {
             return true;
@@ -99,9 +91,8 @@
 
     /**
      * Returns the certificate path of this {@code Timestamp}.
-     * 
+     *
      * @return the certificate path of this {@code Timestamp}.
-     * @since Android 1.0
      */
     public CertPath getSignerCertPath() {
         return signerCertPath;
@@ -109,15 +100,11 @@
 
     /**
      * Returns the date and time of this {@code Timestamp}.
-     * 
+     *
      * @return the date and time of this {@code Timestamp}.
-     * @since Android 1.0
      */
     public Date getTimestamp() {
-        // BEGIN android-changed
-        // copied from a newer version of harmony
         return (Date) timestamp.clone();
-        // END android-changed
     }
 
     /**
@@ -128,8 +115,8 @@
      * @return the hash code value for this {@code Timestamp}.
      * @see Object#equals(Object)
      * @see Timestamp#equals(Object)
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         if (hash == 0) {
             hash = timestamp.hashCode() ^ signerCertPath.hashCode();
@@ -140,15 +127,15 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * {@code Timestamp}.
-     * 
+     *
      * @return a printable representation for this {@code Timestamp}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        StringBuffer buf = new StringBuffer(256);
+        StringBuilder buf = new StringBuilder(256);
         // Dump only the first certificate
         buf.append("Timestamp [").append(timestamp).append(" certPath="); //$NON-NLS-1$ //$NON-NLS-2$
         buf.append(signerCertPath.getCertificates().get(0)).append("]"); //$NON-NLS-1$
         return buf.toString();
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/UnrecoverableEntryException.java b/libcore/security/src/main/java/java/security/UnrecoverableEntryException.java
index dc2981a..24ff54b 100644
--- a/libcore/security/src/main/java/java/security/UnrecoverableEntryException.java
+++ b/libcore/security/src/main/java/java/security/UnrecoverableEntryException.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 
@@ -29,7 +24,6 @@
  * 
  * @see KeyStore
  * @see KeyStore.Entry
- * @since Android 1.0
  */
 public class UnrecoverableEntryException extends GeneralSecurityException {
 
@@ -37,8 +31,6 @@
 
     /**
      * Constructs a new instance of {@code UnrecoverableEntryException}.
-     * 
-     * @since Android 1.0
      */
     public UnrecoverableEntryException() {
     }
@@ -46,12 +38,11 @@
     /**
      * Constructs a new instance of {@code UnrecoverableEntryException} with the
      * given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnrecoverableEntryException(String msg) {
         super(msg);
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/UnrecoverableKeyException.java b/libcore/security/src/main/java/java/security/UnrecoverableKeyException.java
index e4b399b..3840e6b 100644
--- a/libcore/security/src/main/java/java/security/UnrecoverableKeyException.java
+++ b/libcore/security/src/main/java/java/security/UnrecoverableKeyException.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security;
 
 /**
@@ -27,7 +22,6 @@
  * from a {@code KeyStore}.
  * 
  * @see KeyStore
- * @since Android 1.0
  */
 public class UnrecoverableKeyException extends GeneralSecurityException {
 
@@ -36,10 +30,9 @@
     /**
      * Constructs a new instance of {@code UnrecoverableKeyException} with the
      * given message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception
-     * @since Android 1.0
      */
     public UnrecoverableKeyException(String msg) {
         super(msg);
@@ -47,8 +40,6 @@
 
     /**
      * Constructs a new instance of {@code UnrecoverableKeyException}.
-     * 
-     * @since Android 1.0
      */
     public UnrecoverableKeyException() {
     }
diff --git a/libcore/security/src/main/java/java/security/UnresolvedPermission.java b/libcore/security/src/main/java/java/security/UnresolvedPermission.java
index 6570de4..bf99a40 100644
--- a/libcore/security/src/main/java/java/security/UnresolvedPermission.java
+++ b/libcore/security/src/main/java/java/security/UnresolvedPermission.java
@@ -15,27 +15,18 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InvalidObjectException;
 import java.io.NotSerializableException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.io.ObjectStreamField;
 import java.io.Serializable;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
-import java.util.ArrayList;
-import java.util.List;
 
 import org.apache.harmony.security.fortress.PolicyUtils;
 import org.apache.harmony.security.internal.nls.Messages;
@@ -46,24 +37,17 @@
  * Policy}. {@code UnresolvedPermission}s contain all information to be replaced
  * by a concrete typed {@code Permission} right before the access checks are
  * performed.
- * 
- * @since Android 1.0
  */
 public final class UnresolvedPermission extends Permission
     implements Serializable {
 
     private static final long serialVersionUID = -4821973115467008846L;
 
-    private static final ObjectStreamField serialPersistentFields[] = {
-        new ObjectStreamField("type", String.class), //$NON-NLS-1$
-        new ObjectStreamField("name", String.class), //$NON-NLS-1$
-        new ObjectStreamField("actions", String.class), }; //$NON-NLS-1$
-
-    // Target name
-    private transient String targetName;
-
-    //Target actions
-    private transient String targetActions;
+    private String type;    
+    
+    private String name;
+    
+    private String actions;
 
     // The signer certificates 
     private transient Certificate[] targetCerts;
@@ -75,7 +59,7 @@
      * Constructs a new instance of {@code UnresolvedPermission}. The supplied
      * parameters are used when this instance is resolved to the concrete
      * {@code Permission}.
-     * 
+     *
      * @param type
      *            the fully qualified class name of the permission this class is
      *            resolved to.
@@ -90,26 +74,17 @@
      *            maybe {@code null}.
      * @throws NullPointerException
      *             if type is {@code null}.
-     * @since Android 1.0
      */
     public UnresolvedPermission(String type, String name, String actions,
                                 Certificate[] certs) {
         super(type);
         checkType(type);
-        targetName = name;
-        targetActions = actions;
-        if (certs != null && certs.length != 0) {
-            //TODO filter non-signer certificates ???
-            List tmp = new ArrayList();
-            for (int i = 0; i < certs.length; i++) {
-                if (certs[i] != null) {
-                    tmp.add(certs[i]);
-                }
-            }
-            if (tmp.size() != 0) {
-                targetCerts = (Certificate[])tmp.toArray(
-                                new Certificate[tmp.size()]);
-            }
+        this.type = type;
+        this.name = name;
+        this.actions = actions;
+        if (certs != null) {
+            this.targetCerts = new Certificate[certs.length];
+            System.arraycopy(certs, 0, targetCerts, 0, certs.length);
         }
         hash = 0;
     }
@@ -136,52 +111,105 @@
      * instance of {@code UnresolvedPermission}, the two {@code
      * UnresolvedPermission}s must refer to the same type and must have the same
      * name, the same actions and certificates.
-     * 
+     *
      * @param obj
      *            object to be compared for equality with this {@code
      *            UnresolvedPermission}.
      * @return {@code true} if the specified object is equal to this {@code
      *         UnresolvedPermission}, otherwise {@code false}.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj == this) {
             return true;
         }
         if (obj instanceof UnresolvedPermission) {
-            UnresolvedPermission that = (UnresolvedPermission)obj;
+            UnresolvedPermission that = (UnresolvedPermission) obj;
             if (getName().equals(that.getName())
-                && (targetName == null ? that.targetName == null 
-                    : targetName.equals(that.targetName))
-                && (targetActions == null ? that.targetActions == null
-                    : targetActions.equals(that.targetActions))
-                && (PolicyUtils.matchSubset(targetCerts, that.targetCerts) 
-                    && PolicyUtils.matchSubset(that.targetCerts, targetCerts))) {
+                    && (name == null ? that.name == null : name
+                            .equals(that.name))
+                    && (actions == null ? that.actions == null : actions
+                            .equals(that.actions))
+                    && equalsCertificates(this.targetCerts, that.targetCerts)) {
                 return true;
             }
         }
         return false;
     }
 
+    /*
+     * check whether given array of certificates are equivalent
+     */
+    private boolean equalsCertificates(Certificate[] certs1,
+            Certificate[] certs2) {
+        if (certs1 == null || certs2 == null) {
+            return certs1 == certs2;
+        }
+
+        int length = certs1.length;
+        if (length != certs2.length) {
+            return false;
+        }
+
+        if (length > 0) {
+            boolean found;
+            for (int i = 0; i < length; i++) {
+            	// Skip the checking for null
+            	if(certs1[i] == null){
+            		continue;
+            	}
+                found = false;
+                for (int j = 0; j < length; j++) {
+                    if (certs1[i].equals(certs2[j])) {
+                        found = true;
+                        break;
+                    }
+                }
+
+                if (!found) {
+                    return false;
+                }
+            }
+
+            for (int i = 0; i < length; i++) {
+            	if(certs2[i] == null){
+            		continue;
+            	}
+                found = false;
+                for (int j = 0; j < length; j++) {
+                    if (certs2[i].equals(certs1[j])) {
+                        found = true;
+                        break;
+                    }
+                }
+
+                if (!found) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     /**
      * Returns the hash code value for this {@code UnresolvedPermission}.
      * Returns the same hash code for {@code UnresolvedPermission}s that are
      * equal to each other as required by the general contract of
      * {@link Object#hashCode}.
-     * 
+     *
      * @return the hash code value for this {@code UnresolvedPermission}.
      * @see Object#equals(Object)
      * @see UnresolvedPermission#equals(Object)
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         if (hash == 0) {
             hash = getName().hashCode();
-            if (targetName != null) {
-                hash ^= targetName.hashCode();
+            if (name != null) {
+                hash ^= name.hashCode();
             }
-            if (targetActions != null) {
-                hash ^= targetActions.hashCode();
+            if (actions != null) {
+                hash ^= actions.hashCode();
             }
         }
         return hash;
@@ -191,10 +219,10 @@
      * Returns an empty string since there are no actions allowed for {@code
      * UnresolvedPermission}. The actions, specified in the constructor, are
      * used when the concrete permission is resolved and created.
-     * 
+     *
      * @return an empty string, indicating that there are no actions.
-     * @since Android 1.0
      */
+    @Override
     public String getActions() {
         return ""; //$NON-NLS-1$
     }
@@ -202,34 +230,31 @@
     /**
      * Returns the name of the permission this {@code UnresolvedPermission} is
      * resolved to.
-     * 
+     *
      * @return the name of the permission this {@code UnresolvedPermission} is
      *         resolved to.
-     * @since Android 1.0
      */
     public String getUnresolvedName() {
-        return targetName;
+        return name;
     }
 
     /**
      * Returns the actions of the permission this {@code UnresolvedPermission}
      * is resolved to.
-     * 
+     *
      * @return the actions of the permission this {@code UnresolvedPermission}
      *         is resolved to.
-     * @since Android 1.0
      */
     public String getUnresolvedActions() {
-        return targetActions;
+        return actions;
     }
 
     /**
      * Returns the fully qualified class name of the permission this {@code
      * UnresolvedPermission} is resolved to.
-     * 
+     *
      * @return the fully qualified class name of the permission this {@code
      *         UnresolvedPermission} is resolved to.
-     * @since Android 1.0
      */
     public String getUnresolvedType() {
         return super.getName();
@@ -238,10 +263,9 @@
     /**
      * Returns the certificates of the permission this {@code
      * UnresolvedPermission} is resolved to.
-     * 
+     *
      * @return the certificates of the permission this {@code
      *         UnresolvedPermission} is resolved to.
-     * @since Android 1.0
      */
     public Certificate[] getUnresolvedCerts() {
         if (targetCerts != null) {
@@ -261,13 +285,12 @@
      * UnresolvedPermissions (if any) against the passed instance. Successfully
      * resolved permissions (if any) are taken into account during further
      * processing.
-     * </p>
-     * 
+     *
      * @param permission
      *            the permission to check.
      * @return always {@code false}
-     * @since Android 1.0
      */
+    @Override
     public boolean implies(Permission permission) {
         return false;
     }
@@ -276,23 +299,23 @@
      * Returns a string containing a concise, human-readable description of this
      * {@code UnresolvedPermission} including its target name and its target
      * actions.
-     * 
+     *
      * @return a printable representation for this {@code UnresolvedPermission}.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        return "(unresolved " + getName() + " " + targetName + " " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-            + targetActions + ")"; //$NON-NLS-1$
+        return "(unresolved " + type + " " + name + " " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+            + actions + ")"; //$NON-NLS-1$
     }
 
     /**
      * Returns a new {@code PermissionCollection} for holding {@code
      * UnresolvedPermission} objects.
-     * 
+     *
      * @return a new PermissionCollection for holding {@code
      *         UnresolvedPermission} objects.
-     * @since Android 1.0
      */
+    @Override
     public PermissionCollection newPermissionCollection() {
         return new UnresolvedPermissionCollection();
     }
@@ -306,16 +329,12 @@
      * per {@code getUnresolvedCerts()}) among the passed collection of signers.
      * If it does, a zero, one, and/or two-argument constructor is tried to
      * instantiate a new permission, which is then returned.
-     * </p>
      * <p>
      * If an appropriate constructor is not available or the class is improperly
      * signed, {@code null} is returned.
-     * </p>
-     * 
+     *
      * @param targetType
      *            - a target class instance, must not be {@code null}
-     * @param signers
-     *            - actual signers of the targetType
      * @return resolved permission or null
      */
     Permission resolve(Class targetType) {
@@ -323,8 +342,8 @@
         if (PolicyUtils.matchSubset(targetCerts, targetType.getSigners())) {
             try {
                 return PolicyUtils.instantiatePermission(targetType,
-                                                         targetName,
-                                                         targetActions);
+                                                         name,
+                                                         actions);
             } catch (Exception ignore) {
                 //TODO log warning?
             }
@@ -333,8 +352,6 @@
     }
 
     /**
-     * @com.intel.drl.spec_ref
-     * 
      * Outputs {@code type},{@code name},{@code actions}
      * fields via default mechanism; next manually writes certificates in the
      * following format: <br>
@@ -353,11 +370,7 @@
      *  @see  <a href="http://java.sun.com/j2se/1.5.0/docs/api/serialized-form.html#java.security.UnresolvedPermission">Java Spec</a>
      */
     private void writeObject(ObjectOutputStream out) throws IOException {
-        ObjectOutputStream.PutField fields = out.putFields();
-        fields.put("type", getUnresolvedType()); //$NON-NLS-1$
-        fields.put("name", getUnresolvedName()); //$NON-NLS-1$
-        fields.put("actions", getUnresolvedActions()); //$NON-NLS-1$
-        out.writeFields();
+        out.defaultWriteObject();
         if (targetCerts == null) {
             out.writeInt(0);
         } else {
@@ -378,19 +391,12 @@
     }
 
     /** 
-     * @com.intel.drl.spec_ref
-     * 
      * Reads the object from stream and checks target type for validity. 
      */
     private void readObject(ObjectInputStream in) throws IOException,
         ClassNotFoundException {
-        checkType(getUnresolvedType());
-        ObjectInputStream.GetField fields = in.readFields();
-        if (!getUnresolvedType().equals(fields.get("type", null))) { //$NON-NLS-1$
-            throw new InvalidObjectException(Messages.getString("security.31")); //$NON-NLS-1$
-        }
-        targetName = (String)fields.get("name", null); //$NON-NLS-1$
-        targetActions = (String)fields.get("actions", null); //$NON-NLS-1$
+        in.defaultReadObject();        
+        checkType(getUnresolvedType());      
         int certNumber = in.readInt();
         if (certNumber != 0) {
             targetCerts = new Certificate[certNumber];
diff --git a/libcore/security/src/main/java/java/security/UnresolvedPermissionCollection.java b/libcore/security/src/main/java/java/security/UnresolvedPermissionCollection.java
index a43a54f..3a6ba92 100644
--- a/libcore/security/src/main/java/java/security/UnresolvedPermissionCollection.java
+++ b/libcore/security/src/main/java/java/security/UnresolvedPermissionCollection.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
 package java.security;
 
 import java.io.IOException;
@@ -66,7 +61,6 @@
      * @throws IllegalArgumentException
      *             if {@code permission} is {@code null} or not an {@code
      *             UnresolvedPermission}.
-     * @since Android 1.0
      */
     public void add(Permission permission) {
         if (isReadOnly()) {
@@ -101,7 +95,6 @@
      * 
      * @return always {@code false}
      * @see UnresolvedPermission#implies(Permission).
-     * @since Android 1.0
      */
     public boolean implies(Permission permission) {
         return false;
@@ -159,15 +152,14 @@
     }
 
     /** 
-     * @com.intel.drl.spec_ref
-     * 
      * Output fields via default mechanism. 
      */
     private void writeObject(java.io.ObjectOutputStream out) throws IOException {
         Hashtable permissions = new Hashtable();
-        for (Iterator iter = klasses.keySet().iterator(); iter.hasNext();) {
-            String key = (String)iter.next();
-            permissions.put(key, new Vector(((Collection)klasses.get(key))));
+        for (Iterator iter = klasses.entrySet().iterator(); iter.hasNext();) {
+        	Map.Entry entry = (Map.Entry) iter.next();
+            String key = (String) entry.getKey();
+            permissions.put(key, new Vector(((Collection) entry.getValue())));
         }
         ObjectOutputStream.PutField fields = out.putFields();
         fields.put("permissions", permissions); //$NON-NLS-1$
@@ -175,8 +167,6 @@
     }
 
     /** 
-     * @com.intel.drl.spec_ref
-     * 
      * Reads the object from stream and checks elements grouping for validity. 
      */
     private void readObject(java.io.ObjectInputStream in) throws IOException,
@@ -185,20 +175,23 @@
         Map permissions = (Map)fields.get("permissions", null); //$NON-NLS-1$
         klasses = new HashMap();
         synchronized (klasses) {
-            for (Iterator iter = permissions.keySet().iterator(); iter
-                .hasNext();) {
-                String key = (String)iter.next();
-                Collection values = (Collection)permissions.get(key);
-                for (Iterator iterator = values.iterator(); iterator.hasNext();) {
-                    UnresolvedPermission element = (UnresolvedPermission)iterator
-                        .next();
-                    if (!element.getName().equals(key)) {
-                        throw new InvalidObjectException(
-                            Messages.getString("security.22")); //$NON-NLS-1$
-                    }
-                }
-                klasses.put(key, new HashSet(values));
-            }
+            for (Iterator iter = permissions.entrySet().iterator(); iter
+            	.hasNext();) {
+            	Map.Entry entry = (Map.Entry) iter.next();
+	            String key = (String) entry.getKey();
+	            Collection values = (Collection) entry.getValue();
+
+	            for (Iterator iterator = values.iterator(); iterator.hasNext();) {
+	                UnresolvedPermission element =
+	                        (UnresolvedPermission) iterator.next();
+
+	                if (!element.getName().equals(key)) {
+	                    throw new InvalidObjectException(
+	                        Messages.getString("security.22")); //$NON-NLS-1$
+	                }
+	            }
+	            klasses.put(key, new HashSet(values));
+	        }
         }
     }
 }
\ No newline at end of file
diff --git a/libcore/security/src/main/java/java/security/acl/Acl.java b/libcore/security/src/main/java/java/security/acl/Acl.java
index 35c92fc..88dd9f0 100644
--- a/libcore/security/src/main/java/java/security/acl/Acl.java
+++ b/libcore/security/src/main/java/java/security/acl/Acl.java
@@ -24,17 +24,15 @@
  * The <i>Access Control List</i> (<b>ACL</b>) interface definition.
  * <p>
  * An ACL is a set of {@link AclEntry} objects.
- * </p>
  * <p>
  * An {@code AclEntry} is a list of {@link Permission}s that are granted 
  * (<i>positive</i>) or denied
  * (<i>negative</i>) to a {@link Principal}.
- * </p>
  * <p>
- * An {@code Acl} has a list of owners ({@link Owner}) which are principals as well {@code
- * Principal}. Only those principals which are the {@code Acl}'s owners are allowed to modify the {@code
+ * An {@code Acl} has a list of owners ({@link Owner}) which are principals as
+ * well {@code Principal}. Only those principals which are the {@code Acl}'s
+ * owners are allowed to modify the {@code
  * Acl}.
- * </p>
  * <p>
  * The <i>ACL</i> has to conform to the following rules:
  * <ul>
@@ -49,9 +47,6 @@
  * <li>If there is no {@code AclEntry} associated with a specific {@code
  * Principal}, then it is interpreted as an empty list of permissions.</li>
  * </ul>
- * </p>
- * 
- * @since Android 1.0
  */
 public interface Acl extends Owner {
 
@@ -65,7 +60,6 @@
      * @throws NotOwnerException
      *             if the invoking {@code Principal} is not an owner of this
      *             <i>ACL</i>.
-     * @since Android 1.0
      */
     void setName(Principal caller, String name) throws NotOwnerException;
 
@@ -73,7 +67,6 @@
      * Returns the name of this <i>ACL</i> instance.
      * 
      * @return the name of this <i>ACL</i> instance.
-     * @since Android 1.0
      */
     String getName();
 
@@ -82,18 +75,16 @@
      * <p>
      * If the <i>ACL</i> already has an {@code AclEntry} of the same type (<i>
      * positive</i> or <i>negative</i>) and principal, then the new entry is not added.
-     * </p>
-     * 
+     *
      * @param caller
      *            the invoking {@code Principal}.
      * @param entry
      *            the ACL entry to add.
-     * @return {@code true} if the entry is added, {@code false} if there is already an entry of
-     *         the same type for the same principal
+     * @return {@code true} if the entry is added, {@code false} if there is
+     *             already an entry of the same type for the same principal
      * @throws NotOwnerException
      *             if the invoking {@code Principal} is not an owner of this
      *             <i>ACL</i>.
-     * @since Android 1.0
      */
     boolean addEntry(Principal caller, AclEntry entry) throws NotOwnerException;
     
@@ -104,12 +95,11 @@
      *            the invoking {@code Principal}.
      * @param entry
      *            the ACL entry to remove.
-     * @return {@code true} if the entry is removed, {@code false} if the entry is not in this
-     *         <i>ACL</i>.
+     * @return {@code true} if the entry is removed, {@code false} if the entry
+     *            is not in this <i>ACL</i>.
      * @throws NotOwnerException
      *             if the invoking {@code Principal} is not an owner of this
      *             <i>ACL</i>.
-     * @since Android 1.0
      */
     boolean removeEntry(Principal caller, AclEntry entry) 
                 throws NotOwnerException;
@@ -120,7 +110,6 @@
      * <p>
      * If the specified principal has no entry in this ACL, an empty set is
      * returned.
-     * </p>
      * <p>
      * The allowed permissions are collected according to the following rules:
      * <ul>
@@ -136,12 +125,10 @@
      * permissions override the group's negative permissions and the negative
      * individual permissions override the grpup's positive permissions.</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param user
      *            the principal to get the allowed permissions for.
      * @return the set of allowed permissions for the specified principal.
-     * @since Android 1.0
      */
     Enumeration<Permission> getPermissions(Principal user); 
     
@@ -151,7 +138,6 @@
      * 
      * @return an {@code Enumeration} of the {@code AclEntry} of this
      *         <i>ACL</i>.
-     * @since Android 1.0
      */
     Enumeration<AclEntry> entries();
     
@@ -161,15 +147,14 @@
      * <p>
      * The list of granted permissions is determined according to the rules
      * specified by {@code getPermissions}.
-     * </p>
-     * 
+     *
      * @param principal
      *            the principal the check the permissions for.
      * @param permission
      *            the permission to check for the principal.
-     * @return {@code true} if the principal is granted the permission, otherwise {@code false}.
+     * @return {@code true} if the principal is granted the permission,
+     *            otherwise {@code false}.
      * @see #getPermissions(Principal)
-     * @since Android 1.0
      */
     boolean checkPermission(Principal principal, Permission permission);
     
@@ -177,7 +162,6 @@
      * Returns the string representation of this ACL.
      * 
      * @return the string representation of this ACL.
-     * @since Android 1.0
      */
     String toString();
 }
diff --git a/libcore/security/src/main/java/java/security/acl/AclEntry.java b/libcore/security/src/main/java/java/security/acl/AclEntry.java
index 7a5b722..fe2fb3a 100644
--- a/libcore/security/src/main/java/java/security/acl/AclEntry.java
+++ b/libcore/security/src/main/java/java/security/acl/AclEntry.java
@@ -25,9 +25,6 @@
  * <p>
  * An {@code AclEntry} is a list of the {@link Permission}s that are 
  *  granted (<i>positive</i>) or denied (<i>negative</i>) to a {@link Principal}.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface AclEntry extends Cloneable {
 
@@ -35,13 +32,11 @@
      * Set the principal for this ACL entry.
      * <p>
      * The principal for an ACL entry can only be set once.
-     * </p>
-     * 
+     *
      * @param user
      *            the principal for this ACL entry.
      * @return {@code true} on success, {@code false} if there is a principal already set for
      *         this entry.
-     * @since Android 1.0
      */
     boolean setPrincipal(Principal user);
     
@@ -49,7 +44,6 @@
      * Returns the principal of this ACL entry.
      * 
      * @return the principal of this ACL entry, or null if none is set.
-     * @since Android 1.0
      */
     Principal getPrincipal();
     
@@ -58,13 +52,9 @@
      * <p>
      * The permissions in this ACL entry will be denied to the principal
      * associated with this entry.
-     * </p>
      * <p>
      * Note: An ACL entry is <i>positive</i> by default and can only become
      * <i>negative</i> by calling this method.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     void setNegativePermissions();
     
@@ -72,7 +62,6 @@
      * Returns whether this ACL entry is <i>negative</i>.
      * 
      * @return {@code true} if this ACL entry is negative, {@code false} if it's positive.
-     * @since Android 1.0
      */
     boolean isNegative();
     
@@ -83,7 +72,6 @@
      *            the permission to be added.
      * @return {@code true} if the specified permission is added, {@code false} if the
      *         permission was already in this entry.
-     * @since Android 1.0
      */
     boolean addPermission(Permission permission);
     
@@ -94,7 +82,6 @@
      *            the permission to be removed.
      * @return {@code true} if the permission is removed, {@code false} if the permission was
      *         not in this entry.
-     * @since Android 1.0
      */
     boolean removePermission(Permission permission);
     
@@ -104,7 +91,6 @@
      * @param permission
      *            the permission to check.
      * @return {@code true} if the permission is in this entry, otherwise {@code false}.
-     * @since Android 1.0
      */
     boolean checkPermission(Permission permission);
     
@@ -112,7 +98,6 @@
      * Returns the list of permissions of this ACL entry.
      * 
      * @return the list of permissions of this ACL entry,
-     * @since Android 1.0
      */
     Enumeration<Permission> permissions();
     
@@ -120,7 +105,6 @@
      * Returns the string representation of this ACL entry.
      * 
      * @return the string representation of this ACL entry.
-     * @since Android 1.0
      */
     String toString();
     
@@ -128,7 +112,6 @@
      * Clones this ACL entry instance.
      * 
      * @return a copy of this entry.
-     * @since Android 1.0
      */
     Object clone();
     
diff --git a/libcore/security/src/main/java/java/security/acl/AclNotFoundException.java b/libcore/security/src/main/java/java/security/acl/AclNotFoundException.java
index c8d4208..59b9045 100644
--- a/libcore/security/src/main/java/java/security/acl/AclNotFoundException.java
+++ b/libcore/security/src/main/java/java/security/acl/AclNotFoundException.java
@@ -20,18 +20,13 @@
 /**
  * The exception, that is thrown when a reference to a non-existent <i>Access
  * Control List</i> (ACL) is made.
- * 
- * @since Android 1.0
  */
-
 public class AclNotFoundException extends Exception {
 
     private static final long serialVersionUID = 5684295034092681791L;
 
     /**
      * Creates a new {@code AclNotFoundException}.
-     * 
-     * @since Android 1.0
      */
     public AclNotFoundException() {
 
diff --git a/libcore/security/src/main/java/java/security/acl/Group.java b/libcore/security/src/main/java/java/security/acl/Group.java
index 16898e6..7452181 100644
--- a/libcore/security/src/main/java/java/security/acl/Group.java
+++ b/libcore/security/src/main/java/java/security/acl/Group.java
@@ -24,8 +24,6 @@
  * A {@code Principal} that represents a group of principals.
  * 
  * @see Principal
- * 
- * @since Android 1.0
  */
 public interface Group extends Principal {
     
@@ -35,7 +33,6 @@
      * @param user
      *            the member to add.
      * @return {@code true} if the member was added, {@code false} if it was already a member.
-     * @since Android 1.0
      */
     boolean addMember(Principal user);
     
@@ -45,7 +42,6 @@
      * @param user
      *            the member to remove.
      * @return {@code true} if the member was removed, {@code false} if it was not a member.
-     * @since Android 1.0
      */
     boolean removeMember(Principal user);
     
@@ -55,7 +51,6 @@
      * @param member
      *            the principal to check.
      * @return {@code true} if the principal is a member, otherwise {@code false}.
-     * @since Android 1.0
      */
     boolean isMember(Principal member);
     
@@ -63,7 +58,6 @@
      * Returns the members of this group.
      * 
      * @return the members of this group.
-     * @since Android 1.0
      */
     Enumeration<? extends Principal> members();
     
diff --git a/libcore/security/src/main/java/java/security/acl/LastOwnerException.java b/libcore/security/src/main/java/java/security/acl/LastOwnerException.java
index 11c235f..f947f22 100644
--- a/libcore/security/src/main/java/java/security/acl/LastOwnerException.java
+++ b/libcore/security/src/main/java/java/security/acl/LastOwnerException.java
@@ -18,12 +18,10 @@
 package java.security.acl;
 
 /**
- * The exception that is thrown when an attempt is made to remove the 
+ * The exception that is thrown when an attempt is made to remove the
  * the last {@code Owner} from an {@code Owner}.
- * 
+ *
  * @see Owner
- * 
- * @since Android 1.0
  */
 public class LastOwnerException extends Exception {
 
@@ -31,9 +29,7 @@
 
     /**
      * Creates a new {@code LastOwnerException}.
-     * 
-     * @since Android 1.0
      */
     public LastOwnerException() {
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/acl/NotOwnerException.java b/libcore/security/src/main/java/java/security/acl/NotOwnerException.java
index 081bdea..c7de8c9 100644
--- a/libcore/security/src/main/java/java/security/acl/NotOwnerException.java
+++ b/libcore/security/src/main/java/java/security/acl/NotOwnerException.java
@@ -19,13 +19,11 @@
 
 /**
  * The exception that is thrown when an action that requires ownership is
- * attempted by a principal that is not an owner of the object for which 
- * ownership is required. 
+ * attempted by a principal that is not an owner of the object for which
+ * ownership is required.
  * 
  * @see Acl
  * @see Owner
- * 
- * @since Android 1.0
  */
 public class NotOwnerException extends Exception {
 
@@ -33,9 +31,7 @@
 
     /**
      * Creates a new {@code NotOwnerException}.
-     * 
-     * @since Android 1.0
      */
     public NotOwnerException() {
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/acl/Owner.java b/libcore/security/src/main/java/java/security/acl/Owner.java
index 335dc84..c392e2f 100644
--- a/libcore/security/src/main/java/java/security/acl/Owner.java
+++ b/libcore/security/src/main/java/java/security/acl/Owner.java
@@ -24,7 +24,6 @@
  * 
  * @see Acl
  * @see Principal
- * @since Android 1.0
  */
 public interface Owner {
     
@@ -38,7 +37,6 @@
      * @return {@code true} if the owner was added, {@code false} if it was already an owner.
      * @throws NotOwnerException
      *             if the invoking principal is not an owner.
-     * @since Android 1.0
      */
     boolean addOwner(Principal caller, Principal owner) 
                  throws NotOwnerException;
@@ -56,7 +54,6 @@
      * @throws LastOwnerException
      *             if the owner to be removed is the last owner and hence removing it
      *             would make this object owner-less.
-     * @since Android 1.0
      */
     boolean deleteOwner(Principal caller, Principal owner) 
                 throws NotOwnerException, LastOwnerException;
@@ -67,7 +64,6 @@
      * @param owner
      *            the principal to check.
      * @return {@code true} if the specified principal is an owner, otherwise {@code false}.
-     * @since Android 1.0
      */
     boolean isOwner(Principal owner);
 }
diff --git a/libcore/security/src/main/java/java/security/acl/Permission.java b/libcore/security/src/main/java/java/security/acl/Permission.java
index 0d6e22c..f2ee251 100644
--- a/libcore/security/src/main/java/java/security/acl/Permission.java
+++ b/libcore/security/src/main/java/java/security/acl/Permission.java
@@ -22,9 +22,6 @@
  * <p>
  * It can be granted or denied to a {@link java.security.Principal Principal} 
  * using an {@link Acl}. 
- * </p>
- * 
- * @since Android 1.0
  */
 public interface Permission {
 
@@ -36,7 +33,6 @@
      *            the permission object to compare to this permission.
      * @return true if the specified permission object is equal to this, false
      *         if not.
-     * @since Android 1.0
      */
     boolean equals(Object another);
     
@@ -44,7 +40,6 @@
      * Returns the string representation of this permission.
      * 
      * @return the string representation of this permission.
-     * @since Android 1.0
      */
     String toString();
 }
diff --git a/libcore/security/src/main/java/java/security/cert/CRL.java b/libcore/security/src/main/java/java/security/cert/CRL.java
index b0f3e30..8153853 100644
--- a/libcore/security/src/main/java/java/security/cert/CRL.java
+++ b/libcore/security/src/main/java/java/security/cert/CRL.java
@@ -23,7 +23,6 @@
  * expired and consequently has become invalid.
  * 
  * @see CertificateFactory
- * @since Android 1.0
  */
 public abstract class CRL {
     // The CRL type
@@ -31,10 +30,9 @@
 
     /**
      * Creates a new certificate revocation list of the specified type.
-     * 
+     *
      * @param type
      *            the type for the CRL.
-     * @since Android 1.0
      */
     protected CRL(String type) {
         this.type = type;
@@ -42,9 +40,8 @@
 
     /**
      * Returns the type of this CRL.
-     * 
+     *
      * @return the type of this CRL.
-     * @since Android 1.0
      */
     public final String getType() {
         return type;
@@ -52,20 +49,18 @@
 
     /**
      * Returns whether the specified certificate is revoked by this CRL.
-     * 
+     *
      * @param cert
      *            the certificate to check.
      * @return {@code true} if the certificate is revoked by this CRL, otherwise
      *         {@code false}.
-     * @since Android 1.0
      */
     public abstract boolean isRevoked(Certificate cert);
 
     /**
      * Returns the string representation of this instance.
-     * 
+     *
      * @return the string representation of this instance.
-     * @since Android 1.0
      */
     public abstract String toString();
 }
diff --git a/libcore/security/src/main/java/java/security/cert/CRLException.java b/libcore/security/src/main/java/java/security/cert/CRLException.java
index 625d7d3..01e2071 100644
--- a/libcore/security/src/main/java/java/security/cert/CRLException.java
+++ b/libcore/security/src/main/java/java/security/cert/CRLException.java
@@ -15,19 +15,12 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security.cert;
 
 import java.security.GeneralSecurityException;
 
 /**
  * The exception that is thrown if errors occur during handling of {@code CRL}s.
- * 
- * @since Android 1.0
  */
 public class CRLException extends GeneralSecurityException {
 
@@ -38,7 +31,6 @@
      * 
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public CRLException(String msg) {
         super(msg);
@@ -46,8 +38,6 @@
 
     /**
      * Creates a new {@code CRLException}.
-     * 
-     * @since Android 1.0
      */
     public CRLException() {
     }
@@ -59,7 +49,6 @@
      *            the detail message for this exception.
      * @param cause
      *            the cause for this exception.
-     * @since Android 1.0
      */
     public CRLException(String message, Throwable cause) {
         super(message, cause);
@@ -70,7 +59,6 @@
      * 
      * @param cause
      *            the cause for this exception.
-     * @since Android 1.0
      */
     public CRLException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/cert/CRLSelector.java b/libcore/security/src/main/java/java/security/cert/CRLSelector.java
index ee2d39e..5b14446 100644
--- a/libcore/security/src/main/java/java/security/cert/CRLSelector.java
+++ b/libcore/security/src/main/java/java/security/cert/CRLSelector.java
@@ -23,11 +23,9 @@
  * <p>
  * The implementations of this interface are typically used to define the
  * criteria for selecting {@code CRL}s from a {@code CertStore}.
- * </p>
  * 
  * @see CertStore
  * @see CRL
- * @since Android 1.0
  */
 public interface CRLSelector extends Cloneable {
 
@@ -35,7 +33,6 @@
      * Clones this {@code CRLSelector} instance.
      * 
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone();
 
@@ -47,7 +44,6 @@
      *            the CRL to be evaluated.
      * @return {@code true} if the CRL matches the criteria, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean match(CRL crl);
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPath.java b/libcore/security/src/main/java/java/security/cert/CertPath.java
index 2874a4d..e9d049b 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPath.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPath.java
@@ -33,16 +33,12 @@
  * <p>
  * A {@code CertPath} can be represented as a byte array in at least one
  * supported encoding scheme (i.e. PkiPath or PKCS7) when serialized.
- * </p>
  * <p>
  * When a {@code List} of the certificates is obtained it must be immutable.
- * </p>
  * <p>
  * A {@code CertPath} must be thread-safe without requiring coordinated access.
- * </p>
- * 
+ *
  * @see Certificate
- * @since Android 1.0
  */
 public abstract class CertPath implements Serializable {
 
@@ -53,10 +49,9 @@
     /**
      * Creates a new {@code CertPath} instance for the specified certificate
      * type.
-     * 
+     *
      * @param type
      *            the certificate type.
-     * @since Android 1.0
      */
     protected CertPath(String type) {
         this.type = type;
@@ -64,9 +59,8 @@
 
     /**
      * Returns the type of {@code Certificate} in this instance.
-     * 
+     *
      * @return the certificate type.
-     * @since Android 1.0
      */
     public String getType() {
         return type;
@@ -76,13 +70,11 @@
      * Returns {@code true} if {@code Certificate}s in the list are the same
      * type and the lists are equal (and by implication the certificates
      * contained within are the same).
-     * 
+     *
      * @param other
      *            {@code CertPath} to be compared for equality.
      * @return {@code true} if the object are equal, {@code false} otherwise.
-     * @since Android 1.0
      */
-    @Override
     public boolean equals(Object other) {
         if (this == other) {
             return true;
@@ -99,14 +91,14 @@
     }
 
     /**
-     * Overrides {@code Object.hashCode()}. The function is defined as follows: <br>
+     * Overrides {@code Object.hashCode()}. The function is defined as follows:
+     * <pre>
      * {@code hashCode = 31 * path.getType().hashCode() +
-     * path.getCertificates().hashCode();}</br> </p>
-     * 
+     * path.getCertificates().hashCode();}
+     * </pre>
+     *
      * @return the hash code for this instance.
-     * @since Android 1.0
      */
-    @Override
     public int hashCode() {
         int hash = getType().hashCode();
         hash = hash*31 + getCertificates().hashCode();
@@ -115,13 +107,13 @@
 
     /**
      * Returns a {@code String} representation of this {@code CertPath}
-     * instance.
-     * 
+     * instance. It is the result of calling {@code toString} on all {@code
+     * Certificate}s in the {@code List}.
+     *
      * @return a string representation of this instance.
-     * @since Android 1.0
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer(getType());
+        StringBuilder sb = new StringBuilder(getType());
         sb.append(" Cert Path, len="); //$NON-NLS-1$
         sb.append(getCertificates().size());
         sb.append(": [\n"); //$NON-NLS-1$
@@ -144,7 +136,6 @@
      * in the {@code CertPath}.
      * 
      * @return a list of {@code Certificate}s in the {@code CertPath}.
-     * @since Android 1.0
      */
     public abstract List<? extends Certificate> getCertificates();
 
@@ -154,7 +145,6 @@
      * @return default encoding of the {@code CertPath}.
      * @throws CertificateEncodingException
      *             if the encoding fails.
-     * @since Android 1.0
      */
     public abstract byte[] getEncoded()
         throws CertificateEncodingException;
@@ -167,7 +157,6 @@
      * @return default encoding of the {@code CertPath}.
      * @throws CertificateEncodingException
      *             if the encoding fails.
-     * @since Android 1.0
      */
     public abstract byte[] getEncoded(String encoding)
         throws CertificateEncodingException;
@@ -177,17 +166,15 @@
      * representation of the certificate path.
      * 
      * @return {@code Iterator} over supported encodings (as {@code String}s).
-     * @since Android 1.0
      */
     public abstract Iterator<String> getEncodings();
 
     /**
      * Returns an alternate object to be serialized.
-     * 
+     *
      * @return an alternate object to be serialized.
      * @throws ObjectStreamException
      *             if the creation of the alternate object fails.
-     * @since Android 1.0
      */
     protected Object writeReplace() throws ObjectStreamException {
         try {
@@ -201,8 +188,6 @@
     /**
      * The alternate {@code Serializable} class to be used for serialization and
      * deserialization on {@code CertPath} objects.
-     * 
-     * @since Android 1.0
      */
     protected static class CertPathRep implements Serializable {
 
@@ -222,12 +207,11 @@
         /**
          * Creates a new {@code CertPathRep} instance with the specified type
          * and encoded data.
-         * 
+         *
          * @param type
          *            the certificate type.
          * @param data
          *            the encoded data.
-         * @since Android 1.0
          */
         protected CertPathRep(String type, byte[] data) {
             this.type = type;
@@ -237,11 +221,10 @@
         /**
          * Deserializes a {@code CertPath} from a serialized {@code CertPathRep}
          * object.
-         * 
+         *
          * @return the deserialized {@code CertPath}.
          * @throws ObjectStreamException
          *             if deserialization fails.
-         * @since Android 1.0
          */
         protected Object readResolve() throws ObjectStreamException {
             try {
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathBuilder.java b/libcore/security/src/main/java/java/security/cert/CertPathBuilder.java
index 47eac13..8daa741 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathBuilder.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathBuilder.java
@@ -31,8 +31,6 @@
 /**
  * This class implements the functionality of a builder for an unverified
  * <i>Certification Path</i>s from a specified certificate to a trust anchor.
- * 
- * @since Android 1.0
  */
 public class CertPathBuilder {
 
@@ -60,14 +58,13 @@
 
     /**
      * Creates a new {@code CertPathBuilder}.
-     * 
+     *
      * @param builderSpi
      *            the implementation delegate.
      * @param provider
      *            the provider.
      * @param algorithm
      *            the desired algorithm available at the provider.
-     * @since Android 1.0
      */
     protected CertPathBuilder(CertPathBuilderSpi builderSpi, Provider provider,
             String algorithm) {
@@ -78,9 +75,8 @@
 
     /**
      * Returns the algorithm name of this instance.
-     * 
+     *
      * @return the algorithm name of this instance.
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -88,9 +84,8 @@
 
     /**
      * Returns the provider of this instance.
-     * 
+     *
      * @return the provider of this instance.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -107,7 +102,6 @@
      *             if the algorithm is {@code null}.
      * @throws NoSuchAlgorithmException
      *             if no installed provider can provide the algorithm.
-     * @since Android 1.0
      */
     public static CertPathBuilder getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -138,7 +132,6 @@
      *             if algorithm is {@code null}.
      * @throws IllegalArgumentException
      *             if provider is {@code null} or empty.
-     * @since Android 1.0
      */
     public static CertPathBuilder getInstance(String algorithm, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
@@ -168,7 +161,6 @@
      *             if provider is {@code null}.
      * @throws NullPointerException
      *             if algorithm is {@code null}.
-     * @since Android 1.0
      */
     public static CertPathBuilder getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
@@ -187,7 +179,7 @@
 
     /**
      * Builds a certification path with the specified algorithm parameters.
-     * 
+     *
      * @param params
      *            the algorithm parameters.
      * @return the built certification path.
@@ -197,7 +189,6 @@
      *             if the specified parameters cannot be used to build with this
      *             builder.
      * @see CertPathBuilderResult
-     * @since Android 1.0
      */
     public final CertPathBuilderResult build(CertPathParameters params)
             throws CertPathBuilderException, InvalidAlgorithmParameterException {
@@ -207,11 +198,10 @@
     /**
      * Returns the default {@code CertPathBuilder} type from the <i>Security
      * Properties</i>.
-     * 
+     *
      * @return the default {@code CertPathBuilder} type from the <i>Security
      *         Properties</i>, or the string "{@code PKIX}" if it cannot be
      *         determined.
-     * @since Android 1.0
      */
     public static final String getDefaultType() {
         String defaultType = AccessController
@@ -222,4 +212,4 @@
                 });
         return (defaultType != null ? defaultType : DEFAULTPROPERTY);
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathBuilderException.java b/libcore/security/src/main/java/java/security/cert/CertPathBuilderException.java
index b957291..58a4a60 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathBuilderException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathBuilderException.java
@@ -21,8 +21,6 @@
 
 /**
  * The exception that is thrown when a {@code CertPathBuilder} method fails.
- * 
- * @since Android 1.0
  */
 public class CertPathBuilderException extends GeneralSecurityException {
 
@@ -36,7 +34,6 @@
      *            the detail message for the exception
      * @param cause
      *            why the building of the certification path failed.
-     * @since Android 1.0
      */
     public CertPathBuilderException(String msg, Throwable cause) {
         super(msg, cause);
@@ -47,7 +44,6 @@
      * 
      * @param cause
      *            why the building of the certification path failed.
-     * @since Android 1.0
      */
     public CertPathBuilderException(Throwable cause) {
         super(cause);
@@ -59,7 +55,6 @@
      * 
      * @param msg
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public CertPathBuilderException(String msg) {
         super(msg);
@@ -67,9 +62,7 @@
 
     /**
      * Creates a new {@code CertPathBuilderException}.
-     * 
-     * @since Android 1.0
      */
     public CertPathBuilderException() {
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathBuilderResult.java b/libcore/security/src/main/java/java/security/cert/CertPathBuilderResult.java
index e56c4a0..36d99a1 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathBuilderResult.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathBuilderResult.java
@@ -20,8 +20,6 @@
 /**
  * The interface for results generated by
  * {@link CertPathBuilder#build(CertPathParameters)}.
- * 
- * @since Android 1.0
  */
 public interface CertPathBuilderResult extends Cloneable {
 
@@ -29,7 +27,6 @@
      * Clones this {@code CertPathBuilderResult} instance.
      * 
      * @return the copy of this instance.
-     * @since Android 1.0
      */
     public Object clone();
 
@@ -37,7 +34,6 @@
      * Returns the built {@code CertPath} instance. Never returns {@code null}.
      * 
      * @return the built certificate path instance.
-     * @since Android 1.0
      */
     public CertPath getCertPath();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathBuilderSpi.java b/libcore/security/src/main/java/java/security/cert/CertPathBuilderSpi.java
index 952f387..80ee0ef 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathBuilderSpi.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathBuilderSpi.java
@@ -22,15 +22,11 @@
 /**
  * The <i>Service Provider Interface</i> (<b>SPI</b>) for the {@code
  * CertPathBuilder} class to be implemented by security providers.
- * 
- * @since Android 1.0
  */
 public abstract class CertPathBuilderSpi {
 
     /**
      * Creates a new {@code CertPathBuilderSpi} instance.
-     * 
-     * @since Android 1.0
      */
     public CertPathBuilderSpi() {
     }
@@ -46,7 +42,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters cannot be used to build the path
      *             with this builder.
-     * @since Android 1.0
      */
     public abstract CertPathBuilderResult engineBuild(CertPathParameters params)
             throws CertPathBuilderException, InvalidAlgorithmParameterException;
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathParameters.java b/libcore/security/src/main/java/java/security/cert/CertPathParameters.java
index c99826f..e2cee18 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathParameters.java
@@ -22,8 +22,6 @@
  * <p>
  * This interface is for grouping purposes of {@code CertPath} parameter
  * implementations.
- * </p>
- * @since Android 1.0
  */
 public interface CertPathParameters extends Cloneable {
 
@@ -31,7 +29,6 @@
      * Clones this {@code CertPathParameters} instance.
      * 
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathValidator.java b/libcore/security/src/main/java/java/security/cert/CertPathValidator.java
index f95bd03..0d73280 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathValidator.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathValidator.java
@@ -32,8 +32,6 @@
  * This class provides the functionality for validating certification paths
  * (certificate chains) establishing a trust chain from a certificate to a trust
  * anchor.
- * 
- * @since Android 1.0
  */
 public class CertPathValidator {
     // Store CertPathValidator implementation service name
@@ -60,14 +58,13 @@
 
     /**
      * Creates a new {@code CertPathValidator} instance.
-     * 
+     *
      * @param validatorSpi
      *            the implementation delegate.
      * @param provider
      *            the security provider.
      * @param algorithm
      *            the name of the algorithm.
-     * @since Android 1.0
      */
     protected CertPathValidator(CertPathValidatorSpi validatorSpi,
             Provider provider, String algorithm) {
@@ -78,9 +75,8 @@
 
     /**
      * Returns the certification path algorithm name.
-     * 
+     *
      * @return the certification path algorithm name.
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -88,9 +84,8 @@
 
     /**
      * Returns the security provider.
-     * 
+     *
      * @return the provider.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -106,7 +101,6 @@
      *             if no installed provider provides the specified algorithm.
      * @throws NullPointerException
      *             if algorithm is {@code null}.
-     * @since Android 1.0
      */
     public static CertPathValidator getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -138,7 +132,6 @@
      *             if algorithm is {@code null}.
      * @throws IllegalArgumentException
      *             if provider is {@code null} or empty.
-     * @since Android 1.0
      */
     public static CertPathValidator getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
@@ -169,7 +162,6 @@
      *             if provider is {@code null}.
      * @throws NullPointerException
      *             if algorithm is {@code null}.
-     * @since Android 1.0
      */
     public static CertPathValidator getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
@@ -203,7 +195,6 @@
      *             if the specified algorithm parameters cannot be used with
      *             this algorithm.
      * @see CertPathValidatorResult
-     * @since Android 1.0
      */
     public final CertPathValidatorResult validate(CertPath certPath,
             CertPathParameters params) throws CertPathValidatorException,
@@ -214,11 +205,10 @@
     /**
      * Returns the default {@code CertPathValidator} type from the <i>Security
      * Properties</i>.
-     * 
+     *
      * @return the default {@code CertPathValidator} type from the <i>Security
      *         Properties</i>, or the string {@code "PKIX"} if it cannot be
      *         determined.
-     * @since Android 1.0
      */
     public static final String getDefaultType() {
         String defaultType = AccessController
@@ -229,4 +219,4 @@
                 });
         return (defaultType != null ? defaultType : DEFAULTPROPERTY);
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathValidatorException.java b/libcore/security/src/main/java/java/security/cert/CertPathValidatorException.java
index 072785c..4d2b69f 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathValidatorException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathValidatorException.java
@@ -28,9 +28,6 @@
  * A {@code CertPathValidatorException} may optionally include the certification
  * path instance that failed the validation and the index of the failed
  * certificate.
- * </p>
- * 
- * @since Android 1.0
  */
 public class CertPathValidatorException extends GeneralSecurityException {
 
@@ -65,7 +62,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code certPath} is not {@code null} and index is not
      *             referencing an certificate in the certification path.
-     * @since Android 1.0
      */
     public CertPathValidatorException(String msg, Throwable cause,
             CertPath certPath, int index) {
@@ -91,7 +87,6 @@
      *            the detail message for this exception.
      * @param cause
      *            the cause why the path could not be validated.
-     * @since Android 1.0
      */
     public CertPathValidatorException(String msg, Throwable cause) {
         super(msg, cause);
@@ -103,7 +98,6 @@
      * 
      * @param cause
      *            the cause why the path could not be validated.
-     * @since Android 1.0
      */
     public CertPathValidatorException(Throwable cause) {
         super(cause);
@@ -115,7 +109,6 @@
      * 
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public CertPathValidatorException(String msg) {
         super(msg);
@@ -123,8 +116,6 @@
 
     /**
      * Creates a new {@code CertPathValidatorException}.
-     * 
-     * @since Android 1.0
      */
     public CertPathValidatorException() {
     }
@@ -134,7 +125,6 @@
      * 
      * @return the certification path that failed validation, or {@code null} if
      *         none was specified.
-     * @since Android 1.0
      */
     public CertPath getCertPath() {
         return certPath;
@@ -145,9 +135,8 @@
      * 
      * @return the index of the failed certificate in the certification path, or
      *         {@code -1} if none was specified.
-     * @since Android 1.0
      */
     public int getIndex() {
         return index;
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathValidatorResult.java b/libcore/security/src/main/java/java/security/cert/CertPathValidatorResult.java
index 42540e4..7fab21a 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathValidatorResult.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathValidatorResult.java
@@ -21,8 +21,6 @@
  * The interface specification for certification path validation results.
  * <p>
  * This interface is for grouping purposes of validation result implementations.
- * </p>
- * @since Android 1.0
  */
 public interface CertPathValidatorResult extends Cloneable {
 
@@ -30,7 +28,6 @@
      * Clones this {@code CertPathValidatorResult} instance.
      * 
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathValidatorSpi.java b/libcore/security/src/main/java/java/security/cert/CertPathValidatorSpi.java
index 5573679..e14e8dd 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathValidatorSpi.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathValidatorSpi.java
@@ -22,15 +22,11 @@
 /**
  * The <i>Service Provider Interface</i> (<b>SPI</b>) for the {@code
  * CertPathValidator} class to be implemented by security providers.
- * 
- * @since Android 1.0
  */
 public abstract class CertPathValidatorSpi {
 
     /**
      * Creates a new {@code CertPathValidatorSpi} instance.
-     * 
-     * @since Android 1.0
      */
     public CertPathValidatorSpi() {
     }
@@ -38,7 +34,7 @@
     /**
      * Validates the {@code CertPath} with the algorithm of this {@code
      * CertPathValidator} using the specified algorithm parameters.
-     * 
+     *
      * @param certPath
      *            the certification path to be validated.
      * @param params
@@ -51,10 +47,9 @@
      * @throws InvalidAlgorithmParameterException
      *             if the specified algorithm parameters cannot be used with
      *             this algorithm.
-     * @since Android 1.0
      */
     public abstract CertPathValidatorResult engineValidate(CertPath certPath,
             CertPathParameters params) throws CertPathValidatorException,
             InvalidAlgorithmParameterException;
 
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertSelector.java b/libcore/security/src/main/java/java/security/cert/CertSelector.java
index 0316ad3..c490b22 100644
--- a/libcore/security/src/main/java/java/security/cert/CertSelector.java
+++ b/libcore/security/src/main/java/java/security/cert/CertSelector.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
 package java.security.cert;
 
 /**
@@ -28,11 +23,9 @@
  * <p>
  * The implementations of this interface are typically used to define the
  * criteria for selecting {@code Certificate}s from a {@code CertStore}.
- * </p>
  * 
  * @see CertStore
  * @see Certificate
- * @since Android 1.0
  */
 public interface CertSelector extends Cloneable {
 
@@ -40,7 +33,6 @@
      * Clones this {@code CertSelector} instance.
      * 
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone();
 
@@ -52,7 +44,6 @@
      *            the certificate to be evaluated.
      * @return {@code true} if the certificate matches the criteria, {@code
      *         false} otherwise.
-     * @since Android 1.0
      */
     public boolean match(Certificate cert);
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertStore.java b/libcore/security/src/main/java/java/security/cert/CertStore.java
index a5c8260..d0b7600 100644
--- a/libcore/security/src/main/java/java/security/cert/CertStore.java
+++ b/libcore/security/src/main/java/java/security/cert/CertStore.java
@@ -33,8 +33,6 @@
  * This class provides the functionality to retrieve {@code Certificate}s and
  * {@code CRL}s from a read-only repository. This repository may be very large
  * and may store trusted as well as untrusted certificates.
- * 
- * @since Android 1.0
  */
 public class CertStore {
 
@@ -65,7 +63,7 @@
 
     /**
      * Creates a new {@code CertStore} instance.
-     * 
+     *
      * @param storeSpi
      *            the implementation delegate.
      * @param provider
@@ -74,7 +72,6 @@
      *            the certificate store type.
      * @param params
      *            the certificate store parameters (may be {@code null}.
-     * @since Android 1.0
      */
     protected CertStore(CertStoreSpi storeSpi, Provider provider, String type,
             CertStoreParameters params) {
@@ -101,7 +98,6 @@
      *             certificate store instance.
      * @throws NullPointerException
      *             if the {@code type} is {@code null}.
-     * @since Android 1.0
      */
     public static CertStore getInstance(String type, CertStoreParameters params)
             throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
@@ -147,7 +143,6 @@
      *             if provider is null of empty.
      * @throws NullPointerException
      *             if {@code type} is {@code null}.
-     * @since Android 1.0
      */
     public static CertStore getInstance(String type,
             CertStoreParameters params, String provider)
@@ -183,7 +178,6 @@
      *             if provider is {@code null}.
      * @throws NullPointerException
      *             if {@code type} is {@code null}.
-     * @since Android 1.0
      */
     public static CertStore getInstance(String type,
             CertStoreParameters params, Provider provider)
@@ -212,9 +206,8 @@
 
     /**
      * Returns the certificate store type.
-     * 
+     *
      * @return the certificate store type.
-     * @since Android 1.0
      */
     public final String getType() {
         return type;
@@ -222,9 +215,8 @@
 
     /**
      * Returns the security provider.
-     * 
+     *
      * @return the security provider.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -233,10 +225,9 @@
     /**
      * Returns a copy of the certificate store parameters that were used to
      * initialize this instance.
-     * 
+     *
      * @return a copy of the certificate store parameters or {@code null} if
      *         none were specified.
-     * @since Android 1.0
      */
     public final CertStoreParameters getCertStoreParameters() {
         if (certStoreParams == null) {
@@ -249,7 +240,7 @@
     /**
      * Returns the list of {@code Certificate}s for the specified {@code
      * CertSelector} from this certificate store.
-     * 
+     *
      * @param selector
      *            the selector containing the criteria to search for
      *            certificates in this certificate store.
@@ -257,7 +248,6 @@
      *         specified selector.
      * @throws CertStoreException
      *             if error(s) occur.
-     * @since Android 1.0
      */
     public final Collection<? extends Certificate> getCertificates(CertSelector selector)
             throws CertStoreException {
@@ -267,7 +257,7 @@
     /**
      * Returns the list of {@code CRL}s for the specified {@code CRLSelector}
      * from this certificate store.
-     * 
+     *
      * @param selector
      *            the selector containing the criteria to search for certificate
      *            revocation lists in this store.
@@ -275,7 +265,6 @@
      *         selector
      * @throws CertStoreException
      *             if error(s) occur.
-     * @since Android 1.0
      */
     public final Collection<? extends CRL> getCRLs(CRLSelector selector)
             throws CertStoreException {
@@ -285,12 +274,11 @@
     /**
      * Returns the default {@code CertStore} type from the <i>Security
      * Properties</i>.
-     * 
+     *
      * @return the default {@code CertStore} type from the <i>Security
      *         Properties</i>, or the string {@code "LDAP"} if it cannot be
      *         determined.
-     * @since Android 1.0
-     */    
+     */
     public static final String getDefaultType() {
         String defaultType = AccessController
                 .doPrivileged(new java.security.PrivilegedAction<String>() {
diff --git a/libcore/security/src/main/java/java/security/cert/CertStoreException.java b/libcore/security/src/main/java/java/security/cert/CertStoreException.java
index 8351605..7f356b2 100644
--- a/libcore/security/src/main/java/java/security/cert/CertStoreException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertStoreException.java
@@ -21,8 +21,6 @@
 
 /**
  * The exception that is thrown when an access to a {@code CertStore} fails.
- * 
- * @since Android 1.0
  */
 public class CertStoreException extends GeneralSecurityException {
 
@@ -36,7 +34,6 @@
      *            the detail message for this exception.
      * @param cause
      *            the cause why the access to the certificate store failed.
-     * @since Android 1.0
      */
     public CertStoreException(String msg, Throwable cause) {
         super(msg, cause);
@@ -47,7 +44,6 @@
      * 
      * @param cause
      *            the cause why the access to the certificate store failed.
-     * @since Android 1.0
      */
     public CertStoreException(Throwable cause) {
         super(cause);
@@ -58,7 +54,6 @@
      * 
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public CertStoreException(String msg) {
         super(msg);
@@ -66,9 +61,7 @@
 
     /**
      * Creates a new {@code CertStoreException}.
-     * 
-     * @since Android 1.0
      */
     public CertStoreException() {
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertStoreParameters.java b/libcore/security/src/main/java/java/security/cert/CertStoreParameters.java
index 566b2e2..06a1976 100644
--- a/libcore/security/src/main/java/java/security/cert/CertStoreParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/CertStoreParameters.java
@@ -20,8 +20,6 @@
 /**
  * The marker interface specifying the parameters used to initialize a {@code
  * CertStore} instance.
- * 
- * @since Android 1.0
  */
 public interface CertStoreParameters extends Cloneable {
 
@@ -29,7 +27,6 @@
      * Clones this {@code CertStoreParameters} instance.
      * 
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertStoreSpi.java b/libcore/security/src/main/java/java/security/cert/CertStoreSpi.java
index be680a7..cb38a31 100644
--- a/libcore/security/src/main/java/java/security/cert/CertStoreSpi.java
+++ b/libcore/security/src/main/java/java/security/cert/CertStoreSpi.java
@@ -23,8 +23,6 @@
 /**
  * The <i>Service Provider Interface</i> (<b>SPI</b>) definition for the {@code
  * CertStore} class to be implemented by security providers.
- * 
- * @since Android 1.0
  */
 public abstract class CertStoreSpi {
 
@@ -36,7 +34,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if the specified initialization parameters cannot be used to
      *             initialize this instance.
-     * @since Android 1.0
      */
     public CertStoreSpi(CertStoreParameters params)
             throws InvalidAlgorithmParameterException {
@@ -53,7 +50,6 @@
      *         specified selector.
      * @throws CertStoreException
      *             if error(s) occur.
-     * @since Android 1.0
      */
     public abstract Collection<? extends Certificate> engineGetCertificates(CertSelector selector)
             throws CertStoreException;
@@ -69,7 +65,6 @@
      *         selector
      * @throws CertStoreException
      *             if error(s) occur.
-     * @since Android 1.0
      */
     public abstract Collection<? extends CRL> engineGetCRLs(CRLSelector selector)
             throws CertStoreException;
diff --git a/libcore/security/src/main/java/java/security/cert/Certificate.java b/libcore/security/src/main/java/java/security/cert/Certificate.java
index 0543329..22cbe9c 100644
--- a/libcore/security/src/main/java/java/security/cert/Certificate.java
+++ b/libcore/security/src/main/java/java/security/cert/Certificate.java
@@ -35,8 +35,6 @@
  * Abstract class to represent identity certificates. It represents a way to
  * verify the binding of a Principal and its public key. Examples are X.509,
  * PGP, and SDSI.
- * 
- * @since Android 1.0
  */
 public abstract class Certificate implements Serializable {
 
@@ -47,10 +45,9 @@
 
     /**
      * Creates a new {@code Certificate} with the specified type.
-     * 
+     *
      * @param type
      *        the certificate type.
-     * @since Android 1.0
      */
     protected Certificate(String type) {
         this.type = type;
@@ -58,9 +55,8 @@
 
     /**
      * Returns the certificate type.
-     * 
+     *
      * @return the certificate type.
-     * @since Android 1.0
      */
     public final String getType() {
         return type;
@@ -71,13 +67,12 @@
      * represent the <em>same</em> object using a class specific comparison. The
      * implementation in Object returns {@code true} only if the argument is the
      * exact same object as the callee (==).
-     * 
+     *
      * @param other
      *            the object to compare with this object.
      * @return {@code true} if the object is the same as this object, {@code
      *         false} if it is different from this object.
      * @see #hashCode
-     * @since Android 1.0
      */
     public boolean equals(Object other) {
         // obj equal to itself
@@ -100,10 +95,9 @@
      * Returns an integer hash code for the certificate. Any two objects which
      * return {@code true} when passed to {@code equals} must return the same
      * value for this method.
-     * 
+     *
      * @return the certificate's hash
      * @see #equals
-     * @since Android 1.0
      */
     public int hashCode() {
         try {
@@ -120,17 +114,16 @@
 
     /**
      * Returns the encoded representation for this certificate.
-     * 
+     *
      * @return the encoded representation for this certificate.
      * @throws CertificateEncodingException
      *             if the encoding fails.
-     * @since Android 1.0
      */
     public abstract byte[] getEncoded() throws CertificateEncodingException;
 
     /**
      * Verifies that this certificate was signed with the given public key.
-     * 
+     *
      * @param key
      *            PublicKey public key for which verification should be
      *            performed.
@@ -144,7 +137,6 @@
      *             if there is no default provider.
      * @throws SignatureException
      *             if signature errors are detected.
-     * @since Android 1.0
      */
     public abstract void verify(PublicKey key)
         throws CertificateException,
@@ -156,7 +148,7 @@
     /**
      * Verifies that this certificate was signed with the given public key. It
      * Uses the signature algorithm given by the provider.
-     * 
+     *
      * @param key
      *            PublicKey public key for which verification should be
      *            performed.
@@ -172,7 +164,6 @@
      *                if the specified provider does not exists.
      * @exception SignatureException
      *                if signature errors are detected.
-     * @since Android 1.0
      */
     public abstract void verify(PublicKey key, String sigProvider)
         throws CertificateException,
@@ -184,27 +175,24 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * certificate.
-     * 
+     *
      * @return a printable representation for the certificate.
-     * @since Android 1.0
      */
     public abstract String toString();
 
     /**
      * Returns the public key corresponding to this certificate.
-     * 
+     *
      * @return the public key corresponding to this certificate.
-     * @since Android 1.0
      */
     public abstract PublicKey getPublicKey();
 
     /**
      * Returns an alternate object to be serialized.
-     * 
+     *
      * @return the object to serialize.
      * @throws ObjectStreamException
      *             if the creation of the alternate object fails.
-     * @since Android 1.0
      */
     protected Object writeReplace() throws ObjectStreamException {
         try {
@@ -217,9 +205,7 @@
 
     /**
      * The alternate {@code Serializable} class to be used for serialization and
-     * deserialization of {@code Certificate} objects. 
-     * 
-     * @since Android 1.0
+     * deserialization of {@code Certificate} objects.
      */
     protected static class CertificateRep implements Serializable {
 
@@ -239,12 +225,11 @@
         /**
          * Creates a new {@code CertificateRep} instance with the specified
          * certificate type and encoded data.
-         * 
+         *
          * @param type
          *            the certificate type.
          * @param data
          *            the encoded data.
-         * @since Android 1.0
          */
         protected CertificateRep(String type, byte[] data) {
             this.type = type;
@@ -254,11 +239,10 @@
         /**
          * Deserializes a {@code Certificate} from a serialized {@code
          * CertificateRep} object.
-         * 
+         *
          * @return the deserialized {@code Certificate}.
          * @throws ObjectStreamException
          *             if deserialization fails.
-         * @since Android 1.0
          */
         protected Object readResolve() throws ObjectStreamException {
             try {
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateEncodingException.java b/libcore/security/src/main/java/java/security/cert/CertificateEncodingException.java
index 188d084..c5532b9 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateEncodingException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateEncodingException.java
@@ -20,8 +20,6 @@
 /**
  * The exception that is thrown when an error occurs while a {@code Certificate}
  * is being encoded.
- * 
- * @since Android 1.0
  */
 public class CertificateEncodingException extends CertificateException {
 
@@ -33,7 +31,6 @@
      * 
      * @param msg
      *            The detail message for the exception.
-     * @since Android 1.0
      */
     public CertificateEncodingException(String msg) {
         super(msg);
@@ -41,8 +38,6 @@
 
     /**
      * Creates a new {@code CertificateEncodingException}.
-     * 
-     * @since Android 1.0
      */
     public CertificateEncodingException() {
     }
@@ -55,7 +50,6 @@
      *            the detail message for the exception.
      * @param cause
      *            the cause.
-     * @since Android 1.0
      */
     public CertificateEncodingException(String message, Throwable cause) {
         super(message, cause);
@@ -67,7 +61,6 @@
      * 
      * @param cause
      *            the cause.
-     * @since Android 1.0
      */
     public CertificateEncodingException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateException.java b/libcore/security/src/main/java/java/security/cert/CertificateException.java
index 674d617..8b1c4d3 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateException.java
@@ -21,8 +21,6 @@
 
 /**
  * The base class for all {@code Certificate} related exceptions.
- * 
- * @since Android 1.0
  */
 public class CertificateException extends GeneralSecurityException {
 
@@ -33,7 +31,6 @@
      * 
      * @param msg
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public CertificateException(String msg) {
         super(msg);
@@ -41,8 +38,6 @@
 
     /**
      * Creates a new {@code CertificateException}.
-     * 
-     * @since Android 1.0
      */
     public CertificateException() {
     }
@@ -55,7 +50,6 @@
      *            the detail message for the exception.
      * @param cause
      *            the cause.
-     * @since Android 1.0
      */
     public CertificateException(String message, Throwable cause) {
         super(message, cause);
@@ -66,7 +60,6 @@
      * 
      * @param cause
      *            the cause
-     * @since Android 1.0
      */
     public CertificateException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateExpiredException.java b/libcore/security/src/main/java/java/security/cert/CertificateExpiredException.java
index fe3fc1f..e15bf98 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateExpiredException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateExpiredException.java
@@ -19,8 +19,6 @@
 
 /**
  * The exception that is thrown when a {@code Certificate} has expired.
- * 
- * @since Android 1.0
  */
 public class CertificateExpiredException extends CertificateException {
 
@@ -32,7 +30,6 @@
      * 
      * @param msg
      *            the detail message for this exception
-     * @since Android 1.0
      */
     public CertificateExpiredException(String msg) {
         super(msg);
@@ -40,8 +37,6 @@
 
     /**
      * Creates a new {@code CertificateExpiredException}.
-     * 
-     * @since Android 1.0
      */
     public CertificateExpiredException() {
     }
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateFactory.java b/libcore/security/src/main/java/java/security/cert/CertificateFactory.java
index b4213d4..cb2636a 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateFactory.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateFactory.java
@@ -36,9 +36,6 @@
  * <p>
  * It defines methods for parsing certificate chains (certificate paths) and
  * <i>Certificate Revocation Lists</i> (CRLs).
- * </p>
- * 
- * @since Android 1.0
  */
 public class CertificateFactory {
 
@@ -59,14 +56,13 @@
 
     /**
      * Creates a new {@code CertificateFactory} instance.
-     * 
+     *
      * @param certFacSpi
      *            the implementation delegate.
      * @param provider
      *            the associated provider.
      * @param type
      *            the certificate type.
-     * @since Android 1.0
      */
     protected CertificateFactory(CertificateFactorySpi certFacSpi,
             Provider provider, String type) {
@@ -87,7 +83,6 @@
      *             installed provider.
      * @throws NullPointerException
      *             if {@code type} is {@code null}.
-     * @since Android 1.0
      */
     public static final CertificateFactory getInstance(String type)
             throws CertificateException {
@@ -124,7 +119,6 @@
      *             if the specified provider name is {@code null} or empty.
      * @throws NullPointerException
      *             it {@code type} is {@code null}.
-     * @since Android 1.0
      */
     public static final CertificateFactory getInstance(String type,
             String provider) throws CertificateException,
@@ -156,7 +150,6 @@
      *             if the specified provider is {@code null}.
      * @throws NullPointerException
      *             is {@code type} is {@code null}.
-     * @since Android 1.0
      */
     public static final CertificateFactory getInstance(String type,
             Provider provider) throws CertificateException {
@@ -182,7 +175,6 @@
      * the certificate.
      * 
      * @return the provider of this certificate factory.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -192,7 +184,6 @@
      * Returns the Certificate type.
      * 
      * @return type of certificate being used.
-     * @since Android 1.0
      */
     public final String getType() {
         return type;
@@ -208,7 +199,6 @@
      * @return an initialized Certificate.
      * @throws CertificateException
      *             if parsing problems are detected.
-     * @since Android 1.0
      */
     public final Certificate generateCertificate(InputStream inStream)
             throws CertificateException {
@@ -221,7 +211,6 @@
      * 
      * @return an iterator over supported {@link CertPath} encodings (as
      *         Strings).
-     * @since Android 1.0
      */
     public final Iterator<String> getCertPathEncodings() {
         return spiImpl.engineGetCertPathEncodings();
@@ -236,7 +225,6 @@
      * @return a {@code CertPath} initialized from the provided data.
      * @throws CertificateException
      *             if parsing problems are detected.
-     * @since Android 1.0
      */
     public final CertPath generateCertPath(InputStream inStream)
             throws CertificateException {
@@ -261,7 +249,6 @@
      *             if parsing problems are detected.
      * @throws UnsupportedOperationException
      *             if the provider does not implement this method.
-     * @since Android 1.0
      */
     public final CertPath generateCertPath(InputStream inStream, String encoding)
             throws CertificateException {
@@ -280,7 +267,6 @@
      *             if parsing problems are detected.
      * @throws UnsupportedOperationException
      *             if the provider does not implement this method.
-     * @since Android 1.0
      */
     public final CertPath generateCertPath(List<? extends Certificate> certificates)
             throws CertificateException {
@@ -297,7 +283,6 @@
      * @return an initialized collection of certificates.
      * @throws CertificateException
      *             if parsing problems are detected.
-     * @since Android 1.0
      */
     public final Collection<? extends Certificate> generateCertificates(InputStream inStream)
             throws CertificateException {
@@ -313,7 +298,6 @@
      * @return an initialized CRL.
      * @exception CRLException
      *                if parsing problems are detected.
-     * @since Android 1.0
      */
     public final CRL generateCRL(InputStream inStream) throws CRLException {
         return spiImpl.engineGenerateCRL(inStream);
@@ -328,7 +312,6 @@
      * @return an initialized collection of CRLs.
      * @exception CRLException
      *                if parsing problems are detected.
-     * @since Android 1.0
      */
     public final Collection<? extends CRL> generateCRLs(InputStream inStream)
             throws CRLException {
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateFactorySpi.java b/libcore/security/src/main/java/java/security/cert/CertificateFactorySpi.java
index ed6ffed..d9f2044 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateFactorySpi.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateFactorySpi.java
@@ -28,16 +28,12 @@
  * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for the
  * {@code CertificateFactory} class. This SPI must be implemented for each
  * certificate type a security provider wishes to support.
- * 
- * @since Android 1.0
  */
 
 public abstract class CertificateFactorySpi {
 
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public CertificateFactorySpi() {
     }
@@ -52,7 +48,6 @@
      * @return an initialized certificate.
      * @exception CertificateException
      *                if parsing problems are detected.
-     * @since Android 1.0
      */
     public abstract Certificate engineGenerateCertificate(InputStream inStream)
             throws CertificateException;
@@ -66,7 +61,6 @@
      * @return a collection of certificates.
      * @exception CertificateException
      *                if parsing problems are detected.
-     * @since Android 1.0
      */
     public abstract Collection<? extends Certificate> 
         engineGenerateCertificates(InputStream inStream) throws CertificateException;
@@ -80,7 +74,6 @@
      * @return an CRL instance.
      * @exception CRLException
      *                if parsing problems are detected.
-     * @since Android 1.0
      */
     public abstract CRL engineGenerateCRL(InputStream inStream)
             throws CRLException;
@@ -94,7 +87,6 @@
      * @return a collection of CRLs.
      * @exception CRLException
      *                if parsing problems are detected.
-     * @since Android 1.0
      */
     public abstract Collection<? extends CRL> 
         engineGenerateCRLs(InputStream inStream) throws CRLException;
@@ -108,7 +100,6 @@
      * @return a {@code CertPath} initialized from the provided data.
      * @throws CertificateException
      *             if parsing problems are detected.
-     * @since Android 1.0
      */
     public CertPath engineGenerateCertPath(InputStream inStream)
             throws CertificateException {
@@ -130,7 +121,6 @@
      *             if parsing problems are detected.
      * @throws UnsupportedOperationException
      *             if the provider does not implement this method.
-     * @since Android 1.0
      */
     public CertPath engineGenerateCertPath(InputStream inStream, String encoding)
             throws CertificateException {
@@ -150,7 +140,6 @@
      *             if parsing problems are detected.
      * @throws UnsupportedOperationException
      *             if the provider does not implement this method.
-     * @since Android 1.0
      */
     public CertPath engineGenerateCertPath(List<? extends Certificate>  certificates) 
             throws CertificateException {
@@ -164,7 +153,6 @@
      * 
      * @return an iterator over supported {@code CertPath} encodings (as
      *         Strings).
-     * @since Android 1.0
      */
     public Iterator<String> engineGetCertPathEncodings() {
         throw new UnsupportedOperationException(
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateNotYetValidException.java b/libcore/security/src/main/java/java/security/cert/CertificateNotYetValidException.java
index 221b22a..dd26bf8 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateNotYetValidException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateNotYetValidException.java
@@ -20,8 +20,6 @@
 /**
  * The exception that is thrown when a {@code Certificate} is not yet valid or
  * will not yet be valid on a specified date.
- * 
- * @since Android 1.0
  */
 public class CertificateNotYetValidException extends CertificateException {
 
@@ -33,7 +31,6 @@
      * 
      * @param msg
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public CertificateNotYetValidException(String msg) {
         super(msg);
@@ -41,8 +38,6 @@
 
     /**
      * Creates a new {@code CertificateNotYetValidException}.
-     * 
-     * @since Android 1.0
      */
     public CertificateNotYetValidException() {
     }
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateParsingException.java b/libcore/security/src/main/java/java/security/cert/CertificateParsingException.java
index 2c75d20..4efd159 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateParsingException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateParsingException.java
@@ -19,8 +19,6 @@
 
 /**
  * The exception that is thrown when a {@code Certificate} can not be parsed.
- * 
- * @since Android 1.0
  */
 public class CertificateParsingException extends CertificateException {
 
@@ -29,10 +27,9 @@
     /**
      * Creates a new {@code CertificateParsingException} with the specified
      * message.
-     * 
+     *
      * @param msg
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public CertificateParsingException(String msg) {
         super(msg);
@@ -40,8 +37,6 @@
 
     /**
      * Creates a new {@code CertificateParsingException}.
-     * 
-     * @since Android 1.0
      */
     public CertificateParsingException() {
     }
@@ -49,12 +44,11 @@
     /**
      * Creates a new {@code CertificateParsingException} with the specified
      * message and cause.
-     * 
+     *
      * @param message
      *            the detail message for the exception.
      * @param cause
      *            the exception's source.
-     * @since Android 1.0
      */
     public CertificateParsingException(String message, Throwable cause) {
         super(message, cause);
@@ -63,10 +57,9 @@
     /**
      * Creates a new {@code CertificateParsingException} with the specified
      * cause.
-     * 
+     *
      * @param cause
      *            the exception's source.
-     * @since Android 1.0
      */
     public CertificateParsingException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java b/libcore/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java
index 23d8884..3c2fe1c 100644
--- a/libcore/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java
@@ -24,13 +24,9 @@
  * The parameters to initialize a <i>Collection</i> type {@code CertStore} instance.
  * <p>
  * It is used to specify the {@code Collection} where the {@code CertStore} will
- * retrieve the certificates and CRLs from. 
- * </p>
- * 
- * @since Android 1.0
+ * retrieve the certificates and CRLs from.
  */
 public class CollectionCertStoreParameters implements CertStoreParameters {
-    // BEGIN android-changed
     // Default empty and immutable collection.
     // Used if <code>CollectionCertStoreParameters</code>instance
     // created by the no arg constructor
@@ -38,14 +34,11 @@
     // A <code>Collection</code> of <code>Certificate</code>s
     // and <code>CRL</code>s
     private final Collection<?> collection;
-    // END android-changed
 
     /**
      * Creates a new {@code CollectionCertStoreParameters} without a collection.
      * <p>
      * The default collection is an empty and unmodifiable {@code Collection}.
-     * </p>
-     * @since Android 1.0
      */
     public CollectionCertStoreParameters() {
         this.collection = defaultCollection;
@@ -57,14 +50,12 @@
      * <p>
      * The specified collection is not copied and therefore may be modified at
      * any time.
-     * </p>
-     * 
+     *
      * @param collection
      *            the collection where the {@code Certificate}s and {@code CRL}s
      *            will be retrieved from.
      * @throws NullPointerException
      *             if {@code collection is null}.
-     * @since Android 1.0
      */
     public CollectionCertStoreParameters(Collection<?> collection) {
         this.collection = collection;
@@ -76,21 +67,23 @@
     /**
      * Clones this {@code CollectionCertStoreParameters} instance, but not the
      * underlying collection.
-     * 
+     *
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone() {
-        return new CollectionCertStoreParameters(collection);
+        try {
+			return super.clone();
+		} catch (CloneNotSupportedException e) {
+			return null;
+		}
     }
 
     /**
      * Returns the collection where the {@code Certificate}s and {@code CRL}s
      * are retrieved from.
-     * 
+     *
      * @return the collection where the {@code Certificate}s and {@code CRL}s
      *         will be retrieved from.
-     * @since Android 1.0
      */
     public Collection<?> getCollection() {
         return collection;
@@ -98,13 +91,12 @@
 
     /**
      * Returns the string representation of this instance.
-     * 
+     *
      * @return the string representation of this instance.
-     * @since Android 1.0
      */
     public String toString() {
-        StringBuffer sb =
-            new StringBuffer("CollectionCertStoreParameters: [\ncollection: "); //$NON-NLS-1$
+        StringBuilder sb =
+            new StringBuilder("CollectionCertStoreParameters: [\ncollection: "); //$NON-NLS-1$
         sb.append(getCollection().toString());
         sb.append("\n]"); //$NON-NLS-1$
         return sb.toString();
diff --git a/libcore/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java b/libcore/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java
index 9145848..1d6542f 100644
--- a/libcore/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java
@@ -19,8 +19,6 @@
 
 /**
  * The parameters to initialize a LDAP {@code CertStore} instance.
- * 
- * @since Android 1.0
  */
 public class LDAPCertStoreParameters implements CertStoreParameters {
     // Default LDAP server name
@@ -36,14 +34,13 @@
     /**
      * Creates a new {@code LDAPCertStoreParameters} instance with the specified
      * server name and port.
-     * 
+     *
      * @param serverName
      *            the LDAP server name.
      * @param port
      *            the port.
      * @throws NullPointerException
      *             is {@code serverName} is {@code null}.
-     * @since Android 1.0
      */
     public LDAPCertStoreParameters(String serverName, int port) {
         this.port = port;
@@ -58,9 +55,6 @@
      * parameters.
      * <p>
      * The default parameters are server name "localhost" and port 389.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     public LDAPCertStoreParameters() {
         this.serverName = DEFAULT_LDAP_SERVER_NAME;
@@ -70,12 +64,11 @@
     /**
      * Creates a new {@code LDAPCertStoreParameters} instance with the specified
      * server name and default port 389.
-     * 
+     *
      * @param serverName
      *            the LDAP server name.
      * @throws NullPointerException
      *             if {@code serverName} is {@code null}.
-     * @since Android 1.0
      */
     public LDAPCertStoreParameters(String serverName) {
         this.port = DEFAULT_LDAP_PORT;
@@ -87,19 +80,21 @@
 
     /**
      * Clones this {@code LDAPCertStoreParameters} instance.
-     * 
+     *
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone() {
-        return new LDAPCertStoreParameters(serverName, port);
+    	try {
+			return super.clone();
+		} catch (CloneNotSupportedException e) {
+			return null;
+		}
     }
 
     /**
      * Returns the LDAP server port.
-     * 
+     *
      * @return the LDAP server port.
-     * @since Android 1.0
      */
     public int getPort() {
         return port;
@@ -107,9 +102,8 @@
 
     /**
      * Returns the LDAP server name.
-     * 
+     *
      * @return the LDAP server name.
-     * @since Android 1.0
      */
     public String getServerName() {
         return serverName;
@@ -118,14 +112,13 @@
     /**
      * Returns the string representation of this {@code LDAPCertStoreParameters}
      * instance.
-     * 
+     *
      * @return the string representation of this {@code LDAPCertStoreParameters}
      *         instance.
-     * @since Android 1.0
      */
     public String toString() {
-        StringBuffer sb =
-            new StringBuffer("LDAPCertStoreParameters: [\n serverName: "); //$NON-NLS-1$
+        StringBuilder sb =
+            new StringBuilder("LDAPCertStoreParameters: [\n serverName: "); //$NON-NLS-1$
         sb.append(getServerName());
         sb.append("\n port: "); //$NON-NLS-1$
         sb.append(getPort());
diff --git a/libcore/security/src/main/java/java/security/cert/PKIXBuilderParameters.java b/libcore/security/src/main/java/java/security/cert/PKIXBuilderParameters.java
index a047a80..1a75063 100644
--- a/libcore/security/src/main/java/java/security/cert/PKIXBuilderParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/PKIXBuilderParameters.java
@@ -32,11 +32,9 @@
  * <p>
  * The parameters must be created with <i>trusted</i> certificate authorities
  * and constraints for the target certificates.
- * </p>
- * 
+ *
  * @see CertPathBuilder
  * @see CertPathParameters
- * @since Android 1.0
  */
 public class PKIXBuilderParameters extends PKIXParameters {
     // Maximum certificate path length (5 by default)
@@ -55,7 +53,6 @@
      * @throws ClassCastException
      *             if one of the items in {@code trustAnchors} is not an
      *             instance of {@code java.security.cert.TrustAnchor}.
-     * @since Android 1.0
      */
     public PKIXBuilderParameters(Set<TrustAnchor> trustAnchors,
             CertSelector targetConstraints)
@@ -77,7 +74,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if {@code keyStore} does not contained any trusted
      *             certificate entry.
-     * @since Android 1.0
      */
     public PKIXBuilderParameters(KeyStore keyStore,
             CertSelector targetConstraints)
@@ -92,11 +88,9 @@
      * <p>
      * This is the maximum number of non-self-signed certificates in a
      * certification path.
-     * </p>
-     * 
+     *
      * @return the maximum length of a certification path, or {@code -1} if it
      *         is unlimited.
-     * @since Android 1.0
      */
     public int getMaxPathLength() {
         return maxPathLength;
@@ -107,13 +101,11 @@
      * <p>
      * This is the maximum number of non-self-signed certificates in a
      * certification path.
-     * </p>
      * 
      * @param maxPathLength
      *            the maximum length of a certification path.
      * @throws InvalidParameterException
      *             if {@code maxPathLength} is less than {@code -1}.
-     * @since Android 1.0
      */
     public void setMaxPathLength(int maxPathLength) {
         if (maxPathLength < -1) {
@@ -129,10 +121,9 @@
      * 
      * @return a string representation of this {@code PKIXBuilderParameters}
      *         instance.
-     * @since Android 1.0
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer("[\n"); //$NON-NLS-1$
+        StringBuilder sb = new StringBuilder("[\n"); //$NON-NLS-1$
         sb.append(super.toString());
         sb.append(" Max Path Length: "); //$NON-NLS-1$
         sb.append(maxPathLength);
diff --git a/libcore/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java b/libcore/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
index 6064194..5a9fb2d 100644
--- a/libcore/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
+++ b/libcore/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
@@ -25,8 +25,6 @@
 /**
  * The result of the PKIX certification path builder, returned by
  * {@link CertPathBuilder#build(CertPathParameters)}.
- * 
- * @since Android 1.0
  */
 public class PKIXCertPathBuilderResult extends PKIXCertPathValidatorResult
         implements CertPathBuilderResult {
@@ -49,7 +47,6 @@
      * @throws NullPointerException
      *             if the {@code cerPath}, {@code trustAnchor} or {@code
      *             subjectPolicyKey} is {@code null}.
-     * @since Android 1.0
      */
     public PKIXCertPathBuilderResult(CertPath certPath, TrustAnchor trustAnchor,
             PolicyNode policyTree, PublicKey subjectPublicKey) {
@@ -64,7 +61,6 @@
      * Returns the validated certification path.
      * 
      * @return the validated certification path.
-     * @since Android 1.0
      */
     public CertPath getCertPath() {
         return certPath;
@@ -76,10 +72,9 @@
      * 
      * @return a string representation of this {@code PKIXCertPathBuilderResult}
      *         instance.
-     * @since Android 1.0
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer(super.toString());
+        StringBuilder sb = new StringBuilder(super.toString());
         sb.append("\n Certification Path: "); //$NON-NLS-1$
         sb.append(certPath.toString());
         sb.append("\n]"); //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/cert/PKIXCertPathChecker.java b/libcore/security/src/main/java/java/security/cert/PKIXCertPathChecker.java
index 5614878..710ac11 100644
--- a/libcore/security/src/main/java/java/security/cert/PKIXCertPathChecker.java
+++ b/libcore/security/src/main/java/java/security/cert/PKIXCertPathChecker.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Vladimir N. Molotkov
-* @version $Revision$
-*/
-
 package java.security.cert;
 
 import java.util.Collection;
@@ -38,22 +33,16 @@
  * {@link #check(Certificate, Collection) check} method will be called for each
  * certificate processed by a {@code CertPathBuilder} of {@code
  * CertPathValidator}.
- * </p>
  * <p>
  * A {@code PKIXCertPathChecker} implementation <u>must</u> support reverse
  * checking (from trusted CA to target) and <u>may</u> support forward checking
  * (from target to trusted CA). The return value of {@code
  * isForwardCheckingSupported} indicates whether forward checking is supported.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class PKIXCertPathChecker implements Cloneable {
 
     /**
      * Creates a new {@code PKIXCertPathChecker} instance.
-     * 
-     * @since Android 1.0
      */
     protected PKIXCertPathChecker() {}
 
@@ -61,7 +50,6 @@
      * Clones this {@code PKIXCertPathChecker} instance.
      * 
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone() {
         try {
@@ -84,7 +72,6 @@
      *             if initialization of this {@code PKIXCertPathChecker}
      *             instance fails, or if it cannot process certificates in the
      *             specified order.
-     * @since Android 1.0
      */
     public abstract void init(boolean forward)
         throws CertPathValidatorException;
@@ -95,7 +82,6 @@
      * 
      * @return {@code true} if this {@code PKIXCertPathChecker} instance
      *         supports forward checking, otherwise {@code false}.
-     * @since Android 1.0
      */
     public abstract boolean isForwardCheckingSupported();
 
@@ -106,7 +92,6 @@
      * @return the list of extensions of X.509 certificates that this {@code
      *         PKIXCertPathChecker} is able to process, or {@code null} if there
      *         are none.
-     * @since Android 1.0
      */
     public abstract Set<String> getSupportedExtensions();
 
@@ -120,7 +105,6 @@
      *            the list of critical X.509 extension OID strings.
      * @throws CertPathValidatorException
      *             if check(s) fail on the specified certificate.
-     * @since Android 1.0
      */
     public abstract void check(Certificate cert, Collection<String> unresolvedCritExts)
         throws CertPathValidatorException;
diff --git a/libcore/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java b/libcore/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
index 21f90c9..7d80ae5 100644
--- a/libcore/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
+++ b/libcore/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
@@ -26,7 +26,6 @@
  * 
  * @see CertPathValidator
  * @see CertPathValidator#validate(CertPath, CertPathParameters)
- * @since Android 1.0
  */
 public class PKIXCertPathValidatorResult implements CertPathValidatorResult {
     // A trust anchor used during validation of certification path
@@ -48,7 +47,6 @@
      *            the valid policy tree from the validation.
      * @param subjectPublicKey
      *            the subject public key from the validation.
-     * @since Android 1.0
      */
     public PKIXCertPathValidatorResult(TrustAnchor trustAnchor,
             PolicyNode policyTree, PublicKey subjectPublicKey) {
@@ -68,7 +66,6 @@
      * Returns the valid policy tree from the validation.
      * 
      * @return the valid policy tree from the validation.
-     * @since Android 1.0
      */
     public PolicyNode getPolicyTree() {
         return policyTree;
@@ -78,7 +75,6 @@
      * Returns the subject public key from the validation.
      * 
      * @return the subject public key from the validation.
-     * @since Android 1.0
      */
     public PublicKey getPublicKey() {
         return subjectPublicKey;
@@ -89,7 +85,6 @@
      * served as trust anchor for this certification path.
      * 
      * @return the trust anchor.
-     * @since Android 1.0
      */
     public TrustAnchor getTrustAnchor() {
         return trustAnchor;
@@ -99,7 +94,6 @@
      * Clones this {@code PKIXCertPathValidatorResult} instance.
      * 
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone() {
         try {
@@ -116,10 +110,9 @@
      * 
      * @return a string representation for this {@code
      *         PKIXCertPathValidatorResult} instance.
-     * @since Android 1.0
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer(super.toString());
+        StringBuilder sb = new StringBuilder(super.toString());
         sb.append(": [\n Trust Anchor: "); //$NON-NLS-1$
         sb.append(trustAnchor.toString());
         sb.append("\n Policy Tree: "); //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/cert/PKIXParameters.java b/libcore/security/src/main/java/java/security/cert/PKIXParameters.java
index 16b0686..4034d21 100644
--- a/libcore/security/src/main/java/java/security/cert/PKIXParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/PKIXParameters.java
@@ -36,11 +36,9 @@
  * <p>
  * The parameters must be created with <i>trusted</i> certificate authorities
  * (trust anchors).
- * </p>
- * 
+ *
  * @see CertPathValidator
  * @see CertPathParameters
- * @since Android 1.0
  */
 public class PKIXParameters implements CertPathParameters {
     // Set of trust anchors - most trusted CAs
@@ -79,7 +77,6 @@
      *            the trusted CAs.
      * @throws InvalidAlgorithmParameterException
      *             if {@code trustAnchors} is empty.
-     * @since Android 1.0
      */
     public PKIXParameters(Set<TrustAnchor> trustAnchors)
         throws InvalidAlgorithmParameterException {
@@ -101,7 +98,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if {@code keyStore} does not contained any trusted
      *             certificate entry.
-     * @since Android 1.0
      */
     public PKIXParameters(KeyStore keyStore)
         throws KeyStoreException,
@@ -137,7 +133,6 @@
      * Returns a unmodifiable set of the <i>trusted</i> certificate authorities.
      * 
      * @return a unmodifiable set of the <i>trusted</i> certificate authorities.
-     * @since Android 1.0
      */
     public Set<TrustAnchor> getTrustAnchors() {
         return Collections.unmodifiableSet(trustAnchors);
@@ -150,7 +145,6 @@
      *            the set of <i>trusted</i> certificate authorities.
      * @throws InvalidAlgorithmParameterException
      *             if {@code trustAnchors} is empty.
-     * @since Android 1.0
      */
     public void setTrustAnchors(Set<TrustAnchor> trustAnchors)
         throws InvalidAlgorithmParameterException {
@@ -169,7 +163,6 @@
      * 
      * @return {@code true} if the <i>any policy OID</i> will be inhibited,
      *         otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean isAnyPolicyInhibited() {
         return anyPolicyInhibited;
@@ -182,7 +175,6 @@
      * @param anyPolicyInhibited
      *            {@code true} if the <i>any policy OID</i> should be inhibited,
      *            otherwise {@code false}.
-     * @since Android 1.0
      */
     public void setAnyPolicyInhibited(boolean anyPolicyInhibited) {
         this.anyPolicyInhibited = anyPolicyInhibited;
@@ -192,10 +184,8 @@
      * Returns the list of checkers for the certification path.
      * <p>
      * The list is unmodifiable and the entries in the list are cloned.
-     * </p>
-     * 
+     *
      * @return the list of checkers for the certification path.
-     * @since Android 1.0
      */
     public List<PKIXCertPathChecker> getCertPathCheckers() {
         if (certPathCheckers == null) {
@@ -222,12 +212,10 @@
      * Sets the list of checkers for the certification path.
      * <p>
      * The list is copied and the entries are cloned.
-     * </p>
      * 
      * @param certPathCheckers
      *            the list of checkers for the certification path, or {@code
      *            null} to clear the checkers.
-     * @since Android 1.0
      */
     public void setCertPathCheckers(List<PKIXCertPathChecker> certPathCheckers) {
         if (certPathCheckers == null || certPathCheckers.isEmpty()) {
@@ -254,7 +242,6 @@
      * @param checker
      *            the {@code PKIXCertPathChecker} to add, if {@code null}, it
      *            will be ignored.
-     * @since Android 1.0
      */
     public void addCertPathChecker(PKIXCertPathChecker checker) {
         if (checker == null) {
@@ -274,7 +261,6 @@
      * and CRLs.
      * 
      * @return an immutable list of certificate stores.
-     * @since Android 1.0
      */
     public List<CertStore> getCertStores() {
         if (certStores == null) {
@@ -298,7 +284,6 @@
      * CRLs.
      * 
      * @param certStores the list of certificate stores.
-     * @since Android 1.0
      */
     public void setCertStores(List<CertStore> certStores) {
         if (certStores == null || certStores.isEmpty()) {
@@ -325,7 +310,6 @@
      * 
      * @param store
      *            the store to add, if {@code null}, it will be ignored.
-     * @since Android 1.0
      */
     public void addCertStore(CertStore store) {
         if (store == null) {
@@ -346,7 +330,6 @@
      * 
      * @return the time for the validation, or {@code null} for the current
      *         time.
-     * @since Android 1.0
      */
     public Date getDate() {
         return date == null ? null : (Date)date.clone();
@@ -359,7 +342,6 @@
      * @param date
      *            the time for the validation, or {@code null} for the current
      *            time.
-     * @since Android 1.0
      */
     public void setDate(Date date) {
         this.date = (date == null ? null : new Date(date.getTime()));
@@ -371,7 +353,6 @@
      * 
      * @return {@code true} if an explicit policy is required, otherwise {@code
      *         false}.
-     * @since Android 1.0
      */
     public boolean isExplicitPolicyRequired() {
         return explicitPolicyRequired;
@@ -384,7 +365,6 @@
      * @param explicitPolicyRequired
      *            {@code true} if an explicit policy is required, otherwise
      *            {@code false}.
-     * @since Android 1.0
      */
     public void setExplicitPolicyRequired(boolean explicitPolicyRequired) {
         this.explicitPolicyRequired = explicitPolicyRequired;
@@ -396,7 +376,6 @@
      * 
      * @return the unmodifiable list of policies, or an empty set if any policy
      *         is acceptable.
-     * @since Android 1.0
      */
     public Set<String> getInitialPolicies() {
         if (initialPolicies == null) {
@@ -421,7 +400,6 @@
      * @param initialPolicies
      *            the list of policies, or an empty set or {@code null} if any
      *            policy is acceptable.
-     * @since Android 1.0
      */
     public void setInitialPolicies(Set<String> initialPolicies) {
         if (initialPolicies == null || initialPolicies.isEmpty()) {
@@ -448,7 +426,6 @@
      * 
      * @return {@code true} if policy mapping is inhibited, otherwise {@code
      *         false}.
-     * @since Android 1.0
      */
     public boolean isPolicyMappingInhibited() {
         return policyMappingInhibited;
@@ -460,7 +437,6 @@
      * @param policyMappingInhibited
      *            {@code true} if policy mapping is to be inhibited, otherwise
      *            {@code false}.
-     * @since Android 1.0
      */
     public void setPolicyMappingInhibited(boolean policyMappingInhibited) {
         this.policyMappingInhibited = policyMappingInhibited;
@@ -472,7 +448,6 @@
      * 
      * @return {@code true} if the certificates should be rejected, otherwise
      *         {@code false}.
-     * @since Android 1.0
      */
     public boolean getPolicyQualifiersRejected() {
         return policyQualifiersRejected;
@@ -485,7 +460,6 @@
      * @param policyQualifiersRejected
      *            {@code true} if the certificates should be rejected, otherwise
      *            {@code false}.
-     * @since Android 1.0
      */
     public void setPolicyQualifiersRejected(boolean policyQualifiersRejected) {
         this.policyQualifiersRejected = policyQualifiersRejected;
@@ -497,7 +471,6 @@
      * 
      * @return {@code true} if the default revocation checking mechanism is
      *         used, otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean isRevocationEnabled() {
         return revocationEnabled;
@@ -510,7 +483,6 @@
      * @param revocationEnabled
      *            {@code true} id the default revocation checking mechanism
      *            should be used, otherwise {@code false}.
-     * @since Android 1.0
      */
     public void setRevocationEnabled(boolean revocationEnabled) {
         this.revocationEnabled = revocationEnabled;
@@ -521,7 +493,6 @@
      * 
      * @return the name of the signature provider, or {@code null} if none is
      *         set.
-     * @since Android 1.0
      */
     public String getSigProvider() {
         return sigProvider;
@@ -537,7 +508,6 @@
      * @param sigProvider
      *            the name of the preferred signature provider, or {@code null}
      *            if none is preferred.
-     * @since Android 1.0
      */
     public void setSigProvider(String sigProvider) {
         this.sigProvider = sigProvider;
@@ -548,7 +518,6 @@
      * 
      * @return the constraints for the target certificate, or {@code null} if
      *         none are set.
-     * @since Android 1.0
      */
     public CertSelector getTargetCertConstraints() {
         return (targetCertConstraints == null ? null
@@ -561,7 +530,6 @@
      * @param targetCertConstraints
      *            the constraints for the target certificate, or {@code null} if
      *            none should be used.
-     * @since Android 1.0
      */
     public void setTargetCertConstraints(CertSelector targetCertConstraints) {
         this.targetCertConstraints = (targetCertConstraints == null ? null
@@ -572,7 +540,6 @@
      * Clones this {@code PKIXParameters} instance.
      * 
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone() {
         try {
@@ -595,11 +562,10 @@
      * Returns a string representation of this {@code PKIXParameters} instance.
      * 
      * @return a string representation of this {@code PKIXParameters} instance.
-     * @since Android 1.0
      */
     public String toString() {
-        StringBuffer sb =
-            new StringBuffer("[\n Trust Anchors: "); //$NON-NLS-1$
+        StringBuilder sb =
+            new StringBuilder("[\n Trust Anchors: "); //$NON-NLS-1$
         sb.append(trustAnchors);
         sb.append("\n Revocation Enabled: "); //$NON-NLS-1$
         sb.append(revocationEnabled);
diff --git a/libcore/security/src/main/java/java/security/cert/PolicyNode.java b/libcore/security/src/main/java/java/security/cert/PolicyNode.java
index c112a8a..c485b69 100644
--- a/libcore/security/src/main/java/java/security/cert/PolicyNode.java
+++ b/libcore/security/src/main/java/java/security/cert/PolicyNode.java
@@ -26,9 +26,6 @@
  * <p>
  * Instances of this class are one of the outputs of the PKIX certification path
  * validation algorithm.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface PolicyNode {
 
@@ -36,7 +33,6 @@
      * Returns the list of children of this node as an {@code Iterator}.
      * 
      * @return the list of children of this node as an {@code Iterator}.
-     * @since Android 1.0
      */
     public Iterator<? extends PolicyNode> getChildren();
 
@@ -44,10 +40,8 @@
      * Returns the depth of this node in the policy tree.
      * <p>
      * the depth is zero based.
-     * </p>
      * 
      * @return the depth of this node in the policy tree.
-     * @since Android 1.0
      */
     public int getDepth();
 
@@ -55,7 +49,6 @@
      * Returns the expected policies for the next certificate to be valid.
      * 
      * @return the expected policies.
-     * @since Android 1.0
      */
     public Set<String> getExpectedPolicies();
 
@@ -63,7 +56,6 @@
      * Returns the parent policy node.
      * 
      * @return the parent policy node.
-     * @since Android 1.0
      */
     public PolicyNode getParent();
 
@@ -71,7 +63,6 @@
      * Returns the policy qualifiers associated with the policy of this node.
      * 
      * @return the policy qualifiers associated with the policy of this node.
-     * @since Android 1.0
      */
     public Set<? extends PolicyQualifierInfo> getPolicyQualifiers();
 
@@ -79,7 +70,6 @@
      * Returns the valid policy of this node.
      * 
      * @return the valid policy of this node.
-     * @since Android 1.0
      */
     public String getValidPolicy();
 
@@ -89,7 +79,6 @@
      * 
      * @return {@code true} if the extension is marked as critical, otherwise
      *         {@code false}.
-     * @since Android 1.0
      */
     public boolean isCritical();
 }
diff --git a/libcore/security/src/main/java/java/security/cert/PolicyQualifierInfo.java b/libcore/security/src/main/java/java/security/cert/PolicyQualifierInfo.java
index 5a63d51..903a6e9 100644
--- a/libcore/security/src/main/java/java/security/cert/PolicyQualifierInfo.java
+++ b/libcore/security/src/main/java/java/security/cert/PolicyQualifierInfo.java
@@ -27,8 +27,6 @@
 /**
  * This class implements a policy qualifier as defined by the ASN.1
  * {@code PolicyQualifierInfo} structure.
- * 
- * @since Android 1.0
  */
 public class PolicyQualifierInfo {
     // This PolicyQualifierInfo DER encoding
@@ -48,7 +46,6 @@
      *            the DER encoded policy qualifier.
      * @throws IOException
      *             the policy qualifier cannot be decoded.
-     * @since Android 1.0
      */
     public PolicyQualifierInfo(byte[] encoded) throws IOException {
         if (encoded == null) {
@@ -71,7 +68,6 @@
      * Returns a ASN.1 DER encoded copy of policy qualifier info.
      * 
      * @return a ASN.1 DER encoded copy of policy qualifier info.
-     * @since Android 1.0
      */
     public final byte[] getEncoded() {
         byte[] ret = new byte[encoded.length];
@@ -83,7 +79,6 @@
      * Returns the identifier (an OID) of this policy qualifier info.
      * 
      * @return the identifier of this policy qualifier info.
-     * @since Android 1.0
      */
     public final String getPolicyQualifierId() {
         return policyQualifierId;
@@ -95,7 +90,6 @@
      * 
      * @return a ASN.1 DER encoded copy of the qualifier of this policy
      *         qualifier info.
-     * @since Android 1.0
      */
     public final byte[] getPolicyQualifier() {
         if (policyQualifier == null) {
@@ -112,11 +106,10 @@
      * 
      * @return a string representation of this {@code PolicyQualifierInfo}
      *         instance.
-     * @since Android 1.0
      */
     public String toString() {
-        StringBuffer sb =
-            new StringBuffer("PolicyQualifierInfo: [\npolicyQualifierId: "); //$NON-NLS-1$
+        StringBuilder sb =
+            new StringBuilder("PolicyQualifierInfo: [\npolicyQualifierId: "); //$NON-NLS-1$
         sb.append(policyQualifierId);
         sb.append("\npolicyQualifier: \n"); //$NON-NLS-1$
         sb.append(Array.toString(policyQualifier, " ")); //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/cert/TrustAnchor.java b/libcore/security/src/main/java/java/security/cert/TrustAnchor.java
index 9dc2025..eae38d6 100644
--- a/libcore/security/src/main/java/java/security/cert/TrustAnchor.java
+++ b/libcore/security/src/main/java/java/security/cert/TrustAnchor.java
@@ -36,9 +36,6 @@
  * of the CA, the CA's name and the constraints for the validation of
  * certification paths. The constructor also allows to specify a binary
  * representation of a so called "Name Constraints" extension as a byte array.
- * </p>
- * 
- * @since Android 1.0
  */
 public class TrustAnchor {
     // Most trusted CA as a X500Principal
@@ -58,8 +55,7 @@
      * <p>
      * The name constraints will be used as additional constraints during the
      * validation of certification paths.
-     * </p>
-     * 
+     *
      * @param trustedCert
      *            the trusted certificate
      * @param nameConstraints
@@ -67,7 +63,6 @@
      *            null} if none.
      * @throws IllegalArgumentException
      *             if the decoding of the name constraints fail.
-     * @since Android 1.0
      */
     public TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) {
         if (trustedCert == null) {
@@ -94,8 +89,7 @@
      * <p>
      * The name constraints will be used as additional constraints during the
      * validation of certification paths.
-     * </p>
-     * 
+     *
      * @param caName
      *            the X.500 name of the certificate authority in RFC 2253
      *            {@code String} format.
@@ -107,7 +101,6 @@
      * @throws IllegalArgumentException
      *             if the {@code caName} is empty or if decoding of the name
      *             constraints fail.
-     * @since Android 1.0
      */
     public TrustAnchor(String caName, PublicKey caPublicKey,
             byte[] nameConstraints) {
@@ -146,7 +139,6 @@
      * <p>
      * The name constraints will be used as additional constraints during the
      * validation of certification paths.
-     * </p>
      * 
      * @param caPrincipal
      *            the name of the certificate authority as X500 principal.
@@ -157,7 +149,6 @@
      *            null} if none.
      * @throws IllegalArgumentException
      *             if decoding of the name constraints fail.
-     * @since Android 1.0
      */
     public TrustAnchor(X500Principal caPrincipal,
             PublicKey caPublicKey, byte[] nameConstraints) {
@@ -187,7 +178,6 @@
      * Returns a copy of the name constraints in ASN.1 DER encoded form.
      * 
      * @return a copy of the name constraints in ASN.1 DER encoded form.
-     * @since Android 1.0
      */
     public final byte[] getNameConstraints() {
         if (nameConstraints == null) {
@@ -204,7 +194,6 @@
      * 
      * @return the certificate of this CA or {@code null}, if the trust anchor
      *         of this instance was not created with a certificate.
-     * @since Android 1.0
      */
     public final X509Certificate getTrustedCert() {
         return trustedCert;
@@ -216,7 +205,6 @@
      * @return the name of the certificate authority or {@code null} if the
      *         trust anchor of this instance was not created with a {@code
      *         X500Principal}.
-     * @since Android 1.0
      */
     public final X500Principal getCA() {
         return caPrincipal;
@@ -229,7 +217,6 @@
      * @return the name of the certificate authority as {@code String} in RFC
      *         2253 format or {@code null} if the trust anchor of this instance
      *         was not created with a CA name.
-     * @since Android 1.0
      */
     public final String getCAName() {
         return caName;
@@ -241,7 +228,6 @@
      * @return the public key of the certificate authority or {@code null} if
      *         the trust anchor if this instance was not created with a public
      *         key.
-     * @since Android 1.0
      */
     public final PublicKey getCAPublicKey() {
         return caPublicKey;
@@ -251,10 +237,9 @@
      * Returns a string representation of this {@code TrustAnchor} instance.
      * 
      * @return a string representation of this {@code TrustAnchor} instance.
-     * @since Android 1.0
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer("TrustAnchor: [\n"); //$NON-NLS-1$
+        StringBuilder sb = new StringBuilder("TrustAnchor: [\n"); //$NON-NLS-1$
         if (trustedCert != null) {
             sb.append("Trusted CA certificate: "); //$NON-NLS-1$
             sb.append(trustedCert);
diff --git a/libcore/security/src/main/java/java/security/cert/X509CRL.java b/libcore/security/src/main/java/java/security/cert/X509CRL.java
index eabdb68..cb99843 100644
--- a/libcore/security/src/main/java/java/security/cert/X509CRL.java
+++ b/libcore/security/src/main/java/java/security/cert/X509CRL.java
@@ -44,16 +44,11 @@
  * href
  * ="http://www.ietf.org/rfc/rfc2459.txt">http://www.ietf.org/rfc/rfc2459.txt
  * </a>.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class X509CRL extends CRL implements X509Extension {
 
     /**
      * Creates a new {@code X509CRL} instance.
-     * 
-     * @since Android 1.0
      */
     protected X509CRL() {
         super("X.509"); //$NON-NLS-1$
@@ -66,7 +61,6 @@
      *            the object to compare.
      * @return {@code true} if the specified object is equal to this, otherwise
      *         {@code false}.
-     * @since Android 1.0
      */
     public boolean equals(Object other) {
         if (other == this) {
@@ -87,7 +81,6 @@
      * Returns the hashcode of this CRL instance.
      * 
      * @return the hashcode.
-     * @since Android 1.0
      */
     public int hashCode() {
         try {
@@ -108,7 +101,6 @@
      * @return this CRL in ASN.1 DER encoded form.
      * @throws CRLException
      *             if encoding fails.
-     * @since Android 1.0
      */
     public abstract byte[] getEncoded() throws CRLException;
 
@@ -129,7 +121,6 @@
      *             if no provider can be found.
      * @throws SignatureException
      *             if errors occur on signatures.
-     * @since Android 1.0
      */
     public abstract void verify(PublicKey key)
                      throws CRLException, NoSuchAlgorithmException,
@@ -155,7 +146,6 @@
      *             if the specified provider cannot be found.
      * @throws SignatureException
      *             if errors occur on signatures.
-     * @since Android 1.0
      */
     public abstract void verify(PublicKey key, String sigProvider)
                      throws CRLException, NoSuchAlgorithmException,
@@ -166,7 +156,6 @@
      * Returns the version number of this CRL.
      * 
      * @return the version number of this CRL.
-     * @since Android 1.0
      */
     public abstract int getVersion();
 
@@ -175,7 +164,6 @@
      * the issuer as an implementation specific Principal object.
      * 
      * @return the issuer distinguished name.
-     * @since Android 1.0
      */
     public abstract Principal getIssuerDN();
 
@@ -183,7 +171,6 @@
      * Returns the issuer distinguished name of this CRL.
      * 
      * @return the issuer distinguished name of this CRL.
-     * @since Android 1.0
      */
     public X500Principal getIssuerX500Principal() {
         try {
@@ -206,7 +193,6 @@
      * Returns the {@code thisUpdate} value of this CRL.
      * 
      * @return the {@code thisUpdate} value of this CRL.
-     * @since Android 1.0
      */
     public abstract Date getThisUpdate();
 
@@ -215,7 +201,6 @@
      * 
      * @return the {@code nextUpdate} value of this CRL, or {@code null} if none
      *         is present.
-     * @since Android 1.0
      */
     public abstract Date getNextUpdate();
 
@@ -226,7 +211,6 @@
      *            the certificate serial number to search for a CRL entry.
      * @return the entry for the specified certificate serial number, or {@code
      *         null} if not found.
-     * @since Android 1.0
      */
     public abstract X509CRLEntry getRevokedCertificate(BigInteger serialNumber);
 
@@ -237,7 +221,6 @@
      *            the certificate to search a CRL entry for.
      * @return the entry for the specified certificate, or {@code null} if not
      *         found.
-     * @since Android 1.0
      */
     public X509CRLEntry getRevokedCertificate(X509Certificate certificate) {
         if (certificate == null) {
@@ -251,7 +234,6 @@
      * 
      * @return the set of revoked certificates, or {@code null} if no revoked
      *         certificates are in this CRL.
-     * @since Android 1.0
      */
     public abstract Set<? extends X509CRLEntry> getRevokedCertificates();
 
@@ -262,7 +244,6 @@
      * @return the CRL information in DER encoded form.
      * @throws CRLException
      *             if encoding fails.
-     * @since Android 1.0
      */
     public abstract byte[] getTBSCertList() throws CRLException;
 
@@ -270,7 +251,6 @@
      * Returns the signature bytes of this CRL.
      * 
      * @return the signature bytes of this CRL.
-     * @since Android 1.0
      */
     public abstract byte[] getSignature();
 
@@ -278,7 +258,6 @@
      * Returns the name of the signature algorithm.
      * 
      * @return the name of the signature algorithm.
-     * @since Android 1.0
      */
     public abstract String getSigAlgName();
 
@@ -286,7 +265,6 @@
      * Returns the OID of the signature algorithm.
      * 
      * @return the OID of the signature algorithm.
-     * @since Android 1.0
      */
     public abstract String getSigAlgOID();
 
@@ -295,7 +273,6 @@
      * 
      * @return the parameters of the signature algorithm in DER encoded form, or
      *         {@code null} if not present.
-     * @since Android 1.0
      */
     public abstract byte[] getSigAlgParams();
 }
diff --git a/libcore/security/src/main/java/java/security/cert/X509CRLEntry.java b/libcore/security/src/main/java/java/security/cert/X509CRLEntry.java
index 35fb78b..ccdaf2f 100644
--- a/libcore/security/src/main/java/java/security/cert/X509CRLEntry.java
+++ b/libcore/security/src/main/java/java/security/cert/X509CRLEntry.java
@@ -29,14 +29,11 @@
  * Abstract base class for entries in a certificate revocation list (CRL).
  * 
  * @see X509CRL
- * @since Android 1.0
  */
 public abstract class X509CRLEntry implements X509Extension {
 
     /**
      * Creates a new {@code X509CRLEntry} instance.
-     * 
-     * @since Android 1.0
      */
     public X509CRLEntry() {}
 
@@ -47,7 +44,6 @@
      *            the object to compare.
      * @return {@code true} if the specified object equals to this instance,
      *         otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean equals(Object other) {
         if (other == this) {
@@ -68,7 +64,6 @@
      * Returns the hashcode of this instance.
      * 
      * @return the hashcode of this instance.
-     * @since Android 1.0
      */
     public int hashCode() {
         int res = 0;
@@ -88,7 +83,6 @@
      * @return the encoded form of this entry.
      * @throws CRLException
      *             if encoding fails.
-     * @since Android 1.0
      */
     public abstract byte[] getEncoded() throws CRLException;
 
@@ -96,7 +90,6 @@
      * Returns the serial number of the revoked certificate.
      * 
      * @return the serial number of the revoked certificate.
-     * @since Android 1.0
      */
     public abstract BigInteger getSerialNumber();
 
@@ -105,7 +98,6 @@
      * 
      * @return the issuer of the revoked certificate, or {@code null} if the
      *         issuer is equal to the CRL issuer.
-     * @since Android 1.0
      */
     public X500Principal getCertificateIssuer() {
         return null;
@@ -115,7 +107,6 @@
      * Returns the date when the certificate is revoked.
      * 
      * @return the date when the certificate is revoked.
-     * @since Android 1.0
      */
     public abstract Date getRevocationDate();
 
@@ -124,7 +115,6 @@
      * 
      * @return {@code true} is this CRL entry has extensions, otherwise {@code
      *         false}.
-     * @since Android 1.0
      */
     public abstract boolean hasExtensions();
 
@@ -132,7 +122,6 @@
      * Returns a string representation of this instance.
      * 
      * @return a string representation of this instance.
-     * @since Android 1.0
      */
     public abstract String toString();
 }
diff --git a/libcore/security/src/main/java/java/security/cert/X509CRLSelector.java b/libcore/security/src/main/java/java/security/cert/X509CRLSelector.java
index c1b5f45..0edddf4 100644
--- a/libcore/security/src/main/java/java/security/cert/X509CRLSelector.java
+++ b/libcore/security/src/main/java/java/security/cert/X509CRLSelector.java
@@ -36,10 +36,7 @@
  * X509CRL}s that match the specified criteria.
  * <p>
  * When constructed, all criteria are set to default values that will match any
- * {@code X509CRL}.  
- * </p>
- * 
- * @since Android 1.0
+ * {@code X509CRL}.
  */
 public class X509CRLSelector implements CRLSelector {
 
@@ -60,8 +57,6 @@
 
     /**
      * Creates a new {@code X509CertSelector}.
-     * 
-     * @since Android 1.0
      */
     public X509CRLSelector() { }
 
@@ -70,12 +65,10 @@
      * <p>
      * The CRL issuer must match at least one of the specified distinguished
      * names.
-     * </p>
-     * 
+     *
      * @param issuers
      *            the list of issuer distinguished names to match, or {@code
      *            null} if any issuer distinguished name will do.
-     * @since Android 1.0
      */
     public void setIssuers(Collection<X500Principal> issuers) {
         if (issuers == null) {
@@ -97,20 +90,17 @@
      * <p>
      * The CRL issuer must match at least one of the specified distinguished
      * names.
-     * </p>
      * <p>
      * The specified parameter {@code names} is a collection with an entry for
      * each name to be included in the criterion. The name is specified as a
      * {@code String} or a byte array specifying the name (in RFC 2253 or ASN.1
      * DER encoded form)
-     * </p>
-     * 
+     *
      * @param names
      *            the list of issuer distinguished names to match, or {@code
      *            null} if any issuer distinguished name will do.
      * @throws IOException
      *             if parsing fails.
-     * @since Android 1.0
      */
     public void setIssuerNames(Collection<?> names) throws IOException {
         if (names == null) {
@@ -143,11 +133,9 @@
      * <p>
      * The CRL issuer must match at least one of the specified distinguished
      * names.
-     * </p>
-     * 
+     *
      * @param issuer
      *            the issuer to add to the criterion
-     * @since Android 1.0
      */
     public void addIssuer(X500Principal issuer) {
         if (issuer == null) {
@@ -178,13 +166,11 @@
      * <p>
      * Adds an issuer to the criterion for the issuer distinguished names. The
      * CRK issuer must match at least one of the specified distinguished names.
-     * </p>
-     * 
+     *
      * @param iss_name
      *            the RFC 2253 encoded name.
      * @throws IOException
      *             if parsing fails.
-     * @since Android 1.0
      */
     public void addIssuerName(String iss_name) throws IOException {
         if (issuerNames == null) {
@@ -206,13 +192,11 @@
      * <p>
      * The CRL issuer must match at least one of the specified distinguished
      * names.
-     * </p>
-     * 
+     *
      * @param iss_name
      *            the issuer to add to the criterion in ASN.1 DER encoded form.
      * @throws IOException
      *             if parsing fails.
-     * @since Android 1.0
      */
     public void addIssuerName(byte[] iss_name) throws IOException {
         if (iss_name == null) {
@@ -232,12 +216,10 @@
      * <p>
      * The CRL must have a number extension with a value greater than or equal
      * to the specified parameter.
-     * </p>
-     * 
+     *
      * @param minCRL
      *            the minimum CRL number or null to not check the minimum CRL
      *            number
-     * @since Android 1.0
      */
     public void setMinCRLNumber(BigInteger minCRL) {
         this.minCRL = minCRL;
@@ -248,12 +230,10 @@
      * <p>
      * The CRL must have a number extension with a value less than or equal to
      * the specified parameter.
-     * </p>
-     * 
+     *
      * @param maxCRL
      *            the maximum CRL number or null to not check the maximum CRL
      *            number.
-     * @since Android 1.0
      */
     public void setMaxCRLNumber(BigInteger maxCRL) {
         this.maxCRL = maxCRL;
@@ -264,12 +244,10 @@
      * <p>
      * The CRL's {@code thisUpdate} value must be equal or before the specified
      * date and the {@code nextUpdate} value must be after the specified date.
-     * </p>
-     * 
+     *
      * @param dateAndTime
      *            the date to search for valid CRL's or {@code null} to not
      *            check the date.
-     * @since Android 1.0
      */
     public void setDateAndTime(Date dateAndTime) {
         if (dateAndTime == null) {
@@ -282,10 +260,9 @@
     /**
      * Sets a certificate hint to find CRLs. It's not a criterion but may help
      * finding relevant CRLs.
-     * 
+     *
      * @param cert
      *            the certificate hint or {@code null}.
-     * @since Android 1.0
      */
     public void setCertificateChecking(X509Certificate cert) {
         this.certificateChecking = cert;
@@ -295,11 +272,9 @@
      * Returns the criterion for the issuer distinguished names.
      * <p>
      * The CRL issuer must match at least one of the distinguished names.
-     * </p>
-     * 
+     *
      * @return the unmodifiable list of issuer distinguished names to match, or
      *         {@code null} if any issuer distinguished name will do.
-     * @since Android 1.0
      */
     public Collection<X500Principal> getIssuers() {
         if (issuerNames == null) {
@@ -320,11 +295,9 @@
      * Returns the criterion for the issuer distinguished names.
      * <p>
      * The CRL issuer must match at least one of the distinguished names.
-     * </p>
-     * 
+     *
      * @return a copy of the list of issuer distinguished names to match, or
      *         {@code null} if any issuer distinguished name will do.
-     * @since Android 1.0
      */
     public Collection<Object> getIssuerNames() {
         if (issuerNames == null) {
@@ -338,11 +311,9 @@
      * <p>
      * The CRL must have a number extension with a value greater than or equal
      * to the returned value.
-     * </p>
-     * 
+     *
      * @return the minimum CRL number or {@code null} if the minimum CRL number
      *         is not to be checked.
-     * @since Android 1.0
      */
     public BigInteger getMinCRL() {
         return minCRL;
@@ -353,11 +324,9 @@
      * <p>
      * The CRL must have a number extension with a value less than or equal to
      * the returned value.
-     * </p>
-     * 
+     *
      * @return the maximum CRL number or null if the maximum CRL number is not
      *         checked.
-     * @since Android 1.0
      */
     public BigInteger getMaxCRL() {
         return maxCRL;
@@ -368,11 +337,9 @@
      * <p>
      * The CRL's {@code thisUpdate} value must be equal or before the returned
      * date and the {@code nextUpdate} value must be after the returned date.
-     * </p>
-     * 
+     *
      * @return the date to search for valid CRL's or {@code null} if the date is
      *         not checked.
-     * @since Android 1.0
      */
     public Date getDateAndTime() {
         if (dateAndTime == -1) {
@@ -384,9 +351,8 @@
     /**
      * Returns the certificate hint to find CRLs. It's not a criterion but may
      * help finding relevant CRLs.
-     * 
+     *
      * @return the certificate hint or {@code null} if none set.
-     * @since Android 1.0
      */
     public X509Certificate getCertificateChecking() {
         return certificateChecking;
@@ -394,12 +360,11 @@
 
     /**
      * Returns a string representation of this {@code X509CRLSelector} instance.
-     * 
+     *
      * @return a string representation of this {@code X509CRLSelector} instance.
-     * @since Android 1.0
      */
     public String toString() {
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         result.append("X509CRLSelector:\n["); //$NON-NLS-1$
         if (issuerNames != null) {
             result.append("\n  IssuerNames:\n  ["); //$NON-NLS-1$
@@ -429,12 +394,11 @@
     /**
      * Returns whether the specified CRL matches all the criteria collected in
      * this instance.
-     * 
+     *
      * @param crl
      *            the CRL to check.
      * @return {@code true} if the CRL matches all the criteria, otherwise
      *         {@code false}.
-     * @since Android 1.0
      */
     public boolean match(CRL crl) {
         if (!(crl instanceof X509CRL)) {
@@ -482,19 +446,20 @@
 
     /**
      * Clones this {@code X509CRL} instance.
-     * 
+     *
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone() {
-        X509CRLSelector result = new X509CRLSelector();
-        if (issuerNames != null) {
-            result.issuerNames = new ArrayList<String>(issuerNames);
-        }
-        result.minCRL = minCRL;
-        result.maxCRL = maxCRL;
-        result.dateAndTime = dateAndTime;
-        result.certificateChecking = certificateChecking;
+        X509CRLSelector result;
+
+		try {
+			result = (X509CRLSelector) super.clone();
+			if (issuerNames != null) {
+	            result.issuerNames = new ArrayList<String>(issuerNames);
+	        }
+		} catch (CloneNotSupportedException e) {
+			result = null;
+		}        
         return result;
     }
 }
diff --git a/libcore/security/src/main/java/java/security/cert/X509CertSelector.java b/libcore/security/src/main/java/java/security/cert/X509CertSelector.java
index c6d2e98..e2de95b 100644
--- a/libcore/security/src/main/java/java/security/cert/X509CertSelector.java
+++ b/libcore/security/src/main/java/java/security/cert/X509CertSelector.java
@@ -49,8 +49,6 @@
 /**
  * A certificate selector ({@code CertSelector} for selecting {@code
  * X509Certificate}s that match the specified criteria.
- * 
- * @since Android 1.0
  */
 public class X509CertSelector implements CertSelector {
 
@@ -81,17 +79,14 @@
 
     /**
      * Creates a new {@code X509CertSelector}.
-     * 
-     * @since Android 1.0
      */
     public X509CertSelector() {}
 
     /**
      * Sets the certificate that a matching certificate must be equal to.
-     * 
+     *
      * @param certificate
      *            the certificate to match, or null to not check this criteria.
-     * @since Android 1.0
      */
     public void setCertificate(X509Certificate certificate) {
         certificateEquals = certificate;
@@ -99,10 +94,9 @@
 
     /**
      * Returns the certificate that a matching certificate must be equal to.
-     * 
+     *
      * @return the certificate to match, or null if this criteria is not
      *         checked.
-     * @since Android 1.0
      */
     public X509Certificate getCertificate() {
         return certificateEquals;
@@ -110,11 +104,10 @@
 
     /**
      * Sets the serial number that a certificate must match.
-     * 
+     *
      * @param serialNumber
      *            the serial number to match, or {@code null} to not check the
      *            serial number.
-     * @since Android 1.0
      */
     public void setSerialNumber(BigInteger serialNumber) {
         this.serialNumber = serialNumber;
@@ -122,10 +115,9 @@
 
     /**
      * Returns the serial number that a certificate must match.
-     * 
+     *
      * @return the serial number to match, or {@code null} if the serial number
      *         is not to be checked.
-     * @since Android 1.0
      */
     public BigInteger getSerialNumber() {
         return serialNumber;
@@ -133,11 +125,10 @@
 
     /**
      * Sets the issuer that a certificate must match.
-     * 
+     *
      * @param issuer
      *            the issuer to match, or {@code null} if the issuer is not to
      *            be checked.
-     * @since Android 1.0
      */
     public void setIssuer(X500Principal issuer) {
         this.issuer = issuer;
@@ -147,10 +138,9 @@
 
     /**
      * Returns the issuer that a certificate must match.
-     * 
+     *
      * @return the issuer that a certificate must match, or {@code null} if the
      *         issuer is not to be checked.
-     * @since Android 1.0
      */
     public X500Principal getIssuer() {
         return issuer;
@@ -160,13 +150,12 @@
      * <b>Do not use</b>, use {@link #getIssuer()} or
      * {@link #getIssuerAsBytes()} instead. Sets the issuer that a certificate
      * must match.
-     * 
+     *
      * @param issuerName
      *            the issuer in a RFC 2253 format string, or {@code null} to not
      *            check the issuer.
      * @throws IOException
      *             if parsing the issuer fails.
-     * @since Android 1.0
      */
     public void setIssuer(String issuerName) throws IOException {
         if (issuerName == null) {
@@ -188,10 +177,9 @@
      * <b>Do not use</b>, use {@link #getIssuer()} or
      * {@link #getIssuerAsBytes()} instead. Returns the issuer that a
      * certificate must match in a RFC 2253 format string.
-     * 
+     *
      * @return the issuer in a RFC 2253 format string, or {@code null} if the
      *         issuer is not to be checked.
-     * @since Android 1.0
      */
     public String getIssuerAsString() {
         if (issuer == null) {
@@ -205,13 +193,12 @@
 
     /**
      * Sets the issuer that a certificate must match.
-     * 
+     *
      * @param issuerDN
      *            the distinguished issuer name in ASN.1 DER encoded format, or
      *            {@code null} to not check the issuer.
      * @throws IOException
      *             if decoding the issuer fail.
-     * @since Android 1.0
      */
     public void setIssuer(byte[] issuerDN) throws IOException {
         if (issuerDN == null) {
@@ -230,12 +217,11 @@
 
     /**
      * Returns the issuer that a certificate must match.
-     * 
+     *
      * @return the distinguished issuer name in ASN.1 DER encoded format, or
      *         {@code null} if the issuer is not to be checked.
      * @throws IOException
      *             if encoding the issuer fails.
-     * @since Android 1.0
      */
     public byte[] getIssuerAsBytes() throws IOException {
         if (issuer == null) {
@@ -251,11 +237,10 @@
 
     /**
      * Set the subject that a certificate must match.
-     * 
+     *
      * @param subject
      *            the subject distinguished name or {@code null} to not check
      *            the subject.
-     * @since Android 1.0
      */
     public void setSubject(X500Principal subject) {
         this.subject = subject;
@@ -263,10 +248,9 @@
 
     /**
      * Returns the subject that a certificate must match.
-     * 
+     *
      * @return the subject distinguished name, or null if the subject is not to
      *         be checked.
-     * @since Android 1.0
      */
     public X500Principal getSubject() {
         return subject;
@@ -276,13 +260,12 @@
      * <b>Do not use</b>, use {@link #setSubject(byte[])} or
      * {@link #setSubject(X500Principal)} instead. Returns the subject that a
      * certificate must match.
-     * 
+     *
      * @param subjectDN
      *            the subject distinguished name in RFC 2253 format or {@code
      *            null} to not check the subject.
      * @throws IOException
      *             if decoding the subject fails.
-     * @since Android 1.0
      */
     public void setSubject(String subjectDN) throws IOException {
         if (subjectDN == null) {
@@ -300,10 +283,9 @@
      * <b>Do not use</b>, use {@link #getSubject()} or
      * {@link #getSubjectAsBytes()} instead. Returns the subject that a
      * certificate must match.
-     * 
+     *
      * @return the subject distinguished name in RFC 2253 format, or {@code
      *         null} if the subject is not to be checked.
-     * @since Android 1.0
      */
     public String getSubjectAsString() {
         if (subject == null) {
@@ -314,13 +296,12 @@
 
     /**
      * Sets the subject that a certificate must match.
-     * 
+     *
      * @param subjectDN
      *            the subject distinguished name in ASN.1 DER format, or {@code
      *            null} to not check the subject.
      * @throws IOException
      *             if decoding the subject fails.
-     * @since Android 1.0
      */
     public void setSubject(byte[] subjectDN) throws IOException {
         if (subjectDN == null) {
@@ -336,12 +317,11 @@
 
     /**
      * Returns the subject that a certificate must match.
-     * 
+     *
      * @return the subject distinguished name in ASN.1 DER format, or {@code
      *         null} if the subject is not to be checked.
      * @throws IOException
      *             if encoding the subject fails.
-     * @since Android 1.0
      */
     public byte[] getSubjectAsBytes() throws IOException {
         if (subject == null) {
@@ -354,12 +334,10 @@
      * Sets the criterion for the {@literal SubjectKeyIdentifier} extension.
      * <p>
      * The {@code subjectKeyIdentifier} should be a single DER encoded value.
-     * </p>
-     * 
+     *
      * @param subjectKeyIdentifier
      *            the subject key identifier or {@code null} to disable this
      *            check.
-     * @since Android 1.0
      */
     public void setSubjectKeyIdentifier(byte[] subjectKeyIdentifier) {
         if (subjectKeyIdentifier == null) {
@@ -373,10 +351,9 @@
 
     /**
      * Returns the criterion for the {@literal SubjectKeyIdentifier} extension.
-     * 
+     *
      * @return the subject key identifier or {@code null} if it is not to be
      *         checked.
-     * @since Android 1.0
      */
     public byte[] getSubjectKeyIdentifier() {
         if (subjectKeyIdentifier == null) {
@@ -389,11 +366,10 @@
 
     /**
      * Sets the criterion for the {@literal AuthorityKeyIdentifier} extension.
-     * 
+     *
      * @param authorityKeyIdentifier
      *            the authority key identifier, or {@code null} to disable this
      *            check.
-     * @since Android 1.0
      */
     public void setAuthorityKeyIdentifier(byte[] authorityKeyIdentifier) {
         if (authorityKeyIdentifier == null) {
@@ -409,10 +385,9 @@
     /**
      * Returns the criterion for the {@literal AuthorityKeyIdentifier}
      * extension.
-     * 
+     *
      * @return the authority key identifier, or {@code null} if it is not to be
      *         checked.
-     * @since Android 1.0
      */
     public byte[] getAuthorityKeyIdentifier() {
         if (authorityKeyIdentifier == null) {
@@ -427,10 +402,8 @@
      * Sets the criterion for the validity date of the certificate.
      * <p>
      * The certificate must be valid at the specified date.
-     * </p>
      * @param certificateValid
      *            the validity date or {@code null} to not check the date.
-     * @since Android 1.0
      */
     public void setCertificateValid(Date certificateValid) {
         this.certificateValid = (certificateValid == null)
@@ -440,10 +413,9 @@
 
     /**
      * Returns the criterion for the validity date of the certificate.
-     * 
+     *
      * @return the validity date or {@code null} if the date is not to be
      *         checked.
-     * @since Android 1.0
      */
     public Date getCertificateValid() {
         return (certificateValid == null)
@@ -455,11 +427,9 @@
      * Sets the criterion for the validity date of the private key.
      * <p>
      * The private key must be valid at the specified date.
-     * </p>
-     * 
+     *
      * @param privateKeyValid
      *            the validity date or {@code null} to not check the date.
-     * @since Android 1.0
      */
     public void setPrivateKeyValid(Date privateKeyValid) {
         if (privateKeyValid == null) {
@@ -473,11 +443,9 @@
      * Returns the criterion for the validity date of the private key.
      * <p>
      * The private key must be valid at the specified date.
-     * </p>
-     * 
+     *
      * @return the validity date or {@code null} if the date is not to be
      *         checked.
-     * @since Android 1.0
      */
     public Date getPrivateKeyValid() {
         if (privateKeyValid != null) {
@@ -512,14 +480,12 @@
      * <p>
      * The certificate must contain a subject public key with the algorithm
      * specified.
-     * </p>
-     * 
+     *
      * @param oid
      *            the OID (object identifier) of the signature algorithm or
      *            {@code null} to not check the OID.
      * @throws IOException
      *             if the specified object identifier is invalid.
-     * @since Android 1.0
      */
     public void setSubjectPublicKeyAlgID(String oid) throws IOException {
         if (oid == null) {
@@ -532,10 +498,9 @@
 
     /**
      * Returns the criterion for the subject public key signature algorithm.
-     * 
+     *
      * @return the OID (object identifier) or the signature algorithm or {@code
      *         null} if it's not to be checked.
-     * @since Android 1.0
      */
     public String getSubjectPublicKeyAlgID() {
         return subjectPublicKeyAlgID;
@@ -543,10 +508,9 @@
 
     /**
      * Sets the criterion for the subject public key.
-     * 
+     *
      * @param key
      *            the subject public key or {@code null} to not check the key.
-     * @since Android 1.0
      */
     public void setSubjectPublicKey(PublicKey key) {
         subjectPublicKey = (key == null) ? null : key.getEncoded();
@@ -555,13 +519,12 @@
 
     /**
      * Sets the criterion for the subject public key.
-     * 
+     *
      * @param key
      *            the subject public key in ASN.1 DER encoded format or {@code null} to
      *            not check the key.
      * @throws IOException
      *             if decoding the the public key fails.
-     * @since Android 1.0
      */
     public void setSubjectPublicKey(byte[] key) throws IOException {
         if (key == null) {
@@ -578,10 +541,9 @@
 
     /**
      * Returns the criterion for the subject public key.
-     * 
+     *
      * @return the subject public key or {@code null} if the key is not to be
      *         checked.
-     * @since Android 1.0
      */
     public PublicKey getSubjectPublicKey() {
         return subjectPublicKeyImpl;
@@ -589,12 +551,11 @@
 
     /**
      * Sets the criterion for the {@literal KeyUsage} extension.
-     * 
+     *
      * @param keyUsage
      *            the boolean array in the format as returned by
      *            {@link X509Certificate#getKeyUsage()}, or {@code null} to not
      *            check the key usage.
-     * @since Android 1.0
      */
     public void setKeyUsage(boolean[] keyUsage) {
         if (keyUsage == null) {
@@ -607,11 +568,10 @@
 
     /**
      * Returns the criterion for the {@literal KeyUsage} extension.
-     * 
+     *
      * @return the boolean array in the format as returned by
      *         {@link X509Certificate#getKeyUsage()}, or {@code null} if the key
      *         usage is not to be checked.
-     * @since Android 1.0
      */
     public boolean[] getKeyUsage() {
         if (keyUsage == null) {
@@ -624,12 +584,11 @@
 
     /**
      * Sets the criterion for the {@literal ExtendedKeyUsage} extension.
-     * 
+     *
      * @param keyUsage
      *            the set of key usage OIDs, or {@code null} to not check it.
      * @throws IOException
      *             if one of the OIDs is invalid.
-     * @since Android 1.0
      */
     public void setExtendedKeyUsage(Set<String> keyUsage)
                              throws IOException {
@@ -649,10 +608,9 @@
 
     /**
      * Returns the criterion for the {@literal ExtendedKeyUsage} extension.
-     * 
+     *
      * @return the set of key usage OIDs, or {@code null} if it's not to be
      *         checked.
-     * @since Android 1.0
      */
     public Set<String> getExtendedKeyUsage() {
         return extendedKeyUsage;
@@ -662,15 +620,12 @@
      * Sets the flag for the matching behavior for subject alternative names.
      * <p>
      * The flag indicates whether a certificate must contain all or at least one
-     * of the subject alternative names specified by
-     * {@link #setSubjectAlternativeNames} or {@link #addSubjectAlternativeName}
-     * .
-     * </p>
-     * 
+     * of the subject alternative names specified by {@link
+     * #setSubjectAlternativeNames} or {@link #addSubjectAlternativeName}.
+     *
      * @param matchAllNames
      *            {@code true} if a certificate must contain all of the
      *            specified subject alternative names, otherwise {@code false}.
-     * @since Android 1.0
      */
     public void setMatchAllSubjectAltNames(boolean matchAllNames) {
         this.matchAllNames = matchAllNames;
@@ -680,14 +635,11 @@
      * Returns the flag for the matching behavior for subject alternative names.
      * <p>
      * The flag indicates whether a certificate must contain all or at least one
-     * of the subject alternative names specified by
-     * {@link #setSubjectAlternativeNames} or {@link #addSubjectAlternativeName}
-     * .
-     * </p>
-     * 
+     * of the subject alternative names specified by {@link
+     * #setSubjectAlternativeNames} or {@link #addSubjectAlternativeName}.
+     *
      * @return {@code true} if a certificate must contain all of the specified
      *         subject alternative names, otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean getMatchAllSubjectAltNames() {
         return matchAllNames;
@@ -699,20 +651,17 @@
      * the certificate must contain all or at least one of the specified subject
      * alternative names. The behavior is specified by
      * {@link #getMatchAllSubjectAltNames}.
-     * </p>
      * <p>
      * The specified parameter {@code names} is a collection with an entry for
      * each name to be included in the criterion. The name is specified as a
      * {@code List}, the first entry must be an {@code Integer} specifying the
      * name type (0-8), the second entry must be a {@code String} or a byte
      * array specifying the name (in string or ASN.1 DER encoded form)
-     * </p>
-     * 
+     *
      * @param names
      *            the names collection or {@code null} to not perform this check.
      * @throws IOException
      *             if the decoding of a name fails.
-     * @since Android 1.0
      */
     public void setSubjectAlternativeNames(Collection<List<?>> names)
                                     throws IOException {
@@ -737,14 +686,13 @@
 
     /**
      * Adds a subject alternative name to the respective criterion.
-     * 
+     *
      * @param tag
      *            the type of the name
      * @param name
      *            the name in string format.
      * @throws IOException
      *             if parsing the name fails.
-     * @since Android 1.0
      */
     public void addSubjectAlternativeName(int tag, String name)
                                                        throws IOException {
@@ -761,14 +709,13 @@
 
     /**
      * Adds a subject alternative name to the respective criterion.
-     * 
+     *
      * @param tag
      *            the type of the name.
      * @param name
      *            the name in ASN.1 DER encoded form.
      * @throws IOException
      *             if the decoding of the name fails.
-     * @since Android 1.0
      */
     public void addSubjectAlternativeName(int tag, byte[] name)
                                             throws IOException {
@@ -789,16 +736,13 @@
      * the certificate must contain all or at least one of the specified subject
      * alternative names. The behavior is specified by
      * {@link #getMatchAllSubjectAltNames}.
-     * </p>
      * <p>
      * The subject alternative names is a collection with an entry for each name
      * included in the criterion. The name is specified as a {@code List}, the
      * first entry is an {@code Integer} specifying the name type (0-8), the
      * second entry is byte array specifying the name in ASN.1 DER encoded form)
-     * </p>
-     * 
+     *
      * @return the names collection or {@code null} if none specified.
-     * @since Android 1.0
      */
     public Collection<List<?>> getSubjectAlternativeNames() {
         if (subjectAltNames == null) {
@@ -830,24 +774,23 @@
      * <p>
      * The certificate must constraint subject and subject alternative names
      * that match the specified name constraints.
-     * </p>
      * <p>
      * The name constraints in ASN.1:
-     * 
+     *
      * <pre>
      * NameConstraints ::= SEQUENCE {
      *        permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
      *        excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
-     * 
+     *
      * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
-     * 
+     *
      * GeneralSubtree ::= SEQUENCE {
      *        base                    GeneralName,
      *        minimum         [0]     BaseDistance DEFAULT 0,
      *        maximum         [1]     BaseDistance OPTIONAL }
-     * 
+     *
      * BaseDistance ::= INTEGER (0..MAX)
-     * 
+     *
      * GeneralName ::= CHOICE {
      *        otherName                       [0]     OtherName,
      *        rfc822Name                      [1]     IA5String,
@@ -858,17 +801,14 @@
      *        uniformResourceIdentifier       [6]     IA5String,
      *        iPAddress                       [7]     OCTET STRING,
      *        registeredID                    [8]     OBJECT IDENTIFIER}
-     * 
+     *
      * </pre>
-     * 
-     * </p>
-     * 
+     *
      * @param bytes
      *            the name constraints in ASN.1 DER encoded format, or null to
      *            not check any constraints.
      * @throws IOException
      *             if decoding the name constraints fail.
-     * @since Android 1.0
      */
     public void setNameConstraints(byte[] bytes) throws IOException {
         this.nameConstraints = (bytes == null)
@@ -878,10 +818,9 @@
 
     /**
      * Returns the criterion for the name constraints.
-     * 
+     *
      * @return the name constraints or {@code null} if none specified.
      * @see #setNameConstraints
-     * @since Android 1.0
      */
     public byte[] getNameConstraints() {
         return (nameConstraints == null)
@@ -896,11 +835,9 @@
      * include a basic constraints extension with a path length of a least that
      * value. A value of {@code -2} indicates that only end-entity certificates
      * are accepted. A value of {@code -1} indicates that no check is done.
-     * </p>
-     * 
+     *
      * @param pathLen
      *            the value specifying the criterion.
-     * @since Android 1.0
      * @throws IllegalArgumentException
      *             if {@code pathLen} is less than {@code -2}.
      */
@@ -918,10 +855,8 @@
      * include a basic constraints extension with a path length of a least that
      * value. A value of {@code -2} indicates that only end-entity certificates
      * are accepted. A value of {@code -1} indicates that no check is done.
-     * </p>
-     * 
+     *
      * @return the value of the criterion.
-     * @since Android 1.0
      */
     public int getBasicConstraints() {
         return pathLen;
@@ -933,14 +868,12 @@
      * The certificate must have at least one of the specified certificate
      * policy extensions. For an empty set the certificate must have at least
      * some policies in its policy extension.
-     * </p>
-     * 
+     *
      * @param policies
      *            the certificate policy OIDs, an empty set, or {@code null} to
      *            not perform this check.
      * @throws IOException
      *             if parsing the specified OIDs fails.
-     * @since Android 1.0
      */
     public void setPolicy(Set<String> policies) throws IOException {
         if (policies == null) {
@@ -963,11 +896,9 @@
      * The certificate must have at least one of the certificate policy
      * extensions. For an empty set the certificate must have at least some
      * policies in its policy extension.
-     * </p>
-     * 
+     *
      * @return the certificate policy OIDs, an empty set, or {@code null} if not
      *         to be checked.
-     * @since Android 1.0
      */
     public Set<String> getPolicy() {
         return policies;
@@ -978,21 +909,18 @@
      * <p>
      * This allows to specify the complete set of names, a certificate's name
      * constraints must permit.
-     * </p>
      * <p>
      * The specified parameter {@code names} is a collection with an entry for
      * each name to be included in the criterion. The name is specified as a
      * {@code List}, the first entry must be an {@code Integer} specifying the
      * name type (0-8), the second entry must be a {@code String} or a byte
      * array specifying the name (in string or ASN.1 DER encoded form)
-     * </p>
-     * 
+     *
      * @param names
      *            the names collection or {@code null} to not perform this
      *            check.
      * @throws IOException
      *             if decoding fails.
-     * @since Android 1.0
      */
     public void setPathToNames(Collection<List<?>> names)
                                                         throws IOException {
@@ -1017,7 +945,7 @@
 
     /**
      * Adds a {@literal "pathToName"} to the respective criterion.
-     * 
+     *
      * @param type
      *            the type of the name.
      * @param name
@@ -1025,7 +953,6 @@
      * @throws IOException
      *             if parsing fails.
      * @see #setPathToNames
-     * @since Android 1.0
      */
     public void addPathToName(int type, String name) throws IOException {
         GeneralName path_name = new GeneralName(type, name);
@@ -1038,7 +965,7 @@
 
     /**
      * Adds a {@literal "pathToName"} to the respective criterion.
-     * 
+     *
      * @param type
      *            the type of the name
      * @param name
@@ -1046,7 +973,6 @@
      * @throws IOException
      *             if decoding fails.
      * @see #setPathToNames
-     * @since Android 1.0
      */
     public void addPathToName(int type, byte[] name) throws IOException {
         GeneralName path_name= new GeneralName(type, name);
@@ -1064,10 +990,8 @@
      * in the criterion. The name is specified as a {@code List}, the first
      * entry is an {@code Integer} specifying the name type (0-8), the second
      * entry is a byte array specifying the name in ASN.1 DER encoded form.
-     * </p>
-     * 
+     *
      * @return the pathToNames constraint or {@code null} if none specified.
-     * @since Android 1.0
      */
     public Collection<List<?>> getPathToNames() {
         if (pathToNames == null) {
@@ -1085,17 +1009,16 @@
     /**
      * Returns a string representation of this {@code X509CertSelector}
      * instance.
-     * 
+     *
      * @return a string representation of this {@code X509CertSelector}
      *         instance.
-     * @since Android 1.0
      */
     public String toString() {
         // For convenient reading of the string representation
         // all of the fields named according to the rfc 3280
         // (http://www.ietf.org/rfc/rfc3280.txt).
 
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         result.append("X509CertSelector: \n["); //$NON-NLS-1$
         if (this.certificateEquals != null) {
             result.append("\n  certificateEquals: " + certificateEquals); //$NON-NLS-1$
@@ -1210,12 +1133,11 @@
     /**
      * Returns whether the specified certificate matches all the criteria
      * collected in this instance.
-     * 
+     *
      * @param certificate
      *            the certificate to check.
      * @return {@code true} if the certificate matches all the criteria,
      *         otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean match(Certificate certificate) {
         if (! (certificate instanceof X509Certificate)) {
@@ -1452,16 +1374,18 @@
 
     /**
      * Clones this {@code X509CertSelector} instance.
-     * 
+     *
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone() {
-        X509CertSelector result = new X509CertSelector();
-        result.certificateEquals = this.certificateEquals;
-        result.serialNumber = this.serialNumber;
-        result.issuer = this.issuer;
-        result.subject = this.subject;
+        X509CertSelector result;
+
+		try {
+			result = (X509CertSelector) super.clone();
+		} catch (CloneNotSupportedException e) {
+			return null;
+		}
+
         if (this.subjectKeyIdentifier != null) {
             result.subjectKeyIdentifier =
                 new byte[this.subjectKeyIdentifier.length];
@@ -1476,9 +1400,6 @@
                     result.authorityKeyIdentifier, 0,
                     this.authorityKeyIdentifier.length);
         }
-        result.certificateValid = this.certificateValid;
-        result.subjectPublicKeyAlgID = this.subjectPublicKeyAlgID;
-        result.privateKeyValid = this.privateKeyValid;
         if (this.subjectPublicKey != null) {
             result.subjectPublicKey = new byte[this.subjectPublicKey.length];
             System.arraycopy(this.subjectPublicKey, 0, result.subjectPublicKey,
@@ -1492,8 +1413,6 @@
         result.extendedKeyUsage = (this.extendedKeyUsage == null)
             ? null
             : new HashSet(this.extendedKeyUsage);
-        result.matchAllNames = this.matchAllNames;
-        result.pathLen = this.pathLen;
         if (this.subjectAltNames != null) {
             result.subjectAltNames = new ArrayList[9];
             for (int i=0; i<9; i++) {
@@ -1503,15 +1422,12 @@
                 }
             }
         }
-        result.nameConstraints = this.nameConstraints;
         result.policies = (this.policies == null)
             ? null
             : new HashSet(this.policies);
         result.pathToNames = (this.pathToNames == null)
             ? null
             : new ArrayList(this.pathToNames);
-        result.subjectPublicKeyImpl = this.subjectPublicKeyImpl;
-
         return result;
     }
 }
diff --git a/libcore/security/src/main/java/java/security/cert/X509Certificate.java b/libcore/security/src/main/java/java/security/cert/X509Certificate.java
index 9e10077..e49901c 100644
--- a/libcore/security/src/main/java/java/security/cert/X509Certificate.java
+++ b/libcore/security/src/main/java/java/security/cert/X509Certificate.java
@@ -33,7 +33,6 @@
  * <p>
  * This represents a standard way for accessing the attributes of X.509
  * certificates.
- * </p>
  * <p>
  * The basic X.509 v3 format described in ASN.1:
  * 
@@ -59,16 +58,12 @@
  *                           -- If present, version must be v3
  *      }
  * </pre>
- * </p>
  * <p>
  * For more information consult RFC 2459
  * "Internet X.509 Public Key Infrastructure Certificate and CRL Profile" at <a
  * href
  * ="http://www.ietf.org/rfc/rfc2459.txt">http://www.ietf.org/rfc/rfc2459.txt
  * </a> .
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class X509Certificate
         extends Certificate implements X509Extension {
@@ -77,8 +72,6 @@
 
     /**
      * Creates a new {@code X509Certificate}.
-     * 
-     * @since Android 1.0
      */
     protected X509Certificate() {
         super("X.509"); //$NON-NLS-1$
@@ -101,13 +94,10 @@
      *      generalTime     GeneralizedTime }
      * </pre>
      * 
-     * </p>
-     * 
      * @throws CertificateExpiredException
      *             if the certificate has expired.
      * @throws CertificateNotYetValidException
      *             if the certificate is not yet valid.
-     * @since Android 1.0
      */
     public abstract void checkValidity()
             throws CertificateExpiredException, CertificateNotYetValidException;
@@ -122,7 +112,6 @@
      * @throws CertificateNotYetValidException
      *             if the certificate is not yet valid.
      * @see #checkValidity()
-     * @since Android 1.0
      */
     public abstract void checkValidity(Date date)
             throws CertificateExpiredException, CertificateNotYetValidException;
@@ -136,10 +125,7 @@
      * Version ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
      * </pre>
      * 
-     * </p>
-     * 
      * @return the version number.
-     * @since Android 1.0
      */
     public abstract int getVersion();
 
@@ -152,10 +138,7 @@
      * CertificateSerialNumber  ::=  INTEGER
      * </pre>
      * 
-     * </p>
-     * 
      * @return the serial number.
-     * @since Android 1.0
      */
     public abstract BigInteger getSerialNumber();
 
@@ -184,12 +167,10 @@
      *    AttributeValue ::= ANY DEFINED BY AttributeType
      * </pre>
      * 
-     * </p>
      * <b>replaced by:</b> {@link #getIssuerX500Principal()}.
      * 
      * @return the {@code issuer} as an implementation specific {@code
      *         Principal}.
-     * @since Android 1.0
      */
     public abstract Principal getIssuerDN() ;
 
@@ -198,7 +179,6 @@
      * X500Principal}.
      * 
      * @return the {@code issuer} (issuer distinguished name).
-     * @since Android 1.0
      */
     public X500Principal getIssuerX500Principal() {
 
@@ -243,13 +223,10 @@
      *    AttributeValue ::= ANY DEFINED BY AttributeType
      * </pre>
      * 
-     * </p>
      * <p>
      * <b>replaced by:</b> {@link #getSubjectX500Principal()}.
-     * </p>
-     * 
+     *
      * @return the {@code subject} (subject distinguished name).
-     * @since Android 1.0
      */
     public abstract Principal getSubjectDN();
 
@@ -258,7 +235,6 @@
      * X500Principal}.
      * 
      * @return the {@code subject} (subject distinguished name)
-     * @since Android 1.0
      */
     public X500Principal getSubjectX500Principal() {
 
@@ -283,7 +259,6 @@
      * certificate.
      * 
      * @return the start of the validity period.
-     * @since Android 1.0
      */
     public abstract Date getNotBefore();
 
@@ -292,7 +267,6 @@
      * certificate.
      * 
      * @return the end of the validity period.
-     * @since Android 1.0
      */
     public abstract Date getNotAfter();
 
@@ -303,7 +277,6 @@
      * @return the DER-encoded certificate information.
      * @throws CertificateEncodingException
      *             if an error occurs in encoding
-     * @since Android 1.0
      */
     public abstract byte[] getTBSCertificate()
                                     throws CertificateEncodingException;
@@ -312,7 +285,6 @@
      * Returns the raw signature bits from the certificate.
      * 
      * @return the raw signature bits from the certificate.
-     * @since Android 1.0
      */
     public abstract byte[] getSignature();
 
@@ -320,7 +292,6 @@
      * Returns the name of the algorithm for the certificate signature.
      * 
      * @return the signature algorithm name.
-     * @since Android 1.0
      */
     public abstract String getSigAlgName();
 
@@ -328,7 +299,6 @@
      * Returns the OID of the signature algorithm from the certificate.
      * 
      * @return the OID of the signature algorithm.
-     * @since Android 1.0
      */
     public abstract String getSigAlgOID();
 
@@ -337,7 +307,6 @@
      * 
      * @return the parameters of the signature algorithm, or {@code null} if
      *         none are used.
-     * @since Android 1.0
      */
     public abstract byte[] getSigAlgParams();
 
@@ -346,7 +315,6 @@
      * 
      * @return the {@code issuerUniqueID} or {@code null} if there's none in the
      *         certificate.
-     * @since Android 1.0
      */
     public abstract boolean[] getIssuerUniqueID();
 
@@ -355,7 +323,6 @@
      * 
      * @return the {@code subjectUniqueID} or null if there's none in the
      *         certificate.
-     * @since Android 1.0
      */
     public abstract boolean[] getSubjectUniqueID();
 
@@ -378,11 +345,8 @@
      * 
      * </pre>
      * 
-     * </p>
-     * 
      * @return the {@code KeyUsage} extension or {@code null} if there's none in
      *         the certificate.
-     * @since Android 1.0
      */
     public abstract boolean[] getKeyUsage();
 
@@ -394,7 +358,6 @@
      *         in the certificate.
      * @throws CertificateParsingException
      *             if the extension decoding fails.
-     * @since Android 1.0
      */
     public List<String> getExtendedKeyUsage()
                         throws CertificateParsingException {
@@ -408,7 +371,6 @@
      * @return the path length of the certificate constraints if the extension
      *         is present or {@code -1} if the extension is not present. {@code
      *         Integer.MAX_VALUE} if there's not limit.
-     * @since Android 1.0
      */
     public abstract int getBasicConstraints();
 
@@ -436,13 +398,10 @@
      * 
      * </pre>
      * 
-     * </p>
-     * 
      * @return the subject alternative names or {@code null} if there are none
      *         in the certificate.
      * @throws CertificateParsingException
      *             if decoding of the extension fails.
-     * @since Android 1.0
      */
     public Collection<List<?>> getSubjectAlternativeNames()
                                     throws CertificateParsingException {
@@ -473,13 +432,10 @@
      * 
      * </pre>
      * 
-     * </p>
-     * 
      * @return the issuer alternative names of {@code null} if there are none in
      *         the certificate.
      * @throws CertificateParsingException
      *             if decoding of the extension fails.
-     * @since Android 1.0
      */
     public Collection<List<?>> getIssuerAlternativeNames()
                                     throws CertificateParsingException {
diff --git a/libcore/security/src/main/java/java/security/cert/X509Extension.java b/libcore/security/src/main/java/java/security/cert/X509Extension.java
index cc8648b..1543f3d 100644
--- a/libcore/security/src/main/java/java/security/cert/X509Extension.java
+++ b/libcore/security/src/main/java/java/security/cert/X509Extension.java
@@ -21,8 +21,6 @@
 
 /**
  * The interface specifying an X.509 Certificate or CRL extension.
- * 
- * @since Android 1.0
  */
 public interface X509Extension {
 
@@ -33,7 +31,6 @@
      * @return the set of extension OIDs marked as CRITIAL, an empty set if none
      *         are marked as CRITICAL, or {@code null} if no extensions are
      *         present.
-     * @since Android 1.0
      */
     public Set<String> getCriticalExtensionOIDs();
 
@@ -45,7 +42,6 @@
      *            the object identifier to get the extension value for.
      * @return the extension value as DER-encoded OCTET string, or {@code null}
      *         if no extension for the specified OID can be found.
-     * @since Android 1.0
      */
     public byte[] getExtensionValue(String oid);
 
@@ -56,7 +52,6 @@
      * @return the set of extension OIDs marked as NON-CRITIAL, an empty set if
      *         none are marked as NON-.CRITICAL, or {@code null} if no
      *         extensions are present.
-     * @since Android 1.0
      */
     public Set<String> getNonCriticalExtensionOIDs();
 
@@ -66,7 +61,6 @@
      * 
      * @return {@code true} if an unsupported CRITICAL extension is present,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean hasUnsupportedCriticalExtension();
 }
diff --git a/libcore/security/src/main/java/java/security/interfaces/DSAKey.java b/libcore/security/src/main/java/java/security/interfaces/DSAKey.java
index 1362bff..ac9aade 100644
--- a/libcore/security/src/main/java/java/security/interfaces/DSAKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/DSAKey.java
@@ -21,8 +21,6 @@
 /**
  * The base interface for Digital Signature Algorithm (DSA) public or private
  * keys.
- * 
- * @since Android 1.0
  */
 public interface DSAKey {
 
@@ -30,8 +28,7 @@
      * Returns the DSA key parameters.
      * 
      * @return the DSA key parameters.
-     * @since Android 1.0
      */
     public DSAParams getParams();
 
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java b/libcore/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
index 4b89c6a..b7b5480 100644
--- a/libcore/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
+++ b/libcore/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
@@ -22,8 +22,6 @@
 
 /**
  * The interface for key generators that can generate DSA key pairs.
- * 
- * @since Android 1.0
  */
 public interface DSAKeyPairGenerator {
 
@@ -38,7 +36,6 @@
      * @throws InvalidParameterException
      *             if the specified parameter values are {@code null} or
      *             invalid.
-     * @since Android 1.0
      */
     public void initialize(DSAParams params, SecureRandom random)
             throws InvalidParameterException;
@@ -53,7 +50,6 @@
      * it will use the pre-calculated values for the specified modulus
      * length. Default parameters are available for modulus lengths of 512 and 1024
      * bits.
-     * </p>
      * 
      * @param modlen
      *            the length of the modulus in bits.
@@ -65,8 +61,7 @@
      *             if the specified modulus length is not valid, or if there are
      *             no pre-calculated values and {@code genParams} is {@code
      *             false}.
-     * @since Android 1.0
      */
     public void initialize(int modlen, boolean genParams, SecureRandom random)
             throws InvalidParameterException;
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/DSAParams.java b/libcore/security/src/main/java/java/security/interfaces/DSAParams.java
index 0483da2..62f2d00 100644
--- a/libcore/security/src/main/java/java/security/interfaces/DSAParams.java
+++ b/libcore/security/src/main/java/java/security/interfaces/DSAParams.java
@@ -21,8 +21,6 @@
 
 /**
  * The interface for Digital Signature Algorithm (DSA) specific parameters. 
- * 
- * @since Android 1.0
  */
 public interface DSAParams {
 
@@ -30,7 +28,6 @@
      * Returns the base ({@code g}) value.
      * 
      * @return the base ({@code g}) value.
-     * @since Android 1.0
      */
     public BigInteger getG();
 
@@ -38,7 +35,6 @@
      * Returns the prime ({@code p}) value.
      * 
      * @return the prime ({@code p}) value.
-     * @since Android 1.0
      */
     public BigInteger getP();
 
@@ -46,7 +42,6 @@
      * Returns the subprime ({@code q} value.
      * 
      * @return the subprime ({@code q} value.
-     * @since Android 1.0
      */
     public BigInteger getQ();
 
diff --git a/libcore/security/src/main/java/java/security/interfaces/DSAPrivateKey.java b/libcore/security/src/main/java/java/security/interfaces/DSAPrivateKey.java
index e2592ca..6419440 100644
--- a/libcore/security/src/main/java/java/security/interfaces/DSAPrivateKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/DSAPrivateKey.java
@@ -22,15 +22,11 @@
 
 /**
  * The interface for a Digital Signature Algorithm (DSA) private key.
- * 
- * @since Android 1.0
  */
 public interface DSAPrivateKey extends DSAKey, PrivateKey {
 
     /**
      * The serial version identifier.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = 7776497482533790279L;
 
@@ -38,8 +34,7 @@
      * Returns the private key value {@code x}.
      * 
      * @return the private key value {@code x}.
-     * @since Android 1.0
      */
     public BigInteger getX();
 
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/DSAPublicKey.java b/libcore/security/src/main/java/java/security/interfaces/DSAPublicKey.java
index ccb985e..9642bf1 100644
--- a/libcore/security/src/main/java/java/security/interfaces/DSAPublicKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/DSAPublicKey.java
@@ -22,15 +22,11 @@
 
 /**
  * The interface for a Digital Signature Algorithm (DSA) public key. 
- * 
- * @since Android 1.0
  */
 public interface DSAPublicKey extends DSAKey, PublicKey {
 
     /**
      * The serial version identifier.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = 1234526332779022332L;
 
@@ -38,8 +34,7 @@
      * Returns the public key value {@code y}.
      * 
      * @return the public key value {@code y}.
-     * @since Android 1.0
      */
     public BigInteger getY();
 
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/ECKey.java b/libcore/security/src/main/java/java/security/interfaces/ECKey.java
index 9f5d254..5469392 100644
--- a/libcore/security/src/main/java/java/security/interfaces/ECKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/ECKey.java
@@ -21,8 +21,6 @@
 
 /**
  * The base interface for Elliptic Curve (EC) public or private keys.
- * 
- * @since Android 1.0
  */
 public interface ECKey {
 
@@ -30,7 +28,6 @@
      * Returns the EC key parameters.
      * 
      * @return the EC key parameters.
-     * @since Android 1.0
      */
     public ECParameterSpec getParams();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/ECPrivateKey.java b/libcore/security/src/main/java/java/security/interfaces/ECPrivateKey.java
index 74ef4c2..254d2a6 100644
--- a/libcore/security/src/main/java/java/security/interfaces/ECPrivateKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/ECPrivateKey.java
@@ -22,15 +22,11 @@
 
 /**
  * The interface for an Elliptic Curve (EC) private key.
- * 
- * @since Android 1.0
  */
 public interface ECPrivateKey extends PrivateKey, ECKey {
 
     /**
      * The serial version identifier.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = -7896394956925609184L;
 
@@ -38,7 +34,6 @@
      * Returns the private value {@code S}.
      * 
      * @return the private value {@code S}.
-     * @since Android 1.0
      */
     public BigInteger getS();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/ECPublicKey.java b/libcore/security/src/main/java/java/security/interfaces/ECPublicKey.java
index 063dfe9..8ad97fc 100644
--- a/libcore/security/src/main/java/java/security/interfaces/ECPublicKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/ECPublicKey.java
@@ -22,15 +22,11 @@
 
 /**
  * The interface for an Elliptic Curve (EC) public key.
- * 
- * @since Android 1.0
  */
 public interface ECPublicKey extends PublicKey, ECKey {
 
     /**
      * The serial version identifier.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = -3314988629879632826L;
 
@@ -38,7 +34,6 @@
      * Returns the public point {@code W} on an elliptic curve (EC).
      * 
      * @return the public point {@code W} on an elliptic curve (EC).
-     * @since Android 1.0
      */
     public ECPoint getW();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/RSAKey.java b/libcore/security/src/main/java/java/security/interfaces/RSAKey.java
index bc0877e..2c9e6c1 100644
--- a/libcore/security/src/main/java/java/security/interfaces/RSAKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/RSAKey.java
@@ -21,8 +21,6 @@
 
 /**
  * The base interface for PKCS#1 RSA public and private keys.
- * 
- * @since Android 1.0
  */
 public interface RSAKey {
 
@@ -30,7 +28,6 @@
      * Returns the modulus.
      * 
      * @return the modulus.
-     * @since Android 1.0
      */
     public BigInteger getModulus();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java b/libcore/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
index c5e86c3..d8aa1bf 100644
--- a/libcore/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
@@ -24,15 +24,11 @@
  * The interface for a Multi-Prime RSA private key. Specified by <a
  * href="http://www.rsa.com/rsalabs/node.asp?id=2125">PKCS #1 v2.0 Amendment 1:
  * Multi-Prime RSA</a>.
- * 
- * @since Android 1.0
  */
 public interface RSAMultiPrimePrivateCrtKey extends RSAPrivateKey {
 
     /**
      * the serial version identifier.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = 618058533534628008L;
 
@@ -40,7 +36,6 @@
      * Returns the CRT coefficient, {@code q^-1 mod p}.
      * 
      * @return the CRT coefficient.
-     * @since Android 1.0
      */
     public BigInteger getCrtCoefficient();
 
@@ -49,7 +44,6 @@
      * 
      * @return the information for the additional primes, or {@code null} if
      *         there are only the two primes ({@code p, q}),
-     * @since Android 1.0
      */
     public RSAOtherPrimeInfo[] getOtherPrimeInfo();
 
@@ -57,7 +51,6 @@
      * Returns the prime factor {@code p} of {@code n}.
      * 
      * @return the prime factor {@code p} of {@code n}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeP();
 
@@ -65,7 +58,6 @@
      * Returns the prime factor {@code q} of {@code n}.
      * 
      * @return the prime factor {@code q} of {@code n}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeQ();
 
@@ -73,7 +65,6 @@
      * Returns the CRT exponent of the prime {@code p}.
      * 
      * @return the CRT exponent of the prime {@code p}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeExponentP();
 
@@ -81,7 +72,6 @@
      * Returns the CRT exponent of the prime {@code q}.
      * 
      * @return the CRT exponent of the prime {@code q}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeExponentQ();
 
@@ -89,7 +79,6 @@
      * Returns the public exponent {@code e}.
      * 
      * @return the public exponent {@code e}.
-     * @since Android 1.0
      */
     public BigInteger getPublicExponent();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java b/libcore/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
index 48d70ce..a670491 100644
--- a/libcore/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
@@ -21,15 +21,11 @@
 
 /**
  * The interface for a PKCS#1 RSA private key using CRT information values.
- * 
- * @since Android 1.0
  */
 public interface RSAPrivateCrtKey extends RSAPrivateKey {
 
     /**
      * The serial version identifier.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = -5682214253527700368L;
 
@@ -37,7 +33,6 @@
      * Returns the CRT coefficient, {@code q^-1 mod p}.
      * 
      * @return the CRT coefficient.
-     * @since Android 1.0
      */
     public BigInteger getCrtCoefficient();
 
@@ -45,7 +40,6 @@
      * Returns the prime factor {@code p} of {@code n}.
      * 
      * @return the prime factor {@code p} of {@code n}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeP();
 
@@ -53,7 +47,6 @@
      * Returns the prime factor {@code q} of {@code n}.
      * 
      * @return the prime factor {@code q} of {@code n}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeQ();
 
@@ -61,7 +54,6 @@
      * Returns the CRT exponent of the primet {@code p}.
      * 
      * @return the CRT exponent of the prime {@code p}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeExponentP();
 
@@ -69,7 +61,6 @@
      * Returns the CRT exponent of the prime {@code q}.
      * 
      * @return the CRT exponent of the prime {@code q}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeExponentQ();
 
@@ -77,7 +68,6 @@
      * Returns the public exponent {@code e}.
      * 
      * @return the public exponent {@code e}.
-     * @since Android 1.0
      */
     public BigInteger getPublicExponent();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/RSAPrivateKey.java b/libcore/security/src/main/java/java/security/interfaces/RSAPrivateKey.java
index 041a1e3..0da15e9 100644
--- a/libcore/security/src/main/java/java/security/interfaces/RSAPrivateKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/RSAPrivateKey.java
@@ -22,15 +22,11 @@
 
 /**
  * The interface for an PKCS#1 RSA private key.
- * 
- * @since Android 1.0
  */
 public interface RSAPrivateKey extends PrivateKey, RSAKey {
 
     /**
      * The serial version identifier.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = 5187144804936595022L;
 
@@ -38,7 +34,6 @@
      * Returns the private exponent {@code d}.
      * 
      * @return the private exponent {@code d}.
-     * @since Android 1.0
      */
     public BigInteger getPrivateExponent();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/RSAPublicKey.java b/libcore/security/src/main/java/java/security/interfaces/RSAPublicKey.java
index b13b1aa..379351f 100644
--- a/libcore/security/src/main/java/java/security/interfaces/RSAPublicKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/RSAPublicKey.java
@@ -22,15 +22,11 @@
 
 /**
  * The interface for a PKCS#1 RSA public key.
- * 
- * @since Android 1.0
  */
 public interface RSAPublicKey extends PublicKey, RSAKey {
 
     /**
      * The serial version identifier.
-     * 
-     * @since Android 1.0
      */
     public static final long serialVersionUID = -8727434096241101194L;
 
@@ -38,8 +34,7 @@
      * Returns the public exponent {@code e}.
      * 
      * @return the public exponent {@code e}.
-     * @since Android 1.0
      */
     public BigInteger getPublicExponent();
 
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java b/libcore/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java
index 32c7a3a..0cbba76 100644
--- a/libcore/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java
@@ -20,8 +20,6 @@
 /**
  * The marker interface for algorithm parameter specifications. The purpose is
  * to group parameter specifications for algorithms.
- * 
- * @since Android 1.0
  */
 public interface AlgorithmParameterSpec {
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/spec/DSAParameterSpec.java b/libcore/security/src/main/java/java/security/spec/DSAParameterSpec.java
index 5465b5b..e23a682 100644
--- a/libcore/security/src/main/java/java/security/spec/DSAParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/DSAParameterSpec.java
@@ -22,8 +22,6 @@
 
 /**
  * The parameter specification used with the Digital Signature Algorithm (DSA). 
- * 
- * @since Android 1.0
  */
 public class DSAParameterSpec implements AlgorithmParameterSpec, DSAParams {
     // Prime
@@ -43,7 +41,6 @@
      *            the sub-prime {@code q}.
      * @param g
      *            the base {@code g};
-     * @since Android 1.0
      */
     public DSAParameterSpec(BigInteger p, BigInteger q, BigInteger g) {
         this.p = p;
@@ -55,7 +52,6 @@
      * Returns the base {@code g}.
      * 
      * @return the base {@code g}.
-     * @since Android 1.0
      */
     public BigInteger getG() {
         return g;
@@ -65,7 +61,6 @@
      * Returns the prime {@code p}.
      * 
      * @return the prime {@code p}.
-     * @since Android 1.0
      */
     public BigInteger getP() {
         return p;
@@ -73,8 +68,8 @@
 
     /**
      * Returns the sub-prime {@code q}.
+     * 
      * @return the sub-prime {@code q}.
-     * @since Android 1.0
      */
     public BigInteger getQ() {
         return q;
diff --git a/libcore/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java b/libcore/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java
index 3b692c8..6dc12c8 100644
--- a/libcore/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java
@@ -21,8 +21,6 @@
 
 /**
  * The parameters specifying a DSA private key.
- * 
- * @since Android 1.0
  */
 public class DSAPrivateKeySpec implements KeySpec {
     // Private key
@@ -46,7 +44,6 @@
      *            the sub-prime {@code q}.
      * @param g
      *            the base {@code g}.
-     * @since Android 1.0
      */
     public DSAPrivateKeySpec(BigInteger x, BigInteger p,
             BigInteger q, BigInteger g) {
@@ -60,7 +57,6 @@
      * Returns the base {@code g}.
      * 
      * @return the base {@code g}.
-     * @since Android 1.0
      */
     public BigInteger getG() {
         return g;
@@ -70,7 +66,6 @@
      * Returns the prime {@code p}.
      * 
      * @return the prime {@code p}.
-     * @since Android 1.0
      */
     public BigInteger getP() {
         return p;
@@ -80,7 +75,6 @@
      * Returns the sub-prime {@code q}.
      * 
      * @return the sub-prime {@code q}.
-     * @since Android 1.0
      */
     public BigInteger getQ() {
         return q;
@@ -90,7 +84,6 @@
      * Returns the private key {@code x}.
      * 
      * @return the private key {@code x}.
-     * @since Android 1.0
      */
     public BigInteger getX() {
         return x;
diff --git a/libcore/security/src/main/java/java/security/spec/DSAPublicKeySpec.java b/libcore/security/src/main/java/java/security/spec/DSAPublicKeySpec.java
index 95d1141..af90919 100644
--- a/libcore/security/src/main/java/java/security/spec/DSAPublicKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/DSAPublicKeySpec.java
@@ -21,8 +21,6 @@
 
 /**
  * The parameters specifying a DSA public key.
- * 
- * @since Android 1.0
  */
 public class DSAPublicKeySpec implements KeySpec {
     // Public key
@@ -46,7 +44,6 @@
      *            the sub-prime {@code q}.
      * @param g
      *            the base {@code g}.
-     * @since Android 1.0
      */
     public DSAPublicKeySpec(BigInteger y, BigInteger p,
             BigInteger q, BigInteger g) {
@@ -60,7 +57,6 @@
      * Returns the base {@code g}.
      * 
      * @return the base {@code g}.
-     * @since Android 1.0
      */
     public BigInteger getG() {
         return g;
@@ -70,7 +66,6 @@
      * Returns the prime {@code p}.
      * 
      * @return the prime {@code p}.
-     * @since Android 1.0
      */
     public BigInteger getP() {
         return p;
@@ -80,7 +75,6 @@
      * Returns the sub-prime {@code q}.
      * 
      * @return the sub-prime {@code q}.
-     * @since Android 1.0
      */
     public BigInteger getQ() {
         return q;
@@ -90,7 +84,6 @@
      * Returns the public key value {@code y}.
      * 
      * @return the public key value {@code y}.
-     * @since Android 1.0
      */
     public BigInteger getY() {
         return y;
diff --git a/libcore/security/src/main/java/java/security/spec/ECField.java b/libcore/security/src/main/java/java/security/spec/ECField.java
index 74a5eb8..b4c6be2 100644
--- a/libcore/security/src/main/java/java/security/spec/ECField.java
+++ b/libcore/security/src/main/java/java/security/spec/ECField.java
@@ -19,8 +19,6 @@
 
 /**
  * The base interface for a Finite Field of an Elliptic Curve. 
- * 
- * @since Android 1.0
  */
 public interface ECField {
 
@@ -28,7 +26,6 @@
      * Returns the size of the field (in bits).
      * 
      * @return the size of the field (in bits).
-     * @since Android 1.0
      */
     int getFieldSize();
 }
diff --git a/libcore/security/src/main/java/java/security/spec/ECFieldF2m.java b/libcore/security/src/main/java/java/security/spec/ECFieldF2m.java
index d68378b..e5a636a 100644
--- a/libcore/security/src/main/java/java/security/spec/ECFieldF2m.java
+++ b/libcore/security/src/main/java/java/security/spec/ECFieldF2m.java
@@ -25,8 +25,6 @@
 /**
  * The parameters specifying a <i>characteristic 2 finite field</i> of an
  * elliptic curve.
- * 
- * @since Android 1.0
  */
 public class ECFieldF2m implements ECField {
     // Mid terms array length for trinomial basis
@@ -52,7 +50,6 @@
      *            the exponent {@code m} for the number of elements.
      * @throws IllegalArgumentException
      *             if {@code m <= zero}.
-     * @since Android 1.0
      */
     public ECFieldF2m(int m) {
         this.m = m;
@@ -69,8 +66,7 @@
      * <p>
      * The reduction polynomial must be either <i>trinomial</i> or
      * <i>pentanomial</i>.
-     * </p>
-     * 
+     *
      * @param m
      *            the exponent {@code m} for the number of elements.
      * @param rp
@@ -79,7 +75,6 @@
      *            polynomial.
      * @throws IllegalArgumentException
      *             if {@code m <= zero} or the {@code rp} is invalid.
-     * @since Android 1.0
      */
     public ECFieldF2m(int m, BigInteger rp) {
         this.m = m;
@@ -117,7 +112,6 @@
      * <p>
      * The reduction polynomial must be either <i>trinomial</i> or
      * <i>pentanomial</i>.
-     * </p>
      * 
      * @param m
      *            the exponent {@code m} for the number of elements.
@@ -127,7 +121,6 @@
      * @throws IllegalArgumentException
      *             if {@code m <= zero} or the reduction polynomial is not
      *             valid.
-     * @since Android 1.0
      */
     public ECFieldF2m(int m, int[] ks) {
         this.m = m;
@@ -182,7 +175,6 @@
      *            the object to compare to this finite field.
      * @return {@code true} if the specified object is equal to this finite field,
      *         otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean equals(Object obj) {
         // object equals to itself
@@ -214,7 +206,6 @@
      * Returns the size of this finite field (in bits).
      * 
      * @return the size of this finite field (in bits).
-     * @since Android 1.0
      */
     public int getFieldSize() {
         return m;
@@ -225,7 +216,6 @@
      * the number of elements.
      * 
      * @return the exponent {@code m} for this finite field
-     * @since Android 1.0
      */
     public int getM() {
         return m;
@@ -238,7 +228,6 @@
      * @return a copy of the integer array containing the order of the middle
      *         term(s) of the reduction polynomial for a polynomial basis or
      *         {@code null} for a normal basis.
-     * @since Android 1.0
      */
     public int[] getMidTermsOfReductionPolynomial() {
         // Defensively copies private array
@@ -261,7 +250,6 @@
      * @return the base of the reduction polynomial with the n-th bit
      *         corresponding to the n-th coefficient of the reduction polynomial
      *         for a polynomial basis or {@code null} for a normal basis.
-     * @since Android 1.0
      */
     public BigInteger getReductionPolynomial() {
         return rp;
@@ -271,7 +259,6 @@
      * Returns the hashcode value for this finite field.
      * 
      * @return the hashcode value for this finite field.
-     * @since Android 1.0
      */
     public int hashCode() {
         return rp == null ? m : m + rp.hashCode();
diff --git a/libcore/security/src/main/java/java/security/spec/ECFieldFp.java b/libcore/security/src/main/java/java/security/spec/ECFieldFp.java
index d3f4ee6..b68238d 100644
--- a/libcore/security/src/main/java/java/security/spec/ECFieldFp.java
+++ b/libcore/security/src/main/java/java/security/spec/ECFieldFp.java
@@ -24,8 +24,6 @@
 /**
  * The parameters specifying a <i>prime finite field</i> of an
  * elliptic curve.
- * 
- * @since Android 1.0
  */
 public class ECFieldFp implements ECField {
     // Prime
@@ -39,7 +37,6 @@
      *            the prime value {@code p}.
      * @throws IllegalArgumentException
      *             if {@code p <= zero}.
-     * @since Android 1.0
      */
     public ECFieldFp(BigInteger p) {
         this.p = p;
@@ -56,7 +53,6 @@
      * Returns the size of the finite field (in bits).
      * 
      * @return the size of the finite field (in bits).
-     * @since Android 1.0
      */
     public int getFieldSize() {
         return p.bitLength();
@@ -66,7 +62,6 @@
      * Returns the prime value {@code p} for this finite field.
      * 
      * @return the prime value {@code p} for this finite field.
-     * @since Android 1.0
      */
     public BigInteger getP() {
         return p;
@@ -79,7 +74,6 @@
      *            the object to compare to this finite field.
      * @return {@code true} if the specified object is equal to this finite field,
      *         otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean equals(Object obj) {
         // object equals itself
@@ -96,7 +90,6 @@
      * Returns the hashcode value for this finite field.
      * 
      * @return the hashcode value for this finite field.
-     * @since Android 1.0
      */
     public int hashCode() {
         return p.hashCode();
diff --git a/libcore/security/src/main/java/java/security/spec/ECGenParameterSpec.java b/libcore/security/src/main/java/java/security/spec/ECGenParameterSpec.java
index 210b315..de4cd04 100644
--- a/libcore/security/src/main/java/java/security/spec/ECGenParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/ECGenParameterSpec.java
@@ -21,8 +21,6 @@
 
 /**
  * The parameter specification used to generate elliptic curve domain parameters. 
- * 
- * @since Android 1.0
  */
 public class ECGenParameterSpec implements AlgorithmParameterSpec {
     // Standard (or predefined) name for EC domain
@@ -35,7 +33,6 @@
      * 
      * @param name
      *            the name of the elliptic curve domain parameter.
-     * @since Android 1.0
      */
     public ECGenParameterSpec(String name) {
         this.name = name;
@@ -49,7 +46,6 @@
      * curve domain parameter.
      * 
      * @return the name
-     * @since Android 1.0
      */
     public String getName() {
         return name;
diff --git a/libcore/security/src/main/java/java/security/spec/ECParameterSpec.java b/libcore/security/src/main/java/java/security/spec/ECParameterSpec.java
index e10757b..a1985db 100644
--- a/libcore/security/src/main/java/java/security/spec/ECParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/ECParameterSpec.java
@@ -23,8 +23,6 @@
 
 /**
  * The parameter specification used with Elliptic Curve Cryptography (ECC). 
- * 
- * @since Android 1.0
  */
 public class ECParameterSpec implements AlgorithmParameterSpec {
     // Elliptic curve for which this is parameter
@@ -51,7 +49,6 @@
      *            the co-factor.
      * @throws IllegalArgumentException
      *             if {@code order <= zero} or {@code cofactor <= zero}.
-     * @since Android 1.0
      */
     public ECParameterSpec(EllipticCurve curve, ECPoint generator,
             BigInteger order, int cofactor) {
@@ -84,7 +81,6 @@
      * Returns the {@code cofactor}.
      * 
      * @return the {@code cofactor}.
-     * @since Android 1.0
      */
     public int getCofactor() {
         return cofactor;
@@ -94,7 +90,6 @@
      * Returns the elliptic curve.
      * 
      * @return the elliptic curve.
-     * @since Android 1.0
      */
     public EllipticCurve getCurve() {
         return curve;
@@ -104,7 +99,6 @@
      * Returns the generator (or base point).
      * 
      * @return the generator (or base point).
-     * @since Android 1.0
      */
     public ECPoint getGenerator() {
         return generator;
@@ -114,7 +108,6 @@
      * Returns the order of the generator.
      * 
      * @return the order of the generator.
-     * @since Android 1.0
      */
     public BigInteger getOrder() {
         return order;
diff --git a/libcore/security/src/main/java/java/security/spec/ECPoint.java b/libcore/security/src/main/java/java/security/spec/ECPoint.java
index 3aba6c7..0751757 100644
--- a/libcore/security/src/main/java/java/security/spec/ECPoint.java
+++ b/libcore/security/src/main/java/java/security/spec/ECPoint.java
@@ -23,15 +23,11 @@
 
 /**
  * A Point on an Elliptic Curve in barycentric (or affine) coordinates.  
- * 
- * @since Android 1.0
  */
 public class ECPoint {
 
     /**
      * The point on an Elliptic Curve at infinity.
-     * 
-     * @since Android 1.0
      */
     public static final ECPoint POINT_INFINITY = new ECPoint();
     // affine X coordinate of this point
@@ -52,7 +48,6 @@
      *            the x-coordinate.
      * @param affineY
      *            the y-coordinate.
-     * @since Android 1.0
      */
     public ECPoint(BigInteger affineX, BigInteger affineY) {
         this.affineX = affineX;
@@ -69,7 +64,6 @@
      * Returns the x-coordinate.
      * 
      * @return the x-coordinate, or {@code null} for the infinite point.
-     * @since Android 1.0
      */
     public BigInteger getAffineX() {
         return affineX;
@@ -79,7 +73,6 @@
      * Returns the y-coordinate.
      * 
      * @return the y-coordinate, or {@code null} fot the infinite point.
-     * @since Android 1.0
      */
     public BigInteger getAffineY() {
         return affineY;
@@ -93,7 +86,6 @@
      *            the object to compare.
      * @return {@code true} if the specified object and this elliptic curve
      *         point are equal, otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean equals(Object other) {
         if (this == other) {
@@ -116,7 +108,6 @@
      * Returns the hashcode of this elliptic curve point.
      * 
      * @return the hashcode of this elliptic curve point.
-     * @since Android 1.0
      */
     public int hashCode() {
         if (this.affineX != null) {
diff --git a/libcore/security/src/main/java/java/security/spec/ECPrivateKeySpec.java b/libcore/security/src/main/java/java/security/spec/ECPrivateKeySpec.java
index de778fd..1ddfec3 100644
--- a/libcore/security/src/main/java/java/security/spec/ECPrivateKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/ECPrivateKeySpec.java
@@ -23,8 +23,6 @@
 
 /**
  * The parameters specifying an Elliptic Curve (EC) private key. 
- * 
- * @since Android 1.0
  */
 public class ECPrivateKeySpec implements KeySpec {
     // Private value associated with this key
@@ -40,7 +38,6 @@
      *            the private value {@code S}.
      * @param params
      *            the domain parameter specification.
-     * @since Android 1.0
      */
     public ECPrivateKeySpec(BigInteger s, ECParameterSpec params) {
         this.s = s;
@@ -58,7 +55,6 @@
      * Returns the domain parameter specification.
      * 
      * @return the domain parameter specification.
-     * @since Android 1.0
      */
     public ECParameterSpec getParams() {
         return params;
@@ -68,7 +64,6 @@
      * Returns the private value {@code S}.
      * 
      * @return the private value {@code S}.
-     * @since Android 1.0
      */
     public BigInteger getS() {
         return s;
diff --git a/libcore/security/src/main/java/java/security/spec/ECPublicKeySpec.java b/libcore/security/src/main/java/java/security/spec/ECPublicKeySpec.java
index da182b5..0c88590 100644
--- a/libcore/security/src/main/java/java/security/spec/ECPublicKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/ECPublicKeySpec.java
@@ -21,8 +21,6 @@
 
 /**
  * The parameters specifying an Elliptic Curve (EC) public key. 
- * 
- * @since Android 1.0
  */
 public class ECPublicKeySpec implements KeySpec {
     // The public point
@@ -40,7 +38,6 @@
      *            the domain parameter specification.
      * @throws IllegalArgumentException
      *             if the specified point {@code W} is at infinity.
-     * @since Android 1.0
      */
     public ECPublicKeySpec(ECPoint w, ECParameterSpec params) {
         this.w = w;
@@ -63,7 +60,6 @@
      * Returns the domain parameter specification.
      * 
      * @return the domain parameter specification.
-     * @since Android 1.0
      */
     public ECParameterSpec getParams() {
         return params;
@@ -73,7 +69,6 @@
      * Returns the public elliptic curve point {@code W}.
      * 
      * @return the public elliptic curve point {@code W}.
-     * @since Android 1.0
      */
     public ECPoint getW() {
         return w;
diff --git a/libcore/security/src/main/java/java/security/spec/EllipticCurve.java b/libcore/security/src/main/java/java/security/spec/EllipticCurve.java
index 3ab2921..45ff042 100644
--- a/libcore/security/src/main/java/java/security/spec/EllipticCurve.java
+++ b/libcore/security/src/main/java/java/security/spec/EllipticCurve.java
@@ -24,8 +24,6 @@
 
 /**
  * An Elliptic Curve with its necessary values.
- * 
- * @since Android 1.0
  */
 public class EllipticCurve {
 
@@ -59,7 +57,6 @@
      *            the seed used for the generation of the curve.
      * @throws IllegalArgumentException
      *             if the specified coefficients are not in the specified field.
-     * @since Android 1.0
      */
     public EllipticCurve(ECField field, BigInteger a, BigInteger b, byte[] seed) {
         this.field = field;
@@ -115,7 +112,6 @@
      *            the coefficient {@code b}.
      * @throws IllegalArgumentException
      *             if the specified coefficients are not in the specified field.
-     * @since Android 1.0
      */
     public EllipticCurve(ECField field, BigInteger a, BigInteger b) {
         this(field, a, b, null);
@@ -125,7 +121,6 @@
      * Returns the coefficient {@code a} of this elliptic curve.
      * 
      * @return the coefficient {@code a} of this elliptic curve.
-     * @since Android 1.0
      */
     public BigInteger getA() {
         return a;
@@ -135,7 +130,6 @@
      * Returns the coefficient {@code b} of this elliptic curve.
      * 
      * @return the coefficient {@code b} of this elliptic curve.
-     * @since Android 1.0
      */
     public BigInteger getB() {
         return b;
@@ -145,7 +139,6 @@
      * Returns the finite field of this elliptic curve.
      * 
      * @return the finite field of this elliptic curve.
-     * @since Android 1.0
      */
     public ECField getField() {
         return field;
@@ -156,7 +149,6 @@
      * 
      * @return a copy of the seed that was used to generate this elliptic curve,
      *         or {@code null} if none specified.
-     * @since Android 1.0
      */
     public byte[] getSeed() {
         if (seed == null) {
@@ -176,7 +168,6 @@
      *            the object to compare.
      * @return {@code true} if the specified object is equal to this elliptic
      *         curve, otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean equals(Object other) {
         if (this == other) {
@@ -195,7 +186,6 @@
      * Returns the hashcode of this elliptic curve.
      * 
      * @return the hashcode of this elliptic curve.
-     * @since Android 1.0
      */
     public int hashCode() {
         // hash init is delayed
diff --git a/libcore/security/src/main/java/java/security/spec/EncodedKeySpec.java b/libcore/security/src/main/java/java/security/spec/EncodedKeySpec.java
index f199bca..d34794c 100644
--- a/libcore/security/src/main/java/java/security/spec/EncodedKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/EncodedKeySpec.java
@@ -20,8 +20,6 @@
 /**
  * The abstract key specification for a public or a private key in encoded
  * format.
- * 
- * @since Android 1.0
  */
 public abstract class EncodedKeySpec implements KeySpec {
     // Encoded key
@@ -32,7 +30,6 @@
      * 
      * @param encodedKey
      *            the encoded key bytes.
-     * @since Android 1.0
      */
     public EncodedKeySpec(byte[] encodedKey) {
         // Defensively copies parameter
@@ -46,7 +43,6 @@
      * Returns the encoded key bytes.
      * 
      * @return the encoded key bytes.
-     * @since Android 1.0
      */
     public byte[] getEncoded() {
         // Defensively copies private array
@@ -62,7 +58,6 @@
      * 
      * @return the name of the encoding format of this encoded key
      *         specification.
-     * @since Android 1.0
      */
     public abstract String getFormat();
 }
diff --git a/libcore/security/src/main/java/java/security/spec/InvalidKeySpecException.java b/libcore/security/src/main/java/java/security/spec/InvalidKeySpecException.java
index a83e984..4ae5877 100644
--- a/libcore/security/src/main/java/java/security/spec/InvalidKeySpecException.java
+++ b/libcore/security/src/main/java/java/security/spec/InvalidKeySpecException.java
@@ -22,15 +22,11 @@
 /**
  * The exception that is thrown when an invalid key specification is
  * encountered.
- * 
- * @since Android 1.0
  */
 public class InvalidKeySpecException extends GeneralSecurityException {
 
     /**
      * The serial version identifier.
-     * 
-     * @since Android 1.0
      */
     private static final long serialVersionUID = 3546139293998810778L;
 
@@ -39,7 +35,6 @@
      * 
      * @param msg
      *            the detail message of this exception.
-     * @since Android 1.0
      */
     public InvalidKeySpecException(String msg) {
         super(msg);
@@ -47,8 +42,6 @@
 
     /**
      * Creates a new {@code InvalidKeySpecException}.
-     * 
-     * @since Android 1.0
      */
     public InvalidKeySpecException() {
     }
@@ -61,7 +54,6 @@
      *            the detail message of this exception.
      * @param cause
      *            the cause of this exception.
-     * @since Android 1.0
      */
     public InvalidKeySpecException(String message, Throwable cause) {
         super(message, cause);
@@ -72,7 +64,6 @@
      * 
      * @param cause
      *            the cause of this exception.
-     * @since Android 1.0
      */
     public InvalidKeySpecException(Throwable cause) {
         super(cause);
diff --git a/libcore/security/src/main/java/java/security/spec/InvalidParameterSpecException.java b/libcore/security/src/main/java/java/security/spec/InvalidParameterSpecException.java
index 668fda5..e308dd8 100644
--- a/libcore/security/src/main/java/java/security/spec/InvalidParameterSpecException.java
+++ b/libcore/security/src/main/java/java/security/spec/InvalidParameterSpecException.java
@@ -22,15 +22,11 @@
 /**
  * The exception that is thrown when an invalid parameter specification is
  * encountered.
- * 
- * @since Android 1.0
  */
 public class InvalidParameterSpecException extends GeneralSecurityException {
 
     /**
      * The serial version identifier.
-     * 
-     * @since Android 1.0
      */
     private static final long serialVersionUID = -970468769593399342L;
 
@@ -40,7 +36,6 @@
      * 
      * @param msg
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InvalidParameterSpecException(String msg) {
         super(msg);
@@ -48,9 +43,7 @@
 
     /**
      * Creates a new {@code InvalidParameterSpecException}.
-     * 
-     * @since Android 1.0
      */
     public InvalidParameterSpecException() {
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/spec/KeySpec.java b/libcore/security/src/main/java/java/security/spec/KeySpec.java
index 350a7eb..fe8df1d 100644
--- a/libcore/security/src/main/java/java/security/spec/KeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/KeySpec.java
@@ -20,8 +20,6 @@
 /**
  * The marker interface for key specifications. The purpose is
  * to group key specifications for cryptographic keys.
- * 
- * @since Android 1.0
  */
 public interface KeySpec {
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/spec/MGF1ParameterSpec.java b/libcore/security/src/main/java/java/security/spec/MGF1ParameterSpec.java
index a40f0b3..6475d90 100644
--- a/libcore/security/src/main/java/java/security/spec/MGF1ParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/MGF1ParameterSpec.java
@@ -26,17 +26,12 @@
  * Defined in the <a
  * href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
  * standard
- * </p>
- * 
- * @since Android 1.0
  */
 public class MGF1ParameterSpec implements AlgorithmParameterSpec {
 
     /**
      * The predefined MGF1 parameter specification with an "SHA-1" message
      * digest.
-     * 
-     * @since Android 1.0
      */
     public static final MGF1ParameterSpec SHA1 =
         new MGF1ParameterSpec("SHA-1"); //$NON-NLS-1$
@@ -44,8 +39,6 @@
     /**
      * The predefined MGF1 parameter specification with an "SHA-256" message
      * digest.
-     * 
-     * @since Android 1.0
      */
     public static final MGF1ParameterSpec SHA256 =
         new MGF1ParameterSpec("SHA-256"); //$NON-NLS-1$
@@ -53,8 +46,6 @@
     /**
      * The predefined MGF1 parameter specification with an "SHA-384" message
      * digest.
-     * 
-     * @since Android 1.0
      */
     public static final MGF1ParameterSpec SHA384 =
         new MGF1ParameterSpec("SHA-384"); //$NON-NLS-1$
@@ -62,8 +53,6 @@
     /**
      * The predefined MGF1 parameter specification with an "SHA-512" message
      * digest.
-     * 
-     * @since Android 1.0
      */
     public static final MGF1ParameterSpec SHA512 =
         new MGF1ParameterSpec("SHA-512"); //$NON-NLS-1$
@@ -77,7 +66,6 @@
      * 
      * @param mdName
      *            the name of the message digest algorithm.
-     * @since Android 1.0
      */
     public MGF1ParameterSpec(String mdName) {
         this.mdName = mdName;
@@ -90,7 +78,6 @@
      * Returns the name of the message digest algorithm.
      * 
      * @return the name of the message digest algorithm.
-     * @since Android 1.0
      */
     public String getDigestAlgorithm() {
         return mdName;
diff --git a/libcore/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java b/libcore/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java
index 5cb67b8..6910789 100644
--- a/libcore/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java
@@ -20,8 +20,6 @@
 /**
  * The key specification for an encoded private key in ASN.1 format as defined
  * in the PKCS#8 standard.  
- * 
- * @since Android 1.0
  */
 public class PKCS8EncodedKeySpec extends EncodedKeySpec {    
 
@@ -31,7 +29,6 @@
      * 
      * @param encodedKey
      *            the encoded key bytes.
-     * @since Android 1.0
      */
     public PKCS8EncodedKeySpec(byte[] encodedKey) {
         // Super class' ctor makes defensive parameter copy
@@ -42,7 +39,6 @@
      * Returns a copy of the encoded key bytes.
      * 
      * @return a copy of the encoded key bytes.
-     * @since Android 1.0
      */
     public byte[] getEncoded() {
         // Super class' getEncoded() always returns a new array
@@ -54,7 +50,6 @@
      * specification.
      * 
      * @return the string "PKCS#8".
-     * @since Android 1.0
      */
     public final String getFormat() {
         return "PKCS#8"; //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/spec/PSSParameterSpec.java b/libcore/security/src/main/java/java/security/spec/PSSParameterSpec.java
index c6a5bc5..06c1d05 100644
--- a/libcore/security/src/main/java/java/security/spec/PSSParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/PSSParameterSpec.java
@@ -25,9 +25,6 @@
  * Defined in the <a
  * href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
  * standard.
- * </p>
- * 
- * @since Android 1.0
  */
 public class PSSParameterSpec implements AlgorithmParameterSpec {   
 
@@ -40,8 +37,6 @@
      * <li>salt length: {@code 20}</li>
      * <li>trailer field: {@code -1}</li>
      * </ul>
-     * 
-     * @since Android 1.0
      */
     public static final PSSParameterSpec DEFAULT = new PSSParameterSpec(20);
 
@@ -64,7 +59,6 @@
      *            the salt length (in bits).
      * @throws IllegalArgumentException
      *             if {@code saltLen} is negative.
-     * @since Android 1.0
      */
     public PSSParameterSpec(int saltLen) {
         if (saltLen < 0) {
@@ -94,7 +88,6 @@
      *            the trailer field value.
      * @throws IllegalArgumentException
      *             if {@code saltLen} or {@code trailerField} is negative.
-     * @since Android 1.0
      */
     public PSSParameterSpec(String mdName, String mgfName,
             AlgorithmParameterSpec mgfSpec, int saltLen, int trailerField) {
@@ -122,7 +115,6 @@
      * Returns the length of the salt (in bits).
      * 
      * @return the length of the salt (in bits).
-     * @since Android 1.0
      */
     public int getSaltLength() {
         return saltLen;
@@ -132,7 +124,6 @@
      * Returns the name of the message digest algorithm.
      * 
      * @return the name of the message digest algorithm.
-     * @since Android 1.0
      */
     public String getDigestAlgorithm() {
         return mdName;
@@ -142,7 +133,6 @@
      * Returns the name of the mask generation function algorithm.
      * 
      * @return the name of the mask generation function algorithm.
-     * @since Android 1.0
      */
     public String getMGFAlgorithm() {
         return mgfName;
@@ -153,7 +143,6 @@
      * 
      * @return the parameter for the mask generation function algorithm, or
      *         {@code null} if none specified.
-     * @since Android 1.0
      */
     public AlgorithmParameterSpec getMGFParameters() {
         return mgfSpec;
@@ -163,7 +152,6 @@
      * Returns the trailer field value.
      * 
      * @return the trailer field value.
-     * @since Android 1.0
      */
     public int getTrailerField() {
         return trailerField;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java b/libcore/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java
index 06f3498..2377c75 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java
@@ -21,22 +21,16 @@
 
 /**
  * The parameter specification for generating an RSA key pair. 
- * 
- * @since Android 1.0
  */
 public class RSAKeyGenParameterSpec implements AlgorithmParameterSpec {    
 
     /**
      * The value of the public exponent {@code F0} = 3.
-     * 
-     * @since Android 1.0
      */
     public static final BigInteger F0 = BigInteger.valueOf(3L);
 
     /**
      * The value of the public exponent {@code F4} = 65537.
-     * 
-     * @since Android 1.0
      */
     public static final BigInteger F4 = BigInteger.valueOf(65537L);
 
@@ -53,7 +47,6 @@
      *            the size of the modulus (number of bits).
      * @param publicExponent
      *            the value of the public exponent.
-     * @since Android 1.0
      */
     public RSAKeyGenParameterSpec(int keysize, BigInteger publicExponent) {
         this.keysize = keysize;
@@ -64,7 +57,6 @@
      * Returns the size of the modulus (number of bits).
      * 
      * @return the size of the modulus (number of bits).
-     * @since Android 1.0
      */
     public int getKeysize() {
         return keysize;
@@ -74,7 +66,6 @@
      * Returns the value of the public exponent.
      * 
      * @return the value of the public exponent.
-     * @since Android 1.0
      */
     public BigInteger getPublicExponent() {
         return publicExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java b/libcore/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
index 93e3193..28469d7 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
@@ -28,9 +28,6 @@
  * Defined in the <a
  * href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
  * standard.
- * </p>
- * 
- * @since Android 1.0
  */
 public class RSAMultiPrimePrivateCrtKeySpec extends RSAPrivateKeySpec {
     // Public Exponent
@@ -74,7 +71,6 @@
      *            there are only the two primes ({@code p, q}).
      * @throws IllegalArgumentException
      *             if {@code otherPrimeInfo} is not null but empty.
-     * @since Android 1.0
      */
     public RSAMultiPrimePrivateCrtKeySpec(
             BigInteger modulus,
@@ -139,7 +135,6 @@
      * Returns the CRT coefficient, {@code q^-1 mod p}.
      * 
      * @return the CRT coefficient, {@code q^-1 mod p}.
-     * @since Android 1.0
      */
     public BigInteger getCrtCoefficient() {
         return crtCoefficient;
@@ -150,7 +145,6 @@
      * 
      * @return the information for the additional primes, or {@code null} if
      *         there are only the two primes ({@code p, q}).
-     * @since Android 1.0
      */
     public RSAOtherPrimeInfo[] getOtherPrimeInfo() {
         // Clone array (if not null) to prevent subsequent modification
@@ -168,7 +162,6 @@
      * Returns the exponent of the prime {@code p}.
      * 
      * @return the exponent of the prime {@code p}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeExponentP() {
         return primeExponentP;
@@ -178,7 +171,6 @@
      * Returns the exponent of the prime {@code q}.
      * 
      * @return the exponent of the prime {@code q}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeExponentQ() {
         return primeExponentQ;
@@ -188,7 +180,6 @@
      * Returns the prime factor {@code p}.
      * 
      * @return the prime factor {@code p}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeP() {
         return primeP;
@@ -198,7 +189,6 @@
      * Returns the prime factor {@code q}.
      * 
      * @return the prime factor {@code q}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeQ() {
         return primeQ;
@@ -208,7 +198,6 @@
      * Returns the public exponent {@code e}.
      * 
      * @return the public exponent {@code e}.
-     * @since Android 1.0
      */
     public BigInteger getPublicExponent() {
         return publicExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java b/libcore/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java
index 9b4828e..177ddf5 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java
@@ -28,9 +28,6 @@
  * Defined in the <a
  * href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
  * standard.
- * </p>
- * 
- * @since Android 1.0
  */
 public class RSAOtherPrimeInfo {
     // Prime
@@ -50,7 +47,6 @@
      *            the prime exponent.
      * @param crtCoefficient
      *            the CRT coefficient.
-     * @since Android 1.0
      */
     public RSAOtherPrimeInfo(BigInteger prime,
             BigInteger primeExponent, BigInteger crtCoefficient) {
@@ -72,7 +68,6 @@
      * Returns the CRT coefficient.
      * 
      * @return the CRT coefficient.
-     * @since Android 1.0
      */
     public final BigInteger getCrtCoefficient() {
         return crtCoefficient;
@@ -82,7 +77,6 @@
      * Returns the prime factor.
      * 
      * @return the prime factor.
-     * @since Android 1.0
      */
     public final BigInteger getPrime() {
         return prime;
@@ -92,7 +86,6 @@
      * Returns the exponent.
      * 
      * @return the exponent.
-     * @since Android 1.0
      */
     public final BigInteger getExponent() {
         return primeExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java b/libcore/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java
index 1157099..e786e9e 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java
@@ -26,9 +26,6 @@
  * Defined in the <a
  * href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
  * standard.
- * </p>
- * 
- * @since Android 1.0
  */
 public class RSAPrivateCrtKeySpec extends RSAPrivateKeySpec {    
     // Public Exponent
@@ -65,7 +62,6 @@
      *            the exponent of the prime {@code q}.
      * @param crtCoefficient
      *            the CRT coefficient {@code q^-1 mod p}.
-     * @since Android 1.0
      */
     public RSAPrivateCrtKeySpec(BigInteger modulus,
                                 BigInteger publicExponent,
@@ -90,7 +86,6 @@
      * Returns the CRT coefficient, {@code q^-1 mod p}.
      * 
      * @return the CRT coefficient, {@code q^-1 mod p}.
-     * @since Android 1.0
      */
     public BigInteger getCrtCoefficient() {
         return crtCoefficient;
@@ -100,7 +95,6 @@
      * Returns the exponent of the prime {@code p}.
      * 
      * @return the exponent of the prime {@code p}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeExponentP() {
         return primeExponentP;
@@ -110,7 +104,6 @@
      * Returns the exponent of the prime {@code q}.
      * 
      * @return the exponent of the prime {@code q}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeExponentQ() {
         return primeExponentQ;
@@ -120,7 +113,6 @@
      * Returns the prime factor {@code p}.
      * 
      * @return the prime factor {@code p}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeP() {
         return primeP;
@@ -130,7 +122,6 @@
      * Returns the prime factor {@code q}.
      * 
      * @return the prime factor {@code q}.
-     * @since Android 1.0
      */
     public BigInteger getPrimeQ() {
         return primeQ;
@@ -140,7 +131,6 @@
      * Returns the public exponent {@code e}.
      * 
      * @return the public exponent {@code e}.
-     * @since Android 1.0
      */
     public BigInteger getPublicExponent() {
         return publicExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java b/libcore/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java
index bd7d4e8..c94420e 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java
@@ -25,9 +25,6 @@
  * Defined in the <a
  * href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
  * standard
- * </p>
- * 
- * @since Android 1.0
  */
 public class RSAPrivateKeySpec implements KeySpec {    
     // Modulus
@@ -43,7 +40,6 @@
      *            the modulus {@code n}.
      * @param privateExponent
      *            the private exponent {@code e}
-     * @since Android 1.0
      */
     public RSAPrivateKeySpec(BigInteger modulus, BigInteger privateExponent) {
         this.modulus = modulus;
@@ -54,7 +50,6 @@
      * Returns the modulus {@code n}.
      * 
      * @return the modulus {@code n}.
-     * @since Android 1.0
      */
     public BigInteger getModulus() {
         return modulus;
@@ -64,7 +59,6 @@
      * Returns the private exponent {@code e}.
      * 
      * @return the private exponent {@code e}.
-     * @since Android 1.0
      */
     public BigInteger getPrivateExponent() {
         return privateExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAPublicKeySpec.java b/libcore/security/src/main/java/java/security/spec/RSAPublicKeySpec.java
index bd4c5b5..fe6de07 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAPublicKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAPublicKeySpec.java
@@ -25,8 +25,6 @@
  * Defined in the <a
  * href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
  * standard.
- * </p>
- * @since Android 1.0
  */
 public class RSAPublicKeySpec implements KeySpec {
     // Modulus
@@ -42,7 +40,6 @@
      *            the modulus {@code n}.
      * @param publicExponent
      *            the public exponent {@code d}.
-     * @since Android 1.0
      */
     public RSAPublicKeySpec(BigInteger modulus, BigInteger publicExponent) {
         this.modulus = modulus;
@@ -53,7 +50,6 @@
      * Returns the modulus {@code n}.
      * 
      * @return the modulus {@code n}.
-     * @since Android 1.0
      */
     public BigInteger getModulus() {
         return modulus;
@@ -63,7 +59,6 @@
      * Returns the public exponent {@code d}.
      * 
      * @return the public exponent {@code d}.
-     * @since Android 1.0
      */
     public BigInteger getPublicExponent() {
         return publicExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/X509EncodedKeySpec.java b/libcore/security/src/main/java/java/security/spec/X509EncodedKeySpec.java
index 6cc6104..61f3475 100644
--- a/libcore/security/src/main/java/java/security/spec/X509EncodedKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/X509EncodedKeySpec.java
@@ -19,8 +19,6 @@
 
 /**
  * The key specification of an X.509 encoded key in ASN.1 format.
- * 
- * @since Android 1.0
  */
 public class X509EncodedKeySpec extends EncodedKeySpec {
 
@@ -30,7 +28,6 @@
      * 
      * @param encodedKey
      *            the encoded key bytes.
-     * @since Android 1.0
      */
     public X509EncodedKeySpec(byte[] encodedKey) {
         // Super class' ctor makes defensive parameter copy
@@ -41,7 +38,6 @@
      * Returns the encoded key bytes.
      * 
      * @return the encoded key bytes.
-     * @since Android 1.0
      */
     public byte[] getEncoded() {
         // Super class' getEncoded() always returns a new array
@@ -53,7 +49,6 @@
      * specification.
      * 
      * @return the string "X.509".
-     * @since Android 1.0
      */
     public final String getFormat() {
         return "X.509"; //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/javax/security/cert/Certificate.java b/libcore/security/src/main/java/javax/security/cert/Certificate.java
index fb00789..ef513a3 100644
--- a/libcore/security/src/main/java/javax/security/cert/Certificate.java
+++ b/libcore/security/src/main/java/javax/security/cert/Certificate.java
@@ -29,34 +29,30 @@
 /**
  * Abstract class to represent identity certificates. It represents a way to
  * verify the binding of a Principal and its public key. Examples are X.509,
- * PGP, and SDSI. 
+ * PGP, and SDSI.
  * <p>
  * Note: This package is provided only for compatibility reasons.
  * It contains a simplified version of the java.security.cert package that was
  * previously used by JSSE (Java SSL package). All applications that do not have
  * to be compatible with older versions of JSSE (that is before Java SDK 1.5)
  * should only use java.security.cert.
- * </p>
- * @since Android 1.0
  */
 public abstract class Certificate {
 
     /**
      * Creates a new {@code Certificate}.
-     * @since Android 1.0
      */
     public Certificate() {}
 
     /**
      * Compares the argument to this Certificate. If both have the same bytes
      * they are assumed to be equal.
-     * 
+     *
      * @param obj
      *            the {@code Certificate} to compare with this object
      * @return <code>true</code> if {@code obj} is the same as this
      *         {@code Certificate}, <code>false</code> otherwise
      * @see #hashCode
-     * @since Android 1.0
      */
     public boolean equals(Object obj) {
         if (obj == this) {
@@ -77,10 +73,9 @@
      * Returns an integer hash code for the receiver. Any two objects which
      * return <code>true</code> when passed to <code>equals</code> must answer
      * the same value for this method.
-     * 
+     *
      * @return the receiver's hash
      * @see #equals
-     * @since Android 1.0
      */
     public int hashCode() {
         int res = 0;
@@ -96,18 +91,17 @@
 
     /**
      * Returns the encoded representation for this certificate.
-     * 
+     *
      * @return the encoded representation for this certificate.
      * @throws CertificateEncodingException
      *             if encoding fails.
-     * @since Android 1.0
      */
     public abstract byte[] getEncoded()
             throws CertificateEncodingException;
 
     /**
      * Verifies that this certificate was signed with the given public key.
-     * 
+     *
      * @param key
      *            public key for which verification should be performed.
      * @throws CertificateException
@@ -120,7 +114,6 @@
      *             if there is no default provider
      * @throws SignatureException
      *             if signature errors are detected
-     * @since Android 1.0
      */
     public abstract void verify(PublicKey key)
             throws CertificateException, NoSuchAlgorithmException,
@@ -130,7 +123,7 @@
     /**
      * Verifies that this certificate was signed with the given public key. Uses
      * the signature algorithm given by the provider.
-     * 
+     *
      * @param key
      *            public key for which verification should be performed.
      * @param sigProvider
@@ -145,7 +138,6 @@
      *                if the specified provider does not exists.
      * @exception SignatureException
      *                if signature errors are detected
-     * @since Android 1.0
      */
     public abstract void verify(PublicKey key, String sigProvider)
             throws CertificateException, NoSuchAlgorithmException, 
@@ -155,17 +147,15 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * receiver.
-     * 
+     *
      * @return a printable representation for the receiver.
-     * @since Android 1.0
      */
     public abstract String toString();
 
     /**
      * Returns the public key corresponding to this certificate.
-     * 
+     *
      * @return the public key corresponding to this certificate.
-     * @since Android 1.0
      */
     public abstract PublicKey getPublicKey();
 }
diff --git a/libcore/security/src/main/java/javax/security/cert/CertificateEncodingException.java b/libcore/security/src/main/java/javax/security/cert/CertificateEncodingException.java
index 4091695..780e43f 100644
--- a/libcore/security/src/main/java/javax/security/cert/CertificateEncodingException.java
+++ b/libcore/security/src/main/java/javax/security/cert/CertificateEncodingException.java
@@ -27,20 +27,20 @@
  * by JSSE (Java SSL package). All applications that do not have to be
  * compatible with older versions of JSSE (that is before Java SDK 1.5) should
  * only use java.security.cert.
- * </p>
- * @since Android 1.0
  */
 public class CertificateEncodingException extends CertificateException {
 
+    /**
+     * @serial
+     */
     private static final long serialVersionUID = -8187642723048403470L;
 
     /**
      * Creates a new {@code CertificateEncodingException} with the specified
      * message.
-     * 
+     *
      * @param msg
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public CertificateEncodingException(String msg) {
         super(msg);
@@ -48,9 +48,7 @@
 
     /**
      * Creates a new {@code CertificateEncodingException}.
-     * 
-     * @since Android 1.0
      */
     public CertificateEncodingException() {
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/javax/security/cert/CertificateException.java b/libcore/security/src/main/java/javax/security/cert/CertificateException.java
index f186e51..fd2a614 100644
--- a/libcore/security/src/main/java/javax/security/cert/CertificateException.java
+++ b/libcore/security/src/main/java/javax/security/cert/CertificateException.java
@@ -26,19 +26,19 @@
  * by JSSE (Java SSL package). All applications that do not have to be
  * compatible with older versions of JSSE (that is before Java SDK 1.5) should
  * only use java.security.cert.
- * </p>
- * @since Android 1.0
  */
 public class CertificateException extends Exception {
 
+    /**
+     * @serial
+     */
     private static final long serialVersionUID = -5757213374030785290L;
 
     /**
      * Creates a new {@code CertificateException} with the specified message.
-     * 
+     *
      * @param msg
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public CertificateException(String msg) {
         super(msg);
@@ -46,9 +46,7 @@
 
     /**
      * Creates a new {@code CertificateException}.
-     * 
-     * @since Android 1.0
      */
     public CertificateException() {
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/javax/security/cert/CertificateExpiredException.java b/libcore/security/src/main/java/javax/security/cert/CertificateExpiredException.java
index 62870a6..94e6558 100644
--- a/libcore/security/src/main/java/javax/security/cert/CertificateExpiredException.java
+++ b/libcore/security/src/main/java/javax/security/cert/CertificateExpiredException.java
@@ -25,20 +25,20 @@
  * by JSSE (Java SSL package). All applications that do not have to be
  * compatible with older versions of JSSE (that is before Java SDK 1.5) should
  * only use java.security.cert.
- * </p>
- * @since Android 1.0
  */
 public class CertificateExpiredException extends CertificateException {
 
+    /**
+     * @serial
+     */
     private static final long serialVersionUID = 5091601212177261883L;
 
     /**
      * Creates a new {@code CertificateExpiredException} with the specified
      * message.
-     * 
+     *
      * @param msg
      *            the detail message for this exception
-     * @since Android 1.0
      */
     public CertificateExpiredException(String msg) {
         super(msg);
@@ -46,9 +46,7 @@
 
     /**
      * Creates a new {@code CertificateExpiredException}.
-     * 
-     * @since Android 1.0
      */
     public CertificateExpiredException() {
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java b/libcore/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java
index 6f32945..8fe0a33 100644
--- a/libcore/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java
+++ b/libcore/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java
@@ -25,20 +25,20 @@
  * by JSSE (Java SSL package). All applications that do not have to be
  * compatible with older versions of JSSE (that is before Java SDK 1.5) should
  * only use java.security.cert.
- * </p>
- * @since Android 1.0
  */
 public class CertificateNotYetValidException extends CertificateException {
 
+    /**
+     * @serial
+     */
     private static final long serialVersionUID = -8976172474266822818L;
 
     /**
      * Creates a new {@code CertificateNotYetValidException} with the specified
      * message.
-     * 
+     *
      * @param msg
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public CertificateNotYetValidException(String msg) {
         super(msg);
@@ -46,9 +46,7 @@
 
     /**
      * Creates a new {@code CertificateNotYetValidException}.
-     * 
-     * @since Android 1.0
      */
     public CertificateNotYetValidException() {
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/javax/security/cert/CertificateParsingException.java b/libcore/security/src/main/java/javax/security/cert/CertificateParsingException.java
index 9b208e6..48986c0 100644
--- a/libcore/security/src/main/java/javax/security/cert/CertificateParsingException.java
+++ b/libcore/security/src/main/java/javax/security/cert/CertificateParsingException.java
@@ -25,20 +25,20 @@
  * by JSSE (Java SSL package). All applications that do not have to be
  * compatible with older versions of JSSE (that is before Java SDK 1.5) should
  * only use java.security.cert.
- * </p>
- * @since Android 1.0
  */
 public class CertificateParsingException extends CertificateException {
 
+    /**
+     * @serial
+     */
     private static final long serialVersionUID = -8449352422951136229L;
 
     /**
      * Creates a new {@code CertificateParsingException} with the specified
      * message.
-     * 
+     *
      * @param msg
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public CertificateParsingException(String msg) {
         super(msg);
@@ -46,9 +46,7 @@
 
     /**
      * Creates a new {@code CertificateParsingException}.
-     * 
-     * @since Android 1.0
      */
     public CertificateParsingException() {
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/javax/security/cert/X509Certificate.java b/libcore/security/src/main/java/javax/security/cert/X509Certificate.java
index 77bffae..8877386 100644
--- a/libcore/security/src/main/java/javax/security/cert/X509Certificate.java
+++ b/libcore/security/src/main/java/javax/security/cert/X509Certificate.java
@@ -44,15 +44,12 @@
  * <p>
  * This represents a standard way for accessing the attributes of X.509 v1
  * certificates.
- * </p>
  * <p>
  * Note: This package is provided only for compatibility reasons.
  * It contains a simplified version of the java.security.cert package that was
  * previously used by JSSE (Java SSL package). All applications that do not have
  * to be compatible with older versions of JSSE (that is before Java SDK 1.5)
  * should only use java.security.cert.
- * </p>
- * @since Android 1.0
  */
 public abstract class X509Certificate extends Certificate {
 
@@ -76,8 +73,6 @@
     
     /**
      * Creates a new {@code X509Certificate}.
-     * 
-     * @since Android 1.0
      */
     public X509Certificate() {
         super();
@@ -86,13 +81,12 @@
     /**
      * Creates a new {@code X509Certificate} and initializes it from the
      * specified input stream.
-     * 
+     *
      * @param inStream
      *            input stream containing data to initialize the certificate.
      * @return the certificate initialized from the specified input stream
      * @throws CertificateException
      *             if the certificate cannot be created or initialized.
-     * @since Android 1.0
      */
     public static final X509Certificate getInstance(InputStream inStream)
                                              throws CertificateException {
@@ -220,13 +214,12 @@
     /**
      * Creates a new {@code X509Certificate} and initializes it from the
      * specified byte array.
-     * 
+     *
      * @param certData
      *            byte array containing data to initialize the certificate.
      * @return the certificate initialized from the specified byte array
      * @throws CertificateException
      *             if the certificate cannot be created or initialized.
-     * @since Android 1.0
      */
     public static final X509Certificate getInstance(byte[] certData)
                                              throws CertificateException {
@@ -241,26 +234,23 @@
      * Checks whether the certificate is currently valid.
      * <p>
      * The validity defined in ASN.1:
-     * 
+     *
      * <pre>
      * validity             Validity
-     * 
-     * Validity ::= SEQUENCE { 
-     *      notBefore       CertificateValidityDate, 
+     *
+     * Validity ::= SEQUENCE {
+     *      notBefore       CertificateValidityDate,
      *      notAfter        CertificateValidityDate }
-     * 
-     * CertificateValidityDate ::= CHOICE { 
-     *      utcTime         UTCTime, 
+     *
+     * CertificateValidityDate ::= CHOICE {
+     *      utcTime         UTCTime,
      *      generalTime     GeneralizedTime }
      * </pre>
-     * 
-     * </p>
-     * 
+     *
      * @throws CertificateExpiredException
      *             if the certificate has expired.
      * @throws CertificateNotYetValidException
      *             if the certificate is not yet valid.
-     * @since Android 1.0
      */
     public abstract void checkValidity()
             throws CertificateExpiredException, CertificateNotYetValidException;
@@ -268,7 +258,7 @@
 
     /**
      * Checks whether the certificate is valid at the specified date.
-     * 
+     *
      * @param date
      *            the date to check the validity against.
      * @throws CertificateExpiredException
@@ -276,7 +266,6 @@
      * @throws CertificateNotYetValidException
      *             if the certificate is not yet valid.
      * @see #checkValidity()
-     * @since Android 1.0
      */
     public abstract void checkValidity(Date date)
             throws CertificateExpiredException, CertificateNotYetValidException;
@@ -285,15 +274,12 @@
      * Returns the certificates {@code version} (version number).
      * <p>
      * The version defined is ASN.1:
-     * 
+     *
      * <pre>
      * Version ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
      * </pre>
-     * 
-     * </p>
-     * 
+     *
      * @return the version number.
-     * @since Android 1.0
      */
     public abstract int getVersion();
 
@@ -301,15 +287,12 @@
      * Returns the {@code serialNumber} of the certificate.
      * <p>
      * The ASN.1 definition of {@code serialNumber}:
-     * 
+     *
      * <pre>
      * CertificateSerialNumber  ::=  INTEGER
      * </pre>
-     * 
-     * </p>
-     * 
+     *
      * @return the serial number.
-     * @since Android 1.0
      */
     public abstract BigInteger getSerialNumber();
 
@@ -318,31 +301,28 @@
      * implementation specific {@code Principal} object.
      * <p>
      * The ASN.1 definition of {@code issuer}:
-     * 
+     *
      * <pre>
      *  issuer      Name
-     * 
+     *
      *  Name ::= CHOICE {
      *      RDNSequence }
-     * 
+     *
      *    RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
-     * 
+     *
      *    RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
-     * 
+     *
      *    AttributeTypeAndValue ::= SEQUENCE {
      *      type     AttributeType,
      *      value    AttributeValue }
-     * 
+     *
      *    AttributeType ::= OBJECT IDENTIFIER
-     * 
+     *
      *    AttributeValue ::= ANY DEFINED BY AttributeType
      * </pre>
-     * 
-     * </p>
-     * 
+     *
      * @return the {@code issuer} as an implementation specific {@code
      *         Principal}.
-     * @since Android 1.0
      */
     public abstract Principal getIssuerDN();
 
@@ -351,73 +331,65 @@
      * implementation specific {@code Principal} object.
      * <p>
      * The ASN.1 definition of {@code subject}:
-     * 
+     *
      * <pre>
      * subject      Name
-     * 
+     *
      *  Name ::= CHOICE {
      *      RDNSequence }
-     * 
+     *
      *    RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
-     * 
+     *
      *    RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
-     * 
+     *
      *    AttributeTypeAndValue ::= SEQUENCE {
      *      type     AttributeType,
      *      value    AttributeValue }
-     * 
+     *
      *    AttributeType ::= OBJECT IDENTIFIER
-     * 
+     *
      *    AttributeValue ::= ANY DEFINED BY AttributeType
      * </pre>
-     * 
-     * </p>
-     * 
+     *
      * @return the {@code subject} (subject distinguished name).
-     * @since Android 1.0
      */
     public abstract Principal getSubjectDN();
 
     /**
      * Returns the {@code notBefore} date from the validity period of the
      * certificate.
-     * 
+     *
      * @return the start of the validity period.
-     * @since Android 1.0
      */
     public abstract Date getNotBefore();
 
     /**
      * Returns the {@code notAfter} date of the validity period of the
      * certificate.
-     * 
+     *
      * @return the end of the validity period.
-     * @since Android 1.0
      */
     public abstract Date getNotAfter();
 
     /**
      * Returns the name of the algorithm for the certificate signature.
-     * 
+     *
      * @return the signature algorithm name.
-     * @since Android 1.0
      */
     public abstract String getSigAlgName();
 
     /**
      * Returns the OID of the signature algorithm from the certificate.
-     * 
+     *
      * @return the OID of the signature algorithm.
-     * @since Android 1.0
      */
     public abstract String getSigAlgOID();
 
     /**
      * Returns the parameters of the signature algorithm in DER-encoded format.
-     * 
+     *
      * @return the parameters of the signature algorithm, or null if none are
      *         used.
-     * @since Android 1.0
      */
     public abstract byte[] getSigAlgParams();
 }
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java b/libcore/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java
index ba3229b..afab96e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java
@@ -127,9 +127,9 @@
                 break parsing;
 
             case StreamTokenizer.TT_WORD:
-                if ("keystore".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+                if (Util.equalsIgnoreCase("keystore", st.sval)) { //$NON-NLS-1$
                     keystoreEntries.add(readKeystoreEntry(st));
-                } else if ("grant".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+                } else if (Util.equalsIgnoreCase("grant", st.sval)) { //$NON-NLS-1$
                     grantEntries.add(readGrantEntry(st));
                 } else {
                     handleUnexpectedToken(st, Messages.getString("security.89")); //$NON-NLS-1$
@@ -208,19 +208,19 @@
             switch (st.nextToken()) {
 
             case StreamTokenizer.TT_WORD:
-                if ("signedby".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+                if (Util.equalsIgnoreCase("signedby", st.sval)) { //$NON-NLS-1$
                     if (st.nextToken() == '"') {
                         ge.signers = st.sval;
                     } else {
                         handleUnexpectedToken(st, Messages.getString("security.8B")); //$NON-NLS-1$
                     }
-                } else if ("codebase".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+                } else if (Util.equalsIgnoreCase("codebase", st.sval)) { //$NON-NLS-1$
                     if (st.nextToken() == '"') {
                         ge.codebase = st.sval;
                     } else {
                         handleUnexpectedToken(st, Messages.getString("security.8C")); //$NON-NLS-1$
                     }
-                } else if ("principal".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+                } else if (Util.equalsIgnoreCase("principal", st.sval)) { //$NON-NLS-1$
                     ge.addPrincipal(readPrincipalEntry(st));
                 } else {
                     handleUnexpectedToken(st);
@@ -308,7 +308,7 @@
             switch (st.nextToken()) {
 
             case StreamTokenizer.TT_WORD:
-                if ("permission".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+                if (Util.equalsIgnoreCase("permission", st.sval)) { //$NON-NLS-1$
                     PermissionEntry pe = new PermissionEntry();
                     if (st.nextToken() == StreamTokenizer.TT_WORD) {
                         pe.klass = st.sval;
@@ -326,7 +326,7 @@
                             }
                         }
                         if (st.ttype == StreamTokenizer.TT_WORD
-                                && "signedby".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+                                && Util.equalsIgnoreCase("signedby", st.sval)) { //$NON-NLS-1$
                             if (st.nextToken() == '"') {
                                 pe.signers = st.sval;
                             } else {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/PolicyEntry.java b/libcore/security/src/main/java/org/apache/harmony/security/PolicyEntry.java
index 4c7aa5b..0037ad6 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/PolicyEntry.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/PolicyEntry.java
@@ -22,6 +22,8 @@
 
 package org.apache.harmony.security;
 
+import java.net.URL;
+import java.security.CodeSigner;
 import java.security.CodeSource;
 import java.security.Permission;
 import java.security.Principal;
@@ -30,7 +32,6 @@
 
 import org.apache.harmony.security.fortress.PolicyUtils;
 
-
 /**
  * This class represents an elementary block of a security policy. It associates
  * a CodeSource of an executable code, Principals allowed to execute the code,
@@ -55,7 +56,7 @@
      */
     public PolicyEntry(CodeSource cs, Collection<? extends Principal> prs,
             Collection<? extends Permission> permissions) {
-        this.cs = cs;
+        this.cs = (cs != null) ? normalizeCodeSource(cs) : null;
         this.principals = (prs == null || prs.isEmpty()) ? null
                 : (Principal[]) prs.toArray(new Principal[prs.size()]);
         this.permissions = (permissions == null || permissions.isEmpty()) ? null
@@ -68,7 +69,31 @@
      * imply() method.
      */
     public boolean impliesCodeSource(CodeSource codeSource) {
-        return (cs == null) ? true : cs.implies(codeSource);
+        if (cs == null) {
+            return true;
+        }
+
+        if (codeSource == null) {
+            return false;
+        }
+        return cs.implies(normalizeCodeSource(codeSource));
+    }
+
+    private CodeSource normalizeCodeSource(CodeSource codeSource) {
+        URL codeSourceURL = PolicyUtils.normalizeURL(codeSource.getLocation());
+        CodeSource result = codeSource;
+
+        if (codeSourceURL != codeSource.getLocation()) {
+            // URL was normalized - recreate codeSource with new URL
+            CodeSigner[] signers = codeSource.getCodeSigners();
+            if (signers == null) {
+                result = new CodeSource(codeSourceURL, codeSource
+                        .getCertificates());
+            } else {
+                result = new CodeSource(codeSourceURL, signers);
+            }
+        }
+        return result;
     }
 
     /**
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/Util.java b/libcore/security/src/main/java/org/apache/harmony/security/Util.java
new file mode 100644
index 0000000..e6e764f
--- /dev/null
+++ b/libcore/security/src/main/java/org/apache/harmony/security/Util.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.security;
+
+public class Util {
+
+    public static String toUpperCase(String s) {
+        return org.apache.harmony.luni.util.Util.toASCIIUpperCase(s);
+    }
+
+    public static boolean equalsIgnoreCase(String s1, String s2) {
+        s1 = org.apache.harmony.luni.util.Util.toASCIIUpperCase(s1);
+        s2 = org.apache.harmony.luni.util.Util.toASCIIUpperCase(s2);
+        return s1.equals(s2);
+    }
+}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java
index 1f5534d..e8db789 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java
@@ -25,6 +25,7 @@
 import java.math.BigInteger;
 import java.util.Arrays;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.TreeMap;
 
 import org.apache.harmony.security.internal.nls.Messages;
@@ -269,12 +270,14 @@
         // fill identifiers array
         int size = map.size();
         identifiers = new int[2][size];
-        Iterator it = map.keySet().iterator();
+        Iterator it = map.entrySet().iterator();
+
         for (int i = 0; i < size; i++) {
-            BigInteger identifier = (BigInteger) it.next();
+        	Map.Entry entry = (Map.Entry) it.next();
+            BigInteger identifier = (BigInteger) entry.getKey();
 
             identifiers[0][i] = identifier.intValue();
-            identifiers[1][i] = ((BigInteger) map.get(identifier)).intValue();
+            identifiers[1][i] = ((BigInteger) entry.getValue()).intValue();
         }
 
         this.type = type;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
index 4ec103b..4908afb 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
@@ -23,6 +23,7 @@
 package org.apache.harmony.security.asn1;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.text.SimpleDateFormat;
 import java.util.TimeZone;
 
@@ -30,10 +31,7 @@
 /**
  * This class represents ASN.1 GeneralizedTime type.
  * 
- * According to X.680 specification this type is defined as follows:
- *     GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT VisibleString
- * 
- * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a>
+ * @see http://asn1.elibel.tm.fr/en/standards/index.htm
  */
 
 public class ASN1GeneralizedTime extends ASN1Time {
@@ -114,7 +112,13 @@
         if (temp.charAt(currLength) == '.') {
             temp = temp.substring(0, currLength);
         }
-        out.content = (temp + "Z").getBytes(); //$NON-NLS-1$
+
+        try {
+            out.content = (temp + "Z").getBytes("UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e.getMessage());
+        }
+        
         out.length = ((byte[]) out.content).length;
     }
 }
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java
index 6292870..960dc0f 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java
@@ -154,7 +154,7 @@
 
         public Object getDecodedObject(BerInputStream in) throws IOException {
 
-            StringBuffer buf = new StringBuffer();
+            StringBuilder buf = new StringBuilder();
 
             int element;
 
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
index 55f48fa..0bc4b8a 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
@@ -118,7 +118,9 @@
      * @return java.land.String object
      */
     public Object getDecodedObject(BerInputStream in) throws IOException {
-        return new String(in.buffer, in.contentOffset, in.length);
+        /* To ensure we get the correct encoding on non-ASCII platforms, specify
+           that we wish to convert from ASCII to the default platform encoding */
+        return new String(in.buffer, in.contentOffset, in.length, "ISO-8859-1");
     }
 
     //
@@ -137,11 +139,15 @@
     }
 
     public void setEncodingContent(BerOutputStream out) {
-
-        byte[] bytes = ((String) out.content).getBytes();
-
-        out.content = bytes;
-        out.length = bytes.length;
+        try {
+            byte[] bytes = ((String) out.content).getBytes("UTF-8"); //$NON-NLS-1$
+            out.content = bytes;
+            out.length = bytes.length;
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e.getMessage());
+        }
     }
 }
 
+
+
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
index 0dd7ae4..3d2cb3e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
@@ -23,6 +23,7 @@
 package org.apache.harmony.security.asn1;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.text.SimpleDateFormat;
 import java.util.TimeZone;
 
@@ -30,10 +31,7 @@
 /**
  * This class represents ASN.1 UTCTime type
  * 
- * According to X.680 specification this type is defined as follows:
- *     UTCTime ::= [UNIVERSAL 23] IMPLICIT VisibleString
- * 
- * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a>
+ * @see http://asn1.elibel.tm.fr/en/standards/index.htm
  */
 public class ASN1UTCTime extends ASN1Time {
 
@@ -118,7 +116,11 @@
     public void setEncodingContent(BerOutputStream out) {
         SimpleDateFormat sdf = new SimpleDateFormat(UTC_PATTERN);
         sdf.setTimeZone(TimeZone.getTimeZone("UTC")); //$NON-NLS-1$
-        out.content = sdf.format(out.content).getBytes();
+        try {
+            out.content = sdf.format(out.content).getBytes("UTF-8"); //$NON-NLS-1$
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e.getMessage());
+        }
         out.length = ((byte[]) out.content).length;
     }
 }
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java
index 68819b8..531d760 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java
@@ -25,7 +25,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Calendar;
 
 import org.apache.harmony.security.internal.nls.Messages;
 
@@ -132,8 +131,8 @@
         if (length != INDEFINIT_LENGTH) {
             // input stream has definite length encoding
             // check allocated length to avoid further reallocations
-            if (buffer.length < length) {
-                byte[] newBuffer = new byte[length];
+            if (buffer.length < (length + offset)) {
+                byte[] newBuffer = new byte[length + offset];
                 System.arraycopy(buffer, 0, newBuffer, 0, offset);
                 buffer = newBuffer;
             }
@@ -916,9 +915,22 @@
         if (in == null) {
             offset += length;
         } else {
-            if (in.read(buffer, offset, length) != length) {
-                throw new ASN1Exception(Messages.getString("security.13C")); //$NON-NLS-1$
+            int bytesRead = in.read(buffer, offset, length);
+
+            if (bytesRead != length) {
+                // if input stream didn't return all data at once
+                // try to read it in several blocks
+                int c = bytesRead;
+                do {
+                    if (c < 1 || bytesRead > length) {
+                        throw new ASN1Exception(Messages
+                                .getString("security.13C")); //$NON-NLS-1$
+                    }
+                    c = in.read(buffer, offset + bytesRead, length - bytesRead);
+                    bytesRead += c;
+                } while (bytesRead != length);
             }
+
             offset += length;
         }
     }
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java
index 2a267e5..06ada53 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java
@@ -95,7 +95,7 @@
         return intHash & 0x7FFFFFFF; // only positive
     }
 
-    private class Entry {
+    private static class Entry {
         public int[] oid;
 
         public Object object;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java
index 0e7269a..0d3a77a 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java
@@ -243,7 +243,7 @@
      * @return oid string representation
      */
     public static String toString(int[] oid) {
-        StringBuffer sb = new StringBuffer(3 * oid.length);
+        StringBuilder sb = new StringBuilder(3 * oid.length);
 
         for (int i = 0; i < oid.length - 1; ++i) {
             sb.append(oid[i]);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java b/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java
index 2aa474e..df425a4 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java
@@ -163,7 +163,7 @@
 
     // A flag indicating brand new instance which needs to be loaded
     // on the first appeal to it's data.
-    private boolean initiailized;
+    private boolean initialized;
 
     /**
      * Default constructor, equivalent to
@@ -180,7 +180,7 @@
      */
     public DefaultPolicy(DefaultPolicyParser dpr) {
         parser = dpr;
-        initiailized = false;
+        initialized = false;
         refresh();
     }
 
@@ -191,9 +191,9 @@
      * to be <code>null</code> if the domain is <code>null</code>.
      */
     public PermissionCollection getPermissions(ProtectionDomain pd) {
-        if (!initiailized) {
+        if (!initialized) {
             synchronized (this) {
-                if (!initiailized) {
+                if (!initialized) {
                     refresh();
                 }
             }
@@ -230,9 +230,9 @@
      * The evaluation assumes that current principals are undefined.
      */
     public PermissionCollection getPermissions(CodeSource cs) {
-        if (!initiailized) {
+        if (!initialized) {
             synchronized (this) {
-                if (!initiailized) {
+                if (!initialized) {
                     refresh();
                 }
             }
@@ -306,6 +306,6 @@
 
             cache.clear();
         }
-        initiailized = true;
+        initialized = true;
     }
 }
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java b/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java
index fafa66c..c809fe4 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java
@@ -25,7 +25,6 @@
 import java.io.BufferedReader;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.io.File;
 import java.io.Reader;
 import java.net.URL;
 import java.security.cert.Certificate;
@@ -62,8 +61,7 @@
  * a pluggable scanner and converts received tokens to a set of 
  * {@link org.apache.harmony.security.PolicyEntry PolicyEntries}. 
  * For details of policy format, see the 
- * {@link org.apache.harmony.security.fortress.DefaultPolicy default policy
- * description}.
+ * {@link org.apache.harmony.security.DefaultPolicy default policy description}.
  * <br>
  * For ordinary uses, this class has just one public method <code>parse()</code>, 
  * which performs the main task.
@@ -73,7 +71,7 @@
  * This implementation is effectively thread-safe, as it has no field references 
  * to data being processed (that is, passes all the data as method parameters).
  * 
- * @see org.apache.harmony.security.fortress.DefaultPolicy
+ * @see org.apache.harmony.security.DefaultPolicy
  * @see org.apache.harmony.security.DefaultPolicyScanner
  * @see org.apache.harmony.security.PolicyEntry
  */
@@ -188,7 +186,7 @@
      * of the GrantEntry
      * @see DefaultPolicyScanner.PrincipalEntry
      * @see DefaultPolicyScanner.PermissionEntry
-     * @see org.apache.harmony.security.fortress.PolicyUtils
+     * @see org.apache.harmony.security.PolicyUtils
      */
     protected PolicyEntry resolveGrant(DefaultPolicyScanner.GrantEntry ge,
             KeyStore ks, Properties system, boolean resolve) throws Exception {
@@ -200,14 +198,6 @@
         if (ge.codebase != null) {
             codebase = new URL(resolve ? PolicyUtils.expandURL(ge.codebase,
                     system) : ge.codebase);
-            //Fix HARMONY-1963
-            if ("file".equals(codebase.getProtocol())) { //$NON-NLS-1$
-                File codeFile = new File(codebase.getFile());
-                if (codeFile.isAbsolute()) {
-                    codebase = new URL("file://" +  //$NON-NLS-1$
-                            codeFile.getAbsolutePath());                    
-                }
-            }
         }
         if (ge.signers != null) {
             if (resolve) {
@@ -342,7 +332,7 @@
             if ("self".equals(protocol)) { //$NON-NLS-1$
                 //need expanding to list of principals in grant clause 
                 if (ge.principals != null && ge.principals.size() != 0) {
-                    StringBuffer sb = new StringBuffer();
+                    StringBuilder sb = new StringBuilder();
                     for (Iterator<PrincipalEntry> iter = ge.principals.iterator(); iter
                             .hasNext();) {
                         DefaultPolicyScanner.PrincipalEntry pr = iter
@@ -385,7 +375,7 @@
         private String pc2str(Principal pc) {
             String klass = pc.getClass().getName();
             String name = pc.getName();
-            StringBuffer sb = new StringBuffer(klass.length() + name.length()
+            StringBuilder sb = new StringBuilder(klass.length() + name.length()
                     + 5);
             return sb.append(klass).append(" \"").append(name).append("\"") //$NON-NLS-1$ //$NON-NLS-2$
                     .toString();
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/fortress/Engine.java b/libcore/security/src/main/java/org/apache/harmony/security/fortress/Engine.java
index 3b6f5d5..19fed41 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/fortress/Engine.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/fortress/Engine.java
@@ -25,6 +25,7 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.Provider;
 
+import org.apache.harmony.security.Util;
 import org.apache.harmony.security.internal.nls.Messages;
 
 
@@ -89,7 +90,7 @@
         }
         Services.refresh();
         if (returnedService != null
-                && algorithm.equalsIgnoreCase(lastAlgorithm)
+                && Util.equalsIgnoreCase(algorithm, lastAlgorithm)
                 && refreshNumber == Services.refreshNumber) {
             serv = returnedService;
         } else {
@@ -97,9 +98,9 @@
                 throw new NoSuchAlgorithmException(Messages.getString("security.14A", //$NON-NLS-1$
                         serviceName, algorithm));
             }
-            serv = Services.getService(new StringBuffer(128)
+            serv = Services.getService(new StringBuilder(128)
                     .append(serviceName).append(".").append( //$NON-NLS-1$
-                            algorithm.toUpperCase()).toString());
+                            Util.toUpperCase(algorithm)).toString());
             if (serv == null) {
                 throw new NoSuchAlgorithmException(Messages.getString("security.14A", //$NON-NLS-1$
                         serviceName, algorithm));
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java b/libcore/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java
index eda7327..b4e0e6a 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java
@@ -25,6 +25,8 @@
 import java.io.File;
 import java.io.InputStream;
 import java.lang.reflect.Constructor;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.security.AccessController;
 import java.security.Permission;
@@ -39,6 +41,7 @@
 import java.util.List;
 import java.util.Properties;
 
+import org.apache.harmony.security.Util;
 import org.apache.harmony.security.internal.nls.Messages;
 
 /**
@@ -282,6 +285,56 @@
             throws ExpansionFailedException {
         return expand(str, properties).replace(File.separatorChar, '/');
     }
+    
+    /**
+     * Normalizes URLs to standard ones, eliminating pathname symbols.
+     * 
+     * @param codebase -
+     *            the original URL.
+     * @return - the normalized URL.
+     */
+    public static URL normalizeURL(URL codebase) {
+        if (codebase != null && "file".equals(codebase.getProtocol())) { //$NON-NLS-1$
+            try {
+                if (codebase.getHost().length() == 0) {
+                    String path = codebase.getFile();
+
+                    if (path.length() == 0) {
+                        // codebase is "file:"
+                        path = "*";
+                    }
+                    return filePathToURI(new File(path)
+                            .getAbsolutePath()).normalize().toURL();
+                } else {
+                    // codebase is "file://<smth>"
+                    return codebase.toURI().normalize().toURL();
+                }
+            } catch (Exception e) {
+                // Ignore
+            }
+        }
+        return codebase;
+    }
+
+    /**
+     * Converts a file path to URI without accessing file system
+     * (like {File#toURI()} does).
+     * 
+     * @param path -
+     *            file path.
+     * @return - the resulting URI.
+     * @throw URISyntaxException
+     */
+    public static URI filePathToURI(String path) throws URISyntaxException {
+        path = path.replace(File.separatorChar, '/');
+
+        if (!path.startsWith("/")) { //$NON-NLS-1$
+            return new URI("file", null, //$NON-NLS-1$
+                    new StringBuilder(path.length() + 1).append('/')
+                            .append(path).toString(), null, null);
+        }
+        return new URI("file", null, path, null, null); //$NON-NLS-1$
+    }
 
     /**
      * Instances of this interface are intended for resolving  
@@ -371,7 +424,7 @@
      * @see #expand(String, Properties)  
      */
     public static boolean canExpandProperties() {
-        return !FALSE.equalsIgnoreCase(AccessController
+        return !Util.equalsIgnoreCase(FALSE,AccessController
                 .doPrivileged(new SecurityPropertyAccessor(POLICY_EXPAND)));
     }
 
@@ -417,7 +470,7 @@
         URL dynamicURL = null;
 
         //first check if policy is set via system properties
-        if (!FALSE.equalsIgnoreCase(AccessController
+        if (!Util.equalsIgnoreCase(FALSE, AccessController
                 .doPrivileged(security.key(POLICY_ALLOW_DYNAMIC)))) {
             String location = system.getProperty(systemUrlKey);
             if (location != null) {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/fortress/Services.java b/libcore/security/src/main/java/org/apache/harmony/security/fortress/Services.java
index 300854a..60d9edd 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/fortress/Services.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/fortress/Services.java
@@ -33,6 +33,8 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.harmony.security.Util;
+
 
 /**
  * This class contains information about all registered providers and preferred
@@ -56,7 +58,7 @@
     /**
      * Refresh number
      */
-    public static int refreshNumber = 1;
+    static int refreshNumber = 1;
 
     // Registered providers
     private static final List<Provider> providers = new ArrayList<Provider>(20);
@@ -89,8 +91,10 @@
                 providers.add(p);
                 providersNames.put(p.getName(), p);
                 initServiceInfo(p);
-            } catch (Exception e) { // ignore
-            }
+            } catch (ClassNotFoundException e) { // ignore Exceptions
+            } catch (IllegalAccessException e) {
+			} catch (InstantiationException e) {
+			}
         }
         Engine.door.renumProviders();
     }
@@ -166,21 +170,21 @@
         String key;
         String type;
         String alias;
-        StringBuffer sb = new StringBuffer(128);
+        StringBuilder sb = new StringBuilder(128);
 
         for (Iterator<Provider.Service> it1 = p.getServices().iterator(); it1.hasNext();) {
             serv = it1.next();
             type = serv.getType();
             sb.delete(0, sb.length());
             key = sb.append(type).append(".").append( //$NON-NLS-1$
-                    serv.getAlgorithm().toUpperCase()).toString();
+                    Util.toUpperCase(serv.getAlgorithm())).toString();
             if (!services.containsKey(key)) {
                 services.put(key, serv);
             }
             for (Iterator<String> it2 = Engine.door.getAliases(serv); it2.hasNext();) {
                 alias = it2.next();
                 sb.delete(0, sb.length());
-                key = sb.append(type).append(".").append(alias.toUpperCase()) //$NON-NLS-1$
+                key = sb.append(type).append(".").append(Util.toUpperCase(alias)) //$NON-NLS-1$
                         .toString();
                 if (!services.containsKey(key)) {
                     services.put(key, serv);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java b/libcore/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java
index 7c57e93..2f31131 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java
@@ -115,7 +115,7 @@
 
 
     public String toString() {
-        StringBuffer res = new StringBuffer();
+        StringBuilder res = new StringBuilder();
         res.append("-- CertificationRequestInfo:"); //$NON-NLS-1$
         res.append("\n version: "); //$NON-NLS-1$
         res.append(version);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java
index 0249055..2c129e2 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java
@@ -93,7 +93,7 @@
     }
     
     public String toString() {
-        StringBuffer res = new StringBuffer();
+        StringBuilder res = new StringBuilder();
         res.append("==== ContentInfo:"); //$NON-NLS-1$
         res.append("\n== ContentType (OID): "); //$NON-NLS-1$
         for (int i = 0; i< oid.length; i++) {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java
index 718d3d3..2f9e99d 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java
@@ -105,7 +105,7 @@
     }
 
     public String toString() {
-        StringBuffer res = new StringBuffer();
+        StringBuilder res = new StringBuilder();
         res.append("---- SignedData:"); //$NON-NLS-1$
         res.append("\nversion: "); //$NON-NLS-1$
         res.append(version);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
index 05a0c7a..9235577 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
@@ -130,7 +130,7 @@
 
     
     public String toString() {
-        StringBuffer res = new StringBuffer();
+        StringBuilder res = new StringBuilder();
         res.append("-- SignerInfo:"); //$NON-NLS-1$
         res.append("\n version : "); //$NON-NLS-1$
         res.append(version);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java
index d53eb8a..7414e75 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java
@@ -201,7 +201,7 @@
      * from the TBSCertList structure and converts them to the
      * X509CRLEntryImpl objects
      */
-    private void retirieveEntries() {
+    private void retrieveEntries() {
         entriesRetrieved = true;
         List rcerts = tbsCertList.getRevokedCertificates();
         if (rcerts == null) {
@@ -243,7 +243,7 @@
             throw new NullPointerException();
         }
         if (!entriesRetrieved) {
-            retirieveEntries();
+            retrieveEntries();
         }
         if (entries == null) {
             return null;
@@ -295,7 +295,7 @@
      */
     public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) {
         if (!entriesRetrieved) {
-            retirieveEntries();
+            retrieveEntries();
         }
         if (entries == null) {
             return null;
@@ -315,7 +315,7 @@
      */
     public Set<? extends X509CRLEntry> getRevokedCertificates() {
         if (!entriesRetrieved) {
-            retirieveEntries();
+            retrieveEntries();
         }
         if (entries == null) {
             return null;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
index 17fd6f7..f0e47d9 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
@@ -25,6 +25,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
 import java.security.cert.CRL;
 import java.security.cert.CRLException;
 import java.security.cert.CertPath;
@@ -446,8 +447,8 @@
     // ------------------------ Staff methods ------------------------------
     // ---------------------------------------------------------------------
 
-    private static byte[] pemBegin = "-----BEGIN".getBytes(); //$NON-NLS-1$
-    private static byte[] pemClose = "-----END".getBytes(); //$NON-NLS-1$
+    private static byte[] pemBegin;
+    private static byte[] pemClose;
     /**
      * Code describing free format for PEM boundary suffix:
      * "^-----BEGIN.*\n"         at the beginning, and<br>
@@ -459,8 +460,18 @@
      * "^-----BEGIN CERTIFICATE-----\n"   at the beginning, and<br>
      * "\n-----END CERTIFICATE-----"   at the end.
      */
-    private static byte[] CERT_BOUND_SUFFIX = 
-        " CERTIFICATE-----".getBytes(); //$NON-NLS-1$
+    private static byte[] CERT_BOUND_SUFFIX;
+
+    static {
+        // Initialise statics
+        try {
+            pemBegin = "-----BEGIN".getBytes("UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+            pemClose = "-----END".getBytes("UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+            CERT_BOUND_SUFFIX = " CERTIFICATE-----".getBytes("UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
 
     /**
      * Method retrieves the PEM encoded data from the stream 
@@ -515,9 +526,7 @@
                 if (boundary_suffix[i] != inStream.read()) {
                     throw new IOException(
                         Messages.getString("security.15B", //$NON-NLS-1$
-                            ((boundary_suffix == null) 
-                                ? "" 
-                                : new String(boundary_suffix)))); //$NON-NLS-1$
+                            new String(boundary_suffix))); //$NON-NLS-1$
                 }
             }
             // read new line characters
@@ -574,9 +583,7 @@
                 if (boundary_suffix[i] != inStream.read()) {
                     throw new IOException(
                         Messages.getString("security.15B1", //$NON-NLS-1$
-                            ((boundary_suffix == null) 
-                                ? "" 
-                                : new String(boundary_suffix)))); //$NON-NLS-1$
+                            new String(boundary_suffix))); //$NON-NLS-1$
                 }
             }
         }
@@ -933,3 +940,5 @@
     }
 }
 
+
+
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java
index 2234ce4..83b9944 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java
@@ -313,7 +313,7 @@
     /**
      * ASN.1 DER Encoder/Decoder for PkiPath structure.
      */
-    public static ASN1SequenceOf ASN1 =
+    public static final ASN1SequenceOf ASN1 =
                                     new ASN1SequenceOf(ASN1Any.getInstance()) {
 
         /**
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java
index af314ef..42d3043 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java
@@ -38,7 +38,7 @@
 public class DSAKeyFactoryImpl extends KeyFactorySpi {
 
     /**
-     * The method generates a DSAPrivateKey object from the provided key specification. 
+     * This method generates a DSAPrivateKey object from the provided key specification. 
      *
      * @param
      *    keySpec - the specification (key material) for the DSAPrivateKey.
@@ -66,7 +66,7 @@
     }
 
     /**
-     * The method generates a DSAPublicKey object from the provided key specification. 
+     * This method generates a DSAPublicKey object from the provided key specification. 
      *
      * @param
      *    keySpec - the specification (key material) for the DSAPublicKey.
@@ -92,28 +92,23 @@
         }
         throw new InvalidKeySpecException(Messages.getString("security.19D")); //$NON-NLS-1$
     }
-
+    
     /**
-     * The method returns a specification (key material) of the given key object. 
-     * 'keySpec' identifies the specification class 
-     * in which the key material should be returned.
-     *
-     * If it is DSAPublicKeySpec.class, the key material should be returned 
-     * in an instance of the DSAPublicKeySpec class;
-     * if it is DSAPrivateKeySpec.class, the key material should be returned 
-     * in an instance of the DSAPrivateKeySpec class.
-     *
-     * @param
-     *    key - either DSAPrivateKey or DSAPublicKey
-     * @param
-     *    keySpec - either DSAPublicKeySpec.class or DSAPublicKeySpec.class
-     *
-     * @return
-     *    either DSAPublicKeySpec object or DSAPublicKeySpec object
-     *
+     * This method returns a specification for the supplied key.
+     * 
+     * The specification will be returned in the form of an object of the type
+     * specified by keySpec.
+     * 
+     * @param key -
+     *            either DSAPrivateKey or DSAPublicKey
+     * @param keySpec -
+     *            either DSAPrivateKeySpec.class or DSAPublicKeySpec.class
+     * 
+     * @return either a DSAPrivateKeySpec or a DSAPublicKeySpec
+     * 
      * @throws InvalidKeySpecException
-     *     if "keySpec" is not s specification for DSAPublicKey or DSAPrivateKey
-     *
+     *             if "keySpec" is not a specification for DSAPublicKey or
+     *             DSAPrivateKey
      */
     protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
             throws InvalidKeySpecException {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java
index 17af038..291d69e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java
@@ -27,6 +27,7 @@
 package org.apache.harmony.security.provider.crypto;
 
 import java.io.IOException;
+import java.io.NotActiveException;
 import java.math.BigInteger;
 import java.security.interfaces.DSAParams;
 import java.security.interfaces.DSAPrivateKey;
@@ -53,9 +54,9 @@
      */
     private static final long serialVersionUID = -4716227614104950081L;
 
-    private BigInteger x;
+    private BigInteger x, g, p, q;
 
-    private DSAParams params;
+    private transient DSAParams params;
 
     /**
      * Creates object from DSAPrivateKeySpec.
@@ -68,9 +69,9 @@
 
         PrivateKeyInfo pki;
 
-        BigInteger g = keySpec.getG();
-        BigInteger p = keySpec.getP();
-        BigInteger q = keySpec.getQ();
+        g = keySpec.getG();
+        p = keySpec.getP();
+        q = keySpec.getQ();
 
         ThreeIntegerSequence threeInts = new ThreeIntegerSequence(p
                 .toByteArray(), q.toByteArray(), g.toByteArray());
@@ -133,9 +134,10 @@
             throw new InvalidKeySpecException(Messages.getString(
                     "security.19B", e)); //$NON-NLS-1$
         }
-        params = new DSAParameterSpec(new BigInteger(threeInts.p),
-                new BigInteger(threeInts.q), new BigInteger(threeInts.g));
-
+        p = new BigInteger(threeInts.p);
+        q = new BigInteger(threeInts.q);
+        g = new BigInteger(threeInts.g);
+        params = new DSAParameterSpec(p, q, g);
         setEncoding(encoding);
 
         /* 
@@ -153,5 +155,10 @@
     public DSAParams getParams() {
         return params;
     }
+    
+    private void readObject(java.io.ObjectInputStream in) throws NotActiveException, IOException, ClassNotFoundException {
+    	in.defaultReadObject();
+    	params = new DSAParameterSpec(p, q, g);    	
+    }
 
 }
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java
index bd1efdd..f4bb13d 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java
@@ -29,6 +29,7 @@
 package org.apache.harmony.security.provider.crypto;
 
 import java.io.IOException;
+import java.io.NotActiveException;
 
 import java.math.BigInteger;
 
@@ -45,12 +46,6 @@
 import org.apache.harmony.security.x509.SubjectPublicKeyInfo;
 
 import org.apache.harmony.security.asn1.ASN1Integer;
-//import org.apache.harmony.security.asn1.ASN1Sequence;
-//import org.apache.harmony.security.asn1.ASN1Type;
-//import org.apache.harmony.security.asn1.BerInputStream;
-//import org.apache.harmony.security.asn1.ASN1BitString;
-//import org.apache.harmony.security.asn1.BitString;
-//import org.apache.harmony.security.asn1.ASN1OctetString;
 
 import org.apache.harmony.security.internal.nls.Messages;
 
@@ -67,9 +62,9 @@
      */
     private static final long serialVersionUID = -2279672131310978336L;
 
-    private BigInteger y;
+    private BigInteger y, g, p, q;
 
-    private DSAParams params;
+    private transient DSAParams params;
 
     /**
      * Creates object from DSAPublicKeySpec.
@@ -82,9 +77,9 @@
 
         SubjectPublicKeyInfo spki;
 
-        BigInteger p = keySpec.getP();
-        BigInteger q = keySpec.getQ();
-        BigInteger g = keySpec.getG();
+        p = keySpec.getP();
+        q = keySpec.getQ();
+        g = keySpec.getG();
 
         ThreeIntegerSequence threeInts = new ThreeIntegerSequence(p
                 .toByteArray(), q.toByteArray(), g.toByteArray());
@@ -148,8 +143,10 @@
             throw new InvalidKeySpecException(Messages.getString(
                     "security.19B", e)); //$NON-NLS-1$
         }
-        params = (DSAParams) (new DSAParameterSpec(new BigInteger(threeInts.p),
-                new BigInteger(threeInts.q), new BigInteger(threeInts.g)));
+        p = new BigInteger(threeInts.p);
+        q = new BigInteger(threeInts.q);
+        g = new BigInteger(threeInts.g);
+        params = (DSAParams) (new DSAParameterSpec(p, q, g));
 
         setEncoding(encoding);
 
@@ -176,5 +173,10 @@
     public DSAParams getParams() {
         return params;
     }
+    
+    private void readObject(java.io.ObjectInputStream in) throws NotActiveException, IOException, ClassNotFoundException {
+    	in.defaultReadObject();
+    	params = new DSAParameterSpec(p, q, g);    	
+    }
 
 }
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
index 14db652..e3fde7f 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
@@ -35,7 +35,7 @@
  *  The static class providing access on Linux platform
  *  to system means for generating true random bits. <BR>
  *
- *  The source for true random bits is one of Linux's devices "/dev/urandom/" or
+ *  The source for true random bits is one of Linux's devices "/dev/urandom" or
  *  "/dev/random" depends on which one is available; if both the first is used. <BR>
  *
  *  If no device available the service is not available,
@@ -69,7 +69,7 @@
     /**
      * value of field is "true" only if a device is available
      */
-    private static boolean serviceAvailable;
+    private static boolean serviceAvailable = false;
 
 
     static {
@@ -86,16 +86,26 @@
                                 bis = new FileInputStream(file);
                                 // END android-modified
                                 randomFile = file;
+                                serviceAvailable = true;
                                 return null;
                             }
                         } catch (FileNotFoundException e) {
                         }
                     }
+
+                    // BEGIN android-removed
+//                    // If we have come out of the above loop, then we have been unable to
+//                    // access /dev/*random, so try to fall back to using the system random() API
+//                    try {
+//                        System.loadLibrary(LIBRARY_NAME); 
+//                        serviceAvailable = true;
+//                    } catch (UnsatisfiedLinkError e) {
+//                        serviceAvailable = false;
+//                    }
                     return null;
                 }
             }
         );
-        serviceAvailable = (bis != null);
     }
 
 
@@ -108,12 +118,12 @@
 
 
     /**
-     * On the Linux platform with "random" devices available,
+     * On platforms with "random" devices available,
      * the method reads random bytes from the device.  <BR>
      *
      * In case of any runtime failure ProviderException gets thrown.
      */
-    private static synchronized byte[] getLinuxRandomBits(int numBytes) {
+    private static synchronized byte[] getUnixDeviceRandom(int numBytes) {
 
         byte[] bytes = new byte[numBytes];
 
@@ -128,7 +138,6 @@
 
                 // the below case should not occur because /dev/random or /dev/urandom is a special file
                 // hence, if it is happened there is some internal problem
-                //
                 if ( bytesRead == -1 ) {
                     throw new ProviderException(
                         Messages.getString("security.193") ); //$NON-NLS-1$
@@ -146,7 +155,6 @@
             // actually there should be no IOException because device is a special file;
             // hence, there is either some internal problem or, for instance,
             // device was removed in runtime, or something else
-            //
             throw new ProviderException(
                 Messages.getString("security.194"), e ); //$NON-NLS-1$
         }
@@ -154,6 +162,17 @@
     }
 
 
+    // BEGIN android-removed
+//    /**
+//     * On platforms with no "random" devices available, this native 
+//     * method uses system API calls to generate random numbers<BR> 
+//     *
+//     * In case of any runtime failure ProviderException gets thrown.
+//     */
+//    private static native synchronized boolean getUnixSystemRandom(byte[] randomBits, int numBytes);
+    // END android-removed
+
+
     /**
      * The method returns byte array of requested length provided service is available.
      * ProviderException gets thrown otherwise.
@@ -171,12 +190,15 @@
             throw new IllegalArgumentException(Messages.getString("security.195", numBytes)); //$NON-NLS-1$
         }
 
+        // We have been unable to get a random device or fall back to the
+        // native security module code - throw an exception.
         if ( !serviceAvailable ) {
             throw new ProviderException(
                 Messages.getString("security.196")); //$NON-NLS-1$
         }
 
-        return getLinuxRandomBits(numBytes);
+        // BEGIN android-changed
+        return getUnixDeviceRandom(numBytes);
+        // END android-changed
     }
-
 }
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
index 6e9ecb8..7294361 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
@@ -82,10 +82,12 @@
     static final int DIGEST_LENGTH = 20;
 
 
-    /**
-     *  name of native library to use on Windows platform
-     */
-    static final String LIBRARY_NAME = "hysecurity";  //$NON-NLS-1$
+    // BEGIN android-removed
+//    /**
+//     *  name of native library to use on Windows platform
+//     */
+//    static final String LIBRARY_NAME = "hysecurity";  //$NON-NLS-1$
+    // END android-removed
 
 
     /**
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java
index 576ac76..b7b9c98 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java
@@ -83,7 +83,7 @@
         DSAParams params;
 
         // parameters and private key
-        BigInteger p, q, g, x;
+        BigInteger p, q, x;
 
         int n;
 
@@ -95,7 +95,6 @@
         params = ((DSAPrivateKey) privateKey).getParams();
         p = params.getP();
         q = params.getQ();
-        g = params.getG();
         x = ((DSAPrivateKey) privateKey).getX();
 
         // checks described in DSA standard
@@ -129,7 +128,7 @@
             throws InvalidKeyException {
 
         // parameters and public key
-        BigInteger p, q, g, y;
+        BigInteger p, q, y;
 
         int n1;
 
@@ -141,7 +140,6 @@
         DSAParams params = ((DSAPublicKey) publicKey).getParams();
         p = params.getP();
         q = params.getQ();
-        g = params.getG();
         y = ((DSAPublicKey) publicKey).getY();
 
         // checks described in DSA standard
@@ -207,7 +205,6 @@
 
         // various byte array being used in computing signature
         byte randomBytes[];
-        byte digest[];
         byte rBytes[], sBytes[], signature[];
 
         int n, n1, n2;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java b/libcore/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
index f1f5bce..bc84c01 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
@@ -29,43 +29,13 @@
 import java.util.Set;
 import java.util.Map.Entry;
 
+import org.apache.harmony.security.Util;
 import org.apache.harmony.security.asn1.ObjectIdentifier;
 
 /**
- * Provides Algorithm Name to OID
- * and OID to Algorithm Name mappings.
- * Some known mappings are hardcoded.
- * Tries to obtain additional mappings
- * from installed providers during initialization.
- * 
- * Hardcoded mappings
- * (source: http://asn1.elibel.tm.fr):
- * 
- * 1.2.840.10040.4.1 -> DSA
- * 
- * 1.2.840.113549.1.1.1 -> RSA
- * 
- * 1.2.840.113549.1.3.1 -> DiffieHellman
- * 
- * 1.2.840.113549.1.5.3 -> PBEWithMD5AndDES
- * 
- * 1.2.840.113549.1.12.1.3 -> pbeWithSHAAnd3-KeyTripleDES-CBC
- * 1.2.840.113549.1.12.1.3 -> PBEWithSHA1AndDESede
- * 1.2.840.113549.1.12.1.3 -> PBEWithSHA1AndTripleDES
- * 
- * 1.2.840.113549.1.12.1.6 -> pbeWithSHAAnd40BitRC2-CBC
- * 1.2.840.113549.1.12.1.6 -> PBEWithSHA1AndRC2_40
- * 
- * 1.2.840.113549.3.2 -> RC2-CBC
- * 1.2.840.113549.3.3 -> RC2-EBC
- * 1.2.840.113549.3.4 -> RC4
- * 1.2.840.113549.3.5 -> RC4WithMAC
- * 1.2.840.113549.3.6 -> DESx-CBC
- * 1.2.840.113549.3.7 -> TripleDES-CBC
- * 1.2.840.113549.3.8 -> rc5CBC
- * 1.2.840.113549.3.9 -> RC5-CBC
- * 1.2.840.113549.3.10 -> DESCDMF (CDMFCBCPad)
- *  
+ * Provides Algorithm Name to OID and OID to Algorithm Name mappings. Some known
+ * mappings are hardcoded. Tries to obtain additional mappings from installed
+ * providers during initialization.
  */
 public class AlgNameMapper {
     
@@ -114,7 +84,7 @@
 
     static {
         for (String[] element : knownAlgMappings) {
-            String algUC = element[1].toUpperCase();
+            String algUC = Util.toUpperCase(element[1]);
             alg2OidMap.put(algUC, element[0]);
             oid2AlgMap.put(element[0], algUC);
             // map upper case alg name to its original name
@@ -144,7 +114,7 @@
      */
     public static String map2OID(String algName) {
         // alg2OidMap map contains upper case keys
-        return alg2OidMap.get(algName.toUpperCase());
+        return alg2OidMap.get(Util.toUpperCase(algName));
     }
 
     /**
@@ -167,7 +137,7 @@
      * @return algorithm name
      */
     public static String getStandardName(String algName) {
-        return algAliasesMap.get(algName.toUpperCase());
+        return algAliasesMap.get(Util.toUpperCase(algName));
     }
 
     // Searches given provider for mappings like
@@ -184,7 +154,7 @@
                 if (key.startsWith(keyPrfix2find)) {
                     String alias = key.substring(keyPrfix2find.length());
                     String alg = (String)me.getValue();
-                    String algUC = alg.toUpperCase();
+                    String algUC = Util.toUpperCase(alg);
                     if (isOID(alias)) {
                         if (alias.startsWith("OID.")) { //$NON-NLS-1$
                             alias = alias.substring(4);
@@ -203,8 +173,8 @@
                             algAliasesMap.put(algUC, alg);
                         }
                            // Do not override known standard names
-                    } else if (!algAliasesMap.containsKey(alias.toUpperCase())) {
-                        algAliasesMap.put(alias.toUpperCase(), alg);
+                    } else if (!algAliasesMap.containsKey(Util.toUpperCase(alias))) {
+                        algAliasesMap.put(Util.toUpperCase(alias), alg);
                     }
                 }
             }
@@ -240,7 +210,7 @@
      * @return Internal maps String representation
      */
     public static String dump() {
-        StringBuffer sb = new StringBuffer("alg2OidMap: "); //$NON-NLS-1$
+        StringBuilder sb = new StringBuilder("alg2OidMap: "); //$NON-NLS-1$
         sb.append(alg2OidMap);
         sb.append("\noid2AlgMap: "); //$NON-NLS-1$
         sb.append(oid2AlgMap);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java b/libcore/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java
index 517e096..2a19656 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java
@@ -158,7 +158,7 @@
      */
     public String toString() {
         if (soid == null) {
-            StringBuffer sb = new StringBuffer(4 * oid.length);
+            StringBuilder sb = new StringBuilder(4 * oid.length);
 
             for (int i = 0; i < oid.length - 1; ++i) {
                 sb.append(oid[i]);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
index 34337eb..6343489 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
@@ -28,6 +28,7 @@
 import java.util.Iterator;
 
 import javax.security.auth.x500.X500Principal;
+import java.io.UnsupportedEncodingException;
 
 import org.apache.harmony.security.asn1.ASN1Constants;
 import org.apache.harmony.security.asn1.ASN1Oid;
@@ -38,6 +39,7 @@
 import org.apache.harmony.security.asn1.BerOutputStream;
 import org.apache.harmony.security.internal.nls.Messages;
 import org.apache.harmony.security.utils.ObjectIdentifier;
+import org.apache.harmony.security.Util;
 
 
 /**
@@ -284,7 +286,7 @@
             this.oid = thisOid;
 
         } else {
-            this.oid = (ObjectIdentifier) KNOWN_NAMES.get(sOid.toUpperCase());
+            this.oid = (ObjectIdentifier) KNOWN_NAMES.get(Util.toUpperCase(sOid));
             if (this.oid == null) {
                 throw new IOException(Messages.getString("security.178", sOid)); //$NON-NLS-1$
             }
@@ -301,7 +303,7 @@
     public void appendName(String attrFormat, StringBuffer buf) {
 
         boolean hexFormat = false;
-        if (attrFormat == X500Principal.RFC1779) {
+        if (X500Principal.RFC1779.equals(attrFormat)) {
             if (RFC1779_NAMES == oid.getGroup()) {
                 buf.append(oid.getName());
             } else {
@@ -311,7 +313,7 @@
             buf.append('=');
             if (value.escapedString == value.getHexString()) {
                 //FIXME all chars in upper case
-                buf.append(value.getHexString().toUpperCase());
+                buf.append(Util.toUpperCase(value.getHexString()));
             } else if (value.escapedString.length() != value.rawString.length()) {
                 // was escaped
                 value.appendQEString(buf);
@@ -324,7 +326,7 @@
             if (RFC1779_NAMES == group || RFC2253_NAMES == group) {
                 buf.append(oid.getName());
 
-                if (attrFormat == X500Principal.CANONICAL) {
+                if (X500Principal.CANONICAL.equals(attrFormat)) {
                     // only PrintableString and UTF8String in string format
                     // all others are output in hex format
                     // BEGIN android-changed
@@ -348,7 +350,7 @@
             if (hexFormat) {
                 buf.append(value.getHexString());
             } else {
-                if (attrFormat == X500Principal.CANONICAL) {
+                if (X500Principal.CANONICAL.equals(attrFormat)) {
                     buf.append(value.makeCanonical());
                 } else {
                     buf.append(value.escapedString);
@@ -387,7 +389,7 @@
      *  
      */
 
-    public static ASN1Type AttributeValue = new ASN1Type(
+    public static final ASN1Type attributeValue = new ASN1Type(
             ASN1Constants.TAG_PRINTABLESTRING) {
 
         public boolean checkTag(int tag) {
@@ -452,7 +454,11 @@
                     av.bytes = (byte[]) out.content;
                     out.content = av;
                 } else {
-                    av.bytes = av.rawString.getBytes();
+                    try {
+                        av.bytes = av.rawString.getBytes("UTF-8"); //$NON-NLS-1$
+                    } catch (UnsupportedEncodingException e) {
+                        throw new RuntimeException(e.getMessage());
+                    }
                     out.length = av.bytes.length;
                 }
             }
@@ -476,7 +482,7 @@
     };
 
     public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {
-            ASN1Oid.getInstance(), AttributeValue }) {
+            ASN1Oid.getInstance(), attributeValue }) {
 
         protected Object getDecodedObject(BerInputStream in) throws IOException {
             Object[] values = (Object[]) in.content;
@@ -541,4 +547,4 @@
         }
         return intHash & 0x7FFFFFFF; // only positive
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java
index 8844035..30d71e7 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java
@@ -22,6 +22,7 @@
 
 package org.apache.harmony.security.x501;
 
+import java.io.Serializable;
 import java.util.Comparator;
 
 import org.apache.harmony.security.utils.ObjectIdentifier;
@@ -30,9 +31,11 @@
  * AttributeTypeAndValue comparator
  * 
  */
-public class AttributeTypeAndValueComparator implements Comparator {
+public class AttributeTypeAndValueComparator implements Comparator, Serializable {
 
-    /**
+	private static final long serialVersionUID = -1286471842007103132L;
+
+	/**
      * compares two AttributeTypeAndValues
      * 
      * @param obj1
@@ -63,14 +66,7 @@
 
         return compateOids(atav1.getType(), atav2.getType());
     }
-
-    /**
-     * @return false
-     */
-    public boolean equals(Object obj) {
-        return false;
-    }
-
+    
     /**
      * compares two Object identifiers
      * 
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
index 51f9725..0844c5e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
@@ -126,7 +126,7 @@
                 }
             }
 
-            StringBuffer buf = new StringBuffer(encoded.length * 2 + 1);
+            StringBuilder buf = new StringBuilder(encoded.length * 2 + 1);
             buf.append('#');
 
             for (int i = 0, c; i < encoded.length; i++) {
@@ -180,7 +180,7 @@
         if (length == 0) {
             return name;
         }
-        StringBuffer buf = new StringBuffer(length * 2);
+        StringBuilder buf = new StringBuilder(length * 2);
 
         for (int index = 0; index < length; index++) {
 
@@ -223,7 +223,7 @@
         if (length == 0) {
             return rawString;
         }
-        StringBuffer buf = new StringBuffer(length * 2);
+        StringBuilder buf = new StringBuilder(length * 2);
 
         int index = 0;
         if (rawString.charAt(0) == '#') {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x501/Name.java b/libcore/security/src/main/java/org/apache/harmony/security/x501/Name.java
index 836342e..ae08671 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x501/Name.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x501/Name.java
@@ -118,21 +118,21 @@
         //
         // check X500Principal constants first
         //
-        if (format == X500Principal.RFC1779) {
+        if (X500Principal.RFC1779.equals(format)) {
 
             if (rfc1779String == null) {
                 rfc1779String = getName0(format);
             }
             return rfc1779String;
 
-        } else if (format == X500Principal.RFC2253) {
+        } else if (X500Principal.RFC2253.equals(format)) {
 
             if (rfc2253String == null) {
                 rfc2253String = getName0(format);
             }
             return rfc2253String;
 
-        } else if (format == X500Principal.CANONICAL) {
+        } else if (X500Principal.CANONICAL.equals(format)) {
 
             if (canonicalString == null) {
                 canonicalString = getName0(format);
@@ -217,7 +217,7 @@
         }
 
         String sName = name.toString();
-        if (format == X500Principal.CANONICAL) {
+        if (X500Principal.CANONICAL.equals(format)) {
             sName = sName.toLowerCase(Locale.US);
         }
         return sName;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java
index bc8fd28..69b9258 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java
@@ -70,7 +70,7 @@
     }
 
     public String toString() {
-        StringBuffer res = new StringBuffer();
+        StringBuilder res = new StringBuilder();
         res.append("\n-- AccessDescription:"); //$NON-NLS-1$
         res.append("\naccessMethod:  "); //$NON-NLS-1$
         res.append(accessMethod);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java
index 70dba99..728fd6a 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java
@@ -143,6 +143,11 @@
                     : Arrays.equals(parameters, algid.parameters));
     }
     
+    public int hashCode() {
+    	return algorithm.hashCode() * 37 + 
+    		(parameters != null ? parameters.hashCode() : 0);
+    }
+    
     /**
      * Places the string representation into the StringBuffer object.
      */
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java
index 1cf9c3e..3de59fb 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java
@@ -103,7 +103,7 @@
         buffer.append(prefix).append("]\n"); //$NON-NLS-1$
     }
 
-    public static ASN1Type ASN1 = new ASN1Sequence(
+    public static final ASN1Type ASN1 = new ASN1Sequence(
             new ASN1Type[] {
                 new ASN1Implicit(0, ASN1OctetString.getInstance()),
                 new ASN1Implicit(1, GeneralNames.ASN1),
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java
index 10b3156..edbf13e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java
@@ -105,7 +105,7 @@
     /**
      * ASN.1 Encoder/Decoder.
      */
-    public static ASN1Type ASN1 = new ASN1Sequence(new ASN1Type[] {
+    public static final ASN1Type ASN1 = new ASN1Sequence(new ASN1Type[] {
             ASN1Boolean.getInstance(), ASN1Integer.getInstance() }) {
         {
             setDefault(Boolean.FALSE, 0);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java
index 85cbea0..db2480e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java
@@ -84,5 +84,5 @@
     /**
      * ASN.1 Encoder/Decoder.
      */
-    public static ASN1Type ASN1 = ASN1Integer.getInstance();
+    public static final ASN1Type ASN1 = ASN1Integer.getInstance();
 }
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java
index 3a31734..d6ab760 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java
@@ -87,7 +87,7 @@
     /**
      * ASN.1 Encoder/Decoder.
      */
-    public static ASN1Type ASN1 = new ASN1Sequence(new ASN1Type[] {
+    public static final ASN1Type ASN1 = new ASN1Sequence(new ASN1Type[] {
         GeneralName.ASN1
     }) {
         public Object getDecodedObject(BerInputStream in) {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/DNParser.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/DNParser.java
index 730f7df..5870bcd 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/DNParser.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/DNParser.java
@@ -293,6 +293,9 @@
         case '#':
         case ';':
         case ' ':
+        case '*':
+        case '%':
+        case '_':
             //FIXME: escaping is allowed only for leading or trailing space char 
             return chars[pos];
         default:
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java
index 69e9cee..4eacbd5 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java
@@ -109,7 +109,7 @@
     /**
      * ASN.1 Encoder/Decoder.
      */
-    public static ASN1Type ASN1 =
+    public static final ASN1Type ASN1 =
         new ASN1SequenceOf(new ASN1Oid() {
 
             public Object getDecodedObject(BerInputStream in)
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/Extension.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/Extension.java
index 833f2fe..86e7a45 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/Extension.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/Extension.java
@@ -58,34 +58,34 @@
     
     // constants: the extension OIDs
     // certificate extensions:
-    public static final int[] SUBJ_DIRECTORY_ATTRS = {2, 5, 29, 9};
-    public static final int[] SUBJ_KEY_ID = {2, 5, 29, 14};
-    public static final int[] KEY_USAGE = {2, 5, 29, 15};
-    public static final int[] PRIVATE_KEY_USAGE_PERIOD = {2, 5, 29, 16};
-    public static final int[] SUBJECT_ALT_NAME = {2, 5, 29, 17};
-    public static final int[] ISSUER_ALTERNATIVE_NAME = {2, 5, 29, 18};
-    public static final int[] BASIC_CONSTRAINTS = {2, 5, 29, 19};
-    public static final int[] NAME_CONSTRAINTS = {2, 5, 29, 30};
-    public static final int[] CRL_DISTR_POINTS = {2, 5, 29, 31};
-    public static final int[] CERTIFICATE_POLICIES = {2, 5, 29, 32};
-    public static final int[] POLICY_MAPPINGS = {2, 5, 29, 33};
-    public static final int[] AUTH_KEY_ID = {2, 5, 29, 35};
-    public static final int[] POLICY_CONSTRAINTS = {2, 5, 29, 36};
-    public static final int[] EXTENDED_KEY_USAGE = {2, 5, 29, 37};
-    public static final int[] FRESHEST_CRL = {2, 5, 29, 46};
-    public static final int[] INHIBIT_ANY_POLICY = {2, 5, 29, 54};
-    public static final int[] AUTHORITY_INFO_ACCESS =
+    static final int[] SUBJ_DIRECTORY_ATTRS = {2, 5, 29, 9};
+    static final int[] SUBJ_KEY_ID = {2, 5, 29, 14};
+    static final int[] KEY_USAGE = {2, 5, 29, 15};
+    static final int[] PRIVATE_KEY_USAGE_PERIOD = {2, 5, 29, 16};
+    static final int[] SUBJECT_ALT_NAME = {2, 5, 29, 17};
+    static final int[] ISSUER_ALTERNATIVE_NAME = {2, 5, 29, 18};
+    static final int[] BASIC_CONSTRAINTS = {2, 5, 29, 19};
+    static final int[] NAME_CONSTRAINTS = {2, 5, 29, 30};
+    static final int[] CRL_DISTR_POINTS = {2, 5, 29, 31};
+    static final int[] CERTIFICATE_POLICIES = {2, 5, 29, 32};
+    static final int[] POLICY_MAPPINGS = {2, 5, 29, 33};
+    static final int[] AUTH_KEY_ID = {2, 5, 29, 35};
+    static final int[] POLICY_CONSTRAINTS = {2, 5, 29, 36};
+    static final int[] EXTENDED_KEY_USAGE = {2, 5, 29, 37};
+    static final int[] FRESHEST_CRL = {2, 5, 29, 46};
+    static final int[] INHIBIT_ANY_POLICY = {2, 5, 29, 54};
+    static final int[] AUTHORITY_INFO_ACCESS =
                                             {1, 3, 6, 1, 5, 5, 7, 1, 1};
-    public static final int[] SUBJECT_INFO_ACCESS =
+    static final int[] SUBJECT_INFO_ACCESS =
                                             {1, 3, 6, 1, 5, 5, 7, 1, 11};
     // crl extensions:
-    public static final int[] ISSUING_DISTR_POINT = {2, 5, 29, 28};
+    static final int[] ISSUING_DISTR_POINT = {2, 5, 29, 28};
     // crl entry extensions:
-    public static final int[] CRL_NUMBER = {2, 5, 29, 20};
-    public static final int[] CERTIFICATE_ISSUER = {2, 5, 29, 29};
-    public static final int[] INVALIDITY_DATE = {2, 5, 29, 24};
-    public static final int[] REASON_CODE = {2, 5, 29, 21};
-    public static final int[] ISSUING_DISTR_POINTS = {2, 5, 29, 28};
+    static final int[] CRL_NUMBER = {2, 5, 29, 20};
+    static final int[] CERTIFICATE_ISSUER = {2, 5, 29, 29};
+    static final int[] INVALIDITY_DATE = {2, 5, 29, 24};
+    static final int[] REASON_CODE = {2, 5, 29, 21};
+    static final int[] ISSUING_DISTR_POINTS = {2, 5, 29, 28};
     
     // the value of extnID field of the structure
     private final int[] extnID;
@@ -238,6 +238,10 @@
             && (critical == extn.critical)
             && Arrays.equals(extnValue, extn.extnValue);
     }
+    
+    public int hashCode() {
+    	return (extnID.hashCode() * 37 + (critical ? 1 : 0)) * 37 + extnValue.hashCode();
+    }
 
     public ExtensionValue getDecodedExtensionValue() throws IOException {
         if (!valueDecoded) {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/Extensions.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/Extensions.java
index e98a116..1fee6c0 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/Extensions.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/Extensions.java
@@ -386,6 +386,14 @@
                 );
     }
     
+    public int hashCode() {
+    	int hashcode = 0;
+    	if (extensions != null) {
+    		hashcode = extensions.hashCode();
+    	}
+    	return hashcode;
+    }
+    
     /**
      * Places the string representation into the StringBuffer object.
      */
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java
index db4daaa..3b291a1 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java
@@ -328,6 +328,24 @@
         return false;
     }
     
+	public int hashCode() {
+		switch(tag) {
+	        case RFC822_NAME:
+	        case DNS_NAME:
+	        case UR_ID:
+	        case REG_ID:
+	        case IP_ADDR: 
+	            return name.hashCode();
+	        case DIR_NAME: 
+	        case X400_ADDR:
+	        case OTHER_NAME:
+	        case EDIP_NAME:
+	            return getEncoded().hashCode();
+	        default:
+	            return super.hashCode();
+		}
+	}
+    
     /**
      * Checks if the other general name is acceptable by this object.
      * The name is acceptable if it has the same type name and its
@@ -562,16 +580,21 @@
 
     /**
      * Checks the correctness of the string representation of DNS name.
-     * The correctness is checked as specified in RFC 1034 p. 10.
+     * The correctness is checked as specified in RFC 1034 p. 10, and modified
+     * by RFC 1123 (section 2.1).
      */
     public static void checkDNS(String dns) throws IOException {
-        byte[] bytes = dns.toLowerCase().getBytes();
+        byte[] bytes = dns.toLowerCase().getBytes("UTF-8"); //$NON-NLS-1$
         // indicates if it is a first letter of the label
         boolean first_letter = true;
         for (int i=0; i<bytes.length; i++) {
             byte ch = bytes[i];
             if (first_letter) {
-                if (ch > 'z' || ch < 'a') {
+                if ((bytes.length > 2) && (ch == '*') && (bytes[1] == '.')) {
+                    first_letter = false;
+                    continue;
+                }
+                if ((ch > 'z' || ch < 'a') && (ch < '0' || ch > '9')) {
                     throw new IOException(Messages.getString("security.184", //$NON-NLS-1$
                             (char)ch, dns));
                 }
@@ -585,7 +608,7 @@
             if (ch == '.') {
                 // check the end of the previous label, it should not
                 // be '-' sign
-                if (bytes[i-i] == '-') {
+                if (bytes[i-1] == '-') {
                     throw new IOException(
                             Messages.getString("security.186", dns)); //$NON-NLS-1$
                 }
@@ -619,7 +642,7 @@
      * Converts OID into array of bytes.
      */
     public static int[] oidStrToInts(String oid) throws IOException {
-        byte[] bytes = oid.getBytes();
+        byte[] bytes = oid.getBytes("UTF-8"); //$NON-NLS-1$
         if (bytes[bytes.length-1] == '.') {
             throw new IOException(Messages.getString("security.56", oid)); //$NON-NLS-1$
         }
@@ -673,7 +696,7 @@
         }
         // the resulting array
         byte[] result = new byte[num_components];
-        byte[] ip_bytes = ip.getBytes();
+        byte[] ip_bytes = ip.getBytes("UTF-8"); //$NON-NLS-1$
         // number of address component to be read
         int component = 0;
         // if it is reading the second bound of a range
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java
index 7323124..ce5404e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java
@@ -86,7 +86,7 @@
     }
 
     public String toString() {
-        StringBuffer res = new StringBuffer();
+        StringBuilder res = new StringBuilder();
         res.append("\n---- InfoAccessSyntax:"); //$NON-NLS-1$
         if (accessDescriptions != null) {
             for (Iterator it = accessDescriptions.iterator(); it.hasNext();) {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java
index bc04caf..b01fa45 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java
@@ -82,6 +82,6 @@
     /**
      * ASN.1 Encoder/Decoder.
      */
-    public static ASN1Type ASN1 = ASN1GeneralizedTime.getInstance();
+    public static final ASN1Type ASN1 = ASN1GeneralizedTime.getInstance();
 }
 
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java
index aec57c3..102fe05 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java
@@ -180,7 +180,7 @@
     /**
      * ASN.1 Encoder/Decoder.
      */
-    public static ASN1Type ASN1 = new ASN1Sequence(
+    public static final ASN1Type ASN1 = new ASN1Sequence(
             new ASN1Type[] {
                 // ASN.1 prohibits implicitly tagged CHOICE
                 new ASN1Explicit(0, DistributionPointName.ASN1),
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java
index 26b4acc..de3505d 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java
@@ -128,6 +128,6 @@
     /**
      * ASN.1 Encoder/Decoder.
      */
-    public static ASN1Type ASN1 = ASN1Enumerated.getInstance();
+    public static final ASN1Type ASN1 = ASN1Enumerated.getInstance();
 }
 
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java
index 6f72dc7..842784f 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java
@@ -55,7 +55,7 @@
     /**
      * The names of the reasons.
      */
-    public static final String[] REASONS = {
+    static final String[] REASONS = {
         "unused", //$NON-NLS-1$
         "keyCompromise", //$NON-NLS-1$
         "cACompromise", //$NON-NLS-1$
@@ -97,7 +97,7 @@
     /**
      * ASN.1 Encoder/Decoder.
      */
-    public static ASN1BitString ASN1 = 
+    public static final ASN1BitString ASN1 = 
                             new ASN1BitString.ASN1NamedBitList(REASONS.length) {
         public Object getDecodedObject(BerInputStream in) throws IOException {
             return new ReasonFlags((boolean[]) super.getDecodedObject(in));
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java
index 597ca59..6b04d55 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java
@@ -153,6 +153,11 @@
                     ? rcert.crlEntryExtensions == null
                     : crlEntryExtensions.equals(rcert.crlEntryExtensions));
         }
+        
+        public int hashCode() {
+        	return userCertificate.hashCode() * 37 + (int)revocationDate.getTime() / 1000
+        	+ (crlEntryExtensions == null ? 0 : crlEntryExtensions.hashCode());
+        }
 
         /**
          * Places the string representation of extension value
@@ -171,7 +176,7 @@
             }
         }
         
-        public static ASN1Sequence ASN1 = new ASN1Sequence(
+        public static final ASN1Sequence ASN1 = new ASN1Sequence(
                 new ASN1Type[] {ASN1Integer.getInstance(), Time.ASN1,
                 Extensions.ASN1}) {
             {
@@ -358,6 +363,12 @@
                     ? tbscert.crlExtensions == null
                     : crlExtensions.equals(tbscert.crlExtensions));
     }
+    
+    public int hashCode() {
+    	return ((version * 37 + signature.hashCode()) * 37
+    		+ issuer.getEncoded().hashCode()) * 37
+    		+ (int)thisUpdate.getTime() / 1000;
+    }
 
     /**
      * Places the string representation of extension value
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java
index 336a60d..b0b75a6 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java
@@ -59,7 +59,7 @@
     }
     
     public String toString(){
-        StringBuffer res = new StringBuffer();
+        StringBuilder res = new StringBuilder();
         res.append("-- PKIStatusInfo:");
         res.append("\nPKIStatus : ");
         res.append(status);
@@ -122,8 +122,7 @@
             
             int failInfoValue = -1;
             if (values[2] != null) {
-                boolean[] failInfoBoolArray = (values[2] == null) ? null
-                        : ((BitString) values[2]).toBooleanArray();
+                boolean[] failInfoBoolArray = ((BitString) values[2]).toBooleanArray();
                 for (int i = 0; i < failInfoBoolArray.length; i++) {
                     if (failInfoBoolArray[i]) {
                         failInfoValue = i;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java
index 4c9454e..f2aa0ee 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java
@@ -102,7 +102,7 @@
     }
     
     public String toString() {
-        StringBuffer res = new StringBuffer();
+        StringBuilder res = new StringBuilder();
         res.append("-- TSTInfo:");
         res.append("\nversion:  ");
         res.append(version);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java
index 117ae27..5e4e6ff 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java
@@ -82,7 +82,7 @@
     }
 
     public String toString() {
-        StringBuffer res = new StringBuffer();
+        StringBuilder res = new StringBuilder();
         res.append("-- TimeStampReq:");
         res.append("\nversion : ");
         res.append(version);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java
index ea50a2d..af03ea5 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java
@@ -46,7 +46,7 @@
     }
     
     public String toString(){
-        StringBuffer res = new StringBuffer();
+        StringBuilder res = new StringBuilder();
         res.append("-- TimeStampResp:");
         res.append("\nstatus:  ");
         res.append(status);
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java
index bbbe861..13ac904 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java
@@ -709,8 +709,7 @@
         params = AlgorithmParameters.getInstance("DSA");
         try {
             params.init(enc, "DOUGLASMAWSON");
-            params.init(enc, "DOUGLASMAWSON");
-            fail("IOException exception expected");
+            fail("unsupported format should have raised IOException");
         } catch (IOException e) {
             // expected
         }
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java
index 2803251..089a7db 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java
@@ -47,33 +47,26 @@
         suite.addTestSuite(CodeSignerTest.class);
         suite.addTestSuite(CodeSource2Test.class);
         suite.addTestSuite(CodeSourceTest.class);
-        suite.addTestSuite(DigestException2Test.class);
         suite.addTestSuite(DigestExceptionTest.class);
         suite.addTestSuite(DigestInputStream2Test.class);
         suite.addTestSuite(DigestInputStreamTest.class);
         suite.addTestSuite(DigestOutputStreamTest.class);
-        suite.addTestSuite(GeneralSecurityException2Test.class);
         suite.addTestSuite(GeneralSecurityExceptionTest.class);
         suite.addTestSuite(GuardedObjectTest.class);
         suite.addTestSuite(Identity2Test.class);
         suite.addTestSuite(IdentityScope2Test.class);
         suite.addTestSuite(IdentityScopeTest.class);
-        suite.addTestSuite(InvalidAlgorithmParameterException2Test.class);
         suite.addTestSuite(InvalidAlgorithmParameterExceptionTest.class);
-        suite.addTestSuite(InvalidKeyException2Test.class);
         suite.addTestSuite(InvalidKeyExceptionTest.class);
-        suite.addTestSuite(InvalidParameterException2Test.class);
         suite.addTestSuite(InvalidParameterExceptionTest.class);
         suite.addTestSuite(KSCallbackHandlerProtectionTest.class);
         suite.addTestSuite(KSPasswordProtectionTest.class);
         suite.addTestSuite(KSPrivateKeyEntryTest.class);
         suite.addTestSuite(KSSecretKeyEntryTest.class);
         suite.addTestSuite(KSTrustedCertificateEntryTest.class);
-        suite.addTestSuite(KeyException2Test.class);
         suite.addTestSuite(KeyExceptionTest.class);
         suite.addTestSuite(KeyFactory2Test.class);
         suite.addTestSuite(KeyFactorySpiTest.class);
-        suite.addTestSuite(KeyManagementException2Test.class);
         suite.addTestSuite(KeyManagementExceptionTest.class);
         suite.addTestSuite(KeyPairGenerator1Test.class);
         suite.addTestSuite(KeyPairGenerator2Test.class);
@@ -86,7 +79,6 @@
         suite.addTestSuite(KeyStore2Test.class);
         suite.addTestSuite(KeyStore3Test.class);
         suite.addTestSuite(KeyStoreBuilderTest.class);
-        suite.addTestSuite(KeyStoreException2Test.class);
         suite.addTestSuite(KeyStoreExceptionTest.class);
         suite.addTestSuite(KeyStoreSpiTest.class);
         suite.addTestSuite(KeyStoreTest.class);
@@ -94,9 +86,7 @@
         suite.addTestSuite(MessageDigest1Test.class);
         suite.addTestSuite(MessageDigest2Test.class);
         suite.addTestSuite(MessageDigestSpiTest.class);
-        suite.addTestSuite(NoSuchAlgorithmException2Test.class);
         suite.addTestSuite(NoSuchAlgorithmExceptionTest.class);
-        suite.addTestSuite(NoSuchProviderException2Test.class);
         suite.addTestSuite(NoSuchProviderExceptionTest.class);
         suite.addTestSuite(Permission2Test.class);
         suite.addTestSuite(PermissionCollectionTest.class);
@@ -109,7 +99,6 @@
         suite.addTestSuite(PrivilegedActionExceptionTest.class);
         suite.addTestSuite(ProtectionDomainTest.class);
         suite.addTestSuite(Provider2Test.class);
-        suite.addTestSuite(ProviderException2Test.class);
         suite.addTestSuite(ProviderExceptionTest.class);
         suite.addTestSuite(ProviderServiceTest.class);
         suite.addTestSuite(ProviderTest.class);
@@ -121,7 +110,6 @@
         suite.addTestSuite(SecurityPermissionTest.class);
         suite.addTestSuite(SecurityTest.class);
         suite.addTestSuite(Signature2Test.class);
-        suite.addTestSuite(SignatureException2Test.class);
         suite.addTestSuite(SignatureExceptionTest.class);
         suite.addTestSuite(SignatureSpiTest.class);
         suite.addTestSuite(SignatureTest.class);
@@ -129,7 +117,6 @@
         suite.addTestSuite(SignerTest.class);
         suite.addTestSuite(TimestampTest.class);
         suite.addTestSuite(UnrecoverableEntryExceptionTest.class);
-        suite.addTestSuite(UnrecoverableKeyException2Test.class);
         suite.addTestSuite(UnrecoverableKeyExceptionTest.class);
         suite.addTestSuite(UnresolvedPermissionTest.class);
 
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java
index c70bc57..fa94fbf 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java
@@ -128,7 +128,7 @@
     public void test_hashCode() throws Exception {
         URL url = new java.net.URL("file:///test");
         CodeSource cs = new CodeSource(url, (Certificate[]) null);
-        assertTrue("Did not get expected hashCode!", cs.hashCode() == url
+        assertEquals("Did not get expected hashCode!", cs.hashCode(), url
                 .hashCode());
     }
 
@@ -163,6 +163,7 @@
                 (Certificate[]) null);
         assertEquals("Did not get expected location!", "file:/test", cs
                 .getLocation().toString());
+        assertNotNull("Host should not be null", cs.getLocation().getHost());
     }
 
     /**
@@ -187,7 +188,7 @@
                 (Certificate[]) null);
         cs2 = new CodeSource(new URL("file:/d:/somedir/"), (Certificate[]) null);
         assertTrue("null host should imply host", cs1.implies(cs2));
-        assertTrue("host should not imply null host", !cs2.implies(cs1));
-    }
+        assertFalse("host should not imply null host", cs2.implies(cs1));
+	}
 
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestException2Test.java
deleted file mode 100644
index 544e618..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestException2Test.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.DigestException;
-
-@TestTargetClass(DigestException.class)
-public class DigestException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.DigestException#DigestException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "DigestException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.DigestException()
-        DigestException de = new DigestException();
-        assertNull("Exception with no message should yield null message.", de
-                .getMessage());
-    }
-
-    /**
-     * @tests java.security.DigestException#DigestException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Different variants of string parameter (empty, null, etc.) weren't checked",
-        method = "DigestException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method java.security.DigestException(java.lang.String)
-        DigestException de = new DigestException("Test message");
-        assertEquals("Exception message is incorrect", "Test message", de
-                .getMessage());
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java
index 69a73a3..93ffe77 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java
@@ -19,6 +19,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.security.DigestInputStream;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -280,4 +281,4 @@
             fail("Unable to find SHA-1 algorithm");
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
index 8309c87..ca80f19 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
@@ -651,32 +651,28 @@
         method = "on",
         args = {boolean.class}
     )
-    public void test_onZ() {
+    public void test_onZ() throws Exception {
         // Test for method void java.security.DigestOutputStream.on(boolean)
-        try {
-            DigestOutputStream dos = new DigestOutputStream(
-                    new ByteArrayOutputStream(), MessageDigest
-                            .getInstance("SHA"));
-            dos.on(false);
-            byte digestArray[] = { 23, 43, 44 };
-            dos.write(digestArray, 1, 1);
-            byte digestResult[] = dos.getMessageDigest().digest();
-            byte expected[] = { -38, 57, -93, -18, 94, 107, 75, 13, 50, 85,
-                    -65, -17, -107, 96, 24, -112, -81, -40, 7, 9 };
-            assertTrue("Digest did not return expected result.",
-                    java.util.Arrays.equals(digestResult, expected));
-            // now turn on processing and re-run
-            dos.on(true);
-            dos.write(digestArray, 1, 1);
-            digestResult = dos.getMessageDigest().digest();
-            byte expected1[] = { -87, 121, -17, 16, -52, 111, 106, 54, -33,
-                    107, -118, 50, 51, 7, -18, 59, -78, -30, -37, -100 };
+        DigestOutputStream dos = new DigestOutputStream(
+                new ByteArrayOutputStream(), MessageDigest
+                        .getInstance("SHA"));
+        dos.on(false);
+        byte digestArray[] = { 23, 43, 44 };
+        dos.write(digestArray, 1, 1);
+        byte digestResult[] = dos.getMessageDigest().digest();
+        byte expected[] = { -38, 57, -93, -18, 94, 107, 75, 13, 50, 85,
+                -65, -17, -107, 96, 24, -112, -81, -40, 7, 9 };
+        assertTrue("Digest did not return expected result.",
+                java.util.Arrays.equals(digestResult, expected));
+        // now turn on processing and re-run
+        dos.on(true);
+        dos.write(digestArray, 1, 1);
+        digestResult = dos.getMessageDigest().digest();
+        byte expected1[] = { -87, 121, -17, 16, -52, 111, 106, 54, -33,
+                107, -118, 50, 51, 7, -18, 59, -78, -30, -37, -100 };
 
-            assertTrue("Digest did not return expected result.",
-                    java.util.Arrays.equals(digestResult, expected1));
-        } catch (Exception e) {
-            fail("Caught exception : " + e);
-        }
+        assertTrue("Digest did not return expected result.",
+                java.util.Arrays.equals(digestResult, expected1));
     }
 
     /**
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/GeneralSecurityException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/GeneralSecurityException2Test.java
deleted file mode 100644
index 3647115..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/GeneralSecurityException2Test.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.GeneralSecurityException;
-
-@TestTargetClass(GeneralSecurityException.class)
-public class GeneralSecurityException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.GeneralSecurityException#GeneralSecurityException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "GeneralSecurityException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.GeneralSecurityException()
-        GeneralSecurityException e = new GeneralSecurityException();
-        assertNotNull("Constructor returned null instance", e);
-        assertEquals("Failed toString test for constructed instance", "java.security.GeneralSecurityException", e
-                .toString());
-    }
-
-    /**
-     * @tests java.security.GeneralSecurityException#GeneralSecurityException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Verifies non null parameter only",
-        method = "GeneralSecurityException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method
-        // java.security.GeneralSecurityException(java.lang.String)
-        GeneralSecurityException e = new GeneralSecurityException(
-                "test message");
-        assertNotNull("Constructor returned null instance", e);
-        assertEquals("Failed toString test for constructed instance", 
-                        "java.security.GeneralSecurityException: test message", e
-                .toString());
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
index 55e2fd2..865bbea 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
@@ -20,6 +20,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
 import java.security.Certificate;
 import java.security.Identity;
 import java.security.IdentityScope;
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidAlgorithmParameterException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidAlgorithmParameterException2Test.java
deleted file mode 100644
index dafdb38..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidAlgorithmParameterException2Test.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.InvalidAlgorithmParameterException;
-
-@TestTargetClass(InvalidAlgorithmParameterException.class)
-public class InvalidAlgorithmParameterException2Test extends
-        junit.framework.TestCase {
-
-    /**
-     * @tests java.security.InvalidAlgorithmParameterException#InvalidAlgorithmParameterException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "InvalidAlgorithmParameterException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.InvalidAlgorithmParameterException()
-        InvalidAlgorithmParameterException e = new InvalidAlgorithmParameterException();
-        assertNotNull("Constructor returned null instance", e);
-        assertEquals("Failed toString test for constructed instance",
-                "java.security.InvalidAlgorithmParameterException", e
-                        .toString());
-    }
-
-    /**
-     * @tests java.security.InvalidAlgorithmParameterException#InvalidAlgorithmParameterException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Verifies constructor with one string parameter",
-        method = "InvalidAlgorithmParameterException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method
-        // java.security.InvalidAlgorithmParameterException(java.lang.String)
-        InvalidAlgorithmParameterException e = new InvalidAlgorithmParameterException(
-                "test message");
-        assertNotNull("Constructor returned null instance", e);
-        assertEquals(
-                "Failed toString test for constructed instance",
-                "java.security.InvalidAlgorithmParameterException: test message",
-                e.toString());
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidKeyException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidKeyException2Test.java
deleted file mode 100644
index bbe9e08..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidKeyException2Test.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.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.InvalidKeyException;
-
-@TestTargetClass(InvalidKeyException.class)
-public class InvalidKeyException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.InvalidKeyException#InvalidKeyException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "InvalidKeyException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.InvalidKeyException()
-        InvalidKeyException e = new InvalidKeyException();
-        assertNotNull("Constructor returned a null", e);
-        assertEquals("Failed toString test for constructed instance", "java.security.InvalidKeyException", e
-                .toString());
-    }
-
-    /**
-     * @tests java.security.InvalidKeyException#InvalidKeyException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Verifies constructor with one string parameter",
-        method = "InvalidKeyException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method java.security.InvalidKeyException(java.lang.String)
-        InvalidKeyException e = new InvalidKeyException("test message");
-        assertNotNull("Constructor returned a null", e);
-        assertEquals("Failed toString test for constructed instance", 
-                        "java.security.InvalidKeyException: test message", e
-                .toString());
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidParameterException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidParameterException2Test.java
deleted file mode 100644
index 4830731..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidParameterException2Test.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.InvalidParameterException;
-
-@TestTargetClass(InvalidParameterException.class)
-public class InvalidParameterException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.InvalidParameterException#InvalidParameterException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "InvalidParameterException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.InvalidParameterException()
-        InvalidParameterException e = new InvalidParameterException();
-        assertEquals("Failed toString test for constructed instance", "java.security.InvalidParameterException", e
-                .toString());
-    }
-
-    /**
-     * @tests java.security.InvalidParameterException#InvalidParameterException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Verifies constructor with one variant of string parameter",
-        method = "InvalidParameterException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method
-        // java.security.InvalidParameterException(java.lang.String)
-        InvalidParameterException e = new InvalidParameterException(
-                "test message");
-        assertEquals("Failed toString test for constructed instance",
-                
-                                "java.security.InvalidParameterException: test message", e
-                        .toString()
-                        );
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyException2Test.java
deleted file mode 100644
index 1c7b71f..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyException2Test.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.KeyException;
-
-@TestTargetClass(KeyException.class)
-public class KeyException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.KeyException#KeyException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "KeyException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.KeyException()
-        KeyException e = new KeyException();
-        assertEquals("Failed toString test for constructed instance", "java.security.KeyException", e
-                .toString());
-    }
-
-    /**
-     * @tests java.security.KeyException#KeyException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Verifies constructor with one variant of string parameter",
-        method = "KeyException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method java.security.KeyException(java.lang.String)
-        KeyException e = new KeyException("test message");
-        assertEquals("Failed toString test for constructed instance", "java.security.KeyException: test message", e
-                .toString());
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyManagementException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyManagementException2Test.java
deleted file mode 100644
index c30370a..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyManagementException2Test.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.KeyManagementException;
-
-@TestTargetClass(KeyManagementException.class)
-public class KeyManagementException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.KeyManagementException#KeyManagementException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "KeyManagementException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.KeyManagementException()
-        KeyManagementException e = new KeyManagementException();
-        assertEquals("Failed toString test for constructed instance",
-                "java.security.KeyManagementException", e.toString());
-    }
-
-    /**
-     * @tests java.security.KeyManagementException#KeyManagementException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Checking with null and empty string parameter missed",
-        method = "KeyManagementException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method
-        // java.security.KeyManagementException(java.lang.String)
-        KeyManagementException e = new KeyManagementException("test message");
-        assertEquals("Failed toString test for constructed instance",
-                "java.security.KeyManagementException: test message",
-                e.toString());
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java
index 817de35..059cef4 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java
@@ -1372,4 +1372,4 @@
         }
 
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreException2Test.java
deleted file mode 100644
index b3c9583..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreException2Test.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.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.KeyStoreException;
-
-@TestTargetClass(KeyStoreException.class)
-public class KeyStoreException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.KeyStoreException#KeyStoreException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "KeyStoreException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.KeyStoreException()
-        KeyStoreException e = new KeyStoreException();
-        assertEquals("Failed toString test for constructed instance", "java.security.KeyStoreException", e
-                .toString());
-    }
-
-    /**
-     * @tests java.security.KeyStoreException#KeyStoreException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Verifies constructor with one variant of string parameter",
-        method = "KeyStoreException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method java.security.KeyStoreException(java.lang.String)
-        KeyStoreException e = new KeyStoreException("test message");
-        assertEquals("Failed toString test for constructed instance", 
-                        "java.security.KeyStoreException: test message", e
-                .toString());
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStorePrivateKeyEntryTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStorePrivateKeyEntryTest.java
new file mode 100644
index 0000000..42feeec
--- /dev/null
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStorePrivateKeyEntryTest.java
@@ -0,0 +1,79 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+ 
+package org.apache.harmony.security.tests.java.security;
+
+import java.io.ByteArrayInputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import junit.framework.TestCase;
+
+public class KeyStorePrivateKeyEntryTest extends TestCase {
+
+    public void testGetCertificateChain() throws Exception {
+
+        String certificateData = "-----BEGIN CERTIFICATE-----\n"
+                + "MIICZTCCAdICBQL3AAC2MA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMSAw\n"
+                + "HgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5jLjEuMCwGA1UECxMlU2VjdXJl\n"
+                + "IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NzAyMjAwMDAwMDBa\n"
+                + "Fw05ODAyMjAyMzU5NTlaMIGWMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv\n"
+                + "cm5pYTESMBAGA1UEBxMJUGFsbyBBbHRvMR8wHQYDVQQKExZTdW4gTWljcm9zeXN0\n"
+                + "ZW1zLCBJbmMuMSEwHwYDVQQLExhUZXN0IGFuZCBFdmFsdWF0aW9uIE9ubHkxGjAY\n"
+                + "BgNVBAMTEWFyZ29uLmVuZy5zdW4uY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\n"
+                + "iQKBgQCofmdY+PiUWN01FOzEewf+GaG+lFf132UpzATmYJkA4AEA/juW7jSi+LJk\n"
+                + "wJKi5GO4RyZoyimAL/5yIWDV6l1KlvxyKslr0REhMBaD/3Z3EsLTTEf5gVrQS6sT\n"
+                + "WMoSZAyzB39kFfsB6oUXNtV8+UKKxSxKbxvhQn267PeCz5VX2QIDAQABMA0GCSqG\n"
+                + "SIb3DQEBAgUAA34AXl3at6luiV/7I9MN5CXYoPJYI8Bcdc1hBagJvTMcmlqL2uOZ\n"
+                + "H9T5hNMEL9Tk6aI7yZPXcw/xI2K6pOR/FrMp0UwJmdxX7ljV6ZtUZf7pY492UqwC\n"
+                + "1777XQ9UEZyrKJvF5ntleeO0ayBqLGVKCWzWZX9YsXCpv47FNLZbupE=\n"
+                + "-----END CERTIFICATE-----\n";
+
+        ByteArrayInputStream certArray;
+        {
+            try{
+                 certArray = new ByteArrayInputStream(
+                    certificateData.getBytes("UTF-8"));
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e.getMessage());
+            }
+        }
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        Certificate certificate = cf.generateCertificate(certArray);
+        assertTrue(certificate instanceof X509Certificate);
+
+        String algorithm = certificate.getPublicKey().getAlgorithm();
+        KeyPairGenerator keyPairGenerator = KeyPairGenerator
+                .getInstance(algorithm);
+        KeyPair keyPair = keyPairGenerator.generateKeyPair();
+        PrivateKey privateKey = keyPair.getPrivate();
+
+        // If all the certificate in the chain is X509Certificate,
+        // KeyStore.PrivateKeyEntry will return a X509Certificate array.
+        KeyStore.PrivateKeyEntry privateKeyEntry = new KeyStore.PrivateKeyEntry(
+                privateKey, new Certificate[] { certificate });
+        Certificate[] chain = privateKeyEntry.getCertificateChain();
+        assertTrue(chain instanceof X509Certificate[]);
+
+    }
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java
index d7ae43f..210116e 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java
@@ -47,6 +47,8 @@
 import java.util.Date;
 import java.util.Set;
 import java.math.BigInteger;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
 
 import org.apache.harmony.security.tests.support.KeyStoreTestSupport;
 import org.apache.harmony.security.tests.support.MyLoadStoreParams;
@@ -277,6 +279,35 @@
         
     }
 
+
+    /*
+     * @tests java.security.KeyStoreSpi.engineEntryInstanceOf(String, Class<? extends Entry>)
+     */
+    public void testEngineEntryInstanceOf() throws Exception {
+        //Regression for HARMONY-615
+
+        // create a KeyStore 
+        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        keyStore.load(null, "pwd".toCharArray());
+
+        // generate a key 
+        KeyGenerator keyGen = KeyGenerator.getInstance("DES");
+        keyGen.init(56);
+        SecretKey secretKey = keyGen.generateKey();
+
+        // put the key into keystore 
+        String alias = "alias";
+        keyStore.setKeyEntry(alias, secretKey, "pwd".toCharArray(), null);
+
+        // check if it is a secret key 
+        assertTrue(keyStore.entryInstanceOf(alias,
+                KeyStore.SecretKeyEntry.class));
+
+        // check if it is NOT a private key 
+        assertFalse(keyStore.entryInstanceOf(alias,
+                KeyStore.PrivateKeyEntry.class));
+    }
+
     /**
      * @tests java.security.KeyStore.TrustedCertificateEntry.toString()
      */
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
index c26708d..9eca936 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
@@ -25,6 +25,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.security.DigestException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -676,4 +677,4 @@
         }
         
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java
index b7c11e5..8bcb392 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java
@@ -109,29 +109,29 @@
     )
     public void test_engineDigestLB$LILI() throws Exception {
 
-        final int DIGEST_LENGHT = 2;
+        final int DIGEST_LENGTH = 2;
 
         MyMessageDigest md = new MyMessageDigest() {
 
             public int engineGetDigestLength() {
-                return DIGEST_LENGHT;
+                return DIGEST_LENGTH;
             }
 
             public byte[] engineDigest() {
-                return new byte[DIGEST_LENGHT]; // return non-null value
+                return new byte[DIGEST_LENGTH]; // return non-null value
             }
         };
 
         byte[] b = new byte[5];
         try {
             // test: null output buffer
-            md.engineDigest(null, 1, DIGEST_LENGHT);
+            md.engineDigest(null, 1, DIGEST_LENGTH);
             fail("No expected NullPointerException");
         } catch (NullPointerException e) {
         }
         try {
             //test: len param < digest length
-            md.engineDigest(b, 1, DIGEST_LENGHT - 1);
+            md.engineDigest(b, 1, DIGEST_LENGTH - 1);
             fail("No expected DigestException");
         } catch (DigestException e) {
         }
@@ -153,7 +153,7 @@
             // ok
         }
 
-        assertEquals("incorrect result", DIGEST_LENGHT, md
+        assertEquals("incorrect result", DIGEST_LENGTH, md
                 .engineDigest(b, 1, 3));
         
         // Regression for HARMONY-3045
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchAlgorithmException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchAlgorithmException2Test.java
deleted file mode 100644
index 289047b..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchAlgorithmException2Test.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.NoSuchAlgorithmException;
-
-@TestTargetClass(NoSuchAlgorithmException.class)
-public class NoSuchAlgorithmException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.NoSuchAlgorithmException#NoSuchAlgorithmException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "NoSuchAlgorithmException",
-        args = {}
-    )
-    public void test_Constructor() {
-        try {
-            throw new NoSuchAlgorithmException();
-        } catch (NoSuchAlgorithmException e) {
-            assertNull("Message should be null", e.getMessage());
-            assertEquals("Unexpected toString value",
-                    "java.security.NoSuchAlgorithmException", e.toString());
-        }
-    }
-
-    /**
-     * @tests java.security.NoSuchAlgorithmException#NoSuchAlgorithmException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Null parameter checking missed",
-        method = "NoSuchAlgorithmException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method
-        // java.security.NoSuchAlgorithmException(java.lang.String)
-        try {
-            throw new NoSuchAlgorithmException("Test string");
-        } catch (NoSuchAlgorithmException e) {
-            assertEquals("Wrong message", "Test string", e.getMessage());
-            assertEquals("Unexpected toString value",
-                    "java.security.NoSuchAlgorithmException: Test string", e
-                            .toString());
-        }
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchProviderException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchProviderException2Test.java
deleted file mode 100644
index 256ed66..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchProviderException2Test.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.NoSuchProviderException;
-
-@TestTargetClass(NoSuchProviderException.class)
-public class NoSuchProviderException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.NoSuchProviderException#NoSuchProviderException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "NoSuchProviderException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.NoSuchProviderException()
-        try {
-            throw new NoSuchProviderException();
-        } catch (NoSuchProviderException e) {
-            assertNull("Message should be null", e.getMessage());
-            assertEquals("Unexpected toString value",
-                    "java.security.NoSuchProviderException", e.toString());
-        }
-    }
-
-    /**
-     * @tests java.security.NoSuchProviderException#NoSuchProviderException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Null parameter checking missed",
-        method = "NoSuchProviderException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method
-        // java.security.NoSuchProviderException(java.lang.String)
-        try {
-            throw new NoSuchProviderException("Test string");
-        } catch (NoSuchProviderException e) {
-            assertEquals("Wrong message", "Test string", e.getMessage());
-            assertEquals("Unexpected toString value",
-                    "java.security.NoSuchProviderException: Test string", e
-                            .toString());
-        }
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java
index af33804..a60adbf 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java
@@ -55,7 +55,7 @@
     public void test_Constructor() {
         // Test for method java.security.Permissions()
         new Permissions();
-    }
+	}
 
     /**
      * @tests java.security.Permissions#add(java.security.Permission)
@@ -192,4 +192,4 @@
         public void checkPermission(Permission permission) {
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java
index 78038b5..cfa2af1 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java
@@ -395,7 +395,7 @@
         
         String policyFile = getClass().getClassLoader().getResource(
                 "PolicyTest.txt").toString();
-        String oldSysProp = System.getProperty(JAVA_SECURITY_POLICY);
+        String oldJavaPolicy = System.getProperty(JAVA_SECURITY_POLICY);
         Policy oldPolicy = Policy.getPolicy();
 
         try {
@@ -404,12 +404,20 @@
             // test: absolute paths
             assertCodeBasePropertyExpansion("/11111/*", "/11111/-");
             assertCodeBasePropertyExpansion("/22222/../22222/*", "/22222/-");
+            assertCodeBasePropertyExpansion("/33333/*", "/33333/../33333/-");
+            assertCodeBasePropertyExpansion("/44444/../44444/-", "/44444/*");
+            assertCodeBasePropertyExpansion("/55555/../55555/-", "/55555/../55555/-");
+            assertCodeBasePropertyExpansion("/666 66 66/-", "/666 66 66/-");
 
             // test: relative paths
-            assertCodeBasePropertyExpansion("44444/*", "44444/-");
-            assertCodeBasePropertyExpansion("55555/../55555/*", "55555/-");
+            assertCodeBasePropertyExpansion("11111/*", "11111/-");
+            assertCodeBasePropertyExpansion("22222/../22222/*", "22222/-");
+            assertCodeBasePropertyExpansion("33333/*", "33333/../33333/-");
+            assertCodeBasePropertyExpansion("44444/../44444/-", "44444/*");
+            assertCodeBasePropertyExpansion("55555/../55555/-", "55555/../55555/-");
+            assertCodeBasePropertyExpansion("666 66 66/-", "666 66 66/-");
         } finally {
-            TestUtils.setSystemProperty(JAVA_SECURITY_POLICY, oldSysProp);
+            TestUtils.setSystemProperty(JAVA_SECURITY_POLICY, oldJavaPolicy);
             Policy.setPolicy(oldPolicy);
         }
     }
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java
index 48e8f32..a8ec69a 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java
@@ -22,7 +22,10 @@
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetNew;
 
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.security.Provider;
+import java.security.Security;
 
 @TestTargetClass(Provider.class)
 public class Provider2Test extends junit.framework.TestCase {
@@ -172,4 +175,44 @@
         // Regression for HARMONY-3734
         assertEquals("provTest version 1.2", provTest.toString());
     }
+    
+    // Regression Test for Provider.Service.getAlias(), which is an package
+    // private method but will lead to NPE thrown at
+    // Secure.SecurityDorr.getAliases
+    public void test_getAlias() throws Exception {
+        MockProvider mockProvider = new MockProvider("MOCKNAME", 1.0,
+                "MOCKINFO");
+        Provider.Service service = new Provider.Service(mockProvider,
+                "MOCKTYPE", "MOCKALGORITHM", "TESTCLASSNAME", null, null);
+        mockProvider.putService(service);
+        Security.addProvider(mockProvider);
+        try {
+            MessageDigest messageDigest = MessageDigest
+                    .getInstance("NOTEXISTS");
+        }
+
+        catch (NoSuchAlgorithmException e) {
+            // expected
+        } finally {
+            Security.removeProvider("MOCKNAME");
+        }
+    }
+
+    public static class MockProvider extends Provider {
+
+        private static final long serialVersionUID = 1L;
+
+        public MockProvider(String name, double version, String info) {
+            super(name, version, info);
+
+        }
+
+        public void putService(Provider.Service service) {
+            super.putService(service);
+        }
+
+        public void removeService(Provider.Service service) {
+            super.removeService(service);
+        }
+    }
 }
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderException2Test.java
deleted file mode 100644
index 4b0f2ec..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderException2Test.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.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.ProviderException;
-
-@TestTargetClass(ProviderException.class)
-public class ProviderException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.ProviderException#ProviderException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "ProviderException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.ProviderException()
-        ProviderException e = new ProviderException();
-        assertEquals("Failed toString test for constructed instance",
-                "java.security.ProviderException", e.toString());
-    }
-
-    /**
-     * @tests java.security.ProviderException#ProviderException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Verification with null/empty parameter is absent",
-        method = "ProviderException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method java.security.ProviderException(java.lang.String)
-        ProviderException e = new ProviderException("test message");
-        assertEquals("Failed toString test for constructed instance", 
-                        "java.security.ProviderException: test message", e
-                .toString());
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java
index c93011c..730e329 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java
@@ -138,22 +138,16 @@
         method = "newInstance",
         args = {java.lang.Object.class}
     )
-    public void testNewInstance() {
+    public void testNewInstance() throws Exception {
         Provider p = new MyProvider();
         Provider.Service s = new Provider.Service(p, "SecureRandom",
-                "algorithm", "org.apache.harmony.security.tests.support.RandomImpl", null,
-                null);
-        Object o = null;
-        try {
-            o = s.newInstance(null);
-        } catch (NoSuchAlgorithmException e) {
-            e.printStackTrace();
-            fail("newInstance() failed");
-        }
-        if (!(o instanceof RandomImpl)) {
-            fail("incorrect instance");
-        }
+                "algorithm",
+                "org.apache.harmony.security.tests.support.RandomImpl",
+                null, null);
 
+        Object o = s.newInstance(null);
+        assertTrue("incorrect instance", o instanceof RandomImpl);
+        
         try {
             o = s.newInstance(new Object());
             fail("No expected NoSuchAlgorithmException");
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java
index a3b3077..3cc447f 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java
@@ -129,27 +129,9 @@
     )
     public final void testClear() {
         p.clear();
-        if (p.getProperty("MessageDigest.ASH-1") != null) {
-            fail("Provider contains properties");
-        }
+        assertNull(p.getProperty("MessageDigest.SHA-1"));
     }
     
-    @TestTargetNew(
-            level = TestLevel.PARTIAL_COMPLETE,
-            notes = "",
-            method = "clear",
-            args = {}
-        )
-    public final void testClear_SecurityManager() {
-        TestSecurityManager sm = new TestSecurityManager("clearProviderProperties.MyProvider");
-        System.setSecurityManager(sm);
-        p.clear();
-        assertTrue("Provider.clear must call checkPermission with "
-                + "SecurityPermission clearProviderProperties.NAME",
-                sm.called);
-        System.setSecurityManager(null);
-    }
-
     /*
      * Class under test for void Provider(String, double, String)
      */
@@ -161,22 +143,13 @@
     )
     public final void testProviderStringdoubleString() {
         Provider p = new MyProvider("Provider name", 123.456, "Provider info");
-        if (!p.getName().equals("Provider name") || p.getVersion() != 123.456
-                || !p.getInfo().equals("Provider info")) {
-            fail("Incorrect values");
-        }
+        assertEquals("Provider name", p.getName());
+        assertEquals(123.456, p.getVersion(), 0L);
+        assertEquals("Provider info", p.getInfo());
     }
 
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getName",
-        args = {}
-    )
     public final void testGetName() {
-        if (!p.getName().equals("MyProvider")) {
-            fail("Incorrect provider name");
-        }
+        assertEquals("MyProvider", p.getName());
     }
 
     @TestTargetNew(
@@ -186,9 +159,7 @@
         args = {}
     )
     public final void testGetVersion() {
-        if (p.getVersion() != 1.0) {
-            fail("Incorrect provider version");
-        }
+        assertEquals(1.0, p.getVersion(), 0L);
     }
 
     @TestTargetNew(
@@ -198,9 +169,7 @@
         args = {}
     )
     public final void testGetInfo() {
-        if (!p.getInfo().equals("Provider for testing")) {
-            fail("Incorrect provider info");
-        }
+        assertEquals("Provider for testing", p.getInfo());
     }
 
     /*
@@ -213,19 +182,16 @@
         args = {java.util.Map.class}
     )
     public final void testPutAllMap() {
-        HashMap<String, String> hm = new HashMap<String, String>();
-        hm.put("MessageDigest.ASH-1", "aaa.bbb.ccc.ddd");
+        HashMap hm = new HashMap();
+        hm.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
         hm.put("Property 1", "value 1");
         hm.put("serviceName.algName attrName", "attrValue");
-        hm.put("Alg.Alias.engineClassName.aliasName", "stanbdardName");
+        hm.put("Alg.Alias.engineClassName.aliasName", "standardName");
         p.putAll(hm);
-        if (!"value 1".equals(p.getProperty("Property 1").trim())
-                || !"attrValue".equals(p.getProperty(
-                        "serviceName.algName attrName").trim())
-                || !"stanbdardName".equals(p.getProperty(
-                        "Alg.Alias.engineClassName.aliasName").trim())
-                || !"aaa.bbb.ccc.ddd".equals(p.getProperty(
-                        "MessageDigest.ASH-1").trim())) {
+        if (!"value 1".equals(p.getProperty("Property 1").trim()) ||
+                !"attrValue".equals(p.getProperty("serviceName.algName attrName").trim()) ||
+                !"standardName".equals(p.getProperty("Alg.Alias.engineClassName.aliasName").trim()) ||
+                !"aaa.bbb.ccc.ddd".equals(p.getProperty("MessageDigest.SHA-1").trim()) ) {
             fail("Incorrect property value");
         }
     }
@@ -240,48 +206,43 @@
         args = {}
     )
     public final void testEntrySet() {
-        p.put("MessageDigest.ASH-256", "aaa.bbb.ccc.ddd");
-
-        Set<Map.Entry<Object, Object>> s = p.entrySet();
+        p.put("MessageDigest.SHA-256", "aaa.bbb.ccc.ddd");
+        
+        Set s = p.entrySet();
         try {
             s.clear();
             fail("Must return unmodifiable set");
         } catch (UnsupportedOperationException e) {
         }
-
+        
         assertEquals("Incorrect set size", 8, s.size());
-
-        for (Iterator<Entry<Object, Object>> it = s.iterator(); it.hasNext();) {
-            Entry<Object, Object> e = it.next();
-            String key = (String) e.getKey();
-            String val = (String) e.getValue();
-            if (key.equals("MessageDigest.ASH-1")
-                    && val.equals("SomeClassName")) {
+        
+        for (Iterator it = s.iterator(); it.hasNext();) {
+            Entry e = (Entry)it.next();
+            String key = (String)e.getKey();
+            String val = (String)e.getValue();
+            if (key.equals("MessageDigest.SHA-1") && val.equals("SomeClassName")) {
                 continue;
             }
-            if (key.equals("Alg.Alias.MessageDigest.ASH1")
-                    && val.equals("ASH-1")) {
+            if (key.equals("Alg.Alias.MessageDigest.SHA1") && val.equals("SHA-1")) {
                 continue;
             }
             if (key.equals("MessageDigest.abc") && val.equals("SomeClassName")) {
                 continue;
             }
-            if (key.equals("Provider.id className")
-                    && val.equals(p.getClass().getName())) {
+            if (key.equals("Provider.id className") && val.equals(p.getClass().getName())) {
                 continue;
             }
             if (key.equals("Provider.id name") && val.equals("MyProvider")) {
                 continue;
             }
-            if (key.equals("MessageDigest.ASH-256")
-                    && val.equals("aaa.bbb.ccc.ddd")) {
+            if (key.equals("MessageDigest.SHA-256") && val.equals("aaa.bbb.ccc.ddd")) {
                 continue;
             }
             if (key.equals("Provider.id version") && val.equals("1.0")) {
                 continue;
             }
-            if (key.equals("Provider.id info")
-                    && val.equals("Provider for testing")) {
+            if (key.equals("Provider.id info") && val.equals("Provider for testing")) {
                 continue;
             }
             fail("Incorrect set");
@@ -298,30 +259,27 @@
         args = {}
     )
     public final void testKeySet() {
-        p.put("MessageDigest.ASH-256", "aaa.bbb.ccc.ddd");
+        p.put("MessageDigest.SHA-256", "aaa.bbb.ccc.ddd");
 
         Set<Object> s = p.keySet();
         try {
             s.clear();
         } catch (UnsupportedOperationException e) {
         }
-        Set<Object> s1 = p.keySet();
-        if ((s == s1) || s1.isEmpty()) {
-            fail("Must return unmodifiable set");
-        }
-        if (s1.size() != 8) {
-            fail("Incorrect set size");
-        }
-        if (!s1.contains("MessageDigest.ASH-256")
-                || !s1.contains("MessageDigest.ASH-1")
-                || !s1.contains("Alg.Alias.MessageDigest.ASH1")
-                || !s1.contains("MessageDigest.abc")
-                || !s1.contains("Provider.id info")
-                || !s1.contains("Provider.id className")
-                || !s1.contains("Provider.id version")
-                || !s1.contains("Provider.id name")) {
-            fail("Incorrect set");
-        }
+        Set s1 = p.keySet();
+
+        assertNotSame(s, s1);
+        assertFalse(s1.isEmpty());
+        assertEquals(8, s1.size());
+
+        assertTrue(s1.contains("MessageDigest.SHA-256"));
+        assertTrue(s1.contains("MessageDigest.SHA-1"));
+        assertTrue(s1.contains("Alg.Alias.MessageDigest.SHA1"));
+        assertTrue(s1.contains("MessageDigest.abc"));
+        assertTrue(s1.contains("Provider.id info"));
+        assertTrue(s1.contains("Provider.id className"));
+        assertTrue(s1.contains("Provider.id version"));
+        assertTrue(s1.contains("Provider.id name"));
     }
 
     /*
@@ -341,19 +299,19 @@
             c.clear();
         } catch (UnsupportedOperationException e) {
         }
-        Collection<Object> c1 = p.values();
-        if ((c == c1) || c1.isEmpty()) {
-            fail("Must return unmodifiable set");
-        }
-        if (c1.size() != 8) {
-            fail("Incorrect set size " + c1.size());
-        }
-        if (!c1.contains("MyProvider") || !c1.contains("aaa.bbb.ccc.ddd")
-                || !c1.contains("Provider for testing") || !c1.contains("1.0")
-                || !c1.contains("SomeClassName") || !c1.contains("ASH-1")
-                || !c1.contains(p.getClass().getName())) {
-            fail("Incorrect set");
-        }
+        Collection c1 = p.values();
+
+        assertNotSame(c, c1);
+        assertFalse(c1.isEmpty());
+        assertEquals(8, c1.size());
+
+        assertTrue(c1.contains("MyProvider"));
+        assertTrue(c1.contains("aaa.bbb.ccc.ddd"));
+        assertTrue(c1.contains("Provider for testing"));
+        assertTrue(c1.contains("1.0"));
+        assertTrue(c1.contains("SomeClassName"));
+        assertTrue(c1.contains("SHA-1"));
+        assertTrue(c1.contains(p.getClass().getName()));
     }
 
     /*
@@ -366,38 +324,124 @@
         args = {java.lang.Object.class, java.lang.Object.class}
     )
     public final void testPutObjectObject() {
-        p.put("MessageDigest.ASH-1", "aaa.bbb.ccc.ddd");
+        p.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
         p.put("Type.Algorithm", "className");
-        if (!"aaa.bbb.ccc.ddd".equals(p.getProperty("MessageDigest.ASH-1")
-                .trim())) {
-            fail("Incorrect property value");
-        }
-
-        Set<Service> services = p.getServices();
-        if (services.size() != 3) {
-            fail("incorrect size");
-        }
-        for (Iterator<Service> it = services.iterator(); it.hasNext();) {
-            Provider.Service s = it.next();
-            if ("Type".equals(s.getType())
-                    && "Algorithm".equals(s.getAlgorithm())
-                    && "className".equals(s.getClassName())) {
+        assertEquals("aaa.bbb.ccc.ddd", p.getProperty("MessageDigest.SHA-1")
+                .trim());
+        
+        Set services = p.getServices();
+        assertEquals(3, services.size());
+        
+        for (Iterator it = services.iterator(); it.hasNext();) {
+            Provider.Service s = (Provider.Service)it.next();
+            if ("Type".equals(s.getType()) &&
+                    "Algorithm".equals(s.getAlgorithm()) &&
+                    "className".equals(s.getClassName())) {
                 continue;
             }
-            if ("MessageDigest".equals(s.getType())
-                    && "ASH-1".equals(s.getAlgorithm())
-                    && "aaa.bbb.ccc.ddd".equals(s.getClassName())) {
+            if ("MessageDigest".equals(s.getType()) &&
+                    "SHA-1".equals(s.getAlgorithm()) &&
+                    "aaa.bbb.ccc.ddd".equals(s.getClassName())) {
                 continue;
             }
-            if ("MessageDigest".equals(s.getType())
-                    && "abc".equals(s.getAlgorithm())
-                    && "SomeClassName".equals(s.getClassName())) {
+            if ("MessageDigest".equals(s.getType()) &&
+                    "abc".equals(s.getAlgorithm()) &&
+                    "SomeClassName".equals(s.getClassName())) {
                 continue;
             }
             fail("Incorrect service");
         }
     }
 
+    /*
+     * Class under test for Object remove(Object)
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "remove",
+        args = {java.lang.Object.class}
+    )
+    public final void testRemoveObject() {
+        Object o = p.remove("MessageDigest.SHA-1");
+
+        assertEquals("SomeClassName", o);
+        assertNull(p.getProperty("MessageDigest.SHA-1"));
+        assertEquals(1, p.getServices().size());
+    }
+ 
+    public final void testService1() {
+        p.put("MessageDigest.SHA-1", "AnotherClassName");
+        Provider.Service s = p.getService("MessageDigest", "SHA-1");
+
+        assertEquals("AnotherClassName", s.getClassName());
+    }
+
+    // Regression for HARMONY-2760.
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Regression test: verifies constructor with two null parameters.",
+        method = "Provider",
+        args = {java.lang.String.class, double.class, java.lang.String.class}
+    )
+    public void testConstructor() {
+        MyProvider myProvider = new MyProvider(null, 1, null);
+        assertNull(myProvider.getName());
+        assertNull(myProvider.getInfo());
+        assertEquals("null", myProvider.getProperty("Provider.id name"));
+        assertEquals("null", myProvider.getProperty("Provider.id info"));
+    }
+
+    class MyProvider extends Provider {
+        MyProvider() {
+            super("MyProvider", 1.0, "Provider for testing");
+            put("MessageDigest.SHA-1", "SomeClassName");
+            put("MessageDigest.abc", "SomeClassName");
+            put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
+        }
+        
+        MyProvider(String name, double version, String info) {
+            super(name, version, info);
+        }
+        
+        // BEGIN android-added
+        public void putService(Provider.Service s) {
+            super.putService(s);
+        }
+        // END android-added
+        
+        // BEGIN android-added
+        public void removeService(Provider.Service s) {
+            super.removeService(s);
+        }
+        // END android-added
+        
+        // BEGIN android-added
+        public int getNumServices() {
+            return getServices().size();
+        }
+        // END android-added
+    }
+
+    // BEGIN android-added
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "clear",
+            args = {}
+        )
+    public final void testClear_SecurityManager() {
+        TestSecurityManager sm = new TestSecurityManager("clearProviderProperties.MyProvider");
+        System.setSecurityManager(sm);
+        p.clear();
+        assertTrue("Provider.clear must call checkPermission with "
+                + "SecurityPermission clearProviderProperties.NAME",
+                sm.called);
+        System.setSecurityManager(null);
+    }
+    // END android-added
+
+    // BEGIN android-added
     @TestTargetNew(
             level = TestLevel.PARTIAL_COMPLETE,
             notes = "",
@@ -414,39 +458,9 @@
                 + "SecurityPermission putProviderProperty.Name", sm.called);
         System.setSecurityManager(null);
     }
+    // END android-added
 
-    /*
-     * Class under test for Object remove(Object)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "remove",
-        args = {java.lang.Object.class}
-    )
-    public final void testRemoveObject() {
-        Object o = p.remove("MessageDigest.ASH-1");
-        if (!"SomeClassName".equals(o)) {
-            fail("Incorrect return value");
-        }
-        if (p.getProperty("MessageDigest.ASH-1") != null) {
-            fail("Provider contains properties");
-        }
-        if (p.getServices().size() != 1) {
-            fail("Service not removed");
-        }
-
-        try {
-            p.remove(null);
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // ok
-        }
-    }
-
-    /*
-     * Class under test for Object remove(Object)
-     */
+    // BEGIN android-added
     @TestTargetNew(
         level = TestLevel.PARTIAL_COMPLETE,
         notes = "",
@@ -463,35 +477,9 @@
                 sm.called);
         System.setSecurityManager(null);
     }
+    // END android-added
 
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getService",
-        args = {java.lang.String.class, java.lang.String.class}
-    )
-    public final void testService1() {
-        p.put("MessageDigest.ASH-1", "AnotherClassName");
-        Provider.Service s = p.getService("MessageDigest", "ASH-1");
-        if (!"AnotherClassName".equals(s.getClassName())) {
-            fail("Incorrect class name " + s.getClassName());
-        }
-        
-        try {
-           p.getService("MessageDigest", null);
-           fail("expected NullPointerException");
-        } catch (NullPointerException e)  {
-            // ok;
-        }
-        
-        try {
-            p.getService(null, "ASH-1");
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // ok
-        }
-    }
-
+    // BEGIN android-added
     @TestTargetNew(
             level = TestLevel.COMPLETE,
             notes = "",
@@ -516,23 +504,9 @@
         } catch (NoSuchAlgorithmException e) {
         }
     }
-     
+    // END android-added
 
-    // Regression for HARMONY-2760.
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "Regression test: verifies constructor with two null parameters.",
-        method = "Provider",
-        args = {java.lang.String.class, double.class, java.lang.String.class}
-    )
-    public void testConstructor() {
-        MyProvider myProvider = new MyProvider(null, 1, null);
-        assertNull(myProvider.getName());
-        assertNull(myProvider.getInfo());
-        assertEquals("null", myProvider.getProperty("Provider.id name"));
-        assertEquals("null", myProvider.getProperty("Provider.id info"));
-    }
-
+    // BEGIN android-added
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
@@ -576,7 +550,9 @@
         assertTrue(!actual.contains(s[1]));
         assertTrue(actual.contains(s[2]));
     }
+    // END android-added
 
+    // BEGIN android-added
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
@@ -631,7 +607,9 @@
             // expected
         }
     }
+    // END android-added
 
+    // BEGIN android-added
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
@@ -703,10 +681,9 @@
             // expected
         }
     }
+    // END android-added
 
-    /*
-     * Class under test for void load(InputStream)
-     */
+    // BEGIN android-added
     @TestTargetNew(
         level = TestLevel.PARTIAL_COMPLETE,
         notes = "",
@@ -735,7 +712,9 @@
             // expected
         }
     }
-    
+    // END android-added
+
+    // BEGIN android-added
     @TestTargetNew(
             level = TestLevel.PARTIAL_COMPLETE,
             notes = "",
@@ -755,11 +734,12 @@
             p.load(new TestInputStream());
             fail("expected IOException");
         } catch (IOException e) {
-            // ok
+            // expected
         }
-        
     }
+    // END android-added
 
+    // BEGIN android-added
     protected byte[] writeProperties() {
         ByteArrayOutputStream bout = new ByteArrayOutputStream();
         PrintStream ps = new PrintStream(bout);
@@ -769,34 +749,9 @@
         ps.close();
         return bout.toByteArray();
     }
+    // END android-added
 
-    class MyProvider extends Provider {
-       // private Set<Provider.Service> services = null;
-
-        MyProvider() {
-            super("MyProvider", 1.0, "Provider for testing");
-            put("MessageDigest.ASH-1", "SomeClassName");
-            put("MessageDigest.abc", "SomeClassName");
-            put("Alg.Alias.MessageDigest.ASH1", "ASH-1");
-        }
-
-        MyProvider(String name, double version, String info) {
-            super(name, version, info);
-        }
-
-        public void putService(Provider.Service s) {
-            super.putService(s);
-        }
-
-        public void removeService(Provider.Service s) {
-            super.removeService(s);
-        }
-
-        public int getNumServices() {
-            return getServices().size();
-        }
-    }
-    
+    // BEGIN android-added
     static class TestSecurityManager extends SecurityManager {
         boolean called = false;
         private final String permissionName;
@@ -814,4 +769,5 @@
             }
         }
     }
+    // END android-added
 }
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java
index 49a0365..a59ada5 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java
@@ -358,4 +358,4 @@
             Security.removeProvider(entrust.getName());
         }
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java
index c03afc5..aa4c71b 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java
@@ -205,9 +205,7 @@
             }
             assertEquals("Providers not removed", 0,
                     Security.getProviders().length);
-        } catch (Exception e) {
-            e.printStackTrace();
-        } finally { // restore providers
+        } finally {    // restore providers
             for (int i = 0; i < providers.length; i++) {
                 Security.addProvider(providers[i]);
             }
@@ -453,6 +451,9 @@
             fail("No expected NullPointerException.");
         } catch (NullPointerException e) {
         }
+        
+        Security.setProperty("myprop","test white space    ");
+        assertEquals("test white space", Security.getProperty("myprop"));
     }
 
     /**
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
index 20bc4b1..a657f60 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
@@ -39,6 +39,7 @@
 import java.security.cert.Certificate;
 import java.security.spec.DSAParameterSpec;
 import java.util.HashSet;
+import java.util.Locale;
 import java.util.Set;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignatureException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignatureException2Test.java
deleted file mode 100644
index 9a6209a..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignatureException2Test.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.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-
-import java.security.SignatureException;
-
-@TestTargetClass(SignatureException.class)
-public class SignatureException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.SignatureException#SignatureException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "SignatureException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.SignatureException()
-        SignatureException e = new SignatureException();
-        assertEquals("Failed toString test for constructed instance", "java.security.SignatureException", e
-                .toString());
-    }
-
-    /**
-     * @tests java.security.SignatureException#SignatureException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Verification with null string parameter missed",
-        method = "SignatureException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method java.security.SignatureException(java.lang.String)
-        SignatureException e = new SignatureException("test message");
-        assertEquals("Failed toString test for constructed instance", 
-                        "java.security.SignatureException: test message", e
-                .toString());
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java
index 77f341b..89d872e 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package org.apache.harmony.security.tests.java.security;
 
 import dalvik.annotation.TestLevel;
@@ -27,6 +22,11 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
 
+import java.security.NoSuchAlgorithmException;
+import java.security.Signature;
+import java.security.SignedObject;
+import java.util.Properties;
+
 import junit.framework.TestCase;
 
 import org.apache.harmony.security.tests.support.TestKeyPair;
@@ -47,7 +47,6 @@
 @TestTargetClass(SignedObject.class)
 /**
  * Tests for <code>SignedObject</code> constructor and methods
- * 
  */
 public class SignedObjectTest extends TestCase {
 
@@ -83,17 +82,11 @@
             args = {java.security.PublicKey.class, java.security.Signature.class}
         )
     })
-    public void testSignedObject() {
-        Signature sig = null;
+    public void testSignedObject() throws Exception {
         TestKeyPair tkp = null;
         Properties prop;
-        
-        try {
-            sig = Signature.getInstance("SHA1withDSA");        
-        } catch (NoSuchAlgorithmException e) {
-            fail(e.toString());
-        }
-        
+        Signature sig = Signature.getInstance("SHA1withDSA");
+
         try {
             tkp = new TestKeyPair("DSA");
         } catch (NoSuchAlgorithmException e) {
@@ -102,133 +95,14 @@
         }
         prop = new Properties();
         prop.put("aaa", "bbb");
-        SignedObject so = null;
-        try {
-            so = new SignedObject(prop, tkp.getPrivate(), sig);
-        } catch (IOException e) {
-               fail(e.toString());  
-        } catch (SignatureException e) {   
-               fail(e.toString());  
-        } catch (InvalidKeyException e) {
-               fail(e.toString());  
-        } catch (InvalidKeySpecException e) {
-              fail(e.toString());
-        }
+
+        SignedObject so = new SignedObject(prop, tkp.getPrivate(), sig);
 
         assertEquals("SHA1withDSA", so.getAlgorithm());
- 
-        try {
-            assertEquals(so.getObject(), prop);          
-        } catch (ClassNotFoundException e) {
-               fail(e.toString());  
-        } catch (IOException e) {
-               fail(e.toString());  
-        }
-        try {
-            if (!so.verify(tkp.getPublic(), sig)) {
-                fail("verify() failed");
-            }    
-        } catch (SignatureException e) {
-            fail(e.toString());          
-        } catch (InvalidKeyException e) {
-               fail(e.toString());             
-        } catch (InvalidKeySpecException e) {
-               fail(e.toString()); 
-        }
-        
-        if (so.getSignature() == null) {
-            fail("signature is null");
-        }
-        
-        try {
-            TestKeyPair tkp2 = new TestKeyPair("DH");
-            so = new SignedObject(prop, tkp2.getPrivate(), sig);
-        } catch(InvalidKeyException e) {
-            // ok
-        } catch (NoSuchAlgorithmException e) {
-            fail(e.toString()); 
-        } catch (SignatureException e) {
-            fail(e.toString()); 
-        } catch (InvalidKeySpecException e) {
-            fail(e.toString()); 
-        } catch (IOException e) {
-            fail(e.toString()); 
-        }
-        
-        try {
-            new SignedObject(new Serializable() {
-                private void writeObject(ObjectOutputStream out) throws IOException {
-                    throw new IOException();
-                }
-            }, tkp.getPrivate(), sig);
-        } catch(InvalidKeyException e) {
-            fail(e.toString()); 
-        } catch (SignatureException e) {
-            fail(e.toString()); 
-        } catch (InvalidKeySpecException e) {
-            fail(e.toString()); 
-        } catch (IOException e) {
-            // ok 
-        } 
+        assertEquals(prop, so.getObject());
 
-        
-        try {
-            new SignedObject(prop, tkp.getPrivate(), new Signature("TST") {
-            
-                @Override
-                protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
-                    throw new SignatureException();
-                }
-            
-                @Override
-                protected void engineUpdate(byte[] b, int off, int len)
-                        throws SignatureException {
-                    throw new SignatureException();
-                }
-            
-                @Override
-                protected void engineUpdate(byte b) throws SignatureException {
-                    throw new SignatureException();
-                }
-            
-                @Override
-                protected byte[] engineSign() throws SignatureException {
-                    throw new SignatureException();
-                }
-            
-                @Override
-                protected void engineSetParameter(String param, Object value)
-                        throws InvalidParameterException {
-            
-                }
-            
-                @Override
-                protected void engineInitVerify(PublicKey publicKey)
-                        throws InvalidKeyException {
-            
-                }
-            
-                @Override
-                protected void engineInitSign(PrivateKey privateKey)
-                        throws InvalidKeyException {
-            
-                }
-            
-                @Override
-                protected Object engineGetParameter(String param)
-                        throws InvalidParameterException {
-                    return null;
-                }
-            });
-        } catch(InvalidKeyException e) {
-            fail(e.toString()); 
-        } catch (SignatureException e) {
-            // ok 
-        } catch (InvalidKeySpecException e) {
-            fail(e.toString()); 
-        } catch (IOException e) {
-            fail(e.toString()); 
-        } 
-        
+        assertTrue("verify() failed", so.verify(tkp.getPublic(), sig));
+
+        assertNotNull("signature is null", so.getSignature());
     }
 }
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java
index c3414f4..1015521 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java
@@ -118,7 +118,7 @@
         args = {}
     )
     public void testGetTimestamp() {
-        Timestamp t = new Timestamp(now, cpath);
+    	Timestamp t = new Timestamp(now, cpath);
         assertEquals(now, t.getTimestamp());
         assertNotSame(now, t.getTimestamp());
     }
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnrecoverableKeyException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnrecoverableKeyException2Test.java
deleted file mode 100644
index ce97d60..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnrecoverableKeyException2Test.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.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-
-import java.security.UnrecoverableKeyException;
-
-@TestTargetClass(UnrecoverableKeyException.class)
-public class UnrecoverableKeyException2Test extends junit.framework.TestCase {
-
-    /**
-     * @tests java.security.UnrecoverableKeyException#UnrecoverableKeyException()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "UnrecoverableKeyException",
-        args = {}
-    )
-    public void test_Constructor() {
-        // Test for method java.security.UnrecoverableKeyException()
-        UnrecoverableKeyException e = new UnrecoverableKeyException();
-        assertEquals("Failed toString test for constructed instance", "java.security.UnrecoverableKeyException", e
-                .toString());
-    }
-
-    /**
-     * @tests java.security.UnrecoverableKeyException#UnrecoverableKeyException(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Verification with null string parameter missed",
-        method = "UnrecoverableKeyException",
-        args = {java.lang.String.class}
-    )
-    public void test_ConstructorLjava_lang_String() {
-        // Test for method
-        // java.security.UnrecoverableKeyException(java.lang.String)
-        UnrecoverableKeyException e = new UnrecoverableKeyException(
-                "test message");
-        assertEquals("Failed toString test for constructed instance",
-                "java.security.UnrecoverableKeyException: test message", e
-                        .toString());
-    }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java
index ce02e9d..d03b43d 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java
@@ -42,6 +42,11 @@
 
 import tests.util.SerializationTester;
 
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+import tests.util.SerializationTester;
+
 import junit.framework.TestCase;
 
 @TestTargetClass(UnresolvedPermission.class)
@@ -111,7 +116,6 @@
         assertFalse(up.implies(new AllPermission()));
         assertFalse(up.implies(new SecurityPermission("a.b.c")));
     }
-
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
@@ -134,7 +138,6 @@
         assertEquals("actions", deserializedUp.getUnresolvedActions());
         assertNull(deserializedUp.getUnresolvedCerts());
     }
-
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
@@ -155,14 +158,11 @@
                 assertEquals("java.security.SecurityPermission", deserializedUp
                         .getUnresolvedType());
                 assertEquals("a.b.c", deserializedUp.getUnresolvedName());
-                assertEquals("action", deserializedUp.getUnresolvedActions());
-                Certificate[] certs = deserializedUp.getUnresolvedCerts();
-                assertNotNull(certs);
-                assertEquals(1, certs.length);
+                assertEquals("actions", deserializedUp.getUnresolvedActions());
+                assertNull(deserializedUp.getUnresolvedCerts());
             }
         });
     }
-
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
diff --git a/libcore/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java b/libcore/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java
index f36f119..267923a 100644
--- a/libcore/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java
+++ b/libcore/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java
@@ -28,6 +28,8 @@
 import java.util.StringTokenizer;
 
 import tests.support.Support_Exec;
+import static tests.support.Support_Exec.javaProcessBuilder;
+import static tests.support.Support_Exec.execAndGetOutput;
 import tests.support.Support_GetLocal;
 import tests.support.resource.Support_Resources;
 import dalvik.annotation.KnownFailure;
@@ -168,17 +170,14 @@
             }
         }
 
-        String classPath = new File(classURL.getFile()).getPath();
-
-        // Execute Support_PermissionCollection in another VM
-        String[] classPathArray = new String[2];
-        classPathArray[0] = classPath;
-        classPathArray[1] = jarFile.getPath();
-        String[] args = { "-Djava.security.policy=" + policyFile.toURL(),
-                "tests.support.Support_PermissionCollection",
-                signedBKS.toExternalForm() };
-
-        String result = Support_Exec.execJava(args, classPathArray, true);
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("-cp");
+        builder.command().add(Support_Exec.createPath(
+                new File(classURL.getFile()).getPath(), jarFile.getPath()));
+        builder.command().add("-Djava.security.policy=" + policyFile.toURL());
+        builder.command().add("tests.support.Support_PermissionCollection");
+        builder.command().add(signedBKS.toExternalForm());
+        String result = execAndGetOutput(builder);
 
         StringTokenizer resultTokenizer = new StringTokenizer(result, ",");
 
@@ -266,6 +265,7 @@
                 "testing permissionCollection-isREadOnly");
         assertNotNull("toString should have returned a string of elements",
                 permi.newPermissionCollection().toString());
+        assertTrue(permi.newPermissionCollection().toString().endsWith("\n"));
     }
 
     // FIXME move me to Support_Resources
diff --git a/libcore/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser b/libcore/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
index 2937f2f..931ee3f 100755
--- a/libcore/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
+++ b/libcore/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
Binary files differ
diff --git a/libcore/sql/src/main/native/sqlite_jni.c b/libcore/sql/src/main/native/sqlite_jni.c
index 4923869..1a23769 100644
--- a/libcore/sql/src/main/native/sqlite_jni.c
+++ b/libcore/sql/src/main/native/sqlite_jni.c
@@ -1,3 +1,5 @@
+#include "JNIHelp.h"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -276,23 +278,13 @@
 static void
 throwex(JNIEnv *env, const char *msg)
 {
-    jclass except = (*env)->FindClass(env, "SQLite/Exception");
-
-    (*env)->ExceptionClear(env);
-    if (except) {
-	(*env)->ThrowNew(env, except, msg);
-    }
+    jniThrowException(env, "SQLite/Exception", msg);
 }
 
 static void
 throwoom(JNIEnv *env, const char *msg)
 {
-    jclass except = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
-
-    (*env)->ExceptionClear(env);
-    if (except) {
-	(*env)->ThrowNew(env, except, msg);
-    }
+    jniThrowException(env, "java/lang/OutOfMemoryError", msg);
 }
 
 static void
@@ -305,12 +297,7 @@
 static void
 throwioex(JNIEnv *env, const char *msg)
 {
-    jclass except = (*env)->FindClass(env, "java/io/IOException");
-
-    (*env)->ExceptionClear(env);
-    if (except) {
-	(*env)->ThrowNew(env, except, msg);
-    }
+    jniThrowException(env, "java/io/IOException", msg);
 }
 #endif
 
@@ -331,16 +318,10 @@
     dest->result = 0;
     dest->tofree = 0;
     if (haveutf) {
-	const char *utf = (*env)->GetStringUTFChars(env, src, 0);
-
-	if (!utf) {
-	    return dest->result;
-	}
-	dest->tofree = malloc(strlen(utf) + 1);
-	dest->result = dest->tofree;
-	strcpy(dest->result, utf);
-	(*env)->ReleaseStringUTFChars(env, src, utf);
-	return dest->result;
+        const jsize utfLength = (*env)->GetStringUTFLength(env, src);
+        dest->result = dest->tofree = malloc(utfLength + 1);
+        (*env)->GetStringUTFRegion(env, src, 0, utfLength, dest->result);
+        return dest->result;
     }
     if (enc) {
 	bytes = (*env)->CallObjectMethod(env, src,
@@ -1331,11 +1312,10 @@
     }
     if (h) {
 	if (h->sqlite) {
-	    jboolean b;
 	    jthrowable exc;
 	    int rc = SQLITE_ERROR, nargs, i;
 	    char *err = 0, *p;
-	    const char *str = (*env)->GetStringUTFChars(env, sql, &b);
+	    const char *str = (*env)->GetStringUTFChars(env, sql, NULL);
 	    transstr sqlstr;
 	    struct args {
 		char *arg;
@@ -3009,10 +2989,9 @@
 	hvm *v;
 	jvalue vv;
 	jthrowable exc;
-	jboolean b;
 	int rc = SQLITE_ERROR, nargs, i;
 	char *p;
-	const char *str = (*env)->GetStringUTFChars(env, sql, &b);
+	const char *str = (*env)->GetStringUTFChars(env, sql, NULL);
 	const char *tail;
 	transstr sqlstr;
 	struct args {
@@ -3401,7 +3380,7 @@
 	return;
     }
     len16 = len16 + sizeof (jchar) - ((char *) tail - (char *) sql16);
-    if (len16 < sizeof (jchar)) {
+    if (len16 < (jsize) sizeof (jchar)) {
         len16 = sizeof (jchar);
     }
     v = malloc(sizeof (hvm) + len16);
@@ -3674,19 +3653,16 @@
 	    return;
 	}
 	if (val) {
-	    len = (*env)->GetStringLength(env, val);
+	    const jsize charCount = (*env)->GetStringLength(env, val);
+	    len = charCount * sizeof(jchar);
 	    if (len > 0) {
-	        const jchar *ch;
-
-		len *= sizeof (jchar);
 		data = sqlite3_malloc(len);
 		if (!data) {
 		    throwoom(env, "unable to get blob parameter");
 		    return;
 		}
-		ch = (*env)->GetStringChars(env, val, 0);
-		memcpy(data, ch, len);
-		(*env)->ReleaseStringChars(env, val, ch);
+		
+		(*env)->GetStringRegion(env, val, 0, charCount, (jchar*) data);
 		ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm,
 					  pos, data, len, sqlite3_free);
 	    } else {
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
index 68ac6c5..ebb055c 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
@@ -19,12 +19,10 @@
 
 import dalvik.annotation.KnownFailure;
 import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetNew;
 
 import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.lang.reflect.Method;
@@ -37,9 +35,11 @@
 import java.sql.SQLPermission;
 import java.util.Enumeration;
 import java.util.Properties;
-import tests.support.Support_Exec;
 
 import junit.framework.TestCase;
+import static tests.support.Support_Exec.javaProcessBuilder;
+import static tests.support.Support_Exec.execAndGetOutput;
+
 @TestTargetClass(DriverManager.class)
 /**
  * JUnit Testcase for the java.sql.DriverManager class
@@ -715,10 +715,9 @@
      * Regression for HARMONY-4303
      */
     public void test_initClass() throws Exception {
-        String[] arg = new String[1];
-        arg[0] = "org/apache/harmony/sql/tests/java/sql/TestMainForDriver";
-        String result = Support_Exec.execJava(arg, null, true);
-        assertEquals("", result);
+        ProcessBuilder builder = javaProcessBuilder();
+        builder.command().add("org/apache/harmony/sql/tests/java/sql/TestMainForDriver");
+        assertEquals("", execAndGetOutput(builder));
     }
 
     private static class BadDummyDriver extends DummyDriver {
diff --git a/libcore/support/src/test/java/tests/support/Support_Exec.java b/libcore/support/src/test/java/tests/support/Support_Exec.java
index c3a5ccc..7b92d0d 100644
--- a/libcore/support/src/test/java/tests/support/Support_Exec.java
+++ b/libcore/support/src/test/java/tests/support/Support_Exec.java
@@ -17,204 +17,115 @@
 
 package tests.support;
 
-import java.io.ByteArrayOutputStream;
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.StringTokenizer;
-
-import junit.framework.TestCase;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
 
 public class Support_Exec extends TestCase {
 
-    static final boolean againstDalvik;
-    static {
-        String platform = System.getProperty("java.vendor");
-        againstDalvik = (platform.contains("Android"));
-    }
+    private static final boolean againstDalvik
+            = System.getProperty("java.vendor").contains("Android");
 
     /**
-     *  This function returns the output of the process as a string
+     * Returns a builder configured with the appropriate VM ("dalvikvm" or
+     * "java") and arguments (as specified by the system property
+     * {@code hy.test.vmargs}).
      */
-    public static String execJava(String[] args, String[] classpath,
-            boolean displayOutput) throws IOException, InterruptedException {
-        Object[] arr =
-                execJavaCommon(args, classpath, null, displayOutput, true);
-
-        return getProcessOutput(arr, displayOutput);
-    }
-
-    /**
-     * This function returns the output of the process as a string
-     */
-    public static String execJava(String[] args, String[] classpath, String[] envp,
-            boolean displayOutput) throws IOException, InterruptedException {
-        Object[] arr =
-                execJavaCommon(args, classpath, envp, displayOutput, false);
-
-        return getProcessOutput(arr, displayOutput);
-    }
-
-    public static String getProcessOutput(Object[] arr, boolean displayOutput)
+    public static ProcessBuilder javaProcessBuilder()
             throws IOException, InterruptedException {
-        Process proc = (Process) arr[0];
-        StringBuilder output = new StringBuilder();
-        InputStream in = proc.getInputStream();
-        int result;
-        byte[] bytes = new byte[1024];
-
-        while ((result = in.read(bytes)) != -1) {
-            output.append(new String(bytes, 0, result));
-
-            if (displayOutput) {
-                System.out.write(bytes, 0, result);
-            }
-        }
-
-        in.close();
-        proc.waitFor();
-        checkStderr(arr);
-        proc.destroy();
-
-        return output.toString();
-    }
-
-    public static void checkStderr(Object[] execArgs) {
-        StringBuilder errBuf = (StringBuilder) execArgs[1];
-
-        synchronized (errBuf) {
-            if (errBuf.length() > 0) {
-                fail(errBuf.toString());
-            }
-        }
-    }
-
-    public static Object[] execJava2(String[] args, String[] classpath,
-            boolean displayOutput) throws IOException, InterruptedException {
-        return execJavaCommon(args, classpath, null, displayOutput, true);
-    }
-
-    private static Object[] execJavaCommon(String[] args, String[] classpath,
-            String[] envp, boolean displayOutput, boolean appendToSystemClassPath)
-            throws IOException, InterruptedException {
-        // this function returns the resulting process from the exec
-        ArrayList<String> execArgs = null;
-        StringBuilder classPathString = new StringBuilder();
-        StringBuilder command;
-        String executable;
-        String testVMArgs;
-        StringTokenizer st;
-
-        execArgs = new ArrayList<String>(3 + args.length);
+        ProcessBuilder builder = new ProcessBuilder();
 
         // construct the name of executable file
-        if (againstDalvik) {
-            execArgs.add("dalvikvm");
-        } else {
-            execArgs.add("java");
-        }
-
-        // add classpath string
-        if (classpath != null) {
-            for (String element : classpath) {
-                classPathString.append(File.pathSeparator);
-                classPathString.append(element);
-            }
-        }
-        if (appendToSystemClassPath) {
-            execArgs.add("-cp");
-            execArgs.add(System.getProperty("java.class.path") +
-                    classPathString);
-        } else {
-            if (classpath != null) {
-                execArgs.add("-cp");
-                execArgs.add(classPathString.toString());
-            }
-        }
+        builder.command().add(againstDalvik ? "dalvikvm" : "java");
 
         // parse hy.test.vmargs if was given
-        testVMArgs = System.getProperty("hy.test.vmargs");
+        String testVMArgs = System.getProperty("hy.test.vmargs");
         if (testVMArgs != null) {
-            st = new StringTokenizer(testVMArgs, " ");
-
-            while (st.hasMoreTokens()) {
-                execArgs.add(st.nextToken());
-            }
+            builder.command().addAll(Arrays.asList(testVMArgs.split("\\s+")));
         }
 
-        // add custom args given as parameter
-        for (String arg : args) {
-            execArgs.add(arg);
-        }
-
-        if (displayOutput) {
-            // Construct command line string and print it to stdout.
-            command = new StringBuilder(execArgs.get(0));
-            for (int i = 1; i < execArgs.size(); i++) {
-                command.append(" ");
-                command.append(execArgs.get(i));
-            }
-        }
-
-        // execute java process
-        return execAndDigestOutput(execArgs.toArray(new String[execArgs.size()]), envp);
+        return builder;
     }
 
-    //
-    // mc: This looks like functionaly worth publicity:
-    //
-    public static Object[] execAndDigestOutput (String[] cmdLine, String[] envp)
-            throws IOException, InterruptedException {
+    /**
+     * Returns a command-line ready path formed by joining the path elements
+     * with the system path separator as a separator.
+     */
+    public static String createPath(String... elements) {
+        StringBuilder result = new StringBuilder();
+        for (String element : elements) {
+            result.append(File.pathSeparator);
+            result.append(element);
+        }
+        return result.toString();
+    }
 
-//        System.out.println("Commandline BEGIN");
-//        for (int i = 0; i < cmdLine.length; i++) {
-//            System.out.println(cmdLine[i]);
-//        }
-//        System.out.println("END");
+    /**
+     * Starts the specified process, collects its output from standard out and
+     * standard err, and returns. If the stream emits anything to standard err,
+     * an AssertionFailedError will be thrown.
+     *
+     * <p>This method assumes the target process will complete within ten
+     * seconds. If it does not, an AssertionFailedError will be thrown.
+     */
+    public static String execAndGetOutput(ProcessBuilder builder)
+            throws IOException {
+        Process process = builder.start();
+        ExecutorService executorService = Executors.newFixedThreadPool(2);
+        try {
+            Future<String> errFuture = executorService.submit(
+                    streamToStringCallable(process.getErrorStream()));
+            Future<String> outFuture = executorService.submit(
+                    streamToStringCallable(process.getInputStream()));
 
-        final Process proc = Runtime.getRuntime().exec(cmdLine, envp);
-        final StringBuilder errBuf = new StringBuilder();
+            Throwable failure;
+            String out = "";
+            try {
+                out = outFuture.get(10, TimeUnit.SECONDS);
+                String err = errFuture.get(10, TimeUnit.SECONDS);
+                failure = err.length() > 0
+                        ? new AssertionFailedError("Unexpected err stream data:\n" + err)
+                        : null;
+            } catch (Exception e) {
+                failure = e;
+            }
 
-        Thread errThread = new Thread(new Runnable() {
-            public void run() {
-                synchronized (errBuf) {
-                    InputStream err;
-                    int result;
-                    byte[] bytes = new byte[1024];
+            if (failure != null) {
+                AssertionFailedError error = new AssertionFailedError(
+                        "Failed to execute " + builder.command() + "; output was:\n" + out);
+                error.initCause(failure);
+                throw error;
+            } else {
+                return out;
+            }
+        } finally {
+            executorService.shutdown();
+        }
+    }
 
-                    synchronized (proc) {
-                        proc.notifyAll();
-                    }
-
-                    err = proc.getErrorStream();
-                    try {
-                        while ((result = err.read(bytes)) != -1) {
-                            System.err.write(bytes, 0, result);
-                            errBuf.append(new String(bytes));
-                        }
-                        err.close();
-                    } catch (IOException e) {
-                        ByteArrayOutputStream out = new ByteArrayOutputStream();
-                        PrintStream printer = new PrintStream(out);
-
-                        e.printStackTrace();
-                        e.printStackTrace(printer);
-                        printer.close();
-                        errBuf.append(new String(out.toByteArray()));
-                    }
+    private static Callable<String> streamToStringCallable(final InputStream in) {
+        return new Callable<String>() {
+            public String call() throws Exception {
+                StringWriter writer = new StringWriter();
+                Reader reader = new InputStreamReader(in);
+                int c;
+                while ((c = reader.read()) != -1) {
+                    writer.write(c);
                 }
+                return writer.toString();
             }
-        });
-
-        synchronized (proc) {
-            errThread.start();
-            // wait for errThread to start
-            proc.wait();
-        }
-
-        return new Object[] { proc, errBuf };
+        };
     }
-
 }
diff --git a/libcore/text/src/main/java/java/text/BreakIterator.java b/libcore/text/src/main/java/java/text/BreakIterator.java
index 7d19179..3a08427 100644
--- a/libcore/text/src/main/java/java/text/BreakIterator.java
+++ b/libcore/text/src/main/java/java/text/BreakIterator.java
@@ -23,6 +23,8 @@
 
 import java.util.Locale;
 
+import org.apache.harmony.text.internal.nls.Messages;
+
 /**
  * Locates boundaries in text. This class defines a protocol for objects that
  * break up a piece of natural-language text according to a set of criteria.
@@ -542,11 +544,10 @@
      *             greater than the length of {@code buf}.
      */
     protected static long getLong(byte[] buf, int offset) {
-        if (null == buf) {
-            throw new NullPointerException();
-        }
-        if (offset < 0 || buf.length - offset < LONG_LENGTH) {
-            throw new ArrayIndexOutOfBoundsException();
+        // Force a buf null check first!
+        if (buf.length - offset < LONG_LENGTH || offset < 0) {
+            // text.1E=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("text.1E", offset)); //$NON-NLS-1$
         }
         long result = 0;
         for (int i = offset; i < offset + LONG_LENGTH; i++) {
@@ -571,11 +572,10 @@
      *             greater than the length of {@code buf}.
      */
     protected static int getInt(byte[] buf, int offset) {
-        if (null == buf) {
-            throw new NullPointerException();
-        }
-        if (offset < 0 || buf.length - INT_LENGTH < offset) {
-            throw new ArrayIndexOutOfBoundsException();
+        // Force buf null check first!
+        if (buf.length - INT_LENGTH < offset || offset < 0) {
+            // text.1E=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("text.1E", offset)); //$NON-NLS-1$
         }
         int result = 0;
         for (int i = offset; i < offset + INT_LENGTH; i++) {
@@ -600,11 +600,10 @@
      *             greater than the length of {@code buf}.
      */
     protected static short getShort(byte[] buf, int offset) {
-        if (null == buf) {
-            throw new NullPointerException();
-        }
-        if (offset < 0 || buf.length - SHORT_LENGTH < offset) {
-            throw new ArrayIndexOutOfBoundsException();
+        // Force buf null check first!
+        if (buf.length - SHORT_LENGTH < offset || offset < 0) {
+            // text.1E=Offset out of bounds \: {0}
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("text.1E", offset)); //$NON-NLS-1$
         }
         short result = 0;
         for (int i = offset; i < offset + SHORT_LENGTH; i++) {
diff --git a/libcore/text/src/main/java/java/text/Collator.java b/libcore/text/src/main/java/java/text/Collator.java
index aaa3e12..71ebb94 100644
--- a/libcore/text/src/main/java/java/text/Collator.java
+++ b/libcore/text/src/main/java/java/text/Collator.java
@@ -22,12 +22,11 @@
 package java.text;
 
 import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Comparator;
 import java.util.Locale;
 import java.util.Vector;
 
-import org.apache.harmony.luni.util.PriviAction;
-
 /**
  * Performs locale-sensitive string comparison. A concrete subclass,
  * {@link RuleBasedCollator}, allows customization of the collation ordering by
@@ -163,7 +162,11 @@
     static {
         // CACHE_SIZE includes key and value, so needs to be double
         String cacheSize = AccessController
-                .doPrivileged(new PriviAction<String>("collator.cache")); //$NON-NLS-1$
+                .doPrivileged(new PrivilegedAction<String>() {
+                    public String run() {
+                        return System.getProperty("collator.cache"); //$NON-NLS-1$
+                    }
+                });
         if (cacheSize != null) {
             try {
                 CACHE_SIZE = Integer.parseInt(cacheSize);
diff --git a/libcore/text/src/main/java/java/text/DateFormat.java b/libcore/text/src/main/java/java/text/DateFormat.java
index f39965a..531bed8 100644
--- a/libcore/text/src/main/java/java/text/DateFormat.java
+++ b/libcore/text/src/main/java/java/text/DateFormat.java
@@ -666,7 +666,7 @@
     public Date parse(String string) throws ParseException {
         ParsePosition position = new ParsePosition(0);
         Date date = parse(string, position);
-        if (position.getErrorIndex() != -1 || position.getIndex() == 0) {
+        if (position.getIndex() == 0) {
             // text.19=Unparseable date: {0}
             throw new ParseException(
                     Messages.getString("text.19", string), position.getErrorIndex()); //$NON-NLS-1$
diff --git a/libcore/text/src/main/java/java/text/Format.java b/libcore/text/src/main/java/java/text/Format.java
index 6ee1ba2..3a6e49d 100644
--- a/libcore/text/src/main/java/java/text/Format.java
+++ b/libcore/text/src/main/java/java/text/Format.java
@@ -202,8 +202,10 @@
     public Object parseObject(String string) throws ParseException {
         ParsePosition position = new ParsePosition(0);
         Object result = parseObject(string, position);
-        if (position.getErrorIndex() != -1 || position.getIndex() == 0) {
-            throw new ParseException(null, position.getErrorIndex());
+        if (position.getIndex() == 0) {
+            // text.1C=Format.parseObject(String) parse failure
+            throw new ParseException(
+                    Messages.getString("text.1C"), position.getErrorIndex()); //$NON-NLS-1$
         }
         return result;
     }
diff --git a/libcore/text/src/main/java/java/text/MessageFormat.java b/libcore/text/src/main/java/java/text/MessageFormat.java
index 4ab1ade..f6074b2 100644
--- a/libcore/text/src/main/java/java/text/MessageFormat.java
+++ b/libcore/text/src/main/java/java/text/MessageFormat.java
@@ -859,8 +859,10 @@
     public Object[] parse(String string) throws ParseException {
         ParsePosition position = new ParsePosition(0);
         Object[] result = parse(string, position);
-        if (position.getErrorIndex() != -1 || position.getIndex() == 0) {
-            throw new ParseException(null, position.getErrorIndex());
+        if (position.getIndex() == 0) {
+            // text.1B=MessageFormat.parseObject(String) parse failure
+            throw new ParseException(
+                    Messages.getString("text.1B"), position.getErrorIndex()); //$NON-NLS-1$
         }
         return result;
     }
diff --git a/libcore/text/src/main/java/java/text/NumberFormat.java b/libcore/text/src/main/java/java/text/NumberFormat.java
index 5b8d883..87f17c1 100644
--- a/libcore/text/src/main/java/java/text/NumberFormat.java
+++ b/libcore/text/src/main/java/java/text/NumberFormat.java
@@ -555,8 +555,10 @@
     public Number parse(String string) throws ParseException {
         ParsePosition pos = new ParsePosition(0);
         Number number = parse(string, pos);
-        if (pos.getErrorIndex() != -1 || pos.getIndex() == 0) {
-            throw new ParseException(null, pos.getErrorIndex());
+        if (pos.getIndex() == 0) {
+            // text.1D=Unparseable number: {0}
+            throw new ParseException(
+                    Messages.getString("text.1D", string), pos.getErrorIndex()); //$NON-NLS-1$
         }
         return number;
     }
diff --git a/libcore/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties b/libcore/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties
index 22221a9..b80cde2 100644
--- a/libcore/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties
+++ b/libcore/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties
@@ -43,4 +43,7 @@
 text.18=Not a valid {0}, subclass should override readResolve()
 text.19=Unparseable date: {0}
 text.1A=position is null
-
+text.1B=MessageFormat.parseObject(String) parse failure
+text.1C=Format.parseObject(String) parse failure
+text.1D=Unparseable number: {0}
+text.1E=Offset out of bounds \: {0}
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java
index aa36abc..2b8c267 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java
@@ -78,6 +78,29 @@
         String result;
         char current;
 
+        // For BigDecimal with multiplier test.
+        DecimalFormat df = new DecimalFormat();
+        df.setMultiplier(10);
+        iterator = df.formatToCharacterIterator(new BigDecimal("12345678901234567890"));
+        result = "123,456,789,012,345,678,900";
+        current = iterator.current();
+        for (int i = 0; i < result.length(); i++) {
+            assertEquals("wrong char @" + i, result.charAt(i), current);
+            current = iterator.next();
+        }
+
+        // For BigDecimal with multiplier test.
+        df = new DecimalFormat();
+        df.setMultiplier(-1);
+        df.setMaximumFractionDigits(20);
+        iterator = df.formatToCharacterIterator(new BigDecimal("1.23456789012345678901"));
+        result = "-1.23456789012345678901";
+        current = iterator.current();
+        for (int i = 0; i < result.length(); i++) {
+            assertEquals("wrong char @" + i, result.charAt(i), current);
+            current = iterator.next();
+        }
+
         iterator = new DecimalFormat()
                 .formatToCharacterIterator(new BigDecimal("1.23456789E1234"));
         runStarts = new int[] {0, 0, 2, 3, 3, 3, 6, 7, 7, 7, 10, 11, 11, 11, 14};
@@ -2547,4 +2570,119 @@
         DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance();
         format.setDecimalFormatSymbols(null);
     }
+
+    private void assertBigDecimalWithFraction(
+            BigDecimal bd,
+            String expectedResult,
+            int fraction) {
+        NumberFormat pf = NumberFormat.getPercentInstance();
+        pf.setMaximumFractionDigits(fraction);
+        assertEquals(expectedResult, pf.format(bd));
+    }
+
+    private void assertDecFmtWithMultiplierAndFraction(
+            String value,
+            int multiplier,
+            int fraction,
+            String expectedResult) {
+
+        DecimalFormat df = (DecimalFormat)NumberFormat.getInstance();
+        df.setMultiplier(multiplier);
+        df.setMaximumFractionDigits(fraction);
+        BigDecimal d = new BigDecimal(value);
+        assertEquals(expectedResult, df.format(d));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.ADDITIONAL,
+        notes = "Regression test for some existing bugs and crashes",
+        method = "format",
+        args = { String.class, Object[].class }
+    )
+    public void testBigDecimalBug1897917() {
+        // Bug1897917 : BigDecimal does not take into account multiplier.
+        // So the BigDecimal 0.17 formatted in PercentInstance is 0% instead of 17%.
+
+        NumberFormat pf = NumberFormat.getPercentInstance();
+
+        // Test bug 1897917 case.
+        assertEquals("17%", pf.format(BigDecimal.valueOf(0.17)));
+
+        // Test long decimal formatted in PercentInstance with various fractions.
+        String longDec = "11.2345678901234567890123456789012345678901234567890";
+        BigDecimal bd = new BigDecimal(longDec);
+        assertBigDecimalWithFraction(bd, "1,123.46%", 2);
+        assertBigDecimalWithFraction(bd, "1,123.45678901%", 8);
+        assertBigDecimalWithFraction(bd, "1,123.4567890123%", 10);
+        assertBigDecimalWithFraction(bd, "1,123.45678901234567890123%", 20);
+        assertBigDecimalWithFraction(bd, "1,123.456789012345678901234567890123%", 30);
+
+        // Test trailing zeros.
+        assertDecFmtWithMultiplierAndFraction("3333.33333333", 3, 4, "10,000");
+        assertDecFmtWithMultiplierAndFraction("3333.33333333", -3, 4, "-10,000");
+        assertDecFmtWithMultiplierAndFraction("0.00333333", 3, 4, "0.01");
+        assertDecFmtWithMultiplierAndFraction("3330000000000000000000000000000000", 3, 4,
+                                               "9,990,000,000,000,000,000,000,000,000,000,000");
+    }
+
+    @TestTargetNew(
+        level = TestLevel.ADDITIONAL,
+        notes = "Regression test for some existing bugs and crashes",
+        method = "format",
+        args = { String.class, Object[].class }
+    )
+    public void testBigDecimalTestBigIntWithMultiplier() {
+       // Big integer tests.
+       assertDecFmtWithMultiplierAndFraction("123456789012345", 10, 0, "1,234,567,890,123,450");
+       assertDecFmtWithMultiplierAndFraction("12345678901234567890", 10, 0,
+                                              "123,456,789,012,345,678,900");
+       assertDecFmtWithMultiplierAndFraction("98765432109876543210987654321", 10, 0,
+                                              "987,654,321,098,765,432,109,876,543,210");
+
+       assertDecFmtWithMultiplierAndFraction("123456789012345", -10, 0, "-1,234,567,890,123,450");
+       assertDecFmtWithMultiplierAndFraction("12345678901234567890", -10, 0,
+                                              "-123,456,789,012,345,678,900");
+       assertDecFmtWithMultiplierAndFraction("98765432109876543210987654321", -10, 0,
+                                              "-987,654,321,098,765,432,109,876,543,210");
+   }
+
+   @TestTargetNew(
+        level = TestLevel.ADDITIONAL,
+        notes = "Regression test for some existing bugs and crashes",
+        method = "format",
+        args = { String.class, Object[].class }
+   )
+   public void testBigDecimalICUConsistency() {
+       DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
+       df.setMaximumFractionDigits(2);
+       df.setMultiplier(2);
+       assertEquals(df.format(BigDecimal.valueOf(0.16)),
+                    df.format(BigDecimal.valueOf(0.16).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(0.0293)),
+                    df.format(BigDecimal.valueOf(0.0293).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(0.006)),
+                    df.format(BigDecimal.valueOf(0.006).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(0.00283)),
+                    df.format(BigDecimal.valueOf(0.00283).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(1.60)),
+                    df.format(BigDecimal.valueOf(1.60).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(15)),
+                    df.format(BigDecimal.valueOf(15).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(170)),
+                    df.format(BigDecimal.valueOf(170).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(234.56)),
+                    df.format(BigDecimal.valueOf(234.56).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(0)),
+                    df.format(BigDecimal.valueOf(0).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(-1)),
+                    df.format(BigDecimal.valueOf(-1).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(-10000)),
+                    df.format(BigDecimal.valueOf(-10000).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(-0.001)),
+                    df.format(BigDecimal.valueOf(-0.001).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(1234567890.1234567)),
+                    df.format(BigDecimal.valueOf(1234567890.1234567).doubleValue()));
+       assertEquals(df.format(BigDecimal.valueOf(1.234567E100)),
+                    df.format(BigDecimal.valueOf(1.234567E100).doubleValue()));
+    }
 }
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java
index 1c2da6a..3bcc38c 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java
@@ -37,15 +37,13 @@
         args = {java.lang.String.class, int.class}
     )
     public void test_ConstructorLjava_lang_StringI() {
-        // Test for method java.text.ParseException(java.lang.String, int)
-        // SM
         try {
             DateFormat df = DateFormat.getInstance();
             df.parse("HelloWorld");
+            fail("ParseException not created/thrown.");
         } catch (ParseException e) {
-            return;
+            // expected
         }
-        fail("ParseException not created/thrown.");
     }
 
     /**
@@ -58,8 +56,6 @@
         args = {}
     )
     public void test_getErrorOffset() {
-        // Test for method int java.text.ParseException.getErrorOffset()
-        // SM
         try {
             DateFormat df = DateFormat.getInstance();
             df.parse("1999HelloWorld");
@@ -67,18 +63,4 @@
             assertEquals("getErrorOffsetFailed.", 4, e.getErrorOffset());
         }
     }
-
-    /**
-     * Sets up the fixture, for example, open a network connection. This method
-     * is called before a test is executed.
-     */
-    protected void setUp() {
-    }
-
-    /**
-     * Tears down the fixture, for example, close a network connection. This
-     * method is called after a test is executed.
-     */
-    protected void tearDown() {
-    }
 }
diff --git a/libcore/tools/integrate/Android.mk b/libcore/tools/integrate/Android.mk
index 629a5fd..f0f25b3 100644
--- a/libcore/tools/integrate/Android.mk
+++ b/libcore/tools/integrate/Android.mk
@@ -7,9 +7,9 @@
 	Filesystem.java \
 	Git.java \
 	Module.java \
-	Modules.java \
 	MappedDirectory.java \
 	PullHarmonyCode.java \
+	PushAndroidCode.java \
 	Svn.java
 
 LOCAL_MODULE:= integrate
diff --git a/libcore/tools/integrate/Filesystem.java b/libcore/tools/integrate/Filesystem.java
index a9c1789..4b296a0 100644
--- a/libcore/tools/integrate/Filesystem.java
+++ b/libcore/tools/integrate/Filesystem.java
@@ -32,11 +32,28 @@
      * directory is nonempty.
      */
     public int moveContents(String source, String target) {
+        return copyContents(true, source, target);
+    }
+
+    /**
+     * Copies all of the files in {@code source} to {@code target}, one at a
+     * time. Unlike {@code move}, this approach works even if the target
+     * directory is nonempty.
+     */
+    public int copyContents(String source, String target) {
+        return copyContents(false, source, target);
+    }
+
+    private int copyContents(boolean move, String source, String target) {
         List<String> files = new Command("find", source, "-type", "f") .execute();
         for (String file : files) {
             String targetFile = target + "/" + file.substring(source.length());
             mkdir(parent(targetFile));
-            new Command("mv", "-i", file, targetFile).execute();
+            if (move) {
+                new Command("mv", "-i", file, targetFile).execute();
+            } else {
+                new Command("cp", file, targetFile).execute();
+            }
         }
         return files.size();
     }
diff --git a/libcore/tools/integrate/Module.java b/libcore/tools/integrate/Module.java
index 5cb7035..63d35a2 100644
--- a/libcore/tools/integrate/Module.java
+++ b/libcore/tools/integrate/Module.java
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
+import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -22,6 +25,47 @@
  */
 class Module {
 
+    static final Map<String, Module> VALUES;
+    static {
+        Map<String, Module> valuesMutable = new LinkedHashMap<String, Module>();
+
+        String svnRoot = "http://svn.apache.org/repos/asf/harmony/enhanced/classlib/trunk/modules";
+        valuesMutable.put("archive", new Module.Builder(svnRoot, "archive")
+                .mapDirectory("archive/src/main/native/archive/shared",
+                        "archive/src/main/native")
+                .mapDirectory("archive/src/main/native/zip/shared",
+                        "archive/src/main/native")
+                .build());
+
+        valuesMutable.put("crypto", new Module.Builder(svnRoot, "crypto")
+                .mapDirectory("crypto/src/test/api/java.injected/javax",
+                        "crypto/src/test/java/org/apache/harmony/crypto/tests/javax")
+                .mapDirectory("crypto/src/test/api/java",
+                        "crypto/src/test/java")
+                .mapDirectory("crypto/src/test/resources/serialization",
+                        "crypto/src/test/java/serialization")
+                .mapDirectory("crypto/src/test/support/common/java",
+                        "crypto/src/test/java")
+                .build());
+
+        valuesMutable.put("regex", new Module.Builder(svnRoot, "regex").build());
+
+        valuesMutable.put("security", new Module.Builder(svnRoot, "security")
+                .mapDirectory("security/src/main/java/common",
+                        "security/src/main/java")
+                .mapDirectory("security/src/main/java/unix/org",
+                        "security/src/main/java/org")
+                .mapDirectory("security/src/test/api/java",
+                        "security/src/test/java")
+                .build());
+
+        valuesMutable.put("text", new Module.Builder(svnRoot, "text").build());
+
+        valuesMutable.put("x-net", new Module.Builder(svnRoot, "x-net").build());
+
+        VALUES = Collections.unmodifiableMap(valuesMutable);
+    }
+
     private final String svnBaseUrl;
     private final String path;
     private final Set<MappedDirectory> mappedDirectories;
diff --git a/libcore/tools/integrate/Modules.java b/libcore/tools/integrate/Modules.java
deleted file mode 100644
index 2475852..0000000
--- a/libcore/tools/integrate/Modules.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Constants that define modules shared by Harmony and Dalvik.
- */
-public class Modules {
-
-    private static final String SVN_ROOT
-            = "http://svn.apache.org/repos/asf/harmony/enhanced/classlib/trunk/modules";
-
-    public static final Module ARCHIVE = new Module.Builder(SVN_ROOT, "archive")
-            .mapDirectory("archive/src/main/native/archive/shared",
-                    "archive/src/main/native")
-            .mapDirectory("archive/src/main/native/zip/shared",
-                    "archive/src/main/native")
-            .build();
-
-    public static final Module CRYPTO = new Module.Builder(SVN_ROOT, "crypto")
-            .mapDirectory("crypto/src/test/api/java.injected/javax",
-                    "crypto/src/test/java/org/apache/harmony/crypto/tests/javax")
-            .mapDirectory("crypto/src/test/api/java",
-                    "crypto/src/test/java")
-            .mapDirectory("crypto/src/test/resources/serialization",
-                    "crypto/src/test/java/serialization")
-            .mapDirectory("crypto/src/test/support/common/java",
-                    "crypto/src/test/java")
-            .build();
-
-    public static final Module REGEX
-            = new Module.Builder(SVN_ROOT, "regex").build();
-
-    public static final Module SECURITY = new Module.Builder(SVN_ROOT, "security")
-            .mapDirectory("security/src/main/java/common",
-                    "security/src/main/java")
-            .mapDirectory("security/src/main/java/unix/org",
-                    "security/src/main/java/org")
-            .mapDirectory("security/src/test/api/java",
-                    "security/src/test/java")
-            .build();
-
-    public static final Module TEXT
-            = new Module.Builder(SVN_ROOT, "text").build();
-
-    public static final Module X_NET
-            = new Module.Builder(SVN_ROOT, "x-net").build();
-
-    // TODO: add the other modules
-}
diff --git a/libcore/tools/integrate/PullHarmonyCode.java b/libcore/tools/integrate/PullHarmonyCode.java
index 6710801..ce019d4 100644
--- a/libcore/tools/integrate/PullHarmonyCode.java
+++ b/libcore/tools/integrate/PullHarmonyCode.java
@@ -102,8 +102,61 @@
         }
     }
 
+
     public static void main(String[] args) {
-//        new PullHarmonyCode(527399, 802921).pull(Modules.CRYPTO);
-        new PullHarmonyCode(772995, 802921).pull(Modules.ARCHIVE);
+        if (args.length < 3) {
+            printUsage();
+            return;
+        }
+
+        int currentSvnRev = Integer.parseInt(args[0]);
+        int targetSvnRev = Integer.parseInt(args[1]);
+
+        if (currentSvnRev < 527399 || targetSvnRev <= currentSvnRev) {
+            System.out.println("Invalid SVN revision range: "
+                    + currentSvnRev + ".." + targetSvnRev);
+            return;
+        }
+
+        Module module = Module.VALUES.get(args[2]);
+        if (module == null) {
+            System.out.println("No such module: " + args[2]);
+            return;
+        }
+
+        PullHarmonyCode puller = new PullHarmonyCode(currentSvnRev, targetSvnRev);
+        puller.pull(module);
+    }
+
+    private static void printUsage() {
+        System.out.println("This tool will prepare a three-way merge between the latest Harmony");
+        System.out.println("the latest Dalvik, and their common ancestor. It downloads both old");
+        System.out.println("and new versions of Harmony code from SVN for better merge results.");
+        System.out.println();
+        System.out.println("Usage: PullHarmonyCode <current_rev> <target_rev> <module>...");
+        System.out.println();
+        System.out.println("  <current_rev>  is the SVN revision of the Harmony code that was");
+        System.out.println("                 most recently integrated into Dalvik. This should");
+        System.out.println("                 be a number greater than 527399. The current");
+        System.out.println("                 revision for each module is tracked at");
+        System.out.println("                 http://go/dalvik/harmony");
+        System.out.println();
+        System.out.println("    <target_rev> is the SVN revision of the Harmony code to be");
+        System.out.println("                 merged into Dalvik. This should be a number greater");
+        System.out.println("                 than <current_rev>. The latest Harmony revision is");
+        System.out.println("                 tracked at");
+        System.out.println("                 http://svn.apache.org/viewvc/harmony/?root=Apache-SVN");
+        System.out.println();
+        System.out.println("        <module> is one of " + Module.VALUES.keySet());
+        System.out.println();
+        System.out.println("This program must be executed from within the dalvik/libcore directory");
+        System.out.println("of an Android git client. Such a client must be synced and contain no");
+        System.out.println("uncommitted changes. Upon termination, a new Git branch with the");
+        System.out.println("integrated changes will be active. This branch may require some manual");
+        System.out.println("merging.");
+        System.out.println();
+        System.out.println("Example usage:");
+        System.out.println("  java -cp ../../out/host/linux-x86/framework/integrate.jar PullAndroidCode \\");
+        System.out.println("    527399  802921 security");
     }
 }
diff --git a/libcore/tools/integrate/PushAndroidCode.java b/libcore/tools/integrate/PushAndroidCode.java
new file mode 100644
index 0000000..c0002f5
--- /dev/null
+++ b/libcore/tools/integrate/PushAndroidCode.java
@@ -0,0 +1,87 @@
+// Copyright 2009 Google Inc. All Rights Reserved.
+
+import java.util.UUID;
+
+/**
+ * Copy the current Android sourcecode into Apache Harmony, where it can be
+ * reviewed and submitted to their SVN. Only run this script after first merging
+ * the latest harmony code into Android.
+ */
+public class PushAndroidCode {
+
+    private final String androidPath;
+    private final String harmonyPath;
+
+    public PushAndroidCode(String androidPath, String harmonyPath) {
+        this.androidPath = androidPath;
+        this.harmonyPath = harmonyPath;
+    }
+
+    public void push(Module module) {
+        Filesystem filesystem = new Filesystem();
+
+        // copy android code to a temp directory that is laid out like Harmony
+        String temp = "/tmp/" + UUID.randomUUID();
+        filesystem.mkdir(temp);
+        filesystem.copyContents(androidPath + "/" + module.path(),
+                temp + "/" + module.path());
+        for (MappedDirectory mappedDirectory : module.getMappedDirectories()) {
+            filesystem.moveContents(
+                    temp + "/" + mappedDirectory.gitPath(),
+                    temp + "/" + mappedDirectory.svnPath());
+        }
+
+        // clobber files from harmony with their Android equivalents
+        filesystem.copyContents(temp + "/" + module.path(),
+                harmonyPath + "/" + module.path());
+    }
+
+    public static void main(String[] args) {
+        if (args.length < 3) {
+            printUsage();
+            return;
+        }
+
+        String androidPath = args[0] + "/dalvik/libcore";
+        String harmonyPath = args[1] + "/working_classlib/modules";
+
+        // TODO: validate directories?
+        
+        Module[] modules = new Module[args.length - 2];
+        for (int i = 0; i < modules.length; i++) {
+            modules[i] = Module.VALUES.get(args[i+2]);
+            if (modules[i] == null) {
+                System.out.println("No such module: " + args[i+2]);
+                return;
+            }
+        }
+
+        PushAndroidCode pusher = new PushAndroidCode(androidPath, harmonyPath);
+        for (Module module : modules) {
+            pusher.push(module);
+        }
+    }
+
+    private static void printUsage() {
+        System.out.println("This tool will clobber Harmony's core libraries with Android's copy");
+        System.out.println("so that a patch can be submitted upstream.");
+        System.out.println();
+        System.out.println("Usage: PushAndroidCode <android_root> <harmony_root> <module>...");
+        System.out.println();
+        System.out.println("  <android_root> is the android git client directory that contains dalvik");
+        System.out.println("                 This should hold an up-to-date checkout of Android. The");
+        System.out.println("                 target modules should also be up-to-date with respect to");
+        System.out.println("                 Harmony; use the PullHarmonyCode tool first if necessary.");
+        System.out.println();
+        System.out.println("  <harmony_root> is the android client directory that contains working_classlib.");
+        System.out.println("                 This should hold an up-to-date checkout of Harmony.");
+        System.out.println();
+        System.out.println("  <module> is one of " + Module.VALUES.keySet());
+        System.out.println();
+        System.out.println("Example usage:");
+        System.out.println("  java -cp out/host/linux-x86/framework/integrate.jar PushAndroidCode \\");
+        System.out.println("    /usr/local/google/jesse/clients/jessewilson_g1 \\");
+        System.out.println("    /usr/local/google/jesse/clients/jessewilson_h0/trunk \\");
+        System.out.println("    crypto");
+    }
+}
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
index 6c23a91..507e14f 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
@@ -94,10 +94,11 @@
      * Reads and returns uint64 value.
      */
     public long readUint64() throws IOException {
-        return (read() << 56) | (read() << 48)
-              | (read() << 40) | (read() << 32)
-              | (read() << 24) | (read() << 16)
-              | (read() << 8) | (read() & 0x00FF);
+        // BEGIN android-changed
+        long hi = readUint32();
+        long lo = readUint32();
+        return (hi << 32) | lo;
+        // END android-changed
     }
 
     /**
@@ -131,4 +132,3 @@
         return i;
     }
 }
-
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
index 13a1e61..eec2efe 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
@@ -41,20 +41,10 @@
 static jfieldID field_ssl_ctx;
 
 /**
- * Throws java.io.IOexception with the provided message.
+ * Throws java.io.IOException with the provided message.
  */
-static void throwIOExceptionStr(JNIEnv* env, const char* message)
-{
-    jclass exClass = env->FindClass("java/io/IOException");
-
-    if (exClass == NULL)
-    {
-        LOGE("Unable to find class java/io/IOException");
-    }
-    else
-    {
-        env->ThrowNew(exClass, message);
-    }
+static void throwIOExceptionStr(JNIEnv* env, const char* message) {
+    jniThrowException(env, "java/io/IOException", message);
 }
 
 /**
@@ -87,9 +77,9 @@
     // 'seed == null' when no SecureRandom Object is set
     // in the SSLContext.
     if (seed != NULL) {
-        jboolean iscopy = JNI_FALSE;
-        jbyte* randseed = env->GetByteArrayElements(seed, &iscopy);
+        jbyte* randseed = env->GetByteArrayElements(seed, NULL);
         RAND_seed((unsigned char*) randseed, 1024);
+        env->ReleaseByteArrayElements(seed, randseed, 0);
     } else {
         RAND_load_file("/dev/urandom", 1024);
     }
@@ -167,38 +157,13 @@
 static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_getsupportedciphersuites(JNIEnv* env,
         jobject object)
 {
-    SSL_CTX* ctx;
-    SSL* ssl;
-    STACK_OF(SSL_CIPHER) *sk;
-    jobjectArray ret;
-    int i;
-    const char *c;
-
-    ctx = SSL_CTX_new(SSLv23_server_method());
-    ssl = SSL_new(ctx);
-    sk=SSL_get_ciphers(ssl);
-
-    ret= (jobjectArray)env->NewObjectArray(5,
-         env->FindClass("java/lang/String"),
-         env->NewStringUTF(""));
-
-    i = 0;
-    while (SSL_get_cipher_list(ssl,i) != NULL) {
-        i++;
+    SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_server_method());
+    if (ssl_ctx == NULL) {
+        return NULL;
     }
-
-    ret = (jobjectArray)env->NewObjectArray(i,
-        env->FindClass("java/lang/String"),
-        env->NewStringUTF(""));
-
-    for (i=0; ; i++) {
-        c=SSL_get_cipher_list(ssl,i);
-        if (c == NULL) break;
-
-        env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
-    }
-
-    return ret;
+    jobjectArray result = makeCipherList(env, ssl_ctx);
+    SSL_CTX_free(ssl_ctx);
+    return result;
 }
 
 /**
@@ -208,52 +173,20 @@
 static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_getenabledciphersuites(JNIEnv* env,
         jobject object)
 {
-    SSL_CTX* ctx;
-    SSL* ssl;
-    jobjectArray ret;
-    int i;
-    const char *c;
-
-    ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
-    ssl = SSL_new(ctx);
-
-    i = 0;
-    while (SSL_get_cipher_list(ssl,i) != NULL) {
-        i++;
-    }
-
-    ret = (jobjectArray)env->NewObjectArray(i,
-        env->FindClass("java/lang/String"),
-        env->NewStringUTF(""));
-
-    for (i = 0; ; i++) {
-        c = SSL_get_cipher_list(ssl,i);
-        if (c == NULL) break;
-
-        env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
-    }
-
-    return ret;
+    SSL_CTX* ssl_ctx =
+            reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+    return makeCipherList(env, ssl_ctx);
 }
 
 /**
  * Sets the ciphers suites that are enabled in the OpenSSL server.
  */
 static void org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_setenabledciphersuites(JNIEnv* env,
-        jobject object, jstring controlstring)
+        jobject object, jstring controlString)
 {
-    SSL_CTX* ctx;
-    const char *str;
-    int ret;
-
-    ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
-    str = env->GetStringUTFChars(controlstring, 0);
-    ret = SSL_CTX_set_cipher_list(ctx, str);
-
-    if(ret == 0) {
-        jclass exClass = env->FindClass("java/lang/IllegalArgumentException");
-        env->ThrowNew(exClass, "Illegal cipher suite strings.");
-    }    
+    SSL_CTX* ssl_ctx =
+            reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+    setEnabledCipherSuites(env, controlString, ssl_ctx);
 }
 
 /**
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
index feae690..324dacf 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
@@ -47,20 +47,6 @@
 }
 
 /**
- * Throws java.io.IOexception with the provided message.
- */
-static void throwIOExceptionStr(JNIEnv* env, const char* message)
-{
-    jclass exClass = env->FindClass("java/io/IOException");
-
-    if (exClass == NULL) {
-        LOGE("Unable to find class java/io/IOException");
-    } else {
-        env->ThrowNew(exClass, message);
-    }
-}
-
-/**
  * Gets the peer certificate in the chain and fills a byte array with the
  * information therein.
  */
@@ -150,20 +136,15 @@
  */
 static jbyteArray org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getid(JNIEnv* env, jobject object)
 {
-    SSL_SESSION * ssl_session;
-    jbyteArray bytes;
-    jbyte *tmp;
+    SSL_SESSION* ssl_session = getSslSessionPointer(env, object);
 
-    ssl_session = getSslSessionPointer(env, object);
-
-    bytes = env->NewByteArray(ssl_session->session_id_length);
-    if (bytes != NULL) {
-        tmp = env->GetByteArrayElements(bytes, NULL);
-        memcpy(tmp, ssl_session->session_id, ssl_session->session_id_length);
-        env->ReleaseByteArrayElements(bytes, tmp, 0);
+    jbyteArray result = env->NewByteArray(ssl_session->session_id_length);
+    if (result != NULL) {
+        jbyte* src = reinterpret_cast<jbyte*>(ssl_session->session_id);
+        env->SetByteArrayRegion(result, 0, ssl_session->session_id_length, src);
     }
 
-    return bytes;
+    return result;
 }
 
 /**
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
index 87f2af3..b474905 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
@@ -989,9 +989,9 @@
     // 'seed == null' when no SecureRandom Object is set
     // in the SSLContext.
     if (seed != NULL) {
-        jboolean iscopy = JNI_FALSE;
-        jbyte* randseed = env->GetByteArrayElements(seed, &iscopy);
+        jbyte* randseed = env->GetByteArrayElements(seed, NULL);
         RAND_seed((unsigned char*) randseed, 1024);
+        env->ReleaseByteArrayElements(seed, randseed, 0);
     } else {
         RAND_load_file("/dev/urandom", 1024);
     }
@@ -1011,6 +1011,19 @@
      */
     SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
 
+    int mode = SSL_CTX_get_mode(ssl_ctx);
+    /*
+     * Turn on "partial write" mode. This means that SSL_write() will
+     * behave like Posix write() and possibly return after only
+     * writing a partial buffer. Note: The alternative, perhaps
+     * surprisingly, is not that SSL_write() always does full writes
+     * but that it will force you to retry write calls having
+     * preserved the full state of the original call. (This is icky
+     * and undesirable.)
+     */
+    mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
+    SSL_CTX_set_mode(ssl_ctx, mode);
+
     if (privatekey != NULL) {
         BIO* privatekeybio = stringToMemBuf(env, (jstring) privatekey);
         EVP_PKEY* privatekeyevp =
@@ -1114,17 +1127,6 @@
 
     fd = jniGetFDFromFileDescriptor(env, fdObject);
 
-    /*
-     * Turn on "partial write" mode. This means that SSL_write() will
-     * behave like Posix write() and possibly return after only
-     * writing a partial buffer. Note: The alternative, perhaps
-     * surprisingly, is not that SSL_write() always does full writes
-     * but that it will force you to retry write calls having
-     * preserved the full state of the original call. (This is icky
-     * and undesirable.)
-     */
-    SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
-
     ssl_session = (SSL_SESSION *) session;
 
     ret = SSL_set_fd(ssl, fd);
@@ -1404,45 +1406,13 @@
 static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_getsupportedciphersuites(JNIEnv* env,
         jobject object)
 {
-    SSL_CTX* ssl_ctx;
-    SSL* ssl;
-    jobjectArray ret;
-    int i;
-    const char *c;
-
-    ssl_ctx = SSL_CTX_new(SSLv23_client_method());
-
+    SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method());
     if (ssl_ctx == NULL) {
         return NULL;
     }
-
-    ssl = SSL_new(ssl_ctx);
-
-    if (ssl == NULL) {
-        SSL_CTX_free(ssl_ctx);
-        return NULL;
-    }
-    
-    i = 0;
-    while (SSL_get_cipher_list(ssl,i) != NULL) {
-        i++;
-    }
-
-    ret = (jobjectArray)env->NewObjectArray(i,
-        env->FindClass("java/lang/String"),
-        env->NewStringUTF(""));
-
-    for (i=0; ; i++) {
-        c=SSL_get_cipher_list(ssl,i);
-        if (c == NULL) break;
-
-        env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
-    }
-
-    SSL_free(ssl);
+    jobjectArray result = makeCipherList(env, ssl_ctx);
     SSL_CTX_free(ssl_ctx);
-
-    return ret;
+    return result;
 }
 
 /**
@@ -1452,57 +1422,66 @@
 static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_getenabledciphersuites(JNIEnv* env,
         jobject object)
 {
-    SSL_CTX* ssl_ctx;
-    SSL* ssl;
-    jobjectArray ret;
-    int i;
-    const char *c;
-
-    ssl = getSslPointer(env, object, false);
-    if (ssl == NULL) {
-        ssl_ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
-        ssl = SSL_new(ssl_ctx);
-        env->SetIntField(object, field_ssl, (int)ssl);
-    }
-
-    i = 0;
-    while (SSL_get_cipher_list(ssl,i) != NULL) {
-        i++;
-    }
-
-    ret = (jobjectArray)env->NewObjectArray(i,
-        env->FindClass("java/lang/String"),
-        env->NewStringUTF(""));
-
-    for (i = 0; ; i++) {
-        c = SSL_get_cipher_list(ssl,i);
-        if (c == NULL) break;
-
-        env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
-    }
-
-    return ret;
+    SSL_CTX* ssl_ctx =
+            reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+    return makeCipherList(env, ssl_ctx);
 }
 
 /**
  * Sets the ciphers suites that are enabled in the OpenSSL client.
  */
 static void org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_setenabledciphersuites(JNIEnv* env, jobject object,
-        jstring controlstring)
+        jstring controlString)
 {
-    SSL_CTX* ctx;
-    const char *str;
-    int ret;
+    SSL_CTX* ssl_ctx =
+            reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+    setEnabledCipherSuites(env, controlString, ssl_ctx);
+}
 
-    ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
-    str = env->GetStringUTFChars(controlstring, 0);
-    ret = SSL_CTX_set_cipher_list(ctx, str);
+static jobjectArray makeCipherList(JNIEnv* env, SSL* ssl) {
+    // Count the ciphers.
+    int cipherCount = 0;
+    while (SSL_get_cipher_list(ssl, cipherCount) != NULL) {
+        ++cipherCount;
+    }
 
-    if (ret == 0) {
+    // Create a String[].
+    jclass stringClass = env->FindClass("java/lang/String");
+    if (stringClass == NULL) {
+        return NULL;
+    }
+    jobjectArray array = env->NewObjectArray(cipherCount, stringClass, NULL);
+    if (array == NULL) {
+        return NULL;
+    }
+
+    // Fill in the cipher names.
+    for (int i = 0; i < cipherCount; ++i) {
+        const char* c = SSL_get_cipher_list(ssl, i);
+        env->SetObjectArrayElement(array, i, env->NewStringUTF(c));
+    }
+    return array;
+}
+
+jobjectArray makeCipherList(JNIEnv* env, SSL_CTX* ssl_ctx) {
+    SSL* ssl = SSL_new(ssl_ctx);
+    if (ssl == NULL) {
+        return NULL;
+    }
+    jobjectArray result = makeCipherList(env, ssl);
+    SSL_free(ssl);
+    return result;
+}
+
+void setEnabledCipherSuites(JNIEnv* env, jstring controlString, SSL_CTX* ssl_ctx) {
+    const char* str = env->GetStringUTFChars(controlString, NULL);
+    int rc = SSL_CTX_set_cipher_list(ssl_ctx, str);
+    env->ReleaseStringUTFChars(controlString, str);
+    if (rc == 0) {
         freeSslErrorState();
-        jclass exClass = env->FindClass("java/lang/IllegalArgumentException");
-        env->ThrowNew(exClass, "Illegal cipher suite strings.");
-    }    
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          "Illegal cipher suite strings.");
+    }
 }
 
 #define SSL_AUTH_MASK           0x00007F00L
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
index 9ed75be..e78cdd8 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
@@ -26,10 +26,10 @@
 /**
  * Structure to hold together useful JNI variables.
  */
-typedef struct {
+struct mydata_t {
     JNIEnv* env;
     jobject object;
-} mydata_t;
+};
 
 /**
  * Gives an array back containing all the X509 certificate's bytes.
@@ -76,9 +76,8 @@
                 joa = NULL;
                 break;
             } else {
-                jbyte *tmp = env->GetByteArrayElements(bytes, NULL);
-                memcpy(tmp, bptr->data, bptr->length);
-                env->ReleaseByteArrayElements(bytes, tmp, 0);
+                jbyte* src = reinterpret_cast<jbyte*>(bptr->data);
+                env->SetByteArrayRegion(bytes, 0, bptr->length, src);
                 env->SetObjectArrayElement(joa, i, bytes);
             }
         }
@@ -118,4 +117,7 @@
     return 1;
 }
 
+extern jobjectArray makeCipherList(JNIEnv* env, SSL_CTX* ssl);
+extern void setEnabledCipherSuites(JNIEnv* env, jstring controlString, SSL_CTX* ssl_ctx);
+
 #endif
diff --git a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
index 3c1fb2e..c4bae0a 100644
--- a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
+++ b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
@@ -32,6 +32,7 @@
 import java.io.InputStream;
 import java.net.InetAddress;
 import java.security.KeyStore;
+import java.security.SecureRandom;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
@@ -585,4 +586,26 @@
                 .createServerSocket();
         return sss;
     }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Guard against native resource leakage.",
+        method = "SSLSocket",
+        args = {}
+    )
+    public void test_creationStressTest() throws Exception {
+        KeyManager[] keyManagers = getKeyManagers();
+        // Test the default codepath, which uses /dev/urandom.
+        SSLContext sslContext = SSLContext.getInstance("TLS");
+        sslContext.init(keyManagers, null, null);
+        for (int i = 0; i < 2048; ++i) {
+            sslContext.getServerSocketFactory().createServerSocket();
+        }
+        
+        // Test the other codepath, which copies a seed from a byte[].
+        sslContext.init(keyManagers, null, new SecureRandom());
+        for (int i = 0; i < 2048; ++i) {
+            sslContext.getServerSocketFactory().createServerSocket();
+        }
+    }
 }
diff --git a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
index 5e39cb1..13a0e59 100644
--- a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
+++ b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
@@ -26,6 +26,7 @@
 
 import java.net.*;
 import java.security.KeyStore;
+import java.security.SecureRandom;
 import java.lang.String;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -336,6 +337,27 @@
         }
     }
     
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Guard against native resource leakage.",
+        method = "SSLSocket",
+        args = {}
+    )
+    public void test_creationStressTest() throws Exception {
+        // Test the default codepath, which uses /dev/urandom.
+        SSLContext sslContext = SSLContext.getInstance("TLS");
+        sslContext.init(null, null, null);
+        for (int i = 0; i < 2048; ++i) {
+            sslContext.getSocketFactory().createSocket();
+        }
+        
+        // Test the other codepath, which copies a seed from a byte[].
+        sslContext.init(null, null, new SecureRandom());
+        for (int i = 0; i < 2048; ++i) {
+            sslContext.getSocketFactory().createSocket();
+        }
+    }
+    
     /**
      * @throws IOException 
      * @tests javax.net.ssl.SSLSocket#addHandshakeCompletedListener(HandshakeCompletedListener listener) 
diff --git a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
index f71d289..2fd16d0 100644
--- a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
+++ b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
@@ -69,7 +69,7 @@
     }
 
     public Node getNextSibling() {
-        if (parent == null || index >= parent.children.size()) {
+        if (parent == null || index + 1 >= parent.children.size()) {
             return null;
         }
 
diff --git a/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index 40a4116..9192b1a 100644
--- a/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -105,16 +105,7 @@
 static jstring emptyString;
 
 /**
- * Throws a NullPointerException.
- *
- * @param msg exception message
- */
-static void throw_NullPointerException(JNIEnv* env, const char* msg) {
-    jniThrowException(env, "java/lang/NullPointerException", msg);
-}
-
-/**
- * Throw a NullPointerException.
+ * Throws OutOfMemoryError.
  */
 static void throw_OutOfMemoryError(JNIEnv* env) {
     jniThrowException(env, "java/lang/OutOfMemoryError", "Out of memory.");
@@ -336,15 +327,9 @@
     return internString(env, parsingContext, nullTerminated);
 }
 
-/**
- * Throw an assertion error.
- *
- * @param message to show
- */
-static void fail(JNIEnv* env, const char* message) {
-    jclass clazz;
-    clazz = env->FindClass("java/lang/AssertionError");
-    env->ThrowNew(clazz, message);
+static void jniThrowExpatException(JNIEnv* env, XML_Error error) {
+    const char* message = XML_ErrorString(error);
+    jniThrowException(env, "org/apache/harmony/xml/ExpatException", message);
 }
 
 /**
@@ -805,18 +790,7 @@
     env->CallVoidMethod(javaParser, processingInstructionMethod, javaTarget,
         javaInstructionData);
 
-    // We have to temporarily clear an exception before we can release local
-    // references.
-    jthrowable exception = env->ExceptionOccurred();
-    if (exception != NULL) {
-        env->ExceptionClear();
-    }
-
     env->DeleteLocalRef(javaInstructionData);
-
-    if (exception != NULL) {
-        env->Throw(exception);
-    }
 }
 
 /**
@@ -1010,21 +984,10 @@
 
     if (!XML_Parse(parser, (char*) characters, length, isFinal)
             && !env->ExceptionCheck()) {
-        jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException");
-        const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser));
-        env->ThrowNew(clazz, errorMessage);
+        jniThrowExpatException(env, XML_GetErrorCode(parser));
     }
 
-    // We have to temporarily clear an exception before we can release local
-    // references.
-    jthrowable exception = env->ExceptionOccurred();
-    if (exception) {
-        env->ExceptionClear();
-        env->ReleaseStringChars(xml, characters);
-        env->Throw(exception);
-    } else {
-        env->ReleaseStringChars(xml, characters);
-    }
+    env->ReleaseStringChars(xml, characters);
 
     context->object = NULL;
     context->env = NULL;
@@ -1050,21 +1013,10 @@
 
     if (!XML_Parse(parser, ((char*) characters) + (offset << 1),
             length << 1, XML_FALSE) && !env->ExceptionCheck()) {
-        jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException");
-        const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser));
-        env->ThrowNew(clazz, errorMessage);
+        jniThrowExpatException(env, XML_GetErrorCode(parser));
     }
 
-    // We have to temporarily clear an exception before we can release local
-    // references.
-    jthrowable exception = env->ExceptionOccurred();
-    if (exception) {
-        env->ExceptionClear();
-        env->ReleaseCharArrayElements(xml, characters, JNI_ABORT);
-        env->Throw(exception);
-    } else {
-        env->ReleaseCharArrayElements(xml, characters, JNI_ABORT);
-    }
+    env->ReleaseCharArrayElements(xml, characters, JNI_ABORT);
 
     context->object = NULL;
     context->env = NULL;
@@ -1090,21 +1042,10 @@
 
     if (!XML_Parse(parser, ((char*) bytes) + offset, length, XML_FALSE)
             && !env->ExceptionCheck()) {
-        jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException");
-        const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser));
-        env->ThrowNew(clazz, errorMessage);
+        jniThrowExpatException(env, XML_GetErrorCode(parser));
     }
 
-    // We have to temporarily clear an exception before we can release local
-    // references.
-    jthrowable exception = env->ExceptionOccurred();
-    if (exception) {
-        env->ExceptionClear();
-        env->ReleaseByteArrayElements(xml, bytes, JNI_ABORT);
-        env->Throw(exception);
-    } else {
-        env->ReleaseByteArrayElements(xml, bytes, JNI_ABORT);
-    }
+    env->ReleaseByteArrayElements(xml, bytes, JNI_ABORT);
 
     context->object = NULL;
     context->env = NULL;
@@ -1308,26 +1249,21 @@
         return getAttributeIndexForQName(
                 env, clazz, attributePointer, localName);
     }
-
     int localNameLength = env->GetStringUTFLength(localName);
 
     // Create string in the same format used by Expat: "uri|localName"
+    // TODO: do we have a guarantee that uriLength and localNameLength are small?
     char concatenated[uriLength + localNameLength + 2];
 
     // Append uri.
-    const char* uriBytes = env->GetStringUTFChars(uri, NULL);
-    if (uriBytes == NULL) return -1;
-    strcpy(concatenated, uriBytes);
-    env->ReleaseStringUTFChars(uri, uriBytes);
+    env->GetStringUTFRegion(uri, 0, uriLength, concatenated);
 
-    // Separarator.
+    // Separator.
     concatenated[uriLength] = '|';
 
     // Append local name.
-    const char* localNameBytes = env->GetStringUTFChars(localName, NULL);
-    if (localNameBytes == NULL) return -1;
-    strcpy(concatenated + uriLength + 1, localNameBytes);
-    env->ReleaseStringUTFChars(localName, localNameBytes);
+    env->GetStringUTFRegion(localName, 0, localNameLength,
+                            concatenated + uriLength + 1);
 
     return findAttributeByName(attributes, concatenated);
 }
diff --git a/libcore/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java b/libcore/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java
index bc5e6a1..a1627ba 100644
--- a/libcore/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java
+++ b/libcore/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java
@@ -54,7 +54,7 @@
     public static final String KEY_ERROR = "error";
     public static final String KEY_FATAL_ERROR = "fatalError";
     public static final String KEY_WARNING = "warning";
-    public static final String KEY_END_ELEMENT = "endEement";
+    public static final String KEY_END_ELEMENT = "endElement";
     public static final String KEY_END_PREFIX_MAPPING = "endPrefixMapping";
     public static final String KEY_IGNORABLE_WHITE_SPACE = 
         "ignorableWhitespace";
diff --git a/libcore/xml/src/test/java/tests/xml/AllTests.java b/libcore/xml/src/test/java/tests/xml/AllTests.java
index eefae50..8c089e3 100644
--- a/libcore/xml/src/test/java/tests/xml/AllTests.java
+++ b/libcore/xml/src/test/java/tests/xml/AllTests.java
@@ -26,6 +26,7 @@
 
         suite.addTestSuite(SimpleParserTest.class);
         suite.addTestSuite(SimpleBuilderTest.class);
+        suite.addTestSuite(NodeTests.class);
         
         //suite.addTest(tests.org.w3c.dom.AllTests.suite());
         suite.addTest(tests.api.javax.xml.parsers.AllTests.suite());
diff --git a/libcore/xml/src/test/java/tests/xml/NodeTests.java b/libcore/xml/src/test/java/tests/xml/NodeTests.java
new file mode 100644
index 0000000..e46e216
--- /dev/null
+++ b/libcore/xml/src/test/java/tests/xml/NodeTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.xml;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.io.ByteArrayInputStream;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+@TestTargetClass(Node.class)
+public class NodeTests extends TestCase {
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Issue #779: org.w3c.dom.Node#getNextSibling throws IndexOutOfBoundsException.",
+        method = "getNextSibling",
+        args = {}
+    )
+    public void test_getNextSibling() throws Exception {
+        // Calling getNextSibling when there is no next sibling should return null.
+        // From http://code.google.com/p/android/issues/detail?id=779.
+        ByteArrayInputStream bis = new ByteArrayInputStream("<root/>".getBytes());
+        Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bis);
+        Node root = document.getDocumentElement();
+        assertNull(root.getNextSibling());
+    }
+}
diff --git a/libnativehelper/Android.mk b/libnativehelper/Android.mk
index aa4be86..f030fea 100644
--- a/libnativehelper/Android.mk
+++ b/libnativehelper/Android.mk
@@ -55,8 +55,8 @@
 
 LOCAL_SRC_FILES := $(src_files)
 LOCAL_C_INCLUDES := $(c_includes)
-LOCAL_SHARED_LIBRARIES := $(shared_libraries)
 LOCAL_STATIC_LIBRARIES := $(static_libraries)
+LOCAL_SHARED_LIBRARIES := $(shared_libraries)
 
 # liblog and libcutils are shared for target.
 LOCAL_SHARED_LIBRARIES += \
@@ -77,15 +77,23 @@
 
     LOCAL_SRC_FILES := $(src_files)
     LOCAL_C_INCLUDES := $(c_includes)
-    LOCAL_SHARED_LIBRARIES := $(shared_libraries)
     LOCAL_STATIC_LIBRARIES := $(static_libraries)
 
+    ifeq ($(HOST_OS)-$(HOST_ARCH),darwin-x86)
+        # OSX has a lot of libraries built in, which we don't have to
+        # bother building; just include them on the ld line.
+        LOCAL_LDLIBS := -lexpat -lssl -lz -lcrypto -licucore -lsqlite3
+	LOCAL_STATIC_LIBRARIES += libutils
+    else
+        LOCAL_SHARED_LIBRARIES := $(shared_libraries)
+    endif
+
     # liblog and libcutils are static for host.
     LOCAL_STATIC_LIBRARIES += \
         liblog libcutils
 
     LOCAL_MODULE := libnativehelper-host
 
-    include $(BUILD_HOST_SHARED_LIBRARY)
+    include $(BUILD_HOST_STATIC_LIBRARY)
 
 endif
diff --git a/tests/020-string/expected.txt b/tests/020-string/expected.txt
index 67b7159..081fea3 100644
--- a/tests/020-string/expected.txt
+++ b/tests/020-string/expected.txt
@@ -3,3 +3,5 @@
 Compare result is 32
 Compare unicode: -65302
 Got expected exception
+subStr is 'uick brown fox jumps over the lazy '
+Indexes are: 0:-1:0:43:33:-1:18:13:13:-1:18:18:-1:13:-1:-1:-1
diff --git a/tests/020-string/src/Main.java b/tests/020-string/src/Main.java
index 4a57fc6..bb8ce1f 100644
--- a/tests/020-string/src/Main.java
+++ b/tests/020-string/src/Main.java
@@ -19,6 +19,11 @@
  */
 public class Main {
     public static void main(String args[]) {
+        basicTest();
+        indexTest();
+    }
+
+    public static void basicTest() {
         String baseStr = "*** This is a very nice string!!!";
         String testStr;
         int i;
@@ -49,4 +54,31 @@
             System.out.println("Got expected exception");
         }
     }
+
+    public static void indexTest() {
+        String baseStr = "The quick brown fox jumps over the lazy dog!";
+        String subStr;
+
+        subStr = baseStr.substring(5, baseStr.length() - 4);
+        System.out.println("subStr is '" + subStr + "'");
+
+        System.out.println("Indexes are: " +
+            baseStr.indexOf('T') + ":" +
+            subStr.indexOf('T') + ":" +
+            subStr.indexOf('u') + ":" +
+            baseStr.indexOf('!') + ":" +
+            subStr.indexOf('y') + ":" +
+            subStr.indexOf('d') + ":" +
+            baseStr.indexOf('x') + ":" +
+            subStr.indexOf('x', 0) + ":" +
+            subStr.indexOf('x', -1) + ":" +
+            subStr.indexOf('x', 200) + ":" +
+            baseStr.indexOf('x', 17) + ":" +
+            baseStr.indexOf('x', 18) + ":" +
+            baseStr.indexOf('x', 19) + ":" +
+            subStr.indexOf('x', 13) + ":" +
+            subStr.indexOf('x', 14) + ":" +
+            subStr.indexOf('&') + ":" +
+            baseStr.indexOf(0x12341234));
+    }
 }
diff --git a/tests/062-character-encodings/expected.txt b/tests/062-character-encodings/expected.txt
index e82e437..aa0279a 100644
--- a/tests/062-character-encodings/expected.txt
+++ b/tests/062-character-encodings/expected.txt
@@ -22,19 +22,29 @@
   ibm-954
   ibm-954_P101-2007
   ujis
-GB2312
-  1383
-  EUC-CN
-  cp1383
-  csGB2312
-  hp15CN
-  ibm-1383
-  ibm-1383_P110-1999
-  ibm-1383_VPUA
-  ibm-eucCN
+EUC-KR
+  5601
+  KSC_5601
+  KS_C_5601-1987
+  KS_C_5601-1989
+  csEUCKR
+  csKSC56011987
+  iso-ir-149
+  korean
+  ms949
+  windows-949
+  windows-949-2000
 GBK
   CP936
+  EUC-CN
+  GB2312
+  GB_2312-80
   MS936
+  chinese
+  csGB2312
+  csISO58GB231280
+  gb2312-1980
+  iso-ir-58
   windows-936
   windows-936-2000
 HZ-GB-2312
@@ -223,12 +233,14 @@
   x-ms-cp932
   x-sjis
 TIS-620
+  MS874
   cp874
   eucTH
   ibm-874
-  ibm-874_P100-1995
   ibm-9066
   tis620.2533
+  windows-874
+  windows-874-2000
 US-ASCII
   646
   ANSI_X3.4-1968
@@ -351,16 +363,14 @@
 x-gsm-03.38-2000
   GSM0338
   gsm-03.38-2000
-x-ibm-1373_P100-2002
-  ibm-1373
-  ibm-1373_P100-2002
-  windows-950
-x-ibm-1386_P100-2001
-  cp1386
-  ibm-1386
-  ibm-1386_P100-2001
-  ibm-1386_VSUB_VPUA
-  windows-936
+x-ibm-1383_P110-1999
+  1383
+  cp1383
+  hp15CN
+  ibm-1383
+  ibm-1383_P110-1999
+  ibm-1383_VPUA
+  ibm-eucCN
 x-IMAP-mailbox-name
   IMAP-mailbox-name
 x-iscii-be
diff --git a/tests/079-phantom/expected.txt b/tests/079-phantom/expected.txt
new file mode 100644
index 0000000..a932b77
--- /dev/null
+++ b/tests/079-phantom/expected.txt
@@ -0,0 +1,14 @@
+start
+Created Bitmap one: 10x10 (100)
+Created Bitmap two: 20x20 (101)
+Created Bitmap three/four: 20x20 (101)
+Drawing Bitmap two: 20x20 (101)
+nulling 1
+freeNativeStorage: 100
+nulling 2
+nulling 3
+nulling 4
+freeNativeStorage: 101
+intr
+Bitmap has shut down
+done
diff --git a/tests/079-phantom/info.txt b/tests/079-phantom/info.txt
new file mode 100644
index 0000000..d974e2c
--- /dev/null
+++ b/tests/079-phantom/info.txt
@@ -0,0 +1 @@
+Exercise phantom references.
diff --git a/tests/079-phantom/src/Bitmap.java b/tests/079-phantom/src/Bitmap.java
new file mode 100644
index 0000000..4d9c259
--- /dev/null
+++ b/tests/079-phantom/src/Bitmap.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.PhantomReference;
+import java.util.ArrayList;
+
+public class Bitmap {
+    String mName;           /* for debugging */
+    int mWidth, mHeight;
+    Bitmap.NativeWrapper mNativeWrapper;
+
+    private static int sSerial = 100;
+    private static ArrayList sPhantomList = new ArrayList<PhantomWrapper>();
+    private static ReferenceQueue<PhantomWrapper> sPhantomQueue =
+            new ReferenceQueue<PhantomWrapper>();
+    private static BitmapWatcher sWatcher = new BitmapWatcher(sPhantomQueue);
+    static {
+        sWatcher.start();
+    };
+
+    Bitmap(String name, int width, int height, Bitmap.NativeWrapper nativeData) {
+        mName = name;
+        mWidth = width;
+        mHeight = height;
+        mNativeWrapper = nativeData;
+
+        System.out.println("Created " + this);
+    }
+
+    public String toString() {
+        return "Bitmap " + mName + ": " + mWidth + "x" + mHeight + " (" +
+                mNativeWrapper.mNativeData + ")";
+    }
+
+    public void drawAt(int x, int y) {
+        System.out.println("Drawing " + this);
+    }
+
+    public static void shutDown() {
+        sWatcher.shutDown();
+        try {
+            sWatcher.join();
+        } catch (InterruptedException ie) {
+            System.out.println("join intr");
+        }
+        System.out.println("Bitmap has shut down");
+    }
+
+    /*
+     * Pretend we're allocating native storage.  Just returns a unique
+     * serial number.
+     */
+    static Bitmap.NativeWrapper allocNativeStorage(int width, int height) {
+        int nativeData;
+
+        synchronized (Bitmap.class) {
+            nativeData = sSerial++;
+        }
+
+        Bitmap.NativeWrapper wrapper = new Bitmap.NativeWrapper(nativeData);
+        PhantomWrapper phan = new PhantomWrapper(wrapper, sPhantomQueue,
+                nativeData);
+        sPhantomList.add(phan);
+        return wrapper;
+    }
+
+    static void freeNativeStorage(int nativeDataPtr) {
+        System.out.println("freeNativeStorage: " + nativeDataPtr);
+    }
+
+    /*
+     * Wraps a native data pointer in an object.  When this object is no
+     * longer referenced, we free the native data.
+     */
+    static class NativeWrapper {
+        public NativeWrapper(int nativeDataPtr) {
+            mNativeData = nativeDataPtr;
+        }
+        public int mNativeData;
+
+        /*
+        @Override
+        protected void finalize() throws Throwable {
+            System.out.println("finalized " + mNativeData);
+        }
+        */
+    }
+}
+
+/*
+ * Keep an eye on the native data.
+ *
+ * We keep a copy of the native data pointer value, and set the wrapper
+ * as our referent.  We need the copy because you can't get the referred-to
+ * object back out of a PhantomReference.
+ */
+class PhantomWrapper extends PhantomReference {
+    PhantomWrapper(Bitmap.NativeWrapper wrapper,
+        ReferenceQueue<PhantomWrapper> queue, int nativeDataPtr)
+    {
+        super(wrapper, queue);
+        mNativeData = nativeDataPtr;
+    }
+
+    public int mNativeData;
+}
+
+/*
+ * Thread that watches for un-referenced bitmap data.
+ */
+class BitmapWatcher extends Thread {
+    ReferenceQueue<PhantomWrapper> mQueue;
+    volatile boolean mQuit = false;
+
+    BitmapWatcher(ReferenceQueue<PhantomWrapper> queue) {
+        mQueue = queue;
+        setName("Bitmap Watcher");
+    }
+
+    public void run() {
+        while (!mQuit) {
+            try {
+                PhantomWrapper ref = (PhantomWrapper) mQueue.remove();
+                //System.out.println("dequeued ref " + ref.mNativeData +
+                //    " - " + ref);
+                Bitmap.freeNativeStorage(ref.mNativeData);
+                //ref.clear();
+            } catch (InterruptedException ie) {
+                System.out.println("intr");
+            }
+        }
+    }
+
+    public void shutDown() {
+        mQuit = true;
+        interrupt();
+    }
+}
+
diff --git a/tests/079-phantom/src/Main.java b/tests/079-phantom/src/Main.java
new file mode 100644
index 0000000..3965481
--- /dev/null
+++ b/tests/079-phantom/src/Main.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+    Bitmap mBitmap1, mBitmap2, mBitmap3, mBitmap4;
+
+    public static void sleep(int ms) {
+        try {
+            Thread.sleep(ms);
+        } catch (InterruptedException ie) {
+            System.err.println("sleep interrupted");
+        }
+    }
+
+    public static void main(String args[]) {
+        System.out.println("start");
+
+        Main main = new Main();
+        main.run();
+
+        sleep(1000);
+        System.out.println("done");
+    }
+
+    public void run() {
+        createBitmaps();
+
+        System.gc();
+        sleep(250);
+
+        mBitmap2.drawAt(0, 0);
+
+        System.out.println("nulling 1");
+        mBitmap1 = null;
+        System.gc();
+        sleep(500);
+
+        System.out.println("nulling 2");
+        mBitmap2 = null;
+        System.gc();
+        sleep(500);
+
+        System.out.println("nulling 3");
+        mBitmap3 = null;
+        System.gc();
+        sleep(500);
+
+        System.out.println("nulling 4");
+        mBitmap4 = null;
+        System.gc();
+        sleep(500);
+
+        Bitmap.shutDown();
+    }
+
+    /*
+     * Create bitmaps.
+     *
+     * bitmap1 is 10x10 and unique
+     * bitmap2 and bitmap3 are 20x20 and share the same storage.
+     * bitmap4 is just another reference to bitmap3
+     *
+     * When we return there should be no local refs lurking on the stack.
+     */
+    public void createBitmaps() {
+        Bitmap.NativeWrapper dataA = Bitmap.allocNativeStorage(10, 10);
+        Bitmap.NativeWrapper dataB = Bitmap.allocNativeStorage(20, 20);
+        mBitmap1 = new Bitmap("one", 10, 10, dataA);
+        mBitmap2 = new Bitmap("two", 20, 20, dataB);
+        mBitmap3 = mBitmap4 = new Bitmap("three/four", 20, 20, dataB);
+    }
+}
+
diff --git a/tests/080-oom-throw/expected.txt b/tests/080-oom-throw/expected.txt
new file mode 100644
index 0000000..811f68c
--- /dev/null
+++ b/tests/080-oom-throw/expected.txt
@@ -0,0 +1,2 @@
+Array allocation failed
+Instance allocation failed
diff --git a/tests/080-oom-throw/info.txt b/tests/080-oom-throw/info.txt
new file mode 100644
index 0000000..e8ae6f6
--- /dev/null
+++ b/tests/080-oom-throw/info.txt
@@ -0,0 +1,3 @@
+Inject memory allocation failures for NEW_ARRAY and NEW_INSTANCE and make sure
+the JIT'ed code handles OOM exception correctly since it cannot fall back to
+the interpreter and re-execute the bytecode.
diff --git a/tests/080-oom-throw/src/Main.java b/tests/080-oom-throw/src/Main.java
new file mode 100644
index 0000000..3d75f3d
--- /dev/null
+++ b/tests/080-oom-throw/src/Main.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+    static class ArrayMemEater {
+        static int blowup(char[][] holder, int size) {
+            int i = 0;
+            try {
+                for ( ; i < size; i++)
+                    holder[i] = new char[128];
+            } catch (OutOfMemoryError oome) {
+                return i;
+            }
+
+            return size;
+        }
+
+        static void confuseCompilerOptimization(char[][] holder) {
+        }
+    }
+
+    static class InstanceMemEater {
+        InstanceMemEater next;
+        double d1, d2, d3, d4, d5, d6, d7, d8;
+
+        static InstanceMemEater blowup() {
+            InstanceMemEater memEater;
+            try {
+                memEater = new InstanceMemEater();
+            } catch (OutOfMemoryError e) {
+                memEater = null;
+            }
+            return memEater;
+        }
+
+        static void confuseCompilerOptimization(InstanceMemEater memEater) {
+        }
+    }
+
+    static void triggerArrayOOM() {
+        int size = 1 * 1024 * 1024;
+        char[][] holder = new char[size][];
+
+        int count = ArrayMemEater.blowup(holder, size);
+        ArrayMemEater.confuseCompilerOptimization(holder);
+        if (count < size) {
+            System.out.println("Array allocation failed");
+        }
+    }
+
+    static void triggerInstanceOOM() {
+        InstanceMemEater memEater = InstanceMemEater.blowup();
+        InstanceMemEater lastMemEater = memEater;
+        do {
+            lastMemEater.next = InstanceMemEater.blowup();
+            lastMemEater = lastMemEater.next;
+        } while (lastMemEater != null);
+        memEater.confuseCompilerOptimization(memEater);
+        System.out.println("Instance allocation failed");
+    }
+
+    public static void main(String[] args) {
+        triggerArrayOOM();
+        triggerInstanceOOM();
+    }
+}
diff --git a/tests/081-hot-exceptions/expected.txt b/tests/081-hot-exceptions/expected.txt
new file mode 100644
index 0000000..2432ff4
--- /dev/null
+++ b/tests/081-hot-exceptions/expected.txt
@@ -0,0 +1,2 @@
+sum = 0
+exception = 1024
diff --git a/tests/081-hot-exceptions/info.txt b/tests/081-hot-exceptions/info.txt
new file mode 100644
index 0000000..cc514f3
--- /dev/null
+++ b/tests/081-hot-exceptions/info.txt
@@ -0,0 +1,3 @@
+Make a hot exception-throwing path to stress test how the trace builder handles
+exceptions encountered during trace selection. The existence of exceptions will
+cause a control flow change to deviate from the current method.
diff --git a/tests/081-hot-exceptions/src/Main.java b/tests/081-hot-exceptions/src/Main.java
new file mode 100644
index 0000000..90e7af2
--- /dev/null
+++ b/tests/081-hot-exceptions/src/Main.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+    static class ArrayObj {
+        int[] array;
+
+        int getArrayElement(int i) throws NullPointerException {
+            return array[i];
+        }
+    }
+
+    public static void main(String[] args) {
+        ArrayObj arrayObj2 = new ArrayObj();
+        int sum = 0;
+        int exception = 0;
+
+        for (int i = 0; i < 1024; i++) {
+            try {
+                // A hot method invocation that always encounters exceptions
+                sum += arrayObj2.getArrayElement(i);
+            } catch (NullPointerException npe) {
+                exception++;
+            }
+        }
+        System.out.println("sum = " + sum);
+        System.out.println("exception = " + exception);
+    }
+}
diff --git a/tools/dexcheck b/tools/dexcheck
index 76662e8..ff3e98d 100755
--- a/tools/dexcheck
+++ b/tools/dexcheck
@@ -1,5 +1,19 @@
 #!/bin/bash
 #
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 # This requires read permission on /data/dalvik-cache.  On an eng build this
 # works, on userdebug you will need to "adb root", or "su" followed by
 # "chmod 777 /data/dalvik-cache".
@@ -14,7 +28,7 @@
 failure=0
 
 # Check each file in turn.  This is much faster with "dexdump -c", but that
-# was added post-cupcake.
+# flag was not available in 1.6 and earlier.
 #
 # The dexdump found in older builds does not stop on checksum failures and
 # will likely crash.
diff --git a/vm/Android.mk b/vm/Android.mk
index 5c276aa..6e71655 100644
--- a/vm/Android.mk
+++ b/vm/Android.mk
@@ -69,14 +69,21 @@
     LOCAL_STATIC_LIBRARIES += \
         liblog libcutils
 
-    # libffi is called libffi-host on the host. Similarly libnativehelper.
-    LOCAL_SHARED_LIBRARIES := \
-        $(patsubst libffi,libffi-host,$(LOCAL_SHARED_LIBRARIES))
-    LOCAL_SHARED_LIBRARIES := \
-        $(patsubst libnativehelper,libnativehelper-host,$(LOCAL_SHARED_LIBRARIES))
+    # libffi is called libffi-host on the host and should be staticly
+    # linked. Similarly libnativehelper.
+    ifneq (,$(findstring libffi,$(LOCAL_SHARED_LIBRARIES)))
+        LOCAL_SHARED_LIBRARIES := \
+            $(patsubst libffi, ,$(LOCAL_SHARED_LIBRARIES))
+        LOCAL_STATIC_LIBRARIES += libffi-host
+    endif
+    ifneq (,$(findstring libnativehelper,$(LOCAL_SHARED_LIBRARIES)))
+        LOCAL_SHARED_LIBRARIES := \
+            $(patsubst libnativehelper, ,$(LOCAL_SHARED_LIBRARIES))
+        LOCAL_STATIC_LIBRARIES += libnativehelper-host
+    endif
 
     LOCAL_MODULE := libdvm-host
 
-    include $(BUILD_HOST_SHARED_LIBRARY)
+    include $(BUILD_HOST_STATIC_LIBRARY)
 
 endif
diff --git a/vm/DalvikVersion.h b/vm/DalvikVersion.h
index efbb393..eae335d 100644
--- a/vm/DalvikVersion.h
+++ b/vm/DalvikVersion.h
@@ -24,7 +24,7 @@
  * The version we show to tourists.
  */
 #define DALVIK_MAJOR_VERSION    1
-#define DALVIK_MINOR_VERSION    1
+#define DALVIK_MINOR_VERSION    2
 #define DALVIK_BUG_VERSION      0
 
 /*
@@ -32,6 +32,6 @@
  * way classes load changes, e.g. field ordering or vtable layout.  Changing
  * this guarantees that the optimized form of the DEX file is regenerated.
  */
-#define DALVIK_VM_BUILD         17
+#define DALVIK_VM_BUILD         18
 
 #endif /*_DALVIK_VERSION*/
diff --git a/vm/Debugger.c b/vm/Debugger.c
index 4ddf25c..eec8176 100644
--- a/vm/Debugger.c
+++ b/vm/Debugger.c
@@ -419,7 +419,7 @@
     dvmHashTableLock(gDvm.dbgRegistry);
     gDvm.debuggerConnected = false;
 
-    LOGI("Debugger has detached; object registry had %d entries\n",
+    LOGD("Debugger has detached; object registry had %d entries\n",
         dvmHashTableNumEntries(gDvm.dbgRegistry));
     //int i;
     //for (i = 0; i < gDvm.dbgRegistryNext; i++)
@@ -512,6 +512,15 @@
 }
 
 /*
+ * Convert a RefTypeId to an ObjectId.
+ */
+ObjectId dvmDbgGetClassObject(RefTypeId id)
+{
+    ClassObject* clazz = refTypeIdToClassObject(id);
+    return objectToObjectId((Object*) clazz);
+}
+
+/*
  * Return the superclass of a class (will be NULL for java/lang/Object).
  */
 RefTypeId dvmDbgGetSuperclass(RefTypeId id)
@@ -1117,6 +1126,19 @@
 }
 
 /*
+ * Allocate a new object of the specified type.
+ *
+ * Add it to the registry to prevent it from being GCed.
+ */
+ObjectId dvmDbgCreateObject(RefTypeId classId)
+{
+    ClassObject* clazz = refTypeIdToClassObject(classId);
+    Object* newObj = dvmAllocObject(clazz, ALLOC_DEFAULT);
+    dvmReleaseTrackedAlloc(newObj, NULL);
+    return objectToObjectId(newObj);
+}
+
+/*
  * Determine if "instClassId" is an instance of "classId".
  */
 bool dvmDbgMatchType(RefTypeId instClassId, RefTypeId classId)
@@ -2676,6 +2698,30 @@
     }
 
     /*
+     * We currently have a bug where we don't successfully resume the
+     * target thread if the suspend count is too deep.  We're expected to
+     * require one "resume" for each "suspend", but when asked to execute
+     * a method we have to resume fully and then re-suspend it back to the
+     * same level.  (The easiest way to cause this is to type "suspend"
+     * multiple times in jdb.)
+     *
+     * It's unclear what this means when the event specifies "resume all"
+     * and some threads are suspended more deeply than others.  This is
+     * a rare problem, so for now we just prevent it from hanging forever
+     * by rejecting the method invocation request.  Without this, we will
+     * be stuck waiting on a suspended thread.
+     */
+    if (targetThread->suspendCount > 1) {
+        LOGW("threadid=%d: suspend count on threadid=%d is %d, too deep "
+             "for method exec\n",
+            dvmThreadSelf()->threadId, targetThread->threadId,
+            targetThread->suspendCount);
+        err = ERR_THREAD_SUSPENDED;     /* probably not expected here */
+        dvmUnlockThreadList();
+        goto bail;
+    }
+
+    /*
      * TODO: ought to screen the various IDs, and verify that the argument
      * list is valid.
      */
@@ -2796,9 +2842,11 @@
 
     /*
      * Translate the method through the vtable, unless we're calling a
-     * static method or the debugger wants to suppress it.
+     * direct method or the debugger wants to suppress it.
      */
-    if ((pReq->options & INVOKE_NONVIRTUAL) != 0 || pReq->obj == NULL) {
+    if ((pReq->options & INVOKE_NONVIRTUAL) != 0 || pReq->obj == NULL ||
+        dvmIsDirectMethod(pReq->method))
+    {
         meth = pReq->method;
     } else {
         meth = dvmGetVirtualizedMethod(pReq->clazz, pReq->method);
@@ -2809,8 +2857,8 @@
 
     IF_LOGV() {
         char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
-        LOGV("JDWP invoking method %s.%s %s\n",
-            meth->clazz->descriptor, meth->name, desc);
+        LOGV("JDWP invoking method %p/%p %s.%s:%s\n",
+            pReq->method, meth, meth->clazz->descriptor, meth->name, desc);
         free(desc);
     }
 
@@ -2819,8 +2867,10 @@
     pReq->exceptObj = objectToObjectId(dvmGetException(self));
     pReq->resultTag = resultTagFromSignature(meth);
     if (pReq->exceptObj != 0) {
-        LOGD("  JDWP invocation returning with exceptObj=%p\n",
-            dvmGetException(self));
+        Object* exc = dvmGetException(self);
+        LOGD("  JDWP invocation returning with exceptObj=%p (%s)\n",
+            exc, exc->clazz->descriptor);
+        //dvmLogExceptionStackTrace();
         dvmClearException(self);
         /*
          * Nothing should try to use this, but it looks like something is.
diff --git a/vm/Debugger.h b/vm/Debugger.h
index fcf07c7..189e2be 100644
--- a/vm/Debugger.h
+++ b/vm/Debugger.h
@@ -159,6 +159,7 @@
  * Class, Object, Array
  */
 const char* dvmDbgGetClassDescriptor(RefTypeId id);
+ObjectId dvmDbgGetClassObject(RefTypeId id);
 RefTypeId dvmDbgGetSuperclass(RefTypeId id);
 ObjectId dvmDbgGetClassLoader(RefTypeId id);
 u4 dvmDbgGetAccessFlags(RefTypeId id);
@@ -188,6 +189,7 @@
     const u1* buf);
 
 ObjectId dvmDbgCreateString(const char* str);
+ObjectId dvmDbgCreateObject(RefTypeId classId);
 
 bool dvmDbgMatchType(RefTypeId instClassId, RefTypeId classId);
 
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
index 96f6dac..5aea242 100644
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -194,23 +194,34 @@
 	test/TestHash.c \
 	test/TestIndirectRefTable.c
 
-ifeq ($(WITH_JIT_TUNING),true)
-  LOCAL_CFLAGS += -DWITH_JIT_TUNING
-  # NOTE: Turn on assertion for JIT for now
-  LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1 -DLOG_NDEBUG=1 -DWITH_DALVIK_ASSERT
-endif
+WITH_JIT := $(strip $(WITH_JIT))
 
 ifeq ($(WITH_JIT),true)
   LOCAL_CFLAGS += -DWITH_JIT
+  # Enable assert and JIT_TUNING for now
+  LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1 -DLOG_NDEBUG=1 -DWITH_DALVIK_ASSERT
+  WITH_JIT_TUNING := true
   LOCAL_SRC_FILES += \
 	../dexdump/OpCodeNames.c \
 	compiler/Compiler.c \
 	compiler/Frontend.c \
 	compiler/Utility.c \
 	compiler/IntermediateRep.c \
+	compiler/Dataflow.c \
+	compiler/Loop.c \
 	interp/Jit.c
 endif
 
+ifeq ($(strip $(WITH_JIT_TUNING)),true)
+  LOCAL_CFLAGS += -DWITH_JIT_TUNING
+endif
+
+# Enable JIT self verification tool. Runs compiled traces natively, then replays
+# them with the interpreter, and ensures memory and register state are the same.
+ifeq ($(WITH_SELF_VERIFICATION),true)
+  LOCAL_CFLAGS += -DWITH_SELF_VERIFICATION
+endif
+
 WITH_HPROF := $(strip $(WITH_HPROF))
 ifeq ($(WITH_HPROF),)
   WITH_HPROF := true
@@ -308,7 +319,13 @@
 ifeq ($(MTERP_ARCH_KNOWN),false)
   # unknown architecture, try to use FFI
   LOCAL_C_INCLUDES += external/libffi/$(dvm_os)-$(dvm_arch)
-  LOCAL_SHARED_LIBRARIES += libffi
+
+  ifeq ($(dvm_os)-$(dvm_arch),darwin-x86)
+      # OSX includes libffi, so just make the linker aware of it directly.
+      LOCAL_LDLIBS += -lffi
+  else
+      LOCAL_SHARED_LIBRARIES += libffi
+  endif
 
   LOCAL_SRC_FILES += \
 		arch/generic/Call.c \
diff --git a/vm/Globals.h b/vm/Globals.h
index 9b12d84..23b7497 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -748,8 +748,16 @@
     /* Flag to count trace execution */
     bool profile;
 
+    /* Vector to disable selected optimizations */
+    int disableOpt;
+
     /* Table to track the overall and trace statistics of hot methods */
     HashTable*  methodStatsTable;
+
+#if defined(WITH_SELF_VERIFICATION)
+    /* Spin when error is detected, volatile so GDB can reset it */
+    volatile bool selfVerificationSpin;
+#endif
 };
 
 extern struct DvmJitGlobals gDvmJit;
diff --git a/vm/IndirectRefTable.c b/vm/IndirectRefTable.c
index f7c7647..bea0a0f 100644
--- a/vm/IndirectRefTable.c
+++ b/vm/IndirectRefTable.c
@@ -35,6 +35,12 @@
 #ifndef NDEBUG
     memset(pRef->table, 0xd1, initialCount * sizeof(Object*));
 #endif
+
+    pRef->slotData =
+        (IndirectRefSlot*) calloc(maxCount, sizeof(IndirectRefSlot));
+    if (pRef->slotData == NULL)
+        return false;
+
     pRef->segmentState.all = IRT_FIRST_SEGMENT;
     pRef->allocEntries = initialCount;
     pRef->maxEntries = maxCount;
@@ -79,8 +85,8 @@
         return false;
     }
 
-    LOGV("--- after pop, top=%d holes=%d\n",
-        sst.parts.topIndex, sst.parts.numHoles);
+    LOGV("IRT %p[%d]: pop, top=%d holes=%d\n",
+        pRef, pRef->kind, sst.parts.topIndex, sst.parts.numHoles);
 
     return true;
 }
@@ -91,15 +97,45 @@
 static bool checkEntry(IndirectRefTable* pRef, IndirectRef iref, int idx)
 {
     Object* obj = pRef->table[idx];
-    IndirectRef checkRef = dvmObjectToIndirectRef(obj, idx, pRef->kind);
+    IndirectRef checkRef = dvmObjectToIndirectRef(pRef, obj, idx, pRef->kind);
     if (checkRef != iref) {
-        LOGW("iref mismatch: %p vs %p\n", iref, checkRef);
+        LOGW("IRT %p[%d]: iref mismatch (req=%p vs cur=%p)\n",
+            pRef, pRef->kind, iref, checkRef);
         return false;
     }
     return true;
 }
 
 /*
+ * Update extended debug info when an entry is added.
+ *
+ * We advance the serial number, invalidating any outstanding references to
+ * this slot.
+ */
+static inline void updateSlotAdd(IndirectRefTable* pRef, Object* obj, int slot)
+{
+    if (pRef->slotData != NULL) {
+        IndirectRefSlot* pSlot = &pRef->slotData[slot];
+        pSlot->serial++;
+        //LOGI("+++ add [%d] slot %d (%p->%p), serial=%d\n",
+        //    pRef->kind, slot, obj, iref, pSlot->serial);
+        pSlot->previous[pSlot->serial % kIRTPrevCount] = obj;
+    }
+}
+
+/*
+ * Update extended debug info when an entry is removed.
+ */
+static inline void updateSlotRemove(IndirectRefTable* pRef, int slot)
+{
+    if (pRef->slotData != NULL) {
+        IndirectRefSlot* pSlot = &pRef->slotData[slot];
+        //LOGI("+++ remove [%d] slot %d, serial now %d\n",
+        //    pRef->kind, slot, pSlot->serial);
+    }
+}
+
+/*
  * Add "obj" to "pRef".
  */
 IndirectRef dvmAddToIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
@@ -161,12 +197,15 @@
         while (*--pScan != NULL) {
             assert(pScan >= pRef->table + bottomIndex);
         }
-        result = dvmObjectToIndirectRef(obj, pScan - pRef->table, pRef->kind);
+        updateSlotAdd(pRef, obj, pScan - pRef->table);
+        result = dvmObjectToIndirectRef(pRef, obj, pScan - pRef->table,
+            pRef->kind);
         *pScan = obj;
         pRef->segmentState.parts.numHoles--;
     } else {
         /* add to the end */
-        result = dvmObjectToIndirectRef(obj, topIndex, pRef->kind);
+        updateSlotAdd(pRef, obj, topIndex);
+        result = dvmObjectToIndirectRef(pRef, obj, topIndex, pRef->kind);
         pRef->table[topIndex++] = obj;
         pRef->segmentState.parts.topIndex = topIndex;
     }
@@ -220,6 +259,9 @@
  * specified by the cookie, we don't remove anything.  This is the behavior
  * required by JNI's DeleteLocalRef function.
  *
+ * Note this is NOT called when a local frame is popped.  This is only used
+ * for explict single removals.
+ *
  * Returns "false" if nothing was removed.
  */
 bool dvmRemoveFromIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
@@ -255,6 +297,7 @@
          */
         if (!checkEntry(pRef, iref, idx))
             return false;
+        updateSlotRemove(pRef, idx);
 
 #ifndef NDEBUG
         pRef->table[idx] = (IndirectRef) 0xd3d3d3d3;
@@ -290,6 +333,7 @@
         }
         if (!checkEntry(pRef, iref, idx))
             return false;
+        updateSlotRemove(pRef, idx);
 
         pRef->table[idx] = NULL;
         pRef->segmentState.parts.numHoles++;
@@ -408,7 +452,7 @@
     qsort(tableCopy, count, sizeof(Object*), compareObject);
     refs = tableCopy;       // use sorted list
 
-    {
+    if (false) {
         int q;
         for (q = 0; q < count; q++)
             LOGI("%d %p\n", q, refs[q]);
diff --git a/vm/IndirectRefTable.h b/vm/IndirectRefTable.h
index c03353b..6a4db04 100644
--- a/vm/IndirectRefTable.h
+++ b/vm/IndirectRefTable.h
@@ -98,6 +98,16 @@
 } IndirectRefKind;
 
 /*
+ * Extended debugging structure.  We keep a parallel array of these, one
+ * per slot in the table.
+ */
+#define kIRTPrevCount   4
+typedef struct IndirectRefSlot {
+    u4          serial;         /* slot serial */
+    Object*     previous[kIRTPrevCount];
+} IndirectRefSlot;
+
+/*
  * Table definition.
  *
  * For the global reference table, the expected common operations are
@@ -179,6 +189,7 @@
     Object**        table;              /* bottom of the stack */
 
     /* private */
+    IndirectRefSlot* slotData;          /* extended debugging info */
     int             allocEntries;       /* #of entries we have space for */
     int             maxEntries;         /* max #of entries allowed */
     IndirectRefKind kind;               /* bit mask, ORed into all irefs */
@@ -198,12 +209,14 @@
  * The object pointer itself is subject to relocation in some GC
  * implementations, so we shouldn't really be using it here.
  */
-INLINE IndirectRef dvmObjectToIndirectRef(Object* obj, u4 tableIndex,
-    IndirectRefKind kind)
+INLINE IndirectRef dvmObjectToIndirectRef(IndirectRefTable* pRef,
+    Object* obj, u4 tableIndex, IndirectRefKind kind)
 {
     assert(tableIndex < 65536);
-    u4 objChunk = (((u4) obj >> 3) ^ ((u4) obj >> 19)) & 0x3fff;
-    u4 uref = objChunk << 18 | (tableIndex << 2) | kind;
+    //u4 objChunk = (((u4) obj >> 3) ^ ((u4) obj >> 19)) & 0x3fff;
+    //u4 uref = objChunk << 18 | (tableIndex << 2) | kind;
+    u4 serialChunk = pRef->slotData[tableIndex].serial;
+    u4 uref = serialChunk << 20 | (tableIndex << 2) | kind;
     return (IndirectRef) uref;
 }
 
@@ -270,7 +283,7 @@
  *
  * IMPORTANT: this is implemented as a single instruction in mterp, rather
  * than a call here.  You can add debugging aids for the C-language
- * interpreters, but the basic implementation may not change.
+ * interpreters, but the basic implementation must not change.
  */
 INLINE void dvmPopIndirectRefTableSegment(IndirectRefTable* pRef, u4 cookie)
 {
@@ -323,7 +336,8 @@
         /* up against alloc or max limit, call the fancy version */
         return dvmAddToIndirectRefTable(pRef, cookie, obj);
     } else {
-        IndirectRef result = dvmObjectToIndirectRef(obj, topIndex, pRef->kind);
+        IndirectRef result = dvmObjectToIndirectRef(pRef, obj, topIndex,
+            pRef->kind);
         pRef->table[topIndex++] = obj;
         pRef->segmentState.parts.topIndex = topIndex;
         return result;
diff --git a/vm/Init.c b/vm/Init.c
index c46de25..7f83bc5 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -120,6 +120,7 @@
                        "(eg Ljava/lang/String\\;replace)\n");
     dvmFprintf(stderr, "  -Xjitverbose\n");
     dvmFprintf(stderr, "  -Xjitprofile\n");
+    dvmFprintf(stderr, "  -Xjitdisableopt\n");
 #endif
     dvmFprintf(stderr, "\n");
     dvmFprintf(stderr, "Configured with:"
@@ -185,7 +186,10 @@
         " resolver_cache_disabled"
 #endif
 #if defined(WITH_JIT)
-        " with_jit"
+        " jit"
+#endif
+#if defined(WITH_SELF_VERIFICATION)
+        " self_verification"
 #endif
     );
 #ifdef DVM_SHOW_EXCEPTION
@@ -907,6 +911,8 @@
           gDvmJit.printMe = true;
         } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
           gDvmJit.profile = true;
+        } else if (strncmp(argv[i], "-Xjitdisableopt:", 16) == 0) {
+          sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
 #endif
 
         } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
@@ -1362,8 +1368,10 @@
         (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
 
 #ifdef WITH_JIT
-    if (!dvmJitStartup())
-        return false;
+    if (gDvm.executionMode == kExecutionModeJit) {
+        if (!dvmJitStartup())
+            return false;
+    }
 #endif
 
     return true;
@@ -1552,8 +1560,10 @@
     dvmStdioConverterShutdown();
 
 #ifdef WITH_JIT
-    /* tell the compiler to shut down if it was started */
-    dvmJitShutdown();
+    if (gDvm.executionMode == kExecutionModeJit) {
+        /* shut down the compiler thread */
+        dvmJitShutdown();
+    }
 #endif
 
     /*
diff --git a/vm/InlineNative.c b/vm/InlineNative.c
index f829360..ec8a1fb 100644
--- a/vm/InlineNative.c
+++ b/vm/InlineNative.c
@@ -129,14 +129,14 @@
         return false;
 
     //LOGI("String.charAt this=0x%08x index=%d\n", arg0, arg1);
-    count = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
+    count = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
     if ((s4) arg1 < 0 || (s4) arg1 >= count) {
         dvmThrowException("Ljava/lang/StringIndexOutOfBoundsException;", NULL);
         return false;
     } else {
-        offset = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_offset);
+        offset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET);
         chars = (ArrayObject*)
-            dvmGetFieldObject((Object*) arg0, gDvm.offJavaLangString_value);
+            dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
 
         pResult->i = ((const u2*) chars->contents)[arg1 + offset];
         return true;
@@ -157,17 +157,17 @@
     int thisOffset, compOffset, thisCount, compCount;
 
     thisCount =
-        dvmGetFieldInt((Object*) thisStrObj, gDvm.offJavaLangString_count);
+        dvmGetFieldInt((Object*) thisStrObj, STRING_FIELDOFF_COUNT);
     compCount =
-        dvmGetFieldInt((Object*) compStrObj, gDvm.offJavaLangString_count);
+        dvmGetFieldInt((Object*) compStrObj, STRING_FIELDOFF_COUNT);
     thisOffset =
-        dvmGetFieldInt((Object*) thisStrObj, gDvm.offJavaLangString_offset);
+        dvmGetFieldInt((Object*) thisStrObj, STRING_FIELDOFF_OFFSET);
     compOffset =
-        dvmGetFieldInt((Object*) compStrObj, gDvm.offJavaLangString_offset);
+        dvmGetFieldInt((Object*) compStrObj, STRING_FIELDOFF_OFFSET);
     thisArray = (ArrayObject*)
-        dvmGetFieldObject((Object*) thisStrObj, gDvm.offJavaLangString_value);
+        dvmGetFieldObject((Object*) thisStrObj, STRING_FIELDOFF_VALUE);
     compArray = (ArrayObject*)
-        dvmGetFieldObject((Object*) compStrObj, gDvm.offJavaLangString_value);
+        dvmGetFieldObject((Object*) compStrObj, STRING_FIELDOFF_VALUE);
 
     thisStr = dvmCreateCstrFromString(thisStrObj);
     compStr = dvmCreateCstrFromString(compStrObj);
@@ -221,16 +221,16 @@
     const u2* compChars;
     int i, minCount, countDiff;
 
-    thisCount = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
-    compCount = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_count);
+    thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
+    compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT);
     countDiff = thisCount - compCount;
     minCount = (countDiff < 0) ? thisCount : compCount;
-    thisOffset = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_offset);
-    compOffset = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_offset);
+    thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET);
+    compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET);
     thisArray = (ArrayObject*)
-        dvmGetFieldObject((Object*) arg0, gDvm.offJavaLangString_value);
+        dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
     compArray = (ArrayObject*)
-        dvmGetFieldObject((Object*) arg1, gDvm.offJavaLangString_value);
+        dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE);
     thisChars = ((const u2*) thisArray->contents) + thisOffset;
     compChars = ((const u2*) compArray->contents) + compOffset;
 
@@ -321,19 +321,19 @@
     int i;
 
     /* quick length check */
-    thisCount = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
-    compCount = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_count);
+    thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
+    compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT);
     if (thisCount != compCount) {
         pResult->i = false;
         return true;
     }
 
-    thisOffset = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_offset);
-    compOffset = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_offset);
+    thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET);
+    compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET);
     thisArray = (ArrayObject*)
-        dvmGetFieldObject((Object*) arg0, gDvm.offJavaLangString_value);
+        dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
     compArray = (ArrayObject*)
-        dvmGetFieldObject((Object*) arg1, gDvm.offJavaLangString_value);
+        dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE);
     thisChars = ((const u2*) thisArray->contents) + thisOffset;
     compChars = ((const u2*) compArray->contents) + compOffset;
 
@@ -383,7 +383,90 @@
     if (!dvmValidateObject((Object*) arg0))
         return false;
 
-    pResult->i = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
+    pResult->i = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
+    return true;
+}
+
+/*
+ * Determine the index of the first character matching "ch".  The string
+ * to search is described by "chars", "offset", and "count".
+ *
+ * The "ch" parameter is allowed to be > 0xffff.  Our Java-language
+ * implementation does not currently handle this, so neither do we.
+ *
+ * The "start" parameter must be clamped to [0..count].
+ *
+ * Returns -1 if no match is found.
+ */
+static inline int indexOfCommon(Object* strObj, int ch, int start)
+{
+    //if ((ch & 0xffff) != ch)        /* 32-bit code point */
+    //    return -1;
+
+    /* pull out the basic elements */
+    ArrayObject* charArray =
+        (ArrayObject*) dvmGetFieldObject(strObj, STRING_FIELDOFF_VALUE);
+    const u2* chars = (const u2*) charArray->contents;
+    int offset = dvmGetFieldInt(strObj, STRING_FIELDOFF_OFFSET);
+    int count = dvmGetFieldInt(strObj, STRING_FIELDOFF_COUNT);
+    //LOGI("String.indexOf(0x%08x, 0x%04x, %d) off=%d count=%d\n",
+    //    (u4) strObj, ch, start, offset, count);
+
+    /* factor out the offset */
+    chars += offset;
+
+    if (start < 0)
+        start = 0;
+
+#if 0
+    /* 16-bit loop, simple */
+    while (start < count) {
+        if (chars[start] == ch)
+            return start;
+        start++;
+    }
+#else
+    /* 16-bit loop, slightly better on ARM */
+    const u2* ptr = chars + start;
+    const u2* endPtr = chars + count;
+    while (ptr < endPtr) {
+        if (*ptr++ == ch)
+            return (ptr-1) - chars;
+    }
+#endif
+
+    return -1;
+}
+
+/*
+ * public int indexOf(int c)
+ *
+ * Scan forward through the string for a matching character.
+ */
+static bool javaLangString_indexOf_I(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    /* null reference check on "this" */
+    if (!dvmValidateObject((Object*) arg0))
+        return false;
+
+    pResult->i = indexOfCommon((Object*) arg0, arg1, 0);
+    return true;
+}
+
+/*
+ * public int indexOf(int c, int start)
+ *
+ * Scan forward through the string for a matching character.
+ */
+static bool javaLangString_indexOf_II(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    /* null reference check on "this" */
+    if (!dvmValidateObject((Object*) arg0))
+        return false;
+
+    pResult->i = indexOfCommon((Object*) arg0, arg1, arg2);
     return true;
 }
 
@@ -550,8 +633,11 @@
  * pointer field.
  *
  * IMPORTANT: you must update DALVIK_VM_BUILD in DalvikVersion.h if you make
- * changes to this table.  Must also be kept in sync with NativeInlineOps
- * enum in InlineNative.h.
+ * changes to this table.
+ *
+ * NOTE: If present, the JIT will also need to know about changes
+ * to this table.  Update the NativeInlineOps enum in InlineNative.h and
+ * the dispatch code in compiler/codegen/<target>/Codegen.c.
  */
 const InlineOperation gDvmInlineOpsTable[] = {
     { org_apache_harmony_dalvik_NativeTestTarget_emptyInlineMethod,
@@ -564,6 +650,10 @@
         "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I" },
     { javaLangString_equals,
         "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z" },
+    { javaLangString_indexOf_I,
+        "Ljava/lang/String;", "indexOf", "(I)I" },
+    { javaLangString_indexOf_II,
+        "Ljava/lang/String;", "indexOf", "(II)I" },
     { javaLangString_length,
         "Ljava/lang/String;", "length", "()I" },
 
@@ -587,7 +677,6 @@
         "Ljava/lang/Math;", "sin", "(D)D" },
 };
 
-
 /*
  * Allocate some tables.
  */
diff --git a/vm/InlineNative.h b/vm/InlineNative.h
index 98398da..300c94c 100644
--- a/vm/InlineNative.h
+++ b/vm/InlineNative.h
@@ -54,16 +54,18 @@
     INLINE_STRING_CHARAT = 1,
     INLINE_STRING_COMPARETO = 2,
     INLINE_STRING_EQUALS = 3,
-    INLINE_STRING_LENGTH = 4,
-    INLINE_MATH_ABS_INT = 5,
-    INLINE_MATH_ABS_LONG = 6,
-    INLINE_MATH_ABS_FLOAT = 7,
-    INLINE_MATH_ABS_DOUBLE = 8,
-    INLINE_MATH_MIN_INT = 9,
-    INLINE_MATH_MAX_INT = 10,
-    INLINE_MATH_SQRT = 11,
-    INLINE_MATH_COS = 12,
-    INLINE_MATH_SIN = 13,
+    INLINE_STRING_INDEXOF_I = 4,
+    INLINE_STRING_INDEXOF_II = 5,
+    INLINE_STRING_LENGTH = 6,
+    INLINE_MATH_ABS_INT = 7,
+    INLINE_MATH_ABS_LONG = 8,
+    INLINE_MATH_ABS_FLOAT = 9,
+    INLINE_MATH_ABS_DOUBLE = 10,
+    INLINE_MATH_MIN_INT = 11,
+    INLINE_MATH_MAX_INT = 12,
+    INLINE_MATH_SQRT = 13,
+    INLINE_MATH_COS = 14,
+    INLINE_MATH_SIN = 15,
 } NativeInlineOps;
 
 /*
diff --git a/vm/Jni.c b/vm/Jni.c
index 10afcaa..d7d1122 100644
--- a/vm/Jni.c
+++ b/vm/Jni.c
@@ -3102,7 +3102,7 @@
     JNI_ENTER();
 
     ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
-    jint retval;
+    jint retval = JNI_OK;
     int i;
 
     if (gDvm.verboseJni) {
@@ -3115,12 +3115,9 @@
                 methods[i].signature, methods[i].fnPtr))
         {
             retval = JNI_ERR;
-            goto bail;
         }
     }
-    retval = JNI_OK;
 
-bail:
     JNI_EXIT();
     return retval;
 }
@@ -4218,4 +4215,3 @@
     free(argv);
     return result;
 }
-
diff --git a/vm/Misc.c b/vm/Misc.c
index f8f7256..193e0bd 100644
--- a/vm/Misc.c
+++ b/vm/Misc.c
@@ -345,6 +345,39 @@
 }
 
 /*
+ * Copy a whole vector to the other. Only do that when the both vectors have
+ * the same size and attribute.
+ */
+bool dvmCopyBitVector(BitVector *dest, const BitVector *src)
+{
+    if (dest->storageSize != src->storageSize ||
+        dest->expandable != src->expandable)
+        return false;
+    memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
+    return true;
+}
+
+/*
+ * Intersect two bit vectores and merge the result on top of the pre-existing
+ * value in the dest vector.
+ */
+bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
+                            const BitVector *src2)
+{
+    if (dest->storageSize != src1->storageSize ||
+        dest->storageSize != src2->storageSize ||
+        dest->expandable != src1->expandable ||
+        dest->expandable != src2->expandable)
+        return false;
+
+    int i;
+    for (i = 0; i < dest->storageSize; i++) {
+        dest->storage[i] |= src1->storage[i] & src2->storage[i];
+    }
+    return true;
+}
+
+/*
  * Return a newly-allocated string in which all occurrences of '.' have
  * been changed to '/'.  If we find a '/' in the original string, NULL
  * is returned to avoid ambiguity.
@@ -354,6 +387,9 @@
     char* newStr = strdup(str);
     char* cp = newStr;
 
+    if (newStr == NULL)
+        return NULL;
+
     while (*cp != '\0') {
         if (*cp == '/') {
             assert(false);
@@ -384,6 +420,9 @@
     }
 
     newStr = malloc(at + 1); /* Add one for the '\0'. */
+    if (newStr == NULL)
+        return NULL;
+
     newStr[at] = '\0';
 
     while (at > 0) {
diff --git a/vm/Misc.h b/vm/Misc.h
index 14635a3..3e04f84 100644
--- a/vm/Misc.h
+++ b/vm/Misc.h
@@ -164,6 +164,16 @@
 /* count the number of bits that have been set */
 int dvmCountSetBits(const BitVector* pBits);
 
+/* copy one vector to the other compatible one */
+bool dvmCopyBitVector(BitVector *dest, const BitVector *src);
+
+/*
+ * Intersect two bit vectores and merge the result on top of the pre-existing
+ * value in the dest vector.
+ */
+bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
+                            const BitVector *src2);
+
 #define kBitVectorGrowth    4   /* increase by 4 u4s when limit hit */
 
 
diff --git a/vm/Sync.c b/vm/Sync.c
index 1f81349..8528c0f 100644
--- a/vm/Sync.c
+++ b/vm/Sync.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Fundamental synchronization mechanisms.
  *
@@ -985,8 +986,10 @@
         LOG_THIN("(%d) lock 0x%08x fattened by wait() to count %d\n",
                  self->threadId, (uint)&obj->lock, mon->lockCount);
 
+
         /* Make the monitor public now that it's in the right state.
          */
+        MEM_BARRIER();
         obj->lock.mon = mon;
     }
 
diff --git a/vm/Thread.c b/vm/Thread.c
index be3e952..7ca3dc7 100644
--- a/vm/Thread.c
+++ b/vm/Thread.c
@@ -36,6 +36,11 @@
 #include <sys/prctl.h>
 #endif
 
+#if defined(WITH_SELF_VERIFICATION)
+#include "interp/Jit.h"         // need for self verification
+#endif
+
+
 /* desktop Linux needs a little help with gettid() */
 #if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS)
 #define __KERNEL__
@@ -895,6 +900,11 @@
     if (thread == NULL)
         return NULL;
 
+#if defined(WITH_SELF_VERIFICATION)
+    if (dvmSelfVerificationShadowSpaceAlloc(thread) == NULL)
+        return NULL;
+#endif
+
     assert(interpStackSize >= kMinStackSize && interpStackSize <=kMaxStackSize);
 
     thread->status = THREAD_INITIALIZING;
@@ -914,6 +924,9 @@
 #ifdef MALLOC_INTERP_STACK
     stackBottom = (u1*) malloc(interpStackSize);
     if (stackBottom == NULL) {
+#if defined(WITH_SELF_VERIFICATION)
+        dvmSelfVerificationShadowSpaceFree(thread);
+#endif
         free(thread);
         return NULL;
     }
@@ -922,6 +935,9 @@
     stackBottom = mmap(NULL, interpStackSize, PROT_READ | PROT_WRITE,
         MAP_PRIVATE | MAP_ANON, -1, 0);
     if (stackBottom == MAP_FAILED) {
+#if defined(WITH_SELF_VERIFICATION)
+        dvmSelfVerificationShadowSpaceFree(thread);
+#endif
         free(thread);
         return NULL;
     }
@@ -1061,6 +1077,9 @@
     if (&thread->jniMonitorRefTable.table != NULL)
         dvmClearReferenceTable(&thread->jniMonitorRefTable);
 
+#if defined(WITH_SELF_VERIFICATION)
+    dvmSelfVerificationShadowSpaceFree(thread);
+#endif
     free(thread);
 }
 
diff --git a/vm/Thread.h b/vm/Thread.h
index 1bb5314..179a920 100644
--- a/vm/Thread.h
+++ b/vm/Thread.h
@@ -220,6 +220,11 @@
     const u2*   currentPc2;
 #endif
 
+#if defined(WITH_SELF_VERIFICATION)
+    /* Buffer for register state during self verification */
+    struct ShadowSpace* shadowSpace;
+#endif
+
     /* system thread state */
     SystemThread* systemThread;
 } Thread;
diff --git a/vm/UtfString.c b/vm/UtfString.c
index dfb76bc..8e20a0f 100644
--- a/vm/UtfString.c
+++ b/vm/UtfString.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * UTF-8 and Unicode string manipulation, plus java/lang/String convenience
  * functions.
@@ -69,6 +70,30 @@
         return false;
     }
 
+    bool badValue = false;
+    if (gDvm.offJavaLangString_value != STRING_FIELDOFF_VALUE) {
+        LOGE("InlineNative: String.value offset = %d, expected %d\n",
+            gDvm.offJavaLangString_value, STRING_FIELDOFF_VALUE);
+        badValue = true;
+    }
+    if (gDvm.offJavaLangString_count != STRING_FIELDOFF_COUNT) {
+        LOGE("InlineNative: String.count offset = %d, expected %d\n",
+            gDvm.offJavaLangString_count, STRING_FIELDOFF_COUNT);
+        badValue = true;
+    }
+    if (gDvm.offJavaLangString_offset != STRING_FIELDOFF_OFFSET) {
+        LOGE("InlineNative: String.offset offset = %d, expected %d\n",
+            gDvm.offJavaLangString_offset, STRING_FIELDOFF_OFFSET);
+        badValue = true;
+    }
+    if (gDvm.offJavaLangString_hashCode != STRING_FIELDOFF_HASHCODE) {
+        LOGE("InlineNative: String.hashCode offset = %d, expected %d\n",
+            gDvm.offJavaLangString_hashCode, STRING_FIELDOFF_HASHCODE);
+        badValue = true;
+    }
+    if (badValue)
+        return false;
+
     gDvm.javaLangStringReady = 1;
 
     return true;
@@ -213,11 +238,11 @@
 }
 u4 dvmComputeStringHash(StringObject* strObj) {
     ArrayObject* chars = (ArrayObject*) dvmGetFieldObject((Object*) strObj,
-                                gDvm.offJavaLangString_value);
+                                STRING_FIELDOFF_VALUE);
     int offset, len;
 
-    len = dvmGetFieldInt((Object*) strObj, gDvm.offJavaLangString_count);
-    offset = dvmGetFieldInt((Object*) strObj, gDvm.offJavaLangString_offset);
+    len = dvmGetFieldInt((Object*) strObj, STRING_FIELDOFF_COUNT);
+    offset = dvmGetFieldInt((Object*) strObj, STRING_FIELDOFF_OFFSET);
 
     return dvmComputeUtf16Hash((u2*) chars->contents + offset, len);
 }
@@ -285,11 +310,11 @@
     dvmConvertUtf8ToUtf16((u2*)chars->contents, utf8Str);
     hashCode = dvmComputeUtf16Hash((u2*) chars->contents, utf16Length);
 
-    dvmSetFieldObject((Object*)newObj, gDvm.offJavaLangString_value,
+    dvmSetFieldObject((Object*)newObj, STRING_FIELDOFF_VALUE,
         (Object*)chars);
     dvmReleaseTrackedAllocIFN((Object*) chars, NULL, allocFlags);
-    dvmSetFieldInt((Object*)newObj, gDvm.offJavaLangString_count, utf16Length);
-    dvmSetFieldInt((Object*)newObj, gDvm.offJavaLangString_hashCode, hashCode);
+    dvmSetFieldInt((Object*)newObj, STRING_FIELDOFF_COUNT, utf16Length);
+    dvmSetFieldInt((Object*)newObj, STRING_FIELDOFF_HASHCODE, hashCode);
     /* leave offset set to zero */
 
     /* debugging stuff */
@@ -339,11 +364,11 @@
         memcpy(chars->contents, unichars, len * sizeof(u2));
     hashCode = dvmComputeUtf16Hash((u2*) chars->contents, len);
 
-    dvmSetFieldObject((Object*)newObj, gDvm.offJavaLangString_value,
+    dvmSetFieldObject((Object*)newObj, STRING_FIELDOFF_VALUE,
         (Object*)chars);
     dvmReleaseTrackedAlloc((Object*) chars, NULL);
-    dvmSetFieldInt((Object*)newObj, gDvm.offJavaLangString_count, len);
-    dvmSetFieldInt((Object*)newObj, gDvm.offJavaLangString_hashCode, hashCode);
+    dvmSetFieldInt((Object*)newObj, STRING_FIELDOFF_COUNT, len);
+    dvmSetFieldInt((Object*)newObj, STRING_FIELDOFF_HASHCODE, hashCode);
     /* leave offset set to zero */
 
     /* debugging stuff */
@@ -371,10 +396,10 @@
     if (jstr == NULL)
         return NULL;
 
-    len = dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_count);
-    offset = dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_offset);
+    len = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_COUNT);
+    offset = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_OFFSET);
     chars = (ArrayObject*) dvmGetFieldObject((Object*) jstr,
-                                gDvm.offJavaLangString_value);
+                                STRING_FIELDOFF_VALUE);
     data = (const u2*) chars->contents + offset;
     assert(offset + len <= (int) chars->length);
 
@@ -416,10 +441,10 @@
     if (jstr == NULL)
         return 0;       // should we throw something?  assert?
 
-    len = dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_count);
-    offset = dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_offset);
+    len = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_COUNT);
+    offset = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_OFFSET);
     chars = (ArrayObject*) dvmGetFieldObject((Object*) jstr,
-                                gDvm.offJavaLangString_value);
+                                STRING_FIELDOFF_VALUE);
     data = (const u2*) chars->contents + offset;
     assert(offset + len <= (int) chars->length);
 
@@ -431,7 +456,7 @@
  */
 int dvmStringLen(StringObject* jstr)
 {
-    return dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_count);
+    return dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_COUNT);
 }
 
 /*
@@ -440,7 +465,7 @@
 ArrayObject* dvmStringCharArray(StringObject* jstr)
 {
     return (ArrayObject*) dvmGetFieldObject((Object*) jstr,
-                                gDvm.offJavaLangString_value);
+                                STRING_FIELDOFF_VALUE);
 }
 
 /*
@@ -451,9 +476,9 @@
     ArrayObject* chars;
     int offset;
 
-    offset = dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_offset);
+    offset = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_OFFSET);
     chars = (ArrayObject*) dvmGetFieldObject((Object*) jstr,
-                                gDvm.offJavaLangString_value);
+                                STRING_FIELDOFF_VALUE);
     return (const u2*) chars->contents + offset;
 }
 
@@ -476,17 +501,17 @@
     assert(gDvm.javaLangStringReady > 0);
 
     /* get offset and length into char array; all values are in 16-bit units */
-    len1 = dvmGetFieldInt((Object*) strObj1, gDvm.offJavaLangString_count);
-    offset1 = dvmGetFieldInt((Object*) strObj1, gDvm.offJavaLangString_offset);
-    len2 = dvmGetFieldInt((Object*) strObj2, gDvm.offJavaLangString_count);
-    offset2 = dvmGetFieldInt((Object*) strObj2, gDvm.offJavaLangString_offset);
+    len1 = dvmGetFieldInt((Object*) strObj1, STRING_FIELDOFF_COUNT);
+    offset1 = dvmGetFieldInt((Object*) strObj1, STRING_FIELDOFF_OFFSET);
+    len2 = dvmGetFieldInt((Object*) strObj2, STRING_FIELDOFF_COUNT);
+    offset2 = dvmGetFieldInt((Object*) strObj2, STRING_FIELDOFF_OFFSET);
     if (len1 != len2)
         return len1 - len2;
 
     chars1 = (ArrayObject*) dvmGetFieldObject((Object*) strObj1,
-                                gDvm.offJavaLangString_value);
+                                STRING_FIELDOFF_VALUE);
     chars2 = (ArrayObject*) dvmGetFieldObject((Object*) strObj2,
-                                gDvm.offJavaLangString_value);
+                                STRING_FIELDOFF_VALUE);
 
     /* damage here actually indicates a broken java/lang/String */
     assert(offset1 + len1 <= (int) chars1->length);
diff --git a/vm/UtfString.h b/vm/UtfString.h
index ca500a7..8f0f972 100644
--- a/vm/UtfString.h
+++ b/vm/UtfString.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * UTF-8 and Unicode string manipulation functions, plus convenience
  * functions for working with java/lang/String.
@@ -21,6 +22,30 @@
 #define _DALVIK_STRING
 
 /*
+ * (This is private to UtfString.c, but we cheat a bit and also use it
+ * for InlineNative.c.  Not really worth creating a separate header.)
+ *
+ * We can avoid poking around in gDvm by hard-coding the expected values of
+ * the String field offsets.  This will be annoying if String is in flux
+ * or the VM field layout is changing, so we use defines here to make it
+ * easy to switch back to the gDvm version.
+ *
+ * The values are checked for correctness during startup.
+ */
+//#define USE_GLOBAL_STRING_DEFS
+#ifdef USE_GLOBAL_STRING_DEFS
+# define STRING_FIELDOFF_VALUE      gDvm.offJavaLangString_value
+# define STRING_FIELDOFF_OFFSET     gDvm.offJavaLangString_offset
+# define STRING_FIELDOFF_COUNT      gDvm.offJavaLangString_count
+# define STRING_FIELDOFF_HASHCODE   gDvm.offJavaLangString_hashCode
+#else
+# define STRING_FIELDOFF_VALUE      8
+# define STRING_FIELDOFF_HASHCODE   12
+# define STRING_FIELDOFF_OFFSET     16
+# define STRING_FIELDOFF_COUNT      20
+#endif
+
+/*
  * Hash function for modified UTF-8 strings.
  */
 u4 dvmComputeUtf8Hash(const char* str);
diff --git a/vm/alloc/Heap.c b/vm/alloc/Heap.c
index 17d6a5c..33efa85 100644
--- a/vm/alloc/Heap.c
+++ b/vm/alloc/Heap.c
@@ -573,10 +573,6 @@
             }
         }
 
-#if WITH_OBJECT_HEADERS
-        hc->header = OBJECT_HEADER;
-        hc->birthGeneration = gGeneration;
-#endif
         ptr = hc->data;
 
         /* The caller may not want us to collect this object.
diff --git a/vm/alloc/HeapInternal.h b/vm/alloc/HeapInternal.h
index fafb87a..a2d31fe 100644
--- a/vm/alloc/HeapInternal.h
+++ b/vm/alloc/HeapInternal.h
@@ -29,27 +29,7 @@
 #define ptr2chunk(p)    (((DvmHeapChunk *)(p)) - 1)
 #define chunk2ptr(p)    ((void *)(((DvmHeapChunk *)(p)) + 1))
 
-#define WITH_OBJECT_HEADERS 0
-#if WITH_OBJECT_HEADERS
-#define OBJECT_HEADER   0x11335577
-extern u2 gGeneration;
-#endif
-
 typedef struct DvmHeapChunk {
-#if WITH_OBJECT_HEADERS
-    u4 header;
-    const Object *parent;
-    const Object *parentOld;
-    const Object *markFinger;
-    const Object *markFingerOld;
-    u2 birthGeneration;
-    u2 markCount;
-    u2 scanCount;
-    u2 oldMarkGeneration;
-    u2 markGeneration;
-    u2 oldScanGeneration;
-    u2 scanGeneration;
-#endif
 #if WITH_HPROF && WITH_HPROF_STACK
     u4 stackTraceSerialNumber;
 #endif
diff --git a/vm/alloc/MarkSweep.c b/vm/alloc/MarkSweep.c
index 09cc25f..4bb917b 100644
--- a/vm/alloc/MarkSweep.c
+++ b/vm/alloc/MarkSweep.c
@@ -68,11 +68,6 @@
 #define LOGV_SWEEP(...) LOGVV_GC("SWEEP: " __VA_ARGS__)
 #define LOGV_REF(...)   LOGVV_GC("REF: " __VA_ARGS__)
 
-#if WITH_OBJECT_HEADERS
-u2 gGeneration = 0;
-static const Object *gMarkParent = NULL;
-#endif
-
 #ifndef PAGE_SIZE
 #define PAGE_SIZE 4096
 #endif
@@ -170,10 +165,6 @@
     mc->numBitmaps = numBitmaps;
     mc->finger = NULL;
 
-#if WITH_OBJECT_HEADERS
-    gGeneration++;
-#endif
-
     return true;
 }
 
@@ -213,28 +204,6 @@
             MARK_STACK_PUSH(ctx->stack, obj);
         }
 
-#if WITH_OBJECT_HEADERS
-        if (hc->scanGeneration != hc->markGeneration) {
-            LOGE("markObject(0x%08x): wasn't scanned last time\n", (uint)obj);
-            dvmAbort();
-        }
-        if (hc->markGeneration == gGeneration) {
-            LOGE("markObject(0x%08x): already marked this generation\n",
-                    (uint)obj);
-            dvmAbort();
-        }
-        hc->oldMarkGeneration = hc->markGeneration;
-        hc->markGeneration = gGeneration;
-        hc->markFingerOld = hc->markFinger;
-        hc->markFinger = ctx->finger;
-        if (gMarkParent != NULL) {
-            hc->parentOld = hc->parent;
-            hc->parent = gMarkParent;
-        } else {
-            hc->parent = (const Object *)((uintptr_t)hc->parent | 1);
-        }
-        hc->markCount++;
-#endif
 #if WITH_HPROF
         if (gDvm.gcHeap->hprofContext != NULL) {
             hprofMarkRootObject(gDvm.gcHeap->hprofContext, obj, 0);
@@ -535,17 +504,6 @@
     }
 #endif
 
-#if WITH_OBJECT_HEADERS
-    if (ptr2chunk(obj)->scanGeneration == gGeneration) {
-        LOGE("object 0x%08x was already scanned this generation\n",
-                (uintptr_t)obj);
-        dvmAbort();
-    }
-    ptr2chunk(obj)->oldScanGeneration = ptr2chunk(obj)->scanGeneration;
-    ptr2chunk(obj)->scanGeneration = gGeneration;
-    ptr2chunk(obj)->scanCount++;
-#endif
-
     /* Get and mark the class object for this particular instance.
      */
     clazz = obj->clazz;
@@ -567,10 +525,6 @@
         return;
     }
 
-#if WITH_OBJECT_HEADERS
-    gMarkParent = obj;
-#endif
-
     assert(dvmIsValidObject((Object *)clazz));
     markObjectNonNull((Object *)clazz, ctx);
 
@@ -720,10 +674,6 @@
             scanClassObject((ClassObject *)obj, ctx);
         }
     }
-
-#if WITH_OBJECT_HEADERS
-    gMarkParent = NULL;
-#endif
 }
 
 static void
@@ -1225,13 +1175,6 @@
         hc = (DvmHeapChunk *)*ptrs++;
         obj = (Object *)chunk2ptr(hc);
 
-#if WITH_OBJECT_HEADERS
-        if (hc->markGeneration == gGeneration) {
-            LOGE("sweeping marked object: 0x%08x\n", (uint)obj);
-            dvmAbort();
-        }
-#endif
-
         /* Free the monitor associated with the object.
          */
         dvmFreeObjectMonitor(obj);
@@ -1264,16 +1207,9 @@
         {
             int chunklen;
             ClassObject *clazz = obj->clazz;
-#if WITH_OBJECT_HEADERS
-            DvmHeapChunk chunk = *hc;
-            chunk.header = ~OBJECT_HEADER | 1;
-#endif
             chunklen = dvmHeapSourceChunkSize(hc);
             memset(hc, 0xa5, chunklen);
             obj->clazz = (ClassObject *)((uintptr_t)clazz ^ 0xffffffff);
-#if WITH_OBJECT_HEADERS
-            *hc = chunk;
-#endif
         }
 #endif
     }
diff --git a/vm/analysis/RegisterMap.c b/vm/analysis/RegisterMap.c
index 0e3445a..d1f2600 100644
--- a/vm/analysis/RegisterMap.c
+++ b/vm/analysis/RegisterMap.c
@@ -1036,6 +1036,7 @@
     default:
         LOGE("Unknown format %d in dvmGetExpandedRegisterMap\n", format);
         dvmAbort();
+        newMap = NULL;      // make gcc happy
     }
 
     if (newMap == NULL) {
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 203a080..9db641e 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -21,7 +21,6 @@
 #include "interp/Jit.h"
 #include "CompilerInternals.h"
 
-
 static inline bool workQueueLength(void)
 {
     return gDvmJit.compilerQueueLength;
@@ -101,13 +100,14 @@
 
 static void *compilerThreadStart(void *arg)
 {
+    dvmChangeStatus(NULL, THREAD_VMWAIT);
+
     dvmLockMutex(&gDvmJit.compilerLock);
     /*
      * Since the compiler thread will not touch any objects on the heap once
      * being created, we just fake its state as VMWAIT so that it can be a
      * bit late when there is suspend request pending.
      */
-    dvmChangeStatus(NULL, THREAD_VMWAIT);
     while (!gDvmJit.haltCompilerThread) {
         if (workQueueLength() == 0) {
             int cc;
@@ -144,6 +144,13 @@
     pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
     dvmUnlockMutex(&gDvmJit.compilerLock);
 
+    /*
+     * As part of detaching the thread we need to call into Java code to update
+     * the ThreadGroup, and we should not be in VMWAIT state while executing
+     * interpreted code.
+     */
+    dvmChangeStatus(NULL, THREAD_RUNNING);
+
     LOGD("Compiler thread shutting down\n");
     return NULL;
 }
@@ -156,7 +163,7 @@
     /* Allocate the code cache */
     gDvmJit.codeCache = mmap(0, CODE_CACHE_SIZE,
                           PROT_READ | PROT_WRITE | PROT_EXEC,
-                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+                          MAP_PRIVATE | MAP_ANON, -1, 0);
     if (gDvmJit.codeCache == MAP_FAILED) {
         LOGE("Failed to create the code cache: %s\n", strerror(errno));
         return false;
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
index 3b7ae54..47de33d 100644
--- a/vm/compiler/Compiler.h
+++ b/vm/compiler/Compiler.h
@@ -62,8 +62,23 @@
     kJitTSelectEnd = 5,        // Done with the trace - wrap it up
     kJitSingleStep = 6,        // Single step interpretation
     kJitSingleStepEnd = 7,     // Done with single step, return to mterp
+    kJitSelfVerification = 8,  // Self Verification Mode
 } JitState;
 
+#if defined(WITH_SELF_VERIFICATION)
+typedef enum SelfVerificationState {
+    kSVSIdle = 0,           // Idle
+    kSVSStart = 1,          // Shadow space set up, running compiled code
+    kSVSPunt = 2,           // Exiting compiled code by punting
+    kSVSSingleStep = 3,     // Exiting compiled code by single stepping
+    kSVSTraceSelect = 4,    // Exiting compiled code by trace select
+    kSVSNormal = 5,         // Exiting compiled code normally
+    kSVSNoChain = 6,        // Exiting compiled code by no chain
+    kSVSBackwardBranch = 7, // Exiting compiled code with backward branch trace
+    kSVSDebugInterp = 8,    // Normal state restored, running debug interpreter
+} SelfVerificationState;
+#endif
+
 typedef enum JitHint {
    kJitHintNone = 0,
    kJitHintTaken = 1,         // Last inst in run was taken branch
@@ -122,4 +137,26 @@
 void dvmJitUnchainAll(void);
 void dvmCompilerSortAndPrintTraceProfiles(void);
 
+struct CompilationUnit;
+struct BasicBlock;
+struct SSARepresentation;
+struct GrowableList;
+
+void dvmInitializeSSAConversion(struct CompilationUnit *cUnit);
+int dvmConvertSSARegToDalvik(struct CompilationUnit *cUnit, int ssaReg);
+void dvmCompilerLoopOpt(struct CompilationUnit *cUnit);
+void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit);
+void dvmCompilerFindLiveIn(struct CompilationUnit *cUnit,
+                           struct BasicBlock *bb);
+void dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit,
+                                struct BasicBlock *bb);
+void dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit,
+                                      struct BasicBlock *bb);
+void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
+                                       struct BasicBlock *bb);
+char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
+                              struct SSARepresentation *ssaRep);
+void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
+                void (*func)(struct CompilationUnit *, struct BasicBlock *));
+
 #endif /* _DALVIK_VM_COMPILER */
diff --git a/vm/compiler/CompilerIR.h b/vm/compiler/CompilerIR.h
index d61d2ee..d5f60b6 100644
--- a/vm/compiler/CompilerIR.h
+++ b/vm/compiler/CompilerIR.h
@@ -14,19 +14,22 @@
  * limitations under the License.
  */
 
-#include "codegen/Optimizer.h"
-
 #ifndef _DALVIK_VM_COMPILER_IR
 #define _DALVIK_VM_COMPILER_IR
 
+#include "codegen/Optimizer.h"
+
 typedef enum BBType {
     /* For coding convenience reasons chaining cell types should appear first */
     CHAINING_CELL_NORMAL = 0,
     CHAINING_CELL_HOT,
     CHAINING_CELL_INVOKE_SINGLETON,
     CHAINING_CELL_INVOKE_PREDICTED,
+    CHAINING_CELL_BACKWARD_BRANCH,
     CHAINING_CELL_LAST,
+    ENTRY_BLOCK,
     DALVIK_BYTECODE,
+    EXIT_BLOCK,
     PC_RECONSTRUCTION,
     EXCEPTION_HANDLING,
 } BBType;
@@ -45,14 +48,42 @@
     struct LIR *target;
 } LIR;
 
+enum ExtendedMIROpcode {
+    MIR_OP_FIRST = 256,
+    MIR_OP_PHI = MIR_OP_FIRST,
+    MIR_OP_NULL_N_RANGE_UP_CHECK,
+    MIR_OP_NULL_N_RANGE_DOWN_CHECK,
+    MIR_OP_LOWER_BOUND_CHECK,
+    MIR_OP_PUNT,
+    MIR_OP_LAST,
+};
+
+struct SSARepresentation;
+
+typedef enum {
+    kMIRIgnoreNullCheck = 0,
+    kMIRNullCheckOnly,
+    kMIRIgnoreRangeCheck,
+    kMIRRangeCheckOnly,
+} MIROptimizationFlagPositons;
+
+#define MIR_IGNORE_NULL_CHECK           (1 << kMIRIgnoreNullCheck)
+#define MIR_NULL_CHECK_ONLY             (1 << kMIRNullCheckOnly)
+#define MIR_IGNORE_RANGE_CHECK          (1 << kMIRIgnoreRangeCheck)
+#define MIR_RANGE_CHECK_ONLY            (1 << kMIRRangeCheckOnly)
+
 typedef struct MIR {
     DecodedInstruction dalvikInsn;
     unsigned int width;
     unsigned int offset;
     struct MIR *prev;
     struct MIR *next;
+    struct SSARepresentation *ssaRep;
+    int OptimizationFlags;
 } MIR;
 
+struct BasicBlockDataFlow;
+
 typedef struct BasicBlock {
     int id;
     int visited;
@@ -65,8 +96,11 @@
     struct BasicBlock *fallThrough;
     struct BasicBlock *taken;
     struct BasicBlock *next;            // Serial link for book keeping purposes
+    struct BasicBlockDataFlow *dataFlowInfo;
 } BasicBlock;
 
+struct LoopAnalysis;
+
 typedef struct CompilationUnit {
     int numInsts;
     int numBlocks;
@@ -87,21 +121,39 @@
     bool allSingleStep;
     bool halveInstCount;
     bool executionCount;                // Add code to count trace executions
+    bool hasLoop;
     int numChainingCells[CHAINING_CELL_LAST];
     LIR *firstChainingLIR[CHAINING_CELL_LAST];
     RegisterScoreboard registerScoreboard;      // Track register dependency
     int optRound;                       // round number to tell an LIR's age
     JitInstructionSetType instructionSet;
+    /* Number of total regs used in the whole cUnit after SSA transformation */
+    int numSSARegs;
+    /* Map SSA reg i to the Dalvik[15..0]/Sub[31..16] pair. */
+    GrowableList *ssaToDalvikMap;
+
+    /* The following are new data structures to support SSA representations */
+    /* Map original Dalvik reg i to the SSA[15..0]/Sub[31..16] pair */
+    int *dalvikToSSAMap;                // length == method->registersSize
+    BitVector *isConstantV;             // length == numSSAReg
+    int *constantValues;                // length == numSSAReg
+
+    /* Data structure for loop analysis and optimizations */
+    struct LoopAnalysis *loopAnalysis;
 } CompilationUnit;
 
 BasicBlock *dvmCompilerNewBB(BBType blockType);
 
 void dvmCompilerAppendMIR(BasicBlock *bb, MIR *mir);
 
+void dvmCompilerPrependMIR(BasicBlock *bb, MIR *mir);
+
 void dvmCompilerAppendLIR(CompilationUnit *cUnit, LIR *lir);
 
 void dvmCompilerInsertLIRBefore(LIR *currentLIR, LIR *newLIR);
 
+void dvmCompilerInsertLIRAfter(LIR *currentLIR, LIR *newLIR);
+
 /* Debug Utilities */
 void dvmCompilerDumpCompilationUnit(CompilationUnit *cUnit);
 
diff --git a/vm/compiler/CompilerInternals.h b/vm/compiler/CompilerInternals.h
index 410213a..9a30b34 100644
--- a/vm/compiler/CompilerInternals.h
+++ b/vm/compiler/CompilerInternals.h
@@ -19,7 +19,6 @@
 
 #include "Dalvik.h"
 #include "CompilerUtility.h"
-#include "CompilerIR.h"
 #include "codegen/CompilerCodegen.h"
 #include "interp/Jit.h"
 
diff --git a/vm/compiler/CompilerUtility.h b/vm/compiler/CompilerUtility.h
index 7b4de11..409de29 100644
--- a/vm/compiler/CompilerUtility.h
+++ b/vm/compiler/CompilerUtility.h
@@ -38,7 +38,16 @@
     void **elemList;
 } GrowableList;
 
+#define GET_ELEM_N(LIST, TYPE, N) (((TYPE*) LIST->elemList)[N])
+
+struct LIR;
+
 void dvmInitGrowableList(GrowableList *gList, size_t initLength);
 void dvmInsertGrowableList(GrowableList *gList, void *elem);
+BitVector* dvmCompilerAllocBitVector(int startBits, bool expandable);
+bool dvmCompilerSetBit(BitVector* pBits, int num);
+void dvmDebugBitVector(char *msg, const BitVector *bv, int length);
+void dvmDumpLIRInsn(struct LIR *lir, unsigned char *baseAddr);
+void dvmDumpResourceMask(struct LIR *lir, u8 mask, const char *prefix);
 
 #endif /* _DALVIK_COMPILER_UTILITY */
diff --git a/vm/compiler/Dataflow.c b/vm/compiler/Dataflow.c
new file mode 100644
index 0000000..9a2e5c0
--- /dev/null
+++ b/vm/compiler/Dataflow.c
@@ -0,0 +1,1394 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Dalvik.h"
+#include "Dataflow.h"
+#include "Loop.h"
+
+/*
+ * Main table containing data flow attributes for each bytecode. The first
+ * 256 entries are for Dalvik bytecode instructions, where extended opcode at
+ * the MIR level are appended afterwards.
+ *
+ * TODO - many optimization flags are incomplete - they will only limit the
+ * scope of optimizations but will not cause mis-optimizations.
+ */
+int dvmCompilerDataFlowAttributes[MIR_OP_LAST] = {
+    // 00 OP_NOP
+    DF_NOP,
+
+    // 01 OP_MOVE vA, vB
+    DF_DA | DF_UB | DF_IS_MOVE,
+
+    // 02 OP_MOVE_FROM16 vAA, vBBBB
+    DF_DA | DF_UB | DF_IS_MOVE,
+
+    // 03 OP_MOVE_16 vAAAA, vBBBB
+    DF_DA | DF_UB | DF_IS_MOVE,
+
+    // 04 OP_MOVE_WIDE vA, vB
+    DF_DA_WIDE | DF_UB_WIDE | DF_IS_MOVE,
+
+    // 05 OP_MOVE_WIDE_FROM16 vAA, vBBBB
+    DF_DA_WIDE | DF_UB_WIDE | DF_IS_MOVE,
+
+    // 06 OP_MOVE_WIDE_16 vAAAA, vBBBB
+    DF_DA_WIDE | DF_UB_WIDE | DF_IS_MOVE,
+
+    // 07 OP_MOVE_OBJECT vA, vB
+    DF_DA | DF_UB | DF_IS_MOVE,
+
+    // 08 OP_MOVE_OBJECT_FROM16 vAA, vBBBB
+    DF_DA | DF_UB | DF_IS_MOVE,
+
+    // 09 OP_MOVE_OBJECT_16 vAAAA, vBBBB
+    DF_DA | DF_UB | DF_IS_MOVE,
+
+    // 0A OP_MOVE_RESULT vAA
+    DF_DA,
+
+    // 0B OP_MOVE_RESULT_WIDE vAA
+    DF_DA_WIDE,
+
+    // 0C OP_MOVE_RESULT_OBJECT vAA
+    DF_DA,
+
+    // 0D OP_MOVE_EXCEPTION vAA
+    DF_DA,
+
+    // 0E OP_RETURN_VOID
+    DF_NOP,
+
+    // 0F OP_RETURN vAA
+    DF_UA,
+
+    // 10 OP_RETURN_WIDE vAA
+    DF_UA_WIDE,
+
+    // 11 OP_RETURN_OBJECT vAA
+    DF_UA,
+
+    // 12 OP_CONST_4 vA, #+B
+    DF_DA | DF_SETS_CONST,
+
+    // 13 OP_CONST_16 vAA, #+BBBB
+    DF_DA | DF_SETS_CONST,
+
+    // 14 OP_CONST vAA, #+BBBBBBBB
+    DF_DA | DF_SETS_CONST,
+
+    // 15 OP_CONST_HIGH16 VAA, #+BBBB0000
+    DF_DA | DF_SETS_CONST,
+
+    // 16 OP_CONST_WIDE_16 vAA, #+BBBB
+    DF_DA_WIDE | DF_SETS_CONST,
+
+    // 17 OP_CONST_WIDE_32 vAA, #+BBBBBBBB
+    DF_DA_WIDE | DF_SETS_CONST,
+
+    // 18 OP_CONST_WIDE vAA, #+BBBBBBBBBBBBBBBB
+    DF_DA_WIDE | DF_SETS_CONST,
+
+    // 19 OP_CONST_WIDE_HIGH16 vAA, #+BBBB000000000000
+    DF_DA_WIDE | DF_SETS_CONST,
+
+    // 1A OP_CONST_STRING vAA, string@BBBB
+    DF_DA,
+
+    // 1B OP_CONST_STRING_JUMBO vAA, string@BBBBBBBB
+    DF_DA,
+
+    // 1C OP_CONST_CLASS vAA, type@BBBB
+    DF_DA,
+
+    // 1D OP_MONITOR_ENTER vAA
+    DF_UA,
+
+    // 1E OP_MONITOR_EXIT vAA
+    DF_UA,
+
+    // 1F OP_CHECK_CAST vAA, type@BBBB
+    DF_UA,
+
+    // 20 OP_INSTANCE_OF vA, vB, type@CCCC
+    DF_DA | DF_UB,
+
+    // 21 OP_ARRAY_LENGTH vA, vB
+    DF_DA | DF_UB,
+
+    // 22 OP_NEW_INSTANCE vAA, type@BBBB
+    DF_DA,
+
+    // 23 OP_NEW_ARRAY vA, vB, type@CCCC
+    DF_DA | DF_UB,
+
+    // 24 OP_FILLED_NEW_ARRAY {vD, vE, vF, vG, vA}
+    DF_FORMAT_35C,
+
+    // 25 OP_FILLED_NEW_ARRAY_RANGE {vCCCC .. vNNNN}, type@BBBB
+    DF_FORMAT_3RC,
+
+    // 26 OP_FILL_ARRAY_DATA vAA, +BBBBBBBB
+    DF_UA,
+
+    // 27 OP_THROW vAA
+    DF_UA,
+
+    // 28 OP_GOTO
+    DF_NOP,
+
+    // 29 OP_GOTO_16
+    DF_NOP,
+
+    // 2A OP_GOTO_32
+    DF_NOP,
+
+    // 2B OP_PACKED_SWITCH vAA, +BBBBBBBB
+    DF_UA,
+
+    // 2C OP_SPARSE_SWITCH vAA, +BBBBBBBB
+    DF_UA,
+
+    // 2D OP_CMPL_FLOAT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 2E OP_CMPG_FLOAT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 2F OP_CMPL_DOUBLE vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // 30 OP_CMPG_DOUBLE vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // 31 OP_CMP_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // 32 OP_IF_EQ vA, vB, +CCCC
+    DF_UA | DF_UB,
+
+    // 33 OP_IF_NE vA, vB, +CCCC
+    DF_UA | DF_UB,
+
+    // 34 OP_IF_LT vA, vB, +CCCC
+    DF_UA | DF_UB,
+
+    // 35 OP_IF_GE vA, vB, +CCCC
+    DF_UA | DF_UB,
+
+    // 36 OP_IF_GT vA, vB, +CCCC
+    DF_UA | DF_UB,
+
+    // 37 OP_IF_LE vA, vB, +CCCC
+    DF_UA | DF_UB,
+
+
+    // 38 OP_IF_EQZ vAA, +BBBB
+    DF_UA,
+
+    // 39 OP_IF_NEZ vAA, +BBBB
+    DF_UA,
+
+    // 3A OP_IF_LTZ vAA, +BBBB
+    DF_UA,
+
+    // 3B OP_IF_GEZ vAA, +BBBB
+    DF_UA,
+
+    // 3C OP_IF_GTZ vAA, +BBBB
+    DF_UA,
+
+    // 3D OP_IF_LEZ vAA, +BBBB
+    DF_UA,
+
+    // 3E OP_UNUSED_3E
+    DF_NOP,
+
+    // 3F OP_UNUSED_3F
+    DF_NOP,
+
+    // 40 OP_UNUSED_40
+    DF_NOP,
+
+    // 41 OP_UNUSED_41
+    DF_NOP,
+
+    // 42 OP_UNUSED_42
+    DF_NOP,
+
+    // 43 OP_UNUSED_43
+    DF_NOP,
+
+    // 44 OP_AGET vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+    // 45 OP_AGET_WIDE vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+    // 46 OP_AGET_OBJECT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+    // 47 OP_AGET_BOOLEAN vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+    // 48 OP_AGET_BYTE vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+    // 49 OP_AGET_CHAR vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+    // 4A OP_AGET_SHORT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+    // 4B OP_APUT vAA, vBB, vCC
+    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+    // 4C OP_APUT_WIDE vAA, vBB, vCC
+    DF_UA_WIDE | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_2,
+
+    // 4D OP_APUT_OBJECT vAA, vBB, vCC
+    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+    // 4E OP_APUT_BOOLEAN vAA, vBB, vCC
+    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+    // 4F OP_APUT_BYTE vAA, vBB, vCC
+    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+    // 50 OP_APUT_CHAR vAA, vBB, vCC
+    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+    // 51 OP_APUT_SHORT vAA, vBB, vCC
+    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+    // 52 OP_IGET vA, vB, field@CCCC
+    DF_DA | DF_UB,
+
+    // 53 OP_IGET_WIDE vA, vB, field@CCCC
+    DF_DA_WIDE | DF_UB,
+
+    // 54 OP_IGET_OBJECT vA, vB, field@CCCC
+    DF_DA | DF_UB,
+
+    // 55 OP_IGET_BOOLEAN vA, vB, field@CCCC
+    DF_DA | DF_UB,
+
+    // 56 OP_IGET_BYTE vA, vB, field@CCCC
+    DF_DA | DF_UB,
+
+    // 57 OP_IGET_CHAR vA, vB, field@CCCC
+    DF_DA | DF_UB,
+
+    // 58 OP_IGET_SHORT vA, vB, field@CCCC
+    DF_DA | DF_UB,
+
+    // 59 OP_IPUT vA, vB, field@CCCC
+    DF_UA | DF_UB,
+
+    // 5A OP_IPUT_WIDE vA, vB, field@CCCC
+    DF_UA_WIDE | DF_UB,
+
+    // 5B OP_IPUT_OBJECT vA, vB, field@CCCC
+    DF_UA | DF_UB,
+
+    // 5C OP_IPUT_BOOLEAN vA, vB, field@CCCC
+    DF_UA | DF_UB,
+
+    // 5D OP_IPUT_BYTE vA, vB, field@CCCC
+    DF_UA | DF_UB,
+
+    // 5E OP_IPUT_CHAR vA, vB, field@CCCC
+    DF_UA | DF_UB,
+
+    // 5F OP_IPUT_SHORT vA, vB, field@CCCC
+    DF_UA | DF_UB,
+
+    // 60 OP_SGET vAA, field@BBBB
+    DF_DA,
+
+    // 61 OP_SGET_WIDE vAA, field@BBBB
+    DF_DA_WIDE,
+
+    // 62 OP_SGET_OBJECT vAA, field@BBBB
+    DF_DA,
+
+    // 63 OP_SGET_BOOLEAN vAA, field@BBBB
+    DF_DA,
+
+    // 64 OP_SGET_BYTE vAA, field@BBBB
+    DF_DA,
+
+    // 65 OP_SGET_CHAR vAA, field@BBBB
+    DF_DA,
+
+    // 66 OP_SGET_SHORT vAA, field@BBBB
+    DF_DA,
+
+    // 67 OP_SPUT vAA, field@BBBB
+    DF_UA,
+
+    // 68 OP_SPUT_WIDE vAA, field@BBBB
+    DF_UA_WIDE,
+
+    // 69 OP_SPUT_OBJECT vAA, field@BBBB
+    DF_UA,
+
+    // 6A OP_SPUT_BOOLEAN vAA, field@BBBB
+    DF_UA,
+
+    // 6B OP_SPUT_BYTE vAA, field@BBBB
+    DF_UA,
+
+    // 6C OP_SPUT_CHAR vAA, field@BBBB
+    DF_UA,
+
+    // 6D OP_SPUT_SHORT vAA, field@BBBB
+    DF_UA,
+
+    // 6E OP_INVOKE_VIRTUAL {vD, vE, vF, vG, vA}
+    DF_FORMAT_35C,
+
+    // 6F OP_INVOKE_SUPER {vD, vE, vF, vG, vA}
+    DF_FORMAT_35C,
+
+    // 70 OP_INVOKE_DIRECT {vD, vE, vF, vG, vA}
+    DF_FORMAT_35C,
+
+    // 71 OP_INVOKE_STATIC {vD, vE, vF, vG, vA}
+    DF_FORMAT_35C,
+
+    // 72 OP_INVOKE_INTERFACE {vD, vE, vF, vG, vA}
+    DF_FORMAT_35C,
+
+    // 73 OP_UNUSED_73
+    DF_NOP,
+
+    // 74 OP_INVOKE_VIRTUAL_RANGE {vCCCC .. vNNNN}
+    DF_FORMAT_3RC,
+
+    // 75 OP_INVOKE_SUPER_RANGE {vCCCC .. vNNNN}
+    DF_FORMAT_3RC,
+
+    // 76 OP_INVOKE_DIRECT_RANGE {vCCCC .. vNNNN}
+    DF_FORMAT_3RC,
+
+    // 77 OP_INVOKE_STATIC_RANGE {vCCCC .. vNNNN}
+    DF_FORMAT_3RC,
+
+    // 78 OP_INVOKE_INTERFACE_RANGE {vCCCC .. vNNNN}
+    DF_FORMAT_3RC,
+
+    // 79 OP_UNUSED_79
+    DF_NOP,
+
+    // 7A OP_UNUSED_7A
+    DF_NOP,
+
+    // 7B OP_NEG_INT vA, vB
+    DF_DA | DF_UB,
+
+    // 7C OP_NOT_INT vA, vB
+    DF_DA | DF_UB,
+
+    // 7D OP_NEG_LONG vA, vB
+    DF_DA_WIDE | DF_UB_WIDE,
+
+    // 7E OP_NOT_LONG vA, vB
+    DF_DA_WIDE | DF_UB_WIDE,
+
+    // 7F OP_NEG_FLOAT vA, vB
+    DF_DA | DF_UB,
+
+    // 80 OP_NEG_DOUBLE vA, vB
+    DF_DA_WIDE | DF_UB_WIDE,
+
+    // 81 OP_INT_TO_LONG vA, vB
+    DF_DA_WIDE | DF_UB,
+
+    // 82 OP_INT_TO_FLOAT vA, vB
+    DF_DA | DF_UB,
+
+    // 83 OP_INT_TO_DOUBLE vA, vB
+    DF_DA_WIDE | DF_UB,
+
+    // 84 OP_LONG_TO_INT vA, vB
+    DF_DA | DF_UB_WIDE,
+
+    // 85 OP_LONG_TO_FLOAT vA, vB
+    DF_DA | DF_UB_WIDE,
+
+    // 86 OP_LONG_TO_DOUBLE vA, vB
+    DF_DA_WIDE | DF_UB_WIDE,
+
+    // 87 OP_FLOAT_TO_INT vA, vB
+    DF_DA | DF_UB,
+
+    // 88 OP_FLOAT_TO_LONG vA, vB
+    DF_DA_WIDE | DF_UB,
+
+    // 89 OP_FLOAT_TO_DOUBLE vA, vB
+    DF_DA_WIDE | DF_UB,
+
+    // 8A OP_DOUBLE_TO_INT vA, vB
+    DF_DA | DF_UB_WIDE,
+
+    // 8B OP_DOUBLE_TO_LONG vA, vB
+    DF_DA_WIDE | DF_UB_WIDE,
+
+    // 8C OP_DOUBLE_TO_FLOAT vA, vB
+    DF_DA | DF_UB_WIDE,
+
+    // 8D OP_INT_TO_BYTE vA, vB
+    DF_DA | DF_UB,
+
+    // 8E OP_INT_TO_CHAR vA, vB
+    DF_DA | DF_UB,
+
+    // 8F OP_INT_TO_SHORT vA, vB
+    DF_DA | DF_UB,
+
+    // 90 OP_ADD_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC | DF_IS_LINEAR,
+
+    // 91 OP_SUB_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC | DF_IS_LINEAR,
+
+    // 92 OP_MUL_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 93 OP_DIV_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 94 OP_REM_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 95 OP_AND_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 96 OP_OR_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 97 OP_XOR_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 98 OP_SHL_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 99 OP_SHR_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 9A OP_USHR_INT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // 9B OP_ADD_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // 9C OP_SUB_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // 9D OP_MUL_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // 9E OP_DIV_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // 9F OP_REM_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // A0 OP_AND_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // A1 OP_OR_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // A2 OP_XOR_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // A3 OP_SHL_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // A4 OP_SHR_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // A5 OP_USHR_LONG vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // A6 OP_ADD_FLOAT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // A7 OP_SUB_FLOAT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // A8 OP_MUL_FLOAT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // A9 OP_DIV_FLOAT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // AA OP_REM_FLOAT vAA, vBB, vCC
+    DF_DA | DF_UB | DF_UC,
+
+    // AB OP_ADD_DOUBLE vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // AC OP_SUB_DOUBLE vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // AD OP_MUL_DOUBLE vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // AE OP_DIV_DOUBLE vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // AF OP_REM_DOUBLE vAA, vBB, vCC
+    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+    // B0 OP_ADD_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // B1 OP_SUB_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // B2 OP_MUL_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // B3 OP_DIV_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // B4 OP_REM_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // B5 OP_AND_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // B6 OP_OR_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // B7 OP_XOR_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // B8 OP_SHL_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // B9 OP_SHR_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // BA OP_USHR_INT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // BB OP_ADD_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // BC OP_SUB_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // BD OP_MUL_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // BE OP_DIV_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // BF OP_REM_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // C0 OP_AND_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // C1 OP_OR_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // C2 OP_XOR_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // C3 OP_SHL_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // C4 OP_SHR_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // C5 OP_USHR_LONG_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // C6 OP_ADD_FLOAT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // C7 OP_SUB_FLOAT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // C8 OP_MUL_FLOAT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // C9 OP_DIV_FLOAT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // CA OP_REM_FLOAT_2ADDR vA, vB
+    DF_DA | DF_UA | DF_UB,
+
+    // CB OP_ADD_DOUBLE_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // CC OP_SUB_DOUBLE_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // CD OP_MUL_DOUBLE_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // CE OP_DIV_DOUBLE_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // CF OP_REM_DOUBLE_2ADDR vA, vB
+    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+    // D0 OP_ADD_INT_LIT16 vA, vB, #+CCCC
+    DF_DA | DF_UB,
+
+    // D1 OP_RSUB_INT vA, vB, #+CCCC
+    DF_DA | DF_UB,
+
+    // D2 OP_MUL_INT_LIT16 vA, vB, #+CCCC
+    DF_DA | DF_UB,
+
+    // D3 OP_DIV_INT_LIT16 vA, vB, #+CCCC
+    DF_DA | DF_UB,
+
+    // D4 OP_REM_INT_LIT16 vA, vB, #+CCCC
+    DF_DA | DF_UB,
+
+    // D5 OP_AND_INT_LIT16 vA, vB, #+CCCC
+    DF_DA | DF_UB,
+
+    // D6 OP_OR_INT_LIT16 vA, vB, #+CCCC
+    DF_DA | DF_UB,
+
+    // D7 OP_XOR_INT_LIT16 vA, vB, #+CCCC
+    DF_DA | DF_UB,
+
+    // D8 OP_ADD_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB | DF_IS_LINEAR,
+
+    // D9 OP_RSUB_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB,
+
+    // DA OP_MUL_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB,
+
+    // DB OP_DIV_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB,
+
+    // DC OP_REM_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB,
+
+    // DD OP_AND_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB,
+
+    // DE OP_OR_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB,
+
+    // DF OP_XOR_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB,
+
+    // E0 OP_SHL_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB,
+
+    // E1 OP_SHR_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB,
+
+    // E2 OP_USHR_INT_LIT8 vAA, vBB, #+CC
+    DF_DA | DF_UB,
+
+    // E3 OP_UNUSED_E3
+    DF_NOP,
+
+    // E4 OP_UNUSED_E4
+    DF_NOP,
+
+    // E5 OP_UNUSED_E5
+    DF_NOP,
+
+    // E6 OP_UNUSED_E6
+    DF_NOP,
+
+    // E7 OP_UNUSED_E7
+    DF_NOP,
+
+    // E8 OP_UNUSED_E8
+    DF_NOP,
+
+    // E9 OP_UNUSED_E9
+    DF_NOP,
+
+    // EA OP_UNUSED_EA
+    DF_NOP,
+
+    // EB OP_UNUSED_EB
+    DF_NOP,
+
+    // EC OP_UNUSED_EC
+    DF_NOP,
+
+    // ED OP_THROW_VERIFICATION_ERROR
+    DF_NOP,
+
+    // EE OP_EXECUTE_INLINE
+    DF_FORMAT_35C,
+
+    // EF OP_UNUSED_EF
+    DF_NOP,
+
+    // F0 OP_INVOKE_DIRECT_EMPTY
+    DF_NOP,
+
+    // F1 OP_UNUSED_F1
+    DF_NOP,
+
+    // F2 OP_IGET_QUICK
+    DF_DA | DF_UB,
+
+    // F3 OP_IGET_WIDE_QUICK
+    DF_DA_WIDE | DF_UB,
+
+    // F4 OP_IGET_OBJECT_QUICK
+    DF_DA | DF_UB,
+
+    // F5 OP_IPUT_QUICK
+    DF_UA | DF_UB,
+
+    // F6 OP_IPUT_WIDE_QUICK
+    DF_UA_WIDE | DF_UB,
+
+    // F7 OP_IPUT_OBJECT_QUICK
+    DF_UA | DF_UB,
+
+    // F8 OP_INVOKE_VIRTUAL_QUICK
+    DF_FORMAT_35C,
+
+    // F9 OP_INVOKE_VIRTUAL_QUICK_RANGE
+    DF_FORMAT_3RC,
+
+    // FA OP_INVOKE_SUPER_QUICK
+    DF_FORMAT_35C,
+
+    // FB OP_INVOKE_SUPER_QUICK_RANGE
+    DF_FORMAT_3RC,
+
+    // FC OP_UNUSED_FC
+    DF_NOP,
+
+    // FD OP_UNUSED_FD
+    DF_NOP,
+
+    // FE OP_UNUSED_FE
+    DF_NOP,
+
+    // FF OP_UNUSED_FF
+    DF_NOP,
+
+    // Beginning of extended MIR opcodes
+    // 100 OP_MIR_PHI
+    DF_PHI | DF_DA,
+
+    /*
+     * For extended MIR inserted at the MIR2LIR stage, it is okay to have
+     * undefined values here.
+     */
+};
+
+/* Return the Dalvik register/subscript pair of a given SSA register */
+int dvmConvertSSARegToDalvik(CompilationUnit *cUnit, int ssaReg)
+{
+      return GET_ELEM_N(cUnit->ssaToDalvikMap, int, ssaReg);
+}
+
+/*
+ * Utility function to convert encoded SSA register value into Dalvik register
+ * and subscript pair. Each SSA register can be used to index the
+ * ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
+ */
+char *dvmCompilerGetSSAString(CompilationUnit *cUnit, SSARepresentation *ssaRep)
+{
+    char buffer[256];
+    char *ret;
+    int i;
+
+    buffer[0] = 0;
+    for (i = 0; i < ssaRep->numDefs; i++) {
+        int ssa2DalvikValue = dvmConvertSSARegToDalvik(cUnit, ssaRep->defs[i]);
+
+        sprintf(buffer + strlen(buffer), "s%d(v%d_%d) ",
+                ssaRep->defs[i], DECODE_REG(ssa2DalvikValue),
+                DECODE_SUB(ssa2DalvikValue));
+    }
+
+    if (ssaRep->numDefs) {
+        strcat(buffer, "<- ");
+    }
+
+    for (i = 0; i < ssaRep->numUses; i++) {
+        int ssa2DalvikValue = dvmConvertSSARegToDalvik(cUnit, ssaRep->uses[i]);
+        int len = strlen(buffer);
+
+        if (snprintf(buffer + len, 250 - len, "s%d(v%d_%d) ",
+                     ssaRep->uses[i], DECODE_REG(ssa2DalvikValue),
+                     DECODE_SUB(ssa2DalvikValue)) >= (250 - len)) {
+            strcat(buffer, "...");
+            break;
+        }
+    }
+
+    int length = strlen(buffer) + 1;
+    ret = dvmCompilerNew(length, false);
+    memcpy(ret, buffer, length);
+    return ret;
+}
+
+/* Any register that is used before being defined is considered live-in */
+static inline void handleLiveInUse(BitVector *useV, BitVector *defV,
+                                   BitVector *liveInV, int dalvikRegId)
+{
+    dvmCompilerSetBit(useV, dalvikRegId);
+    if (!dvmIsBitSet(defV, dalvikRegId)) {
+        dvmCompilerSetBit(liveInV, dalvikRegId);
+    }
+}
+
+/* Mark a reg as being defined */
+static inline void handleLiveInDef(BitVector *defV, int dalvikRegId)
+{
+    dvmCompilerSetBit(defV, dalvikRegId);
+}
+
+/*
+ * Find out live-in variables for natural loops. Variables that are live-in in
+ * the main loop body are considered to be defined in the entry block.
+ */
+void dvmCompilerFindLiveIn(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    MIR *mir;
+    BitVector *useV, *defV, *liveInV;
+
+    if (bb->blockType != DALVIK_BYTECODE &&
+        bb->blockType != ENTRY_BLOCK) {
+        return;
+    }
+
+    useV = bb->dataFlowInfo->useV =
+        dvmCompilerAllocBitVector(cUnit->method->registersSize, false);
+    defV = bb->dataFlowInfo->defV =
+        dvmCompilerAllocBitVector(cUnit->method->registersSize, false);
+    liveInV = bb->dataFlowInfo->liveInV =
+        dvmCompilerAllocBitVector(cUnit->method->registersSize, false);
+
+    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+        int dfAttributes =
+            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+        DecodedInstruction *dInsn = &mir->dalvikInsn;
+
+        if (dfAttributes & DF_HAS_USES) {
+            if (dfAttributes & DF_UA) {
+                handleLiveInUse(useV, defV, liveInV, dInsn->vA);
+            } else if (dfAttributes & DF_UA_WIDE) {
+                handleLiveInUse(useV, defV, liveInV, dInsn->vA);
+                handleLiveInUse(useV, defV, liveInV, dInsn->vA+1);
+            }
+            if (dfAttributes & DF_UB) {
+                handleLiveInUse(useV, defV, liveInV, dInsn->vB);
+            } else if (dfAttributes & DF_UB_WIDE) {
+                handleLiveInUse(useV, defV, liveInV, dInsn->vB);
+                handleLiveInUse(useV, defV, liveInV, dInsn->vB+1);
+            }
+            if (dfAttributes & DF_UC) {
+                handleLiveInUse(useV, defV, liveInV, dInsn->vC);
+            } else if (dfAttributes & DF_UC_WIDE) {
+                handleLiveInUse(useV, defV, liveInV, dInsn->vC);
+                handleLiveInUse(useV, defV, liveInV, dInsn->vC+1);
+            }
+        }
+        if (dfAttributes & DF_HAS_DEFS) {
+            handleLiveInDef(defV, dInsn->vA);
+            if (dfAttributes & DF_DA_WIDE) {
+                handleLiveInDef(defV, dInsn->vA+1);
+            }
+        }
+    }
+}
+
+/* Find out the latest SSA register for a given Dalvik register */
+static void handleSSAUse(CompilationUnit *cUnit, int *uses, int dalvikReg,
+                         int regIndex)
+{
+    int encodedValue = cUnit->dalvikToSSAMap[dalvikReg];
+    int ssaReg = DECODE_REG(encodedValue);
+    uses[regIndex] = ssaReg;
+}
+
+/* Setup a new SSA register for a given Dalvik register */
+static void handleSSADef(CompilationUnit *cUnit, int *defs, int dalvikReg,
+                         int regIndex)
+{
+    int encodedValue = cUnit->dalvikToSSAMap[dalvikReg];
+    int ssaReg = cUnit->numSSARegs++;
+    /* Bump up the subscript */
+    int dalvikSub = DECODE_SUB(encodedValue) + 1;
+    int newD2SMapping = ENCODE_REG_SUB(ssaReg, dalvikSub);
+
+    cUnit->dalvikToSSAMap[dalvikReg] = newD2SMapping;
+
+    int newS2DMapping = ENCODE_REG_SUB(dalvikReg, dalvikSub);
+    dvmInsertGrowableList(cUnit->ssaToDalvikMap, (void *) newS2DMapping);
+
+    defs[regIndex] = ssaReg;
+}
+
+/* Loop up new SSA names for format_35c instructions */
+static void dataFlowSSAFormat35C(CompilationUnit *cUnit, MIR *mir)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int numUses = dInsn->vA;
+    int i;
+
+    mir->ssaRep->numUses = numUses;
+    mir->ssaRep->uses = dvmCompilerNew(sizeof(int) * numUses, false);
+
+    for (i = 0; i < numUses; i++) {
+        handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->arg[i], i);
+    }
+}
+
+/* Loop up new SSA names for format_3rc instructions */
+static void dataFlowSSAFormat3RC(CompilationUnit *cUnit, MIR *mir)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int numUses = dInsn->vA;
+    int i;
+
+    mir->ssaRep->numUses = numUses;
+    mir->ssaRep->uses = dvmCompilerNew(sizeof(int) * numUses, false);
+
+    for (i = 0; i < numUses; i++) {
+        handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC+i, i);
+    }
+}
+
+/* Entry function to convert a block into SSA representation */
+void dvmCompilerDoSSAConversion(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    MIR *mir;
+
+    if (bb->blockType != DALVIK_BYTECODE && bb->blockType != ENTRY_BLOCK) {
+        return;
+    }
+
+    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+        mir->ssaRep = dvmCompilerNew(sizeof(SSARepresentation), true);
+
+        int dfAttributes =
+            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+
+        int numUses = 0;
+
+        if (dfAttributes & DF_FORMAT_35C) {
+            dataFlowSSAFormat35C(cUnit, mir);
+            continue;
+        }
+
+        if (dfAttributes & DF_FORMAT_3RC) {
+            dataFlowSSAFormat3RC(cUnit, mir);
+            continue;
+        }
+
+        if (dfAttributes & DF_HAS_USES) {
+            if (dfAttributes & DF_UA) {
+                numUses++;
+            } else if (dfAttributes & DF_UA_WIDE) {
+                numUses += 2;
+            }
+            if (dfAttributes & DF_UB) {
+                numUses++;
+            } else if (dfAttributes & DF_UB_WIDE) {
+                numUses += 2;
+            }
+            if (dfAttributes & DF_UC) {
+                numUses++;
+            } else if (dfAttributes & DF_UC_WIDE) {
+                numUses += 2;
+            }
+        }
+
+        if (numUses) {
+            mir->ssaRep->numUses = numUses;
+            mir->ssaRep->uses = dvmCompilerNew(sizeof(int) * numUses, false);
+        }
+
+        int numDefs = 0;
+
+        if (dfAttributes & DF_HAS_DEFS) {
+            numDefs++;
+            if (dfAttributes & DF_DA_WIDE) {
+                numDefs++;
+            }
+        }
+
+        if (numDefs) {
+            mir->ssaRep->numDefs = numDefs;
+            mir->ssaRep->defs = dvmCompilerNew(sizeof(int) * numDefs, false);
+        }
+
+        DecodedInstruction *dInsn = &mir->dalvikInsn;
+
+        if (dfAttributes & DF_HAS_USES) {
+            numUses = 0;
+            if (dfAttributes & DF_UA) {
+                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vA, numUses++);
+            } else if (dfAttributes & DF_UA_WIDE) {
+                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vA, numUses++);
+                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vA+1, numUses++);
+            }
+            if (dfAttributes & DF_UB) {
+                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vB, numUses++);
+            } else if (dfAttributes & DF_UB_WIDE) {
+                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vB, numUses++);
+                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vB+1, numUses++);
+            }
+            if (dfAttributes & DF_UC) {
+                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC, numUses++);
+            } else if (dfAttributes & DF_UC_WIDE) {
+                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC, numUses++);
+                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC+1, numUses++);
+            }
+        }
+        if (dfAttributes & DF_HAS_DEFS) {
+            handleSSADef(cUnit, mir->ssaRep->defs, dInsn->vA, 0);
+            if (dfAttributes & DF_DA_WIDE) {
+                handleSSADef(cUnit, mir->ssaRep->defs, dInsn->vA+1, 1);
+            }
+        }
+    }
+
+    bb->dataFlowInfo->dalvikToSSAMap =
+        dvmCompilerNew(sizeof(int) * cUnit->method->registersSize, false);
+
+    /* Take a snapshot of Dalvik->SSA mapping at the end of each block */
+    memcpy(bb->dataFlowInfo->dalvikToSSAMap, cUnit->dalvikToSSAMap,
+           sizeof(int) * cUnit->method->registersSize);
+}
+
+/* Setup a constant value for opcodes thare have the DF_SETS_CONST attribute */
+static void setConstant(CompilationUnit *cUnit, int ssaReg, int value)
+{
+    dvmSetBit(cUnit->isConstantV, ssaReg);
+    cUnit->constantValues[ssaReg] = value;
+}
+
+void dvmCompilerDoConstantPropagation(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    MIR *mir;
+    BitVector *isConstantV = cUnit->isConstantV;
+
+    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+        int dfAttributes =
+            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+
+        int numUses = 0;
+
+        DecodedInstruction *dInsn = &mir->dalvikInsn;
+
+        if (!(dfAttributes & DF_HAS_DEFS)) continue;
+
+        /* Handle instructions that set up constants directly */
+        if (dfAttributes & DF_SETS_CONST) {
+            if (dfAttributes & DF_DA) {
+                switch (dInsn->opCode) {
+                    case OP_CONST_4:
+                    case OP_CONST_16:
+                    case OP_CONST:
+                        setConstant(cUnit, mir->ssaRep->defs[0], dInsn->vB);
+                        break;
+                    case OP_CONST_HIGH16:
+                        setConstant(cUnit, mir->ssaRep->defs[0],
+                                    dInsn->vB << 16);
+                        break;
+                    default:
+                        break;
+                }
+            } else if (dfAttributes & DF_DA_WIDE) {
+                switch (dInsn->opCode) {
+                    case OP_CONST_WIDE_16:
+                    case OP_CONST_WIDE_32:
+                        setConstant(cUnit, mir->ssaRep->defs[0], dInsn->vB);
+                        setConstant(cUnit, mir->ssaRep->defs[1], 0);
+                        break;
+                    case OP_CONST_WIDE:
+                        setConstant(cUnit, mir->ssaRep->defs[0],
+                                    (int) dInsn->vB_wide);
+                        setConstant(cUnit, mir->ssaRep->defs[1],
+                                    (int) (dInsn->vB_wide >> 32));
+                        break;
+                    case OP_CONST_WIDE_HIGH16:
+                        setConstant(cUnit, mir->ssaRep->defs[0], 0);
+                        setConstant(cUnit, mir->ssaRep->defs[1],
+                                    dInsn->vB << 16);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        /* Handle instructions that set up constants directly */
+        } else if (dfAttributes & DF_IS_MOVE) {
+            int i;
+
+            for (i = 0; i < mir->ssaRep->numUses; i++) {
+                if (!dvmIsBitSet(isConstantV, mir->ssaRep->uses[i])) break;
+            }
+            /* Move a register holding a constant to another register */
+            if (i == mir->ssaRep->numUses) {
+                setConstant(cUnit, mir->ssaRep->defs[0],
+                            cUnit->constantValues[mir->ssaRep->uses[0]]);
+                if (dfAttributes & DF_DA_WIDE) {
+                    setConstant(cUnit, mir->ssaRep->defs[1],
+                                cUnit->constantValues[mir->ssaRep->uses[1]]);
+                }
+            }
+        }
+    }
+    /* TODO: implement code to handle arithmetic operations */
+}
+
+void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
+                                       struct BasicBlock *bb)
+{
+    BitVector *isIndVarV = cUnit->loopAnalysis->isIndVarV;
+    BitVector *isConstantV = cUnit->isConstantV;
+    GrowableList *ivList = cUnit->loopAnalysis->ivList;
+    MIR *mir;
+
+    if (bb->blockType != DALVIK_BYTECODE &&
+        bb->blockType != ENTRY_BLOCK) {
+        return;
+    }
+
+    /* If the bb doesn't have a phi it cannot contain an induction variable */
+    if (bb->firstMIRInsn == NULL ||
+        bb->firstMIRInsn->dalvikInsn.opCode != MIR_OP_PHI) {
+        return;
+    }
+
+    /* Find basic induction variable first */
+    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+        int dfAttributes =
+            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+
+        if (!(dfAttributes & DF_IS_LINEAR)) continue;
+
+        /*
+         * For a basic induction variable:
+         *   1) use[0] should belong to the output of a phi node
+         *   2) def[0] should belong to the input of the same phi node
+         *   3) the value added/subtracted is a constant
+         */
+        MIR *phi;
+        for (phi = bb->firstMIRInsn; phi; phi = phi->next) {
+            if (phi->dalvikInsn.opCode != MIR_OP_PHI) break;
+
+            if (phi->ssaRep->defs[0] == mir->ssaRep->uses[0] &&
+                phi->ssaRep->uses[1] == mir->ssaRep->defs[0]) {
+                bool deltaIsConstant = false;
+                int deltaValue;
+
+                switch (mir->dalvikInsn.opCode) {
+                    case OP_ADD_INT:
+                        if (dvmIsBitSet(isConstantV,
+                                        mir->ssaRep->uses[1])) {
+                            deltaValue =
+                                cUnit->constantValues[mir->ssaRep->uses[1]];
+                            deltaIsConstant = true;
+                        }
+                        break;
+                    case OP_SUB_INT:
+                        if (dvmIsBitSet(isConstantV,
+                                        mir->ssaRep->uses[1])) {
+                            deltaValue =
+                                -cUnit->constantValues[mir->ssaRep->uses[1]];
+                            deltaIsConstant = true;
+                        }
+                        break;
+                    case OP_ADD_INT_LIT8:
+                        deltaValue = mir->dalvikInsn.vC;
+                        deltaIsConstant = true;
+                        break;
+                    default:
+                        break;
+                }
+                if (deltaIsConstant) {
+                    dvmSetBit(isIndVarV, mir->ssaRep->uses[0]);
+                    InductionVariableInfo *ivInfo =
+                        dvmCompilerNew(sizeof(InductionVariableInfo),
+                                       false);
+
+                    ivInfo->ssaReg = mir->ssaRep->uses[0];
+                    ivInfo->basicSSAReg = mir->ssaRep->uses[0];
+                    ivInfo->m = 1;         // always 1 to basic iv
+                    ivInfo->c = 0;         // N/A to basic iv
+                    ivInfo->inc = deltaValue;
+                    dvmInsertGrowableList(ivList, (void *) ivInfo);
+                    cUnit->loopAnalysis->numBasicIV++;
+                    break;
+                }
+            }
+        }
+    }
+
+    /* Find dependent induction variable now */
+    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+        int dfAttributes =
+            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+
+        if (!(dfAttributes & DF_IS_LINEAR)) continue;
+
+        /* Skip already identified induction variables */
+        if (dvmIsBitSet(isIndVarV, mir->ssaRep->defs[0])) continue;
+
+        /*
+         * For a dependent induction variable:
+         *  1) use[0] should be an induction variable (basic/dependent)
+         *  2) operand2 should be a constant
+         */
+        if (dvmIsBitSet(isIndVarV, mir->ssaRep->uses[0])) {
+            int srcDalvikReg = dvmConvertSSARegToDalvik(cUnit,
+                                                        mir->ssaRep->uses[0]);
+            int dstDalvikReg = dvmConvertSSARegToDalvik(cUnit,
+                                                        mir->ssaRep->defs[0]);
+
+            bool cIsConstant = false;
+            int c = 0;
+
+            switch (mir->dalvikInsn.opCode) {
+                case OP_ADD_INT:
+                    if (dvmIsBitSet(isConstantV,
+                                    mir->ssaRep->uses[1])) {
+                        c = cUnit->constantValues[mir->ssaRep->uses[1]];
+                        cIsConstant = true;
+                    }
+                    break;
+                case OP_SUB_INT:
+                    if (dvmIsBitSet(isConstantV,
+                                    mir->ssaRep->uses[1])) {
+                        c = -cUnit->constantValues[mir->ssaRep->uses[1]];
+                        cIsConstant = true;
+                    }
+                    break;
+                case OP_ADD_INT_LIT8:
+                    c = mir->dalvikInsn.vC;
+                    cIsConstant = true;
+                    break;
+                default:
+                    break;
+            }
+
+            /* Ignore the update to the basic induction variable itself */
+            if (DECODE_REG(srcDalvikReg) == DECODE_REG(dstDalvikReg))  {
+                cUnit->loopAnalysis->ssaBIV = mir->ssaRep->defs[0];
+                cIsConstant = false;
+            }
+
+            if (cIsConstant) {
+                unsigned int i;
+                dvmSetBit(isIndVarV, mir->ssaRep->defs[0]);
+                InductionVariableInfo *ivInfo =
+                    dvmCompilerNew(sizeof(InductionVariableInfo),
+                                   false);
+                InductionVariableInfo *ivInfoOld = NULL ;
+
+                for (i = 0; i < ivList->numUsed; i++) {
+                    ivInfoOld = ivList->elemList[i];
+                    if (ivInfoOld->ssaReg == mir->ssaRep->uses[0]) break;
+                }
+
+                /* Guaranteed to find an element */
+                assert(i < ivList->numUsed);
+
+                ivInfo->ssaReg = mir->ssaRep->defs[0];
+                ivInfo->basicSSAReg = ivInfoOld->basicSSAReg;
+                ivInfo->m = ivInfoOld->m;
+                ivInfo->c = c + ivInfoOld->c;
+                ivInfo->inc = ivInfoOld->inc;
+                dvmInsertGrowableList(ivList, (void *) ivInfo);
+            }
+        }
+    }
+}
+
+/* Setup the basic data structures for SSA conversion */
+void dvmInitializeSSAConversion(CompilationUnit *cUnit)
+{
+    int i;
+    int numDalvikReg = cUnit->method->registersSize;
+
+    cUnit->ssaToDalvikMap = dvmCompilerNew(sizeof(GrowableList), false);
+    dvmInitGrowableList(cUnit->ssaToDalvikMap, numDalvikReg);
+
+    /*
+     * Initial number of SSA registers is equal to the number of Dalvik
+     * registers.
+     */
+    cUnit->numSSARegs = numDalvikReg;
+
+    /*
+     * Initialize the SSA2Dalvik map list. For the first numDalvikReg elements,
+     * the subscript is 0 so we use the ENCODE_REG_SUB macro to encode the value
+     * into "(0 << 16) | i"
+     */
+    for (i = 0; i < numDalvikReg; i++) {
+        dvmInsertGrowableList(cUnit->ssaToDalvikMap,
+                              (void *) ENCODE_REG_SUB(i, 0));
+    }
+
+    /*
+     * Initialize the DalvikToSSAMap map. The low 16 bit is the SSA register id,
+     * while the high 16 bit is the current subscript. The original Dalvik
+     * register N is mapped to SSA register N with subscript 0.
+     */
+    cUnit->dalvikToSSAMap = dvmCompilerNew(sizeof(int) * numDalvikReg, false);
+    for (i = 0; i < numDalvikReg; i++) {
+        cUnit->dalvikToSSAMap[i] = i;
+    }
+
+    /*
+     * Allocate the BasicBlockDataFlow structure for the entry and code blocks
+     */
+    for (i = 0; i < cUnit->numBlocks; i++) {
+        BasicBlock *bb = cUnit->blockList[i];
+        if (bb->blockType == DALVIK_BYTECODE ||
+            bb->blockType == ENTRY_BLOCK) {
+            bb->dataFlowInfo = dvmCompilerNew(sizeof(BasicBlockDataFlow), true);
+        }
+    }
+}
+
+void dvmCompilerDataFlowAnalysisDispatcher(CompilationUnit *cUnit,
+                void (*func)(CompilationUnit *, BasicBlock *))
+{
+    int i;
+    for (i = 0; i < cUnit->numBlocks; i++) {
+        BasicBlock *bb = cUnit->blockList[i];
+        (*func)(cUnit, bb);
+    }
+}
+
+/* Main entry point to do SSA conversion for non-loop traces */
+void dvmCompilerNonLoopAnalysis(CompilationUnit *cUnit)
+{
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion);
+}
diff --git a/vm/compiler/Dataflow.h b/vm/compiler/Dataflow.h
new file mode 100644
index 0000000..e4ae93d
--- /dev/null
+++ b/vm/compiler/Dataflow.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DALVIK_VM_DATAFLOW
+#define _DALVIK_VM_DATAFLOW
+
+#include "Dalvik.h"
+#include "CompilerInternals.h"
+
+typedef enum DataFlowAttributePos {
+    kUA = 0,
+    kUB,
+    kUC,
+    kUAWide,
+    kUBWide,
+    kUCWide,
+    kDA,
+    kDAWide,
+    kIsMove,
+    kIsLinear,
+    kSetsConst,
+    kFormat35c,
+    kFormat3rc,
+    kPhi,
+    kNullNRangeCheck0,
+    kNullNRangeCheck1,
+    kNullNRangeCheck2,
+} DataFlowAttributes;
+
+#define DF_NOP                  0
+#define DF_UA                   (1 << kUA)
+#define DF_UB                   (1 << kUB)
+#define DF_UC                   (1 << kUC)
+#define DF_UA_WIDE              (1 << kUAWide)
+#define DF_UB_WIDE              (1 << kUBWide)
+#define DF_UC_WIDE              (1 << kUCWide)
+#define DF_DA                   (1 << kDA)
+#define DF_DA_WIDE              (1 << kDAWide)
+#define DF_IS_MOVE              (1 << kIsMove)
+#define DF_IS_LINEAR            (1 << kIsLinear)
+#define DF_SETS_CONST           (1 << kSetsConst)
+#define DF_FORMAT_35C           (1 << kFormat35c)
+#define DF_FORMAT_3RC           (1 << kFormat3rc)
+#define DF_PHI                  (1 << kPhi)
+#define DF_NULL_N_RANGE_CHECK_0 (1 << kNullNRangeCheck0)
+#define DF_NULL_N_RANGE_CHECK_1 (1 << kNullNRangeCheck1)
+#define DF_NULL_N_RANGE_CHECK_2 (1 << kNullNRangeCheck2)
+
+#define DF_HAS_USES             (DF_UA | DF_UB | DF_UC | DF_UA_WIDE | \
+                                 DF_UB_WIDE | DF_UC_WIDE)
+
+#define DF_HAS_DEFS             (DF_DA | DF_DA_WIDE)
+
+#define DF_HAS_NR_CHECKS        (DF_NULL_N_RANGE_CHECK_0 | \
+                                 DF_NULL_N_RANGE_CHECK_1 | \
+                                 DF_NULL_N_RANGE_CHECK_2)
+
+extern int dvmCompilerDataFlowAttributes[MIR_OP_LAST];
+
+typedef struct BasicBlockDataFlow {
+    BitVector *useV;
+    BitVector *defV;
+    BitVector *liveInV;
+    BitVector *phiV;
+    int *dalvikToSSAMap;
+} BasicBlockDataFlow;
+
+typedef struct SSARepresentation {
+    int numUses;
+    int *uses;
+    int numDefs;
+    int *defs;
+} SSARepresentation;
+
+typedef struct InductionVariableInfo {
+    int ssaReg;
+    int basicSSAReg;
+    int m;
+    int c;
+    int inc;
+} InductionVariableInfo;
+
+typedef struct ArrayAccessInfo {
+    int arrayReg;
+    int ivReg;
+    int maxC;                   // For DIV - will affect upper bound checking
+    int minC;                   // For DIV - will affect lower bound checking
+} ArrayAccessInfo;
+
+#define ENCODE_REG_SUB(r,s)             ((s<<16) | r)
+#define DECODE_REG(v)                   (v & 0xffff)
+#define DECODE_SUB(v)                   (((unsigned int) v) >> 16)
+
+#endif /* _DALVIK_VM_DATAFLOW */
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 66060a0..163cdf8 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -47,6 +47,8 @@
     return insnWidth;
 }
 
+#define UNKNOWN_TARGET 0xffffffff
+
 /*
  * Identify block-ending instructions and collect supplemental information
  * regarding the following instructions.
@@ -63,6 +65,8 @@
         case OP_RETURN_WIDE:
         case OP_RETURN_OBJECT:
         case OP_THROW:
+          *target = UNKNOWN_TARGET;
+          break;
         case OP_INVOKE_VIRTUAL:
         case OP_INVOKE_VIRTUAL_RANGE:
         case OP_INVOKE_INTERFACE:
@@ -146,7 +150,8 @@
 
         default:
             return false;
-    } return true;
+    }
+    return true;
 }
 
 /*
@@ -262,7 +267,7 @@
     methodStats = analyzeMethodBody(desc->method);
 
     cUnit.registerScoreboard.nullCheckedRegs =
-        dvmAllocBitVector(desc->method->registersSize, false);
+        dvmCompilerAllocBitVector(desc->method->registersSize, false);
 
     /* Initialize the printMe flag */
     cUnit.printMe = gDvmJit.printMe;
@@ -333,11 +338,20 @@
         }
     }
 
-    /* Allocate the first basic block */
-    lastBB = startBB = curBB = dvmCompilerNewBB(DALVIK_BYTECODE);
+    /* Allocate the entry block */
+    lastBB = startBB = curBB = dvmCompilerNewBB(ENTRY_BLOCK);
     curBB->startOffset = curOffset;
     curBB->id = numBlocks++;
 
+    curBB = dvmCompilerNewBB(DALVIK_BYTECODE);
+    curBB->startOffset = curOffset;
+    curBB->id = numBlocks++;
+
+    /* Make the first real dalvik block the fallthrough of the entry block */
+    startBB->fallThrough = curBB;
+    lastBB->next = curBB;
+    lastBB = curBB;
+
     if (cUnit.printMe) {
         LOGD("--------\nCompiler: Building trace for %s, offset 0x%x\n",
              desc->method->name, curOffset);
@@ -350,7 +364,7 @@
     while (1) {
         MIR *insn;
         int width;
-        insn = dvmCompilerNew(sizeof(MIR),false);
+        insn = dvmCompilerNew(sizeof(MIR), true);
         insn->offset = curOffset;
         width = parseInsn(codePtr, &insn->dalvikInsn, cUnit.printMe);
 
@@ -394,9 +408,9 @@
      */
     for (curBB = startBB; curBB; curBB = curBB->next) {
         MIR *lastInsn = curBB->lastMIRInsn;
-        /* Hit a pseudo block - exit the search now */
+        /* Skip empty blocks */
         if (lastInsn == NULL) {
-            break;
+            continue;
         }
         curOffset = lastInsn->offset;
         unsigned int targetOffset = curOffset;
@@ -436,33 +450,63 @@
                        kInstrInvoke)) == 0) ||
             (lastInsn->dalvikInsn.opCode == OP_INVOKE_DIRECT_EMPTY);
 
-
-        /* Target block not included in the trace */
         if (curBB->taken == NULL &&
-            (isInvoke || (targetOffset != curOffset))) {
-            BasicBlock *newBB;
-            if (isInvoke) {
-                /* Monomorphic callee */
-                if (callee) {
-                    newBB = dvmCompilerNewBB(CHAINING_CELL_INVOKE_SINGLETON);
-                    newBB->startOffset = 0;
-                    newBB->containingMethod = callee;
-                /* Will resolve at runtime */
-                } else {
-                    newBB = dvmCompilerNewBB(CHAINING_CELL_INVOKE_PREDICTED);
-                    newBB->startOffset = 0;
-                }
-            /* For unconditional branches, request a hot chaining cell */
-            } else {
-                newBB = dvmCompilerNewBB(flags & kInstrUnconditional ?
-                                                  CHAINING_CELL_HOT :
-                                                  CHAINING_CELL_NORMAL);
-                newBB->startOffset = targetOffset;
+            curBB->fallThrough == NULL &&
+            flags == (kInstrCanBranch | kInstrCanContinue) &&
+            fallThroughOffset == startBB->startOffset) {
+            BasicBlock *loopBranch = curBB;
+            BasicBlock *exitBB;
+            BasicBlock *exitChainingCell;
+
+            if (cUnit.printMe) {
+                LOGD("Natural loop detected!");
             }
-            newBB->id = numBlocks++;
-            curBB->taken = newBB;
-            lastBB->next = newBB;
-            lastBB = newBB;
+            exitBB = dvmCompilerNewBB(EXIT_BLOCK);
+            lastBB->next = exitBB;
+            lastBB = exitBB;
+
+            exitBB->startOffset = targetOffset;
+            exitBB->id = numBlocks++;
+            exitBB->needFallThroughBranch = true;
+
+            loopBranch->taken = exitBB;
+#if defined(WITH_SELF_VERIFICATION)
+            BasicBlock *backwardCell =
+                dvmCompilerNewBB(CHAINING_CELL_BACKWARD_BRANCH);
+            lastBB->next = backwardCell;
+            lastBB = backwardCell;
+
+            backwardCell->startOffset = startBB->startOffset;
+            backwardCell->id = numBlocks++;
+            loopBranch->fallThrough = backwardCell;
+#elif defined(WITH_JIT_TUNING)
+            if (gDvmJit.profile) {
+                BasicBlock *backwardCell =
+                    dvmCompilerNewBB(CHAINING_CELL_BACKWARD_BRANCH);
+                lastBB->next = backwardCell;
+                lastBB = backwardCell;
+
+                backwardCell->startOffset = startBB->startOffset;
+                backwardCell->id = numBlocks++;
+                loopBranch->fallThrough = backwardCell;
+            } else {
+                loopBranch->fallThrough = startBB->next;
+            }
+#else
+            loopBranch->fallThrough = startBB->next;
+#endif
+
+            /* Create the chaining cell as the fallthrough of the exit block */
+            exitChainingCell = dvmCompilerNewBB(CHAINING_CELL_NORMAL);
+            lastBB->next = exitChainingCell;
+            lastBB = exitChainingCell;
+
+            exitChainingCell->startOffset = targetOffset;
+            exitChainingCell->id = numBlocks++;
+
+            exitBB->fallThrough = exitChainingCell;
+
+            cUnit.hasLoop = true;
         }
 
         /* Fallthrough block not included in the trace */
@@ -482,6 +526,48 @@
             lastBB->startOffset = fallThroughOffset;
             curBB->fallThrough = lastBB;
         }
+
+        /* Target block not included in the trace */
+        if (curBB->taken == NULL &&
+            (isInvoke || (targetOffset != UNKNOWN_TARGET &&
+                          targetOffset != curOffset))) {
+            BasicBlock *newBB;
+            if (isInvoke) {
+                /* Monomorphic callee */
+                if (callee) {
+                    newBB = dvmCompilerNewBB(CHAINING_CELL_INVOKE_SINGLETON);
+                    newBB->startOffset = 0;
+                    newBB->containingMethod = callee;
+                /* Will resolve at runtime */
+                } else {
+                    newBB = dvmCompilerNewBB(CHAINING_CELL_INVOKE_PREDICTED);
+                    newBB->startOffset = 0;
+                }
+            /* For unconditional branches, request a hot chaining cell */
+            } else {
+#if !defined(WITH_SELF_VERIFICATION)
+                newBB = dvmCompilerNewBB(flags & kInstrUnconditional ?
+                                                  CHAINING_CELL_HOT :
+                                                  CHAINING_CELL_NORMAL);
+                newBB->startOffset = targetOffset;
+#else
+                /* Handle branches that branch back into the block */
+                if (targetOffset >= curBB->firstMIRInsn->offset &&
+                    targetOffset <= curBB->lastMIRInsn->offset) {
+                    newBB = dvmCompilerNewBB(CHAINING_CELL_BACKWARD_BRANCH);
+                } else {
+                    newBB = dvmCompilerNewBB(flags & kInstrUnconditional ?
+                                                      CHAINING_CELL_HOT :
+                                                      CHAINING_CELL_NORMAL);
+                }
+                newBB->startOffset = targetOffset;
+#endif
+            }
+            newBB->id = numBlocks++;
+            curBB->taken = newBB;
+            lastBB->next = newBB;
+            lastBB = newBB;
+        }
     }
 
     /* Now create a special block to host PC reconstruction code */
@@ -524,6 +610,16 @@
     /* Make sure all blocks are added to the cUnit */
     assert(curBB == NULL);
 
+    /* Preparation for SSA conversion */
+    dvmInitializeSSAConversion(&cUnit);
+
+    if (cUnit.hasLoop) {
+        dvmCompilerLoopOpt(&cUnit);
+    }
+    else {
+        dvmCompilerNonLoopAnalysis(&cUnit);
+    }
+
     if (cUnit.printMe) {
         dvmCompilerDumpCompilationUnit(&cUnit);
     }
@@ -551,11 +647,8 @@
     /* Reset the compiler resource pool */
     dvmCompilerArenaReset();
 
-    /* Free the bit vector tracking null-checked registers */
-    dvmFreeBitVector(cUnit.registerScoreboard.nullCheckedRegs);
-
-    if (!cUnit.halveInstCount) {
     /* Success */
+    if (!cUnit.halveInstCount) {
         methodStats->nativeSize += cUnit.totalSize;
         return info->codeAddress != NULL;
 
@@ -584,15 +677,16 @@
     firstBlock->id = blockID++;
 
     /* Allocate the bit-vector to track the beginning of basic blocks */
-    BitVector *bbStartAddr = dvmAllocBitVector(dexCode->insnsSize+1, false);
-    dvmSetBit(bbStartAddr, 0);
+    BitVector *bbStartAddr = dvmCompilerAllocBitVector(dexCode->insnsSize+1,
+                                                       false);
+    dvmCompilerSetBit(bbStartAddr, 0);
 
     /*
      * Sequentially go through every instruction first and put them in a single
      * basic block. Identify block boundaries at the mean time.
      */
     while (codePtr < codeEnd) {
-        MIR *insn = dvmCompilerNew(sizeof(MIR), false);
+        MIR *insn = dvmCompilerNew(sizeof(MIR), true);
         insn->offset = curOffset;
         int width = parseInsn(codePtr, &insn->dalvikInsn, false);
         bool isInvoke = false;
@@ -616,9 +710,9 @@
          */
         if (findBlockBoundary(method, insn, curOffset, &target, &isInvoke,
                               &callee)) {
-            dvmSetBit(bbStartAddr, curOffset + width);
+            dvmCompilerSetBit(bbStartAddr, curOffset + width);
             if (target != curOffset) {
-                dvmSetBit(bbStartAddr, target);
+                dvmCompilerSetBit(bbStartAddr, target);
             }
         }
 
@@ -699,8 +793,6 @@
         dvmAbort();
     }
 
-    dvmFreeBitVector(bbStartAddr);
-
     /* Connect the basic blocks through the taken links */
     for (i = 0; i < numBlocks; i++) {
         BasicBlock *curBB = blockList[i];
diff --git a/vm/compiler/IntermediateRep.c b/vm/compiler/IntermediateRep.c
index 91b7af7..018d890 100644
--- a/vm/compiler/IntermediateRep.c
+++ b/vm/compiler/IntermediateRep.c
@@ -29,7 +29,7 @@
 void dvmCompilerAppendMIR(BasicBlock *bb, MIR *mir)
 {
     if (bb->firstMIRInsn == NULL) {
-        assert(bb->firstMIRInsn == NULL);
+        assert(bb->lastMIRInsn == NULL);
         bb->lastMIRInsn = bb->firstMIRInsn = mir;
         mir->prev = mir->next = NULL;
     } else {
@@ -40,6 +40,21 @@
     }
 }
 
+/* Insert an MIR instruction to the head of a basic block */
+void dvmCompilerPrependMIR(BasicBlock *bb, MIR *mir)
+{
+    if (bb->firstMIRInsn == NULL) {
+        assert(bb->lastMIRInsn == NULL);
+        bb->lastMIRInsn = bb->firstMIRInsn = mir;
+        mir->prev = mir->next = NULL;
+    } else {
+        bb->firstMIRInsn->prev = mir;
+        mir->next = bb->firstMIRInsn;
+        mir->prev = NULL;
+        bb->firstMIRInsn = mir;
+    }
+}
+
 /*
  * Append an LIR instruction to the LIR list maintained by a compilation
  * unit
@@ -75,3 +90,17 @@
     newLIR->next = currentLIR;
     currentLIR->prev = newLIR;
 }
+
+/*
+ * Insert an LIR instruction after the current instruction, which cannot be the
+ * first instruction.
+ *
+ * currentLIR -> newLIR -> oldNext
+ */
+void dvmCompilerInsertLIRAfter(LIR *currentLIR, LIR *newLIR)
+{
+    newLIR->prev = currentLIR;
+    newLIR->next = currentLIR->next;
+    currentLIR->next = newLIR;
+    newLIR->next->prev = newLIR;
+}
diff --git a/vm/compiler/Loop.c b/vm/compiler/Loop.c
new file mode 100644
index 0000000..ffd5883
--- /dev/null
+++ b/vm/compiler/Loop.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Dalvik.h"
+#include "CompilerInternals.h"
+#include "Dataflow.h"
+#include "Loop.h"
+
+#define DEBUG_LOOP(X)
+
+/*
+ * Given the current simple natural loops, the phi node placement can be
+ * determined in the following fashion:
+ *                    entry (B0)
+ *              +---v   v
+ *              |  loop body (B1)
+ *              |       v
+ *              |  loop back (B2)
+ *              +---+   v
+ *                     exit (B3)
+ *
+ *  1) Add live-ins of B1 to B0 as defs
+ *  2) The intersect of defs(B0)/defs(B1) and defs(B2)/def(B0) are the variables
+ *     that need PHI nodes in B1.
+ */
+static void handlePhiPlacement(CompilationUnit *cUnit)
+{
+    BasicBlock *entry = cUnit->blockList[0];
+    BasicBlock *loopBody = cUnit->blockList[1];
+    BasicBlock *loopBranch = cUnit->blockList[2];
+    dvmCopyBitVector(entry->dataFlowInfo->defV,
+                     loopBody->dataFlowInfo->liveInV);
+
+    BitVector *phiV = dvmCompilerAllocBitVector(cUnit->method->registersSize,
+                                                false);
+    dvmIntersectBitVectors(phiV, entry->dataFlowInfo->defV,
+                           loopBody->dataFlowInfo->defV);
+    dvmIntersectBitVectors(phiV, entry->dataFlowInfo->defV,
+                           loopBranch->dataFlowInfo->defV);
+
+    /* Insert the PHI MIRs */
+    int i;
+    for (i = 0; i < cUnit->method->registersSize; i++) {
+        if (!dvmIsBitSet(phiV, i)) {
+            continue;
+        }
+        MIR *phi = dvmCompilerNew(sizeof(MIR), true);
+        phi->dalvikInsn.opCode = MIR_OP_PHI;
+        phi->dalvikInsn.vA = i;
+        dvmCompilerPrependMIR(loopBody, phi);
+    }
+}
+
+static void fillPhiNodeContents(CompilationUnit *cUnit)
+{
+    BasicBlock *entry = cUnit->blockList[0];
+    BasicBlock *loopBody = cUnit->blockList[1];
+    BasicBlock *loopBranch = cUnit->blockList[2];
+    MIR *mir;
+
+    for (mir = loopBody->firstMIRInsn; mir; mir = mir->next) {
+        if (mir->dalvikInsn.opCode != MIR_OP_PHI) break;
+        int dalvikReg = mir->dalvikInsn.vA;
+
+        mir->ssaRep->numUses = 2;
+        mir->ssaRep->uses = dvmCompilerNew(sizeof(int) * 2, false);
+        mir->ssaRep->uses[0] =
+            DECODE_REG(entry->dataFlowInfo->dalvikToSSAMap[dalvikReg]);
+        mir->ssaRep->uses[1] =
+            DECODE_REG(loopBranch->dataFlowInfo->dalvikToSSAMap[dalvikReg]);
+    }
+
+
+}
+
+static void dumpConstants(CompilationUnit *cUnit)
+{
+    int i;
+    for (i = 0; i < cUnit->numSSARegs; i++) {
+        if (dvmIsBitSet(cUnit->isConstantV, i)) {
+            int subNReg = dvmConvertSSARegToDalvik(cUnit, i);
+            LOGE("s%d(v%d_%d) has %d", i,
+                 DECODE_REG(subNReg), DECODE_SUB(subNReg),
+                 cUnit->constantValues[i]);
+        }
+    }
+}
+
+static void dumpIVList(CompilationUnit *cUnit)
+{
+    unsigned int i;
+    GrowableList *ivList = cUnit->loopAnalysis->ivList;
+    int *ssaToDalvikMap = (int *) cUnit->ssaToDalvikMap->elemList;
+
+    for (i = 0; i < ivList->numUsed; i++) {
+        InductionVariableInfo *ivInfo = ivList->elemList[i];
+        /* Basic IV */
+        if (ivInfo->ssaReg == ivInfo->basicSSAReg) {
+            LOGE("BIV %d: s%d(v%d) + %d", i,
+                 ivInfo->ssaReg,
+                 ssaToDalvikMap[ivInfo->ssaReg] & 0xffff,
+                 ivInfo->inc);
+        /* Dependent IV */
+        } else {
+            LOGE("DIV %d: s%d(v%d) = %d * s%d(v%d) + %d", i,
+                 ivInfo->ssaReg,
+                 ssaToDalvikMap[ivInfo->ssaReg] & 0xffff,
+                 ivInfo->m,
+                 ivInfo->basicSSAReg,
+                 ssaToDalvikMap[ivInfo->basicSSAReg] & 0xffff,
+                 ivInfo->c);
+        }
+    }
+}
+
+/*
+ * A loop is considered optimizable if:
+ * 1) It has one basic induction variable
+ * 2) The loop back branch compares the BIV with a constant
+ * 3) If it is a count-up loop, the condition is GE/GT, or LE/LT/LEZ/LTZ for
+ *    a count-down loop.
+ */
+static bool isLoopOptimizable(CompilationUnit *cUnit)
+{
+    unsigned int i;
+    BasicBlock *loopBranch = cUnit->blockList[2];
+    LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
+
+    if (loopAnalysis->numBasicIV != 1) return false;
+    for (i = 0; i < loopAnalysis->ivList->numUsed; i++) {
+        InductionVariableInfo *ivInfo;
+
+        ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i);
+        /* Count up or down loop? */
+        if (ivInfo->ssaReg == ivInfo->basicSSAReg) {
+            loopAnalysis->isCountUpLoop = ivInfo->inc > 0;
+            break;
+        }
+    }
+
+    MIR *branch = loopBranch->lastMIRInsn;
+    OpCode opCode = branch->dalvikInsn.opCode;
+
+    /*
+     * If the instruction is not accessing the IV as the first operand, return
+     * false.
+     */
+    if (branch->ssaRep->numUses == 0 || branch->ssaRep->numDefs != 0) {
+        return false;
+    }
+
+    /*
+     * If the first operand of the comparison is not the basic induction
+     * variable, return false.
+     */
+    if (branch->ssaRep->uses[0] != loopAnalysis->ssaBIV) {
+        return false;
+    }
+
+    if (loopAnalysis->isCountUpLoop) {
+        /*
+         * If the condition op is not > or >=, this is not an optimization
+         * candidate.
+         */
+        if (opCode != OP_IF_GT && opCode != OP_IF_GE) {
+            return false;
+        }
+        /*
+         * If the comparison is not between the BIV and a loop invariant,
+         * return false.
+         */
+        int endReg = dvmConvertSSARegToDalvik(cUnit, branch->ssaRep->uses[1]);
+
+        if (DECODE_SUB(endReg) != 0) {
+            return false;
+        }
+        loopAnalysis->endConditionReg = DECODE_REG(endReg);
+    } else  {
+        /*
+         * If the condition op is not < or <=, this is not an optimization
+         * candidate.
+         */
+        if (opCode == OP_IF_LT || opCode == OP_IF_LE) {
+            /*
+             * If the comparison is not between the BIV and a loop invariant,
+             * return false.
+             */
+            int endReg = dvmConvertSSARegToDalvik(cUnit,
+                                                  branch->ssaRep->uses[1]);
+
+            if (DECODE_SUB(endReg) != 0) {
+                return false;
+            }
+            loopAnalysis->endConditionReg = DECODE_REG(endReg);
+        } else if (opCode != OP_IF_LTZ && opCode != OP_IF_LEZ) {
+            return false;
+        }
+    }
+    loopAnalysis->loopBranchOpcode = opCode;
+    return true;
+}
+
+/*
+ * Record the upper and lower bound information for range checks for each
+ * induction variable. If array A is accessed by index "i+5", the upper and
+ * lower bound will be len(A)-5 and -5, respectively.
+ */
+static void updateRangeCheckInfo(CompilationUnit *cUnit, int arrayReg,
+                                 int idxReg)
+{
+    InductionVariableInfo *ivInfo;
+    LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
+    unsigned int i, j;
+
+    for (i = 0; i < loopAnalysis->ivList->numUsed; i++) {
+        ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i);
+        if (ivInfo->ssaReg == idxReg) {
+            ArrayAccessInfo *arrayAccessInfo = NULL;
+            for (j = 0; j < loopAnalysis->arrayAccessInfo->numUsed; j++) {
+                ArrayAccessInfo *existingArrayAccessInfo =
+                    GET_ELEM_N(loopAnalysis->arrayAccessInfo,
+                               ArrayAccessInfo*,
+                               j);
+                if (existingArrayAccessInfo->arrayReg == arrayReg) {
+                    if (ivInfo->c > existingArrayAccessInfo->maxC) {
+                        existingArrayAccessInfo->maxC = ivInfo->c;
+                    }
+                    if (ivInfo->c < existingArrayAccessInfo->minC) {
+                        existingArrayAccessInfo->minC = ivInfo->c;
+                    }
+                    arrayAccessInfo = existingArrayAccessInfo;
+                    break;
+                }
+            }
+            if (arrayAccessInfo == NULL) {
+                arrayAccessInfo =
+                    dvmCompilerNew(sizeof(ArrayAccessInfo), false);
+                arrayAccessInfo->ivReg = ivInfo->basicSSAReg;
+                arrayAccessInfo->arrayReg = arrayReg;
+                arrayAccessInfo->maxC = (ivInfo->c > 0) ? ivInfo->c : 0;
+                arrayAccessInfo->minC = (ivInfo->c < 0) ? ivInfo->c : 0;
+                dvmInsertGrowableList(loopAnalysis->arrayAccessInfo,
+                                      arrayAccessInfo);
+            }
+            break;
+        }
+    }
+}
+
+/* Returns true if the loop body cannot throw any exceptions */
+static bool doLoopBodyCodeMotion(CompilationUnit *cUnit)
+{
+    BasicBlock *entry = cUnit->blockList[0];
+    BasicBlock *loopBody = cUnit->blockList[1];
+    MIR *mir;
+    bool loopBodyCanThrow = false;
+    int numDalvikRegs = cUnit->method->registersSize;
+
+    for (mir = loopBody->firstMIRInsn; mir; mir = mir->next) {
+        DecodedInstruction *dInsn = &mir->dalvikInsn;
+        int dfAttributes =
+            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+
+        /* Skip extended MIR instructions */
+        if (dInsn->opCode > 255) continue;
+
+        int instrFlags = dexGetInstrFlags(gDvm.instrFlags, dInsn->opCode);
+
+        /* Instruction is clean */
+        if ((instrFlags & kInstrCanThrow) == 0) continue;
+
+        /*
+         * Currently we can only optimize away null and range checks. Punt on
+         * instructions that can throw due to other exceptions.
+         */
+        if (!(dfAttributes & DF_HAS_NR_CHECKS)) {
+            loopBodyCanThrow = true;
+            continue;
+        }
+
+        /*
+         * This comparison is redundant now, but we will have more than one
+         * group of flags to check soon.
+         */
+        if (dfAttributes & DF_HAS_NR_CHECKS) {
+            /*
+             * Check if the null check is applied on a loop invariant register?
+             * If the register's SSA id is less than the number of Dalvik
+             * registers, then it is loop invariant.
+             */
+            int refIdx;
+            switch (dfAttributes & DF_HAS_NR_CHECKS) {
+                case DF_NULL_N_RANGE_CHECK_0:
+                    refIdx = 0;
+                    break;
+                case DF_NULL_N_RANGE_CHECK_1:
+                    refIdx = 1;
+                    break;
+                case DF_NULL_N_RANGE_CHECK_2:
+                    refIdx = 2;
+                    break;
+                default:
+                    refIdx = 0;
+                    dvmAbort();
+            }
+
+            int useIdx = refIdx + 1;
+            int subNRegArray =
+                dvmConvertSSARegToDalvik(cUnit, mir->ssaRep->uses[refIdx]);
+            int arrayReg = DECODE_REG(subNRegArray);
+            int arraySub = DECODE_SUB(subNRegArray);
+
+            /*
+             * If the register is never updated in the loop (ie subscript == 0),
+             * it is an optimization candidate.
+             */
+            if (arraySub != 0) {
+                loopBodyCanThrow = true;
+                continue;
+            }
+
+            /*
+             * Then check if the range check can be hoisted out of the loop if
+             * it is basic or dependent induction variable.
+             */
+            if (dvmIsBitSet(cUnit->loopAnalysis->isIndVarV,
+                            mir->ssaRep->uses[useIdx])) {
+                mir->OptimizationFlags |=
+                    MIR_IGNORE_RANGE_CHECK |  MIR_IGNORE_NULL_CHECK;
+                updateRangeCheckInfo(cUnit, mir->ssaRep->uses[refIdx],
+                                     mir->ssaRep->uses[useIdx]);
+            }
+        }
+    }
+
+    return !loopBodyCanThrow;
+}
+
+static void dumpHoistedChecks(CompilationUnit *cUnit)
+{
+    ArrayAccessInfo *arrayAccessInfo;
+    LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
+    unsigned int i;
+
+    for (i = 0; i < loopAnalysis->arrayAccessInfo->numUsed; i++) {
+        ArrayAccessInfo *arrayAccessInfo =
+            GET_ELEM_N(loopAnalysis->arrayAccessInfo,
+                       ArrayAccessInfo*, i);
+        int arrayReg = DECODE_REG(
+            dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->arrayReg));
+        int idxReg = DECODE_REG(
+            dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->ivReg));
+        LOGE("Array access %d", i);
+        LOGE("  arrayReg %d", arrayReg);
+        LOGE("  idxReg %d", idxReg);
+        LOGE("  endReg %d", loopAnalysis->endConditionReg);
+        LOGE("  maxC %d", arrayAccessInfo->maxC);
+        LOGE("  minC %d", arrayAccessInfo->minC);
+        LOGE("  opcode %d", loopAnalysis->loopBranchOpcode);
+    }
+}
+
+static void genHoistedChecks(CompilationUnit *cUnit)
+{
+    unsigned int i;
+    BasicBlock *entry = cUnit->blockList[0];
+    LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
+    ArrayAccessInfo *arrayAccessInfo;
+    int globalMaxC = 0;
+    int globalMinC = 0;
+    /* Should be loop invariant */
+    int idxReg = 0;
+
+    for (i = 0; i < loopAnalysis->arrayAccessInfo->numUsed; i++) {
+        ArrayAccessInfo *arrayAccessInfo =
+            GET_ELEM_N(loopAnalysis->arrayAccessInfo,
+                       ArrayAccessInfo*, i);
+        int arrayReg = DECODE_REG(
+            dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->arrayReg));
+        idxReg = DECODE_REG(
+            dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->ivReg));
+
+        MIR *rangeCheckMIR = dvmCompilerNew(sizeof(MIR), true);
+        rangeCheckMIR->dalvikInsn.opCode = (loopAnalysis->isCountUpLoop) ?
+            MIR_OP_NULL_N_RANGE_UP_CHECK : MIR_OP_NULL_N_RANGE_DOWN_CHECK;
+        rangeCheckMIR->dalvikInsn.vA = arrayReg;
+        rangeCheckMIR->dalvikInsn.vB = idxReg;
+        rangeCheckMIR->dalvikInsn.vC = loopAnalysis->endConditionReg;
+        rangeCheckMIR->dalvikInsn.arg[0] = arrayAccessInfo->maxC;
+        rangeCheckMIR->dalvikInsn.arg[1] = arrayAccessInfo->minC;
+        rangeCheckMIR->dalvikInsn.arg[2] = loopAnalysis->loopBranchOpcode;
+        dvmCompilerAppendMIR(entry, rangeCheckMIR);
+        if (arrayAccessInfo->maxC > globalMaxC) {
+            globalMaxC = arrayAccessInfo->maxC;
+        }
+        if (arrayAccessInfo->minC < globalMinC) {
+            globalMinC = arrayAccessInfo->minC;
+        }
+    }
+
+    if (loopAnalysis->arrayAccessInfo->numUsed != 0) {
+        if (loopAnalysis->isCountUpLoop) {
+            MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
+            boundCheckMIR->dalvikInsn.opCode = MIR_OP_LOWER_BOUND_CHECK;
+            boundCheckMIR->dalvikInsn.vA = idxReg;
+            boundCheckMIR->dalvikInsn.vB = globalMinC;
+            dvmCompilerAppendMIR(entry, boundCheckMIR);
+        } else {
+            if (loopAnalysis->loopBranchOpcode == OP_IF_LT ||
+                loopAnalysis->loopBranchOpcode == OP_IF_LE) {
+                MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
+                boundCheckMIR->dalvikInsn.opCode = MIR_OP_LOWER_BOUND_CHECK;
+                boundCheckMIR->dalvikInsn.vA = loopAnalysis->endConditionReg;
+                boundCheckMIR->dalvikInsn.vB = globalMinC;
+                /*
+                 * If the end condition is ">", add 1 back to the constant field
+                 * to reflect the fact that the smallest index value is
+                 * "endValue + constant + 1".
+                 */
+                if (loopAnalysis->loopBranchOpcode == OP_IF_LT) {
+                    boundCheckMIR->dalvikInsn.vB++;
+                }
+                dvmCompilerAppendMIR(entry, boundCheckMIR);
+            } else if (loopAnalysis->loopBranchOpcode == OP_IF_LTZ) {
+                /* Array index will fall below 0 */
+                if (globalMinC < 0) {
+                    MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
+                    boundCheckMIR->dalvikInsn.opCode = MIR_OP_PUNT;
+                    dvmCompilerAppendMIR(entry, boundCheckMIR);
+                }
+            } else if (loopAnalysis->loopBranchOpcode == OP_IF_LEZ) {
+                /* Array index will fall below 0 */
+                if (globalMinC < -1) {
+                    MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
+                    boundCheckMIR->dalvikInsn.opCode = MIR_OP_PUNT;
+                    dvmCompilerAppendMIR(entry, boundCheckMIR);
+                }
+            } else {
+                dvmAbort();
+            }
+        }
+
+    }
+}
+
+/* Main entry point to do loop optimization */
+void dvmCompilerLoopOpt(CompilationUnit *cUnit)
+{
+    int numDalvikReg = cUnit->method->registersSize;
+    LoopAnalysis *loopAnalysis = dvmCompilerNew(sizeof(LoopAnalysis), true);
+
+    assert(cUnit->blockList[0]->blockType == ENTRY_BLOCK);
+    assert(cUnit->blockList[2]->blockType == DALVIK_BYTECODE);
+    assert(cUnit->blockList[3]->blockType == EXIT_BLOCK);
+
+    cUnit->loopAnalysis = loopAnalysis;
+    /*
+     * Find live-in variables to the loop body so that we can fake their
+     * definitions in the entry block.
+     */
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerFindLiveIn);
+
+    /* Insert phi nodes to the loop body */
+    handlePhiPlacement(cUnit);
+
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion);
+    fillPhiNodeContents(cUnit);
+
+    /* Constant propagation */
+    cUnit->isConstantV = dvmAllocBitVector(cUnit->numSSARegs, false);
+    cUnit->constantValues = dvmCompilerNew(sizeof(int) * cUnit->numSSARegs,
+                                           true);
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit,
+                                          dvmCompilerDoConstantPropagation);
+    DEBUG_LOOP(dumpConstants(cUnit);)
+
+    /* Find induction variables - basic and dependent */
+    loopAnalysis->ivList = dvmCompilerNew(sizeof(GrowableList), true);
+    dvmInitGrowableList(loopAnalysis->ivList, 4);
+    loopAnalysis->isIndVarV = dvmAllocBitVector(cUnit->numSSARegs, false);
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit,
+                                          dvmCompilerFindInductionVariables);
+    DEBUG_LOOP(dumpIVList(cUnit);)
+
+    /* If the loop turns out to be non-optimizable, return early */
+    if (!isLoopOptimizable(cUnit))
+        return;
+
+    loopAnalysis->arrayAccessInfo = dvmCompilerNew(sizeof(GrowableList), true);
+    dvmInitGrowableList(loopAnalysis->arrayAccessInfo, 4);
+    loopAnalysis->bodyIsClean = doLoopBodyCodeMotion(cUnit);
+    DEBUG_LOOP(dumpHoistedChecks(cUnit);)
+
+    /*
+     * Convert the array access information into extended MIR code in the loop
+     * header.
+     */
+    genHoistedChecks(cUnit);
+}
diff --git a/vm/compiler/Loop.h b/vm/compiler/Loop.h
new file mode 100644
index 0000000..0de2baf
--- /dev/null
+++ b/vm/compiler/Loop.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DALVIK_VM_LOOP
+#define _DALVIK_VM_LOOP
+
+#include "Dalvik.h"
+#include "CompilerInternals.h"
+
+typedef struct LoopAnalysis {
+    BitVector *isIndVarV;               // length == numSSAReg
+    GrowableList *ivList;               // induction variables
+    GrowableList *arrayAccessInfo;      // hoisted checks for array accesses
+    int numBasicIV;                     // number of basic induction variables
+    int ssaBIV;                         // basic IV in SSA name
+    bool isCountUpLoop;                 // count up or down loop
+    OpCode loopBranchOpcode;            // OP_IF_XXX for the loop back branch
+    int endConditionReg;                // vB in "vA op vB"
+    LIR *branchToBody;                  // branch over to the body from entry
+    LIR *branchToPCR;                   // branch over to the PCR cell
+    bool bodyIsClean;                   // loop body cannot throw any exceptions
+} LoopAnalysis;
+
+#endif /* _DALVIK_VM_LOOP */
diff --git a/vm/compiler/Utility.c b/vm/compiler/Utility.c
index 715f750..cbfea16 100644
--- a/vm/compiler/Utility.c
+++ b/vm/compiler/Utility.c
@@ -203,10 +203,80 @@
          gDvmJit.compilerMaxQueued);
     dvmJitStats();
     dvmCompilerArchDump();
-    dvmHashForeach(gDvmJit.methodStatsTable, dumpMethodStats,
-                   &totalMethodStats);
+    if (gDvmJit.methodStatsTable) {
+        dvmHashForeach(gDvmJit.methodStatsTable, dumpMethodStats,
+                       &totalMethodStats);
+    }
     LOGD("Code size stats: %d/%d (compiled/total Dalvik), %d (native)",
          totalMethodStats.compiledDalvikSize,
          totalMethodStats.dalvikSize,
          totalMethodStats.nativeSize);
 }
+
+/*
+ * Allocate a bit vector with enough space to hold at least the specified
+ * number of bits.
+ *
+ * NOTE: this is the sister implementation of dvmAllocBitVector. In this version
+ * memory is allocated from the compiler arena.
+ */
+BitVector* dvmCompilerAllocBitVector(int startBits, bool expandable)
+{
+    BitVector* bv;
+    int count;
+
+    assert(sizeof(bv->storage[0]) == 4);        /* assuming 32-bit units */
+    assert(startBits >= 0);
+
+    bv = (BitVector*) dvmCompilerNew(sizeof(BitVector), false);
+
+    count = (startBits + 31) >> 5;
+
+    bv->storageSize = count;
+    bv->expandable = expandable;
+    bv->storage = (u4*) dvmCompilerNew(count * sizeof(u4), true);
+    return bv;
+}
+
+/*
+ * Mark the specified bit as "set".
+ *
+ * Returns "false" if the bit is outside the range of the vector and we're
+ * not allowed to expand.
+ *
+ * NOTE: this is the sister implementation of dvmSetBit. In this version
+ * memory is allocated from the compiler arena.
+ */
+bool dvmCompilerSetBit(BitVector *pBits, int num)
+{
+    assert(num >= 0);
+    if (num >= pBits->storageSize * (int)sizeof(u4) * 8) {
+        if (!pBits->expandable)
+            return false;
+
+        int newSize = (num + 31) >> 5;
+        assert(newSize > pBits->storageSize);
+        u4 *newStorage = dvmCompilerNew(newSize * sizeof(u4), false);
+        memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
+        memset(&newStorage[pBits->storageSize], 0,
+               (newSize - pBits->storageSize) * sizeof(u4));
+        pBits->storage = newStorage;
+        pBits->storageSize = newSize;
+    }
+
+    pBits->storage[num >> 5] |= 1 << (num & 0x1f);
+    return true;
+}
+
+/* FIXME */
+void dvmDebugBitVector(char *msg, const BitVector *bv, int length)
+{
+    int i;
+
+    LOGE("%s", msg);
+    for (i = 0; i < length; i++) {
+        if (dvmIsBitSet(bv, i)) {
+            LOGE("Bit %d is set", i);
+        }
+    }
+}
diff --git a/vm/compiler/codegen/CompilerCodegen.h b/vm/compiler/codegen/CompilerCodegen.h
index c9e6bd6..28e13a5 100644
--- a/vm/compiler/codegen/CompilerCodegen.h
+++ b/vm/compiler/codegen/CompilerCodegen.h
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#include "../CompilerIR.h"
-
 #ifndef _DALVIK_VM_COMPILERCODEGEN_H_
 #define _DALVIK_VM_COMPILERCODEGEN_H_
 
+#include "compiler/CompilerIR.h"
+
 /* Work unit is architecture dependent */
 bool dvmCompilerDoWork(CompilerWorkOrder *work);
 
diff --git a/vm/compiler/codegen/Optimizer.h b/vm/compiler/codegen/Optimizer.h
index 1a891b1..487e864 100644
--- a/vm/compiler/codegen/Optimizer.h
+++ b/vm/compiler/codegen/Optimizer.h
@@ -14,12 +14,20 @@
  * limitations under the License.
  */
 
-#include "Dalvik.h"
-#include "compiler/CompilerInternals.h"
-
 #ifndef _DALVIK_VM_COMPILER_OPTIMIZATION_H
 #define _DALVIK_VM_COMPILER_OPTIMIZATION_H
 
+#include "Dalvik.h"
+
+/*
+ * If the corresponding bit is set in gDvmJit.disableOpt, the selected
+ * optimization will be suppressed.
+ */
+typedef enum optControlVector {
+    kLoadStoreElimination = 0,
+    kLoadHoisting,
+} optControlVector;
+
 /* Forward declarations */
 struct CompilationUnit;
 struct LIR;
@@ -36,6 +44,8 @@
     int nativeReg;              // And the mapped native register
     int nativeRegHi;            // And the mapped native register
     bool isWide;                // Whether a pair of registers are alive
+    int fp[32];                 // Track the Dalvik register held in a SFP reg
+    int nextFP;                 // Next index for FP register allocation
 } RegisterScoreboard;
 
 void dvmCompilerApplyLocalOptimizations(struct CompilationUnit *cUnit,
diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c
index 60c5cdb..d1f9870 100644
--- a/vm/compiler/codegen/arm/ArchUtility.c
+++ b/vm/compiler/codegen/arm/ArchUtility.c
@@ -79,9 +79,20 @@
                 strcpy(tbuf, "!");
             } else {
                assert(fmt < fmtEnd);
-               assert((unsigned)(nc-'0') < 3);
+               assert((unsigned)(nc-'0') < 4);
                operand = lir->operands[nc-'0'];
                switch(*fmt++) {
+                   case 'b':
+                       strcpy(tbuf,"0000");
+                       for (i=3; i>= 0; i--) {
+                           tbuf[i] += operand & 1;
+                           operand >>= 1;
+                       }
+                       break;
+                   case 'n':
+                       operand = ~expandImmediate(operand);
+                       sprintf(tbuf,"%d [0x%x]", operand, operand);
+                       break;
                    case 'm':
                        operand = expandImmediate(operand);
                        sprintf(tbuf,"%d [0x%x]", operand, operand);
@@ -99,9 +110,6 @@
                    case 'd':
                        sprintf(tbuf,"%d", operand);
                        break;
-                   case 'D':
-                       sprintf(tbuf,"%d", operand+8);
-                       break;
                    case 'E':
                        sprintf(tbuf,"%d", operand*4);
                        break;
@@ -111,28 +119,28 @@
                    case 'c':
                        switch (operand) {
                            case ARM_COND_EQ:
-                               strcpy(tbuf, "beq");
+                               strcpy(tbuf, "eq");
                                break;
                            case ARM_COND_NE:
-                               strcpy(tbuf, "bne");
+                               strcpy(tbuf, "ne");
                                break;
                            case ARM_COND_LT:
-                               strcpy(tbuf, "blt");
+                               strcpy(tbuf, "lt");
                                break;
                            case ARM_COND_GE:
-                               strcpy(tbuf, "bge");
+                               strcpy(tbuf, "ge");
                                break;
                            case ARM_COND_GT:
-                               strcpy(tbuf, "bgt");
+                               strcpy(tbuf, "gt");
                                break;
                            case ARM_COND_LE:
-                               strcpy(tbuf, "ble");
+                               strcpy(tbuf, "le");
                                break;
                            case ARM_COND_CS:
-                               strcpy(tbuf, "bcs");
+                               strcpy(tbuf, "cs");
                                break;
                            case ARM_COND_MI:
-                               strcpy(tbuf, "bmi");
+                               strcpy(tbuf, "mi");
                                break;
                            default:
                                strcpy(tbuf, "");
@@ -182,8 +190,49 @@
     *buf = 0;
 }
 
+void dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
+{
+    char buf[256];
+    buf[0] = 0;
+    ArmLIR *armLIR = (ArmLIR *) lir;
+
+    if (mask == ENCODE_ALL) {
+        strcpy(buf, "all");
+    } else {
+        char num[8];
+        int i;
+
+        for (i = 0; i < kRegEnd; i++) {
+            if (mask & (1ULL << i)) {
+                sprintf(num, "%d ", i);
+                strcat(buf, num);
+            }
+        }
+
+        if (mask & ENCODE_CCODE) {
+            strcat(buf, "cc ");
+        }
+        if (mask & ENCODE_FP_STATUS) {
+            strcat(buf, "fpcc ");
+        }
+        if (armLIR && (mask & ENCODE_DALVIK_REG)) {
+            sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
+                    (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
+        }
+    }
+    if (buf[0]) {
+        LOGD("%s: %s", prefix, buf);
+    }
+}
+
+/*
+ * Debugging macros
+ */
+#define DUMP_RESOURCE_MASK(X)
+#define DUMP_SSA_REP(X)
+
 /* Pretty-print a LIR instruction */
-static void dumpLIRInsn(LIR *arg, unsigned char *baseAddr)
+void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr)
 {
     ArmLIR *lir = (ArmLIR *) arg;
     char buf[256];
@@ -191,10 +240,23 @@
     int offset = lir->generic.offset;
     int dest = lir->operands[0];
     u2 *cPtr = (u2*)baseAddr;
+    const bool dumpNop = false;
+
     /* Handle pseudo-ops individually, and all regular insns as a group */
     switch(lir->opCode) {
+        case ARM_PSEUDO_BARRIER:
+            LOGD("-------- BARRIER");
+            break;
+        case ARM_PSEUDO_EXTENDED_MIR:
+            /* intentional fallthrough */
+        case ARM_PSEUDO_SSA_REP:
+            DUMP_SSA_REP(LOGD("-------- %s\n", (char *) dest));
+            break;
         case ARM_PSEUDO_TARGET_LABEL:
             break;
+        case ARM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH:
+            LOGD("-------- chaining cell (backward branch): 0x%04x\n", dest);
+            break;
         case ARM_PSEUDO_CHAINING_CELL_NORMAL:
             LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
             break;
@@ -209,10 +271,16 @@
                  ((Method *)dest)->name,
                  ((Method *)dest)->insns);
             break;
+        case ARM_PSEUDO_ENTRY_BLOCK:
+            LOGD("-------- entry offset: 0x%04x\n", dest);
+            break;
         case ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY:
             LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
                    getOpcodeName(lir->operands[1]));
             break;
+        case ARM_PSEUDO_EXIT_BLOCK:
+            LOGD("-------- exit offset: 0x%04x\n", dest);
+            break;
         case ARM_PSEUDO_ALIGN4:
             LOGD("%p (%04x): .align4\n", baseAddr + offset, offset);
             break;
@@ -230,17 +298,27 @@
             LOGD("L%#06x:\n", dest);
             break;
         default:
-            if (lir->isNop) {
+            if (lir->isNop && !dumpNop) {
                 break;
             }
             buildInsnString(EncodingMap[lir->opCode].name, lir, opName,
                             baseAddr, 256);
             buildInsnString(EncodingMap[lir->opCode].fmt, lir, buf, baseAddr,
                             256);
-            LOGD("%p (%04x): %-8s%s\n",
-                 baseAddr + offset, offset, opName, buf);
+            LOGD("%p (%04x): %-8s%s%s\n",
+                 baseAddr + offset, offset, opName, buf,
+                 lir->isNop ? "(nop)" : "");
             break;
     }
+
+    if (lir->useMask && (!lir->isNop || dumpNop)) {
+        DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
+                                               lir->useMask, "use"));
+    }
+    if (lir->defMask && (!lir->isNop || dumpNop)) {
+        DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
+                                               lir->defMask, "def"));
+    }
 }
 
 /* Dump instructions and constant pool contents */
@@ -253,12 +331,13 @@
     LOGD("installed code is at %p\n", cUnit->baseAddr);
     LOGD("total size is %d bytes\n", cUnit->totalSize);
     for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
-        dumpLIRInsn(lirInsn, cUnit->baseAddr);
+        dvmDumpLIRInsn(lirInsn, cUnit->baseAddr);
     }
     for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
         armLIR = (ArmLIR *) lirInsn;
         LOGD("%p (%04x): .word (0x%x)\n",
-             (char*)cUnit->baseAddr + armLIR->generic.offset, armLIR->generic.offset,
+             (char*)cUnit->baseAddr + armLIR->generic.offset,
+             armLIR->generic.offset,
              armLIR->operands[0]);
     }
 }
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
index 59c7529..8fedda2 100644
--- a/vm/compiler/codegen/arm/ArmLIR.h
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -27,7 +27,7 @@
  * r6 (rGLUE) is reserved [holds current &interpState]
  * r7 (rINST) is scratch for Jit
  * r8 (rIBASE) is scratch for Jit, but must be restored when resuming interp
- * r9 is always scratch
+ * r9 is reserved
  * r10 is always scratch
  * r11 (fp) used by gcc unless -fomit-frame-pointer set [available for jit?]
  * r12 is always scratch
@@ -35,21 +35,30 @@
  * r14 (lr) is scratch for Jit
  * r15 (pc) is reserved
  *
+ * Preserved across C calls: r4, r5, r6, r7, r8, r10, r11
+ * Trashed across C calls: r0, r1, r2, r3, r12, r14
+ *
+ * Floating pointer registers
+ * s0-s31
+ * d0-d15, where d0={s0,s1}, d1={s2,s3}, ... , d15={s30,s31}
+ *
+ * s16-s31 (d8-d15) preserved across C calls
+ * s0-s15 (d0-d7) trashed across C calls
+ *
  * For Thumb code use:
- *       r0, r1, r2, r3 to hold operands/results via scoreboard
+ *       r0, r1, r2, r3 to hold operands/results
  *       r4, r7 for temps
  *
  * For Thumb2 code use:
- *       r0, r1, r2, r3, r8, r9, r10, r11 for operands/results via scoreboard
- *       r4, r7, r14 for temps
+ *       r0, r1, r2, r3, r8, r9, r10, r11, r12, r14 for operands/results
+ *       r4, r7 for temps
+ *       s16-s31/d8-d15 for operands/results
+ *       s0-s15/d0-d7 for temps
  *
  * When transitioning from code cache to interp:
  *       restore rIBASE
  *       restore rPC
- *       restore r11 (fp)?
- *
- * Double precision values are stored in consecutive single precision registers
- * such that dr0 -> (sr0,sr1), dr1 -> (sr2,sr3) ... dr16 -> (sr30,sr31)
+ *       restore r11?
  */
 
 /* Offset to distingish FP regs */
@@ -57,15 +66,87 @@
 /* Offset to distinguish DP FP regs */
 #define FP_DOUBLE 64
 /* Reg types */
+#define REGTYPE(x) (x & (FP_REG_OFFSET | FP_DOUBLE))
 #define FPREG(x) ((x & FP_REG_OFFSET) == FP_REG_OFFSET)
 #define LOWREG(x) ((x & 0x7) == x)
 #define DOUBLEREG(x) ((x & FP_DOUBLE) == FP_DOUBLE)
 #define SINGLEREG(x) (FPREG(x) && !DOUBLEREG(x))
 /* Mask to strip off fp flags */
 #define FP_REG_MASK (FP_REG_OFFSET-1)
-/* Mask to convert high reg to low for Thumb */
-#define THUMB_REG_MASK 0x7
+/* non-existent Dalvik register */
+#define vNone   (-1)
+/* non-existant physical register */
+#define rNone   (-1)
 
+typedef enum ResourceEncodingPos {
+    kGPReg0     = 0,
+    kRegSP      = 13,
+    kRegLR      = 14,
+    kRegPC      = 15,
+    kFPReg0     = 16,
+    kRegEnd     = 48,
+    kCCode      = kRegEnd,
+    kFPStatus,
+    kDalvikReg,
+} ResourceEncodingPos;
+
+#define ENCODE_REG_LIST(N)      ((u8) N)
+#define ENCODE_REG_SP           (1ULL << kRegSP)
+#define ENCODE_REG_LR           (1ULL << kRegLR)
+#define ENCODE_REG_PC           (1ULL << kRegPC)
+#define ENCODE_CCODE            (1ULL << kCCode)
+#define ENCODE_FP_STATUS        (1ULL << kFPStatus)
+#define ENCODE_DALVIK_REG       (1ULL << kDalvikReg)
+#define ENCODE_ALL              (~0ULL)
+
+#define DECODE_ALIAS_INFO_REG(X)        (X & 0xffff)
+#define DECODE_ALIAS_INFO_WIDE(X)       ((X & 0x80000000) ? 1 : 0)
+
+typedef enum OpSize {
+    WORD,
+    LONG,
+    SINGLE,
+    DOUBLE,
+    UNSIGNED_HALF,
+    SIGNED_HALF,
+    UNSIGNED_BYTE,
+    SIGNED_BYTE,
+} OpSize;
+
+typedef enum OpKind {
+    OP_MOV,
+    OP_MVN,
+    OP_CMP,
+    OP_LSL,
+    OP_LSR,
+    OP_ASR,
+    OP_ROR,
+    OP_NOT,
+    OP_AND,
+    OP_OR,
+    OP_XOR,
+    OP_NEG,
+    OP_ADD,
+    OP_ADC,
+    OP_SUB,
+    OP_SBC,
+    OP_RSUB,
+    OP_MUL,
+    OP_DIV,
+    OP_REM,
+    OP_BIC,
+    OP_CMN,
+    OP_TST,
+    OP_BKPT,
+    OP_BLX,
+    OP_PUSH,
+    OP_POP,
+    OP_2CHAR,
+    OP_2SHORT,
+    OP_2BYTE,
+    OP_COND_BR,
+    OP_UNCOND_BR,
+} OpKind;
 
 typedef enum NativeRegisterPool {
     r0 = 0,
@@ -138,12 +219,20 @@
 typedef enum ArmConditionCode {
     ARM_COND_EQ = 0x0,    /* 0000 */
     ARM_COND_NE = 0x1,    /* 0001 */
-    ARM_COND_LT = 0xb,    /* 1011 */
+    ARM_COND_CS = 0x2,    /* 0010 */
+    ARM_COND_CC = 0x3,    /* 0011 */
+    ARM_COND_MI = 0x4,    /* 0100 */
+    ARM_COND_PL = 0x5,    /* 0101 */
+    ARM_COND_VS = 0x6,    /* 0110 */
+    ARM_COND_VC = 0x7,    /* 0111 */
+    ARM_COND_HI = 0x8,    /* 1000 */
+    ARM_COND_LS = 0x9,    /* 1001 */
     ARM_COND_GE = 0xa,    /* 1010 */
+    ARM_COND_LT = 0xb,    /* 1011 */
     ARM_COND_GT = 0xc,    /* 1100 */
     ARM_COND_LE = 0xd,    /* 1101 */
-    ARM_COND_CS = 0x2,    /* 0010 */
-    ARM_COND_MI = 0x4,    /* 0100 */
+    ARM_COND_AL = 0xe,    /* 1110 */
+    ARM_COND_NV = 0xf,    /* 1111 */
 } ArmConditionCode;
 
 #define isPseudoOpCode(opCode) ((int)(opCode) < 0)
@@ -154,7 +243,13 @@
  * Assemble.c.
  */
 typedef enum ArmOpCode {
-    ARM_PSEUDO_TARGET_LABEL = -11,
+    ARM_PSEUDO_BARRIER = -17,
+    ARM_PSEUDO_EXTENDED_MIR = -16,
+    ARM_PSEUDO_SSA_REP = -15,
+    ARM_PSEUDO_ENTRY_BLOCK = -14,
+    ARM_PSEUDO_EXIT_BLOCK = -13,
+    ARM_PSEUDO_TARGET_LABEL = -12,
+    ARM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH = -11,
     ARM_PSEUDO_CHAINING_CELL_HOT = -10,
     ARM_PSEUDO_CHAINING_CELL_INVOKE_PREDICTED = -9,
     ARM_PSEUDO_CHAINING_CELL_INVOKE_SINGLETON = -8,
@@ -167,7 +262,7 @@
     ARM_PSEUDO_NORMAL_BLOCK_LABEL = -1,
     /************************************************************************/
     ARM_16BIT_DATA,       /* DATA   [0] rd[15..0] */
-    THUMB_ADC,            /* adc     [0100000101] rm[5..3] rd[2..0] */
+    THUMB_ADC_RR,         /* adc     [0100000101] rm[5..3] rd[2..0] */
     THUMB_ADD_RRI3,       /* add(1)  [0001110] imm_3[8..6] rn[5..3] rd[2..0]*/
     THUMB_ADD_RI8,        /* add(2)  [00110] rd[10..8] imm_8[7..0] */
     THUMB_ADD_RRR,        /* add(3)  [0001100] rm[8..6] rn[5..3] rd[2..0] */
@@ -178,25 +273,25 @@
     THUMB_ADD_SP_REL,     /* add(6)  [10101] rd[10..8] imm_8[7..0] */
     THUMB_ADD_SPI7,       /* add(7)  [101100000] imm_7[6..0] */
     THUMB_AND_RR,         /* and     [0100000000] rm[5..3] rd[2..0] */
-    THUMB_ASR,            /* asr(1)  [00010] imm_5[10..6] rm[5..3] rd[2..0] */
-    THUMB_ASRV,           /* asr(2)  [0100000100] rs[5..3] rd[2..0] */
+    THUMB_ASR_RRI5,       /* asr(1)  [00010] imm_5[10..6] rm[5..3] rd[2..0] */
+    THUMB_ASR_RR,         /* asr(2)  [0100000100] rs[5..3] rd[2..0] */
     THUMB_B_COND,         /* b(1)    [1101] cond[11..8] offset_8[7..0] */
     THUMB_B_UNCOND,       /* b(2)    [11100] offset_11[10..0] */
-    THUMB_BIC,            /* bic     [0100001110] rm[5..3] rd[2..0] */
+    THUMB_BIC_RR,         /* bic     [0100001110] rm[5..3] rd[2..0] */
     THUMB_BKPT,           /* bkpt    [10111110] imm_8[7..0] */
     THUMB_BLX_1,          /* blx(1)  [111] H[10] offset_11[10..0] */
     THUMB_BLX_2,          /* blx(1)  [111] H[01] offset_11[10..0] */
     THUMB_BL_1,           /* blx(1)  [111] H[10] offset_11[10..0] */
     THUMB_BL_2,           /* blx(1)  [111] H[11] offset_11[10..0] */
-    THUMB_BLX_R,          /* blx(2)  [010001111] H2[6..6] rm[5..3] SBZ[000] */
+    THUMB_BLX_R,          /* blx(2)  [010001111] rm[6..3] [000] */
     THUMB_BX,             /* bx      [010001110] H2[6..6] rm[5..3] SBZ[000] */
-    THUMB_CMN,            /* cmn     [0100001011] rm[5..3] rd[2..0] */
+    THUMB_CMN_RR,         /* cmn     [0100001011] rm[5..3] rd[2..0] */
     THUMB_CMP_RI8,        /* cmp(1)  [00101] rn[10..8] imm_8[7..0] */
     THUMB_CMP_RR,         /* cmp(2)  [0100001010] rm[5..3] rd[2..0] */
     THUMB_CMP_LH,         /* cmp(3)  [01000101] H12[01] rm[5..3] rd[2..0] */
     THUMB_CMP_HL,         /* cmp(3)  [01000110] H12[10] rm[5..3] rd[2..0] */
     THUMB_CMP_HH,         /* cmp(3)  [01000111] H12[11] rm[5..3] rd[2..0] */
-    THUMB_EOR,            /* eor     [0100000001] rm[5..3] rd[2..0] */
+    THUMB_EOR_RR,         /* eor     [0100000001] rm[5..3] rd[2..0] */
     THUMB_LDMIA,          /* ldmia   [11001] rn[10..8] reglist [7..0] */
     THUMB_LDR_RRI5,       /* ldr(1)  [01101] imm_5[10..6] rn[5..3] rd[2..0] */
     THUMB_LDR_RRR,        /* ldr(2)  [0101100] rm[8..6] rn[5..3] rd[2..0] */
@@ -208,10 +303,10 @@
     THUMB_LDRH_RRR,       /* ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0] */
     THUMB_LDRSB_RRR,      /* ldrsb   [0101011] rm[8..6] rn[5..3] rd[2..0] */
     THUMB_LDRSH_RRR,      /* ldrsh   [0101111] rm[8..6] rn[5..3] rd[2..0] */
-    THUMB_LSL,            /* lsl(1)  [00000] imm_5[10..6] rm[5..3] rd[2..0] */
-    THUMB_LSLV,           /* lsl(2)  [0100000010] rs[5..3] rd[2..0] */
-    THUMB_LSR,            /* lsr(1)  [00001] imm_5[10..6] rm[5..3] rd[2..0] */
-    THUMB_LSRV,           /* lsr(2)  [0100000011] rs[5..3] rd[2..0] */
+    THUMB_LSL_RRI5,       /* lsl(1)  [00000] imm_5[10..6] rm[5..3] rd[2..0] */
+    THUMB_LSL_RR,         /* lsl(2)  [0100000010] rs[5..3] rd[2..0] */
+    THUMB_LSR_RRI5,       /* lsr(1)  [00001] imm_5[10..6] rm[5..3] rd[2..0] */
+    THUMB_LSR_RR,         /* lsr(2)  [0100000011] rs[5..3] rd[2..0] */
     THUMB_MOV_IMM,        /* mov(1)  [00100] rd[10..8] imm_8[7..0] */
     THUMB_MOV_RR,         /* mov(2)  [0001110000] rn[5..3] rd[2..0] */
     THUMB_MOV_RR_H2H,     /* mov(3)  [01000111] H12[11] rm[5..3] rd[2..0] */
@@ -223,7 +318,7 @@
     THUMB_ORR,            /* orr     [0100001100] rm[5..3] rd[2..0] */
     THUMB_POP,            /* pop     [1011110] r[8..8] rl[7..0] */
     THUMB_PUSH,           /* push    [1011010] r[8..8] rl[7..0] */
-    THUMB_ROR,            /* ror     [0100000111] rs[5..3] rd[2..0] */
+    THUMB_ROR_RR,         /* ror     [0100000111] rs[5..3] rd[2..0] */
     THUMB_SBC,            /* sbc     [0100000110] rm[5..3] rd[2..0] */
     THUMB_STMIA,          /* stmia   [11000] rn[10..8] reglist [7.. 0] */
     THUMB_STR_RRI5,       /* str(1)  [01100] imm_5[10..6] rn[5..3] rd[2..0] */
@@ -291,32 +386,208 @@
                                        rn[19..16] rt[15..12] [1100] imm[7..0]*/
     THUMB2_LDR_RRI8_PREDEC, /* ldr(Imm,T4) rd,[rn,#-imm8] [111110000101]
                                        rn[19..16] rt[15..12] [1100] imm[7..0]*/
-    THUMB2_CBNZ,            /* cbnz rd,<label> [101110] i [1] imm5[7..3]
+    THUMB2_CBNZ,          /* cbnz rd,<label> [101110] i [1] imm5[7..3]
                                        rn[2..0] */
-    THUMB2_CBZ,             /* cbn rd,<label> [101100] i [1] imm5[7..3]
+    THUMB2_CBZ,           /* cbn rd,<label> [101100] i [1] imm5[7..3]
                                        rn[2..0] */
-    THUMB2_ADD_RRI12,       /* add rd, rn, #imm12 [11110] i [100000] rn[19..16]
+    THUMB2_ADD_RRI12,     /* add rd, rn, #imm12 [11110] i [100000] rn[19..16]
                                        [0] imm3[14..12] rd[11..8] imm8[7..0] */
-    THUMB2_MOV_RR,          /* mov rd, rm [11101010010011110000] rd[11..8]
+    THUMB2_MOV_RR,        /* mov rd, rm [11101010010011110000] rd[11..8]
                                        [0000] rm[3..0] */
-    THUMB2_VMOVS,           /* vmov.f32 vd, vm [111011101] D [110000]
+    THUMB2_VMOVS,         /* vmov.f32 vd, vm [111011101] D [110000]
                                        vd[15..12] 101001] M [0] vm[3..0] */
-    THUMB2_VMOVD,           /* vmov.f64 vd, vm [111011101] D [110000]
+    THUMB2_VMOVD,         /* vmov.f64 vd, vm [111011101] D [110000]
                                        vd[15..12] 101101] M [0] vm[3..0] */
+    THUMB2_LDMIA,         /* ldmia  [111010001001[ rn[19..16] mask[15..0] */
+    THUMB2_STMIA,         /* stmia  [111010001000[ rn[19..16] mask[15..0] */
+    THUMB2_ADD_RRR,       /* add [111010110000] rn[19..16] [0000] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_SUB_RRR,       /* sub [111010111010] rn[19..16] [0000] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_SBC_RRR,       /* sbc [111010110110] rn[19..16] [0000] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_CMP_RR,        /* cmp [111010111011] rn[19..16] [0000] [1111]
+                                   [0000] rm[3..0] */
+    THUMB2_SUB_RRI12,     /* sub rd, rn, #imm12 [11110] i [01010] rn[19..16]
+                                       [0] imm3[14..12] rd[11..8] imm8[7..0] */
+    THUMB2_MVN_IMM_SHIFT, /* mov(T2) rd, #<const> [11110] i [00011011110]
+                                       imm3 rd[11..8] imm8 */
+    THUMB2_SEL,           /* sel rd, rn, rm [111110101010] rn[19-16] rd[11-8]
+                                       rm[3-0] */
+    THUMB2_UBFX,          /* ubfx rd,rn,#lsb,#width [111100111100] rn[19..16]
+                                       [0] imm3[14-12] rd[11-8] w[4-0] */
+    THUMB2_SBFX,          /* ubfx rd,rn,#lsb,#width [111100110100] rn[19..16]
+                                       [0] imm3[14-12] rd[11-8] w[4-0] */
+    THUMB2_LDR_RRR,       /* ldr rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+                                       rt[15-12] [000000] imm[5-4] rm[3-0] */
+    THUMB2_LDRH_RRR,      /* ldrh rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+                                       rt[15-12] [000000] imm[5-4] rm[3-0] */
+    THUMB2_LDRSH_RRR,     /* ldrsh rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+                                       rt[15-12] [000000] imm[5-4] rm[3-0] */
+    THUMB2_LDRB_RRR,      /* ldrb rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+                                       rt[15-12] [000000] imm[5-4] rm[3-0] */
+    THUMB2_LDRSB_RRR,     /* ldrsb rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+                                       rt[15-12] [000000] imm[5-4] rm[3-0] */
+    THUMB2_STR_RRR,       /* str rt,[rn,rm,LSL #imm] [111110000100] rn[19-16]
+                                       rt[15-12] [000000] imm[5-4] rm[3-0] */
+    THUMB2_STRH_RRR,      /* str rt,[rn,rm,LSL #imm] [111110000010] rn[19-16]
+                                       rt[15-12] [000000] imm[5-4] rm[3-0] */
+    THUMB2_STRB_RRR,      /* str rt,[rn,rm,LSL #imm] [111110000000] rn[19-16]
+                                       rt[15-12] [000000] imm[5-4] rm[3-0] */
+    THUMB2_LDRH_RRI12,    /* ldrh rt,[rn,#imm12] [111110001011]
+                                       rt[15..12] rn[19..16] imm12[11..0] */
+    THUMB2_LDRSH_RRI12,   /* ldrsh rt,[rn,#imm12] [111110011011]
+                                       rt[15..12] rn[19..16] imm12[11..0] */
+    THUMB2_LDRB_RRI12,    /* ldrb rt,[rn,#imm12] [111110001001]
+                                       rt[15..12] rn[19..16] imm12[11..0] */
+    THUMB2_LDRSB_RRI12,   /* ldrsb rt,[rn,#imm12] [111110011001]
+                                       rt[15..12] rn[19..16] imm12[11..0] */
+    THUMB2_STRH_RRI12,    /* strh rt,[rn,#imm12] [111110001010]
+                                       rt[15..12] rn[19..16] imm12[11..0] */
+    THUMB2_STRB_RRI12,    /* strb rt,[rn,#imm12] [111110001000]
+                                       rt[15..12] rn[19..16] imm12[11..0] */
+    THUMB2_POP,           /* pop     [1110100010111101] list[15-0]*/
+    THUMB2_PUSH,          /* push    [1110100010101101] list[15-0]*/
+    THUMB2_CMP_RI8,       /* cmp rn, #<const> [11110] i [011011] rn[19-16] [0]
+                                       imm3 [1111] imm8[7..0] */
+    THUMB2_ADC_RRR,       /* adc [111010110101] rn[19..16] [0000] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_AND_RRR,       /* and [111010100000] rn[19..16] [0000] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_BIC_RRR,       /* bic [111010100010] rn[19..16] [0000] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_CMN_RR,        /* cmn [111010110001] rn[19..16] [0000] [1111]
+                                   [0000] rm[3..0] */
+    THUMB2_EOR_RRR,       /* eor [111010101000] rn[19..16] [0000] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_MUL_RRR,       /* mul [111110110000] rn[19..16] [1111] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_MVN_RR,        /* mvn [11101010011011110] rd[11-8] [0000]
+                                   rm[3..0] */
+    THUMB2_RSUB_RRI8,     /* rsub [111100011100] rn[19..16] [0000] rd[11..8]
+                                   imm8[7..0] */
+    THUMB2_NEG_RR,        /* actually rsub rd, rn, #0 */
+    THUMB2_ORR_RRR,       /* orr [111010100100] rn[19..16] [0000] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_TST_RR,        /* tst [111010100001] rn[19..16] [0000] [1111]
+                                   [0000] rm[3..0] */
+    THUMB2_LSL_RRR,       /* lsl [111110100000] rn[19..16] [1111] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_LSR_RRR,       /* lsr [111110100010] rn[19..16] [1111] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_ASR_RRR,       /* asr [111110100100] rn[19..16] [1111] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_ROR_RRR,       /* ror [111110100110] rn[19..16] [1111] rd[11..8]
+                                   [0000] rm[3..0] */
+    THUMB2_LSL_RRI5,      /* lsl [11101010010011110] imm[14.12] rd[11..8]
+                                   [00] rm[3..0] */
+    THUMB2_LSR_RRI5,      /* lsr [11101010010011110] imm[14.12] rd[11..8]
+                                   [01] rm[3..0] */
+    THUMB2_ASR_RRI5,      /* asr [11101010010011110] imm[14.12] rd[11..8]
+                                   [10] rm[3..0] */
+    THUMB2_ROR_RRI5,      /* ror [11101010010011110] imm[14.12] rd[11..8]
+                                   [11] rm[3..0] */
+    THUMB2_BIC_RRI8,      /* bic [111100000010] rn[19..16] [0] imm3
+                                   rd[11..8] imm8 */
+    THUMB2_AND_RRI8,      /* bic [111100000000] rn[19..16] [0] imm3
+                                   rd[11..8] imm8 */
+    THUMB2_ORR_RRI8,      /* orr [111100000100] rn[19..16] [0] imm3
+                                   rd[11..8] imm8 */
+    THUMB2_EOR_RRI8,      /* eor [111100001000] rn[19..16] [0] imm3
+                                   rd[11..8] imm8 */
+    THUMB2_ADD_RRI8,      /* add [111100001000] rn[19..16] [0] imm3
+                                   rd[11..8] imm8 */
+    THUMB2_ADC_RRI8,      /* adc [111100010101] rn[19..16] [0] imm3
+                                   rd[11..8] imm8 */
+    THUMB2_SUB_RRI8,      /* sub [111100011011] rn[19..16] [0] imm3
+                                   rd[11..8] imm8 */
+    THUMB2_SBC_RRI8,      /* sbc [111100010111] rn[19..16] [0] imm3
+                                   rd[11..8] imm8 */
+    THUMB2_IT,            /* it [10111111] firstcond[7-4] mask[3-0] */
+    THUMB2_FMSTAT,        /* fmstat [11101110111100011111101000010000] */
+    THUMB2_VCMPD,         /* vcmp [111011101] D [11011] rd[15-12] [1011]
+                                   E [1] M [0] rm[3-0] */
+    THUMB2_VCMPS,         /* vcmp [111011101] D [11010] rd[15-12] [1011]
+                                   E [1] M [0] rm[3-0] */
+    THUMB2_LDR_PC_REL12,  /* ldr rd,[pc,#imm12] [1111100011011111] rt[15-12]
+                                     imm12[11-0] */
+    THUMB2_B_COND,        /* b<c> [1110] S cond[25-22] imm6[21-16] [10]
+                                  J1 [0] J2 imm11[10..0] */
+    THUMB2_VMOVD_RR,      /* vmov [111011101] D [110000] vd[15-12 [101101]
+                                  M [0] vm[3-0] */
+    THUMB2_VMOVS_RR,      /* vmov [111011101] D [110000] vd[15-12 [101001]
+                                  M [0] vm[3-0] */
+    THUMB2_FMRS,          /* vmov [111011100000] vn[19-16] rt[15-12] [1010]
+                                  N [0010000] */
+    THUMB2_FMSR,          /* vmov [111011100001] vn[19-16] rt[15-12] [1010]
+                                  N [0010000] */
+    THUMB2_FMRRD,         /* vmov [111011000100] rt2[19-16] rt[15-12]
+                                  [101100] M [1] vm[3-0] */
+    THUMB2_FMDRR,         /* vmov [111011000101] rt2[19-16] rt[15-12]
+                                  [101100] M [1] vm[3-0] */
+
     ARM_LAST,
 } ArmOpCode;
 
 /* Bit flags describing the behavior of each native opcode */
 typedef enum ArmOpFeatureFlags {
-    IS_BRANCH =           1 << 1,
-    CLOBBER_DEST =        1 << 2,
-    CLOBBER_SRC1 =        1 << 3,
-    NO_OPERAND =          1 << 4,
-    IS_UNARY_OP =         1 << 5,
-    IS_BINARY_OP =        1 << 6,
-    IS_TERTIARY_OP =      1 << 7,
+    kIsBranch = 0,
+    kRegDef0,
+    kRegDef1,
+    kRegDefSP,
+    kRegDefLR,
+    kRegDefList0,
+    kRegDefList1,
+    kRegUse0,
+    kRegUse1,
+    kRegUse2,
+    kRegUseSP,
+    kRegUsePC,
+    kRegUseList0,
+    kRegUseList1,
+    kNoOperand,
+    kIsUnaryOp,
+    kIsBinaryOp,
+    kIsTertiaryOp,
+    kIsQuadOp,
+    kIsIT,
+    kSetsCCodes,
+    kUsesCCodes,
 } ArmOpFeatureFlags;
 
+#define IS_BRANCH       (1 << kIsBranch)
+#define REG_DEF0        (1 << kRegDef0)
+#define REG_DEF1        (1 << kRegDef1)
+#define REG_DEF_SP      (1 << kRegDefSP)
+#define REG_DEF_LR      (1 << kRegDefLR)
+#define REG_DEF_LIST0   (1 << kRegDefList0)
+#define REG_DEF_LIST1   (1 << kRegDefList1)
+#define REG_USE0        (1 << kRegUse0)
+#define REG_USE1        (1 << kRegUse1)
+#define REG_USE2        (1 << kRegUse2)
+#define REG_USE_SP      (1 << kRegUseSP)
+#define REG_USE_PC      (1 << kRegUsePC)
+#define REG_USE_LIST0   (1 << kRegUseList0)
+#define REG_USE_LIST1   (1 << kRegUseList1)
+#define NO_OPERAND      (1 << kNoOperand)
+#define IS_UNARY_OP     (1 << kIsUnaryOp)
+#define IS_BINARY_OP    (1 << kIsBinaryOp)
+#define IS_TERTIARY_OP  (1 << kIsTertiaryOp)
+#define IS_QUAD_OP      (1 << kIsQuadOp)
+#define IS_IT           (1 << kIsIT)
+#define SETS_CCODES     (1 << kSetsCCodes)
+#define USES_CCODES     (1 << kUsesCCodes)
+
+/* Common combo register usage patterns */
+#define REG_USE01       (REG_USE0 | REG_USE1)
+#define REG_USE012      (REG_USE01 | REG_USE2)
+#define REG_USE12       (REG_USE1 | REG_USE2)
+#define REG_DEF0_USE0   (REG_DEF0 | REG_USE0)
+#define REG_DEF0_USE1   (REG_DEF0 | REG_USE1)
+#define REG_DEF0_USE01  (REG_DEF0 | REG_USE01)
+#define REG_DEF0_USE12  (REG_DEF0 | REG_USE12)
+#define REG_DEF01_USE2  (REG_DEF0 | REG_DEF1 | REG_USE2)
+
 /* Instruction assembly fieldLoc kind */
 typedef enum ArmEncodingKind {
     UNUSED,
@@ -327,6 +598,11 @@
     IMM16,         /* Zero-extended immediate using [26,19..16,14..12,7..0] */
     IMM6,          /* Encoded branch target using [9,7..3]0 */
     IMM12,         /* Zero-extended immediate using [26,14..12,7..0] */
+    SHIFT,         /* Shift descriptor, [14..12,7..4] */
+    LSB,           /* least significant bit using [14..12][7..6] */
+    BWIDTH,        /* bit-field width, encoded as width-1 */
+    SHIFT5,        /* Shift count, [14..12,7..6] */
+    BROFFSET,      /* Signed extended [26,11,13,21-16,10-0]:0 */
 } ArmEncodingKind;
 
 /* Struct used to define the snippet positions for each Thumb opcode */
@@ -336,7 +612,7 @@
         ArmEncodingKind kind;
         int end;   /* end for BITBLT, 1-bit slice end for FP regs */
         int start; /* start for BITBLT, 4-bit slice end for FP regs */
-    } fieldLoc[3];
+    } fieldLoc[4];
     ArmOpCode opCode;
     int flags;
     char *name;
@@ -349,15 +625,27 @@
 /*
  * Each instance of this struct holds a pseudo or real LIR instruction:
  * - pesudo ones (eg labels and marks) and will be discarded by the assembler.
- * - real ones will e assembled into Thumb instructions.
+ * - real ones will be assembled into Thumb instructions.
+ *
+ * Machine resources are encoded into a 64-bit vector, where the encodings are
+ * as following:
+ * - [ 0..15]: general purpose registers including PC, SP, and LR
+ * - [16..47]: floating-point registers where d0 is expanded to s[01] and s0
+ *   starts at bit 16
+ * - [48]: IT block
+ * - [49]: integer condition code
+ * - [50]: floatint-point status word
  */
 typedef struct ArmLIR {
     LIR generic;
     ArmOpCode opCode;
-    int operands[3];    // [0..2] = [dest, src1, src2]
+    int operands[4];    // [0..3] = [dest, src1, src2, extra]
     bool isNop;         // LIR is optimized away
     int age;            // default is 0, set lazily by the optimizer
     int size;           // 16-bit unit size (1 for thumb, 1 or 2 for thumb2)
+    int aliasInfo;      // For Dalvik register access disambiguation
+    u8 useMask;         // Resource mask for use
+    u8 defMask;         // Resource mask for def
 } ArmLIR;
 
 /* Chain cell for predicted method invocation */
@@ -392,4 +680,6 @@
 
 #define CHAIN_CELL_OFFSET_TAG   0xcdab
 
+ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+
 #endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMLIR_H */
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index ea133e7..e386fac 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -39,9 +39,9 @@
  * fmt: for pretty-prining
  */
 #define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \
-                     operands, name, fmt, size) \
-        {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}}, \
-         opcode, operands, name, fmt, size}
+                     k3, k3s, k3e, flags, name, fmt, size) \
+        {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
+                    {k3, k3s, k3e}}, opcode, flags, name, fmt, size}
 
 /* Instruction dump string format keys: !pf, where "!" is the start
  * of the key, "p" is which numeric operand to use and "f" is the
@@ -51,11 +51,11 @@
  *     0 -> operands[0] (dest)
  *     1 -> operands[1] (src1)
  *     2 -> operands[2] (src2)
+ *     3 -> operands[3] (extra)
  *
  * [f]ormats:
  *     h -> 4-digit hex
  *     d -> decimal
- *     D -> decimal+8 (used to convert 3-bit regnum field to high reg)
  *     E -> decimal*4
  *     F -> decimal*2
  *     c -> branch condition (beq, bne, etc.)
@@ -66,436 +66,711 @@
  *     s -> single precision floating point register
  *     S -> double precision floating point register
  *     m -> Thumb2 modified immediate
+ *     n -> complimented Thumb2 modified immediate
  *     M -> Thumb2 16-bit zero-extended immediate
+ *     b -> 4-digit binary
  *
  *  [!] escape.  To insert "!", use "!!"
  */
 /* NOTE: must be kept in sync with enum ArmOpcode from ArmLIR.h */
 ArmEncodingMap EncodingMap[ARM_LAST] = {
     ENCODING_MAP(ARM_16BIT_DATA,    0x0000,
-                 BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP,
                  "data", "0x!0h(!0d)", 1),
-    ENCODING_MAP(THUMB_ADC,           0x4140,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "adc", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB_ADC_RR,        0x4140,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES | USES_CCODES,
+                 "adcs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_RRI3,      0x1c00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!1d, #!2d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "adds", "r!0d, r!1d, #!2d", 1),
     ENCODING_MAP(THUMB_ADD_RI8,       0x3000,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!0d, #!1d", 1),
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES,
+                 "adds", "r!0d, r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_ADD_RRR,       0x1800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!1d, r!2d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12 | SETS_CCODES,
+                 "adds", "r!0d, r!1d, r!2d", 1),
     ENCODING_MAP(THUMB_ADD_RR_LH,     0x4440,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "add",
-                 "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01,
+                 "add", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_RR_HL,     0x4480,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01,
                  "add", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_RR_HH,     0x44c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01,
                  "add", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_PC_REL,    0xa000,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | IS_BRANCH,
                  "add", "r!0d, pc, #!1E", 1),
     ENCODING_MAP(THUMB_ADD_SP_REL,    0xa800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, sp, #!1E", 1),
+                 BITBLT, 10, 8, UNUSED, -1, -1, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF_SP | REG_USE_SP,
+                 "add", "r!0d, sp, #!2E", 1),
     ENCODING_MAP(THUMB_ADD_SPI7,      0xb000,
-                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP | CLOBBER_DEST,
+                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP,
                  "add", "sp, #!0d*4", 1),
     ENCODING_MAP(THUMB_AND_RR,        0x4000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "and", "r!0d, r!1d", 1),
-    ENCODING_MAP(THUMB_ASR,           0x1000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "asr", "r!0d, r!1d, #!2d", 1),
-    ENCODING_MAP(THUMB_ASRV,          0x4100,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "asr", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+                 "ands", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB_ASR_RRI5,      0x1000,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "asrs", "r!0d, r!1d, #!2d", 1),
+    ENCODING_MAP(THUMB_ASR_RR,        0x4100,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+                 "asrs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_B_COND,        0xd000,
-                 BITBLT, 7, 0, BITBLT, 11, 8, UNUSED, -1, -1,
-                 IS_BINARY_OP | IS_BRANCH,
-                 "!1c", "!0t", 1),
+                 BITBLT, 7, 0, BITBLT, 11, 8, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | IS_BRANCH | USES_CCODES,
+                 "b!1c", "!0t", 1),
     ENCODING_MAP(THUMB_B_UNCOND,      0xe000,
-                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  NO_OPERAND | IS_BRANCH,
                  "b", "!0t", 1),
-    ENCODING_MAP(THUMB_BIC,           0x4380,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "bic", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB_BIC_RR,        0x4380,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+                 "bics", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_BKPT,          0xbe00,
-                 BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "bkpt", "!0d", 1),
     ENCODING_MAP(THUMB_BLX_1,         0xf000,
-                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | IS_BRANCH,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | IS_BRANCH | REG_DEF_LR,
                  "blx_1", "!0u", 1),
     ENCODING_MAP(THUMB_BLX_2,         0xe800,
-                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | IS_BRANCH,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | IS_BRANCH | REG_DEF_LR,
                  "blx_2", "!0v", 1),
     ENCODING_MAP(THUMB_BL_1,          0xf000,
-                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP | IS_BRANCH,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
                  "bl_1", "!0u", 1),
     ENCODING_MAP(THUMB_BL_2,          0xf800,
-                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP | IS_BRANCH,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
                  "bl_2", "!0v", 1),
     ENCODING_MAP(THUMB_BLX_R,         0x4780,
-                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP | IS_BRANCH,
+                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | REG_USE0 | IS_BRANCH | REG_DEF_LR,
                  "blx", "r!0d", 1),
     ENCODING_MAP(THUMB_BX,            0x4700,
-                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "bx", "r!0d", 1),
-    ENCODING_MAP(THUMB_CMN,           0x42c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+    ENCODING_MAP(THUMB_CMN_RR,        0x42c0,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE01 | SETS_CCODES,
                  "cmn", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_CMP_RI8,       0x2800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE0 | SETS_CCODES,
                  "cmp", "r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_CMP_RR,        0x4280,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE01 | SETS_CCODES,
                  "cmp", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_CMP_LH,        0x4540,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP,
-                 "cmp", "r!0d, r!1D", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE01 | SETS_CCODES,
+                 "cmp", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_CMP_HL,        0x4580,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP,
-                 "cmp", "r!0D, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE01 | SETS_CCODES,
+                 "cmp", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_CMP_HH,        0x45c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP,
-                 "cmp", "r!0D, r!1D", 1),
-    ENCODING_MAP(THUMB_EOR,           0x4040,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "eor", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE01 | SETS_CCODES,
+                 "cmp", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB_EOR_RR,        0x4040,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+                 "eors", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_LDMIA,         0xc800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | CLOBBER_SRC1,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE0 | REG_DEF_LIST1,
                  "ldmia", "r!0d!!, <!1R>", 1),
     ENCODING_MAP(THUMB_LDR_RRI5,      0x6800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "ldr", "r!0d, [r!1d, #!2E]", 1),
     ENCODING_MAP(THUMB_LDR_RRR,       0x5800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "ldr", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDR_PC_REL,    0x4800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0 | REG_USE_PC,
                  "ldr", "r!0d, [pc, #!1E]", 1),
     ENCODING_MAP(THUMB_LDR_SP_REL,    0x9800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "ldr", "r!0d, [sp, #!1E]", 1),
+                 BITBLT, 10, 8, UNUSED, -1, -1, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0 | REG_USE_SP,
+                 "ldr", "r!0d, [sp, #!2E]", 1),
     ENCODING_MAP(THUMB_LDRB_RRI5,     0x7800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "ldrb", "r!0d, [r!1d, #2d]", 1),
     ENCODING_MAP(THUMB_LDRB_RRR,      0x5c00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "ldrb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDRH_RRI5,     0x8800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "ldrh", "r!0d, [r!1d, #!2F]", 1),
     ENCODING_MAP(THUMB_LDRH_RRR,      0x5a00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "ldrh", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDRSB_RRR,     0x5600,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "ldrsb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDRSH_RRR,     0x5e00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "ldrsh", "r!0d, [r!1d, r!2d]", 1),
-    ENCODING_MAP(THUMB_LSL,           0x0000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "lsl", "r!0d, r!1d, #!2d", 1),
-    ENCODING_MAP(THUMB_LSLV,          0x4080,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "lsl", "r!0d, r!1d", 1),
-    ENCODING_MAP(THUMB_LSR,           0x0800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "lsr", "r!0d, r!1d, #!2d", 1),
-    ENCODING_MAP(THUMB_LSRV,          0x40c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "lsr", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB_LSL_RRI5,      0x0000,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "lsls", "r!0d, r!1d, #!2d", 1),
+    ENCODING_MAP(THUMB_LSL_RR,        0x4080,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+                 "lsls", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB_LSR_RRI5,      0x0800,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "lsrs", "r!0d, r!1d, #!2d", 1),
+    ENCODING_MAP(THUMB_LSR_RR,        0x40c0,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+                 "lsrs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MOV_IMM,       0x2000,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0d, #!1d", 1),
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0 | SETS_CCODES,
+                 "movs", "r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_MOV_RR,        0x1c00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "movs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MOV_RR_H2H,    0x46c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0D, r!1D", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
+                 "mov", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MOV_RR_H2L,    0x4640,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0d, r!1D", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
+                 "mov", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MOV_RR_L2H,    0x4680,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0D, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
+                 "mov", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MUL,           0x4340,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mul", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+                 "muls", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MVN,           0x43c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mvn", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "mvns", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_NEG,           0x4240,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "neg", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "negs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ORR,           0x4300,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "orr", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+                 "orrs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_POP,           0xbc00,
-                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP,
+                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0,
                  "pop", "<!0R>", 1),
     ENCODING_MAP(THUMB_PUSH,          0xb400,
-                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP,
+                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0,
                  "push", "<!0R>", 1),
-    ENCODING_MAP(THUMB_ROR,           0x41c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "ror", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB_ROR_RR,        0x41c0,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+                 "rors", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_SBC,           0x4180,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "sbc", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE01 | USES_CCODES | SETS_CCODES,
+                 "sbcs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_STMIA,         0xc000,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_SRC1,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0 | REG_USE0 | REG_USE_LIST1,
                  "stmia", "r!0d!!, <!1R>", 1),
     ENCODING_MAP(THUMB_STR_RRI5,      0x6000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01,
                  "str", "r!0d, [r!1d, #!2E]", 1),
     ENCODING_MAP(THUMB_STR_RRR,       0x5000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE012,
                  "str", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_STR_SP_REL,    0x9000,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP,
-                 "str", "r!0d, [sp, #!1E]", 1),
+                 BITBLT, 10, 8, UNUSED, -1, -1, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE0 | REG_USE_SP,
+                 "str", "r!0d, [sp, #!2E]", 1),
     ENCODING_MAP(THUMB_STRB_RRI5,     0x7000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01,
                  "strb", "r!0d, [r!1d, #!2d]", 1),
     ENCODING_MAP(THUMB_STRB_RRR,      0x5400,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE012,
                  "strb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_STRH_RRI5,     0x8000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01,
                  "strh", "r!0d, [r!1d, #!2F]", 1),
     ENCODING_MAP(THUMB_STRH_RRR,      0x5200,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE012,
                  "strh", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_SUB_RRI3,      0x1e00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "sub", "r!0d, r!1d, #!2d]", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "subs", "r!0d, r!1d, #!2d]", 1),
     ENCODING_MAP(THUMB_SUB_RI8,       0x3800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "sub", "r!0d, #!1d", 1),
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES,
+                 "subs", "r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_SUB_RRR,       0x1a00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "sub", "r!0d, r!1d, r!2d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12 | SETS_CCODES,
+                 "subs", "r!0d, r!1d, r!2d", 1),
     ENCODING_MAP(THUMB_SUB_SPI7,      0xb080,
-                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP | CLOBBER_DEST,
+                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP,
                  "sub", "sp, #!0d", 1),
     ENCODING_MAP(THUMB_SWI,           0xdf00,
-                 BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "swi", "!0d", 1),
     ENCODING_MAP(THUMB_TST,           0x4200,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_UNARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | REG_USE01 | SETS_CCODES,
                  "tst", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB2_VLDRS,       0xed900a00,
-                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "vldr", "!0s, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VLDRD,       0xed900b00,
-                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "vldr", "!0S, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VMULS,        0xee200a00,
-                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vmuls", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VMULD,        0xee200b00,
-                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vmuld", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VSTRS,       0xed800a00,
-                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
-                 IS_TERTIARY_OP,
+                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01,
                  "vstr", "!0s, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VSTRD,       0xed800b00,
-                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
-                 IS_TERTIARY_OP,
+                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01,
                  "vstr", "!0S, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VSUBS,        0xee300a40,
-                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vsub", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VSUBD,        0xee300b40,
-                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vsub", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VADDS,        0xee300a00,
-                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vadd", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VADDD,        0xee300b00,
-                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vadd", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VDIVS,        0xee800a00,
-                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vdivs", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VDIVD,        0xee800b00,
-                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "vdivs", "!0S, !1S, !2S", 2),
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "vdivd", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VCVTIF,       0xeeb80ac0,
-                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.f32", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTID,       0xeeb80bc0,
-                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.f64", "!0S, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTFI,       0xeebd0ac0,
-                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.s32.f32 ", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTDI,       0xeebd0bc0,
-                 SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.s32.f64 ", "!0s, !1S", 2),
     ENCODING_MAP(THUMB2_VCVTFD,       0xeeb70ac0,
-                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.f64.f32 ", "!0S, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTDF,       0xeeb70bc0,
-                 SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.f32.f64 ", "!0s, !1S", 2),
     ENCODING_MAP(THUMB2_VSQRTS,       0xeeb10ac0,
-                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vsqrt.f32 ", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_VSQRTD,       0xeeb10bc0,
-                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vsqrt.f64 ", "!0S, !1S", 2),
-    ENCODING_MAP(THUMB2_MOV_IMM_SHIFT,       0xf04f0000,
-                 BITBLT, 11, 8, MODIMM, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+    ENCODING_MAP(THUMB2_MOV_IMM_SHIFT, 0xf04f0000, /* no setflags encoding */
+                 BITBLT, 11, 8, MODIMM, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0,
                  "mov", "r!0d, #!1m", 2),
     ENCODING_MAP(THUMB2_MOV_IMM16,       0xf2400000,
-                 BITBLT, 11, 8, IMM16, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 BITBLT, 11, 8, IMM16, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0,
                  "mov", "r!0d, #!1M", 2),
     ENCODING_MAP(THUMB2_STR_RRI12,       0xf8c00000,
-                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0,
-                 IS_TERTIARY_OP,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01,
                  "str", "r!0d,[r!1d, #!2d", 2),
     ENCODING_MAP(THUMB2_LDR_RRI12,       0xf8d00000,
-                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "ldr", "r!0d,[r!1d, #!2d", 2),
     ENCODING_MAP(THUMB2_STR_RRI8_PREDEC,       0xf8400c00,
-                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0,
-                 IS_TERTIARY_OP,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01,
                  "str", "r!0d,[r!1d, #-!2d]", 2),
     ENCODING_MAP(THUMB2_LDR_RRI8_PREDEC,       0xf8500c00,
-                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "ldr", "r!0d,[r!1d, #-!2d]", 2),
-    ENCODING_MAP(THUMB2_CBNZ,       0xb900,
-                 BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+    ENCODING_MAP(THUMB2_CBNZ,       0xb900, /* Note: does not affect flags */
+                 BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE0 | IS_BRANCH,
                  "cbnz", "r!0d,!1t", 1),
-    ENCODING_MAP(THUMB2_CBZ,       0xb100,
-                 BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+    ENCODING_MAP(THUMB2_CBZ,       0xb100, /* Note: does not affect flags */
+                 BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE0 | IS_BRANCH,
                  "cbz", "r!0d,!1t", 1),
-    ENCODING_MAP(THUMB2_ADD_RRI12,       0xf1000000,
-                 BITBLT, 11, 8, BITBLT, 19, 16, IMM12, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+    ENCODING_MAP(THUMB2_ADD_RRI12,       0xf2000000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, IMM12, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,/* Note: doesn't affect flags */
                  "add", "r!0d,r!1d,#!2d", 2),
-    ENCODING_MAP(THUMB2_MOV_RR,       0xea4f0000,
-                 BITBLT, 11, 8, BITBLT, 3, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+    ENCODING_MAP(THUMB2_MOV_RR,       0xea4f0000, /* no setflags encoding */
+                 BITBLT, 11, 8, BITBLT, 3, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "mov", "r!0d, r!1d", 2),
     ENCODING_MAP(THUMB2_VMOVS,       0xeeb00a40,
-                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "vmov.f32 ", "!0s, !1s", 2),
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
+                 "vmov.f32 ", " !0s, !1s", 2),
     ENCODING_MAP(THUMB2_VMOVD,       0xeeb00b40,
-                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "vmov.f64 ", "!0s, !1s", 2),
+                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
+                 "vmov.f64 ", " !0S, !1S", 2),
+    ENCODING_MAP(THUMB2_LDMIA,         0xe8900000,
+                 BITBLT, 19, 16, BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE0 | REG_DEF_LIST1,
+                 "ldmia", "r!0d!!, <!1R>", 2),
+    ENCODING_MAP(THUMB2_STMIA,         0xe8800000,
+                 BITBLT, 19, 16, BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE0 | REG_USE_LIST1,
+                 "stmia", "r!0d!!, <!1R>", 2),
+    ENCODING_MAP(THUMB2_ADD_RRR,  0xeb100000, /* setflags encoding */
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
+                 "adds", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_SUB_RRR,       0xebb00000, /* setflags enconding */
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
+                 "subs", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_SBC_RRR,       0xeb700000, /* setflags encoding */
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | REG_DEF0_USE12 | USES_CCODES | SETS_CCODES,
+                 "sbcs", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_CMP_RR,       0xebb00f00,
+                 BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01 | SETS_CCODES,
+                 "cmp", "r!0d, r!1d", 2),
+    ENCODING_MAP(THUMB2_SUB_RRI12,       0xf2a00000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, IMM12, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,/* Note: doesn't affect flags */
+                 "sub", "r!0d,r!1d,#!2d", 2),
+    ENCODING_MAP(THUMB2_MVN_IMM_SHIFT,  0xf06f0000, /* no setflags encoding */
+                 BITBLT, 11, 8, MODIMM, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0,
+                 "mvn", "r!0d, #!1n", 2),
+    ENCODING_MAP(THUMB2_SEL,       0xfaa0f080,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12 | USES_CCODES,
+                 "sel", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_UBFX,       0xf3c00000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, LSB, -1, -1, BWIDTH, 4, 0,
+                 IS_QUAD_OP | REG_DEF0_USE1,
+                 "ubfx", "r!0d, r!1d, #!2d, #!3d", 2),
+    ENCODING_MAP(THUMB2_SBFX,       0xf3400000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, LSB, -1, -1, BWIDTH, 4, 0,
+                 IS_QUAD_OP | REG_DEF0_USE1,
+                 "sbfx", "r!0d, r!1d, #!2d, #!3d", 2),
+    ENCODING_MAP(THUMB2_LDR_RRR,    0xf8500000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | REG_DEF0_USE12,
+                 "ldr", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_LDRH_RRR,    0xf8300000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | REG_DEF0_USE12,
+                 "ldrh", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_LDRSH_RRR,    0xf9300000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | REG_DEF0_USE12,
+                 "ldrsh", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_LDRB_RRR,    0xf8100000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | REG_DEF0_USE12,
+                 "ldrb", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_LDRSB_RRR,    0xf9100000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | REG_DEF0_USE12,
+                 "ldrsb", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_STR_RRR,    0xf8400000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | REG_USE012,
+                 "str", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_STRH_RRR,    0xf8200000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | REG_USE012,
+                 "strh", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_STRB_RRR,    0xf8000000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | REG_USE012,
+                 "strb", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_LDRH_RRI12,       0xf8b00000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "ldrh", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_LDRSH_RRI12,       0xf9b00000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "ldrsh", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_LDRB_RRI12,       0xf8900000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "ldrb", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_LDRSB_RRI12,       0xf9900000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "ldrsb", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_STRH_RRI12,       0xf8a00000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01,
+                 "strh", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_STRB_RRI12,       0xf8800000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01,
+                 "strb", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_POP,           0xe8bd0000,
+                 BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0,
+                 "pop", "<!0R>", 2),
+    ENCODING_MAP(THUMB2_PUSH,          0xe8ad0000,
+                 BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0,
+                 "push", "<!0R>", 2),
+    ENCODING_MAP(THUMB2_CMP_RI8, 0xf1b00f00,
+                 BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE0 | SETS_CCODES,
+                 "cmp", "r!0d, #!1m", 2),
+    ENCODING_MAP(THUMB2_ADC_RRR,  0xeb500000, /* setflags encoding */
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
+                 "acds", "r!0d, r!1d, r!2d, shift !3d", 2),
+    ENCODING_MAP(THUMB2_AND_RRR,  0xea000000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | REG_DEF0_USE12,
+                 "and", "r!0d, r!1d, r!2d, shift !3d", 2),
+    ENCODING_MAP(THUMB2_BIC_RRR,  0xea200000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | REG_DEF0_USE12,
+                 "bic", "r!0d, r!1d, r!2d, shift !3d", 2),
+    ENCODING_MAP(THUMB2_CMN_RR,  0xeb000000,
+                 BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "cmn", "r!0d, r!1d, shift !2d", 2),
+    ENCODING_MAP(THUMB2_EOR_RRR,  0xea800000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | REG_DEF0_USE12,
+                 "eor", "r!0d, r!1d, r!2d, shift !3d", 2),
+    ENCODING_MAP(THUMB2_MUL_RRR,  0xfb00f000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "mul", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_MVN_RR,  0xea6f0000,
+                 BITBLT, 11, 8, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "mvn", "r!0d, r!1d, shift !2d", 2),
+    ENCODING_MAP(THUMB2_RSUB_RRI8,       0xf1d00000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "rsb", "r!0d,r!1d,#!2m", 2),
+    ENCODING_MAP(THUMB2_NEG_RR,       0xf1d00000, /* instance of rsub */
+                 BITBLT, 11, 8, BITBLT, 19, 16, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "neg", "r!0d,r!1d", 2),
+    ENCODING_MAP(THUMB2_ORR_RRR,  0xea400000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | REG_DEF0_USE12,
+                 "orr", "r!0d, r!1d, r!2d, shift !3d", 2),
+    ENCODING_MAP(THUMB2_TST_RR,       0xea100f00,
+                 BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_USE01 | SETS_CCODES,
+                 "tst", "r!0d, r!1d, shift !2d", 2),
+    ENCODING_MAP(THUMB2_LSL_RRR,  0xfa00f000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "lsl", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_LSR_RRR,  0xfa20f000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "lsr", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_ASR_RRR,  0xfa40f000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "asr", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_ROR_RRR,  0xfa60f000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "ror", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_LSL_RRI5,  0xea4f0000,
+                 BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "lsl", "r!0d, r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_LSR_RRI5,  0xea4f0010,
+                 BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "lsr", "r!0d, r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_ASR_RRI5,  0xea4f0020,
+                 BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "asr", "r!0d, r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_ROR_RRI5,  0xea4f0030,
+                 BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "ror", "r!0d, r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_BIC_RRI8,  0xf0200000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "bic", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_AND_RRI8,  0xf0000000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "and", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_ORR_RRI8,  0xf0400000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "orr", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_EOR_RRI8,  0xf0800000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
+                 "eor", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_ADD_RRI8,  0xf1100000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "adds", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_ADC_RRI8,  0xf1500000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES | USES_CCODES,
+                 "adcs", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_SUB_RRI8,  0xf1b00000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+                 "subs", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_SBC_RRI8,  0xf1700000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES | USES_CCODES,
+                 "sbcs", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_IT,  0xbf00,
+                 BITBLT, 7, 4, BITBLT, 3, 0, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | IS_IT | USES_CCODES,
+                 "it:!1b", "!0c", 1),
+    ENCODING_MAP(THUMB2_FMSTAT,  0xeef1fa10,
+                 UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 NO_OPERAND | SETS_CCODES,
+                 "fmstat", "", 2),
+    ENCODING_MAP(THUMB2_VCMPD,        0xeeb40b40,
+                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE01,
+                 "vcmp.f64", "!0S, !1S", 2),
+    ENCODING_MAP(THUMB2_VCMPS,        0xeeb40a40,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_USE01,
+                 "vcmp.f32", "!0s, !1s", 2),
+    ENCODING_MAP(THUMB2_LDR_PC_REL12,       0xf8df0000,
+                 BITBLT, 15, 12, BITBLT, 11, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0 | REG_USE_PC,
+                 "ldr", "r!0d,[rpc, #!1d", 2),
+    ENCODING_MAP(THUMB2_B_COND,        0xf0008000,
+                 BROFFSET, -1, -1, BITBLT, 25, 22, UNUSED, -1, -1,
+                 UNUSED, -1, -1,
+                 IS_BINARY_OP | IS_BRANCH | USES_CCODES,
+                 "b!1c", "!0t", 2),
+    ENCODING_MAP(THUMB2_VMOVD_RR,       0xeeb00b40,
+                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
+                 "vmov.f64", "!0S, !1S", 2),
+    ENCODING_MAP(THUMB2_VMOVS_RR,       0xeeb00a40,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
+                 "vmov.f32", "!0S, !1S", 2),
+    ENCODING_MAP(THUMB2_FMRS,       0xee100a10,
+                 BITBLT, 15, 12, SFP, 8, 16, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
+                 "fmrs", "r!0d, !1s", 2),
+    ENCODING_MAP(THUMB2_FMSR,       0xee000a10,
+                 SFP, 8, 16, BITBLT, 15, 12, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | REG_DEF0_USE1,
+                 "fmsr", "!0s, r!1d", 2),
+    ENCODING_MAP(THUMB2_FMRRD,       0xec500b10,
+                 BITBLT, 15, 12, BITBLT, 19, 16, DFP, 5, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF01_USE2,
+                 "fmrrd", "r!0d, r!1d, !2S", 2),
+    ENCODING_MAP(THUMB2_FMDRR,       0xec400b10,
+                 DFP, 5, 0, BITBLT, 15, 12, BITBLT, 19, 16, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
+                 "fmdrr", "!0S, r!1d, r!2d", 2),
 };
 
-#define PADDING_MOV_R0_R0               0x1C00
+/*
+ * The fake NOP of moving r0 to r0 actually will incur data stalls if r0 is
+ * not ready. Since r5 (rFP) is not updated often, it is less likely to
+ * generate unnecessary stall cycles.
+ */
+#define PADDING_MOV_R5_R5               0x1C2D
 
 /* Write the numbers in the literal pool to the codegen stream */
 static void installDataContent(CompilationUnit *cUnit)
@@ -530,7 +805,7 @@
             if ((lir->opCode == ARM_PSEUDO_ALIGN4) &&
                 /* 1 means padding is needed */
                 (lir->operands[0] == 1)) {
-                *bufferAddr++ = PADDING_MOV_R0_R0;
+                *bufferAddr++ = PADDING_MOV_R5_R5;
             }
             continue;
         }
@@ -540,6 +815,7 @@
         }
 
         if (lir->opCode == THUMB_LDR_PC_REL ||
+            lir->opCode == THUMB2_LDR_PC_REL12 ||
             lir->opCode == THUMB_ADD_PC_REL) {
             ArmLIR *lirTarget = (ArmLIR *) lir->generic.target;
             intptr_t pc = (lir->generic.offset + 4) & ~3;
@@ -554,25 +830,34 @@
                 LOGE("PC-rel distance is not multiples of 4: %d\n", delta);
                 dvmAbort();
             }
-            if (delta > 1023) {
+            if ((lir->opCode == THUMB2_LDR_PC_REL12) && (delta > 4091)) {
+                return true;
+            } else if (delta > 1020) {
                 return true;
             }
-            lir->operands[1] = delta >> 2;
+            lir->operands[1] = (lir->opCode == THUMB2_LDR_PC_REL12) ?
+                                delta : delta >> 2;
         } else if (lir->opCode == THUMB2_CBNZ || lir->opCode == THUMB2_CBZ) {
             ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
             intptr_t pc = lir->generic.offset + 4;
             intptr_t target = targetLIR->generic.offset;
             int delta = target - pc;
             if (delta > 126 || delta < 0) {
+                /*
+                 * TODO: allow multiple kinds of assembler failure to allow
+                 * change of code patterns when things don't fit.
+                 */
                 return true;
+            } else {
+                lir->operands[1] = delta >> 1;
             }
-            lir->operands[1] = delta >> 1;
-        } else if (lir->opCode == THUMB_B_COND) {
+        } else if (lir->opCode == THUMB_B_COND ||
+                   lir->opCode == THUMB2_B_COND) {
             ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
             intptr_t pc = lir->generic.offset + 4;
             intptr_t target = targetLIR->generic.offset;
             int delta = target - pc;
-            if (delta > 254 || delta < -256) {
+            if ((lir->opCode == THUMB_B_COND) && (delta > 254 || delta < -256)) {
                 return true;
             }
             lir->operands[0] = delta >> 1;
@@ -606,51 +891,81 @@
         ArmEncodingMap *encoder = &EncodingMap[lir->opCode];
         u4 bits = encoder->skeleton;
         int i;
-        for (i = 0; i < 3; i++) {
+        for (i = 0; i < 4; i++) {
+            u4 operand;
             u4 value;
+            operand = lir->operands[i];
             switch(encoder->fieldLoc[i].kind) {
                 case UNUSED:
                     break;
+                case BROFFSET:
+                    value = ((operand  & 0x80000) >> 19) << 26;
+                    value |= ((operand & 0x40000) >> 18) << 11;
+                    value |= ((operand & 0x20000) >> 17) << 13;
+                    value |= ((operand & 0x1f800) >> 11) << 16;
+                    value |= (operand  & 0x007ff);
+                    break;
+                case SHIFT5:
+                    value = ((operand & 0x1c) >> 2) << 12;
+                    value |= (operand & 0x03) << 6;
+                    bits |= value;
+                    break;
+                case SHIFT:
+                    value = ((operand & 0x70) >> 4) << 12;
+                    value |= (operand & 0x0f) << 4;
+                    bits |= value;
+                    break;
+                case BWIDTH:
+                    value = operand - 1;
+                    bits |= value;
+                    break;
+                case LSB:
+                    value = ((operand & 0x1c) >> 2) << 12;
+                    value |= (operand & 0x03) << 6;
+                    bits |= value;
+                    break;
                 case IMM6:
-                    value = ((lir->operands[i] & 0x20) >> 5) << 9;
-                    value |= (lir->operands[i] & 0x1f) << 3;
+                    value = ((operand & 0x20) >> 5) << 9;
+                    value |= (operand & 0x1f) << 3;
                     bits |= value;
                     break;
                 case BITBLT:
-                    value = (lir->operands[i] << encoder->fieldLoc[i].start) &
+                    value = (operand << encoder->fieldLoc[i].start) &
                             ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
                     bits |= value;
                     break;
-                case DFP:
+                case DFP: {
+                    int regName = (operand & FP_REG_MASK) >> 1;
                     /* Snag the 1-bit slice and position it */
-                    value = ((lir->operands[i] & 0x10) >> 4) <<
+                    value = ((regName & 0x10) >> 4) <<
                             encoder->fieldLoc[i].end;
                     /* Extract and position the 4-bit slice */
-                    value |= (lir->operands[i] & 0x0f) <<
+                    value |= (regName & 0x0f) <<
                             encoder->fieldLoc[i].start;
                     bits |= value;
                     break;
+                }
                 case SFP:
                     /* Snag the 1-bit slice and position it */
-                    value = (lir->operands[i] & 0x1) <<
+                    value = (operand & 0x1) <<
                             encoder->fieldLoc[i].end;
                     /* Extract and position the 4-bit slice */
-                    value |= ((lir->operands[i] & 0x1e) >> 1) <<
+                    value |= ((operand & 0x1e) >> 1) <<
                             encoder->fieldLoc[i].start;
                     bits |= value;
                     break;
                 case IMM12:
                 case MODIMM:
-                    value = ((lir->operands[i] & 0x800) >> 11) << 26;
-                    value |= ((lir->operands[i] & 0x700) >> 8) << 12;
-                    value |= lir->operands[i] & 0x0ff;
+                    value = ((operand & 0x800) >> 11) << 26;
+                    value |= ((operand & 0x700) >> 8) << 12;
+                    value |= operand & 0x0ff;
                     bits |= value;
                     break;
                 case IMM16:
-                    value = ((lir->operands[i] & 0x0800) >> 11) << 26;
-                    value |= ((lir->operands[i] & 0xf000) >> 12) << 16;
-                    value |= ((lir->operands[i] & 0x0700) >> 8) << 12;
-                    value |= lir->operands[i] & 0x0ff;
+                    value = ((operand & 0x0800) >> 11) << 26;
+                    value |= ((operand & 0xf000) >> 12) << 16;
+                    value |= ((operand & 0x0700) >> 8) << 12;
+                    value |= operand & 0x0ff;
                     bits |= value;
                     break;
                 default:
@@ -902,6 +1217,12 @@
                                           PredictedChainingCell *cell,
                                           const ClassObject *clazz)
 {
+#if defined(WITH_SELF_VERIFICATION)
+    /* Disable chaining and prevent this from triggering again for a while */
+    cell->counter = PREDICTED_CHAIN_COUNTER_AVOID;
+    cacheflush((long) cell, (long) (cell+1), 0);
+    goto done;
+#else
     /* Don't come back here for a long time if the method is native */
     if (dvmIsNativeMethod(method)) {
         cell->counter = PREDICTED_CHAIN_COUNTER_AVOID;
@@ -951,6 +1272,7 @@
 
     /* All done - resume all other threads */
     dvmResumeAllThreads(SUSPEND_FOR_JIT);
+#endif
 
 done:
     return method;
@@ -1018,6 +1340,17 @@
                     predChainCell->method = PREDICTED_CHAIN_METHOD_INIT;
                     predChainCell->counter = PREDICTED_CHAIN_COUNTER_INIT;
                     break;
+#if defined(WITH_SELF_VERIFICATION)
+                case CHAINING_CELL_BACKWARD_BRANCH:
+                    targetOffset = offsetof(InterpState,
+                          jitToInterpEntries.dvmJitToBackwardBranch);
+                    break;
+#elif defined(WITH_JIT_TUNING)
+                case CHAINING_CELL_BACKWARD_BRANCH:
+                    targetOffset = offsetof(InterpState,
+                          jitToInterpEntries.dvmJitToInterpNormal);
+                    break;
+#endif
                 default:
                     dvmAbort();
             }
diff --git a/vm/compiler/codegen/arm/Codegen.c b/vm/compiler/codegen/arm/Codegen.c
index 7d127f8..4a85fb2 100644
--- a/vm/compiler/codegen/arm/Codegen.c
+++ b/vm/compiler/codegen/arm/Codegen.c
@@ -24,6 +24,7 @@
  * applicable directory below this one.
  */
 
+#include "compiler/Loop.h"
 
 /* Array holding the entry offset of each template relative to the first one */
 static intptr_t templateEntryOffsets[TEMPLATE_LAST_MARK];
@@ -31,10 +32,591 @@
 /* Track exercised opcodes */
 static int opcodeCoverage[256];
 
-/*****************************************************************************/
+#if defined(WITH_SELF_VERIFICATION)
+/* Prevent certain opcodes from being jitted */
+static inline bool selfVerificationPuntOps(OpCode op)
+{
+  return (op == OP_MONITOR_ENTER || op == OP_MONITOR_EXIT ||
+          op == OP_NEW_INSTANCE  || op == OP_NEW_ARRAY);
+}
 
 /*
- * The following are building blocks to construct low-level IRs with 0 - 3
+ * The following are used to keep compiled loads and stores from modifying
+ * memory during self verification mode.
+ *
+ * Stores do not modify memory. Instead, the address and value pair are stored
+ * into heapSpace. Addresses within heapSpace are unique. For accesses smaller
+ * than a word, the word containing the address is loaded first before being
+ * updated.
+ *
+ * Loads check heapSpace first and return data from there if an entry exists.
+ * Otherwise, data is loaded from memory as usual.
+ */
+
+/* Decode contents of heapArgSpace to determine addr to load from */
+static void selfVerificationLoadDecode(HeapArgSpace* heapArgSpace, int* addr)
+{
+    int reg = heapArgSpace->regMap & 0xF;
+
+    switch (reg) {
+        case 0:
+            *addr = heapArgSpace->r0;
+            break;
+        case 1:
+            *addr = heapArgSpace->r1;
+            break;
+        case 2:
+            *addr = heapArgSpace->r2;
+            break;
+        case 3:
+            *addr = heapArgSpace->r3;
+            break;
+        default:
+            LOGE("ERROR: bad reg used in selfVerificationLoadDecode: %d", reg);
+            break;
+    }
+}
+
+/* Decode contents of heapArgSpace to determine reg to load into */
+static void selfVerificationLoadDecodeData(HeapArgSpace* heapArgSpace,
+                                           int data, int reg)
+{
+    switch (reg) {
+        case 0:
+            heapArgSpace->r0 = data;
+            break;
+        case 1:
+            heapArgSpace->r1 = data;
+            break;
+        case 2:
+            heapArgSpace->r2 = data;
+            break;
+        case 3:
+            heapArgSpace->r3 = data;
+            break;
+        default:
+            LOGE("ERROR: bad reg passed to selfVerificationLoadDecodeData: %d",
+                reg);
+            break;
+    }
+}
+
+static void selfVerificationLoad(InterpState* interpState)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowHeap *heapSpacePtr;
+    ShadowSpace *shadowSpace = self->shadowSpace;
+    HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+    int addr, data;
+    selfVerificationLoadDecode(heapArgSpace, &addr);
+
+    for (heapSpacePtr = shadowSpace->heapSpace;
+         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+        if (heapSpacePtr->addr == addr) {
+            data = heapSpacePtr->data;
+            break;
+        }
+    }
+
+    if (heapSpacePtr == shadowSpace->heapSpaceTail)
+        data = *((unsigned int*) addr);
+
+    int reg = (heapArgSpace->regMap >> 4) & 0xF;
+
+    //LOGD("*** HEAP LOAD: Reg:%d Addr: 0x%x Data: 0x%x", reg, addr, data);
+
+    selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadByte(InterpState* interpState)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowHeap *heapSpacePtr;
+    ShadowSpace *shadowSpace = self->shadowSpace;
+    HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+    int addr, data;
+    selfVerificationLoadDecode(heapArgSpace, &addr);
+
+    int maskedAddr = addr & 0xFFFFFFFC;
+    int alignment = addr & 0x3;
+
+    for (heapSpacePtr = shadowSpace->heapSpace;
+         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+        if (heapSpacePtr->addr == maskedAddr) {
+            addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+            data = *((unsigned char*) addr);
+            break;
+        }
+    }
+
+    if (heapSpacePtr == shadowSpace->heapSpaceTail)
+        data = *((unsigned char*) addr);
+
+    //LOGD("*** HEAP LOAD BYTE: Addr: 0x%x Data: 0x%x", addr, data);
+
+    int reg = (heapArgSpace->regMap >> 4) & 0xF;
+    selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadHalfword(InterpState* interpState)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowHeap *heapSpacePtr;
+    ShadowSpace *shadowSpace = self->shadowSpace;
+    HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+    int addr, data;
+    selfVerificationLoadDecode(heapArgSpace, &addr);
+
+    int maskedAddr = addr & 0xFFFFFFFC;
+    int alignment = addr & 0x2;
+
+    for (heapSpacePtr = shadowSpace->heapSpace;
+         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+        if (heapSpacePtr->addr == maskedAddr) {
+            addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+            data = *((unsigned short*) addr);
+            break;
+        }
+    }
+
+    if (heapSpacePtr == shadowSpace->heapSpaceTail)
+        data = *((unsigned short*) addr);
+
+    //LOGD("*** HEAP LOAD HALFWORD: Addr: 0x%x Data: 0x%x", addr, data);
+
+    int reg = (heapArgSpace->regMap >> 4) & 0xF;
+    selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadSignedByte(InterpState* interpState)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowHeap* heapSpacePtr;
+    ShadowSpace* shadowSpace = self->shadowSpace;
+    HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+    int addr, data;
+    selfVerificationLoadDecode(heapArgSpace, &addr);
+
+    int maskedAddr = addr & 0xFFFFFFFC;
+    int alignment = addr & 0x3;
+
+    for (heapSpacePtr = shadowSpace->heapSpace;
+         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+        if (heapSpacePtr->addr == maskedAddr) {
+            addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+            data = *((signed char*) addr);
+            break;
+        }
+    }
+
+    if (heapSpacePtr == shadowSpace->heapSpaceTail)
+        data = *((signed char*) addr);
+
+    //LOGD("*** HEAP LOAD SIGNED BYTE: Addr: 0x%x Data: 0x%x", addr, data);
+
+    int reg = (heapArgSpace->regMap >> 4) & 0xF;
+    selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadSignedHalfword(InterpState* interpState)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowHeap* heapSpacePtr;
+    ShadowSpace* shadowSpace = self->shadowSpace;
+    HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+    int addr, data;
+    selfVerificationLoadDecode(heapArgSpace, &addr);
+
+    int maskedAddr = addr & 0xFFFFFFFC;
+    int alignment = addr & 0x2;
+
+    for (heapSpacePtr = shadowSpace->heapSpace;
+         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+        if (heapSpacePtr->addr == maskedAddr) {
+            addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+            data = *((signed short*) addr);
+            break;
+        }
+    }
+
+    if (heapSpacePtr == shadowSpace->heapSpaceTail)
+        data = *((signed short*) addr);
+
+    //LOGD("*** HEAP LOAD SIGNED HALFWORD: Addr: 0x%x Data: 0x%x", addr, data);
+
+    int reg = (heapArgSpace->regMap >> 4) & 0xF;
+    selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadDoubleword(InterpState* interpState)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowHeap* heapSpacePtr;
+    ShadowSpace* shadowSpace = self->shadowSpace;
+    HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+    int addr;
+    selfVerificationLoadDecode(heapArgSpace, &addr);
+
+    int addr2 = addr+4;
+    unsigned int data = *((unsigned int*) addr);
+    unsigned int data2 = *((unsigned int*) addr2);
+
+    for (heapSpacePtr = shadowSpace->heapSpace;
+         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+        if (heapSpacePtr->addr == addr) {
+            data = heapSpacePtr->data;
+        } else if (heapSpacePtr->addr == addr2) {
+            data2 = heapSpacePtr->data;
+        }
+    }
+
+    //LOGD("*** HEAP LOAD DOUBLEWORD: Addr: 0x%x Data: 0x%x Data2: 0x%x",
+    //    addr, data, data2);
+
+    int reg = (heapArgSpace->regMap >> 4) & 0xF;
+    int reg2 = (heapArgSpace->regMap >> 8) & 0xF;
+    selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+    selfVerificationLoadDecodeData(heapArgSpace, data2, reg2);
+}
+
+/* Decode contents of heapArgSpace to determine arguments to store. */
+static void selfVerificationStoreDecode(HeapArgSpace* heapArgSpace,
+                                        int* value, int reg)
+{
+    switch (reg) {
+        case 0:
+            *value = heapArgSpace->r0;
+            break;
+        case 1:
+            *value = heapArgSpace->r1;
+            break;
+        case 2:
+            *value = heapArgSpace->r2;
+            break;
+        case 3:
+            *value = heapArgSpace->r3;
+            break;
+        default:
+            LOGE("ERROR: bad reg passed to selfVerificationStoreDecode: %d",
+                reg);
+            break;
+    }
+}
+
+static void selfVerificationStore(InterpState* interpState)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowHeap *heapSpacePtr;
+    ShadowSpace *shadowSpace = self->shadowSpace;
+    HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+    int addr, data;
+    int reg0 = heapArgSpace->regMap & 0xF;
+    int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+    selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+    selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+
+    //LOGD("*** HEAP STORE: Addr: 0x%x Data: 0x%x", addr, data);
+
+    for (heapSpacePtr = shadowSpace->heapSpace;
+         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+        if (heapSpacePtr->addr == addr) break;
+    }
+
+    if (heapSpacePtr == shadowSpace->heapSpaceTail) {
+        heapSpacePtr->addr = addr;
+        shadowSpace->heapSpaceTail++;
+    }
+
+    heapSpacePtr->data = data;
+}
+
+static void selfVerificationStoreByte(InterpState* interpState)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowHeap *heapSpacePtr;
+    ShadowSpace *shadowSpace = self->shadowSpace;
+    HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+    int addr, data;
+    int reg0 = heapArgSpace->regMap & 0xF;
+    int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+    selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+    selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+
+    int maskedAddr = addr & 0xFFFFFFFC;
+    int alignment = addr & 0x3;
+
+    //LOGD("*** HEAP STORE BYTE: Addr: 0x%x Data: 0x%x", addr, data);
+
+    for (heapSpacePtr = shadowSpace->heapSpace;
+         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+        if (heapSpacePtr->addr == maskedAddr) break;
+    }
+
+    if (heapSpacePtr == shadowSpace->heapSpaceTail)  {
+        heapSpacePtr->addr = maskedAddr;
+        heapSpacePtr->data = *((unsigned int*) maskedAddr);
+        shadowSpace->heapSpaceTail++;
+    }
+
+    addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+    *((unsigned char*) addr) = (char) data;
+
+    //LOGD("*** HEAP STORE BYTE: Addr: 0x%x Final Data: 0x%x",
+    //    addr, heapSpacePtr->data);
+}
+
+static void selfVerificationStoreHalfword(InterpState* interpState)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowHeap *heapSpacePtr;
+    ShadowSpace *shadowSpace = self->shadowSpace;
+    HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+    int addr, data;
+    int reg0 = heapArgSpace->regMap & 0xF;
+    int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+    selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+    selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+
+    int maskedAddr = addr & 0xFFFFFFFC;
+    int alignment = addr & 0x2;
+
+    //LOGD("*** HEAP STORE HALFWORD: Addr: 0x%x Data: 0x%x", addr, data);
+
+    for (heapSpacePtr = shadowSpace->heapSpace;
+         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+        if (heapSpacePtr->addr == maskedAddr) break;
+    }
+
+    if (heapSpacePtr == shadowSpace->heapSpaceTail)  {
+        heapSpacePtr->addr = maskedAddr;
+        heapSpacePtr->data = *((unsigned int*) maskedAddr);
+        shadowSpace->heapSpaceTail++;
+    }
+
+    addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+    *((unsigned short*) addr) = (short) data;
+
+    //LOGD("*** HEAP STORE HALFWORD: Addr: 0x%x Final Data: 0x%x",
+    //    addr, heapSpacePtr->data);
+}
+
+static void selfVerificationStoreDoubleword(InterpState* interpState)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowHeap *heapSpacePtr;
+    ShadowSpace *shadowSpace = self->shadowSpace;
+    HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+    int addr, data, data2;
+    int reg0 = heapArgSpace->regMap & 0xF;
+    int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+    int reg2 = (heapArgSpace->regMap >> 8) & 0xF;
+    selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+    selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+    selfVerificationStoreDecode(heapArgSpace, &data2, reg2);
+
+    int addr2 = addr+4;
+    bool store1 = false, store2 = false;
+
+    //LOGD("*** HEAP STORE DOUBLEWORD: Addr: 0x%x Data: 0x%x, Data2: 0x%x",
+    //    addr, data, data2);
+
+    for (heapSpacePtr = shadowSpace->heapSpace;
+         heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+        if (heapSpacePtr->addr == addr) {
+            heapSpacePtr->data = data;
+            store1 = true;
+        } else if (heapSpacePtr->addr == addr2) {
+            heapSpacePtr->data = data2;
+            store2 = true;
+        }
+    }
+
+    if (!store1) {
+        shadowSpace->heapSpaceTail->addr = addr;
+        shadowSpace->heapSpaceTail->data = data;
+        shadowSpace->heapSpaceTail++;
+    }
+    if (!store2) {
+        shadowSpace->heapSpaceTail->addr = addr2;
+        shadowSpace->heapSpaceTail->data = data2;
+        shadowSpace->heapSpaceTail++;
+    }
+}
+
+/* Common wrapper function for all memory operations */
+static void selfVerificationMemOpWrapper(CompilationUnit *cUnit, int regMap,
+                                         void* funct)
+{
+    int regMask = (1 << r4PC) | (1 << r3) | (1 << r2) | (1 << r1) | (1 << r0);
+
+    /* r7 <- InterpState->heapArgSpace */
+    loadConstant(cUnit, r4PC, offsetof(InterpState, heapArgSpace));
+    newLIR3(cUnit, THUMB_ADD_RRR, r7, rGLUE, r4PC);
+
+    /* Save out values to heapArgSpace */
+    loadConstant(cUnit, r4PC, regMap);
+    newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+
+    /* Pass interpState pointer to function */
+    newLIR2(cUnit, THUMB_MOV_RR, r0, rGLUE);
+
+    /* Set function pointer and branch */
+    loadConstant(cUnit, r1, (int) funct);
+    newLIR1(cUnit, THUMB_BLX_R, r1);
+
+    /* r7 <- InterpState->heapArgSpace */
+    loadConstant(cUnit, r4PC, offsetof(InterpState, heapArgSpace));
+    newLIR3(cUnit, THUMB_ADD_RRR, r7, rGLUE, r4PC);
+
+    /* Restore register state */
+    newLIR2(cUnit, THUMB_LDMIA, r7, regMask);
+}
+#endif
+
+/*
+ * Mark load/store instructions that access Dalvik registers through rFP +
+ * offset.
+ */
+static void annotateDalvikRegAccess(ArmLIR *lir, int regId, bool isLoad)
+{
+    if (isLoad) {
+        lir->useMask |= ENCODE_DALVIK_REG;
+    } else {
+        lir->defMask |= ENCODE_DALVIK_REG;
+    }
+
+    /*
+     * Store the Dalvik register id in aliasInfo. Mark he MSB if it is a 64-bit
+     * access.
+     */
+    lir->aliasInfo = regId;
+    if (DOUBLEREG(lir->operands[0])) {
+        lir->aliasInfo |= 0x80000000;
+    }
+}
+
+/*
+ * Decode the register id and mark the corresponding bit(s).
+ */
+static inline void setupRegMask(u8 *mask, int reg)
+{
+    u8 seed;
+    int shift;
+    int regId = reg & 0x1f;
+
+    /*
+     * Each double register is equal to a pair of single-precision FP registers
+     */
+    seed = DOUBLEREG(reg) ? 3 : 1;
+    /* FP register starts at bit position 16 */
+    shift = FPREG(reg) ? kFPReg0 : 0;
+    /* Expand the double register id into single offset */
+    shift += regId;
+    *mask |= seed << shift;
+}
+
+/*
+ * Set up the proper fields in the resource mask
+ */
+static void setupResourceMasks(ArmLIR *lir)
+{
+    int opCode = lir->opCode;
+    int flags;
+
+    if (opCode <= 0) {
+        lir->useMask = lir->defMask = 0;
+        return;
+    }
+
+    flags = EncodingMap[lir->opCode].flags;
+
+    /* Set up the mask for resources that are updated */
+    if (flags & IS_BRANCH) {
+        lir->defMask |= ENCODE_REG_PC;
+        lir->useMask |= ENCODE_REG_PC;
+    }
+
+    if (flags & REG_DEF0) {
+        setupRegMask(&lir->defMask, lir->operands[0]);
+    }
+
+    if (flags & REG_DEF1) {
+        setupRegMask(&lir->defMask, lir->operands[1]);
+    }
+
+    if (flags & REG_DEF_SP) {
+        lir->defMask |= ENCODE_REG_SP;
+    }
+
+    if (flags & REG_DEF_SP) {
+        lir->defMask |= ENCODE_REG_LR;
+    }
+
+    if (flags & REG_DEF_LIST0) {
+        lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_DEF_LIST1) {
+        lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
+    }
+
+    if (flags & SETS_CCODES) {
+        lir->defMask |= ENCODE_CCODE;
+    }
+
+    /* Conservatively treat the IT block */
+    if (flags & IS_IT) {
+        lir->defMask = ENCODE_ALL;
+    }
+
+    /* Set up the mask for resources that are used */
+    if (flags & IS_BRANCH) {
+        lir->useMask |= ENCODE_REG_PC;
+    }
+
+    if (flags & (REG_USE0 | REG_USE1 | REG_USE2)) {
+        int i;
+
+        for (i = 0; i < 3; i++) {
+            if (flags & (1 << (kRegUse0 + i))) {
+                setupRegMask(&lir->useMask, lir->operands[i]);
+            }
+        }
+    }
+
+    if (flags & REG_USE_PC) {
+        lir->useMask |= ENCODE_REG_PC;
+    }
+
+    if (flags & REG_USE_SP) {
+        lir->useMask |= ENCODE_REG_SP;
+    }
+
+    if (flags & REG_USE_LIST0) {
+        lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_USE_LIST1) {
+        lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
+    }
+
+    if (flags & USES_CCODES) {
+        lir->useMask |= ENCODE_CCODE;
+    }
+}
+
+/*
+ * The following are building blocks to construct low-level IRs with 0 - 4
  * operands.
  */
 static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpCode opCode)
@@ -42,6 +624,7 @@
     ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
     assert(isPseudoOpCode(opCode) || (EncodingMap[opCode].flags & NO_OPERAND));
     insn->opCode = opCode;
+    setupResourceMasks(insn);
     dvmCompilerAppendLIR(cUnit, (LIR *) insn);
     return insn;
 }
@@ -53,6 +636,7 @@
     assert(isPseudoOpCode(opCode) || (EncodingMap[opCode].flags & IS_UNARY_OP));
     insn->opCode = opCode;
     insn->operands[0] = dest;
+    setupResourceMasks(insn);
     dvmCompilerAppendLIR(cUnit, (LIR *) insn);
     return insn;
 }
@@ -66,6 +650,7 @@
     insn->opCode = opCode;
     insn->operands[0] = dest;
     insn->operands[1] = src1;
+    setupResourceMasks(insn);
     dvmCompilerAppendLIR(cUnit, (LIR *) insn);
     return insn;
 }
@@ -80,21 +665,46 @@
     insn->operands[0] = dest;
     insn->operands[1] = src1;
     insn->operands[2] = src2;
+    setupResourceMasks(insn);
     dvmCompilerAppendLIR(cUnit, (LIR *) insn);
     return insn;
 }
 
-static ArmLIR *newLIR23(CompilationUnit *cUnit, ArmOpCode opCode,
-                            int srcdest, int src2)
+static ArmLIR *newLIR4(CompilationUnit *cUnit, ArmOpCode opCode,
+                           int dest, int src1, int src2, int info)
 {
-    assert(!isPseudoOpCode(opCode));
-    if (EncodingMap[opCode].flags & IS_BINARY_OP)
-        return newLIR2(cUnit, opCode, srcdest, src2);
-    else
-        return newLIR3(cUnit, opCode, srcdest, srcdest, src2);
+    ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
+    assert(isPseudoOpCode(opCode) ||
+           (EncodingMap[opCode].flags & IS_QUAD_OP));
+    insn->opCode = opCode;
+    insn->operands[0] = dest;
+    insn->operands[1] = src1;
+    insn->operands[2] = src2;
+    insn->operands[3] = info;
+    setupResourceMasks(insn);
+    dvmCompilerAppendLIR(cUnit, (LIR *) insn);
+    return insn;
 }
 
-/*****************************************************************************/
+/*
+ * If the next instruction is a move-result or move-result-long,
+ * return the target Dalvik instruction and convert the next to a
+ * nop.  Otherwise, return -1.  Used to optimize method inlining.
+ */
+static int inlinedTarget(MIR *mir)
+{
+    if (mir->next &&
+        ((mir->next->dalvikInsn.opCode == OP_MOVE_RESULT) ||
+         (mir->next->dalvikInsn.opCode == OP_MOVE_RESULT_OBJECT) ||
+         (mir->next->dalvikInsn.opCode == OP_MOVE_RESULT_WIDE))) {
+        mir->next->dalvikInsn.opCode = OP_NOP;
+        return mir->next->dalvikInsn.vA;
+    } else {
+        return -1;
+    }
+}
+
+
 
 /*
  * The following are building blocks to insert constants into the pool or
@@ -136,6 +746,17 @@
     return NULL;
 }
 
+/*
+ * Generate an ARM_PSEUDO_BARRIER marker to indicate the boundary of special
+ * blocks.
+ */
+static void genBarrier(CompilationUnit *cUnit)
+{
+    ArmLIR *barrier = newLIR0(cUnit, ARM_PSEUDO_BARRIER);
+    /* Mark all resources as being clobbered */
+    barrier->defMask = -1;
+}
+
 /* Perform the actual operation for OP_RETURN_* */
 static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
 {
@@ -157,34 +778,6 @@
     branch->generic.target = (LIR *) pcrLabel;
 }
 
-/*
- * Perform a binary operation on 64-bit operands and leave the results in the
- * r0/r1 pair.
- */
-static void genBinaryOpWide(CompilationUnit *cUnit, int vDest,
-                            ArmOpCode preinst, ArmOpCode inst,
-                            int reg0, int reg2)
-{
-    int reg1 = NEXT_REG(reg0);
-    int reg3 = NEXT_REG(reg2);
-    newLIR23(cUnit, preinst, reg0, reg2);
-    newLIR23(cUnit, inst, reg1, reg3);
-    storeValuePair(cUnit, reg0, reg1, vDest, reg2);
-}
-
-/* Perform a binary operation on 32-bit operands and leave the results in r0. */
-static void genBinaryOp(CompilationUnit *cUnit, int vDest, ArmOpCode inst,
-                        int reg0, int reg1, int regDest)
-{
-    if (EncodingMap[inst].flags & IS_BINARY_OP) {
-        newLIR2(cUnit, inst, reg0, reg1);
-        storeValue(cUnit, reg0, vDest, reg1);
-    } else {
-        newLIR3(cUnit, inst, regDest, reg0, reg1);
-        storeValue(cUnit, regDest, vDest, reg1);
-    }
-}
-
 /* Create the PC reconstruction slot if not already done */
 static inline ArmLIR *genCheckCommon(CompilationUnit *cUnit, int dOffset,
                                          ArmLIR *branch,
@@ -210,14 +803,16 @@
  * Perform a "reg cmp reg" operation and jump to the PCR region if condition
  * satisfies.
  */
-static inline ArmLIR *inertRegRegCheck(CompilationUnit *cUnit,
-                                           ArmConditionCode cond,
-                                           int reg1, int reg2, int dOffset,
-                                           ArmLIR *pcrLabel)
+static inline ArmLIR *genRegRegCheck(CompilationUnit *cUnit,
+                                     ArmConditionCode cond,
+                                     int reg1, int reg2, int dOffset,
+                                     ArmLIR *pcrLabel)
 {
-    newLIR2(cUnit, THUMB_CMP_RR, reg1, reg2);
-    ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
-    return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
+    ArmLIR *res;
+    res = opRegReg(cUnit, OP_CMP, reg1, reg2);
+    ArmLIR *branch = opCondBranch(cUnit, cond);
+    genCheckCommon(cUnit, dOffset, branch, pcrLabel);
+    return res;
 }
 
 /*
@@ -250,7 +845,7 @@
 static ArmLIR *genBoundsCheck(CompilationUnit *cUnit, int rIndex,
                                   int rBound, int dOffset, ArmLIR *pcrLabel)
 {
-    return inertRegRegCheck(cUnit, ARM_COND_CS, rIndex, rBound, dOffset,
+    return genRegRegCheck(cUnit, ARM_COND_CS, rIndex, rBound, dOffset,
                             pcrLabel);
 }
 
@@ -258,7 +853,7 @@
 static inline ArmLIR *genTrap(CompilationUnit *cUnit, int dOffset,
                                   ArmLIR *pcrLabel)
 {
-    ArmLIR *branch = newLIR0(cUnit, THUMB_B_UNCOND);
+    ArmLIR *branch = opNone(cUnit, OP_UNCOND_BR);
     return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
 }
 
@@ -277,14 +872,20 @@
     /*
      * Ping reg0 to the first register of the alternate register pair
      */
-    reg0 = (reg2 + 2) & 0x2;
+    reg0 = (reg2 + 2) & 0xa;
     reg1 = NEXT_REG(reg0);
 
     loadValue(cUnit, dInsn->vB, reg2);
     loadConstant(cUnit, reg3, fieldOffset);
     genNullCheck(cUnit, dInsn->vB, reg2, mir->offset, NULL); /* null object? */
-    newLIR3(cUnit, THUMB_ADD_RRR, reg2, reg2, reg3);
-    newLIR2(cUnit, THUMB_LDMIA, reg2, (1<<reg0 | 1<<reg1));
+    opRegReg(cUnit, OP_ADD, reg2, reg3);
+#if !defined(WITH_SELF_VERIFICATION)
+    loadMultiple(cUnit, reg2, (1<<reg0 | 1<<reg1));
+#else
+    int regMap = reg1 << 8 | reg0 << 4 | reg2;
+    selfVerificationMemOpWrapper(cUnit, regMap,
+        &selfVerificationLoadDoubleword);
+#endif
     storeValuePair(cUnit, reg0, reg1, dInsn->vA, reg3);
 }
 
@@ -303,7 +904,7 @@
     /*
      * Ping reg0 to the first register of the alternate register pair
      */
-    reg0 = (reg2 + 2) & 0x2;
+    reg0 = (reg2 + 2) & 0xa;
     reg1 = NEXT_REG(reg0);
 
 
@@ -312,21 +913,21 @@
     updateLiveRegisterPair(cUnit, dInsn->vA, reg0, reg1);
     loadConstant(cUnit, reg3, fieldOffset);
     genNullCheck(cUnit, dInsn->vB, reg2, mir->offset, NULL); /* null object? */
-    newLIR3(cUnit, THUMB_ADD_RRR, reg2, reg2, reg3);
-    newLIR2(cUnit, THUMB_STMIA, reg2, (1<<reg0 | 1<<reg1));
+    opRegReg(cUnit, OP_ADD, reg2, reg3);
+#if !defined(WITH_SELF_VERIFICATION)
+    storeMultiple(cUnit, reg2, (1<<reg0 | 1<<reg1));
+#else
+    int regMap = reg1 << 8 | reg0 << 4 | reg2;
+    selfVerificationMemOpWrapper(cUnit, regMap,
+        &selfVerificationStoreDoubleword);
+#endif
 }
 
 /*
  * Load a field from an object instance
  *
- * Inst should be one of:
- *      THUMB_LDR_RRR
- *      THUMB_LDRB_RRR
- *      THUMB_LDRH_RRR
- *      THUMB_LDRSB_RRR
- *      THUMB_LDRSH_RRR
  */
-static void genIGet(CompilationUnit *cUnit, MIR *mir, ArmOpCode inst,
+static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
                     int fieldOffset)
 {
     DecodedInstruction *dInsn = &mir->dalvikInsn;
@@ -334,23 +935,26 @@
 
     reg0 = selectFirstRegister(cUnit, dInsn->vB, false);
     reg1 = NEXT_REG(reg0);
-    /* TUNING: write a utility routine to load via base + constant offset */
     loadValue(cUnit, dInsn->vB, reg0);
-    loadConstant(cUnit, reg1, fieldOffset);
+#if !defined(WITH_SELF_VERIFICATION)
+    loadBaseDisp(cUnit, mir, reg0, fieldOffset, reg1, size, true, dInsn->vB);
+#else
     genNullCheck(cUnit, dInsn->vB, reg0, mir->offset, NULL); /* null object? */
-    newLIR3(cUnit, inst, reg0, reg0, reg1);
-    storeValue(cUnit, reg0, dInsn->vA, reg1);
+    /* Combine address and offset */
+    loadConstant(cUnit, reg1, fieldOffset);
+    opRegReg(cUnit, OP_ADD, reg0, reg1);
+
+    int regMap = reg1 << 4 | reg0;
+    selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationLoad);
+#endif
+    storeValue(cUnit, reg1, dInsn->vA, reg0);
 }
 
 /*
  * Store a field to an object instance
  *
- * Inst should be one of:
- *      THUMB_STR_RRR
- *      THUMB_STRB_RRR
- *      THUMB_STRH_RRR
  */
-static void genIPut(CompilationUnit *cUnit, MIR *mir, ArmOpCode inst,
+static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
                     int fieldOffset)
 {
     DecodedInstruction *dInsn = &mir->dalvikInsn;
@@ -360,36 +964,38 @@
     reg1 = NEXT_REG(reg0);
     reg2 = NEXT_REG(reg1);
 
-    /* TUNING: write a utility routine to load via base + constant offset */
     loadValue(cUnit, dInsn->vB, reg0);
-    loadConstant(cUnit, reg1, fieldOffset);
     loadValue(cUnit, dInsn->vA, reg2);
     updateLiveRegister(cUnit, dInsn->vA, reg2);
     genNullCheck(cUnit, dInsn->vB, reg0, mir->offset, NULL); /* null object? */
-    newLIR3(cUnit, inst, reg2, reg0, reg1);
+#if !defined(WITH_SELF_VERIFICATION)
+    storeBaseDisp(cUnit, reg0, fieldOffset, reg2, size, reg1);
+#else
+    /* Combine address and offset */
+    loadConstant(cUnit, reg1, fieldOffset);
+    opRegReg(cUnit, OP_ADD, reg0, reg1);
+
+    int regMap = reg2 << 4 | reg0;
+    selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationStore);
+
+    opRegReg(cUnit, OP_SUB, reg0, reg1);
+#endif
 }
 
 
-/* TODO: This should probably be done as an out-of-line instruction handler. */
-
 /*
  * Generate array load
  *
- * Inst should be one of:
- *      THUMB_LDR_RRR
- *      THUMB_LDRB_RRR
- *      THUMB_LDRH_RRR
- *      THUMB_LDRSB_RRR
- *      THUMB_LDRSH_RRR
  */
-static void genArrayGet(CompilationUnit *cUnit, MIR *mir, ArmOpCode inst,
+static void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
                         int vArray, int vIndex, int vDest, int scale)
 {
     int lenOffset = offsetof(ArrayObject, length);
     int dataOffset = offsetof(ArrayObject, contents);
     int reg0, reg1, reg2, reg3;
 
-    reg0 = selectFirstRegister(cUnit, vArray, false);
+    reg0 = selectFirstRegister(cUnit, vArray,
+                               (size == LONG) || (size == DOUBLE));
     reg1 = NEXT_REG(reg0);
     reg2 = NEXT_REG(reg1);
     reg3 = NEXT_REG(reg2);
@@ -398,43 +1004,91 @@
     loadValue(cUnit, vIndex, reg3);
 
     /* null object? */
-    ArmLIR * pcrLabel = genNullCheck(cUnit, vArray, reg2, mir->offset,
-                                         NULL);
-    newLIR3(cUnit, THUMB_LDR_RRI5, reg0, reg2, lenOffset >> 2);  /* Get len */
-    newLIR2(cUnit, THUMB_ADD_RI8, reg2, dataOffset); /* reg2 -> array data */
-    genBoundsCheck(cUnit, reg3, reg0, mir->offset, pcrLabel);
-    if (scale) {
-        newLIR3(cUnit, THUMB_LSL, reg3, reg3, scale);
+    ArmLIR * pcrLabel = NULL;
+
+    if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
+        pcrLabel = genNullCheck(cUnit, vArray, reg2, mir->offset, NULL);
     }
-    if (scale==3) {
-        newLIR3(cUnit, inst, reg0, reg2, reg3);
-        newLIR2(cUnit, THUMB_ADD_RI8, reg2, 4);
-        newLIR3(cUnit, inst, reg1, reg2, reg3);
+
+    if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
+        /* Get len */
+        loadWordDisp(cUnit, reg2, lenOffset, reg0);
+        /* reg2 -> array data */
+        opRegImm(cUnit, OP_ADD, reg2, dataOffset, rNone);
+        genBoundsCheck(cUnit, reg3, reg0, mir->offset, pcrLabel);
+    } else {
+        /* reg2 -> array data */
+        opRegImm(cUnit, OP_ADD, reg2, dataOffset, rNone);
+    }
+#if !defined(WITH_SELF_VERIFICATION)
+    if ((size == LONG) || (size == DOUBLE)) {
+        //TUNING: redo.  Make specific wide routine, perhaps use ldmia/fp regs
+        opRegRegImm(cUnit, OP_LSL, reg3, reg3, scale, rNone);
+        loadBaseIndexed(cUnit, reg2, reg3, reg0, 0, WORD);
+        opRegImm(cUnit, OP_ADD, reg2, 4, rNone);
+        loadBaseIndexed(cUnit, reg2, reg3, reg1, 0, WORD);
         storeValuePair(cUnit, reg0, reg1, vDest, reg3);
     } else {
-        newLIR3(cUnit, inst, reg0, reg2, reg3);
+        loadBaseIndexed(cUnit, reg2, reg3, reg0, scale, size);
         storeValue(cUnit, reg0, vDest, reg3);
     }
-}
+#else
+    //TODO: probably want to move this into loadBaseIndexed
+    void *funct = NULL;
+    switch(size) {
+        case LONG:
+        case DOUBLE:
+            funct = (void*) &selfVerificationLoadDoubleword;
+            break;
+        case WORD:
+            funct = (void*) &selfVerificationLoad;
+            break;
+        case UNSIGNED_HALF:
+            funct = (void*) &selfVerificationLoadHalfword;
+            break;
+        case SIGNED_HALF:
+            funct = (void*) &selfVerificationLoadSignedHalfword;
+            break;
+        case UNSIGNED_BYTE:
+            funct = (void*) &selfVerificationLoadByte;
+            break;
+        case SIGNED_BYTE:
+            funct = (void*) &selfVerificationLoadSignedByte;
+            break;
+        default:
+            assert(0);
+            dvmAbort();
+    }
+    /* Combine address and index */
+    if (scale)
+        opRegRegImm(cUnit, OP_LSL, reg3, reg3, scale, rNone);
+    opRegReg(cUnit, OP_ADD, reg2, reg3);
 
-/* TODO: This should probably be done as an out-of-line instruction handler. */
+    int regMap = reg1 << 8 | reg0 << 4 | reg2;
+    selfVerificationMemOpWrapper(cUnit, regMap, funct);
+
+    opRegReg(cUnit, OP_SUB, reg2, reg3);
+
+    if ((size == LONG) || (size == DOUBLE))
+        storeValuePair(cUnit, reg0, reg1, vDest, reg3);
+    else
+        storeValue(cUnit, reg0, vDest, reg3);
+#endif
+}
 
 /*
  * Generate array store
  *
- * Inst should be one of:
- *      THUMB_STR_RRR
- *      THUMB_STRB_RRR
- *      THUMB_STRH_RRR
  */
-static void genArrayPut(CompilationUnit *cUnit, MIR *mir, ArmOpCode inst,
+static void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
                         int vArray, int vIndex, int vSrc, int scale)
 {
     int lenOffset = offsetof(ArrayObject, length);
     int dataOffset = offsetof(ArrayObject, contents);
     int reg0, reg1, reg2, reg3;
 
-    reg0 = selectFirstRegister(cUnit, vArray, false);
+    reg0 = selectFirstRegister(cUnit, vArray,
+                               (size == LONG) || (size == DOUBLE));
     reg1 = NEXT_REG(reg0);
     reg2 = NEXT_REG(reg1);
     reg3 = NEXT_REG(reg2);
@@ -443,33 +1097,80 @@
     loadValue(cUnit, vIndex, reg3);
 
     /* null object? */
-    ArmLIR * pcrLabel = genNullCheck(cUnit, vArray, reg2, mir->offset,
-                                         NULL);
-    newLIR3(cUnit, THUMB_LDR_RRI5, reg0, reg2, lenOffset >> 2);  /* Get len */
-    newLIR2(cUnit, THUMB_ADD_RI8, reg2, dataOffset); /* reg2 -> array data */
-    genBoundsCheck(cUnit, reg3, reg0, mir->offset, pcrLabel);
+    ArmLIR * pcrLabel = NULL;
+
+    if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
+        pcrLabel = genNullCheck(cUnit, vArray, reg2, mir->offset, NULL);
+    }
+
+    if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
+        /* Get len */
+        loadWordDisp(cUnit, reg2, lenOffset, reg0);
+        /* reg2 -> array data */
+        opRegImm(cUnit, OP_ADD, reg2, dataOffset, rNone);
+        genBoundsCheck(cUnit, reg3, reg0, mir->offset, pcrLabel);
+    } else {
+        /* reg2 -> array data */
+        opRegImm(cUnit, OP_ADD, reg2, dataOffset, rNone);
+    }
+
     /* at this point, reg2 points to array, reg3 is unscaled index */
-    if (scale==3) {
+#if !defined(WITH_SELF_VERIFICATION)
+    if ((size == LONG) || (size == DOUBLE)) {
+        //TUNING: redo.  Make specific wide routine, perhaps use ldmia/fp regs
+        loadValuePair(cUnit, vSrc, reg0, reg1);
+        updateLiveRegisterPair(cUnit, vSrc, reg0, reg1);
+        if (scale)
+            opRegRegImm(cUnit, OP_LSL, reg3, reg3, scale, rNone);
+        storeBaseIndexed(cUnit, reg2, reg3, reg0, 0, WORD);
+        opRegImm(cUnit, OP_ADD, reg2, 4, rNone);
+        storeBaseIndexed(cUnit, reg2, reg3, reg1, 0, WORD);
+    } else {
+        loadValue(cUnit, vSrc, reg0);
+        updateLiveRegister(cUnit, vSrc, reg0);
+        storeBaseIndexed(cUnit, reg2, reg3, reg0, scale, size);
+    }
+#else
+    //TODO: probably want to move this into storeBaseIndexed
+    void *funct = NULL;
+    switch(size) {
+        case LONG:
+        case DOUBLE:
+            funct = (void*) &selfVerificationStoreDoubleword;
+            break;
+        case WORD:
+            funct = (void*) &selfVerificationStore;
+            break;
+        case SIGNED_HALF:
+        case UNSIGNED_HALF:
+            funct = (void*) &selfVerificationStoreHalfword;
+            break;
+        case SIGNED_BYTE:
+        case UNSIGNED_BYTE:
+            funct = (void*) &selfVerificationStoreByte;
+            break;
+        default:
+            assert(0);
+            dvmAbort();
+    }
+
+    /* Combine address and index */
+    if ((size == LONG) || (size == DOUBLE)) {
         loadValuePair(cUnit, vSrc, reg0, reg1);
         updateLiveRegisterPair(cUnit, vSrc, reg0, reg1);
     } else {
         loadValue(cUnit, vSrc, reg0);
         updateLiveRegister(cUnit, vSrc, reg0);
     }
-    if (scale) {
-        newLIR3(cUnit, THUMB_LSL, reg3, reg3, scale);
-    }
-    /*
-     * at this point, reg2 points to array, reg3 is scaled index, and
-     * reg0[reg1] is data
-     */
-    if (scale==3) {
-        newLIR3(cUnit, inst, reg0, reg2, reg3);
-        newLIR2(cUnit, THUMB_ADD_RI8, reg2, 4);
-        newLIR3(cUnit, inst, reg1, reg2, reg3);
-    } else {
-        newLIR3(cUnit, inst, reg0, reg2, reg3);
-    }
+    if (scale)
+        opRegRegImm(cUnit, OP_LSL, reg3, reg3, scale, rNone);
+    opRegReg(cUnit, OP_ADD, reg2, reg3);
+
+    int regMap = reg1 << 8 | reg0 << 4 | reg2;
+    selfVerificationMemOpWrapper(cUnit, regMap, funct);
+
+    opRegReg(cUnit, OP_SUB, reg2, reg3);
+#endif
 }
 
 static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir, int vDest,
@@ -543,8 +1244,7 @@
             break;
         case OP_NEG_FLOAT: {
             loadValue(cUnit, vSrc2, reg0);
-            loadConstant(cUnit, reg1, 0x80000000);
-            newLIR3(cUnit, THUMB_ADD_RRR, reg0, reg0, reg1);
+            opRegImm(cUnit, OP_ADD, reg0, 0x80000000, reg1);
             storeValue(cUnit, reg0, vDest, reg1);
             return false;
         }
@@ -554,7 +1254,7 @@
     loadConstant(cUnit, r2, (int)funct);
     loadValue(cUnit, vSrc1, r0);
     loadValue(cUnit, vSrc2, r1);
-    newLIR1(cUnit, THUMB_BLX_R, r2);
+    opReg(cUnit, OP_BLX, r2);
     storeValue(cUnit, r0, vDest, r1);
     return false;
 }
@@ -599,8 +1299,7 @@
             break;
         case OP_NEG_DOUBLE: {
             loadValuePair(cUnit, vSrc2, reg0, reg1);
-            loadConstant(cUnit, reg2, 0x80000000);
-            newLIR3(cUnit, THUMB_ADD_RRR, reg1, reg1, reg2);
+            opRegImm(cUnit, OP_ADD, reg1, 0x80000000, reg2);
             storeValuePair(cUnit, reg0, reg1, vDest, reg2);
             return false;
         }
@@ -614,7 +1313,7 @@
     loadConstant(cUnit, r4PC, (int)funct);
     loadValuePair(cUnit, vSrc1, r0, r1);
     loadValuePair(cUnit, vSrc2, r2, r3);
-    newLIR1(cUnit, THUMB_BLX_R, r4PC);
+    opReg(cUnit, OP_BLX, r4PC);
     storeValuePair(cUnit, r0, r1, vDest, r2);
     return false;
 }
@@ -622,8 +1321,8 @@
 static bool genArithOpLong(CompilationUnit *cUnit, MIR *mir, int vDest,
                            int vSrc1, int vSrc2)
 {
-    int firstOp = THUMB_BKPT;
-    int secondOp = THUMB_BKPT;
+    OpKind firstOp = OP_BKPT;
+    OpKind secondOp = OP_BKPT;
     bool callOut = false;
     void *callTgt;
     int retReg = r0;
@@ -633,18 +1332,18 @@
 
     switch (mir->dalvikInsn.opCode) {
         case OP_NOT_LONG:
-            firstOp = THUMB_MVN;
-            secondOp = THUMB_MVN;
+            firstOp = OP_MVN;
+            secondOp = OP_MVN;
             break;
         case OP_ADD_LONG:
         case OP_ADD_LONG_2ADDR:
-            firstOp = THUMB_ADD_RRR;
-            secondOp = THUMB_ADC;
+            firstOp = OP_ADD;
+            secondOp = OP_ADC;
             break;
         case OP_SUB_LONG:
         case OP_SUB_LONG_2ADDR:
-            firstOp = THUMB_SUB_RRR;
-            secondOp = THUMB_SBC;
+            firstOp = OP_SUB;
+            secondOp = OP_SBC;
             break;
         case OP_MUL_LONG:
         case OP_MUL_LONG_2ADDR:
@@ -669,18 +1368,18 @@
             break;
         case OP_AND_LONG:
         case OP_AND_LONG_2ADDR:
-            firstOp = THUMB_AND_RR;
-            secondOp = THUMB_AND_RR;
+            firstOp = OP_AND;
+            secondOp = OP_AND;
             break;
         case OP_OR_LONG:
         case OP_OR_LONG_2ADDR:
-            firstOp = THUMB_ORR;
-            secondOp = THUMB_ORR;
+            firstOp = OP_OR;
+            secondOp = OP_OR;
             break;
         case OP_XOR_LONG:
         case OP_XOR_LONG_2ADDR:
-            firstOp = THUMB_EOR;
-            secondOp = THUMB_EOR;
+            firstOp = OP_XOR;
+            secondOp = OP_XOR;
             break;
         case OP_NEG_LONG: {
             reg0 = selectFirstRegister(cUnit, vSrc2, true);
@@ -690,8 +1389,8 @@
 
             loadValuePair(cUnit, vSrc2, reg0, reg1);
             loadConstant(cUnit, reg3, 0);
-            newLIR3(cUnit, THUMB_SUB_RRR, reg2, reg3, reg0);
-            newLIR2(cUnit, THUMB_SBC, reg3, reg1);
+            opRegRegReg(cUnit, OP_SUB, reg2, reg3, reg0);
+            opRegReg(cUnit, OP_SBC, reg3, reg1);
             storeValuePair(cUnit, reg2, reg3, vDest, reg0);
             return false;
         }
@@ -707,16 +1406,18 @@
 
         loadValuePair(cUnit, vSrc1, reg0, reg1);
         loadValuePair(cUnit, vSrc2, reg2, reg3);
-        genBinaryOpWide(cUnit, vDest, firstOp, secondOp, reg0, reg2);
+        opRegReg(cUnit, firstOp, reg0, reg2);
+        opRegReg(cUnit, secondOp, reg1, reg3);
+        storeValuePair(cUnit, reg0, reg1, vDest, reg2);
     /*
-     * Don't optimize the regsiter usage here as they are governed by the EABI
+     * Don't optimize the register usage here as they are governed by the EABI
      * calling convention.
      */
     } else {
         loadValuePair(cUnit, vSrc2, r2, r3);
         loadConstant(cUnit, r4PC, (int) callTgt);
         loadValuePair(cUnit, vSrc1, r0, r1);
-        newLIR1(cUnit, THUMB_BLX_R, r4PC);
+        opReg(cUnit, OP_BLX, r4PC);
         storeValuePair(cUnit, retReg, retReg+1, vDest, r4PC);
     }
     return false;
@@ -725,9 +1426,10 @@
 static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir, int vDest,
                           int vSrc1, int vSrc2)
 {
-    int armOp = THUMB_BKPT;
+    OpKind op = OP_BKPT;
     bool callOut = false;
     bool checkZero = false;
+    bool threeOperand = false;
     int retReg = r0;
     void *callTgt;
     int reg0, reg1, regDest;
@@ -738,22 +1440,24 @@
 
     switch (mir->dalvikInsn.opCode) {
         case OP_NEG_INT:
-            armOp = THUMB_NEG;
+            op = OP_NEG;
             break;
         case OP_NOT_INT:
-            armOp = THUMB_MVN;
+            op = OP_MVN;
             break;
         case OP_ADD_INT:
         case OP_ADD_INT_2ADDR:
-            armOp = THUMB_ADD_RRR;
+            op = OP_ADD;
+            threeOperand = true;
             break;
         case OP_SUB_INT:
         case OP_SUB_INT_2ADDR:
-            armOp = THUMB_SUB_RRR;
+            op = OP_SUB;
+            threeOperand = true;
             break;
         case OP_MUL_INT:
         case OP_MUL_INT_2ADDR:
-            armOp = THUMB_MUL;
+            op = OP_MUL;
             break;
         case OP_DIV_INT:
         case OP_DIV_INT_2ADDR:
@@ -772,27 +1476,27 @@
             break;
         case OP_AND_INT:
         case OP_AND_INT_2ADDR:
-            armOp = THUMB_AND_RR;
+            op = OP_AND;
             break;
         case OP_OR_INT:
         case OP_OR_INT_2ADDR:
-            armOp = THUMB_ORR;
+            op = OP_OR;
             break;
         case OP_XOR_INT:
         case OP_XOR_INT_2ADDR:
-            armOp = THUMB_EOR;
+            op = OP_XOR;
             break;
         case OP_SHL_INT:
         case OP_SHL_INT_2ADDR:
-            armOp = THUMB_LSLV;
+            op = OP_LSL;
             break;
         case OP_SHR_INT:
         case OP_SHR_INT_2ADDR:
-            armOp = THUMB_ASRV;
+            op = OP_ASR;
             break;
         case OP_USHR_INT:
         case OP_USHR_INT_2ADDR:
-            armOp = THUMB_LSRV;
+            op = OP_LSR;
             break;
         default:
             LOGE("Invalid word arith op: 0x%x(%d)",
@@ -808,7 +1512,13 @@
 
             loadValue(cUnit, vSrc1, reg0); /* Should be optimized away */
             loadValue(cUnit, vSrc2, reg1);
-            genBinaryOp(cUnit, vDest, armOp, reg0, reg1, regDest);
+            if (threeOperand) {
+                opRegRegReg(cUnit, op, regDest, reg0, reg1);
+                storeValue(cUnit, regDest, vDest, reg1);
+            } else {
+                opRegReg(cUnit, op, reg0, reg1);
+                storeValue(cUnit, reg0, vDest, reg1);
+            }
         } else {
             reg0 = selectFirstRegister(cUnit, vSrc2, false);
             reg1 = NEXT_REG(reg0);
@@ -816,7 +1526,13 @@
 
             loadValue(cUnit, vSrc1, reg1); /* Load this value first */
             loadValue(cUnit, vSrc2, reg0); /* May be optimized away */
-            genBinaryOp(cUnit, vDest, armOp, reg1, reg0, regDest);
+            if (threeOperand) {
+                opRegRegReg(cUnit, op, regDest, reg1, reg0);
+                storeValue(cUnit, regDest, vDest, reg1);
+            } else {
+                opRegReg(cUnit, op, reg1, reg0);
+                storeValue(cUnit, reg1, vDest, reg0);
+            }
         }
     } else {
         /*
@@ -841,7 +1557,7 @@
         if (checkZero) {
             genNullCheck(cUnit, vSrc2, r1, mir->offset, NULL);
         }
-        newLIR1(cUnit, THUMB_BLX_R, r2);
+        opReg(cUnit, OP_BLX, r2);
         storeValue(cUnit, retReg, vDest, r2);
     }
     return false;
@@ -900,7 +1616,7 @@
     } else {
         loadValuePair(cUnit, mir->dalvikInsn.vB, r0, r1);
     }
-    newLIR1(cUnit, THUMB_BLX_R, r2);
+    opReg(cUnit, OP_BLX, r2);
     if (tgtSize == 1) {
         storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
     } else {
@@ -909,136 +1625,6 @@
     return false;
 }
 
-static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
-{
-    DecodedInstruction *dInsn = &mir->dalvikInsn;
-    int offset = offsetof(InterpState, retval);
-    int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
-    int reg1 = NEXT_REG(regObj);
-    loadValue(cUnit, dInsn->arg[0], regObj);
-    genNullCheck(cUnit, dInsn->arg[0], regObj, mir->offset, NULL);
-    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, reg1);
-    newLIR3(cUnit, THUMB_STR_RRI5, reg1, rGLUE, offset >> 2);
-    return false;
-}
-
-/*
- * NOTE: The amount of code for this body suggests it ought to
- * be handled in a template (and could also be coded quite a bit
- * more efficiently in ARM).  However, the code is dependent on the
- * internal structure layout of string objects which are most safely
- * known at run time.
- * TUNING:  One possibility (which could also be used for StringCompareTo
- * and StringEquals) is to generate string access helper subroutines on
- * Jit startup, and then call them from the translated inline-executes.
- */
-static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
-{
-    DecodedInstruction *dInsn = &mir->dalvikInsn;
-    int offset = offsetof(InterpState, retval);
-    int contents = offsetof(ArrayObject, contents);
-    int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
-    int regIdx = NEXT_REG(regObj);
-    int regMax = NEXT_REG(regIdx);
-    int regOff = NEXT_REG(regMax);
-    loadValue(cUnit, dInsn->arg[0], regObj);
-    loadValue(cUnit, dInsn->arg[1], regIdx);
-    ArmLIR * pcrLabel = genNullCheck(cUnit, dInsn->arg[0], regObj,
-                                         mir->offset, NULL);
-    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, regMax);
-    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_offset, regOff);
-    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_value, regObj);
-    genBoundsCheck(cUnit, regIdx, regMax, mir->offset, pcrLabel);
-
-    newLIR2(cUnit, THUMB_ADD_RI8, regObj, contents);
-    newLIR3(cUnit, THUMB_ADD_RRR, regIdx, regIdx, regOff);
-    newLIR3(cUnit, THUMB_ADD_RRR, regIdx, regIdx, regIdx);
-    newLIR3(cUnit, THUMB_LDRH_RRR, regMax, regObj, regIdx);
-    newLIR3(cUnit, THUMB_STR_RRI5, regMax, rGLUE, offset >> 2);
-    return false;
-}
-
-static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
-{
-    int offset = offsetof(InterpState, retval);
-    DecodedInstruction *dInsn = &mir->dalvikInsn;
-    int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
-    int sign = NEXT_REG(reg0);
-    /* abs(x) = y<=x>>31, (x+y)^y.  Shorter in ARM/THUMB2, no skip in THUMB */
-    loadValue(cUnit, dInsn->arg[0], reg0);
-    newLIR3(cUnit, THUMB_ASR, sign, reg0, 31);
-    newLIR3(cUnit, THUMB_ADD_RRR, reg0, reg0, sign);
-    newLIR2(cUnit, THUMB_EOR, reg0, sign);
-    newLIR3(cUnit, THUMB_STR_RRI5, reg0, rGLUE, offset >> 2);
-    return false;
-}
-
-static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir)
-{
-    int offset = offsetof(InterpState, retval);
-    DecodedInstruction *dInsn = &mir->dalvikInsn;
-    int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
-    int signMask = NEXT_REG(reg0);
-    loadValue(cUnit, dInsn->arg[0], reg0);
-    loadConstant(cUnit, signMask, 0x7fffffff);
-    newLIR2(cUnit, THUMB_AND_RR, reg0, signMask);
-    newLIR3(cUnit, THUMB_STR_RRI5, reg0, rGLUE, offset >> 2);
-    return false;
-}
-
-static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir)
-{
-    int offset = offsetof(InterpState, retval);
-    DecodedInstruction *dInsn = &mir->dalvikInsn;
-    int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
-    int ophi = NEXT_REG(oplo);
-    int signMask = NEXT_REG(ophi);
-    loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
-    loadConstant(cUnit, signMask, 0x7fffffff);
-    newLIR3(cUnit, THUMB_STR_RRI5, oplo, rGLUE, offset >> 2);
-    newLIR2(cUnit, THUMB_AND_RR, ophi, signMask);
-    newLIR3(cUnit, THUMB_STR_RRI5, ophi, rGLUE, (offset >> 2)+1);
-    return false;
-}
-
- /* No select in thumb, so we need to branch.  Thumb2 will do better */
-static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin)
-{
-    int offset = offsetof(InterpState, retval);
-    DecodedInstruction *dInsn = &mir->dalvikInsn;
-    int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
-    int reg1 = NEXT_REG(reg0);
-    loadValue(cUnit, dInsn->arg[0], reg0);
-    loadValue(cUnit, dInsn->arg[1], reg1);
-    newLIR2(cUnit, THUMB_CMP_RR, reg0, reg1);
-    ArmLIR *branch1 = newLIR2(cUnit, THUMB_B_COND, 2,
-           isMin ? ARM_COND_LT : ARM_COND_GT);
-    newLIR2(cUnit, THUMB_MOV_RR, reg0, reg1);
-    ArmLIR *target =
-        newLIR3(cUnit, THUMB_STR_RRI5, reg0, rGLUE, offset >> 2);
-    branch1->generic.target = (LIR *)target;
-    return false;
-}
-
-static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
-{
-    int offset = offsetof(InterpState, retval);
-    DecodedInstruction *dInsn = &mir->dalvikInsn;
-    int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
-    int ophi = NEXT_REG(oplo);
-    int sign = NEXT_REG(ophi);
-    /* abs(x) = y<=x>>31, (x+y)^y.  Shorter in ARM/THUMB2, no skip in THUMB */
-    loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
-    newLIR3(cUnit, THUMB_ASR, sign, ophi, 31);
-    newLIR3(cUnit, THUMB_ADD_RRR, oplo, oplo, sign);
-    newLIR2(cUnit, THUMB_ADC, ophi, sign);
-    newLIR2(cUnit, THUMB_EOR, oplo, sign);
-    newLIR2(cUnit, THUMB_EOR, ophi, sign);
-    newLIR3(cUnit, THUMB_STR_RRI5, oplo, rGLUE, offset >> 2);
-    newLIR3(cUnit, THUMB_STR_RRI5, ophi, rGLUE, (offset >> 2)+1);
-    return false;
-}
-
 static void genProcessArgsNoRange(CompilationUnit *cUnit, MIR *mir,
                                   DecodedInstruction *dInsn,
                                   ArmLIR **pcrLabel)
@@ -1053,15 +1639,14 @@
     }
     if (regMask) {
         /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
-        newLIR2(cUnit, THUMB_MOV_RR, r7, rFP);
-        newLIR2(cUnit, THUMB_SUB_RI8, r7,
-                sizeof(StackSaveArea) + (dInsn->vA << 2));
+        opRegRegImm(cUnit, OP_SUB, r7, rFP,
+                    sizeof(StackSaveArea) + (dInsn->vA << 2), rNone);
         /* generate null check */
         if (pcrLabel) {
             *pcrLabel = genNullCheck(cUnit, dInsn->arg[0], r0, mir->offset,
                                      NULL);
         }
-        newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+        storeMultiple(cUnit, r7, regMask);
     }
 }
 
@@ -1076,25 +1661,19 @@
      * r4PC     : &rFP[vC]
      * r7: &newFP[0]
      */
-    if (srcOffset < 8) {
-        newLIR3(cUnit, THUMB_ADD_RRI3, r4PC, rFP, srcOffset);
-    } else {
-        loadConstant(cUnit, r4PC, srcOffset);
-        newLIR3(cUnit, THUMB_ADD_RRR, r4PC, rFP, r4PC);
-    }
+    opRegRegImm(cUnit, OP_ADD, r4PC, rFP, srcOffset, rNone);
     /* load [r0 .. min(numArgs,4)] */
     regMask = (1 << ((numArgs < 4) ? numArgs : 4)) - 1;
-    newLIR2(cUnit, THUMB_LDMIA, r4PC, regMask);
+    /*
+     * Protect the loadMultiple instruction from being reordered with other
+     * Dalvik stack accesses.
+     */
+    genBarrier(cUnit);
+    loadMultiple(cUnit, r4PC, regMask);
+    genBarrier(cUnit);
 
-    if (sizeof(StackSaveArea) + (numArgs << 2) < 256) {
-        newLIR2(cUnit, THUMB_MOV_RR, r7, rFP);
-        newLIR2(cUnit, THUMB_SUB_RI8, r7,
-                sizeof(StackSaveArea) + (numArgs << 2));
-    } else {
-        loadConstant(cUnit, r7, sizeof(StackSaveArea) + (numArgs << 2));
-        newLIR3(cUnit, THUMB_SUB_RRR, r7, rFP, r7);
-    }
-
+    opRegRegImm(cUnit, OP_SUB, r7, rFP,
+                sizeof(StackSaveArea) + (numArgs << 2), rNone);
     /* generate null check */
     if (pcrLabel) {
         *pcrLabel = genNullCheck(cUnit, dInsn->vC, r0, mir->offset, NULL);
@@ -1108,37 +1687,50 @@
         ArmLIR *loopLabel = NULL;
         /*
          * r0 contains "this" and it will be used later, so push it to the stack
-         * first. Pushing r5 is just for stack alignment purposes.
+         * first. Pushing r5 (rFP) is just for stack alignment purposes.
          */
-        newLIR1(cUnit, THUMB_PUSH, 1 << r0 | 1 << 5);
+        opImm(cUnit, OP_PUSH, (1 << r0 | 1 << rFP));
         /* No need to generate the loop structure if numArgs <= 11 */
         if (numArgs > 11) {
             loadConstant(cUnit, 5, ((numArgs - 4) >> 2) << 2);
             loopLabel = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+            loopLabel->defMask = ENCODE_ALL;
         }
-        newLIR2(cUnit, THUMB_STMIA, r7, regMask);
-        newLIR2(cUnit, THUMB_LDMIA, r4PC, regMask);
+        storeMultiple(cUnit, r7, regMask);
+        /*
+         * Protect the loadMultiple instruction from being reordered with other
+         * Dalvik stack accesses.
+         */
+        genBarrier(cUnit);
+        loadMultiple(cUnit, r4PC, regMask);
+        genBarrier(cUnit);
         /* No need to generate the loop structure if numArgs <= 11 */
         if (numArgs > 11) {
-            newLIR2(cUnit, THUMB_SUB_RI8, 5, 4);
+            opRegImm(cUnit, OP_SUB, rFP, 4, rNone);
             genConditionalBranch(cUnit, ARM_COND_NE, loopLabel);
         }
     }
 
     /* Save the last batch of loaded values */
-    newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+    storeMultiple(cUnit, r7, regMask);
 
     /* Generate the loop epilogue - don't use r0 */
     if ((numArgs > 4) && (numArgs % 4)) {
         regMask = ((1 << (numArgs & 0x3)) - 1) << 1;
-        newLIR2(cUnit, THUMB_LDMIA, r4PC, regMask);
+        /*
+         * Protect the loadMultiple instruction from being reordered with other
+         * Dalvik stack accesses.
+         */
+        genBarrier(cUnit);
+        loadMultiple(cUnit, r4PC, regMask);
+        genBarrier(cUnit);
     }
     if (numArgs >= 8)
-        newLIR1(cUnit, THUMB_POP, 1 << r0 | 1 << 5);
+        opImm(cUnit, OP_POP, (1 << r0 | 1 << rFP));
 
     /* Save the modulo 4 arguments */
     if ((numArgs > 4) && (numArgs % 4)) {
-        newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+        storeMultiple(cUnit, r7, regMask);
     }
 }
 
@@ -1154,8 +1746,7 @@
     ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
 
     /* r1 = &retChainingCell */
-    ArmLIR *addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL,
-                                           r1, 0, 0);
+    ArmLIR *addrRetChain = opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
     /* r4PC = dalvikCallsite */
     loadConstant(cUnit, r4PC,
                  (int) (cUnit->method->insns + mir->offset));
@@ -1215,13 +1806,12 @@
                  (int) (cUnit->method->insns + mir->offset));
 
     /* r1 = &retChainingCell */
-    ArmLIR *addrRetChain = newLIR2(cUnit, THUMB_ADD_PC_REL,
-                                       r1, 0);
+    ArmLIR *addrRetChain = opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
     addrRetChain->generic.target = (LIR *) retChainingCell;
 
     /* r2 = &predictedChainingCell */
-    ArmLIR *predictedChainingCell =
-        newLIR2(cUnit, THUMB_ADD_PC_REL, r2, 0);
+    ArmLIR *predictedChainingCell = opRegRegImm(cUnit, OP_ADD, r2, rpc, 0,
+                                                rNone);
     predictedChainingCell->generic.target = (LIR *) predChainingCell;
 
     genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
@@ -1256,23 +1846,15 @@
      */
 
     /* r0 <- calleeMethod */
-    if (methodIndex < 32) {
-        newLIR3(cUnit, THUMB_LDR_RRI5, r0, r7, methodIndex);
-    } else {
-        loadConstant(cUnit, r0, methodIndex<<2);
-        newLIR3(cUnit, THUMB_LDR_RRR, r0, r7, r0);
-    }
+    loadWordDisp(cUnit, r7, methodIndex * 4, r0);
 
     /* Check if rechain limit is reached */
-    newLIR2(cUnit, THUMB_CMP_RI8, r1, 0);
+    opRegImm(cUnit, OP_CMP, r1, 0, rNone);
 
-    ArmLIR *bypassRechaining =
-        newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_GT);
+    ArmLIR *bypassRechaining = opCondBranch(cUnit, ARM_COND_GT);
 
-    newLIR3(cUnit, THUMB_LDR_RRI5, r7, rGLUE,
-            offsetof(InterpState,
-                     jitToInterpEntries.dvmJitToPatchPredictedChain)
-            >> 2);
+    loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+                 jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
 
     /*
      * r0 = calleeMethod
@@ -1283,10 +1865,10 @@
      * when patching the chaining cell and will be clobbered upon
      * returning so it will be reconstructed again.
      */
-    newLIR1(cUnit, THUMB_BLX_R, r7);
+    opReg(cUnit, OP_BLX, r7);
 
     /* r1 = &retChainingCell */
-    addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL, r1, 0, 0);
+    addrRetChain = opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
     addrRetChain->generic.target = (LIR *) retChainingCell;
 
     bypassRechaining->generic.target = (LIR *) addrRetChain;
@@ -1318,16 +1900,14 @@
                                           MIR *mir)
 {
     /* r3 now contains this->clazz */
-    newLIR3(cUnit, THUMB_LDR_RRI5, r3, r0,
-            offsetof(Object, clazz) >> 2);
+    loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
 
     /*
      * r2 now contains predicted class. The starting offset of the
      * cached value is 4 bytes into the chaining cell.
      */
     ArmLIR *getPredictedClass =
-        newLIR3(cUnit, THUMB_LDR_PC_REL, r2, 0,
-                offsetof(PredictedChainingCell, clazz));
+         loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, clazz), r2);
     getPredictedClass->generic.target = (LIR *) predChainingCell;
 
     /*
@@ -1335,14 +1915,12 @@
      * cached value is 8 bytes into the chaining cell.
      */
     ArmLIR *getPredictedMethod =
-        newLIR3(cUnit, THUMB_LDR_PC_REL, r0, 0,
-                offsetof(PredictedChainingCell, method));
+        loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, method), r0);
     getPredictedMethod->generic.target = (LIR *) predChainingCell;
 
     /* Load the stats counter to see if it is time to unchain and refresh */
     ArmLIR *getRechainingRequestCount =
-        newLIR3(cUnit, THUMB_LDR_PC_REL, r7, 0,
-                offsetof(PredictedChainingCell, counter));
+        loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, counter), r7);
     getRechainingRequestCount->generic.target =
         (LIR *) predChainingCell;
 
@@ -1351,14 +1929,13 @@
                  (int) (cUnit->method->insns + mir->offset));
 
     /* r1 = &retChainingCell */
-    ArmLIR *addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL,
-                                       r1, 0, 0);
+    ArmLIR *addrRetChain = opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
     addrRetChain->generic.target = (LIR *) retChainingCell;
 
     /* Check if r2 (predicted class) == r3 (actual class) */
-    newLIR2(cUnit, THUMB_CMP_RR, r2, r3);
+    opRegReg(cUnit, OP_CMP, r2, r3);
 
-    return newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_EQ);
+    return opCondBranch(cUnit, ARM_COND_EQ);
 }
 
 /* Geneate a branch to go back to the interpreter */
@@ -1366,9 +1943,10 @@
 {
     /* r0 = dalvik pc */
     loadConstant(cUnit, r0, (int) (cUnit->method->insns + offset));
-    newLIR3(cUnit, THUMB_LDR_RRI5, r1, rGLUE,
-            offsetof(InterpState, jitToInterpEntries.dvmJitToInterpPunt) >> 2);
-    newLIR1(cUnit, THUMB_BLX_R, r1);
+    loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
+    loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+                 jitToInterpEntries.dvmJitToInterpPunt), r1);
+    opReg(cUnit, OP_BLX, r1);
 }
 
 /*
@@ -1386,16 +1964,129 @@
     }
     int entryAddr = offsetof(InterpState,
                              jitToInterpEntries.dvmJitToInterpSingleStep);
-    newLIR3(cUnit, THUMB_LDR_RRI5, r2, rGLUE, entryAddr >> 2);
+    loadWordDisp(cUnit, rGLUE, entryAddr, r2);
     /* r0 = dalvik pc */
     loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset));
     /* r1 = dalvik pc of following instruction */
     loadConstant(cUnit, r1, (int) (cUnit->method->insns + mir->next->offset));
-    newLIR1(cUnit, THUMB_BLX_R, r2);
+    opReg(cUnit, OP_BLX, r2);
 }
 
+/* Generate conditional branch instructions */
+static ArmLIR *genConditionalBranch(CompilationUnit *cUnit,
+                                    ArmConditionCode cond,
+                                    ArmLIR *target)
+{
+    ArmLIR *branch = opCondBranch(cUnit, cond);
+    branch->generic.target = (LIR *) target;
+    return branch;
+}
 
-/*****************************************************************************/
+/* Generate unconditional branch instructions */
+static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
+{
+    ArmLIR *branch = opNone(cUnit, OP_UNCOND_BR);
+    branch->generic.target = (LIR *) target;
+    return branch;
+}
+
+/* Load the address of a Dalvik register on the frame */
+static ArmLIR *loadValueAddress(CompilationUnit *cUnit, int vSrc, int rDest)
+{
+    return opRegRegImm(cUnit, OP_ADD, rDest, rFP, vSrc*4, rNone);
+}
+
+/* Load a single value from rFP[src] and store them into rDest */
+static ArmLIR *loadValue(CompilationUnit *cUnit, int vSrc, int rDest)
+{
+    return loadBaseDisp(cUnit, NULL, rFP, vSrc * 4, rDest, WORD, false, -1);
+}
+
+/* Load a word at base + displacement.  Displacement must be word multiple */
+static ArmLIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
+                            int rDest)
+{
+    return loadBaseDisp(cUnit, NULL, rBase, displacement, rDest, WORD, false,
+                        -1);
+}
+
+static ArmLIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
+                             int displacement, int rSrc, int rScratch)
+{
+    return storeBaseDisp(cUnit, rBase, displacement, rSrc, WORD, rScratch);
+}
+
+/* Store a value from rSrc to vDest */
+static ArmLIR *storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
+                          int rScratch)
+{
+    killNullCheckedRegister(cUnit, vDest);
+    updateLiveRegister(cUnit, vDest, rSrc);
+    return storeBaseDisp(cUnit, rFP, vDest * 4, rSrc, WORD, rScratch);
+}
+/*
+ * Load a pair of values of rFP[src..src+1] and store them into rDestLo and
+ * rDestHi
+ */
+static ArmLIR *loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
+                             int rDestHi)
+{
+    ArmLIR *res;
+    /* Use reg + imm5*4 to load the values if possible */
+    if (vSrc <= 30) {
+        res = loadWordDisp(cUnit, rFP, vSrc*4, rDestLo);
+        loadWordDisp(cUnit, rFP, (vSrc+1)*4, rDestHi);
+    } else {
+        assert(rDestLo < rDestHi);
+        res = loadValueAddress(cUnit, vSrc, rDestLo);
+        /*
+         * Protect the loadMultiple instruction from being reordered with other
+         * Dalvik stack accesses.
+         */
+        genBarrier(cUnit);
+        loadMultiple(cUnit, rDestLo, (1<<rDestLo) | (1<<rDestHi));
+        genBarrier(cUnit);
+    }
+    return res;
+}
+
+/*
+ * Store a pair of values of rSrc and rSrc+1 and store them into vDest and
+ * vDest+1
+ */
+static ArmLIR *storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
+                              int vDest, int rScratch)
+{
+    ArmLIR *res;
+    killNullCheckedRegister(cUnit, vDest);
+    killNullCheckedRegister(cUnit, vDest+1);
+    updateLiveRegisterPair(cUnit, vDest, rSrcLo, rSrcHi);
+
+    /* Use reg + imm5*4 to store the values if possible */
+    if (vDest <= 30) {
+        res = storeWordDisp(cUnit, rFP, vDest*4, rSrcLo, rScratch);
+        storeWordDisp(cUnit, rFP, (vDest+1)*4, rSrcHi, rScratch);
+    } else {
+        assert(rSrcLo < rSrcHi);
+        res = loadValueAddress(cUnit, vDest, rScratch);
+        /*
+         * Protect the storeMultiple instruction from being reordered with
+         * other Dalvik stack accesses.
+         */
+        genBarrier(cUnit);
+        storeMultiple(cUnit, rScratch, (1<<rSrcLo) | (1 << rSrcHi));
+        genBarrier(cUnit);
+    }
+    return res;
+}
+
+static ArmLIR *genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+{
+    ArmLIR *res = dvmCompilerRegCopy(cUnit, rDest, rSrc);
+    dvmCompilerAppendLIR(cUnit, (LIR*)res);
+    return res;
+}
+
 /*
  * The following are the first-level codegen routines that analyze the format
  * of each bytecode then either dispatch special purpose codegen routines
@@ -1455,7 +2146,7 @@
             reg1 = NEXT_REG(reg0);
             reg2 = NEXT_REG(reg1);
             loadConstant(cUnit, reg0, mir->dalvikInsn.vB);
-            newLIR3(cUnit, THUMB_ASR, reg1, reg0, 31);
+            opRegRegImm(cUnit, OP_ASR, reg1, reg0, 31, rNone);
             storeValuePair(cUnit, reg0, reg1, mir->dalvikInsn.vA, reg2);
             break;
         }
@@ -1512,10 +2203,6 @@
     int regvNoneWide = selectFirstRegister(cUnit, vNone, true);
 
     switch (mir->dalvikInsn.opCode) {
-        /*
-         * TODO: Verify that we can ignore the resolution check here because
-         * it will have already successfully been interpreted once
-         */
         case OP_CONST_STRING_JUMBO:
         case OP_CONST_STRING: {
             void *strPtr = (void*)
@@ -1525,10 +2212,6 @@
             storeValue(cUnit, regvNone, mir->dalvikInsn.vA, NEXT_REG(regvNone));
             break;
         }
-        /*
-         * TODO: Verify that we can ignore the resolution check here because
-         * it will have already successfully been interpreted once
-         */
         case OP_CONST_CLASS: {
             void *classPtr = (void*)
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
@@ -1548,7 +2231,13 @@
               (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
             assert(fieldPtr != NULL);
             loadConstant(cUnit, regvNone,  (int) fieldPtr + valOffset);
-            newLIR3(cUnit, THUMB_LDR_RRI5, regvNone, regvNone, 0);
+#if !defined(WITH_SELF_VERIFICATION)
+            loadWordDisp(cUnit, regvNone, 0, regvNone);
+#else
+            int regMap = regvNone << 4 | regvNone;
+            selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationLoad);
+
+#endif
             storeValue(cUnit, regvNone, mir->dalvikInsn.vA, NEXT_REG(regvNone));
             break;
         }
@@ -1563,7 +2252,14 @@
             reg1 = NEXT_REG(reg0);
             reg2 = NEXT_REG(reg1);
             loadConstant(cUnit, reg2,  (int) fieldPtr + valOffset);
-            newLIR2(cUnit, THUMB_LDMIA, reg2, (1<<reg0 | 1<<reg1));
+#if !defined(WITH_SELF_VERIFICATION)
+            loadMultiple(cUnit, reg2, (1<<reg0 | 1<<reg1));
+#else
+            int regMap = reg1 << 8 | reg0 << 4 | reg2;
+            selfVerificationMemOpWrapper(cUnit, regMap,
+                &selfVerificationLoadDoubleword);
+
+#endif
             storeValuePair(cUnit, reg0, reg1, mir->dalvikInsn.vA, reg2);
             break;
         }
@@ -1581,7 +2277,12 @@
             loadValue(cUnit, mir->dalvikInsn.vA, regvA);
             updateLiveRegister(cUnit, mir->dalvikInsn.vA, regvA);
             loadConstant(cUnit, NEXT_REG(regvA),  (int) fieldPtr + valOffset);
-            newLIR3(cUnit, THUMB_STR_RRI5, regvA, NEXT_REG(regvA), 0);
+#if !defined(WITH_SELF_VERIFICATION)
+            storeWordDisp(cUnit, NEXT_REG(regvA), 0 , regvA, -1);
+#else
+            int regMap = regvA << 4 | NEXT_REG(regvA);
+            selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationStore);
+#endif
             break;
         }
         case OP_SPUT_WIDE: {
@@ -1597,7 +2298,13 @@
             loadValuePair(cUnit, mir->dalvikInsn.vA, reg0, reg1);
             updateLiveRegisterPair(cUnit, mir->dalvikInsn.vA, reg0, reg1);
             loadConstant(cUnit, reg2,  (int) fieldPtr + valOffset);
-            newLIR2(cUnit, THUMB_STMIA, reg2, (1<<reg0 | 1<<reg1));
+#if !defined(WITH_SELF_VERIFICATION)
+            storeMultiple(cUnit, reg2, (1<<reg0 | 1<<reg1));
+#else
+            int regMap = reg1 << 8 | reg0 << 4 | reg2;
+            selfVerificationMemOpWrapper(cUnit, regMap,
+                &selfVerificationStoreDoubleword);
+#endif
             break;
         }
         case OP_NEW_INSTANCE: {
@@ -1609,21 +2316,30 @@
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
             assert(classPtr != NULL);
             assert(classPtr->status & CLASS_INITIALIZED);
-            if ((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) != 0) {
-                /* It's going to throw, just let the interp. deal with it. */
-                genInterpSingleStep(cUnit, mir);
-                return false;
-            }
+            /*
+             * If it is going to throw, it should not make to the trace to begin
+             * with.
+             */
+            assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0);
             loadConstant(cUnit, r4PC, (int)dvmAllocObject);
             loadConstant(cUnit, r0, (int) classPtr);
             genExportPC(cUnit, mir, r2, r3 );
             loadConstant(cUnit, r1, ALLOC_DONT_TRACK);
-            newLIR1(cUnit, THUMB_BLX_R, r4PC);
+            opReg(cUnit, OP_BLX, r4PC);
+            /* generate a branch over if allocation is successful */
+            opRegImm(cUnit, OP_CMP, r0, 0, rNone); /* NULL? */
+            ArmLIR *branchOver = opCondBranch(cUnit, ARM_COND_NE);
             /*
-             * TODO: As coded, we'll bail and reinterpret on alloc failure.
-             * Need a general mechanism to bail to thrown exception code.
+             * OOM exception needs to be thrown here and cannot re-execute
              */
-            genZeroCheck(cUnit, r0, mir->offset, NULL);
+            loadConstant(cUnit, r0,
+                         (int) (cUnit->method->insns + mir->offset));
+            genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
+            /* noreturn */
+
+            ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+            target->defMask = ENCODE_ALL;
+            branchOver->generic.target = (LIR *) target;
             storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
             break;
         }
@@ -1636,27 +2352,19 @@
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
             loadConstant(cUnit, r1, (int) classPtr );
             loadValue(cUnit, mir->dalvikInsn.vA, r0);  /* Ref */
-            /*
-             * TODO - in theory classPtr should be resoved by the time this
-             * instruction made into a trace, but we are seeing NULL at runtime
-             * so this check is temporarily used as a workaround.
-             */
-            ArmLIR * pcrLabel = genZeroCheck(cUnit, r1, mir->offset, NULL);
-            newLIR2(cUnit, THUMB_CMP_RI8, r0, 0);    /* Null? */
-            ArmLIR *branch1 =
-                newLIR2(cUnit, THUMB_B_COND, 4, ARM_COND_EQ);
+            opRegImm(cUnit, OP_CMP, r0, 0, rNone);   /* Null? */
+            ArmLIR *branch1 = opCondBranch(cUnit, ARM_COND_EQ);
             /* r0 now contains object->clazz */
-            newLIR3(cUnit, THUMB_LDR_RRI5, r0, r0,
-                    offsetof(Object, clazz) >> 2);
+            loadWordDisp(cUnit, r0, offsetof(Object, clazz), r0);
             loadConstant(cUnit, r4PC, (int)dvmInstanceofNonTrivial);
-            newLIR2(cUnit, THUMB_CMP_RR, r0, r1);
-            ArmLIR *branch2 =
-                newLIR2(cUnit, THUMB_B_COND, 2, ARM_COND_EQ);
-            newLIR1(cUnit, THUMB_BLX_R, r4PC);
+            opRegReg(cUnit, OP_CMP, r0, r1);
+            ArmLIR *branch2 = opCondBranch(cUnit, ARM_COND_EQ);
+            opReg(cUnit, OP_BLX, r4PC);
             /* check cast failed - punt to the interpreter */
-            genZeroCheck(cUnit, r0, mir->offset, pcrLabel);
+            genZeroCheck(cUnit, r0, mir->offset, NULL);
             /* check cast passed - branch target here */
             ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+            target->defMask = ENCODE_ALL;
             branch1->generic.target = (LIR *)target;
             branch2->generic.target = (LIR *)target;
             break;
@@ -1674,65 +2382,61 @@
         case OP_MOVE_EXCEPTION: {
             int offset = offsetof(InterpState, self);
             int exOffset = offsetof(Thread, exception);
-            newLIR3(cUnit, THUMB_LDR_RRI5, r1, rGLUE, offset >> 2);
-            newLIR3(cUnit, THUMB_LDR_RRI5, r0, r1, exOffset >> 2);
+            loadWordDisp(cUnit, rGLUE, offset, r1);
+            loadWordDisp(cUnit, r1, exOffset, r0);
             storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
            break;
         }
         case OP_MOVE_RESULT:
         case OP_MOVE_RESULT_OBJECT: {
             int offset = offsetof(InterpState, retval);
-            newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE, offset >> 2);
+            loadWordDisp(cUnit, rGLUE, offset, r0);
             storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
             break;
         }
         case OP_MOVE_RESULT_WIDE: {
             int offset = offsetof(InterpState, retval);
-            newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE, offset >> 2);
-            newLIR3(cUnit, THUMB_LDR_RRI5, r1, rGLUE, (offset >> 2)+1);
+            loadWordDisp(cUnit, rGLUE, offset, r0);
+            loadWordDisp(cUnit, rGLUE, offset+4, r1);
             storeValuePair(cUnit, r0, r1, mir->dalvikInsn.vA, r2);
             break;
         }
         case OP_RETURN_WIDE: {
-            loadValuePair(cUnit, mir->dalvikInsn.vA, r0, r1);
+            int vSrc = mir->dalvikInsn.vA;
+            int reg0 = selectFirstRegister(cUnit, vSrc, true);
+            int reg1 = NEXT_REG(reg0);
+            int rScratch = NEXT_REG(reg1);
             int offset = offsetof(InterpState, retval);
-            newLIR3(cUnit, THUMB_STR_RRI5, r0, rGLUE, offset >> 2);
-            newLIR3(cUnit, THUMB_STR_RRI5, r1, rGLUE, (offset >> 2)+1);
+            loadValuePair(cUnit, vSrc, reg0, reg1);
+            storeWordDisp(cUnit, rGLUE, offset, reg0, rScratch);
+            storeWordDisp(cUnit, rGLUE, offset + 4, reg1, rScratch);
             genReturnCommon(cUnit,mir);
             break;
         }
         case OP_RETURN:
         case OP_RETURN_OBJECT: {
-            loadValue(cUnit, mir->dalvikInsn.vA, r0);
-            int offset = offsetof(InterpState, retval);
-            newLIR3(cUnit, THUMB_STR_RRI5, r0, rGLUE, offset >> 2);
+            int vSrc = mir->dalvikInsn.vA;
+            int reg0 = selectFirstRegister(cUnit, vSrc, false);
+            int rScratch = NEXT_REG(reg0);
+            loadValue(cUnit, vSrc, reg0);
+            storeWordDisp(cUnit, rGLUE, offsetof(InterpState, retval),
+                          reg0, rScratch);
             genReturnCommon(cUnit,mir);
             break;
         }
-        /*
-         * TODO-VERIFY: May be playing a bit fast and loose here.  As coded,
-         * a failure on lock/unlock will cause us to revert to the interpeter
-         * to try again. This means we essentially ignore the first failure on
-         * the assumption that the interpreter will correctly handle the 2nd.
-         */
         case OP_MONITOR_ENTER:
         case OP_MONITOR_EXIT: {
             int offset = offsetof(InterpState, self);
             loadValue(cUnit, mir->dalvikInsn.vA, r1);
-            newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE, offset >> 2);
+            loadWordDisp(cUnit, rGLUE, offset, r0);
             if (dalvikOpCode == OP_MONITOR_ENTER) {
                 loadConstant(cUnit, r2, (int)dvmLockObject);
             } else {
                 loadConstant(cUnit, r2, (int)dvmUnlockObject);
             }
-          /*
-           * TODO-VERIFY: Note that we're not doing an EXPORT_PC, as
-           * Lock/unlock won't throw, and this code does not support
-           * DEADLOCK_PREDICTION or MONITOR_TRACKING.  Should it?
-           */
             genNullCheck(cUnit, mir->dalvikInsn.vA, r1, mir->offset, NULL);
             /* Do the call */
-            newLIR1(cUnit, THUMB_BLX_R, r2);
+            opReg(cUnit, OP_BLX, r2);
             break;
         }
         case OP_THROW: {
@@ -1757,6 +2461,8 @@
     int    __aeabi_d2iz( double op1 );
     float  __aeabi_l2f(  long op1 );
     double __aeabi_l2d(  long op1 );
+    s8 dvmJitf2l( float op1 );
+    s8 dvmJitd2l( double op1 );
 
     switch (opCode) {
         case OP_INT_TO_FLOAT:
@@ -1792,8 +2498,6 @@
     int vSrc2 = mir->dalvikInsn.vB;
     int reg0, reg1, reg2;
 
-    /* TODO - find the proper include file to declare these */
-
     if ( (opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
         return genArithOp( cUnit, mir );
     }
@@ -1843,7 +2547,7 @@
             reg2 = NEXT_REG(reg1);
 
             loadValue(cUnit, vSrc2, reg0);
-            newLIR3(cUnit, THUMB_ASR, reg1, reg0, 31);
+            opRegRegImm(cUnit, OP_ASR, reg1, reg0, 31, rNone);
             storeValuePair(cUnit, reg0, reg1, vSrc1Dest, reg2);
             break;
         }
@@ -1855,27 +2559,24 @@
             break;
         case OP_INT_TO_BYTE:
             loadValue(cUnit, vSrc2, reg0);
-            newLIR3(cUnit, THUMB_LSL, reg0, reg0, 24);
-            newLIR3(cUnit, THUMB_ASR, reg0, reg0, 24);
-            storeValue(cUnit, reg0, vSrc1Dest, reg1);
+            opRegReg(cUnit, OP_2BYTE, reg1, reg0);
+            storeValue(cUnit, reg1, vSrc1Dest, reg2);
             break;
         case OP_INT_TO_SHORT:
             loadValue(cUnit, vSrc2, reg0);
-            newLIR3(cUnit, THUMB_LSL, reg0, reg0, 16);
-            newLIR3(cUnit, THUMB_ASR, reg0, reg0, 16);
-            storeValue(cUnit, reg0, vSrc1Dest, reg1);
+            opRegReg(cUnit, OP_2SHORT, reg1, reg0);
+            storeValue(cUnit, reg1, vSrc1Dest, reg2);
             break;
         case OP_INT_TO_CHAR:
             loadValue(cUnit, vSrc2, reg0);
-            newLIR3(cUnit, THUMB_LSL, reg0, reg0, 16);
-            newLIR3(cUnit, THUMB_LSR, reg0, reg0, 16);
-            storeValue(cUnit, reg0, vSrc1Dest, reg1);
+            opRegReg(cUnit, OP_2CHAR, reg1, reg0);
+            storeValue(cUnit, reg1, vSrc1Dest, reg2);
             break;
         case OP_ARRAY_LENGTH: {
             int lenOffset = offsetof(ArrayObject, length);
-            loadValue(cUnit, vSrc2, reg0);
-            genNullCheck(cUnit, vSrc2, reg0, mir->offset, NULL);
-            newLIR3(cUnit, THUMB_LDR_RRI5, reg0, reg0, lenOffset >> 2);
+            loadValue(cUnit, vSrc2, reg1);
+            genNullCheck(cUnit, vSrc2, reg1, mir->offset, NULL);
+            loadWordDisp(cUnit, reg1, lenOffset, reg0);
             storeValue(cUnit, reg0, vSrc1Dest, reg1);
             break;
         }
@@ -1900,7 +2601,7 @@
         reg2 = NEXT_REG(reg1);
 
         loadConstant(cUnit, reg0, BBBB);
-        newLIR3(cUnit, THUMB_ASR, reg1, reg0, 31);
+        opRegRegImm(cUnit, OP_ASR, reg1, reg0, 31, rNone);
 
         /* Save the long values to the specified Dalvik register pair */
         storeValuePair(cUnit, reg0, reg1, vDest, reg2);
@@ -1928,8 +2629,9 @@
     int reg0 = selectFirstRegister(cUnit, mir->dalvikInsn.vA, false);
 
     loadValue(cUnit, mir->dalvikInsn.vA, reg0);
-    newLIR2(cUnit, THUMB_CMP_RI8, reg0, 0);
+    opRegImm(cUnit, OP_CMP, reg0, 0, rNone);
 
+//TUNING: break this out to allow use of Thumb2 CB[N]Z
     switch (dalvikOpCode) {
         case OP_IF_EQZ:
             cond = ARM_COND_EQ;
@@ -1966,14 +2668,13 @@
     int vSrc = mir->dalvikInsn.vB;
     int vDest = mir->dalvikInsn.vA;
     int lit = mir->dalvikInsn.vC;
-    int armOp;
+    OpKind op = 0;      /* Make gcc happy */
     int reg0, reg1, regDest;
 
     reg0 = selectFirstRegister(cUnit, vSrc, false);
     reg1 = NEXT_REG(reg0);
     regDest = NEXT_REG(reg1);
 
-    /* TODO: find the proper .h file to declare these */
     int __aeabi_idivmod(int op1, int op2);
     int __aeabi_idiv(int op1, int op2);
 
@@ -1981,31 +2682,16 @@
         case OP_ADD_INT_LIT8:
         case OP_ADD_INT_LIT16:
             loadValue(cUnit, vSrc, reg0);
-            if (lit <= 7 && lit >= 0) {
-                newLIR3(cUnit, THUMB_ADD_RRI3, regDest, reg0, lit);
-                storeValue(cUnit, regDest, vDest, reg1);
-            } else if (lit <= 255 && lit >= 0) {
-                newLIR2(cUnit, THUMB_ADD_RI8, reg0, lit);
-                storeValue(cUnit, reg0, vDest, reg1);
-            } else if (lit >= -7 && lit <= 0) {
-                /* Convert to a small constant subtraction */
-                newLIR3(cUnit, THUMB_SUB_RRI3, regDest, reg0, -lit);
-                storeValue(cUnit, regDest, vDest, reg1);
-            } else if (lit >= -255 && lit <= 0) {
-                /* Convert to a small constant subtraction */
-                newLIR2(cUnit, THUMB_SUB_RI8, reg0, -lit);
-                storeValue(cUnit, reg0, vDest, reg1);
-            } else {
-                loadConstant(cUnit, reg1, lit);
-                genBinaryOp(cUnit, vDest, THUMB_ADD_RRR, reg0, reg1, regDest);
-            }
+            opRegImm(cUnit, OP_ADD, reg0, lit, reg1);
+            storeValue(cUnit, reg0, vDest, reg1);
             break;
 
         case OP_RSUB_INT_LIT8:
         case OP_RSUB_INT:
             loadValue(cUnit, vSrc, reg1);
             loadConstant(cUnit, reg0, lit);
-            genBinaryOp(cUnit, vDest, THUMB_SUB_RRR, reg0, reg1, regDest);
+            opRegRegReg(cUnit, OP_SUB, regDest, reg0, reg1);
+            storeValue(cUnit, regDest, vDest, reg1);
             break;
 
         case OP_MUL_INT_LIT8:
@@ -2017,28 +2703,28 @@
         case OP_XOR_INT_LIT8:
         case OP_XOR_INT_LIT16:
             loadValue(cUnit, vSrc, reg0);
-            loadConstant(cUnit, reg1, lit);
             switch (dalvikOpCode) {
                 case OP_MUL_INT_LIT8:
                 case OP_MUL_INT_LIT16:
-                    armOp = THUMB_MUL;
+                    op = OP_MUL;
                     break;
                 case OP_AND_INT_LIT8:
                 case OP_AND_INT_LIT16:
-                    armOp = THUMB_AND_RR;
+                    op = OP_AND;
                     break;
                 case OP_OR_INT_LIT8:
                 case OP_OR_INT_LIT16:
-                    armOp = THUMB_ORR;
+                    op = OP_OR;
                     break;
                 case OP_XOR_INT_LIT8:
                 case OP_XOR_INT_LIT16:
-                    armOp = THUMB_EOR;
+                    op = OP_XOR;
                     break;
                 default:
                     dvmAbort();
             }
-            genBinaryOp(cUnit, vDest, armOp, reg0, reg1, regDest);
+            opRegRegImm(cUnit, op, regDest, reg0, lit, reg1);
+            storeValue(cUnit, regDest, vDest, reg1);
             break;
 
         case OP_SHL_INT_LIT8:
@@ -2047,18 +2733,22 @@
             loadValue(cUnit, vSrc, reg0);
             switch (dalvikOpCode) {
                 case OP_SHL_INT_LIT8:
-                    armOp = THUMB_LSL;
+                    op = OP_LSL;
                     break;
                 case OP_SHR_INT_LIT8:
-                    armOp = THUMB_ASR;
+                    op = OP_ASR;
                     break;
                 case OP_USHR_INT_LIT8:
-                    armOp = THUMB_LSR;
+                    op = OP_LSR;
                     break;
                 default: dvmAbort();
             }
-            newLIR3(cUnit, armOp, reg0, reg0, lit);
-            storeValue(cUnit, reg0, vDest, reg1);
+            if (lit != 0) {
+                opRegRegImm(cUnit, op, regDest, reg0, lit, reg1);
+                storeValue(cUnit, regDest, vDest, reg1);
+            } else {
+                storeValue(cUnit, reg0, vDest, reg1);
+            }
             break;
 
         case OP_DIV_INT_LIT8:
@@ -2072,7 +2762,7 @@
             loadConstant(cUnit, r2, (int)__aeabi_idiv);
             loadConstant(cUnit, r1, lit);
             loadValue(cUnit, vSrc, r0);
-            newLIR1(cUnit, THUMB_BLX_R, r2);
+            opReg(cUnit, OP_BLX, r2);
             storeValue(cUnit, r0, vDest, r2);
             break;
 
@@ -2087,7 +2777,7 @@
             loadConstant(cUnit, r2, (int)__aeabi_idivmod);
             loadConstant(cUnit, r1, lit);
             loadValue(cUnit, vSrc, r0);
-            newLIR1(cUnit, THUMB_BLX_R, r2);
+            opReg(cUnit, OP_BLX, r2);
             storeValue(cUnit, r1, vDest, r2);
             break;
         default:
@@ -2104,19 +2794,14 @@
     if (dalvikOpCode >= OP_IGET && dalvikOpCode <= OP_IPUT_SHORT) {
         InstField *pInstField = (InstField *)
             cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC];
-        int fieldOffset;
 
         assert(pInstField != NULL);
         fieldOffset = pInstField->byteOffset;
     } else {
-        /* To make the compiler happy */
-        fieldOffset = 0;
+        /* Deliberately break the code while make the compiler happy */
+        fieldOffset = -1;
     }
     switch (dalvikOpCode) {
-        /*
-         * TODO: I may be assuming too much here.
-         * Verify what is known at JIT time.
-         */
         case OP_NEW_ARRAY: {
             void *classPtr = (void*)
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
@@ -2124,46 +2809,54 @@
             loadValue(cUnit, mir->dalvikInsn.vB, r1);  /* Len */
             loadConstant(cUnit, r0, (int) classPtr );
             loadConstant(cUnit, r4PC, (int)dvmAllocArrayByClass);
+            /*
+             * "len < 0": bail to the interpreter to re-execute the
+             * instruction
+             */
             ArmLIR *pcrLabel =
                 genRegImmCheck(cUnit, ARM_COND_MI, r1, 0, mir->offset, NULL);
             genExportPC(cUnit, mir, r2, r3 );
-            newLIR2(cUnit, THUMB_MOV_IMM,r2,ALLOC_DONT_TRACK);
-            newLIR1(cUnit, THUMB_BLX_R, r4PC);
+            loadConstant(cUnit, r2, ALLOC_DONT_TRACK);
+            opReg(cUnit, OP_BLX, r4PC);
+            /* generate a branch over if allocation is successful */
+            opRegImm(cUnit, OP_CMP, r0, 0, rNone); /* NULL? */
+            ArmLIR *branchOver = opCondBranch(cUnit, ARM_COND_NE);
             /*
-             * TODO: As coded, we'll bail and reinterpret on alloc failure.
-             * Need a general mechanism to bail to thrown exception code.
+             * OOM exception needs to be thrown here and cannot re-execute
              */
-            genZeroCheck(cUnit, r0, mir->offset, pcrLabel);
+            loadConstant(cUnit, r0,
+                         (int) (cUnit->method->insns + mir->offset));
+            genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
+            /* noreturn */
+
+            ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+            target->defMask = ENCODE_ALL;
+            branchOver->generic.target = (LIR *) target;
             storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
             break;
         }
-        /*
-         * TODO: I may be assuming too much here.
-         * Verify what is known at JIT time.
-         */
         case OP_INSTANCE_OF: {
             ClassObject *classPtr =
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
             assert(classPtr != NULL);
             loadValue(cUnit, mir->dalvikInsn.vB, r0);  /* Ref */
             loadConstant(cUnit, r2, (int) classPtr );
-            newLIR2(cUnit, THUMB_CMP_RI8, r0, 0);    /* Null? */
+//TUNING: compare to 0 primative to allow use of CB[N]Z
+            opRegImm(cUnit, OP_CMP, r0, 0, rNone); /* NULL? */
             /* When taken r0 has NULL which can be used for store directly */
-            ArmLIR *branch1 = newLIR2(cUnit, THUMB_B_COND, 4,
-                                          ARM_COND_EQ);
+            ArmLIR *branch1 = opCondBranch(cUnit, ARM_COND_EQ);
             /* r1 now contains object->clazz */
-            newLIR3(cUnit, THUMB_LDR_RRI5, r1, r0,
-                    offsetof(Object, clazz) >> 2);
+            loadWordDisp(cUnit, r0, offsetof(Object, clazz), r1);
             loadConstant(cUnit, r4PC, (int)dvmInstanceofNonTrivial);
             loadConstant(cUnit, r0, 1);                /* Assume true */
-            newLIR2(cUnit, THUMB_CMP_RR, r1, r2);
-            ArmLIR *branch2 = newLIR2(cUnit, THUMB_B_COND, 2,
-                                          ARM_COND_EQ);
-            newLIR2(cUnit, THUMB_MOV_RR, r0, r1);
-            newLIR2(cUnit, THUMB_MOV_RR, r1, r2);
-            newLIR1(cUnit, THUMB_BLX_R, r4PC);
+            opRegReg(cUnit, OP_CMP, r1, r2);
+            ArmLIR *branch2 = opCondBranch(cUnit, ARM_COND_EQ);
+            opRegReg(cUnit, OP_MOV, r0, r1);
+            opRegReg(cUnit, OP_MOV, r1, r2);
+            opReg(cUnit, OP_BLX, r4PC);
             /* branch target here */
             ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+            target->defMask = ENCODE_ALL;
             storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
             branch1->generic.target = (LIR *)target;
             branch2->generic.target = (LIR *)target;
@@ -2174,34 +2867,34 @@
             break;
         case OP_IGET:
         case OP_IGET_OBJECT:
-            genIGet(cUnit, mir, THUMB_LDR_RRR, fieldOffset);
+            genIGet(cUnit, mir, WORD, fieldOffset);
             break;
         case OP_IGET_BOOLEAN:
-            genIGet(cUnit, mir, THUMB_LDRB_RRR, fieldOffset);
+            genIGet(cUnit, mir, UNSIGNED_BYTE, fieldOffset);
             break;
         case OP_IGET_BYTE:
-            genIGet(cUnit, mir, THUMB_LDRSB_RRR, fieldOffset);
+            genIGet(cUnit, mir, SIGNED_BYTE, fieldOffset);
             break;
         case OP_IGET_CHAR:
-            genIGet(cUnit, mir, THUMB_LDRH_RRR, fieldOffset);
+            genIGet(cUnit, mir, UNSIGNED_HALF, fieldOffset);
             break;
         case OP_IGET_SHORT:
-            genIGet(cUnit, mir, THUMB_LDRSH_RRR, fieldOffset);
+            genIGet(cUnit, mir, SIGNED_HALF, fieldOffset);
             break;
         case OP_IPUT_WIDE:
             genIPutWide(cUnit, mir, fieldOffset);
             break;
         case OP_IPUT:
         case OP_IPUT_OBJECT:
-            genIPut(cUnit, mir, THUMB_STR_RRR, fieldOffset);
+            genIPut(cUnit, mir, WORD, fieldOffset);
             break;
         case OP_IPUT_SHORT:
         case OP_IPUT_CHAR:
-            genIPut(cUnit, mir, THUMB_STRH_RRR, fieldOffset);
+            genIPut(cUnit, mir, UNSIGNED_HALF, fieldOffset);
             break;
         case OP_IPUT_BYTE:
         case OP_IPUT_BOOLEAN:
-            genIPut(cUnit, mir, THUMB_STRB_RRR, fieldOffset);
+            genIPut(cUnit, mir, UNSIGNED_BYTE, fieldOffset);
             break;
         default:
             return true;
@@ -2216,11 +2909,11 @@
     switch (dalvikOpCode) {
         case OP_IGET_QUICK:
         case OP_IGET_OBJECT_QUICK:
-            genIGet(cUnit, mir, THUMB_LDR_RRR, fieldOffset);
+            genIGet(cUnit, mir, WORD, fieldOffset);
             break;
         case OP_IPUT_QUICK:
         case OP_IPUT_OBJECT_QUICK:
-            genIPut(cUnit, mir, THUMB_STR_RRR, fieldOffset);
+            genIPut(cUnit, mir, WORD, fieldOffset);
             break;
         case OP_IGET_WIDE_QUICK:
             genIGetWide(cUnit, mir, fieldOffset);
@@ -2256,7 +2949,7 @@
         loadValue(cUnit, mir->dalvikInsn.vA, reg0);
         loadValue(cUnit, mir->dalvikInsn.vB, reg1);
     }
-    newLIR2(cUnit, THUMB_CMP_RR, reg0, reg1);
+    opRegReg(cUnit, OP_CMP, reg0, reg1);
 
     switch (dalvikOpCode) {
         case OP_IF_EQ:
@@ -2340,44 +3033,41 @@
         case OP_CMPG_DOUBLE:
             return genCmpX(cUnit, mir, vA, vB, vC);
         case OP_CMP_LONG:
-            loadValuePair(cUnit,vB, r0, r1);
-            loadValuePair(cUnit, vC, r2, r3);
-            genDispatchToHandler(cUnit, TEMPLATE_CMP_LONG);
-            storeValue(cUnit, r0, vA, r1);
+            genCmpLong(cUnit, mir, vA, vB, vC);
             break;
         case OP_AGET_WIDE:
-            genArrayGet(cUnit, mir, THUMB_LDR_RRR, vB, vC, vA, 3);
+            genArrayGet(cUnit, mir, LONG, vB, vC, vA, 3);
             break;
         case OP_AGET:
         case OP_AGET_OBJECT:
-            genArrayGet(cUnit, mir, THUMB_LDR_RRR, vB, vC, vA, 2);
+            genArrayGet(cUnit, mir, WORD, vB, vC, vA, 2);
             break;
         case OP_AGET_BOOLEAN:
-            genArrayGet(cUnit, mir, THUMB_LDRB_RRR, vB, vC, vA, 0);
+            genArrayGet(cUnit, mir, UNSIGNED_BYTE, vB, vC, vA, 0);
             break;
         case OP_AGET_BYTE:
-            genArrayGet(cUnit, mir, THUMB_LDRSB_RRR, vB, vC, vA, 0);
+            genArrayGet(cUnit, mir, SIGNED_BYTE, vB, vC, vA, 0);
             break;
         case OP_AGET_CHAR:
-            genArrayGet(cUnit, mir, THUMB_LDRH_RRR, vB, vC, vA, 1);
+            genArrayGet(cUnit, mir, UNSIGNED_HALF, vB, vC, vA, 1);
             break;
         case OP_AGET_SHORT:
-            genArrayGet(cUnit, mir, THUMB_LDRSH_RRR, vB, vC, vA, 1);
+            genArrayGet(cUnit, mir, SIGNED_HALF, vB, vC, vA, 1);
             break;
         case OP_APUT_WIDE:
-            genArrayPut(cUnit, mir, THUMB_STR_RRR, vB, vC, vA, 3);
+            genArrayPut(cUnit, mir, LONG, vB, vC, vA, 3);
             break;
         case OP_APUT:
         case OP_APUT_OBJECT:
-            genArrayPut(cUnit, mir, THUMB_STR_RRR, vB, vC, vA, 2);
+            genArrayPut(cUnit, mir, WORD, vB, vC, vA, 2);
             break;
         case OP_APUT_SHORT:
         case OP_APUT_CHAR:
-            genArrayPut(cUnit, mir, THUMB_STRH_RRR, vB, vC, vA, 1);
+            genArrayPut(cUnit, mir, UNSIGNED_HALF, vB, vC, vA, 1);
             break;
         case OP_APUT_BYTE:
         case OP_APUT_BOOLEAN:
-            genArrayPut(cUnit, mir, THUMB_STRB_RRR, vB, vC, vA, 0);
+            genArrayPut(cUnit, mir, UNSIGNED_BYTE, vB, vC, vA, 0);
             break;
         default:
             return true;
@@ -2395,7 +3085,7 @@
             loadConstant(cUnit, r1, (mir->dalvikInsn.vB << 1) +
                  (int) (cUnit->method->insns + mir->offset));
             genExportPC(cUnit, mir, r2, r3 );
-            newLIR1(cUnit, THUMB_BLX_R, r4PC);
+            opReg(cUnit, OP_BLX, r4PC);
             genZeroCheck(cUnit, r0, mir->offset, NULL);
             break;
         }
@@ -2415,14 +3105,13 @@
             loadValue(cUnit, mir->dalvikInsn.vA, r1);
             loadConstant(cUnit, r0, (mir->dalvikInsn.vB << 1) +
                  (int) (cUnit->method->insns + mir->offset));
-            newLIR1(cUnit, THUMB_BLX_R, r4PC);
+            opReg(cUnit, OP_BLX, r4PC);
             loadConstant(cUnit, r1, (int)(cUnit->method->insns + mir->offset));
-            newLIR3(cUnit, THUMB_LDR_RRI5, r2, rGLUE,
-                offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNoChain)
-                    >> 2);
-            newLIR3(cUnit, THUMB_ADD_RRR, r0, r0, r0);
-            newLIR3(cUnit, THUMB_ADD_RRR, r4PC, r0, r1);
-            newLIR1(cUnit, THUMB_BLX_R, r2);
+            loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+                         jitToInterpEntries.dvmJitToInterpNoChain), r2);
+            opRegReg(cUnit, OP_ADD, r0, r0);
+            opRegRegReg(cUnit, OP_ADD, r4PC, r0, r1);
+            opReg(cUnit, OP_BLX, r2);
             break;
         }
         default:
@@ -2527,6 +3216,11 @@
                                      calleeMethod);
             break;
         }
+/*
+ * TODO:  When we move to using upper registers in Thumb2, make sure
+ *        the register allocater is told that r9, r10, & r12 are killed
+ *        here.
+ */
         /*
          * calleeMethod = dvmFindInterfaceMethodInCache(this->clazz,
          *                    BBBB, method, method->clazz->pDvmDex)
@@ -2608,13 +3302,13 @@
                          (int) (cUnit->method->insns + mir->offset));
 
             /* r1 = &retChainingCell */
-            ArmLIR *addrRetChain = newLIR2(cUnit, THUMB_ADD_PC_REL,
-                                               r1, 0);
+            ArmLIR *addrRetChain =
+                opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
             addrRetChain->generic.target = (LIR *) retChainingCell;
 
             /* r2 = &predictedChainingCell */
             ArmLIR *predictedChainingCell =
-                newLIR2(cUnit, THUMB_ADD_PC_REL, r2, 0);
+                opRegRegImm(cUnit, OP_ADD, r2, rpc, 0, rNone);
             predictedChainingCell->generic.target = (LIR *) predChainingCell;
 
             genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
@@ -2649,12 +3343,12 @@
              */
 
             /* Save count, &predictedChainCell, and class to high regs first */
-            newLIR2(cUnit, THUMB_MOV_RR_L2H, r9 & THUMB_REG_MASK, r1);
-            newLIR2(cUnit, THUMB_MOV_RR_L2H, r10 & THUMB_REG_MASK, r2);
-            newLIR2(cUnit, THUMB_MOV_RR_L2H, r12 & THUMB_REG_MASK, r3);
+            opRegReg(cUnit, OP_MOV, r9, r1);
+            opRegReg(cUnit, OP_MOV, r10, r2);
+            opRegReg(cUnit, OP_MOV, r12, r3);
 
             /* r0 now contains this->clazz */
-            newLIR2(cUnit, THUMB_MOV_RR, r0, r3);
+            opRegReg(cUnit, OP_MOV, r0, r3);
 
             /* r1 = BBBB */
             loadConstant(cUnit, r1, dInsn->vB);
@@ -2667,25 +3361,22 @@
 
             loadConstant(cUnit, r7,
                          (intptr_t) dvmFindInterfaceMethodInCache);
-            newLIR1(cUnit, THUMB_BLX_R, r7);
+            opReg(cUnit, OP_BLX, r7);
 
             /* r0 = calleeMethod (returned from dvmFindInterfaceMethodInCache */
 
-            newLIR2(cUnit, THUMB_MOV_RR_H2L, r1, r9 & THUMB_REG_MASK);
+            opRegReg(cUnit, OP_MOV, r1, r9);
 
             /* Check if rechain limit is reached */
-            newLIR2(cUnit, THUMB_CMP_RI8, r1, 0);
+            opRegImm(cUnit, OP_CMP, r1, 0, rNone);
 
-            ArmLIR *bypassRechaining =
-                newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_GT);
+            ArmLIR *bypassRechaining = opCondBranch(cUnit, ARM_COND_GT);
 
-            newLIR3(cUnit, THUMB_LDR_RRI5, r7, rGLUE,
-                    offsetof(InterpState,
-                             jitToInterpEntries.dvmJitToPatchPredictedChain)
-                    >> 2);
+            loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+                         jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
 
-            newLIR2(cUnit, THUMB_MOV_RR_H2L, r2, r10 & THUMB_REG_MASK);
-            newLIR2(cUnit, THUMB_MOV_RR_H2L, r3, r12 & THUMB_REG_MASK);
+            opRegReg(cUnit, OP_MOV, r2, r10);
+            opRegReg(cUnit, OP_MOV, r3, r12);
 
             /*
              * r0 = calleeMethod
@@ -2696,11 +3387,10 @@
              * when patching the chaining cell and will be clobbered upon
              * returning so it will be reconstructed again.
              */
-            newLIR1(cUnit, THUMB_BLX_R, r7);
+            opReg(cUnit, OP_BLX, r7);
 
             /* r1 = &retChainingCell */
-            addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL,
-                                               r1, 0, 0);
+            addrRetChain = opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
             addrRetChain->generic.target = (LIR *) retChainingCell;
 
             bypassRechaining->generic.target = (LIR *) addrRetChain;
@@ -2821,14 +3511,7 @@
                     else
                         break;   /* Handle with C routine */
                 case INLINE_MATH_COS:
-                    if (genInlineCos(cUnit, mir))
-                        return false;
-                    else
-                        break;   /* Handle with C routine */
                 case INLINE_MATH_SIN:
-                    if (genInlineSin(cUnit, mir))
-                        return false;
-                    else
                         break;   /* Handle with C routine */
                 case INLINE_MATH_ABS_FLOAT:
                     return genInlinedAbsFloat(cUnit, mir);
@@ -2836,16 +3519,19 @@
                     return genInlinedAbsDouble(cUnit, mir);
                 case INLINE_STRING_COMPARETO:
                 case INLINE_STRING_EQUALS:
+                case INLINE_STRING_INDEXOF_I:
+                case INLINE_STRING_INDEXOF_II:
                     break;
                 default:
                     dvmAbort();
             }
 
             /* Materialize pointer to retval & push */
-            newLIR2(cUnit, THUMB_MOV_RR, r4PC, rGLUE);
-            newLIR2(cUnit, THUMB_ADD_RI8, r4PC, offset);
+            opRegReg(cUnit, OP_MOV, r4PC, rGLUE);
+            opRegImm(cUnit, OP_ADD, r4PC, offset, rNone);
+
             /* Push r4 and (just to take up space) r5) */
-            newLIR1(cUnit, THUMB_PUSH, (1<<r4PC | 1<<rFP));
+            opImm(cUnit, OP_PUSH, (1 << r4PC | 1 << rFP));
 
             /* Get code pointer to inline routine */
             loadConstant(cUnit, r4PC, (int)inLineTable[operation].func);
@@ -2858,10 +3544,10 @@
                 loadValue(cUnit, dInsn->arg[i], i);
             }
             /* Call inline routine */
-            newLIR1(cUnit, THUMB_BLX_R, r4PC);
+            opReg(cUnit, OP_BLX, r4PC);
 
             /* Strip frame */
-            newLIR1(cUnit, THUMB_ADD_SPI7, 2);
+            opRegImm(cUnit, OP_ADD, r13, 8, rNone);
 
             /* Did we throw? If so, redo under interpreter*/
             genZeroCheck(cUnit, r0, mir->offset, NULL);
@@ -2883,7 +3569,6 @@
     return false;
 }
 
-/*****************************************************************************/
 /*
  * The following are special processing routines that handle transfer of
  * controls between compiled code and the interpreter. Certain VM states like
@@ -2894,9 +3579,9 @@
 static void handleNormalChainingCell(CompilationUnit *cUnit,
                                      unsigned int offset)
 {
-    newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE,
-        offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
-    newLIR1(cUnit, THUMB_BLX_R, r0);
+    loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+                 jitToInterpEntries.dvmJitToInterpNormal), r0);
+    opReg(cUnit, OP_BLX, r0);
     addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
 }
 
@@ -2907,19 +3592,36 @@
 static void handleHotChainingCell(CompilationUnit *cUnit,
                                   unsigned int offset)
 {
+    loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+                 jitToInterpEntries.dvmJitToTraceSelect), r0);
+    opReg(cUnit, OP_BLX, r0);
+    addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
+}
+
+#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
+/* Chaining cell for branches that branch back into the same basic block */
+static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
+                                             unsigned int offset)
+{
+#if defined(WITH_SELF_VERIFICATION)
     newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE,
-        offsetof(InterpState, jitToInterpEntries.dvmJitToTraceSelect) >> 2);
+        offsetof(InterpState, jitToInterpEntries.dvmJitToBackwardBranch) >> 2);
+#else
+    newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE,
+        offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
+#endif
     newLIR1(cUnit, THUMB_BLX_R, r0);
     addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
 }
 
+#endif
 /* Chaining cell for monomorphic method invocations. */
 static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
                                               const Method *callee)
 {
-    newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE,
-        offsetof(InterpState, jitToInterpEntries.dvmJitToTraceSelect) >> 2);
-    newLIR1(cUnit, THUMB_BLX_R, r0);
+    loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+                 jitToInterpEntries.dvmJitToTraceSelect), r0);
+    opReg(cUnit, OP_BLX, r0);
     addWordData(cUnit, (int) (callee->insns), true);
 }
 
@@ -2956,7 +3658,185 @@
     }
 }
 
-/* Entry function to invoke the backend of the JIT compiler */
+static char *extendedMIROpNames[MIR_OP_LAST - MIR_OP_FIRST] = {
+    "MIR_OP_PHI",
+    "MIR_OP_NULL_N_RANGE_UP_CHECK",
+    "MIR_OP_NULL_N_RANGE_DOWN_CHECK",
+    "MIR_OP_LOWER_BOUND_CHECK",
+    "MIR_OP_PUNT",
+};
+
+/*
+ * vA = arrayReg;
+ * vB = idxReg;
+ * vC = endConditionReg;
+ * arg[0] = maxC
+ * arg[1] = minC
+ * arg[2] = loopBranchConditionCode
+ */
+static void genHoistedChecksForCountUpLoop(CompilationUnit *cUnit, MIR *mir)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    const int lenOffset = offsetof(ArrayObject, length);
+    const int regArray = 0;
+    const int regIdxEnd = NEXT_REG(regArray);
+    const int regLength = regArray;
+    const int maxC = dInsn->arg[0];
+    const int minC = dInsn->arg[1];
+
+    /* regArray <- arrayRef */
+    loadValue(cUnit, mir->dalvikInsn.vA, regArray);
+    loadValue(cUnit, mir->dalvikInsn.vC, regIdxEnd);
+    genRegImmCheck(cUnit, ARM_COND_EQ, regArray, 0, 0,
+                   (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+
+    /* regLength <- len(arrayRef) */
+    loadWordDisp(cUnit, regArray, lenOffset, regLength);
+
+    int delta = maxC;
+    /*
+     * If the loop end condition is ">=" instead of ">", then the largest value
+     * of the index is "endCondition - 1".
+     */
+    if (dInsn->arg[2] == OP_IF_GE) {
+        delta--;
+    }
+
+    if (delta) {
+        opRegImm(cUnit, OP_ADD, regIdxEnd, delta, regIdxEnd);
+    }
+    /* Punt if "regIdxEnd < len(Array)" is false */
+    genRegRegCheck(cUnit, ARM_COND_GE, regIdxEnd, regLength, 0,
+                   (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+}
+
+/*
+ * vA = arrayReg;
+ * vB = idxReg;
+ * vC = endConditionReg;
+ * arg[0] = maxC
+ * arg[1] = minC
+ * arg[2] = loopBranchConditionCode
+ */
+static void genHoistedChecksForCountDownLoop(CompilationUnit *cUnit, MIR *mir)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    const int lenOffset = offsetof(ArrayObject, length);
+    const int regArray = 0;
+    const int regIdxInit = NEXT_REG(regArray);
+    const int regLength = regArray;
+    const int maxC = dInsn->arg[0];
+    const int minC = dInsn->arg[1];
+
+    /* regArray <- arrayRef */
+    loadValue(cUnit, mir->dalvikInsn.vA, regArray);
+    loadValue(cUnit, mir->dalvikInsn.vB, regIdxInit);
+    genRegImmCheck(cUnit, ARM_COND_EQ, regArray, 0, 0,
+                   (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+
+    /* regLength <- len(arrayRef) */
+    loadWordDisp(cUnit, regArray, lenOffset, regLength);
+
+    if (maxC) {
+        opRegImm(cUnit, OP_ADD, regIdxInit, maxC, regIdxInit);
+    }
+
+    /* Punt if "regIdxInit < len(Array)" is false */
+    genRegRegCheck(cUnit, ARM_COND_GE, regIdxInit, regLength, 0,
+                   (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+}
+
+/*
+ * vA = idxReg;
+ * vB = minC;
+ */
+static void genHoistedLowerBoundCheck(CompilationUnit *cUnit, MIR *mir)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    const int regIdx = 0;
+    const int minC = dInsn->vB;
+
+    /* regIdx <- initial index value */
+    loadValue(cUnit, mir->dalvikInsn.vA, regIdx);
+
+    /* Punt if "regIdxInit + minC >= 0" is false */
+    genRegImmCheck(cUnit, ARM_COND_LT, regIdx, -minC, 0,
+                   (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+}
+
+/* Extended MIR instructions like PHI */
+static void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir)
+{
+    int opOffset = mir->dalvikInsn.opCode - MIR_OP_FIRST;
+    char *msg = dvmCompilerNew(strlen(extendedMIROpNames[opOffset]) + 1,
+                               false);
+    strcpy(msg, extendedMIROpNames[opOffset]);
+    newLIR1(cUnit, ARM_PSEUDO_EXTENDED_MIR, (int) msg);
+
+    switch (mir->dalvikInsn.opCode) {
+        case MIR_OP_PHI: {
+            char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
+            newLIR1(cUnit, ARM_PSEUDO_SSA_REP, (int) ssaString);
+            break;
+        }
+        case MIR_OP_NULL_N_RANGE_UP_CHECK: {
+            genHoistedChecksForCountUpLoop(cUnit, mir);
+            break;
+        }
+        case MIR_OP_NULL_N_RANGE_DOWN_CHECK: {
+            genHoistedChecksForCountDownLoop(cUnit, mir);
+            break;
+        }
+        case MIR_OP_LOWER_BOUND_CHECK: {
+            genHoistedLowerBoundCheck(cUnit, mir);
+            break;
+        }
+        case MIR_OP_PUNT: {
+            genUnconditionalBranch(cUnit,
+                                   (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+            break;
+        }
+        default:
+            break;
+    }
+}
+
+/*
+ * Create a PC-reconstruction cell for the starting offset of this trace.
+ * Since the PCR cell is placed near the end of the compiled code which is
+ * usually out of range for a conditional branch, we put two branches (one
+ * branch over to the loop body and one layover branch to the actual PCR) at the
+ * end of the entry block.
+ */
+static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry,
+                                ArmLIR *bodyLabel)
+{
+    /* Set up the place holder to reconstruct this Dalvik PC */
+    ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
+    pcrLabel->opCode = ARM_PSEUDO_PC_RECONSTRUCTION_CELL;
+    pcrLabel->operands[0] =
+        (int) (cUnit->method->insns + entry->startOffset);
+    pcrLabel->operands[1] = entry->startOffset;
+    /* Insert the place holder to the growable list */
+    dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+
+    /*
+     * Next, create two branches - one branch over to the loop body and the
+     * other branch to the PCR cell to punt.
+     */
+    ArmLIR *branchToBody = dvmCompilerNew(sizeof(ArmLIR), true);
+    branchToBody->opCode = THUMB_B_UNCOND;
+    branchToBody->generic.target = (LIR *) bodyLabel;
+    setupResourceMasks(branchToBody);
+    cUnit->loopAnalysis->branchToBody = (LIR *) branchToBody;
+
+    ArmLIR *branchToPCR = dvmCompilerNew(sizeof(ArmLIR), true);
+    branchToPCR->opCode = THUMB_B_UNCOND;
+    branchToPCR->generic.target = (LIR *) pcrLabel;
+    setupResourceMasks(branchToPCR);
+    cUnit->loopAnalysis->branchToPCR = (LIR *) branchToPCR;
+}
+
 void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
 {
     /* Used to hold the labels of each block */
@@ -2995,7 +3875,8 @@
         cUnit->chainCellOffsetLIR =
             (LIR *) newLIR1(cUnit, ARM_16BIT_DATA, CHAIN_CELL_OFFSET_TAG);
         cUnit->headerSize = 6;
-        newLIR2(cUnit, THUMB_MOV_RR_H2L, r0, rpc & THUMB_REG_MASK);
+        /* Thumb instruction used directly here to ensure correct size */
+        newLIR2(cUnit, THUMB_MOV_RR_H2L, r0, rpc);
         newLIR2(cUnit, THUMB_SUB_RI8, r0, 10);
         newLIR3(cUnit, THUMB_LDR_RRI5, r1, r0, 0);
         newLIR2(cUnit, THUMB_ADD_RI8, r1, 1);
@@ -3022,7 +3903,18 @@
             dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
         }
 
-        if (blockList[i]->blockType == DALVIK_BYTECODE) {
+        if (blockList[i]->blockType == ENTRY_BLOCK) {
+            labelList[i].opCode = ARM_PSEUDO_ENTRY_BLOCK;
+            if (blockList[i]->firstMIRInsn == NULL) {
+                continue;
+            } else {
+              setupLoopEntryBlock(cUnit, blockList[i],
+                                  &labelList[blockList[i]->fallThrough->id]);
+            }
+        } else if (blockList[i]->blockType == EXIT_BLOCK) {
+            labelList[i].opCode = ARM_PSEUDO_EXIT_BLOCK;
+            goto gen_fallthrough;
+        } else if (blockList[i]->blockType == DALVIK_BYTECODE) {
             labelList[i].opCode = ARM_PSEUDO_NORMAL_BLOCK_LABEL;
             /* Reset the register state */
             resetRegisterScoreboard(cUnit);
@@ -3070,13 +3962,22 @@
                 case EXCEPTION_HANDLING:
                     labelList[i].opCode = ARM_PSEUDO_EH_BLOCK_LABEL;
                     if (cUnit->pcReconstructionList.numUsed) {
-                        newLIR3(cUnit, THUMB_LDR_RRI5, r1, rGLUE,
-                            offsetof(InterpState,
-                                     jitToInterpEntries.dvmJitToInterpPunt)
-                            >> 2);
-                        newLIR1(cUnit, THUMB_BLX_R, r1);
+                        loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+                                     jitToInterpEntries.dvmJitToInterpPunt),
+                                     r1);
+                        opReg(cUnit, OP_BLX, r1);
                     }
                     break;
+#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
+                case CHAINING_CELL_BACKWARD_BRANCH:
+                    labelList[i].opCode =
+                        ARM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH;
+                    /* handle the codegen later */
+                    dvmInsertGrowableList(
+                        &chainingListByType[CHAINING_CELL_BACKWARD_BRANCH],
+                        (void *) i);
+                    break;
+#endif
                 default:
                     break;
             }
@@ -3086,16 +3987,29 @@
         ArmLIR *headLIR = NULL;
 
         for (mir = blockList[i]->firstMIRInsn; mir; mir = mir->next) {
+            if (mir->dalvikInsn.opCode >= MIR_OP_FIRST) {
+                handleExtendedMIR(cUnit, mir);
+                continue;
+            }
+
             OpCode dalvikOpCode = mir->dalvikInsn.opCode;
             InstructionFormat dalvikFormat =
                 dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
             ArmLIR *boundaryLIR =
                 newLIR2(cUnit, ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY,
-                        mir->offset,dalvikOpCode);
+                        mir->offset, dalvikOpCode);
+            if (mir->ssaRep) {
+                char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
+                newLIR1(cUnit, ARM_PSEUDO_SSA_REP, (int) ssaString);
+            }
+
             /* Remember the first LIR for this block */
             if (headLIR == NULL) {
                 headLIR = boundaryLIR;
+                /* Set the first boundaryLIR as a scheduling barrier */
+                headLIR->defMask = ENCODE_ALL;
             }
+
             bool notHandled;
             /*
              * Debugging: screen the opcode first to see if it is in the
@@ -3106,6 +4020,11 @@
                 ((gDvmJit.opList[dalvikOpCode >> 3] &
                   (1 << (dalvikOpCode & 0x7))) !=
                  0);
+#if defined(WITH_SELF_VERIFICATION)
+            /* Punt on opcodes we can't replay */
+            if (selfVerificationPuntOps(dalvikOpCode))
+                singleStepMe = true;
+#endif
             if (singleStepMe || cUnit->allSingleStep) {
                 notHandled = false;
                 genInterpSingleStep(cUnit, mir);
@@ -3202,9 +4121,24 @@
                 break;
             }
         }
-        /* Eliminate redundant loads/stores and delay stores into later slots */
-        dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
-                                           cUnit->lastLIRInsn);
+
+        if (blockList[i]->blockType == ENTRY_BLOCK) {
+            dvmCompilerAppendLIR(cUnit,
+                                 (LIR *) cUnit->loopAnalysis->branchToBody);
+            dvmCompilerAppendLIR(cUnit,
+                                 (LIR *) cUnit->loopAnalysis->branchToPCR);
+        }
+
+        if (headLIR) {
+            /*
+             * Eliminate redundant loads/stores and delay stores into later
+             * slots
+             */
+            dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
+                                               cUnit->lastLIRInsn);
+        }
+
+gen_fallthrough:
         /*
          * Check if the block is terminated due to trace length constraint -
          * insert an unconditional branch to the chaining cell.
@@ -3256,6 +4190,12 @@
                     handleHotChainingCell(cUnit,
                         blockList[blockId]->startOffset);
                     break;
+#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
+                case CHAINING_CELL_BACKWARD_BRANCH:
+                    handleBackwardBranchChainingCell(cUnit,
+                        blockList[blockId]->startOffset);
+                    break;
+#endif
                 default:
                     dvmAbort();
                     break;
@@ -3335,3 +4275,19 @@
         LOGD("dalvik.vm.jit.op = %s", buf);
     }
 }
+
+/* Common initialization routine for an architecture family */
+bool dvmCompilerArchInit()
+{
+    int i;
+
+    for (i = 0; i < ARM_LAST; i++) {
+        if (EncodingMap[i].opCode != i) {
+            LOGE("Encoding order for %s is wrong: expecting %d, seeing %d",
+                 EncodingMap[i].name, i, EncodingMap[i].opCode);
+            dvmAbort();
+        }
+    }
+
+    return compilerArchVariantInit();
+}
diff --git a/vm/compiler/codegen/arm/Codegen.h b/vm/compiler/codegen/arm/Codegen.h
index 4016075..b484cd2 100644
--- a/vm/compiler/codegen/arm/Codegen.h
+++ b/vm/compiler/codegen/arm/Codegen.h
@@ -22,6 +22,8 @@
  * variant code such as ThumbUtilty.c
  */
 
+static void annotateDalvikRegAccess(ArmLIR *lir, int regId, bool isLoad);
+static void setupResourceMasks(ArmLIR *lir);
 static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpCode opCode);
 static ArmLIR *newLIR1(CompilationUnit *cUnit, ArmOpCode opCode,
                            int dest);
@@ -29,18 +31,18 @@
                            int dest, int src1);
 static ArmLIR *newLIR3(CompilationUnit *cUnit, ArmOpCode opCode,
                            int dest, int src1, int src2);
-static ArmLIR *newLIR23(CompilationUnit *cUnit, ArmOpCode opCode,
-                            int srcdest, int src2);
+static ArmLIR *newLIR4(CompilationUnit *cUnit, ArmOpCode opCode,
+                            int dest, int src1, int src2, int info);
 static ArmLIR *scanLiteralPool(CompilationUnit *cUnit, int value,
                                    unsigned int delta);
 static ArmLIR *addWordData(CompilationUnit *cUnit, int value, bool inPlace);
 static inline ArmLIR *genCheckCommon(CompilationUnit *cUnit, int dOffset,
                                          ArmLIR *branch,
                                          ArmLIR *pcrLabel);
+static void genBarrier(CompilationUnit *cUnit);
 
 /* Routines which must be supplied by the variant-specific code */
 static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpCode opCode);
-bool dvmCompilerArchInit(void);
 static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir);
 static bool genInlineCos(CompilationUnit *cUnit, MIR *mir);
 static bool genInlineSin(CompilationUnit *cUnit, MIR *mir);
@@ -51,7 +53,6 @@
                              int vSrc1, int vSrc2);
 static bool genCmpX(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
                     int vSrc2);
-
-
+static bool compilerArchVariantInit();
 
 #endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_CODEGEN_H */
diff --git a/vm/compiler/codegen/arm/GlobalOptimizations.c b/vm/compiler/codegen/arm/GlobalOptimizations.c
index 40e1f07..687b7d2 100644
--- a/vm/compiler/codegen/arm/GlobalOptimizations.c
+++ b/vm/compiler/codegen/arm/GlobalOptimizations.c
@@ -48,8 +48,7 @@
                 /*
                  * Found real useful stuff between the branch and the target
                  */
-                if (!isPseudoOpCode(nextLIR->opCode) ||
-                    nextLIR->opCode == ARM_PSEUDO_ALIGN4)
+                if (!isPseudoOpCode(nextLIR->opCode))
                     break;
             }
         }
diff --git a/vm/compiler/codegen/arm/LocalOptimizations.c b/vm/compiler/codegen/arm/LocalOptimizations.c
index 11aaedd..86f692f 100644
--- a/vm/compiler/codegen/arm/LocalOptimizations.c
+++ b/vm/compiler/codegen/arm/LocalOptimizations.c
@@ -18,25 +18,37 @@
 #include "vm/compiler/CompilerInternals.h"
 #include "ArmLIR.h"
 
+#define DEBUG_OPT(X)
+
 ArmLIR* dvmCompilerGenCopy(CompilationUnit *cUnit, int rDest, int rSrc);
 
 /* Is this a Dalvik register access? */
 static inline bool isDalvikLoad(ArmLIR *lir)
 {
-    return ((lir->operands[1] == rFP) &&
-            ((lir->opCode == THUMB_LDR_RRI5) ||
-             (lir->opCode == THUMB2_LDR_RRI12) ||
-             (lir->opCode == THUMB2_VLDRS) ||
-             (lir->opCode == THUMB2_VLDRD)));
+    return (lir->useMask != ~0ULL) && (lir->useMask & ENCODE_DALVIK_REG);
 }
 
 static inline bool isDalvikStore(ArmLIR *lir)
 {
-    return ((lir->operands[1] == rFP) &&
-            ((lir->opCode == THUMB_STR_RRI5) ||
-             (lir->opCode == THUMB2_STR_RRI12) ||
-             (lir->opCode == THUMB2_VSTRS) ||
-             (lir->opCode == THUMB2_VSTRD)));
+    return (lir->defMask != ~0ULL) && (lir->defMask & ENCODE_DALVIK_REG);
+}
+
+static inline bool isDalvikRegisterClobbered(ArmLIR *lir1, ArmLIR *lir2)
+{
+  int reg1Lo = DECODE_ALIAS_INFO_REG(lir1->aliasInfo);
+  int reg1Hi = reg1Lo + DECODE_ALIAS_INFO_WIDE(lir1->aliasInfo);
+  int reg2Lo = DECODE_ALIAS_INFO_REG(lir2->aliasInfo);
+  int reg2Hi = reg2Lo + DECODE_ALIAS_INFO_WIDE(lir2->aliasInfo);
+
+  return (reg1Lo == reg2Lo) || (reg1Lo == reg2Hi) || (reg1Hi == reg2Lo);
+}
+
+static void dumpDependentInsnPair(ArmLIR *thisLIR, ArmLIR *checkLIR,
+                                  const char *optimization)
+{
+    LOGD("************ %s ************", optimization);
+    dvmDumpLIRInsn((LIR *) thisLIR, 0);
+    dvmDumpLIRInsn((LIR *) checkLIR, 0);
 }
 
 /*
@@ -59,10 +71,18 @@
             continue;
         }
         if (isDalvikStore(thisLIR)) {
-            int dRegId = thisLIR->operands[2];
+            int dRegId = DECODE_ALIAS_INFO_REG(thisLIR->aliasInfo);
+            int dRegIdHi = dRegId + DECODE_ALIAS_INFO_WIDE(thisLIR->aliasInfo);
             int nativeRegId = thisLIR->operands[0];
             ArmLIR *checkLIR;
             int sinkDistance = 0;
+            /*
+             * Add r15 (pc) to the mask to prevent this instruction
+             * from sinking past branch instructions. Unset the Dalvik register
+             * bit when checking with native resource constraints.
+             */
+            u8 stopMask = (ENCODE_REG_PC | thisLIR->useMask) &
+                          ~ENCODE_DALVIK_REG;
 
             for (checkLIR = NEXT_LIR(thisLIR);
                  checkLIR != tailLIR;
@@ -70,10 +90,8 @@
 
                 /* Check if a Dalvik register load is redundant */
                 if (isDalvikLoad(checkLIR) &&
-                    checkLIR->operands[2] == dRegId ) {
-                    if (FPREG(nativeRegId) != FPREG(checkLIR->operands[0])) {
-                        break;  // TODO: handle gen<=>float copies
-                    }
+                    (checkLIR->aliasInfo == thisLIR->aliasInfo) &&
+                    (REGTYPE(checkLIR->operands[0]) == REGTYPE(nativeRegId))) {
                     /* Insert a move to replace the load */
                     if (checkLIR->operands[0] != nativeRegId) {
                         ArmLIR *moveLIR;
@@ -90,44 +108,33 @@
                     checkLIR->isNop = true;
                     continue;
 
-                /* Found a true output dependency - nuke the previous store */
+                /*
+                 * Found a true output dependency - nuke the previous store.
+                 * The register type doesn't matter here.
+                 */
                 } else if (isDalvikStore(checkLIR) &&
-                           checkLIR->operands[2] == dRegId) {
+                           (checkLIR->aliasInfo == thisLIR->aliasInfo)) {
                     thisLIR->isNop = true;
                     break;
                 /* Find out the latest slot that the store can be sunk into */
                 } else {
-                    bool stopHere = false;
-
                     /* Last instruction reached */
-                    stopHere |= checkLIR->generic.next == NULL;
+                    bool stopHere = (NEXT_LIR(checkLIR) == tailLIR);
 
-                    /*
-                     * Conservatively assume there is a memory dependency
-                     * for st/ld multiples and reg+reg address mode
-                     */
-                    stopHere |= checkLIR->opCode == THUMB_STMIA ||
-                                checkLIR->opCode == THUMB_LDMIA ||
-                                checkLIR->opCode == THUMB_STR_RRR ||
-                                checkLIR->opCode == THUMB_LDR_RRR ||
-                                checkLIR->opCode == THUMB2_VLDRD ||
-                                checkLIR->opCode == THUMB2_VSTRD;
-;
+                    /* Store data is clobbered */
+                    stopHere |= ((stopMask & checkLIR->defMask) != 0);
 
-                    if (!isPseudoOpCode(checkLIR->opCode)) {
-
-                        /* Store data is clobbered */
-                        stopHere |= (EncodingMap[checkLIR->opCode].flags &
-                                     CLOBBER_DEST) != 0 &&
-                                    checkLIR->operands[0] == nativeRegId;
-
-                        stopHere |= (EncodingMap[checkLIR->opCode].flags &
-                                     IS_BRANCH) != 0;
+                    /* Store data partially clobbers the Dalvik register */
+                    if (stopHere == false &&
+                        ((checkLIR->useMask | checkLIR->defMask) &
+                         ENCODE_DALVIK_REG)) {
+                        stopHere = isDalvikRegisterClobbered(thisLIR, checkLIR);
                     }
 
                     /* Found a new place to put the store - move it here */
                     if (stopHere == true) {
-
+                        DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR,
+                                                        "SINK STORE"));
                         /* The store can be sunk for at least one cycle */
                         if (sinkDistance != 0) {
                             ArmLIR *newStoreLIR =
@@ -157,10 +164,186 @@
     }
 }
 
+static void applyLoadHoisting(CompilationUnit *cUnit,
+                              ArmLIR *headLIR,
+                              ArmLIR *tailLIR)
+{
+    ArmLIR *thisLIR;
+
+    cUnit->optRound++;
+    for (thisLIR = headLIR;
+         thisLIR != tailLIR;
+         thisLIR = NEXT_LIR(thisLIR)) {
+        /* Skip newly added instructions */
+        if (thisLIR->age >= cUnit->optRound ||
+            thisLIR->isNop == true) {
+            continue;
+        }
+        if (isDalvikLoad(thisLIR)) {
+            int dRegId = DECODE_ALIAS_INFO_REG(thisLIR->aliasInfo);
+            int dRegIdHi = dRegId + DECODE_ALIAS_INFO_WIDE(thisLIR->aliasInfo);
+            int nativeRegId = thisLIR->operands[0];
+            ArmLIR *checkLIR;
+            int hoistDistance = 0;
+            u8 stopUseMask = (ENCODE_REG_PC | thisLIR->useMask) &
+                             ~ENCODE_DALVIK_REG;
+            u8 stopDefMask = thisLIR->defMask & ~ENCODE_DALVIK_REG;
+
+            /* First check if the load can be completely elinimated */
+            for (checkLIR = PREV_LIR(thisLIR);
+                 checkLIR != headLIR;
+                 checkLIR = PREV_LIR(checkLIR)) {
+
+                if (checkLIR->isNop) continue;
+
+                /*
+                 * Check if the Dalvik register is previously accessed
+                 * with exactly the same type.
+                 */
+                if ((isDalvikLoad(checkLIR) || isDalvikStore(checkLIR)) &&
+                    (checkLIR->aliasInfo == thisLIR->aliasInfo) &&
+                    (checkLIR->operands[0] == nativeRegId)) {
+                    /*
+                     * If it is previously accessed but with a different type,
+                     * the search will terminate later at the point checking
+                     * for partially overlapping stores.
+                     */
+                    thisLIR->isNop = true;
+                    break;
+                }
+
+                /*
+                 * No earlier use/def can reach this load if:
+                 * 1) Head instruction is reached
+                 * 2) load target register is clobbered
+                 * 3) A branch is seen (stopUseMask has the PC bit set).
+                 */
+                if ((checkLIR == headLIR) ||
+                    (stopUseMask | stopDefMask) & checkLIR->defMask) {
+                    break;
+                }
+
+                /* Store data partially clobbers the Dalvik register */
+                if (isDalvikStore(checkLIR) &&
+                    isDalvikRegisterClobbered(thisLIR, checkLIR)) {
+                    break;
+                }
+            }
+
+            /* The load has been eliminated */
+            if (thisLIR->isNop) continue;
+
+            /*
+             * The load cannot be eliminated. See if it can be hoisted to an
+             * earlier spot.
+             */
+            for (checkLIR = PREV_LIR(thisLIR);
+                 /* empty by intention */;
+                 checkLIR = PREV_LIR(checkLIR)) {
+
+                if (checkLIR->isNop) continue;
+
+                /* Check if the current load is redundant */
+                if ((isDalvikLoad(checkLIR) || isDalvikStore(checkLIR)) &&
+                    (checkLIR->aliasInfo == thisLIR->aliasInfo) &&
+                    (REGTYPE(checkLIR->operands[0]) == REGTYPE(nativeRegId))) {
+                    /* Insert a move to replace the load */
+                    if (checkLIR->operands[0] != nativeRegId) {
+                        ArmLIR *moveLIR;
+                        moveLIR = dvmCompilerRegCopy(cUnit,
+                                                    nativeRegId,
+                                                    checkLIR->operands[0]);
+                        /*
+                         * Convert *thisLIR* load into a move
+                         */
+                        dvmCompilerInsertLIRAfter((LIR *) checkLIR,
+                                                  (LIR *) moveLIR);
+                    }
+                    thisLIR->isNop = true;
+                    break;
+
+                /* Find out if the load can be yanked past the checkLIR */
+                } else {
+                    /* Last instruction reached */
+                    bool stopHere = (checkLIR == headLIR);
+
+                    /* Base address is clobbered by checkLIR */
+                    stopHere |= ((stopUseMask & checkLIR->defMask) != 0);
+
+                    /* Load target clobbers use/def in checkLIR */
+                    stopHere |= ((stopDefMask &
+                                 (checkLIR->useMask | checkLIR->defMask)) != 0);
+
+                    /* Store data partially clobbers the Dalvik register */
+                    if (stopHere == false &&
+                        (checkLIR->defMask & ENCODE_DALVIK_REG)) {
+                        stopHere = isDalvikRegisterClobbered(thisLIR, checkLIR);
+                    }
+
+                    /*
+                     * Stop at an earlier Dalvik load if the offset of checkLIR
+                     * is not less than thisLIR
+                     *
+                     * Experiments show that doing
+                     *
+                     * ldr     r1, [r5, #16]
+                     * ldr     r0, [r5, #20]
+                     *
+                     * is much faster than
+                     *
+                     * ldr     r0, [r5, #20]
+                     * ldr     r1, [r5, #16]
+                     */
+                    if (isDalvikLoad(checkLIR)) {
+                        int dRegId2 =
+                            DECODE_ALIAS_INFO_REG(checkLIR->aliasInfo);
+                        if (dRegId2 <= dRegId) {
+                            stopHere = true;
+                        }
+                    }
+
+                    /* Found a new place to put the load - move it here */
+                    if (stopHere == true) {
+                        DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR,
+                                                        "HOIST LOAD"));
+                        /* The store can be hoisted for at least one cycle */
+                        if (hoistDistance != 0) {
+                            ArmLIR *newLoadLIR =
+                                dvmCompilerNew(sizeof(ArmLIR), true);
+                            *newLoadLIR = *thisLIR;
+                            newLoadLIR->age = cUnit->optRound;
+                            /*
+                             * Insertion is guaranteed to succeed since checkLIR
+                             * is never the first LIR on the list
+                             */
+                            dvmCompilerInsertLIRAfter((LIR *) checkLIR,
+                                                      (LIR *) newLoadLIR);
+                            thisLIR->isNop = true;
+                        }
+                        break;
+                    }
+
+                    /*
+                     * Saw a real instruction that hosting the load is
+                     * beneficial
+                     */
+                    if (!isPseudoOpCode(checkLIR->opCode)) {
+                        hoistDistance++;
+                    }
+                }
+            }
+        }
+    }
+}
+
 void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
                                         LIR *tailLIR)
 {
-    applyLoadStoreElimination(cUnit,
-                              (ArmLIR *) headLIR,
-                              (ArmLIR *) tailLIR);
+    if (!(gDvmJit.disableOpt & (1 << kLoadStoreElimination))) {
+        applyLoadStoreElimination(cUnit, (ArmLIR *) headLIR,
+                                  (ArmLIR *) tailLIR);
+    }
+    if (!(gDvmJit.disableOpt & (1 << kLoadHoisting))) {
+        applyLoadHoisting(cUnit, (ArmLIR *) headLIR, (ArmLIR *) tailLIR);
+    }
 }
diff --git a/vm/compiler/codegen/arm/Thumb2Util.c b/vm/compiler/codegen/arm/Thumb2Util.c
index 3a9f1de..dfbb030 100644
--- a/vm/compiler/codegen/arm/Thumb2Util.c
+++ b/vm/compiler/codegen/arm/Thumb2Util.c
@@ -16,46 +16,85 @@
 
 /*
  * This file contains codegen for the Thumb ISA and is intended to be
- * includes by:and support common to all supported
+ * includes by:
  *
  *        Codegen-$(TARGET_ARCH_VARIANT).c
  *
  */
 
 #include "Codegen.h"
+/* Forward decls */
+static ArmLIR *genNullCheck(CompilationUnit *cUnit, int vReg, int mReg,
+                            int dOffset, ArmLIR *pcrLabel);
+static ArmLIR *loadValueAddress(CompilationUnit *cUnit, int vSrc, int rDest);
+static ArmLIR *loadValue(CompilationUnit *cUnit, int vSrc, int rDest);
+static ArmLIR *loadWordDisp(CompilationUnit *cUnit, int rBase,
+                            int displacement, int rDest);
+static ArmLIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
+                             int displacement, int rSrc, int rScratch);
+static ArmLIR *storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
+                          int rScratch);
+static ArmLIR *genConditionalBranch(CompilationUnit *cUnit,
+                                    ArmConditionCode cond,
+                                    ArmLIR *target);
+static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target);
+static ArmLIR *loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
+                             int rDestHi);
+static ArmLIR *storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
+                              int vDest, int rScratch);
+static ArmLIR *genBoundsCheck(CompilationUnit *cUnit, int rIndex,
+                              int rBound, int dOffset, ArmLIR *pcrLabel);
+static ArmLIR *genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+static int inlinedTarget(MIR *mir);
+
 
 /* Routines which must be supplied here */
-static void loadConstant(CompilationUnit *cUnit, int rDest, int value);
-static void genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC, int rAddr);
-static void genConditionalBranch(CompilationUnit *cUnit,
-                                 ArmConditionCode cond,
-                                 ArmLIR *target);
-static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target);
-static void loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
-                          int rDestHi);
-static void storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
-                           int vDest, int rScratch);
-static void loadValueAddress(CompilationUnit *cUnit, int vSrc, int vDest);
-static void loadValue(CompilationUnit *cUnit, int vSrc, int rDest);
-static void loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
-                         int rDest);
-static void storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
-                       int rScratch);
+static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
+static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC,
+                           int rAddr);
+static ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
+                            int displacement, int rDest, OpSize size,
+                            bool nullCheck, int vReg);
+static ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
+                             int displacement, int rSrc, OpSize size,
+                             int rScratch);
 static inline ArmLIR *genRegImmCheck(CompilationUnit *cUnit,
-                                         ArmConditionCode cond, int reg,
-                                         int checkValue, int dOffset,
-                                         ArmLIR *pcrLabel);
+                                     ArmConditionCode cond, int reg,
+                                     int checkValue, int dOffset,
+                                     ArmLIR *pcrLabel);
 ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+static ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
+static ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask);
 
-/*****************************************************************************/
+static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op);
+static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value);
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc);
+static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc);
+static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+                        int rSrc2);
+static ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+                        int value, int rScratch);
+static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+                           int rSrc1, int value, int rScratch);
+static ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+                           int rSrc1, int rSrc2);
+static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
+                               int rIndex, int rDest, int scale, OpSize size);
+static void genCmpLong(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
+                       int vSrc2);
+
+static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin);
+static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir);
 
 /*
  * Support for register allocation
  */
 
-/* non-existent register */
-#define vNone   (-1)
-
 /* get the next register in r0..r3 in a round-robin fashion */
 #define NEXT_REG(reg) ((reg + 1) & 3)
 /*
@@ -67,11 +106,16 @@
 static inline void resetRegisterScoreboard(CompilationUnit *cUnit)
 {
     RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+    int i;
 
     dvmClearAllBits(registerScoreboard->nullCheckedRegs);
     registerScoreboard->liveDalvikReg = vNone;
     registerScoreboard->nativeReg = vNone;
     registerScoreboard->nativeRegHi = vNone;
+    for (i = 0; i < 32; i++) {
+        registerScoreboard->fp[i] = vNone;
+    }
+    registerScoreboard->nextFP = 0;
 }
 
 /* Kill the corresponding bit in the null-checked register list */
@@ -128,12 +172,50 @@
     } else {
         return (registerScoreboard->nativeReg + 1) & 3;
     }
-
 }
 
-/*****************************************************************************/
+/*
+ * Generate a Thumb2 IT instruction, which can nullify up to
+ * four subsequent instructions based on a condition and its
+ * inverse.  The condition applies to the first instruction, which
+ * is executed if the condition is met.  The string "guide" consists
+ * of 0 to 3 chars, and applies to the 2nd through 4th instruction.
+ * A "T" means the instruction is executed if the condition is
+ * met, and an "E" means the instruction is executed if the condition
+ * is not met.
+ */
+static ArmLIR *genIT(CompilationUnit *cUnit, ArmConditionCode code,
+                     char *guide)
+{
+    int mask;
+    int condBit = code & 1;
+    int altBit = condBit ^ 1;
+    int mask3 = 0;
+    int mask2 = 0;
+    int mask1 = 0;
 
-ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+    //Note: case fallthroughs intentional
+    switch(strlen(guide)) {
+        case 3:
+            mask1 = (guide[2] == 'T') ? condBit : altBit;
+        case 2:
+            mask2 = (guide[1] == 'T') ? condBit : altBit;
+        case 1:
+            mask3 = (guide[0] == 'T') ? condBit : altBit;
+            break;
+        case 0:
+            break;
+        default:
+            assert(0);
+            dvmAbort();
+    }
+    mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
+           (1 << (3 - strlen(guide)));
+    return newLIR2(cUnit, THUMB2_IT, code, mask);
+}
+
+
+static ArmLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
 {
     ArmLIR* res = dvmCompilerNew(sizeof(ArmLIR), true);
     res->operands[0] = rDest;
@@ -141,22 +223,43 @@
     if (rDest == rSrc) {
         res->isNop = true;
     } else {
-        if (LOWREG(rDest) && LOWREG(rSrc)) {
-            res->opCode = THUMB_MOV_RR;
-        } else if (FPREG(rDest) && FPREG(rSrc)) {
-            if (DOUBLEREG(rDest)) {
-                assert(DOUBLEREG(rSrc));
-                res->opCode = THUMB2_VMOVD;
-            } else {
-                assert(SINGLEREG(rSrc));
-                res->opCode = THUMB2_VMOVS;
-            }
+        // TODO: support copy between FP and gen regs
+        if (DOUBLEREG(rDest)) {
+            assert(DOUBLEREG(rSrc));
+            res->opCode = THUMB2_VMOVD;
         } else {
-            // TODO: support copy between FP and gen regs.
-            assert(!FPREG(rDest));
-            assert(!FPREG(rSrc));
-            res->opCode = THUMB2_MOV_RR;
+            assert(SINGLEREG(rSrc));
+            res->opCode = THUMB2_VMOVS;
         }
+        res->operands[0] = rDest;
+        res->operands[1] = rSrc;
+    }
+    setupResourceMasks(res);
+    return res;
+}
+
+ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+{
+    ArmLIR* res;
+    ArmOpCode opCode;
+    if (FPREG(rDest) || FPREG(rSrc))
+        return fpRegCopy(cUnit, rDest, rSrc);
+    res = dvmCompilerNew(sizeof(ArmLIR), true);
+    if (LOWREG(rDest) && LOWREG(rSrc))
+        opCode = THUMB_MOV_RR;
+    else if (!LOWREG(rDest) && !LOWREG(rSrc))
+         opCode = THUMB_MOV_RR_H2H;
+    else if (LOWREG(rDest))
+         opCode = THUMB_MOV_RR_H2L;
+    else
+         opCode = THUMB_MOV_RR_L2H;
+
+    res->operands[0] = rDest;
+    res->operands[1] = rSrc;
+    res->opCode = opCode;
+    setupResourceMasks(res);
+    if (rDest == rSrc) {
+        res->isNop = true;
     }
     return res;
 }
@@ -181,7 +284,7 @@
 }
 
 /*
- * Determine whether value can be encoded as a Thumb modified
+ * Determine whether value can be encoded as a Thumb2 modified
  * immediate.  If not, return -1.  If so, return i:imm3:a:bcdefgh form.
  */
 static int modifiedImmediate(u4 value)
@@ -218,28 +321,29 @@
  * Load a immediate using a shortcut if possible; otherwise
  * grab from the per-translation literal pool
  */
-static void loadConstant(CompilationUnit *cUnit, int rDest, int value)
+static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value)
 {
+    ArmLIR *res;
     int modImm;
     /* See if the value can be constructed cheaply */
-    if ((value & 0xff) == value) {
-        newLIR2(cUnit, THUMB_MOV_IMM, rDest, value);
-        return;
-    } else if ((value & 0xFFFFFF00) == 0xFFFFFF00) {
-        newLIR2(cUnit, THUMB_MOV_IMM, rDest, ~value);
-        newLIR2(cUnit, THUMB_MVN, rDest, rDest);
-        return;
+    if ((value >= 0) && (value <= 255)) {
+        return newLIR2(cUnit, THUMB_MOV_IMM, rDest, value);
     }
     /* Check Modified immediate special cases */
     modImm = modifiedImmediate(value);
     if (modImm >= 0) {
-        newLIR2(cUnit, THUMB2_MOV_IMM_SHIFT, rDest, modImm);
-        return;
+        res = newLIR2(cUnit, THUMB2_MOV_IMM_SHIFT, rDest, modImm);
+        return res;
+    }
+    modImm = modifiedImmediate(~value);
+    if (modImm >= 0) {
+        res = newLIR2(cUnit, THUMB2_MVN_IMM_SHIFT, rDest, modImm);
+        return res;
     }
     /* 16-bit immediate? */
     if ((value & 0xffff) == value) {
-        newLIR2(cUnit, THUMB2_MOV_IMM16, rDest, value);
-        return;
+        res = newLIR2(cUnit, THUMB2_MOV_IMM16, rDest, value);
+        return res;
     }
     /* No shortcut - go ahead and use literal pool */
     ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 255);
@@ -250,6 +354,8 @@
     loadPcRel->opCode = THUMB_LDR_PC_REL;
     loadPcRel->generic.target = (LIR *) dataTarget;
     loadPcRel->operands[0] = rDest;
+    setupResourceMasks(loadPcRel);
+    res = loadPcRel;
     dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
 
     /*
@@ -259,210 +365,359 @@
     if (dataTarget->operands[0] != value) {
         newLIR2(cUnit, THUMB_ADD_RI8, rDest, value - dataTarget->operands[0]);
     }
+    return res;
 }
 
 /* Export the Dalvik PC assicated with an instruction to the StackSave area */
-static void genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC, int rAddr)
+static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC,
+                           int rAddr)
 {
+    ArmLIR *res;
     int offset = offsetof(StackSaveArea, xtra.currentPc);
-    loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
+    res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
     newLIR3(cUnit, THUMB2_STR_RRI8_PREDEC, rDPC, rFP,
             sizeof(StackSaveArea) - offset);
+    return res;
 }
 
-/* Generate conditional branch instructions */
-static void genConditionalBranch(CompilationUnit *cUnit,
-                                 ArmConditionCode cond,
-                                 ArmLIR *target)
+/* Load value from base + scaled index. Note: index reg killed */
+static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
+                               int rIndex, int rDest, int scale, OpSize size)
 {
-    ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
-    branch->generic.target = (LIR *) target;
+    bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest);
+    ArmOpCode opCode = THUMB_BKPT;
+    bool thumbForm = (allLowRegs && (scale == 0));
+    switch (size) {
+        case WORD:
+            opCode = (thumbForm) ? THUMB_LDR_RRR : THUMB2_LDR_RRR;
+            break;
+        case UNSIGNED_HALF:
+            opCode = (thumbForm) ? THUMB_LDRH_RRR : THUMB2_LDRH_RRR;
+            break;
+        case SIGNED_HALF:
+            opCode = (thumbForm) ? THUMB_LDRSH_RRR : THUMB2_LDRSH_RRR;
+            break;
+        case UNSIGNED_BYTE:
+            opCode = (thumbForm) ? THUMB_LDRB_RRR : THUMB2_LDRB_RRR;
+            break;
+        case SIGNED_BYTE:
+            opCode = (thumbForm) ? THUMB_LDRSB_RRR : THUMB2_LDRSB_RRR;
+            break;
+        default:
+            assert(0);
+    }
+    if (thumbForm)
+        return newLIR3(cUnit, opCode, rDest, rBase, rIndex);
+    else
+        return newLIR4(cUnit, opCode, rDest, rBase, rIndex, scale);
 }
 
-/* Generate unconditional branch instructions */
-static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
+/* store value base base + scaled index. Note: index reg killed */
+static ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
+                                int rIndex, int rSrc, int scale, OpSize size)
 {
-    ArmLIR *branch = newLIR0(cUnit, THUMB_B_UNCOND);
-    branch->generic.target = (LIR *) target;
-    return branch;
+    bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc);
+    ArmOpCode opCode = THUMB_BKPT;
+    bool thumbForm = (allLowRegs && (scale == 0));
+    switch (size) {
+        case WORD:
+            opCode = (thumbForm) ? THUMB_STR_RRR : THUMB2_STR_RRR;
+            break;
+        case UNSIGNED_HALF:
+        case SIGNED_HALF:
+            opCode = (thumbForm) ? THUMB_STRH_RRR : THUMB2_STRH_RRR;
+            break;
+        case UNSIGNED_BYTE:
+        case SIGNED_BYTE:
+            opCode = (thumbForm) ? THUMB_STRB_RRR : THUMB2_STRB_RRR;
+            break;
+        default:
+            assert(0);
+    }
+    if (thumbForm)
+        return newLIR3(cUnit, opCode, rSrc, rBase, rIndex);
+    else
+        return newLIR4(cUnit, opCode, rSrc, rBase, rIndex, scale);
 }
 
 /*
- * Load a pair of values of rFP[src..src+1] and store them into rDestLo and
- * rDestHi
+ * Load a float from a Dalvik register.  Note: using fixed r7 here
+ * when operation is out of range.  Revisit this when registor allocation
+ * strategy changes.
  */
-static void loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
-                          int rDestHi)
+static ArmLIR *fpVarAccess(CompilationUnit *cUnit, int vSrcDest,
+                           int rSrcDest, ArmOpCode opCode)
 {
-    bool allLowRegs = (LOWREG(rDestLo) && LOWREG(rDestHi));
-
-    /* Use reg + imm5*4 to load the values if possible */
-    if (allLowRegs && vSrc <= 30) {
-        newLIR3(cUnit, THUMB_LDR_RRI5, rDestLo, rFP, vSrc);
-        newLIR3(cUnit, THUMB_LDR_RRI5, rDestHi, rFP, vSrc+1);
+    ArmLIR *res;
+    if (vSrcDest > 255) {
+        opRegRegImm(cUnit, OP_ADD, r7, rFP, vSrcDest * 4, rNone);
+        res = newLIR3(cUnit, opCode, rSrcDest, r7, 0);
     } else {
-        assert(rDestLo < rDestHi);
-        loadValueAddress(cUnit, vSrc, rDestLo);
-        if (allLowRegs) {
-            newLIR2(cUnit, THUMB_LDMIA, rDestLo, (1<<rDestLo) | (1<<(rDestHi)));
-        } else {
-            assert(0); // Unimp - need Thumb2 ldmia
+        res = newLIR3(cUnit, opCode, rSrcDest, rFP, vSrcDest);
+    }
+    return res;
+}
+
+static int nextFPReg(CompilationUnit *cUnit, int dalvikReg, bool isDouble)
+{
+    RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+    int reg;
+
+    if (isDouble) {
+        reg = ((registerScoreboard->nextFP + 1) & ~1) % 32;
+        registerScoreboard->nextFP = reg + 2;
+        registerScoreboard->nextFP %= 32;
+        registerScoreboard->fp[reg] = dalvikReg;
+        return dr0 + reg;
+    }
+    else {
+        reg = registerScoreboard->nextFP++;
+        registerScoreboard->nextFP %= 32;
+        registerScoreboard->fp[reg] = dalvikReg;
+        return fr0 + reg;
+    }
+}
+
+/*
+ * Select a SFP register for the dalvikReg
+ */
+static int selectSFPReg(CompilationUnit *cUnit, int dalvikReg)
+{
+    RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+    int i;
+
+    if (dalvikReg == vNone) {
+        return nextFPReg(cUnit, dalvikReg, false);;
+    }
+
+    for (i = 0; i < 32; i++) {
+        if (registerScoreboard->fp[i] == dalvikReg) {
+            return fr0 + i;
         }
     }
+    return nextFPReg(cUnit, dalvikReg, false);;
 }
 
 /*
- * Store a pair of values of rSrc and rSrc+1 and store them into vDest and
- * vDest+1
+ * Select a DFP register for the dalvikReg
  */
-static void storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
-                           int vDest, int rScratch)
+static int selectDFPReg(CompilationUnit *cUnit, int dalvikReg)
 {
-    bool allLowRegs = (LOWREG(rSrcLo) && LOWREG(rSrcHi));
-    killNullCheckedRegister(cUnit, vDest);
-    killNullCheckedRegister(cUnit, vDest+1);
-    updateLiveRegisterPair(cUnit, vDest, rSrcLo, rSrcHi);
+    RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+    int i;
 
-    /* Use reg + imm5*4 to store the values if possible */
-    if (allLowRegs && vDest <= 30) {
-        newLIR3(cUnit, THUMB_STR_RRI5, rSrcLo, rFP, vDest);
-        newLIR3(cUnit, THUMB_STR_RRI5, rSrcHi, rFP, vDest+1);
-    } else {
-        assert(rSrcLo < rSrcHi);
-        loadValueAddress(cUnit, vDest, rScratch);
-        if (allLowRegs) {
-            newLIR2(cUnit, THUMB_STMIA, rScratch,
-                    (1<<rSrcLo) | (1 << (rSrcHi)));
-        } else {
-            assert(0); // Unimp - need Thumb2 stmia
+    if (dalvikReg == vNone) {
+        return nextFPReg(cUnit, dalvikReg, true);;
+    }
+
+    for (i = 0; i < 32; i += 2) {
+        if (registerScoreboard->fp[i] == dalvikReg) {
+            return dr0 + i;
         }
     }
+    return nextFPReg(cUnit, dalvikReg, true);
 }
 
-static void addRegisterRegister(CompilationUnit *cUnit, int rDest,
-                                int rSrc1, int rSrc2)
+static ArmLIR *loadFloat(CompilationUnit *cUnit, int vSrc, int rDest)
 {
-    if (!LOWREG(rDest) || !LOWREG(rSrc1) || !LOWREG(rSrc2)) {
-        assert(0); // Unimp
-        //newLIR3(cUnit, THUMB2_ADD_RRR, rDest, rFP, rDest);
-    } else {
-        newLIR3(cUnit, THUMB_ADD_RRR, rDest, rFP, rDest);
-    }
-}
-
-/* Add in immediate to a register. */
-static void addRegisterImmediate(CompilationUnit *cUnit, int rDest, int rSrc,
-                                 int value)
-{
-// TODO: check for modified immediate form
-    if (LOWREG(rDest) && LOWREG(rSrc) && (value <= 7)) {
-        newLIR3(cUnit, THUMB_ADD_RRI3, rDest, rSrc, value);
-    } else if (LOWREG(rDest) && (rDest == rSrc) && ((value & 0xff) == 0xff)) {
-        newLIR2(cUnit, THUMB_ADD_RI8, rDest, value);
-    } else if (value <= 4095) {
-        newLIR3(cUnit, THUMB2_ADD_RRI12, rDest, rSrc, value);
-    } else {
-        loadConstant(cUnit, rDest, value);
-        addRegisterRegister(cUnit, rDest, rDest, rFP);
-    }
-}
-
-/* Load the address of a Dalvik register on the frame */
-static void loadValueAddress(CompilationUnit *cUnit, int vSrc, int rDest)
-{
-    addRegisterImmediate(cUnit, rDest, rFP, vSrc*4);
-}
-
-/*
- * FIXME: We need a general register temp for all of these coprocessor
- * operations in case we can't reach in 1 shot.  Might just want to
- * designate a hot temp that all codegen routines could use in their
- * scope.  Alternately, callers will need to allocate a temp and
- * pass it in to each of these.
- */
-
-/* Load a float from a Dalvik register */
-static void loadFloat(CompilationUnit *cUnit, int vSrc, int rDest)
-{
-    assert(vSrc <= 255); // FIXME - temp limit to 1st 256
     assert(SINGLEREG(rDest));
-    newLIR3(cUnit, THUMB2_VLDRS, rDest, rFP, vSrc);
+    ArmLIR *lir = fpVarAccess(cUnit, vSrc, rDest, THUMB2_VLDRS);
+    annotateDalvikRegAccess(lir, vSrc, true /* isLoad */);
+    return lir;
 }
 
 /* Store a float to a Dalvik register */
-static void storeFloat(CompilationUnit *cUnit, int rSrc, int vDest,
-                       int rScratch)
+static ArmLIR *storeFloat(CompilationUnit *cUnit, int rSrc, int vDest)
 {
-    assert(vSrc <= 255); // FIXME - temp limit to 1st 256
+    RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+
     assert(SINGLEREG(rSrc));
-    newLIR3(cUnit, THUMB2_VSTRS, rSrc, rFP, vDest);
+    registerScoreboard->fp[rSrc % 32] = vDest;
+
+    ArmLIR *lir = fpVarAccess(cUnit, vDest, rSrc, THUMB2_VSTRS);
+    annotateDalvikRegAccess(lir, vDest, false /* isLoad */);
+    return lir;
 }
 
 /* Load a double from a Dalvik register */
-static void loadDouble(CompilationUnit *cUnit, int vSrc, int rDest)
+static ArmLIR *loadDouble(CompilationUnit *cUnit, int vSrc, int rDest)
 {
-    assert(vSrc <= 255); // FIXME - temp limit to 1st 256
     assert(DOUBLEREG(rDest));
-    newLIR3(cUnit, THUMB2_VLDRD, rDest, rFP, vSrc);
+    ArmLIR *lir = fpVarAccess(cUnit, vSrc, rDest, THUMB2_VLDRD);
+    annotateDalvikRegAccess(lir, vSrc, true /* isLoad */);
+    return lir;
 }
 
 /* Store a double to a Dalvik register */
-static void storeDouble(CompilationUnit *cUnit, int rSrc, int vDest,
-                       int rScratch)
+static ArmLIR *storeDouble(CompilationUnit *cUnit, int rSrc, int vDest)
 {
-    assert(vSrc <= 255); // FIXME - temp limit to 1st 256
+    RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+
     assert(DOUBLEREG(rSrc));
-    newLIR3(cUnit, THUMB2_VSTRD, rSrc, rFP, vDest);
+    registerScoreboard->fp[rSrc % 32] = vDest;
+
+    ArmLIR *lir = fpVarAccess(cUnit, vDest, rSrc, THUMB2_VSTRD);
+    annotateDalvikRegAccess(lir, vDest, false /* isLoad */);
+    return lir;
 }
 
-
-/* Load a single value from rFP[src] and store them into rDest */
-static void loadValue(CompilationUnit *cUnit, int vSrc, int rDest)
+/*
+ * Load value from base + displacement.  Optionally perform null check
+ * on base (which must have an associated vReg and MIR).  If not
+ * performing null check, incoming MIR can be null. Note: base and
+ * dest must not be the same if there is any chance that the long
+ * form must be used.
+ * TODO: revisit, perhaps use hot temp reg in (base == dest) case.
+ */
+static ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
+                            int displacement, int rDest, OpSize size,
+                            bool nullCheck, int vReg)
 {
-    loadWordDisp(cUnit, rFP, vSrc * 4, rDest);
-}
-
-/* Load a word at base + displacement.  Displacement must be word multiple */
-static void loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
-                         int rDest)
-{
+    ArmLIR *first = NULL;
+    ArmLIR *res, *load;
+    ArmOpCode opCode = THUMB_BKPT;
+    bool shortForm = false;
+    bool thumb2Form = (displacement < 4092 && displacement >= 0);
+    int shortMax = 128;
     bool allLowRegs = (LOWREG(rBase) && LOWREG(rDest));
-    assert((displacement & 0x3) == 0);
-    /* Can it fit in a RRI5? */
-    if (allLowRegs && displacement < 128) {
-        newLIR3(cUnit, THUMB_LDR_RRI5, rDest, rBase, displacement >> 2);
-    } else if (displacement < 4092) {
-        newLIR3(cUnit, THUMB2_LDR_RRI12, rDest, rFP, displacement);
-    } else {
-        loadConstant(cUnit, rDest, displacement);
-        if (allLowRegs) {
-            newLIR3(cUnit, THUMB_LDR_RRR, rDest, rBase, rDest);
-        } else {
-            assert(0); // Unimp - need Thumb2 ldr_rrr
-        }
+    int encodedDisp = displacement;
+
+    switch (size) {
+        case WORD:
+            if (LOWREG(rDest) && (rBase == rpc) &&
+                (displacement <= 1020) && (displacement >= 0)) {
+                shortForm = true;
+                encodedDisp >>= 2;
+                opCode = THUMB_LDR_PC_REL;
+            } else if (LOWREG(rDest) && (rBase == r13) &&
+                      (displacement <= 1020) && (displacement >= 0)) {
+                shortForm = true;
+                encodedDisp >>= 2;
+                opCode = THUMB_LDR_SP_REL;
+            } else if (allLowRegs && displacement < 128 && displacement >= 0) {
+                assert((displacement & 0x3) == 0);
+                shortForm = true;
+                encodedDisp >>= 2;
+                opCode = THUMB_LDR_RRI5;
+            } else if (thumb2Form) {
+                shortForm = true;
+                opCode = THUMB2_LDR_RRI12;
+            }
+            break;
+        case UNSIGNED_HALF:
+            if (allLowRegs && displacement < 64 && displacement >= 0) {
+                assert((displacement & 0x1) == 0);
+                shortForm = true;
+                encodedDisp >>= 1;
+                opCode = THUMB_LDRH_RRI5;
+            } else if (displacement < 4092 && displacement >= 0) {
+                shortForm = true;
+                opCode = THUMB2_LDRH_RRI12;
+            }
+            break;
+        case SIGNED_HALF:
+            if (thumb2Form) {
+                shortForm = true;
+                opCode = THUMB2_LDRSH_RRI12;
+            }
+            break;
+        case UNSIGNED_BYTE:
+            if (allLowRegs && displacement < 32 && displacement >= 0) {
+                shortForm = true;
+                opCode = THUMB_LDRB_RRI5;
+            } else if (thumb2Form) {
+                shortForm = true;
+                opCode = THUMB2_LDRB_RRI12;
+            }
+            break;
+        case SIGNED_BYTE:
+            if (thumb2Form) {
+                shortForm = true;
+                opCode = THUMB2_LDRSB_RRI12;
+            }
+            break;
+        default:
+            assert(0);
     }
+    if (nullCheck)
+        first = genNullCheck(cUnit, vReg, rBase, mir->offset, NULL);
+    if (shortForm) {
+        load = res = newLIR3(cUnit, opCode, rDest, rBase, encodedDisp);
+    } else {
+        assert(rBase != rDest);
+        res = loadConstant(cUnit, rDest, encodedDisp);
+        load = loadBaseIndexed(cUnit, rBase, rDest, rDest, 0, size);
+    }
+
+    if (rBase == rFP) {
+        annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */);
+    }
+    return (first) ? first : res;
 }
 
-/* Store a value from rSrc to vDest */
-static void storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
-                       int rScratch)
+static ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
+                             int displacement, int rSrc, OpSize size,
+                             int rScratch)
 {
-    killNullCheckedRegister(cUnit, vDest);
-    updateLiveRegister(cUnit, vDest, rSrc);
+    ArmLIR *res, *store;
+    ArmOpCode opCode = THUMB_BKPT;
+    bool shortForm = false;
+    bool thumb2Form = (displacement < 4092 && displacement >= 0);
+    int shortMax = 128;
+    bool allLowRegs = (LOWREG(rBase) && LOWREG(rSrc));
+    int encodedDisp = displacement;
 
-    /* Use reg + imm5*4 to store the value if possible */
-    if (LOWREG(rSrc) && vDest <= 31) {
-        newLIR3(cUnit, THUMB_STR_RRI5, rSrc, rFP, vDest);
-    } else if (vDest <= 1023) {
-        newLIR3(cUnit, THUMB2_STR_RRI12, rSrc, rFP, vDest*4);
-    } else {
-        loadConstant(cUnit, rScratch, vDest*4);
-        if (LOWREG(rSrc)) {
-            newLIR3(cUnit, THUMB_STR_RRR, rSrc, rFP, rScratch);
-        } else {
-            assert(0); // Unimp: Need generic str_rrr routine
-        }
+    if (rScratch != -1)
+        allLowRegs &= LOWREG(rScratch);
+    switch (size) {
+        case WORD:
+            if (allLowRegs && displacement < 128 && displacement >= 0) {
+                assert((displacement & 0x3) == 0);
+                shortForm = true;
+                encodedDisp >>= 2;
+                opCode = THUMB_STR_RRI5;
+            } else if (thumb2Form) {
+                shortForm = true;
+                opCode = THUMB2_STR_RRI12;
+            }
+            break;
+        case UNSIGNED_HALF:
+        case SIGNED_HALF:
+            if (displacement < 64 && displacement >= 0) {
+                assert((displacement & 0x1) == 0);
+                shortForm = true;
+                encodedDisp >>= 1;
+                opCode = THUMB_STRH_RRI5;
+            } else if (thumb2Form) {
+                shortForm = true;
+                opCode = THUMB2_STRH_RRI12;
+            }
+            break;
+        case UNSIGNED_BYTE:
+        case SIGNED_BYTE:
+            if (displacement < 32 && displacement >= 0) {
+                shortForm = true;
+                opCode = THUMB_STRB_RRI5;
+            } else if (thumb2Form) {
+                shortForm = true;
+                opCode = THUMB2_STRH_RRI12;
+            }
+            break;
+        default:
+            assert(0);
     }
+    if (shortForm) {
+        store = res = newLIR3(cUnit, opCode, rSrc, rBase, encodedDisp);
+    } else {
+        assert(rScratch != -1);
+        res = loadConstant(cUnit, rScratch, encodedDisp);
+        store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size);
+    }
+
+    if (rBase == rFP) {
+        annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */);
+    }
+    return res;
 }
 
 /*
@@ -475,14 +730,658 @@
                                          ArmLIR *pcrLabel)
 {
     ArmLIR *branch;
-    if ((LOWREG(reg)) && (checkValue == 0) &&
+    int modImm;
+    /*
+     * TODO: re-enable usage of THUMB2_CBZ & THUMB2_CBNZ once assembler is
+     * enhanced to allow us to replace code patterns when instructions don't
+     * reach.  Currently, CB[N]Z is causing too many assembler aborts.
+     * What we want to do is emit the short forms, and then replace them with
+     * longer versions when needed.
+     */
+    if (0 && (LOWREG(reg)) && (checkValue == 0) &&
        ((cond == ARM_COND_EQ) || (cond == ARM_COND_NE))) {
         branch = newLIR2(cUnit,
                          (cond == ARM_COND_EQ) ? THUMB2_CBZ : THUMB2_CBNZ,
                          reg, 0);
     } else {
-        newLIR2(cUnit, THUMB_CMP_RI8, reg, checkValue);
+        modImm = modifiedImmediate(checkValue);
+        if ((checkValue & 0xff) == checkValue) {
+            newLIR2(cUnit, THUMB_CMP_RI8, reg, checkValue);
+        } else if (modImm >= 0) {
+            newLIR2(cUnit, THUMB2_CMP_RI8, reg, modImm);
+        } else {
+            /* Note: direct use of hot temp r7 here. Revisit. */
+            loadConstant(cUnit, r7, checkValue);
+            newLIR2(cUnit, THUMB_CMP_RR, reg, r7);
+        }
         branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
     }
     return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
 }
+
+static ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+{
+    ArmLIR *res;
+    if (LOWREG(rBase) && ((rMask & 0xff)==rMask)) {
+        res = newLIR2(cUnit, THUMB_LDMIA, rBase, rMask);
+    } else {
+        res = newLIR2(cUnit, THUMB2_LDMIA, rBase, rMask);
+    }
+    return res;
+}
+
+static ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+{
+    ArmLIR *res;
+    if (LOWREG(rBase) && ((rMask & 0xff)==rMask)) {
+        res = newLIR2(cUnit, THUMB_STMIA, rBase, rMask);
+    } else {
+        res = newLIR2(cUnit, THUMB2_STMIA, rBase, rMask);
+    }
+    return res;
+}
+
+static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op)
+{
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_UNCOND_BR:
+            opCode = THUMB_B_UNCOND;
+            break;
+        default:
+            assert(0);
+    }
+    return newLIR0(cUnit, opCode);
+}
+
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc)
+{
+    return newLIR2(cUnit, THUMB_B_COND, 0 /* offset to be patched */, cc);
+}
+
+static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value)
+{
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_PUSH:
+            opCode = ((value & 0xff00) != 0) ? THUMB2_PUSH : THUMB_PUSH;
+            break;
+        case OP_POP:
+            opCode = ((value & 0xff00) != 0) ? THUMB2_POP : THUMB_POP;
+            break;
+        default:
+            assert(0);
+    }
+    return newLIR1(cUnit, opCode, value);
+}
+
+static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
+{
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_BLX:
+            opCode = THUMB_BLX_R;
+            break;
+        default:
+            assert(0);
+    }
+    return newLIR1(cUnit, opCode, rDestSrc);
+}
+
+static ArmLIR *opRegRegShift(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+                        int rSrc2, int shift)
+{
+    bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2));
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_ADC:
+            opCode = (thumbForm) ? THUMB_ADC_RR : THUMB2_ADC_RRR;
+            break;
+        case OP_AND:
+            opCode = (thumbForm) ? THUMB_AND_RR : THUMB2_AND_RRR;
+            break;
+        case OP_BIC:
+            opCode = (thumbForm) ? THUMB_BIC_RR : THUMB2_BIC_RRR;
+            break;
+        case OP_CMN:
+            assert(shift == 0);
+            opCode = (thumbForm) ? THUMB_CMN_RR : THUMB2_CMN_RR;
+            break;
+        case OP_CMP:
+            if (thumbForm)
+                opCode = THUMB_CMP_RR;
+            else if ((shift == 0) && !LOWREG(rDestSrc1) && !LOWREG(rSrc2))
+                opCode = THUMB_CMP_HH;
+            else if ((shift == 0) && LOWREG(rDestSrc1))
+                opCode = THUMB_CMP_LH;
+            else if (shift == 0)
+                opCode = THUMB_CMP_HL;
+            else
+                opCode = THUMB2_CMP_RR;
+            break;
+        case OP_XOR:
+            opCode = (thumbForm) ? THUMB_EOR_RR : THUMB2_EOR_RRR;
+            break;
+        case OP_MOV:
+            assert(shift == 0);
+            if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
+                opCode = THUMB_MOV_RR;
+            else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2))
+                opCode = THUMB_MOV_RR_H2H;
+            else if (LOWREG(rDestSrc1))
+                opCode = THUMB_MOV_RR_H2L;
+            else
+                opCode = THUMB_MOV_RR_L2H;
+            break;
+        case OP_MUL:
+            assert(shift == 0);
+            opCode = (thumbForm) ? THUMB_MUL : THUMB2_MUL_RRR;
+            break;
+        case OP_MVN:
+            opCode = (thumbForm) ? THUMB_MVN : THUMB2_MVN_RR;
+            break;
+        case OP_NEG:
+            assert(shift == 0);
+            opCode = (thumbForm) ? THUMB_NEG : THUMB2_NEG_RR;
+            break;
+        case OP_OR:
+            opCode = (thumbForm) ? THUMB_ORR : THUMB2_ORR_RRR;
+            break;
+        case OP_SBC:
+            opCode = (thumbForm) ? THUMB_SBC : THUMB2_SBC_RRR;
+            break;
+        case OP_TST:
+            opCode = (thumbForm) ? THUMB_TST : THUMB2_TST_RR;
+            break;
+        case OP_LSL:
+            assert(shift == 0);
+            opCode = (thumbForm) ? THUMB_LSL_RR : THUMB2_LSL_RRR;
+            break;
+        case OP_LSR:
+            assert(shift == 0);
+            opCode = (thumbForm) ? THUMB_LSR_RR : THUMB2_LSR_RRR;
+            break;
+        case OP_ASR:
+            assert(shift == 0);
+            opCode = (thumbForm) ? THUMB_ASR_RR : THUMB2_ASR_RRR;
+            break;
+        case OP_ROR:
+            assert(shift == 0);
+            opCode = (thumbForm) ? THUMB_ROR_RR : THUMB2_ROR_RRR;
+            break;
+        case OP_ADD:
+            opCode = (thumbForm) ? THUMB_ADD_RRR : THUMB2_ADD_RRR;
+            break;
+        case OP_SUB:
+            opCode = (thumbForm) ? THUMB_SUB_RRR : THUMB2_SUB_RRR;
+            break;
+        case OP_2BYTE:
+            assert(shift == 0);
+            return newLIR4(cUnit, THUMB2_SBFX, rDestSrc1, rSrc2, 0, 8);
+        case OP_2SHORT:
+            assert(shift == 0);
+            return newLIR4(cUnit, THUMB2_SBFX, rDestSrc1, rSrc2, 0, 16);
+        case OP_2CHAR:
+            assert(shift == 0);
+            return newLIR4(cUnit, THUMB2_UBFX, rDestSrc1, rSrc2, 0, 16);
+        default:
+            assert(0);
+            break;
+    }
+    assert(opCode >= 0);
+    if (EncodingMap[opCode].flags & IS_BINARY_OP)
+        return newLIR2(cUnit, opCode, rDestSrc1, rSrc2);
+    else if (EncodingMap[opCode].flags & IS_TERTIARY_OP) {
+        if (EncodingMap[opCode].fieldLoc[2].kind == SHIFT)
+            return newLIR3(cUnit, opCode, rDestSrc1, rSrc2, shift);
+        else
+            return newLIR3(cUnit, opCode, rDestSrc1, rDestSrc1, rSrc2);
+    } else if (EncodingMap[opCode].flags & IS_QUAD_OP)
+        return newLIR4(cUnit, opCode, rDestSrc1, rDestSrc1, rSrc2, shift);
+    else {
+        assert(0);
+        return NULL;
+    }
+}
+
+static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+                        int rSrc2)
+{
+    return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
+}
+
+/* Handle Thumb-only variants here - otherwise punt to opRegRegImm */
+static ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+                        int value, int rScratch)
+{
+    ArmLIR *res;
+    bool neg = (value < 0);
+    int absValue = (neg) ? -value : value;
+    bool shortForm = (((absValue & 0xff) == absValue) && LOWREG(rDestSrc1));
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_ADD:
+            if ( !neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
+                assert((value & 0x3) == 0);
+                return newLIR1(cUnit, THUMB_ADD_SPI7, value >> 2);
+            } else if (shortForm) {
+                opCode = (neg) ? THUMB_SUB_RI8 : THUMB_ADD_RI8;
+            }
+            break;
+        case OP_SUB:
+            if (!neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
+                assert((value & 0x3) == 0);
+                return newLIR1(cUnit, THUMB_SUB_SPI7, value >> 2);
+            } else if (shortForm) {
+                opCode = (neg) ? THUMB_ADD_RI8 : THUMB_SUB_RI8;
+            }
+            break;
+        case OP_CMP:
+            if (LOWREG(rDestSrc1) && shortForm)
+                opCode = (shortForm) ?  THUMB_CMP_RI8 : THUMB_CMP_RR;
+            else if (LOWREG(rDestSrc1))
+                opCode = THUMB_CMP_RR;
+            else {
+                shortForm = false;
+                opCode = THUMB_CMP_HL;
+            }
+            break;
+        default:
+            /* Punt to opRegRegImm - if bad case catch it there */
+            shortForm = false;
+            break;
+    }
+    if (shortForm)
+        return newLIR2(cUnit, opCode, rDestSrc1, absValue);
+    else
+        return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value, rScratch);
+}
+
+static ArmLIR *opRegRegRegShift(CompilationUnit *cUnit, OpKind op,
+                                int rDest, int rSrc1, int rSrc2, int shift)
+{
+    ArmOpCode opCode = THUMB_BKPT;
+    bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) &&
+                      LOWREG(rSrc2);
+    switch (op) {
+        case OP_ADD:
+            opCode = (thumbForm) ? THUMB_ADD_RRR : THUMB2_ADD_RRR;
+            break;
+        case OP_SUB:
+            opCode = (thumbForm) ? THUMB_SUB_RRR : THUMB2_SUB_RRR;
+            break;
+        case OP_ADC:
+            opCode = THUMB2_ADC_RRR;
+            break;
+        case OP_AND:
+            opCode = THUMB2_AND_RRR;
+            break;
+        case OP_BIC:
+            opCode = THUMB2_BIC_RRR;
+            break;
+        case OP_XOR:
+            opCode = THUMB2_EOR_RRR;
+            break;
+        case OP_MUL:
+            assert(shift == 0);
+            opCode = THUMB2_MUL_RRR;
+            break;
+        case OP_OR:
+            opCode = THUMB2_ORR_RRR;
+            break;
+        case OP_SBC:
+            opCode = THUMB2_SBC_RRR;
+            break;
+        case OP_LSL:
+            assert(shift == 0);
+            opCode = THUMB2_LSL_RRR;
+            break;
+        case OP_LSR:
+            assert(shift == 0);
+            opCode = THUMB2_LSR_RRR;
+            break;
+        case OP_ASR:
+            assert(shift == 0);
+            opCode = THUMB2_ASR_RRR;
+            break;
+        case OP_ROR:
+            assert(shift == 0);
+            opCode = THUMB2_ROR_RRR;
+            break;
+        default:
+            assert(0);
+            break;
+    }
+    assert(opCode >= 0);
+    if (EncodingMap[opCode].flags & IS_QUAD_OP)
+        return newLIR4(cUnit, opCode, rDest, rSrc1, rSrc2, shift);
+    else {
+        assert(EncodingMap[opCode].flags & IS_TERTIARY_OP);
+        return newLIR3(cUnit, opCode, rDest, rSrc1, rSrc2);
+    }
+}
+
+static ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+                           int rSrc1, int rSrc2)
+{
+    return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
+}
+
+static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+                           int rSrc1, int value, int rScratch)
+{
+    ArmLIR *res;
+    bool neg = (value < 0);
+    int absValue = (neg) ? -value : value;
+    ArmOpCode opCode = THUMB_BKPT;
+    ArmOpCode altOpCode = THUMB_BKPT;
+    bool allLowRegs = (LOWREG(rDest) && LOWREG(rSrc1));
+    int modImm = modifiedImmediate(value);
+    int modImmNeg = modifiedImmediate(-value);
+
+    switch(op) {
+        case OP_LSL:
+            if (allLowRegs)
+                return newLIR3(cUnit, THUMB_LSL_RRI5, rDest, rSrc1, value);
+            else
+                return newLIR3(cUnit, THUMB2_LSL_RRI5, rDest, rSrc1, value);
+        case OP_LSR:
+            if (allLowRegs)
+                return newLIR3(cUnit, THUMB_LSR_RRI5, rDest, rSrc1, value);
+            else
+                return newLIR3(cUnit, THUMB2_LSR_RRI5, rDest, rSrc1, value);
+        case OP_ASR:
+            if (allLowRegs)
+                return newLIR3(cUnit, THUMB_ASR_RRI5, rDest, rSrc1, value);
+            else
+                return newLIR3(cUnit, THUMB2_ASR_RRI5, rDest, rSrc1, value);
+        case OP_ROR:
+            return newLIR3(cUnit, THUMB2_ROR_RRI5, rDest, rSrc1, value);
+        case OP_ADD:
+            if (LOWREG(rDest) && (rSrc1 == 13) &&
+                (value <= 1020) && ((value & 0x3)==0)) {
+                return newLIR3(cUnit, THUMB_ADD_SP_REL, rDest, rSrc1,
+                               value >> 2);
+            } else if (LOWREG(rDest) && (rSrc1 == rpc) &&
+                       (value <= 1020) && ((value & 0x3)==0)) {
+                return newLIR3(cUnit, THUMB_ADD_PC_REL, rDest, rSrc1,
+                               value >> 2);
+            }
+            opCode = THUMB2_ADD_RRI8;
+            altOpCode = THUMB2_ADD_RRR;
+            // Note: intentional fallthrough
+        case OP_SUB:
+            if (allLowRegs && ((absValue & 0x7) == absValue)) {
+                if (op == OP_ADD)
+                    opCode = (neg) ? THUMB_SUB_RRI3 : THUMB_ADD_RRI3;
+                else
+                    opCode = (neg) ? THUMB_ADD_RRI3 : THUMB_SUB_RRI3;
+                return newLIR3(cUnit, opCode, rDest, rSrc1, absValue);
+            } else if ((absValue & 0xff) == absValue) {
+                if (op == OP_ADD)
+                    opCode = (neg) ? THUMB2_SUB_RRI12 : THUMB2_ADD_RRI12;
+                else
+                    opCode = (neg) ? THUMB2_ADD_RRI12 : THUMB2_SUB_RRI12;
+                return newLIR3(cUnit, opCode, rDest, rSrc1, absValue);
+            }
+            if (modImmNeg >= 0) {
+                op = (op == OP_ADD) ? OP_SUB : OP_ADD;
+                modImm = modImmNeg;
+            }
+            if (op == OP_SUB) {
+                opCode = THUMB2_SUB_RRI8;
+                altOpCode = THUMB2_SUB_RRR;
+            }
+            break;
+        case OP_ADC:
+            opCode = THUMB2_ADC_RRI8;
+            altOpCode = THUMB2_ADC_RRR;
+            break;
+        case OP_SBC:
+            opCode = THUMB2_SBC_RRI8;
+            altOpCode = THUMB2_SBC_RRR;
+            break;
+        case OP_OR:
+            opCode = THUMB2_ORR_RRI8;
+            altOpCode = THUMB2_ORR_RRR;
+            break;
+        case OP_AND:
+            opCode = THUMB2_AND_RRI8;
+            altOpCode = THUMB2_AND_RRR;
+            break;
+        case OP_XOR:
+            opCode = THUMB2_EOR_RRI8;
+            altOpCode = THUMB2_EOR_RRR;
+            break;
+        case OP_MUL:
+            //TUNING: power of 2, shift & add
+            modImm = -1;
+            altOpCode = THUMB2_MUL_RRR;
+            break;
+        default:
+            assert(0);
+    }
+
+    if (modImm >= 0) {
+        return newLIR3(cUnit, opCode, rDest, rSrc1, modImm);
+    } else {
+        loadConstant(cUnit, rScratch, value);
+        if (EncodingMap[altOpCode].flags & IS_QUAD_OP)
+            return newLIR4(cUnit, altOpCode, rDest, rSrc1, rScratch, 0);
+        else
+            return newLIR3(cUnit, altOpCode, rDest, rSrc1, rScratch);
+    }
+}
+
+/*
+ * 64-bit 3way compare function.
+ *     mov   r7, #-1
+ *     cmp   op1hi, op2hi
+ *     blt   done
+ *     bgt   flip
+ *     sub   r7, op1lo, op2lo (treat as unsigned)
+ *     beq   done
+ *     ite   hi
+ *     mov(hi)   r7, #-1
+ *     mov(!hi)  r7, #1
+ * flip:
+ *     neg   r7
+ * done:
+ */
+static void genCmpLong(CompilationUnit *cUnit, MIR *mir,
+                               int vDest, int vSrc1, int vSrc2)
+{
+    int op1lo = selectFirstRegister(cUnit, vSrc1, true);
+    int op1hi = NEXT_REG(op1lo);
+    int op2lo = NEXT_REG(op1hi);
+    int op2hi = NEXT_REG(op2lo);
+    loadValuePair(cUnit, vSrc1, op1lo, op1hi);
+    loadValuePair(cUnit, vSrc2, op2lo, op2hi);
+    /* Note: using hardcoded r7 & r4PC for now.  revisit */
+    loadConstant(cUnit, r7, -1);
+    opRegReg(cUnit, OP_CMP, op1hi, op2hi);
+    ArmLIR *branch1 = opCondBranch(cUnit, ARM_COND_LT);
+    ArmLIR *branch2 = opCondBranch(cUnit, ARM_COND_GT);
+    opRegRegReg(cUnit, OP_SUB, r7, op1lo, op2lo);
+    ArmLIR *branch3 = opCondBranch(cUnit, ARM_COND_EQ);
+
+    // TODO: need assert mechanism to verify IT block size
+    branch1->generic.target = (LIR *) genIT(cUnit, ARM_COND_HI, "E");
+    newLIR2(cUnit, THUMB2_MOV_IMM_SHIFT, r7, modifiedImmediate(-1));
+    newLIR2(cUnit, THUMB_MOV_IMM, r7, 1);
+    genBarrier(cUnit);
+
+    branch2->generic.target = (LIR *) opRegReg(cUnit, OP_NEG, r7, r7);
+    branch1->generic.target = (LIR *) storeValue(cUnit, r7, vDest, r4PC);
+    branch3->generic.target = branch1->generic.target;
+}
+
+static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int offset = offsetof(InterpState, retval);
+    int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
+    int reg1 = NEXT_REG(regObj);
+    int vDest = inlinedTarget(mir);
+    loadValue(cUnit, dInsn->arg[0], regObj);
+    genNullCheck(cUnit, dInsn->arg[0], regObj, mir->offset, NULL);
+    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, reg1);
+    if (vDest >= 0)
+        storeValue(cUnit, reg1, vDest, regObj);
+    else
+        storeWordDisp(cUnit, rGLUE, offset, reg1, rNone);
+    return false;
+}
+
+static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int offset = offsetof(InterpState, retval);
+    int contents = offsetof(ArrayObject, contents);
+    int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
+    int regIdx = NEXT_REG(regObj);
+    int regMax = NEXT_REG(regIdx);
+    int regOff = NEXT_REG(regMax);
+    int vDest = inlinedTarget(mir);
+    loadValue(cUnit, dInsn->arg[0], regObj);
+    loadValue(cUnit, dInsn->arg[1], regIdx);
+    ArmLIR * pcrLabel = genNullCheck(cUnit, dInsn->arg[0], regObj,
+                                         mir->offset, NULL);
+    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, regMax);
+    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_offset, regOff);
+    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_value, regObj);
+    genBoundsCheck(cUnit, regIdx, regMax, mir->offset, pcrLabel);
+    opRegImm(cUnit, OP_ADD, regObj, contents, rNone);
+    opRegReg(cUnit, OP_ADD, regIdx, regOff);
+    loadBaseIndexed(cUnit, regObj, regIdx, regMax, 1, UNSIGNED_HALF);
+    if (vDest >= 0)
+        storeValue(cUnit, regMax, vDest, regObj);
+    else
+        storeWordDisp(cUnit, rGLUE, offset, regMax, rNone);
+    return false;
+}
+
+static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
+{
+    int offset = offsetof(InterpState, retval);
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+    int sign = NEXT_REG(reg0);
+    int vDest = inlinedTarget(mir);
+    /* abs(x) = y<=x>>31, (x+y)^y.  */
+    loadValue(cUnit, dInsn->arg[0], reg0);
+    /*
+     * Thumb2's IT block also yields 3 instructions, but imposes
+     * scheduling constraints.
+     */
+    opRegRegImm(cUnit, OP_ASR, sign, reg0, 31, rNone);
+    opRegReg(cUnit, OP_ADD, reg0, sign);
+    opRegReg(cUnit, OP_XOR, reg0, sign);
+    if (vDest >= 0)
+        storeValue(cUnit, reg0, vDest, sign);
+    else
+        storeWordDisp(cUnit, rGLUE, offset, reg0, rNone);
+    return false;
+}
+
+static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir)
+{
+    int offset = offsetof(InterpState, retval);
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+    int signMask = NEXT_REG(reg0);
+    int vDest = inlinedTarget(mir);
+    // TUNING: handle case of src already in FP reg
+    loadValue(cUnit, dInsn->arg[0], reg0);
+    loadConstant(cUnit, signMask, 0x7fffffff);
+    newLIR2(cUnit, THUMB_AND_RR, reg0, signMask);
+    if (vDest >= 0)
+        storeValue(cUnit, reg0, vDest, signMask);
+    else
+        storeWordDisp(cUnit, rGLUE, offset, reg0, rNone);
+    return false;
+}
+
+static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir)
+{
+    int offset = offsetof(InterpState, retval);
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
+    int ophi = NEXT_REG(oplo);
+    int signMask = NEXT_REG(ophi);
+    int vSrc = dInsn->arg[0];
+    int vDest = inlinedTarget(mir);
+    // TUNING: handle case of src already in FP reg
+    if (vDest >= 0) {
+        /*
+         * FIXME: disable this case to to work around bug until after
+         * new schedule/ralloc mechanisms are done.
+         */
+        if (0 && (vDest == vSrc)) {
+            loadValue(cUnit, vSrc+1, ophi);
+            opRegRegImm(cUnit, OP_AND, ophi, ophi, 0x7fffffff, signMask);
+            storeValue(cUnit, ophi, vDest + 1, signMask);
+        } else {
+            loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
+            opRegRegImm(cUnit, OP_AND, ophi, ophi, 0x7fffffff, signMask);
+            storeValuePair(cUnit, oplo, ophi, vDest, signMask);
+        }
+    } else {
+        loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
+        loadConstant(cUnit, signMask, 0x7fffffff);
+        storeWordDisp(cUnit, rGLUE, offset, oplo, rNone);
+        opRegReg(cUnit, OP_AND, ophi, signMask);
+        storeWordDisp(cUnit, rGLUE, offset + 4, ophi, rNone);
+    }
+    return false;
+}
+
+static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin)
+{
+    int offset = offsetof(InterpState, retval);
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+    int reg1 = NEXT_REG(reg0);
+    int vDest = inlinedTarget(mir);
+    loadValue(cUnit, dInsn->arg[0], reg0);
+    loadValue(cUnit, dInsn->arg[1], reg1);
+    opRegReg(cUnit, OP_CMP, reg0, reg1);
+    //TODO: need assertion mechanism to validate IT region size
+    genIT(cUnit, (isMin) ? ARM_COND_GT : ARM_COND_LT, "");
+    opRegReg(cUnit, OP_MOV, reg0, reg1);
+    genBarrier(cUnit);
+    if (vDest >= 0)
+        storeValue(cUnit, reg0, vDest, reg1);
+    else
+        storeWordDisp(cUnit, rGLUE, offset, reg0, rNone);
+    return false;
+}
+
+static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
+{
+    int offset = offsetof(InterpState, retval);
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
+    int ophi = NEXT_REG(oplo);
+    int sign = NEXT_REG(ophi);
+    int vDest = inlinedTarget(mir);
+    /* abs(x) = y<=x>>31, (x+y)^y. */
+    loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
+    /*
+     * Thumb2 IT block allows slightly shorter sequence,
+     * but introduces a scheduling barrier.  Stick with this
+     * mechanism for now.
+     */
+    opRegRegImm(cUnit, OP_ASR, sign, ophi, 31, rNone);
+    opRegReg(cUnit, OP_ADD, oplo, sign);
+    opRegReg(cUnit, OP_ADC, ophi, sign);
+    opRegReg(cUnit, OP_XOR, oplo, sign);
+    opRegReg(cUnit, OP_XOR, ophi, sign);
+    if (vDest >= 0) {
+        storeValuePair(cUnit, oplo, ophi, vDest, sign);
+    } else {
+        storeWordDisp(cUnit, rGLUE, offset, oplo, rNone);
+        storeWordDisp(cUnit, rGLUE, offset + 4, ophi, rNone);
+    }
+    return false;
+}
diff --git a/vm/compiler/codegen/arm/ThumbUtil.c b/vm/compiler/codegen/arm/ThumbUtil.c
index 8be50ad..4065865 100644
--- a/vm/compiler/codegen/arm/ThumbUtil.c
+++ b/vm/compiler/codegen/arm/ThumbUtil.c
@@ -16,46 +16,89 @@
 
 /*
  * This file contains codegen for the Thumb ISA and is intended to be
- * includes by:and support common to all supported
+ * includes by:
  *
  *        Codegen-$(TARGET_ARCH_VARIANT).c
  *
  */
 
 #include "Codegen.h"
+/* Forward decls */
+static ArmLIR *genNullCheck(CompilationUnit *cUnit, int vReg, int mReg,
+                            int dOffset, ArmLIR *pcrLabel);
+static ArmLIR *loadValueAddress(CompilationUnit *cUnit, int vSrc, int rDest);
+static ArmLIR *loadValue(CompilationUnit *cUnit, int vSrc, int rDest);
+static ArmLIR *loadWordDisp(CompilationUnit *cUnit, int rBase,
+                            int displacement, int rDest);
+static ArmLIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
+                             int displacement, int rSrc, int rScratch);
+static ArmLIR *storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
+                          int rScratch);
+static ArmLIR *genConditionalBranch(CompilationUnit *cUnit,
+                                    ArmConditionCode cond,
+                                    ArmLIR *target);
+static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target);
+static ArmLIR *loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
+                             int rDestHi);
+static ArmLIR *storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
+                              int vDest, int rScratch);
+static ArmLIR *genBoundsCheck(CompilationUnit *cUnit, int rIndex,
+                              int rBound, int dOffset, ArmLIR *pcrLabel);
+static ArmLIR *genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+static int inlinedTarget(MIR *mir);
+
 
 /* Routines which must be supplied here */
-static void loadConstant(CompilationUnit *cUnit, int rDest, int value);
-static void genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC, int rAddr);
-static void genConditionalBranch(CompilationUnit *cUnit,
-                                 ArmConditionCode cond,
-                                 ArmLIR *target);
-static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target);
-static void loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
-                          int rDestHi);
-static void storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
-                           int vDest, int rScratch);
-static void loadValueAddress(CompilationUnit *cUnit, int vSrc, int vDest);
-static void loadValue(CompilationUnit *cUnit, int vSrc, int rDest);
-static void loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
-                         int rDest);
-static void storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
-                       int rScratch);
+static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
+static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC,
+                           int rAddr);
+static ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
+                            int displacement, int rDest, OpSize size,
+                            bool nullCheck, int vReg);
+static ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
+                             int displacement, int rSrc, OpSize size,
+                             int rScratch);
 static inline ArmLIR *genRegImmCheck(CompilationUnit *cUnit,
-                                         ArmConditionCode cond, int reg,
-                                         int checkValue, int dOffset,
-                                         ArmLIR *pcrLabel);
+                                     ArmConditionCode cond, int reg,
+                                     int checkValue, int dOffset,
+                                     ArmLIR *pcrLabel);
+static inline ArmLIR *genRegRegCheck(CompilationUnit *cUnit,
+                                     ArmConditionCode cond,
+                                     int reg1, int reg2, int dOffset,
+                                     ArmLIR *pcrLabel);
 ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+static ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
+static ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask);
 
-/*****************************************************************************/
+static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op);
+static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value);
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc);
+static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc);
+static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+                        int rSrc2);
+static ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+                        int value, int rScratch);
+static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+                           int rSrc1, int value, int rScratch);
+static ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+                           int rSrc1, int rSrc2);
+static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
+                               int rIndex, int rDest, int scale, OpSize size);
+static void genCmpLong(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
+                       int vSrc2);
+
+static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin);
+static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir);
 
 /*
  * Support for register allocation
  */
 
-/* non-existent register */
-#define vNone   (-1)
-
 /* get the next register in r0..r3 in a round-robin fashion */
 #define NEXT_REG(reg) ((reg + 1) & 3)
 /*
@@ -131,15 +174,24 @@
 
 }
 
-/*****************************************************************************/
-
 ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
 {
-    ArmLIR* res = dvmCompilerNew(sizeof(ArmLIR), true);
-    assert(LOWREG(rDest) && LOWREG(rSrc));
+    ArmLIR* res;
+    ArmOpCode opCode;
+    res = dvmCompilerNew(sizeof(ArmLIR), true);
+    if (LOWREG(rDest) && LOWREG(rSrc))
+        opCode = THUMB_MOV_RR;
+    else if (!LOWREG(rDest) && !LOWREG(rSrc))
+         opCode = THUMB_MOV_RR_H2H;
+    else if (LOWREG(rDest))
+         opCode = THUMB_MOV_RR_H2L;
+    else
+         opCode = THUMB_MOV_RR_L2H;
+
     res->operands[0] = rDest;
     res->operands[1] = rSrc;
-    res->opCode = THUMB_MOV_RR;
+    res->opCode = opCode;
+    setupResourceMasks(res);
     if (rDest == rSrc) {
         res->isNop = true;
     }
@@ -150,16 +202,16 @@
  * Load a immediate using a shortcut if possible; otherwise
  * grab from the per-translation literal pool
  */
-static void loadConstant(CompilationUnit *cUnit, int rDest, int value)
+static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value)
 {
+    ArmLIR *res;
     /* See if the value can be constructed cheaply */
     if ((value >= 0) && (value <= 255)) {
-        newLIR2(cUnit, THUMB_MOV_IMM, rDest, value);
-        return;
+        return newLIR2(cUnit, THUMB_MOV_IMM, rDest, value);
     } else if ((value & 0xFFFFFF00) == 0xFFFFFF00) {
-        newLIR2(cUnit, THUMB_MOV_IMM, rDest, ~value);
+        res = newLIR2(cUnit, THUMB_MOV_IMM, rDest, ~value);
         newLIR2(cUnit, THUMB_MVN, rDest, rDest);
-        return;
+        return res;
     }
     /* No shortcut - go ahead and use literal pool */
     ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 255);
@@ -170,6 +222,8 @@
     loadPcRel->opCode = THUMB_LDR_PC_REL;
     loadPcRel->generic.target = (LIR *) dataTarget;
     loadPcRel->operands[0] = rDest;
+    setupResourceMasks(loadPcRel);
+    res = loadPcRel;
     dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
 
     /*
@@ -179,147 +233,221 @@
     if (dataTarget->operands[0] != value) {
         newLIR2(cUnit, THUMB_ADD_RI8, rDest, value - dataTarget->operands[0]);
     }
+    return res;
 }
 
 /* Export the Dalvik PC assicated with an instruction to the StackSave area */
-static void genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC, int rAddr)
+static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC,
+                           int rAddr)
 {
+    ArmLIR *res;
     int offset = offsetof(StackSaveArea, xtra.currentPc);
-    loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
+    res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
     newLIR2(cUnit, THUMB_MOV_RR, rAddr, rFP);
     newLIR2(cUnit, THUMB_SUB_RI8, rAddr, sizeof(StackSaveArea) - offset);
-    newLIR3(cUnit, THUMB_STR_RRI5, rDPC, rAddr, 0);
+    storeWordDisp( cUnit, rAddr, 0, rDPC, -1);
+    return res;
 }
 
-/* Generate conditional branch instructions */
-static void genConditionalBranch(CompilationUnit *cUnit,
-                                 ArmConditionCode cond,
-                                 ArmLIR *target)
+/* Load value from base + scaled index. Note: index reg killed */
+static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
+                               int rIndex, int rDest, int scale, OpSize size)
 {
-    ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
-    branch->generic.target = (LIR *) target;
+    ArmLIR *first = NULL;
+    ArmLIR *res;
+    ArmOpCode opCode = THUMB_BKPT;
+    if (scale)
+        first = opRegRegImm(cUnit, OP_LSL, rIndex, rIndex, scale, rNone);
+    switch (size) {
+        case WORD:
+            opCode = THUMB_LDR_RRR;
+            break;
+        case UNSIGNED_HALF:
+            opCode = THUMB_LDRH_RRR;
+            break;
+        case SIGNED_HALF:
+            opCode = THUMB_LDRSH_RRR;
+            break;
+        case UNSIGNED_BYTE:
+            opCode = THUMB_LDRB_RRR;
+            break;
+        case SIGNED_BYTE:
+            opCode = THUMB_LDRSB_RRR;
+            break;
+        default:
+            assert(0);
+    }
+    res = newLIR3(cUnit, opCode, rDest, rBase, rIndex);
+    return (first) ? first : res;
 }
 
-/* Generate unconditional branch instructions */
-static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
+/* store value base base + scaled index. Note: index reg killed */
+static ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
+                                int rIndex, int rSrc, int scale, OpSize size)
 {
-    ArmLIR *branch = newLIR0(cUnit, THUMB_B_UNCOND);
-    branch->generic.target = (LIR *) target;
-    return branch;
+    ArmLIR *first = NULL;
+    ArmLIR *res;
+    ArmOpCode opCode = THUMB_BKPT;
+    if (scale)
+        first = opRegRegImm(cUnit, OP_LSL, rIndex, rIndex, scale, rNone);
+    switch (size) {
+        case WORD:
+            opCode = THUMB_STR_RRR;
+            break;
+        case UNSIGNED_HALF:
+        case SIGNED_HALF:
+            opCode = THUMB_STRH_RRR;
+            break;
+        case UNSIGNED_BYTE:
+        case SIGNED_BYTE:
+            opCode = THUMB_STRB_RRR;
+            break;
+        default:
+            assert(0);
+    }
+    res = newLIR3(cUnit, opCode, rSrc, rBase, rIndex);
+    return (first) ? first : res;
 }
 
 /*
- * Load a pair of values of rFP[src..src+1] and store them into rDestLo and
- * rDestHi
+ * Load value from base + displacement.  Optionally perform null check
+ * on base (which must have an associated vReg and MIR).  If not
+ * performing null check, incoming MIR can be null. Note: base and
+ * dest must not be the same if there is any chance that the long
+ * form must be used.
  */
-static void loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
-                          int rDestHi)
+static ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
+                            int displacement, int rDest, OpSize size,
+                            bool nullCheck, int vReg)
 {
-    /* Use reg + imm5*4 to load the values if possible */
-    if (vSrc <= 30) {
-        newLIR3(cUnit, THUMB_LDR_RRI5, rDestLo, rFP, vSrc);
-        newLIR3(cUnit, THUMB_LDR_RRI5, rDestHi, rFP, vSrc+1);
-    } else {
-        if (vSrc <= 64) {
-            /* Sneak 4 into the base address first */
-            newLIR3(cUnit, THUMB_ADD_RRI3, rDestLo, rFP, 4);
-            newLIR2(cUnit, THUMB_ADD_RI8, rDestLo, (vSrc-1)*4);
-        } else {
-            /* Offset too far from rFP */
-            loadConstant(cUnit, rDestLo, vSrc*4);
-            newLIR3(cUnit, THUMB_ADD_RRR, rDestLo, rFP, rDestLo);
-        }
-        assert(rDestLo < rDestHi);
-        newLIR2(cUnit, THUMB_LDMIA, rDestLo, (1<<rDestLo) | (1<<(rDestHi)));
+    ArmLIR *first = NULL;
+    ArmLIR *res, *load;
+    ArmOpCode opCode = THUMB_BKPT;
+    bool shortForm = false;
+    int shortMax = 128;
+    int encodedDisp = displacement;
+
+    switch (size) {
+        case WORD:
+            if (LOWREG(rDest) && (rBase == rpc) &&
+                (displacement <= 1020) && (displacement >= 0)) {
+                shortForm = true;
+                encodedDisp >>= 2;
+                opCode = THUMB_LDR_PC_REL;
+            } else if (LOWREG(rDest) && (rBase == r13) &&
+                      (displacement <= 1020) && (displacement >= 0)) {
+                shortForm = true;
+                encodedDisp >>= 2;
+                opCode = THUMB_LDR_SP_REL;
+            } else if (displacement < 128 && displacement >= 0) {
+                assert((displacement & 0x3) == 0);
+                shortForm = true;
+                encodedDisp >>= 2;
+                opCode = THUMB_LDR_RRI5;
+            } else {
+                opCode = THUMB_LDR_RRR;
+            }
+            break;
+        case UNSIGNED_HALF:
+            if (displacement < 64 && displacement >= 0) {
+                assert((displacement & 0x1) == 0);
+                shortForm = true;
+                encodedDisp >>= 1;
+                opCode = THUMB_LDRH_RRI5;
+            } else {
+                opCode = THUMB_LDRH_RRR;
+            }
+            break;
+        case SIGNED_HALF:
+            opCode = THUMB_LDRSH_RRR;
+            break;
+        case UNSIGNED_BYTE:
+            if (displacement < 32 && displacement >= 0) {
+                shortForm = true;
+                opCode = THUMB_LDRB_RRI5;
+            } else {
+                opCode = THUMB_LDRB_RRR;
+            }
+            break;
+        case SIGNED_BYTE:
+            opCode = THUMB_LDRSB_RRR;
+            break;
+        default:
+            assert(0);
     }
+    if (nullCheck)
+        first = genNullCheck(cUnit, vReg, rBase, mir->offset, NULL);
+    if (shortForm) {
+        load = res = newLIR3(cUnit, opCode, rDest, rBase, encodedDisp);
+    } else {
+        assert(rBase != rDest);
+        res = loadConstant(cUnit, rDest, encodedDisp);
+        load = newLIR3(cUnit, opCode, rDest, rBase, rDest);
+    }
+
+    if (rBase == rFP) {
+        annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */);
+    }
+
+    return (first) ? first : res;
 }
 
-/*
- * Store a pair of values of rSrc and rSrc+1 and store them into vDest and
- * vDest+1
- */
-static void storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
-                           int vDest, int rScratch)
+static ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
+                             int displacement, int rSrc, OpSize size,
+                             int rScratch)
 {
-    killNullCheckedRegister(cUnit, vDest);
-    killNullCheckedRegister(cUnit, vDest+1);
-    updateLiveRegisterPair(cUnit, vDest, rSrcLo, rSrcHi);
+    ArmLIR *res, *store;
+    ArmOpCode opCode = THUMB_BKPT;
+    bool shortForm = false;
+    int shortMax = 128;
+    int encodedDisp = displacement;
 
-    /* Use reg + imm5*4 to store the values if possible */
-    if (vDest <= 30) {
-        newLIR3(cUnit, THUMB_STR_RRI5, rSrcLo, rFP, vDest);
-        newLIR3(cUnit, THUMB_STR_RRI5, rSrcHi, rFP, vDest+1);
-    } else {
-        if (vDest <= 64) {
-            /* Sneak 4 into the base address first */
-            newLIR3(cUnit, THUMB_ADD_RRI3, rScratch, rFP, 4);
-            newLIR2(cUnit, THUMB_ADD_RI8, rScratch, (vDest-1)*4);
-        } else {
-            /* Offset too far from rFP */
-            loadConstant(cUnit, rScratch, vDest*4);
-            newLIR3(cUnit, THUMB_ADD_RRR, rScratch, rFP, rScratch);
-        }
-        assert(rSrcLo < rSrcHi);
-        newLIR2(cUnit, THUMB_STMIA, rScratch, (1<<rSrcLo) | (1 << (rSrcHi)));
+    switch (size) {
+        case WORD:
+            if (displacement < 128 && displacement >= 0) {
+                assert((displacement & 0x3) == 0);
+                shortForm = true;
+                encodedDisp >>= 2;
+                opCode = THUMB_STR_RRI5;
+            } else {
+                opCode = THUMB_STR_RRR;
+            }
+            break;
+        case UNSIGNED_HALF:
+        case SIGNED_HALF:
+            if (displacement < 64 && displacement >= 0) {
+                assert((displacement & 0x1) == 0);
+                shortForm = true;
+                encodedDisp >>= 1;
+                opCode = THUMB_STRH_RRI5;
+            } else {
+                opCode = THUMB_STRH_RRR;
+            }
+            break;
+        case UNSIGNED_BYTE:
+        case SIGNED_BYTE:
+            if (displacement < 32 && displacement >= 0) {
+                shortForm = true;
+                opCode = THUMB_STRB_RRI5;
+            } else {
+                opCode = THUMB_STRB_RRR;
+            }
+            break;
+        default:
+            assert(0);
     }
-}
-
-/* Load the address of a Dalvik register on the frame */
-static void loadValueAddress(CompilationUnit *cUnit, int vSrc, int rDest)
-{
-    /* RRI3 can add up to 7 */
-    if (vSrc <= 1) {
-        newLIR3(cUnit, THUMB_ADD_RRI3, rDest, rFP, vSrc*4);
-    } else if (vSrc <= 64) {
-        /* Sneak 4 into the base address first */
-        newLIR3(cUnit, THUMB_ADD_RRI3, rDest, rFP, 4);
-        newLIR2(cUnit, THUMB_ADD_RI8, rDest, (vSrc-1)*4);
+    if (shortForm) {
+        store = res = newLIR3(cUnit, opCode, rSrc, rBase, encodedDisp);
     } else {
-        loadConstant(cUnit, rDest, vSrc*4);
-        newLIR3(cUnit, THUMB_ADD_RRR, rDest, rFP, rDest);
+        assert(rScratch != -1);
+        res = loadConstant(cUnit, rScratch, encodedDisp);
+        store = newLIR3(cUnit, opCode, rSrc, rBase, rScratch);
     }
-}
 
-/* Load a single value from rFP[src] and store them into rDest */
-static void loadValue(CompilationUnit *cUnit, int vSrc, int rDest)
-{
-    /* Use reg + imm5*4 to load the value if possible */
-    if (vSrc <= 31) {
-        newLIR3(cUnit, THUMB_LDR_RRI5, rDest, rFP, vSrc);
-    } else {
-        loadConstant(cUnit, rDest, vSrc*4);
-        newLIR3(cUnit, THUMB_LDR_RRR, rDest, rFP, rDest);
+    if (rBase == rFP) {
+        annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */);
     }
-}
-
-/* Load a word at base + displacement.  Displacement must be word multiple */
-static void loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
-                         int rDest)
-{
-    assert((displacement & 0x3) == 0);
-    /* Can it fit in a RRI5? */
-    if (displacement < 128) {
-        newLIR3(cUnit, THUMB_LDR_RRI5, rDest, rBase, displacement >> 2);
-    } else {
-        loadConstant(cUnit, rDest, displacement);
-        newLIR3(cUnit, THUMB_LDR_RRR, rDest, rBase, rDest);
-    }
-}
-
-/* Store a value from rSrc to vDest */
-static void storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
-                       int rScratch)
-{
-    killNullCheckedRegister(cUnit, vDest);
-    updateLiveRegister(cUnit, vDest, rSrc);
-
-    /* Use reg + imm5*4 to store the value if possible */
-    if (vDest <= 31) {
-        newLIR3(cUnit, THUMB_STR_RRI5, rSrc, rFP, vDest);
-    } else {
-        loadConstant(cUnit, rScratch, vDest*4);
-        newLIR3(cUnit, THUMB_STR_RRR, rSrc, rFP, rScratch);
-    }
+    return res;
 }
 
 /*
@@ -331,7 +459,441 @@
                                          int checkValue, int dOffset,
                                          ArmLIR *pcrLabel)
 {
+    if ((checkValue & 0xff) != checkValue) {
+        /* NOTE: direct use of hot temp r7 here. Revisit. */
+        loadConstant(cUnit, r7, checkValue);
+        return genRegRegCheck(cUnit, cond, reg, r7, dOffset, pcrLabel);
+    }
     newLIR2(cUnit, THUMB_CMP_RI8, reg, checkValue);
     ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
     return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
 }
+
+static ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+{
+    return newLIR2(cUnit, THUMB_LDMIA, rBase, rMask);
+}
+
+static ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+{
+    return newLIR2(cUnit, THUMB_STMIA, rBase, rMask);
+}
+
+static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op)
+{
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_UNCOND_BR:
+            opCode = THUMB_B_UNCOND;
+            break;
+        default:
+            assert(0);
+    }
+    return newLIR0(cUnit, opCode);
+}
+
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc)
+{
+    return newLIR2(cUnit, THUMB_B_COND, 0 /* offset to be patched */, cc);
+}
+
+static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value)
+{
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_PUSH:
+            opCode = THUMB_PUSH;
+            break;
+        case OP_POP:
+            opCode = THUMB_POP;
+            break;
+        default:
+            assert(0);
+    }
+    return newLIR1(cUnit, opCode, value);
+}
+
+static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
+{
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_BLX:
+            opCode = THUMB_BLX_R;
+            break;
+        default:
+            assert(0);
+    }
+    return newLIR1(cUnit, opCode, rDestSrc);
+}
+
+static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+                        int rSrc2)
+{
+    ArmLIR *res;
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_ADC:
+            opCode = THUMB_ADC_RR;
+            break;
+        case OP_AND:
+            opCode = THUMB_AND_RR;
+            break;
+        case OP_BIC:
+            opCode = THUMB_BIC_RR;
+            break;
+        case OP_CMN:
+            opCode = THUMB_CMN_RR;
+            break;
+        case OP_CMP:
+            opCode = THUMB_CMP_RR;
+            break;
+        case OP_XOR:
+            opCode = THUMB_EOR_RR;
+            break;
+        case OP_MOV:
+            if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
+                opCode = THUMB_MOV_RR;
+            else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2))
+                opCode = THUMB_MOV_RR_H2H;
+            else if (LOWREG(rDestSrc1))
+                opCode = THUMB_MOV_RR_H2L;
+            else
+                opCode = THUMB_MOV_RR_L2H;
+            break;
+        case OP_MUL:
+            opCode = THUMB_MUL;
+            break;
+        case OP_MVN:
+            opCode = THUMB_MVN;
+            break;
+        case OP_NEG:
+            opCode = THUMB_NEG;
+            break;
+        case OP_OR:
+            opCode = THUMB_ORR;
+            break;
+        case OP_SBC:
+            opCode = THUMB_SBC;
+            break;
+        case OP_TST:
+            opCode = THUMB_TST;
+            break;
+        case OP_LSL:
+            opCode = THUMB_LSL_RR;
+            break;
+        case OP_LSR:
+            opCode = THUMB_LSR_RR;
+            break;
+        case OP_ASR:
+            opCode = THUMB_ASR_RR;
+            break;
+        case OP_ROR:
+            opCode = THUMB_ROR_RR;
+        case OP_ADD:
+        case OP_SUB:
+            return opRegRegReg(cUnit, op, rDestSrc1, rDestSrc1, rSrc2);
+        case OP_2BYTE:
+             res = opRegRegImm(cUnit, OP_LSL, rDestSrc1, rSrc2, 24, rNone);
+             opRegRegImm(cUnit, OP_ASR, rDestSrc1, rDestSrc1, 24, rNone);
+             return res;
+        case OP_2SHORT:
+             res = opRegRegImm(cUnit, OP_LSL, rDestSrc1, rSrc2, 16, rNone);
+             opRegRegImm(cUnit, OP_ASR, rDestSrc1, rDestSrc1, 16, rNone);
+             return res;
+        case OP_2CHAR:
+             res = opRegRegImm(cUnit, OP_LSL, rDestSrc1, rSrc2, 16, rNone);
+             opRegRegImm(cUnit, OP_LSR, rDestSrc1, rDestSrc1, 16, rNone);
+             return res;
+        default:
+            assert(0);
+            break;
+    }
+    return newLIR2(cUnit, opCode, rDestSrc1, rSrc2);
+}
+
+static ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+                        int value, int rScratch)
+{
+    ArmLIR *res;
+    bool neg = (value < 0);
+    int absValue = (neg) ? -value : value;
+    bool shortForm = (absValue & 0xff) == absValue;
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_ADD:
+            if ( !neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
+                assert((value & 0x3) == 0);
+                return newLIR1(cUnit, THUMB_ADD_SPI7, value >> 2);
+            } else if (shortForm) {
+                opCode = (neg) ? THUMB_SUB_RI8 : THUMB_ADD_RI8;
+            } else
+                opCode = THUMB_ADD_RRR;
+            break;
+        case OP_SUB:
+            if (!neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
+                assert((value & 0x3) == 0);
+                return newLIR1(cUnit, THUMB_SUB_SPI7, value >> 2);
+            } else if (shortForm) {
+                opCode = (neg) ? THUMB_ADD_RI8 : THUMB_SUB_RI8;
+            } else
+                opCode = THUMB_SUB_RRR;
+            break;
+        case OP_CMP:
+            if (LOWREG(rDestSrc1) && shortForm)
+                opCode = (shortForm) ?  THUMB_CMP_RI8 : THUMB_CMP_RR;
+            else if (LOWREG(rDestSrc1))
+                opCode = THUMB_CMP_RR;
+            else {
+                shortForm = false;
+                opCode = THUMB_CMP_HL;
+            }
+            break;
+        default:
+            assert(0);
+            break;
+    }
+    if (shortForm)
+        res = newLIR2(cUnit, opCode, rDestSrc1, absValue);
+    else {
+        assert(rScratch != rNone);
+        res = loadConstant(cUnit, rScratch, value);
+        newLIR3(cUnit, opCode, rDestSrc1, rDestSrc1, rScratch);
+    }
+    return res;
+}
+
+static ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+                           int rSrc1, int rSrc2)
+{
+    ArmOpCode opCode = THUMB_BKPT;
+    switch (op) {
+        case OP_ADD:
+            opCode = THUMB_ADD_RRR;
+            break;
+        case OP_SUB:
+            opCode = THUMB_SUB_RRR;
+            break;
+        default:
+            assert(0);
+            break;
+    }
+    return newLIR3(cUnit, opCode, rDest, rSrc1, rSrc2);
+}
+
+static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+                           int rSrc1, int value, int rScratch)
+{
+    ArmLIR *res;
+    bool neg = (value < 0);
+    int absValue = (neg) ? -value : value;
+    ArmOpCode opCode = THUMB_BKPT;
+    bool shortForm = (absValue & 0x7) == absValue;
+    switch(op) {
+        case OP_ADD:
+            if ((rSrc1 == 13) && (value <= 1020)) { /* sp */
+                assert((value & 0x3) == 0);
+                shortForm = true;
+                opCode = THUMB_ADD_SP_REL;
+                value >>= 2;
+            } else if ((rSrc1 == 15) && (value <= 1020)) { /* pc */
+                assert((value & 0x3) == 0);
+                shortForm = true;
+                opCode = THUMB_ADD_PC_REL;
+                value >>= 2;
+            } else if (shortForm) {
+                opCode = (neg) ? THUMB_SUB_RRI3 : THUMB_ADD_RRI3;
+            } else if ((absValue > 0) && (absValue <= (255 + 7))) {
+                /* Two shots - 1st handle the 7 */
+                opCode = (neg) ? THUMB_SUB_RRI3 : THUMB_ADD_RRI3;
+                res = newLIR3(cUnit, opCode, rDest, rSrc1, 7);
+                opCode = (neg) ? THUMB_SUB_RI8 : THUMB_ADD_RI8;
+                newLIR2(cUnit, opCode, rDest, absValue - 7);
+                return res;
+            } else
+                opCode = THUMB_ADD_RRR;
+            break;
+
+        case OP_SUB:
+            if (shortForm) {
+                opCode = (neg) ? THUMB_ADD_RRI3 : THUMB_SUB_RRI3;
+            } else if ((absValue > 0) && (absValue <= (255 + 7))) {
+                /* Two shots - 1st handle the 7 */
+                opCode = (neg) ? THUMB_ADD_RRI3 : THUMB_SUB_RRI3;
+                res = newLIR3(cUnit, opCode, rDest, rSrc1, 7);
+                opCode = (neg) ? THUMB_ADD_RI8 : THUMB_SUB_RI8;
+                newLIR2(cUnit, opCode, rDest, absValue - 7);
+                return res;
+            } else
+                opCode = THUMB_SUB_RRR;
+            break;
+        case OP_LSL:
+                shortForm = (!neg && value <= 31);
+                opCode = THUMB_LSL_RRI5;
+                break;
+        case OP_LSR:
+                shortForm = (!neg && value <= 31);
+                opCode = THUMB_LSR_RRI5;
+                break;
+        case OP_ASR:
+                shortForm = (!neg && value <= 31);
+                opCode = THUMB_ASR_RRI5;
+                break;
+        case OP_MUL:
+        case OP_AND:
+        case OP_OR:
+        case OP_XOR:
+                if (rDest == rSrc1) {
+                    res = loadConstant(cUnit, rScratch, value);
+                    opRegReg(cUnit, op, rDest, rScratch);
+                } else {
+                    res = loadConstant(cUnit, rDest, value);
+                    opRegReg(cUnit, op, rDest, rSrc1);
+                }
+                return res;
+        default:
+            assert(0);
+            break;
+    }
+    if (shortForm)
+        res = newLIR3(cUnit, opCode, rDest, rSrc1, absValue);
+    else {
+        if (rDest != rSrc1) {
+            res = loadConstant(cUnit, rDest, value);
+            newLIR3(cUnit, opCode, rDest, rSrc1, rDest);
+        } else {
+            assert(rScratch != rNone);
+            res = loadConstant(cUnit, rScratch, value);
+            newLIR3(cUnit, opCode, rDest, rSrc1, rScratch);
+        }
+    }
+    return res;
+}
+
+static void genCmpLong(CompilationUnit *cUnit, MIR *mir,
+                               int vDest, int vSrc1, int vSrc2)
+{
+    loadValuePair(cUnit, vSrc1, r0, r1);
+    loadValuePair(cUnit, vSrc2, r2, r3);
+    genDispatchToHandler(cUnit, TEMPLATE_CMP_LONG);
+    storeValue(cUnit, r0, vDest, r1);
+}
+
+static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int offset = offsetof(InterpState, retval);
+    int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
+    int reg1 = NEXT_REG(regObj);
+    loadValue(cUnit, dInsn->arg[0], regObj);
+    genNullCheck(cUnit, dInsn->arg[0], regObj, mir->offset, NULL);
+    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, reg1);
+    storeWordDisp(cUnit, rGLUE, offset, reg1, regObj);
+    return false;
+}
+
+static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int offset = offsetof(InterpState, retval);
+    int contents = offsetof(ArrayObject, contents);
+    int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
+    int regIdx = NEXT_REG(regObj);
+    int regMax = NEXT_REG(regIdx);
+    int regOff = NEXT_REG(regMax);
+    loadValue(cUnit, dInsn->arg[0], regObj);
+    loadValue(cUnit, dInsn->arg[1], regIdx);
+    ArmLIR * pcrLabel = genNullCheck(cUnit, dInsn->arg[0], regObj,
+                                         mir->offset, NULL);
+    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, regMax);
+    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_offset, regOff);
+    loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_value, regObj);
+    genBoundsCheck(cUnit, regIdx, regMax, mir->offset, pcrLabel);
+
+    newLIR2(cUnit, THUMB_ADD_RI8, regObj, contents);
+    newLIR3(cUnit, THUMB_ADD_RRR, regIdx, regIdx, regOff);
+    newLIR3(cUnit, THUMB_ADD_RRR, regIdx, regIdx, regIdx);
+    newLIR3(cUnit, THUMB_LDRH_RRR, regMax, regObj, regIdx);
+    storeWordDisp(cUnit, rGLUE, offset, regMax, regObj);
+    return false;
+}
+
+static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
+{
+    int offset = offsetof(InterpState, retval);
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+    int sign = NEXT_REG(reg0);
+    /* abs(x) = y<=x>>31, (x+y)^y.  Shorter in ARM/THUMB2, no skip in THUMB */
+    loadValue(cUnit, dInsn->arg[0], reg0);
+    newLIR3(cUnit, THUMB_ASR_RRI5, sign, reg0, 31);
+    newLIR3(cUnit, THUMB_ADD_RRR, reg0, reg0, sign);
+    newLIR2(cUnit, THUMB_EOR_RR, reg0, sign);
+    storeWordDisp(cUnit, rGLUE, offset, reg0, sign);
+    return false;
+}
+
+static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir)
+{
+    int offset = offsetof(InterpState, retval);
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+    int signMask = NEXT_REG(reg0);
+    loadValue(cUnit, dInsn->arg[0], reg0);
+    loadConstant(cUnit, signMask, 0x7fffffff);
+    newLIR2(cUnit, THUMB_AND_RR, reg0, signMask);
+    storeWordDisp(cUnit, rGLUE, offset, reg0, signMask);
+    return false;
+}
+
+static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir)
+{
+    int offset = offsetof(InterpState, retval);
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
+    int ophi = NEXT_REG(oplo);
+    int signMask = NEXT_REG(ophi);
+    loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
+    loadConstant(cUnit, signMask, 0x7fffffff);
+    storeWordDisp(cUnit, rGLUE, offset, oplo, ophi);
+    newLIR2(cUnit, THUMB_AND_RR, ophi, signMask);
+    storeWordDisp(cUnit, rGLUE, offset + 4, ophi, oplo);
+    return false;
+}
+
+ /* No select in thumb, so we need to branch.  Thumb2 will do better */
+static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin)
+{
+    int offset = offsetof(InterpState, retval);
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+    int reg1 = NEXT_REG(reg0);
+    loadValue(cUnit, dInsn->arg[0], reg0);
+    loadValue(cUnit, dInsn->arg[1], reg1);
+    newLIR2(cUnit, THUMB_CMP_RR, reg0, reg1);
+    ArmLIR *branch1 = newLIR2(cUnit, THUMB_B_COND, 2,
+           isMin ? ARM_COND_LT : ARM_COND_GT);
+    newLIR2(cUnit, THUMB_MOV_RR, reg0, reg1);
+    ArmLIR *target =
+        newLIR3(cUnit, THUMB_STR_RRI5, reg0, rGLUE, offset >> 2);
+    branch1->generic.target = (LIR *)target;
+    return false;
+}
+
+static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
+{
+    int offset = offsetof(InterpState, retval);
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
+    int ophi = NEXT_REG(oplo);
+    int sign = NEXT_REG(ophi);
+    /* abs(x) = y<=x>>31, (x+y)^y.  Shorter in ARM/THUMB2, no skip in THUMB */
+    loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
+    newLIR3(cUnit, THUMB_ASR_RRI5, sign, ophi, 31);
+    newLIR3(cUnit, THUMB_ADD_RRR, oplo, oplo, sign);
+    newLIR2(cUnit, THUMB_ADC_RR, ophi, sign);
+    newLIR2(cUnit, THUMB_EOR_RR, oplo, sign);
+    newLIR2(cUnit, THUMB_EOR_RR, ophi, sign);
+    storeWordDisp(cUnit, rGLUE, offset, oplo, sign);
+    storeWordDisp(cUnit, rGLUE, offset + 4, ophi, sign);
+    return false;
+}
diff --git a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
index 6c5b010..d07d96e 100644
--- a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
@@ -74,7 +74,7 @@
 }
 
 /* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchInit(void)
+static bool compilerArchVariantInit(void)
 {
     /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
 #define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
@@ -116,21 +116,12 @@
 {
     int offset = offsetof(InterpState, retval);
     OpCode opCode = mir->dalvikInsn.opCode;
-    int vSrc = mir->dalvikInsn.vA;
+    int vSrc = mir->dalvikInsn.arg[0];
     loadValueAddress(cUnit, vSrc, r2);
     genDispatchToHandler(cUnit, TEMPLATE_SQRT_DOUBLE_VFP);
     newLIR3(cUnit, THUMB_STR_RRI5, r0, rGLUE, offset >> 2);
     newLIR3(cUnit, THUMB_STR_RRI5, r1, rGLUE, (offset >> 2) + 1);
-    return false;
-}
-
-static bool genInlineCos(CompilationUnit *cUnit, MIR *mir)
-{
-    return false;
-}
-
-static bool genInlineSin(CompilationUnit *cUnit, MIR *mir)
-{
+    resetRegisterScoreboard(cUnit);
     return false;
 }
 
diff --git a/vm/compiler/codegen/arm/armv5te/ArchVariant.c b/vm/compiler/codegen/arm/armv5te/ArchVariant.c
index a1f2b00..b4a3848 100644
--- a/vm/compiler/codegen/arm/armv5te/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv5te/ArchVariant.c
@@ -74,7 +74,7 @@
 }
 
 /* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchInit(void)
+static bool compilerArchVariantInit(void)
 {
     /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
 #define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
@@ -117,16 +117,6 @@
     return false;   /* punt to C handler */
 }
 
-static bool genInlineCos(CompilationUnit *cUnit, MIR *mir)
-{
-    return false;   /* punt to C handler */
-}
-
-static bool genInlineSin(CompilationUnit *cUnit, MIR *mir)
-{
-    return false;   /* punt to C handler */
-}
-
 static bool genConversion(CompilationUnit *cUnit, MIR *mir)
 {
     return genConversionPortable(cUnit, mir);
diff --git a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
index 92097af..fba1e32 100644
--- a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
+#include <math.h>  // for double sqrt(double)
 
-static void loadFloat(CompilationUnit *cUnit, int vSrc, int rDest);
 
 /*
  * This file is included by Codegen-armv5te-vfp.c, and implements architecture
@@ -77,7 +77,7 @@
 }
 
 /* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchInit(void)
+static bool compilerArchVariantInit(void)
 {
     /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
 #define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
@@ -118,25 +118,31 @@
 static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
 {
     int offset = offsetof(InterpState, retval);
-    int vSrc = mir->dalvikInsn.vA;
+    int vSrc = mir->dalvikInsn.arg[0];
+    int vDest = inlinedTarget(mir);
+    ArmLIR *branch;
+    ArmLIR *target;
+
     loadDouble(cUnit, vSrc, dr1);
     newLIR2(cUnit, THUMB2_VSQRTD, dr0, dr1);
-    assert(offset & 0x3 == 0);  /* Must be word aligned */
-    assert(offset < 1024);
-    newLIR3(cUnit, THUMB2_VSTRD, dr0, rGLUE, offset >> 2);
+    newLIR2(cUnit, THUMB2_VCMPD, dr0, dr0);
+    newLIR0(cUnit, THUMB2_FMSTAT);
+    branch = newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_EQ);
+    loadConstant(cUnit, r2, (int)sqrt);
+    newLIR3(cUnit, THUMB2_FMRRD, r0, r1, dr1);
+    newLIR1(cUnit, THUMB_BLX_R, r2);
+    newLIR3(cUnit, THUMB2_FMDRR, dr0, r0, r1);
+    ArmLIR *label = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+    label->defMask = ENCODE_ALL;
+    branch->generic.target = (LIR *)label;
+    if (vDest >= 0)
+        storeDouble(cUnit, dr0, vDest);
+    else
+        newLIR3(cUnit, THUMB2_VSTRD, dr0, rGLUE, offset >> 2);
+    resetRegisterScoreboard(cUnit);
     return true;
 }
 
-static bool genInlineCos(CompilationUnit *cUnit, MIR *mir)
-{
-    return false;
-}
-
-static bool genInlineSin(CompilationUnit *cUnit, MIR *mir)
-{
-    return false;
-}
-
 static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, int vDest,
                                 int vSrc1, int vSrc2)
 {
@@ -171,10 +177,21 @@
         default:
             return true;
     }
-    loadFloat(cUnit, vSrc1, fr2);
-    loadFloat(cUnit, vSrc2, fr4);
-    newLIR3(cUnit, op, fr0, fr2, fr4);
-    storeFloat(cUnit, fr0, vDest, 0);
+    int reg0, reg1, reg2;
+    reg1 = selectSFPReg(cUnit, vSrc1);
+    reg2 = selectSFPReg(cUnit, vSrc2);
+    /*
+     * The register mapping is overly optimistic and lazily updated so we
+     * need to detect false sharing here.
+     */
+    if (reg1 == reg2 && vSrc1 != vSrc2) {
+        reg2 = nextFPReg(cUnit, vSrc2, false /* isDouble */);
+    }
+    loadFloat(cUnit, vSrc1, reg1);
+    loadFloat(cUnit, vSrc2, reg2);
+    reg0 = selectSFPReg(cUnit, vDest);
+    newLIR3(cUnit, op, reg0, reg1, reg2);
+    storeFloat(cUnit, reg0, vDest);
     return false;
 }
 
@@ -183,10 +200,6 @@
 {
     int op = THUMB_BKPT;
 
-    /*
-     * Don't attempt to optimize register usage since these opcodes call out to
-     * the handlers.
-     */
     switch (mir->dalvikInsn.opCode) {
         case OP_ADD_DOUBLE_2ADDR:
         case OP_ADD_DOUBLE:
@@ -212,10 +225,19 @@
         default:
             return true;
     }
-    loadDouble(cUnit, vSrc1, dr1);
-    loadDouble(cUnit, vSrc2, dr2);
-    newLIR3(cUnit, op, dr0, dr1, dr2);
-    storeDouble(cUnit, dr0, vDest, 0);
+
+    int reg0, reg1, reg2;
+    reg1 = selectDFPReg(cUnit, vSrc1);
+    reg2 = selectDFPReg(cUnit, vSrc2);
+    if (reg1 == reg2 && vSrc1 != vSrc2) {
+        reg2 = nextFPReg(cUnit, vSrc2, true /* isDouble */);
+    }
+    loadDouble(cUnit, vSrc1, reg1);
+    loadDouble(cUnit, vSrc2, reg2);
+    /* Rename the new vDest to a new register */
+    reg0 = selectDFPReg(cUnit, vNone);
+    newLIR3(cUnit, op, reg0, reg1, reg2);
+    storeDouble(cUnit, reg0, vDest);
     return false;
 }
 
@@ -270,18 +292,20 @@
             return true;
     }
     if (longSrc) {
-        srcReg = dr1;
+        srcReg = selectDFPReg(cUnit, vSrc2);
         loadDouble(cUnit, vSrc2, srcReg);
     } else {
-        srcReg = fr2;
+        srcReg = selectSFPReg(cUnit, vSrc2);
         loadFloat(cUnit, vSrc2, srcReg);
     }
     if (longDest) {
-        newLIR2(cUnit, op, dr0, srcReg);
-        storeDouble(cUnit, dr0, vSrc1Dest, 0);
+        int destReg = selectDFPReg(cUnit, vNone);
+        newLIR2(cUnit, op, destReg, srcReg);
+        storeDouble(cUnit, destReg, vSrc1Dest);
     } else {
-        newLIR2(cUnit, op, fr0, srcReg);
-        storeFloat(cUnit, fr0, vSrc1Dest, 0);
+        int destReg = selectSFPReg(cUnit, vNone);
+        newLIR2(cUnit, op, destReg, srcReg);
+        storeFloat(cUnit, destReg, vSrc1Dest);
     }
     return false;
 }
@@ -289,31 +313,61 @@
 static bool genCmpX(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
                     int vSrc2)
 {
-    TemplateOpCode template;
+    bool isDouble;
+    int defaultResult;
+    bool ltNaNBias;
+    int fpReg1, fpReg2;
 
-    /*
-     * Don't attempt to optimize register usage since these opcodes call out to
-     * the handlers.
-     */
     switch(mir->dalvikInsn.opCode) {
         case OP_CMPL_FLOAT:
-            template = TEMPLATE_CMPL_FLOAT_VFP;
+            isDouble = false;
+            defaultResult = -1;
             break;
         case OP_CMPG_FLOAT:
-            template = TEMPLATE_CMPG_FLOAT_VFP;
+            isDouble = false;
+            defaultResult = 1;
             break;
         case OP_CMPL_DOUBLE:
-            template = TEMPLATE_CMPL_DOUBLE_VFP;
+            isDouble = true;
+            defaultResult = -1;
             break;
         case OP_CMPG_DOUBLE:
-            template = TEMPLATE_CMPG_DOUBLE_VFP;
+            isDouble = true;
+            defaultResult = 1;
             break;
         default:
             return true;
     }
-    loadValueAddress(cUnit, vSrc1, r0);
-    loadValueAddress(cUnit, vSrc2, r1);
-    genDispatchToHandler(cUnit, template);
-    storeValue(cUnit, r0, vDest, r1);
+    if (isDouble) {
+        fpReg1 = selectDFPReg(cUnit, vSrc1);
+        fpReg2 = selectDFPReg(cUnit, vSrc2);
+        if (fpReg1 == fpReg2 && vSrc1 != vSrc2) {
+            fpReg2 = nextFPReg(cUnit, vSrc2, true /* isDouble */);
+        }
+        loadDouble(cUnit, vSrc1, fpReg1);
+        loadDouble(cUnit, vSrc2, fpReg2);
+        // Hard-coded use of r7 as temp.  Revisit
+        loadConstant(cUnit, r7, defaultResult);
+        newLIR2(cUnit, THUMB2_VCMPD, fpReg1, fpReg2);
+    } else {
+        fpReg1 = selectSFPReg(cUnit, vSrc1);
+        fpReg2 = selectSFPReg(cUnit, vSrc2);
+        if (fpReg1 == fpReg2 && vSrc1 != vSrc2) {
+            fpReg2 = nextFPReg(cUnit, vSrc2, false /* isDouble */);
+        }
+        loadFloat(cUnit, vSrc1, fpReg1);
+        loadFloat(cUnit, vSrc2, fpReg2);
+        // Hard-coded use of r7 as temp.  Revisit
+        loadConstant(cUnit, r7, defaultResult);
+        newLIR2(cUnit, THUMB2_VCMPS, fpReg1, fpReg2);
+    }
+    newLIR0(cUnit, THUMB2_FMSTAT);
+    genIT(cUnit, (defaultResult == -1) ? ARM_COND_GT : ARM_COND_MI, "");
+    newLIR2(cUnit, THUMB2_MOV_IMM_SHIFT, r7,
+            modifiedImmediate(-defaultResult)); // Must not alter ccodes
+    genIT(cUnit, ARM_COND_EQ, "");
+    loadConstant(cUnit, r7, 0);
+    // Hard-coded use of r4PC as temp.  Revisit
+    storeValue(cUnit, r7, vDest, r4PC);
     return false;
 }
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S
index 3801f49..1b143a9 100644
--- a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S
@@ -25,7 +25,7 @@
     /* op vAA, vBB, vCC */
     fldd    d0, [r0]                    @ d0<- vBB
     fldd    d1, [r1]                    @ d1<- vCC
-    fcmped  d0, d1                      @ compare (vBB, vCC)
+    fcmpd  d0, d1                       @ compare (vBB, vCC)
     mov     r0, #1                      @ r0<- 1 (default)
     fmstat                              @ export status flags
     mvnmi   r0, #0                      @ (less than) r0<- -1
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S
index 1faafa1..0510ef6 100644
--- a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S
@@ -24,7 +24,7 @@
     /* op vAA, vBB, vCC */
     flds    s0, [r0]                    @ d0<- vBB
     flds    s1, [r1]                    @ d1<- vCC
-    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    fcmps  s0, s1                      @ compare (vBB, vCC)
     mov     r0, #1                      @ r0<- 1 (default)
     fmstat                              @ export status flags
     mvnmi   r0, #0                      @ (less than) r0<- -1
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S
index 014f160..bdb42d6 100644
--- a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S
@@ -24,7 +24,7 @@
     /* op vAA, vBB, vCC */
     flds    s0, [r0]                    @ d0<- vBB
     flds    s1, [r1]                    @ d1<- vCC
-    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    fcmps  s0, s1                      @ compare (vBB, vCC)
     mvn     r0, #0                      @ r0<- -1 (default)
     fmstat                              @ export status flags
     movgt   r0, #1                      @ (greater than) r0<- 1
diff --git a/vm/compiler/template/armv5te-vfp/TemplateOpList.h b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
index c95163c..6d1ce67 100644
--- a/vm/compiler/template/armv5te-vfp/TemplateOpList.h
+++ b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
@@ -50,3 +50,4 @@
 JIT_TEMPLATE(CMPG_FLOAT_VFP)
 JIT_TEMPLATE(CMPL_FLOAT_VFP)
 JIT_TEMPLATE(SQRT_DOUBLE_VFP)
+JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
index b20d564..8d31807 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
@@ -22,7 +22,11 @@
     str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
     cmp     r8, #0                      @ suspendCount != 0
     ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
     bxne    lr                          @ bail to the interpreter
+#else
+    bx      lr                          @ bail to interpreter unconditionally
+#endif
 
     @ go ahead and transfer control to the native code
     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
index 0ac7cf8..ec37bf9 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
@@ -31,7 +31,11 @@
     cmp     r8, #0                      @ suspendCount != 0
     bxne    lr                          @ bail to the interpreter
     tst     r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
     bne     .LinvokeNative
+#else
+    bxne    lr                          @ bail to the interpreter
+#endif
 
     ldr     r10, .LdvmJitToInterpNoChain
     ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
diff --git a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
index f0a4623..1e4aad2 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
@@ -9,12 +9,20 @@
     ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
     ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
     ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
     ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+    mov     r9, #0                      @ disable chaining
+#endif
     ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
                                         @ r2<- method we're returning to
     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     cmp     r2, #0                      @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
     beq     1f                          @ bail to interpreter
+#else
+    blxeq   lr                          @ punt to interpreter and compare state
+#endif
     ldr     r0, .LdvmJitToInterpNoChain @ defined in footer.S
     mov     rFP, r10                    @ publish new FP
     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
diff --git a/vm/compiler/template/armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S b/vm/compiler/template/armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S
new file mode 100644
index 0000000..b737798
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S
@@ -0,0 +1,6 @@
+    /*
+     * Throw an exception from JIT'ed code.
+     * On entry:
+     *    r0    Dalvik PC that raises the exception
+     */
+    b       .LhandleException
diff --git a/vm/compiler/template/armv5te/TemplateOpList.h b/vm/compiler/template/armv5te/TemplateOpList.h
index 39cd07a..20fb7fa 100644
--- a/vm/compiler/template/armv5te/TemplateOpList.h
+++ b/vm/compiler/template/armv5te/TemplateOpList.h
@@ -35,3 +35,4 @@
 JIT_TEMPLATE(SHL_LONG)
 JIT_TEMPLATE(SHR_LONG)
 JIT_TEMPLATE(USHR_LONG)
+JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
diff --git a/vm/compiler/template/armv5te/footer.S b/vm/compiler/template/armv5te/footer.S
index 3b0b149..c373250 100644
--- a/vm/compiler/template/armv5te/footer.S
+++ b/vm/compiler/template/armv5te/footer.S
@@ -31,15 +31,19 @@
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
     bne     .LhandleException             @ no, handle exception
     bx      r2
 
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0  Faulting Dalvik PC
+ */
 .LhandleException:
-    ldr     r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
     ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
-    ldr     rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
-    mov     pc, r0                  @ branch to dvmMterpCommonExceptionThrown
+    mov     rPC, r0                 @ reload the faulting Dalvik address
+    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
 
     .align  2
 .LdvmAsmInstructionStart:
diff --git a/vm/compiler/template/armv7-a/TemplateOpList.h b/vm/compiler/template/armv7-a/TemplateOpList.h
index c95163c..6d1ce67 100644
--- a/vm/compiler/template/armv7-a/TemplateOpList.h
+++ b/vm/compiler/template/armv7-a/TemplateOpList.h
@@ -50,3 +50,4 @@
 JIT_TEMPLATE(CMPG_FLOAT_VFP)
 JIT_TEMPLATE(CMPL_FLOAT_VFP)
 JIT_TEMPLATE(SQRT_DOUBLE_VFP)
+JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
diff --git a/vm/compiler/template/config-armv5te-vfp b/vm/compiler/template/config-armv5te-vfp
index 628e75f..ab3ff90 100644
--- a/vm/compiler/template/config-armv5te-vfp
+++ b/vm/compiler/template/config-armv5te-vfp
@@ -42,6 +42,7 @@
     op TEMPLATE_SHL_LONG armv5te
     op TEMPLATE_SHR_LONG armv5te
     op TEMPLATE_USHR_LONG armv5te
+    op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
 
 op-end
 
diff --git a/vm/compiler/template/config-armv7-a b/vm/compiler/template/config-armv7-a
index ecf0b3a..aed0fa7 100644
--- a/vm/compiler/template/config-armv7-a
+++ b/vm/compiler/template/config-armv7-a
@@ -42,6 +42,7 @@
     op TEMPLATE_SHL_LONG armv5te
     op TEMPLATE_SHR_LONG armv5te
     op TEMPLATE_USHR_LONG armv5te
+    op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
 
 op-end
 
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
index 0c433a1..74d6936 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -180,12 +180,20 @@
     ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
     ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
     ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
     ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+    mov     r9, #0                      @ disable chaining
+#endif
     ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
                                         @ r2<- method we're returning to
     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     cmp     r2, #0                      @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
     beq     1f                          @ bail to interpreter
+#else
+    blxeq   lr                          @ punt to interpreter and compare state
+#endif
     ldr     r0, .LdvmJitToInterpNoChain @ defined in footer.S
     mov     rFP, r10                    @ publish new FP
     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
@@ -246,7 +254,11 @@
     cmp     r8, #0                      @ suspendCount != 0
     bxne    lr                          @ bail to the interpreter
     tst     r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
     bne     .LinvokeNative
+#else
+    bxne    lr                          @ bail to the interpreter
+#endif
 
     ldr     r10, .LdvmJitToInterpNoChain
     ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
@@ -391,7 +403,11 @@
     str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
     cmp     r8, #0                      @ suspendCount != 0
     ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
     bxne    lr                          @ bail to the interpreter
+#else
+    bx      lr                          @ bail to interpreter unconditionally
+#endif
 
     @ go ahead and transfer control to the native code
     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
@@ -860,7 +876,7 @@
     /* op vAA, vBB, vCC */
     fldd    d0, [r0]                    @ d0<- vBB
     fldd    d1, [r1]                    @ d1<- vCC
-    fcmped  d0, d1                      @ compare (vBB, vCC)
+    fcmpd  d0, d1                       @ compare (vBB, vCC)
     mov     r0, #1                      @ r0<- 1 (default)
     fmstat                              @ export status flags
     mvnmi   r0, #0                      @ (less than) r0<- -1
@@ -929,7 +945,7 @@
     /* op vAA, vBB, vCC */
     flds    s0, [r0]                    @ d0<- vBB
     flds    s1, [r1]                    @ d1<- vCC
-    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    fcmps  s0, s1                      @ compare (vBB, vCC)
     mov     r0, #1                      @ r0<- 1 (default)
     fmstat                              @ export status flags
     mvnmi   r0, #0                      @ (less than) r0<- -1
@@ -963,7 +979,7 @@
     /* op vAA, vBB, vCC */
     flds    s0, [r0]                    @ d0<- vBB
     flds    s1, [r1]                    @ d1<- vCC
-    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    fcmps  s0, s1                      @ compare (vBB, vCC)
     mvn     r0, #0                      @ r0<- -1 (default)
     fmstat                              @ export status flags
     movgt   r0, #1                      @ (greater than) r0<- 1
@@ -998,6 +1014,18 @@
 .Lsqrt:
     .word   sqrt
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
+dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
+/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
+    /*
+     * Throw an exception from JIT'ed code.
+     * On entry:
+     *    r0    Dalvik PC that raises the exception
+     */
+    b       .LhandleException
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
@@ -1033,15 +1061,19 @@
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
     bne     .LhandleException             @ no, handle exception
     bx      r2
 
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0  Faulting Dalvik PC
+ */
 .LhandleException:
-    ldr     r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
     ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
-    ldr     rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
-    mov     pc, r0                  @ branch to dvmMterpCommonExceptionThrown
+    mov     rPC, r0                 @ reload the faulting Dalvik address
+    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
 
     .align  2
 .LdvmAsmInstructionStart:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
index 29dde74..d2e6f54 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -180,12 +180,20 @@
     ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
     ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
     ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
     ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+    mov     r9, #0                      @ disable chaining
+#endif
     ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
                                         @ r2<- method we're returning to
     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     cmp     r2, #0                      @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
     beq     1f                          @ bail to interpreter
+#else
+    blxeq   lr                          @ punt to interpreter and compare state
+#endif
     ldr     r0, .LdvmJitToInterpNoChain @ defined in footer.S
     mov     rFP, r10                    @ publish new FP
     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
@@ -246,7 +254,11 @@
     cmp     r8, #0                      @ suspendCount != 0
     bxne    lr                          @ bail to the interpreter
     tst     r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
     bne     .LinvokeNative
+#else
+    bxne    lr                          @ bail to the interpreter
+#endif
 
     ldr     r10, .LdvmJitToInterpNoChain
     ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
@@ -391,7 +403,11 @@
     str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
     cmp     r8, #0                      @ suspendCount != 0
     ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
     bxne    lr                          @ bail to the interpreter
+#else
+    bx      lr                          @ bail to interpreter unconditionally
+#endif
 
     @ go ahead and transfer control to the native code
     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
@@ -732,6 +748,18 @@
     bx      lr
 
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
+dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
+/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
+    /*
+     * Throw an exception from JIT'ed code.
+     * On entry:
+     *    r0    Dalvik PC that raises the exception
+     */
+    b       .LhandleException
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
@@ -767,15 +795,19 @@
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
     bne     .LhandleException             @ no, handle exception
     bx      r2
 
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0  Faulting Dalvik PC
+ */
 .LhandleException:
-    ldr     r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
     ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
-    ldr     rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
-    mov     pc, r0                  @ branch to dvmMterpCommonExceptionThrown
+    mov     rPC, r0                 @ reload the faulting Dalvik address
+    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
 
     .align  2
 .LdvmAsmInstructionStart:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index 9e97b74..4ed5ea1 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -180,12 +180,20 @@
     ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
     ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
     ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
     ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+    mov     r9, #0                      @ disable chaining
+#endif
     ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
                                         @ r2<- method we're returning to
     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     cmp     r2, #0                      @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
     beq     1f                          @ bail to interpreter
+#else
+    blxeq   lr                          @ punt to interpreter and compare state
+#endif
     ldr     r0, .LdvmJitToInterpNoChain @ defined in footer.S
     mov     rFP, r10                    @ publish new FP
     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
@@ -246,7 +254,11 @@
     cmp     r8, #0                      @ suspendCount != 0
     bxne    lr                          @ bail to the interpreter
     tst     r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
     bne     .LinvokeNative
+#else
+    bxne    lr                          @ bail to the interpreter
+#endif
 
     ldr     r10, .LdvmJitToInterpNoChain
     ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
@@ -391,7 +403,11 @@
     str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
     cmp     r8, #0                      @ suspendCount != 0
     ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
     bxne    lr                          @ bail to the interpreter
+#else
+    bx      lr                          @ bail to interpreter unconditionally
+#endif
 
     @ go ahead and transfer control to the native code
     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
@@ -860,7 +876,7 @@
     /* op vAA, vBB, vCC */
     fldd    d0, [r0]                    @ d0<- vBB
     fldd    d1, [r1]                    @ d1<- vCC
-    fcmped  d0, d1                      @ compare (vBB, vCC)
+    fcmpd  d0, d1                       @ compare (vBB, vCC)
     mov     r0, #1                      @ r0<- 1 (default)
     fmstat                              @ export status flags
     mvnmi   r0, #0                      @ (less than) r0<- -1
@@ -929,7 +945,7 @@
     /* op vAA, vBB, vCC */
     flds    s0, [r0]                    @ d0<- vBB
     flds    s1, [r1]                    @ d1<- vCC
-    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    fcmps  s0, s1                      @ compare (vBB, vCC)
     mov     r0, #1                      @ r0<- 1 (default)
     fmstat                              @ export status flags
     mvnmi   r0, #0                      @ (less than) r0<- -1
@@ -963,7 +979,7 @@
     /* op vAA, vBB, vCC */
     flds    s0, [r0]                    @ d0<- vBB
     flds    s1, [r1]                    @ d1<- vCC
-    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    fcmps  s0, s1                      @ compare (vBB, vCC)
     mvn     r0, #0                      @ r0<- -1 (default)
     fmstat                              @ export status flags
     movgt   r0, #1                      @ (greater than) r0<- 1
@@ -998,6 +1014,18 @@
 .Lsqrt:
     .word   sqrt
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
+dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
+/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
+    /*
+     * Throw an exception from JIT'ed code.
+     * On entry:
+     *    r0    Dalvik PC that raises the exception
+     */
+    b       .LhandleException
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
@@ -1033,15 +1061,19 @@
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
     bne     .LhandleException             @ no, handle exception
     bx      r2
 
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0  Faulting Dalvik PC
+ */
 .LhandleException:
-    ldr     r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
     ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
-    ldr     rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
-    mov     pc, r0                  @ branch to dvmMterpCommonExceptionThrown
+    mov     rPC, r0                 @ reload the faulting Dalvik address
+    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
 
     .align  2
 .LdvmAsmInstructionStart:
diff --git a/vm/interp/Interp.c b/vm/interp/Interp.c
index 233ee3f..5a0e15f 100644
--- a/vm/interp/Interp.c
+++ b/vm/interp/Interp.c
@@ -897,6 +897,9 @@
     extern void dvmJitToInterpSingleStep();
     extern void dvmJitToTraceSelect();
     extern void dvmJitToPatchPredictedChain();
+#if defined(WITH_SELF_VERIFICATION)
+    extern void dvmJitToBackwardBranch();
+#endif
 
     /*
      * Reserve a static entity here to quickly setup runtime contents as
@@ -909,6 +912,9 @@
         dvmJitToInterpSingleStep,
         dvmJitToTraceSelect,
         dvmJitToPatchPredictedChain,
+#if defined(WITH_SELF_VERIFICATION)
+        dvmJitToBackwardBranch,
+#endif
     };
 #endif
 
diff --git a/vm/interp/InterpDefs.h b/vm/interp/InterpDefs.h
index c9c80e3..28994b7 100644
--- a/vm/interp/InterpDefs.h
+++ b/vm/interp/InterpDefs.h
@@ -38,6 +38,16 @@
 } InterpEntry;
 
 #if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+typedef struct HeapArgSpace {
+    int r0;
+    int r1;
+    int r2;
+    int r3;
+    int regMap;
+} HeapArgSpace;
+#endif
+
 /*
  * There are six entry points from the compiled code to the interpreter:
  * 1) dvmJitToInterpNormal: find if there is a corresponding compilation for
@@ -64,6 +74,9 @@
  *    just been reached).
  * 6) dvmJitToPredictedChain: patch the chaining cell for a virtual call site
  *    to a predicted callee.
+ * 7) dvmJitToBackwardBranch: (WITH_SELF_VERIFICATION ONLY) special case of 1)
+ *    and 5). This is used instead if the ending branch of the trace jumps back
+ *    into the same basic block.
  */
 struct JitToInterpEntries {
     void *dvmJitToInterpNormal;
@@ -72,6 +85,9 @@
     void *dvmJitToInterpSingleStep;
     void *dvmJitToTraceSelect;
     void *dvmJitToPatchPredictedChain;
+#if defined(WITH_SELF_VERIFICATION)
+    void *dvmJitToBackwardBranch;
+#endif
 };
 
 #define JIT_TRACE_THRESH_FILTER_SIZE  16
@@ -145,10 +161,14 @@
 
     int currTraceRun;
     int totalTraceLen;        // Number of Dalvik insts in trace
-    const u2* currTraceHead;        // Start of the trace we're building
-    const u2* currRunHead;          // Start of run we're building
+    const u2* currTraceHead;  // Start of the trace we're building
+    const u2* currRunHead;    // Start of run we're building
     int currRunLen;           // Length of run in 16-bit words
     int lastThreshFilter;
+    const u2* lastPC;         // Stage the PC first for the threaded interpreter
+#if defined(WITH_SELF_VERIFICATION)
+    struct HeapArgSpace heapArgSpace;
+#endif
     const u2* threshFilter[JIT_TRACE_THRESH_FILTER_SIZE];
     JitTraceRun trace[MAX_JIT_RUN_LEN];
 #endif
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index 2bcb1f5..d8dcf1e 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -33,6 +33,302 @@
 #include "compiler/CompilerIR.h"
 #include <errno.h>
 
+#if defined(WITH_SELF_VERIFICATION)
+/* Allocate space for per-thread ShadowSpace data structures */
+void* dvmSelfVerificationShadowSpaceAlloc(Thread* self)
+{
+    self->shadowSpace = (ShadowSpace*) calloc(1, sizeof(ShadowSpace));
+    if (self->shadowSpace == NULL)
+        return NULL;
+
+    self->shadowSpace->registerSpaceSize = REG_SPACE;
+    self->shadowSpace->registerSpace =
+        (int*) calloc(self->shadowSpace->registerSpaceSize, sizeof(int));
+
+    return self->shadowSpace->registerSpace;
+}
+
+/* Free per-thread ShadowSpace data structures */
+void dvmSelfVerificationShadowSpaceFree(Thread* self)
+{
+    free(self->shadowSpace->registerSpace);
+    free(self->shadowSpace);
+}
+
+/*
+ * Save out PC, FP, InterpState, and registers to shadow space.
+ * Return a pointer to the shadow space for JIT to use.
+ */
+void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
+                                   void* interpStatePtr)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowSpace *shadowSpace = self->shadowSpace;
+    InterpState *interpState = (InterpState *) interpStatePtr;
+    int preBytes = interpState->method->outsSize*4 + sizeof(StackSaveArea);
+    int postBytes = interpState->method->registersSize*4;
+
+    //LOGD("### selfVerificationSaveState(%d) pc: 0x%x fp: 0x%x",
+    //    self->threadId, (int)pc, (int)fp);
+
+    if (shadowSpace->selfVerificationState != kSVSIdle) {
+        LOGD("~~~ Save: INCORRECT PREVIOUS STATE(%d): %d",
+            self->threadId, shadowSpace->selfVerificationState);
+        LOGD("********** SHADOW STATE DUMP **********");
+        LOGD("* PC: 0x%x FP: 0x%x", (int)pc, (int)fp);
+    }
+    shadowSpace->selfVerificationState = kSVSStart;
+
+    // Dynamically grow shadow register space if necessary
+    while (preBytes + postBytes > shadowSpace->registerSpaceSize) {
+        shadowSpace->registerSpaceSize *= 2;
+        free(shadowSpace->registerSpace);
+        shadowSpace->registerSpace =
+            (int*) calloc(shadowSpace->registerSpaceSize, sizeof(int));
+    }
+
+    // Remember original state
+    shadowSpace->startPC = pc;
+    shadowSpace->fp = fp;
+    shadowSpace->glue = interpStatePtr;
+    shadowSpace->shadowFP = shadowSpace->registerSpace +
+                            shadowSpace->registerSpaceSize - postBytes/4;
+
+    // Create a copy of the InterpState
+    memcpy(&(shadowSpace->interpState), interpStatePtr, sizeof(InterpState));
+    shadowSpace->interpState.fp = shadowSpace->shadowFP;
+    shadowSpace->interpState.interpStackEnd = (u1*)shadowSpace->registerSpace;
+
+    // Create a copy of the stack
+    memcpy(((char*)shadowSpace->shadowFP)-preBytes, ((char*)fp)-preBytes,
+        preBytes+postBytes);
+
+    // Setup the shadowed heap space
+    shadowSpace->heapSpaceTail = shadowSpace->heapSpace;
+
+    // Reset trace length
+    shadowSpace->traceLength = 0;
+
+    return shadowSpace;
+}
+
+/*
+ * Save ending PC, FP and compiled code exit point to shadow space.
+ * Return a pointer to the shadow space for JIT to restore state.
+ */
+void* dvmSelfVerificationRestoreState(const u2* pc, const void* fp,
+                                      SelfVerificationState exitPoint)
+{
+    Thread *self = dvmThreadSelf();
+    ShadowSpace *shadowSpace = self->shadowSpace;
+    shadowSpace->endPC = pc;
+    shadowSpace->endShadowFP = fp;
+
+    //LOGD("### selfVerificationRestoreState(%d) pc: 0x%x fp: 0x%x endPC: 0x%x",
+    //    self->threadId, (int)shadowSpace->startPC, (int)shadowSpace->fp,
+    //    (int)pc);
+
+    if (shadowSpace->selfVerificationState != kSVSStart) {
+        LOGD("~~~ Restore: INCORRECT PREVIOUS STATE(%d): %d",
+            self->threadId, shadowSpace->selfVerificationState);
+        LOGD("********** SHADOW STATE DUMP **********");
+        LOGD("* Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
+            (int)shadowSpace->endPC);
+        LOGD("* Interp FP: 0x%x", (int)shadowSpace->fp);
+        LOGD("* Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
+            (int)shadowSpace->endShadowFP);
+    }
+
+    // Special case when punting after a single instruction
+    if (exitPoint == kSVSPunt && pc == shadowSpace->startPC) {
+        shadowSpace->selfVerificationState = kSVSIdle;
+    } else {
+        shadowSpace->selfVerificationState = exitPoint;
+    }
+
+    return shadowSpace;
+}
+
+/* Print contents of virtual registers */
+static void selfVerificationPrintRegisters(int* addr, int numWords)
+{
+    int i;
+    for (i = 0; i < numWords; i++) {
+        LOGD("* 0x%x: (v%d) 0x%8x", (int)(addr+i), i, *(addr+i));
+    }
+}
+
+/* Print values maintained in shadowSpace */
+static void selfVerificationDumpState(const u2* pc, Thread* self)
+{
+    ShadowSpace* shadowSpace = self->shadowSpace;
+    StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->curFrame);
+    int frameBytes = (int) shadowSpace->registerSpace +
+                     shadowSpace->registerSpaceSize*4 -
+                     (int) shadowSpace->shadowFP;
+    int localRegs = 0;
+    int frameBytes2 = 0;
+    if (self->curFrame < shadowSpace->fp) {
+        localRegs = (stackSave->method->registersSize -
+                     stackSave->method->insSize)*4;
+        frameBytes2 = (int) shadowSpace->fp - (int) self->curFrame - localRegs;
+    }
+    LOGD("********** SHADOW STATE DUMP **********");
+    LOGD("* CurrentPC: 0x%x, Offset: 0x%04x", (int)pc,
+        (int)(pc - stackSave->method->insns));
+    LOGD("* Class: %s Method: %s", stackSave->method->clazz->descriptor,
+        stackSave->method->name);
+    LOGD("* Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
+        (int)shadowSpace->endPC);
+    LOGD("* Interp FP: 0x%x endFP: 0x%x", (int)shadowSpace->fp,
+        (int)self->curFrame);
+    LOGD("* Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
+        (int)shadowSpace->endShadowFP);
+    LOGD("* Frame1 Bytes: %d Frame2 Local: %d Bytes: %d", frameBytes,
+        localRegs, frameBytes2);
+    LOGD("* Trace length: %d State: %d", shadowSpace->traceLength,
+        shadowSpace->selfVerificationState);
+}
+
+/* Print decoded instructions in the current trace */
+static void selfVerificationDumpTrace(const u2* pc, Thread* self)
+{
+    ShadowSpace* shadowSpace = self->shadowSpace;
+    StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->curFrame);
+    int i, addr, offset;
+    DecodedInstruction *decInsn;
+
+    LOGD("********** SHADOW TRACE DUMP **********");
+    for (i = 0; i < shadowSpace->traceLength; i++) {
+        addr = shadowSpace->trace[i].addr;
+        offset =  (int)((u2*)addr - stackSave->method->insns);
+        decInsn = &(shadowSpace->trace[i].decInsn);
+        /* Not properly decoding instruction, some registers may be garbage */
+        LOGD("* 0x%x: (0x%04x) %s v%d, v%d, v%d", addr, offset,
+            getOpcodeName(decInsn->opCode), decInsn->vA, decInsn->vB,
+            decInsn->vC);
+    }
+}
+
+/* Code is forced into this spin loop when a divergence is detected */
+static void selfVerificationSpinLoop()
+{
+    gDvmJit.selfVerificationSpin = true;
+    while(gDvmJit.selfVerificationSpin) sleep(10);
+}
+
+/* Manage self verification while in the debug interpreter */
+static bool selfVerificationDebugInterp(const u2* pc, Thread* self)
+{
+    ShadowSpace *shadowSpace = self->shadowSpace;
+    SelfVerificationState state = shadowSpace->selfVerificationState;
+
+    DecodedInstruction decInsn;
+    dexDecodeInstruction(gDvm.instrFormat, pc, &decInsn);
+
+    //LOGD("### DbgIntp(%d): PC: 0x%x endPC: 0x%x state: %d len: %d %s",
+    //    self->threadId, (int)pc, (int)shadowSpace->endPC, state,
+    //    shadowSpace->traceLength, getOpcodeName(decInsn.opCode));
+
+    if (state == kSVSIdle || state == kSVSStart) {
+        LOGD("~~~ DbgIntrp: INCORRECT PREVIOUS STATE(%d): %d",
+            self->threadId, state);
+        selfVerificationDumpState(pc, self);
+        selfVerificationDumpTrace(pc, self);
+    }
+
+    /* Skip endPC once when trace has a backward branch */
+    if ((state == kSVSBackwardBranch && pc == shadowSpace->endPC) ||
+        state != kSVSBackwardBranch) {
+        shadowSpace->selfVerificationState = kSVSDebugInterp;
+    }
+
+    /* Check that the current pc is the end of the trace */
+    if ((state == kSVSSingleStep || state == kSVSDebugInterp) &&
+        pc == shadowSpace->endPC) {
+
+        shadowSpace->selfVerificationState = kSVSIdle;
+
+        /* Check register space */
+        int frameBytes = (int) shadowSpace->registerSpace +
+                         shadowSpace->registerSpaceSize*4 -
+                         (int) shadowSpace->shadowFP;
+        if (memcmp(shadowSpace->fp, shadowSpace->shadowFP, frameBytes)) {
+            LOGD("~~~ DbgIntp(%d): REGISTERS UNEQUAL!", self->threadId);
+            selfVerificationDumpState(pc, self);
+            selfVerificationDumpTrace(pc, self);
+            LOGD("*** Interp Registers: addr: 0x%x bytes: %d",
+                (int)shadowSpace->fp, frameBytes);
+            selfVerificationPrintRegisters((int*)shadowSpace->fp, frameBytes/4);
+            LOGD("*** Shadow Registers: addr: 0x%x bytes: %d",
+                (int)shadowSpace->shadowFP, frameBytes);
+            selfVerificationPrintRegisters((int*)shadowSpace->shadowFP,
+                frameBytes/4);
+            selfVerificationSpinLoop();
+        }
+        /* Check new frame if it exists (invokes only) */
+        if (self->curFrame < shadowSpace->fp) {
+            StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->curFrame);
+            int localRegs = (stackSave->method->registersSize -
+                             stackSave->method->insSize)*4;
+            int frameBytes2 = (int) shadowSpace->fp -
+                              (int) self->curFrame - localRegs;
+            if (memcmp(((char*)self->curFrame)+localRegs,
+                ((char*)shadowSpace->endShadowFP)+localRegs, frameBytes2)) {
+                LOGD("~~~ DbgIntp(%d): REGISTERS (FRAME2) UNEQUAL!",
+                    self->threadId);
+                selfVerificationDumpState(pc, self);
+                selfVerificationDumpTrace(pc, self);
+                LOGD("*** Interp Registers: addr: 0x%x l: %d bytes: %d",
+                    (int)self->curFrame, localRegs, frameBytes2);
+                selfVerificationPrintRegisters((int*)self->curFrame,
+                    (frameBytes2+localRegs)/4);
+                LOGD("*** Shadow Registers: addr: 0x%x l: %d bytes: %d",
+                    (int)shadowSpace->endShadowFP, localRegs, frameBytes2);
+                selfVerificationPrintRegisters((int*)shadowSpace->endShadowFP,
+                    (frameBytes2+localRegs)/4);
+                selfVerificationSpinLoop();
+            }
+        }
+
+        /* Check memory space */
+        bool memDiff = false;
+        ShadowHeap* heapSpacePtr;
+        for (heapSpacePtr = shadowSpace->heapSpace;
+             heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+            int memData = *((unsigned int*) heapSpacePtr->addr);
+            if (heapSpacePtr->data != memData) {
+                LOGD("~~~ DbgIntp(%d): MEMORY UNEQUAL!", self->threadId);
+                LOGD("* Addr: 0x%x Intrp Data: 0x%x Jit Data: 0x%x",
+                    heapSpacePtr->addr, memData, heapSpacePtr->data);
+                selfVerificationDumpState(pc, self);
+                selfVerificationDumpTrace(pc, self);
+                memDiff = true;
+            }
+        }
+        if (memDiff) selfVerificationSpinLoop();
+        return true;
+
+    /* If end not been reached, make sure max length not exceeded */
+    } else if (shadowSpace->traceLength >= JIT_MAX_TRACE_LEN) {
+        LOGD("~~~ DbgIntp(%d): CONTROL DIVERGENCE!", self->threadId);
+        LOGD("* startPC: 0x%x endPC: 0x%x currPC: 0x%x",
+            (int)shadowSpace->startPC, (int)shadowSpace->endPC, (int)pc);
+        selfVerificationDumpState(pc, self);
+        selfVerificationDumpTrace(pc, self);
+        selfVerificationSpinLoop();
+
+        return true;
+    }
+    /* Log the instruction address and decoded instruction for debug */
+    shadowSpace->trace[shadowSpace->traceLength].addr = (int)pc;
+    shadowSpace->trace[shadowSpace->traceLength].decInsn = decInsn;
+    shadowSpace->traceLength++;
+
+    return false;
+}
+#endif
+
 int dvmJitStartup(void)
 {
     unsigned int i;
@@ -45,8 +341,9 @@
     if (res && gDvm.executionMode == kExecutionModeJit) {
         JitEntry *pJitTable = NULL;
         unsigned char *pJitProfTable = NULL;
-        assert(gDvm.jitTableSize &&
-            !(gDvm.jitTableSize & (gDvmJit.jitTableSize - 1))); // Power of 2?
+        // Power of 2?
+        assert(gDvmJit.jitTableSize &&
+               !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1)));
         dvmLockMutex(&gDvmJit.tableLock);
         pJitTable = (JitEntry*)
                     calloc(gDvmJit.jitTableSize, sizeof(*pJitTable));
@@ -74,7 +371,7 @@
            pJitTable[i].u.info.chain = gDvmJit.jitTableSize;
         }
         /* Is chain field wide enough for termination pattern? */
-        assert(pJitTable[0].u.info.chain == gDvm.maxJitTableEntries);
+        assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize);
 
 done:
         gDvmJit.pJitEntryTable = pJitTable;
@@ -217,6 +514,9 @@
                           || gDvm.activeProfilers
 #endif
             );
+    /* Prepare to handle last PC and stage the current PC */
+    const u2 *lastPC = interpState->lastPC;
+    interpState->lastPC = pc;
 
     switch (interpState->jitState) {
         char* nopStr;
@@ -224,19 +524,24 @@
         int offset;
         DecodedInstruction decInsn;
         case kJitTSelect:
-            dexDecodeInstruction(gDvm.instrFormat, pc, &decInsn);
+            /* First instruction - just remember the PC and exit */
+            if (lastPC == NULL) break;
+            /* Grow the trace around the last PC if jitState is kJitTSelect */
+            dexDecodeInstruction(gDvm.instrFormat, lastPC, &decInsn);
 #if defined(SHOW_TRACE)
             LOGD("TraceGen: adding %s",getOpcodeName(decInsn.opCode));
 #endif
             flags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
-            len = dexGetInstrOrTableWidthAbs(gDvm.instrWidth, pc);
-            offset = pc - interpState->method->insns;
-            if (pc != interpState->currRunHead + interpState->currRunLen) {
+            len = dexGetInstrOrTableWidthAbs(gDvm.instrWidth, lastPC);
+            offset = lastPC - interpState->method->insns;
+            assert((unsigned) offset <
+                   dvmGetMethodInsnsSize(interpState->method));
+            if (lastPC != interpState->currRunHead + interpState->currRunLen) {
                 int currTraceRun;
                 /* We need to start a new trace run */
                 currTraceRun = ++interpState->currTraceRun;
                 interpState->currRunLen = 0;
-                interpState->currRunHead = (u2*)pc;
+                interpState->currRunHead = (u2*)lastPC;
                 interpState->trace[currTraceRun].frag.startOffset = offset;
                 interpState->trace[currTraceRun].frag.numInsts = 0;
                 interpState->trace[currTraceRun].frag.runEnd = false;
@@ -245,6 +550,12 @@
             interpState->trace[interpState->currTraceRun].frag.numInsts++;
             interpState->totalTraceLen++;
             interpState->currRunLen += len;
+
+            /* Will probably never hit this with the current trace buildier */
+            if (interpState->currTraceRun == (MAX_JIT_RUN_LEN - 1)) {
+                interpState->jitState = kJitTSelectEnd;
+            }
+
             if (  ((flags & kInstrUnconditional) == 0) &&
                   /* don't end trace on INVOKE_DIRECT_EMPTY  */
                   (decInsn.opCode != OP_INVOKE_DIRECT_EMPTY) &&
@@ -324,8 +635,23 @@
         case kJitNormal:
             switchInterp = !debugOrProfile;
             break;
+#if defined(WITH_SELF_VERIFICATION)
+        case kJitSelfVerification:
+            if (selfVerificationDebugInterp(pc, self)) {
+                interpState->jitState = kJitNormal;
+                switchInterp = !debugOrProfile;
+            }
+            break;
+#endif
+        /* If JIT is off stay out of interpreter selections */
+        case kJitOff:
+            break;
         default:
-            dvmAbort();
+            if (!debugOrProfile) {
+                LOGE("Unexpected JIT state: %d", interpState->jitState);
+                dvmAbort();
+            }
+            break;
     }
     return switchInterp;
 }
@@ -575,6 +901,7 @@
                  interpState->trace[0].frag.numInsts = 0;
                  interpState->trace[0].frag.runEnd = false;
                  interpState->trace[0].frag.hint = kJitHintNone;
+                 interpState->lastPC = 0;
                  break;
             case kJitTSelect:
             case kJitTSelectAbort:
@@ -583,8 +910,12 @@
             case kJitSingleStepEnd:
             case kJitOff:
             case kJitNormal:
+#if defined(WITH_SELF_VERIFICATION)
+            case kJitSelfVerification:
+#endif
                 break;
             default:
+                LOGE("Unexpected JIT state: %d", interpState->jitState);
                 dvmAbort();
         }
     }
@@ -603,7 +934,7 @@
     unsigned int oldSize;
     unsigned int i;
 
-    assert(gDvm.pJitEntryTable != NULL);
+    assert(gDvmJit.pJitEntryTable != NULL);
     assert(size && !(size & (size - 1)));   /* Is power of 2? */
 
     LOGD("Jit: resizing JitTable from %d to %d", gDvmJit.jitTableSize, size);
diff --git a/vm/interp/Jit.h b/vm/interp/Jit.h
index 660b5ec..70931b8 100644
--- a/vm/interp/Jit.h
+++ b/vm/interp/Jit.h
@@ -25,6 +25,49 @@
 
 #define JIT_MAX_TRACE_LEN 100
 
+#if defined (WITH_SELF_VERIFICATION)
+
+#define REG_SPACE 256                /* default size of shadow space */
+#define HEAP_SPACE JIT_MAX_TRACE_LEN /* default size of heap space */
+
+typedef struct ShadowHeap {
+    int addr;
+    int data;
+} ShadowHeap;
+
+typedef struct InstructionTrace {
+    int addr;
+    DecodedInstruction decInsn;
+} InstructionTrace;
+
+typedef struct ShadowSpace {
+    const u2* startPC;          /* starting pc of jitted region */
+    const void* fp;             /* starting fp of jitted region */
+    void* glue;                 /* starting glue ptr of jitted region */
+    SelfVerificationState selfVerificationState;  /* self verification state */
+    const u2* endPC;            /* ending pc of jitted region */
+    void* shadowFP;       /* pointer to fp in shadow space */
+    InterpState interpState;    /* copy of interpState */
+    int* registerSpace;         /* copy of register state */
+    int registerSpaceSize;      /* current size of register space */
+    ShadowHeap heapSpace[HEAP_SPACE]; /* copy of heap space */
+    ShadowHeap* heapSpaceTail;        /* tail pointer to heapSpace */
+    const void* endShadowFP;    /* ending fp in shadow space */
+    InstructionTrace trace[JIT_MAX_TRACE_LEN]; /* opcode trace for debugging */
+    int traceLength;            /* counter for current trace length */
+} ShadowSpace;
+
+/*
+ * Self verification functions.
+ */
+void* dvmSelfVerificationShadowSpaceAlloc(Thread* self);
+void dvmSelfVerificationShadowSpaceFree(Thread* self);
+void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
+                                   void* interpStatePtr);
+void* dvmSelfVerificationRestoreState(const u2* pc, const void* fp,
+                                      SelfVerificationState exitPoint);
+#endif
+
 /*
  * JitTable hash function.
  */
diff --git a/vm/interp/Stack.c b/vm/interp/Stack.c
index 5920cbc..fe8ab26 100644
--- a/vm/interp/Stack.c
+++ b/vm/interp/Stack.c
@@ -80,7 +80,7 @@
              "(req=%d top=%p cur=%p size=%d %s.%s)\n",
             stackReq, self->interpStackStart, self->curFrame,
             self->interpStackSize, method->clazz->descriptor, method->name);
-        dvmHandleStackOverflow(self);
+        dvmHandleStackOverflow(self, method);
         assert(dvmCheckException(self));
         return false;
     }
@@ -153,7 +153,7 @@
              "(req=%d top=%p cur=%p size=%d '%s')\n",
             stackReq, self->interpStackStart, self->curFrame,
             self->interpStackSize, method->name);
-        dvmHandleStackOverflow(self);
+        dvmHandleStackOverflow(self, method);
         assert(dvmCheckException(self));
         return false;
     }
@@ -227,7 +227,7 @@
              "(req=%d top=%p cur=%p size=%d '%s')\n",
             stackReq, self->interpStackStart, self->curFrame,
             self->interpStackSize, method->name);
-        dvmHandleStackOverflow(self);
+        dvmHandleStackOverflow(self, method);
         assert(dvmCheckException(self));
         return false;
     }
@@ -1014,7 +1014,7 @@
  * need to resolve classes, which requires calling into the class loader if
  * the classes aren't already in the "initiating loader" list.
  */
-void dvmHandleStackOverflow(Thread* self)
+void dvmHandleStackOverflow(Thread* self, const Method* method)
 {
     /*
      * Can we make the reserved area available?
@@ -1030,7 +1030,15 @@
     }
 
     /* open it up to the full range */
-    LOGI("Stack overflow, expanding (%p to %p)\n", self->interpStackEnd,
+    LOGI("threadid=%d: stack overflow on call to %s.%s:%s\n",
+        self->threadId,
+        method->clazz->descriptor, method->name, method->shorty);
+    StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->curFrame);
+    LOGI("  method requires %d+%d+%d=%d bytes, fp is %p (%d left)\n",
+        method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4,
+        (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea),
+        saveArea, (u1*) saveArea - self->interpStackEnd);
+    LOGI("  expanding stack end (%p to %p)\n", self->interpStackEnd,
         self->interpStackStart - self->interpStackSize);
     //dvmDumpThread(self, false);
     self->interpStackEnd = self->interpStackStart - self->interpStackSize;
diff --git a/vm/interp/Stack.h b/vm/interp/Stack.h
index 22f066f..208fe90 100644
--- a/vm/interp/Stack.h
+++ b/vm/interp/Stack.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Stack frames, and uses thereof.
  */
@@ -275,7 +276,7 @@
 /*
  * Common handling for stack overflow.
  */
-void dvmHandleStackOverflow(Thread* self);
+void dvmHandleStackOverflow(Thread* self, const Method* method);
 void dvmCleanupStackOverflow(Thread* self);
 
 /* debugging; dvmDumpThread() is probably a better starting point */
diff --git a/vm/jdwp/JdwpHandler.c b/vm/jdwp/JdwpHandler.c
index ff6ecf4..53b5d26 100644
--- a/vm/jdwp/JdwpHandler.c
+++ b/vm/jdwp/JdwpHandler.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Handle messages from debugger.
  *
@@ -31,6 +32,7 @@
 
 #include "Bits.h"
 #include "Atomic.h"
+#include "DalvikVersion.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -110,10 +112,14 @@
 
 /*
  * Common code for *_InvokeMethod requests.
+ *
+ * If "isConstructor" is set, this returns "objectId" rather than the
+ * expected-to-be-void return value of the called function.
  */
 static JdwpError finishInvoke(JdwpState* state,
     const u1* buf, int dataLen, ExpandBuf* pReply,
-    ObjectId threadId, ObjectId objectId, RefTypeId classId, MethodId methodId)
+    ObjectId threadId, ObjectId objectId, RefTypeId classId, MethodId methodId,
+    bool isConstructor)
 {
     JdwpError err = ERR_NONE;
     u8* argArray = NULL;
@@ -121,6 +127,8 @@
     u4 options;     /* enum InvokeOptions bit flags */
     int i;
 
+    assert(!isConstructor || objectId != 0);
+
     numArgs = read4BE(&buf);
 
     LOGV("    --> threadId=%llx objectId=%llx\n", threadId, objectId);
@@ -163,11 +171,16 @@
         goto bail;
 
     if (err == ERR_NONE) {
-        int width = dvmDbgGetTagWidth(resultTag);
+        if (isConstructor) {
+            expandBufAdd1(pReply, JT_OBJECT);
+            expandBufAddObjectId(pReply, objectId);
+        } else {
+            int width = dvmDbgGetTagWidth(resultTag);
 
-        expandBufAdd1(pReply, resultTag);
-        if (width != 0)
-            jdwpWriteValue(pReply, width, resultValue);
+            expandBufAdd1(pReply, resultTag);
+            if (width != 0)
+                jdwpWriteValue(pReply, width, resultValue);
+        }
         expandBufAdd1(pReply, JT_OBJECT);
         expandBufAddObjectId(pReply, exceptObjId);
 
@@ -198,8 +211,12 @@
 static JdwpError handleVM_Version(JdwpState* state, const u1* buf,
     int dataLen, ExpandBuf* pReply)
 {
+    char tmpBuf[128];
+
     /* text information on VM version */
-    expandBufAddUtf8String(pReply, (const u1*) "Android DalvikVM 1.0.1");
+    sprintf(tmpBuf, "Android DalvikVM %d.%d.%d",
+        DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
+    expandBufAddUtf8String(pReply, (const u1*) tmpBuf);
     /* JDWP version numbers */
     expandBufAdd4BE(pReply, 1);        // major
     expandBufAdd4BE(pReply, 5);        // minor
@@ -400,8 +417,10 @@
     LOGV("  Req to create string '%s'\n", str);
 
     stringId = dvmDbgCreateString(str);
-    expandBufAddObjectId(pReply, stringId);
+    if (stringId == 0)
+        return ERR_OUT_OF_MEMORY;
 
+    expandBufAddObjectId(pReply, stringId);
     return ERR_NONE;
 }
 
@@ -652,8 +671,6 @@
     const u1* buf, int dataLen, ExpandBuf* pReply)
 {
     RefTypeId refTypeId;
-    u4 numInterfaces;
-    int i;
 
     refTypeId = dvmReadRefTypeId(&buf);
 
@@ -666,6 +683,25 @@
 }
 
 /*
+ * Return the class object corresponding to this type.
+ */
+static JdwpError handleRT_ClassObject(JdwpState* state,
+    const u1* buf, int dataLen, ExpandBuf* pReply)
+{
+    RefTypeId refTypeId;
+    ObjectId classObjId;
+
+    refTypeId = dvmReadRefTypeId(&buf);
+    classObjId = dvmDbgGetClassObject(refTypeId);
+
+    LOGV("  RefTypeId %llx -> ObjectId %llx\n", refTypeId, classObjId);
+
+    expandBufAddObjectId(pReply, classObjId);
+
+    return ERR_NONE;
+}
+
+/*
  * Returns the value of the SourceDebugExtension attribute.
  *
  * JDB seems interested, but DEX files don't currently support this.
@@ -834,7 +870,36 @@
     methodId = dvmReadMethodId(&buf);
 
     return finishInvoke(state, buf, dataLen, pReply,
-            threadId, 0, classId, methodId);
+            threadId, 0, classId, methodId, false);
+}
+
+/*
+ * Create a new object of the requested type, and invoke the specified
+ * constructor.
+ *
+ * Example: in IntelliJ, create a watch on "new String(myByteArray)" to
+ * see the contents of a byte[] as a string.
+ */
+static JdwpError handleCT_NewInstance(JdwpState* state,
+    const u1* buf, int dataLen, ExpandBuf* pReply)
+{
+    RefTypeId classId;
+    ObjectId threadId;
+    MethodId methodId;
+    ObjectId objectId;
+    u4 numArgs;
+
+    classId = dvmReadRefTypeId(&buf);
+    threadId = dvmReadObjectId(&buf);
+    methodId = dvmReadMethodId(&buf);
+
+    LOGV("Creating instance of %s\n", dvmDbgGetClassDescriptor(classId));
+    objectId = dvmDbgCreateObject(classId);
+    if (objectId == 0)
+        return ERR_OUT_OF_MEMORY;
+
+    return finishInvoke(state, buf, dataLen, pReply,
+            threadId, objectId, classId, methodId, true);
 }
 
 /*
@@ -1011,7 +1076,7 @@
     methodId = dvmReadMethodId(&buf);
 
     return finishInvoke(state, buf, dataLen, pReply,
-            threadId, objectId, classId, methodId);
+            threadId, objectId, classId, methodId, false);
 }
 
 /*
@@ -1938,7 +2003,7 @@
     //2,    8,  NestedTypes
     { 2,    9,  handleRT_Status,        "ReferenceType.Status" },
     { 2,    10, handleRT_Interfaces,    "ReferenceType.Interfaces" },
-    //2,    11, ClassObject
+    { 2,    11, handleRT_ClassObject,   "ReferenceType.ClassObject" },
     { 2,    12, handleRT_SourceDebugExtension,
                                         "ReferenceType.SourceDebugExtension" },
     { 2,    13, handleRT_SignatureWithGeneric,
@@ -1955,7 +2020,7 @@
     { 3,    1,  handleCT_Superclass,    "ClassType.Superclass" },
     { 3,    2,  handleCT_SetValues,     "ClassType.SetValues" },
     { 3,    3,  handleCT_InvokeMethod,  "ClassType.InvokeMethod" },
-    //3,    4,  NewInstance
+    { 3,    4,  handleCT_NewInstance,   "ClassType.NewInstance" },
 
     /* ArrayType command set (4) */
     //4,    1,  NewInstance
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index 90e3750..461cc66 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -11,6 +11,41 @@
     .align  2
 
 #if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+    .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToBackwardBranch
+dvmJitToBackwardBranch:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+    mov    r0,rPC                       @ pass our target PC
+    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+#else
 /*
  * Return from the translation cache to the interpreter when the compiler is
  * having issues translating/executing a Dalvik instruction. We have to skip
@@ -127,6 +162,7 @@
     bl     dvmJitGetCodeAddr        @ Is there a translation?
     cmp    r0,#0
     bxne   r0                       @ continue native execution if so
+#endif
 
 /*
  * No translation, restore interpreter regs and start interpreting.
@@ -174,13 +210,65 @@
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
     cmp     r0,#0
     beq     common_selectTrace
+#if !defined(WITH_SELF_VERIFICATION)
     bxne    r0                          @ jump to the translation
+#else
+    bne     dvmJitSelfVerificationStart @ set up self verification
+#endif
 common_selectTrace:
     mov     r2,#kJitTSelectRequest      @ ask for trace selection
     str     r2,[rGLUE,#offGlue_jitState]
+    mov     r2,#kInterpEntryInstr       @ normal entry reason
+    str     r2,[rGLUE,#offGlue_entryPoint]
     mov     r1,#1                       @ set changeInterp
     b       common_gotoBail
 
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * Save PC and registers to shadow memory for self verification mode
+ * before jumping to native translation.
+ */
+dvmJitSelfVerificationStart:
+    sub     sp,sp,#4                    @ allocate stack space
+    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
+    mov     r0,rPC                      @ r0<- program counter
+    mov     r1,rFP                      @ r1<- frame pointer
+    mov     r2,rGLUE                    @ r2<- InterpState pointer
+    bl      dvmSelfVerificationSaveState @ save registers to shadow space
+    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
+    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
+    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
+    add     sp,sp,#4                    @ restore stack
+    bx      r0                          @ jump to the translation
+
+/*
+ * Restore PC, registers, and interpState to original values
+ * before jumping back to the interpreter.
+ */
+dvmJitSelfVerificationEnd:
+    mov    r1,rFP                        @ pass ending fp
+    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
+    ldr    rPC,[r0,#0]                   @ restore PC
+    ldr    rFP,[r0,#4]                   @ restore FP
+    ldr    rGLUE,[r0,#8]                 @ restore InterpState
+    ldr    r1,[r0,#12]                   @ get exitPoint
+    cmp    r1,#0                         @ check for punt condition
+    beq    1f
+    mov    r2,#kJitSelfVerification      @ ask for self verification
+    str    r2,[rGLUE,#offGlue_jitState]
+    mov    r2,#kInterpEntryInstr         @ normal entry reason
+    str    r2,[rGLUE,#offGlue_entryPoint]
+    mov    r1,#1                         @ set changeInterp
+    b      common_gotoBail
+
+1:                                       @ exit to interpreter without check
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#endif
+
 #endif
 
 /*
@@ -222,6 +310,9 @@
 common_periodicChecks:
     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
 
+    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
+    str     r0, [rGLUE, #offGlue_entryPoint]
+
 #if defined(WITH_DEBUGGER)
     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
 #endif
@@ -262,7 +353,6 @@
 
 3:  @ debugger/profiler enabled, bail out
     add     rPC, rPC, r9                @ update rPC
-    str     r0, [rGLUE, #offGlue_entryPoint]
     mov     r1, #1                      @ "want switch" = true
     b       common_gotoBail
 
@@ -467,7 +557,8 @@
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
-.LstackOverflow:
+.LstackOverflow:    @ r0=methodToCall
+    mov     r1, r0                      @ r1<- methodToCall
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
     bl      dvmHandleStackOverflow
     b       common_exceptionThrown
diff --git a/vm/mterp/c/gotoTargets.c b/vm/mterp/c/gotoTargets.c
index 5b93583..67b3299 100644
--- a/vm/mterp/c/gotoTargets.c
+++ b/vm/mterp/c/gotoTargets.c
@@ -576,6 +576,12 @@
          */
         PERIODIC_CHECKS(kInterpEntryThrow, 0);
 
+#if defined(WITH_JIT)
+        // Something threw during trace selection - abort the current trace
+        if (interpState->jitState == kJitTSelect) {
+            interpState->jitState = kJitTSelectEnd;
+        }
+#endif
         /*
          * We save off the exception and clear the exception status.  While
          * processing the exception we might need to load some Throwable
@@ -807,10 +813,11 @@
             bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
             if (bottom < self->interpStackEnd) {
                 /* stack overflow */
-                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n",
+                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
                     self->interpStackStart, self->interpStackEnd, bottom,
-                    self->interpStackSize, methodToCall->name);
-                dvmHandleStackOverflow(self);
+                    (u1*) fp - bottom, self->interpStackSize,
+                    methodToCall->name);
+                dvmHandleStackOverflow(self, methodToCall);
                 assert(dvmCheckException(self));
                 GOTO_exceptionThrown();
             }
diff --git a/vm/mterp/common/asm-constants.h b/vm/mterp/common/asm-constants.h
index a69247e..e157c37 100644
--- a/vm/mterp/common/asm-constants.h
+++ b/vm/mterp/common/asm-constants.h
@@ -246,6 +246,19 @@
 MTERP_CONSTANT(kJitTSelectEnd,      5)
 MTERP_CONSTANT(kJitSingleStep,      6)
 MTERP_CONSTANT(kJitSingleStepEnd,   7)
+MTERP_CONSTANT(kJitSelfVerification, 8)
+
+#if defined(WITH_SELF_VERIFICATION)
+MTERP_CONSTANT(kSVSIdle, 0)
+MTERP_CONSTANT(kSVSStart, 1)
+MTERP_CONSTANT(kSVSPunt, 2)
+MTERP_CONSTANT(kSVSSingleStep, 3)
+MTERP_CONSTANT(kSVSTraceSelect, 4)
+MTERP_CONSTANT(kSVSNormal, 5)
+MTERP_CONSTANT(kSVSNoChain, 6)
+MTERP_CONSTANT(kSVSBackwardBranch, 7)
+MTERP_CONSTANT(kSVSDebugInterp, 8)
+#endif
 #endif
 
 /* ClassStatus enumeration */
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index 2df532f..07075bb 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -9483,6 +9483,41 @@
     .align  2
 
 #if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+    .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToBackwardBranch
+dvmJitToBackwardBranch:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+    mov    r0,rPC                       @ pass our target PC
+    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+#else
 /*
  * Return from the translation cache to the interpreter when the compiler is
  * having issues translating/executing a Dalvik instruction. We have to skip
@@ -9599,6 +9634,7 @@
     bl     dvmJitGetCodeAddr        @ Is there a translation?
     cmp    r0,#0
     bxne   r0                       @ continue native execution if so
+#endif
 
 /*
  * No translation, restore interpreter regs and start interpreting.
@@ -9646,13 +9682,65 @@
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
     cmp     r0,#0
     beq     common_selectTrace
+#if !defined(WITH_SELF_VERIFICATION)
     bxne    r0                          @ jump to the translation
+#else
+    bne     dvmJitSelfVerificationStart @ set up self verification
+#endif
 common_selectTrace:
     mov     r2,#kJitTSelectRequest      @ ask for trace selection
     str     r2,[rGLUE,#offGlue_jitState]
+    mov     r2,#kInterpEntryInstr       @ normal entry reason
+    str     r2,[rGLUE,#offGlue_entryPoint]
     mov     r1,#1                       @ set changeInterp
     b       common_gotoBail
 
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * Save PC and registers to shadow memory for self verification mode
+ * before jumping to native translation.
+ */
+dvmJitSelfVerificationStart:
+    sub     sp,sp,#4                    @ allocate stack space
+    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
+    mov     r0,rPC                      @ r0<- program counter
+    mov     r1,rFP                      @ r1<- frame pointer
+    mov     r2,rGLUE                    @ r2<- InterpState pointer
+    bl      dvmSelfVerificationSaveState @ save registers to shadow space
+    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
+    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
+    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
+    add     sp,sp,#4                    @ restore stack
+    bx      r0                          @ jump to the translation
+
+/*
+ * Restore PC, registers, and interpState to original values
+ * before jumping back to the interpreter.
+ */
+dvmJitSelfVerificationEnd:
+    mov    r1,rFP                        @ pass ending fp
+    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
+    ldr    rPC,[r0,#0]                   @ restore PC
+    ldr    rFP,[r0,#4]                   @ restore FP
+    ldr    rGLUE,[r0,#8]                 @ restore InterpState
+    ldr    r1,[r0,#12]                   @ get exitPoint
+    cmp    r1,#0                         @ check for punt condition
+    beq    1f
+    mov    r2,#kJitSelfVerification      @ ask for self verification
+    str    r2,[rGLUE,#offGlue_jitState]
+    mov    r2,#kInterpEntryInstr         @ normal entry reason
+    str    r2,[rGLUE,#offGlue_entryPoint]
+    mov    r1,#1                         @ set changeInterp
+    b      common_gotoBail
+
+1:                                       @ exit to interpreter without check
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#endif
+
 #endif
 
 /*
@@ -9694,6 +9782,9 @@
 common_periodicChecks:
     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
 
+    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
+    str     r0, [rGLUE, #offGlue_entryPoint]
+
 #if defined(WITH_DEBUGGER)
     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
 #endif
@@ -9734,7 +9825,6 @@
 
 3:  @ debugger/profiler enabled, bail out
     add     rPC, rPC, r9                @ update rPC
-    str     r0, [rGLUE, #offGlue_entryPoint]
     mov     r1, #1                      @ "want switch" = true
     b       common_gotoBail
 
@@ -9939,7 +10029,8 @@
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
-.LstackOverflow:
+.LstackOverflow:    @ r0=methodToCall
+    mov     r1, r0                      @ r1<- methodToCall
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
     bl      dvmHandleStackOverflow
     b       common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index 61b2697..55ac716 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -9001,6 +9001,41 @@
     .align  2
 
 #if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+    .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToBackwardBranch
+dvmJitToBackwardBranch:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+    mov    r0,rPC                       @ pass our target PC
+    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+#else
 /*
  * Return from the translation cache to the interpreter when the compiler is
  * having issues translating/executing a Dalvik instruction. We have to skip
@@ -9117,6 +9152,7 @@
     bl     dvmJitGetCodeAddr        @ Is there a translation?
     cmp    r0,#0
     bxne   r0                       @ continue native execution if so
+#endif
 
 /*
  * No translation, restore interpreter regs and start interpreting.
@@ -9164,13 +9200,65 @@
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
     cmp     r0,#0
     beq     common_selectTrace
+#if !defined(WITH_SELF_VERIFICATION)
     bxne    r0                          @ jump to the translation
+#else
+    bne     dvmJitSelfVerificationStart @ set up self verification
+#endif
 common_selectTrace:
     mov     r2,#kJitTSelectRequest      @ ask for trace selection
     str     r2,[rGLUE,#offGlue_jitState]
+    mov     r2,#kInterpEntryInstr       @ normal entry reason
+    str     r2,[rGLUE,#offGlue_entryPoint]
     mov     r1,#1                       @ set changeInterp
     b       common_gotoBail
 
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * Save PC and registers to shadow memory for self verification mode
+ * before jumping to native translation.
+ */
+dvmJitSelfVerificationStart:
+    sub     sp,sp,#4                    @ allocate stack space
+    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
+    mov     r0,rPC                      @ r0<- program counter
+    mov     r1,rFP                      @ r1<- frame pointer
+    mov     r2,rGLUE                    @ r2<- InterpState pointer
+    bl      dvmSelfVerificationSaveState @ save registers to shadow space
+    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
+    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
+    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
+    add     sp,sp,#4                    @ restore stack
+    bx      r0                          @ jump to the translation
+
+/*
+ * Restore PC, registers, and interpState to original values
+ * before jumping back to the interpreter.
+ */
+dvmJitSelfVerificationEnd:
+    mov    r1,rFP                        @ pass ending fp
+    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
+    ldr    rPC,[r0,#0]                   @ restore PC
+    ldr    rFP,[r0,#4]                   @ restore FP
+    ldr    rGLUE,[r0,#8]                 @ restore InterpState
+    ldr    r1,[r0,#12]                   @ get exitPoint
+    cmp    r1,#0                         @ check for punt condition
+    beq    1f
+    mov    r2,#kJitSelfVerification      @ ask for self verification
+    str    r2,[rGLUE,#offGlue_jitState]
+    mov    r2,#kInterpEntryInstr         @ normal entry reason
+    str    r2,[rGLUE,#offGlue_entryPoint]
+    mov    r1,#1                         @ set changeInterp
+    b      common_gotoBail
+
+1:                                       @ exit to interpreter without check
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#endif
+
 #endif
 
 /*
@@ -9212,6 +9300,9 @@
 common_periodicChecks:
     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
 
+    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
+    str     r0, [rGLUE, #offGlue_entryPoint]
+
 #if defined(WITH_DEBUGGER)
     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
 #endif
@@ -9252,7 +9343,6 @@
 
 3:  @ debugger/profiler enabled, bail out
     add     rPC, rPC, r9                @ update rPC
-    str     r0, [rGLUE, #offGlue_entryPoint]
     mov     r1, #1                      @ "want switch" = true
     b       common_gotoBail
 
@@ -9457,7 +9547,8 @@
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
-.LstackOverflow:
+.LstackOverflow:    @ r0=methodToCall
+    mov     r1, r0                      @ r1<- methodToCall
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
     bl      dvmHandleStackOverflow
     b       common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index bafd442..55f6fee 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -9477,6 +9477,41 @@
     .align  2
 
 #if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+    .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToBackwardBranch
+dvmJitToBackwardBranch:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+    mov    r0,rPC                       @ pass our target PC
+    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+#else
 /*
  * Return from the translation cache to the interpreter when the compiler is
  * having issues translating/executing a Dalvik instruction. We have to skip
@@ -9593,6 +9628,7 @@
     bl     dvmJitGetCodeAddr        @ Is there a translation?
     cmp    r0,#0
     bxne   r0                       @ continue native execution if so
+#endif
 
 /*
  * No translation, restore interpreter regs and start interpreting.
@@ -9640,13 +9676,65 @@
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
     cmp     r0,#0
     beq     common_selectTrace
+#if !defined(WITH_SELF_VERIFICATION)
     bxne    r0                          @ jump to the translation
+#else
+    bne     dvmJitSelfVerificationStart @ set up self verification
+#endif
 common_selectTrace:
     mov     r2,#kJitTSelectRequest      @ ask for trace selection
     str     r2,[rGLUE,#offGlue_jitState]
+    mov     r2,#kInterpEntryInstr       @ normal entry reason
+    str     r2,[rGLUE,#offGlue_entryPoint]
     mov     r1,#1                       @ set changeInterp
     b       common_gotoBail
 
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * Save PC and registers to shadow memory for self verification mode
+ * before jumping to native translation.
+ */
+dvmJitSelfVerificationStart:
+    sub     sp,sp,#4                    @ allocate stack space
+    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
+    mov     r0,rPC                      @ r0<- program counter
+    mov     r1,rFP                      @ r1<- frame pointer
+    mov     r2,rGLUE                    @ r2<- InterpState pointer
+    bl      dvmSelfVerificationSaveState @ save registers to shadow space
+    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
+    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
+    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
+    add     sp,sp,#4                    @ restore stack
+    bx      r0                          @ jump to the translation
+
+/*
+ * Restore PC, registers, and interpState to original values
+ * before jumping back to the interpreter.
+ */
+dvmJitSelfVerificationEnd:
+    mov    r1,rFP                        @ pass ending fp
+    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
+    ldr    rPC,[r0,#0]                   @ restore PC
+    ldr    rFP,[r0,#4]                   @ restore FP
+    ldr    rGLUE,[r0,#8]                 @ restore InterpState
+    ldr    r1,[r0,#12]                   @ get exitPoint
+    cmp    r1,#0                         @ check for punt condition
+    beq    1f
+    mov    r2,#kJitSelfVerification      @ ask for self verification
+    str    r2,[rGLUE,#offGlue_jitState]
+    mov    r2,#kInterpEntryInstr         @ normal entry reason
+    str    r2,[rGLUE,#offGlue_entryPoint]
+    mov    r1,#1                         @ set changeInterp
+    b      common_gotoBail
+
+1:                                       @ exit to interpreter without check
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#endif
+
 #endif
 
 /*
@@ -9688,6 +9776,9 @@
 common_periodicChecks:
     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
 
+    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
+    str     r0, [rGLUE, #offGlue_entryPoint]
+
 #if defined(WITH_DEBUGGER)
     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
 #endif
@@ -9728,7 +9819,6 @@
 
 3:  @ debugger/profiler enabled, bail out
     add     rPC, rPC, r9                @ update rPC
-    str     r0, [rGLUE, #offGlue_entryPoint]
     mov     r1, #1                      @ "want switch" = true
     b       common_gotoBail
 
@@ -9933,7 +10023,8 @@
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
-.LstackOverflow:
+.LstackOverflow:    @ r0=methodToCall
+    mov     r1, r0                      @ r1<- methodToCall
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
     bl      dvmHandleStackOverflow
     b       common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index 8d018c1..3c896ae 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -8937,6 +8937,41 @@
     .align  2
 
 #if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+    .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToBackwardBranch
+dvmJitToBackwardBranch:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+    ldr    r0,[r14, #-1]                @ pass our target PC
+    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+
+    .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+    mov    r0,rPC                       @ pass our target PC
+    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
+    b      dvmJitSelfVerificationEnd    @ doesn't return
+#else
 /*
  * Return from the translation cache to the interpreter when the compiler is
  * having issues translating/executing a Dalvik instruction. We have to skip
@@ -9053,6 +9088,7 @@
     bl     dvmJitGetCodeAddr        @ Is there a translation?
     cmp    r0,#0
     bxne   r0                       @ continue native execution if so
+#endif
 
 /*
  * No translation, restore interpreter regs and start interpreting.
@@ -9100,13 +9136,65 @@
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
     cmp     r0,#0
     beq     common_selectTrace
+#if !defined(WITH_SELF_VERIFICATION)
     bxne    r0                          @ jump to the translation
+#else
+    bne     dvmJitSelfVerificationStart @ set up self verification
+#endif
 common_selectTrace:
     mov     r2,#kJitTSelectRequest      @ ask for trace selection
     str     r2,[rGLUE,#offGlue_jitState]
+    mov     r2,#kInterpEntryInstr       @ normal entry reason
+    str     r2,[rGLUE,#offGlue_entryPoint]
     mov     r1,#1                       @ set changeInterp
     b       common_gotoBail
 
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * Save PC and registers to shadow memory for self verification mode
+ * before jumping to native translation.
+ */
+dvmJitSelfVerificationStart:
+    sub     sp,sp,#4                    @ allocate stack space
+    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
+    mov     r0,rPC                      @ r0<- program counter
+    mov     r1,rFP                      @ r1<- frame pointer
+    mov     r2,rGLUE                    @ r2<- InterpState pointer
+    bl      dvmSelfVerificationSaveState @ save registers to shadow space
+    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
+    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
+    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
+    add     sp,sp,#4                    @ restore stack
+    bx      r0                          @ jump to the translation
+
+/*
+ * Restore PC, registers, and interpState to original values
+ * before jumping back to the interpreter.
+ */
+dvmJitSelfVerificationEnd:
+    mov    r1,rFP                        @ pass ending fp
+    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
+    ldr    rPC,[r0,#0]                   @ restore PC
+    ldr    rFP,[r0,#4]                   @ restore FP
+    ldr    rGLUE,[r0,#8]                 @ restore InterpState
+    ldr    r1,[r0,#12]                   @ get exitPoint
+    cmp    r1,#0                         @ check for punt condition
+    beq    1f
+    mov    r2,#kJitSelfVerification      @ ask for self verification
+    str    r2,[rGLUE,#offGlue_jitState]
+    mov    r2,#kInterpEntryInstr         @ normal entry reason
+    str    r2,[rGLUE,#offGlue_entryPoint]
+    mov    r1,#1                         @ set changeInterp
+    b      common_gotoBail
+
+1:                                       @ exit to interpreter without check
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#endif
+
 #endif
 
 /*
@@ -9148,6 +9236,9 @@
 common_periodicChecks:
     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
 
+    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
+    str     r0, [rGLUE, #offGlue_entryPoint]
+
 #if defined(WITH_DEBUGGER)
     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
 #endif
@@ -9188,7 +9279,6 @@
 
 3:  @ debugger/profiler enabled, bail out
     add     rPC, rPC, r9                @ update rPC
-    str     r0, [rGLUE, #offGlue_entryPoint]
     mov     r1, #1                      @ "want switch" = true
     b       common_gotoBail
 
@@ -9393,7 +9483,8 @@
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
-.LstackOverflow:
+.LstackOverflow:    @ r0=methodToCall
+    mov     r1, r0                      @ r1<- methodToCall
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
     bl      dvmHandleStackOverflow
     b       common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S
index 79c98f6..c25071e 100644
--- a/vm/mterp/out/InterpAsm-x86.S
+++ b/vm/mterp/out/InterpAsm-x86.S
@@ -8727,11 +8727,12 @@
     ADVANCE_PC(3)
     GOTO_NEXT                           # jump to next instruction
 
-.LstackOverflow:
+.LstackOverflow:    # eax=methodToCall
+    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
     GET_GLUE(%eax)                      # %eax<- pMterpGlue
     movl        offGlue_self(%eax), %eax # %eax<- glue->self
     movl        %eax, OUT_ARG0(%esp)    # push parameter self
-    call        dvmHandleStackOverflow  # call: (Thread* self)
+    call        dvmHandleStackOverflow  # call: (Thread* self, Method* meth)
     UNSPILL(rPC)                        # return: void
     jmp         common_exceptionThrown  # handle exception
 
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 4e832d8..1d31227 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -3609,6 +3609,12 @@
          */
         PERIODIC_CHECKS(kInterpEntryThrow, 0);
 
+#if defined(WITH_JIT)
+        // Something threw during trace selection - abort the current trace
+        if (interpState->jitState == kJitTSelect) {
+            interpState->jitState = kJitTSelectEnd;
+        }
+#endif
         /*
          * We save off the exception and clear the exception status.  While
          * processing the exception we might need to load some Throwable
@@ -3840,10 +3846,11 @@
             bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
             if (bottom < self->interpStackEnd) {
                 /* stack overflow */
-                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n",
+                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
                     self->interpStackStart, self->interpStackEnd, bottom,
-                    self->interpStackSize, methodToCall->name);
-                dvmHandleStackOverflow(self);
+                    (u1*) fp - bottom, self->interpStackSize,
+                    methodToCall->name);
+                dvmHandleStackOverflow(self, methodToCall);
                 assert(dvmCheckException(self));
                 GOTO_exceptionThrown();
             }
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index 4b92639..03fe00e 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -421,11 +421,9 @@
     checkDebugAndProf(pc, fp, self, curMethod, &debugIsMethodEntry)
 
 #if defined(WITH_JIT)
-#define CHECK_JIT() \
-    if (dvmCheckJit(pc, self, interpState)) GOTO_bail_switch()
+#define CHECK_JIT() (dvmCheckJit(pc, self, interpState))
 #else
-#define CHECK_JIT() \
-    ((void)0)
+#define CHECK_JIT() (0)
 #endif
 
 /* File: portable/stubdefs.c */
@@ -459,7 +457,7 @@
         inst = FETCH(0);                                                    \
         CHECK_DEBUG_AND_PROF();                                             \
         CHECK_TRACKED_REFS();                                               \
-        CHECK_JIT();                                                        \
+        if (CHECK_JIT()) GOTO_bail_switch();                                \
         goto *handlerTable[INST_INST(inst)];                                \
     }
 #else
@@ -520,7 +518,6 @@
         }                                                                   \
     }
 
-
 /* File: c/opcommon.c */
 /* forward declarations of goto targets */
 GOTO_TARGET_DECL(filledNewArray, bool methodCallRange);
@@ -1498,13 +1495,22 @@
     /* Check to see if we've got a trace selection request.  If we do,
      * but something is amiss, revert to the fast interpreter.
      */
+#if !defined(WITH_SELF_VERIFICATION)
     if (dvmJitCheckTraceRequest(self,interpState)) {
         interpState->nextMode = INTERP_STD;
         //LOGD("** something wrong, exiting\n");
         return true;
     }
-#endif
-#endif
+#else
+    if (interpState->jitState != kJitSelfVerification &&
+        dvmJitCheckTraceRequest(self,interpState)) {
+        interpState->nextMode = INTERP_STD;
+        //LOGD("** something wrong, exiting\n");
+        return true;
+    }
+#endif /* WITH_SELF_VERIFICATION */
+#endif /* INTERP_TYPE == INTERP_DBG */
+#endif /* WITH_JIT */
 
     /* copy state in */
     curMethod = interpState->method;
@@ -1537,6 +1543,7 @@
         /* just fall through to instruction loop or threaded kickstart */
         break;
     case kInterpEntryReturn:
+        CHECK_JIT();
         goto returnFromMethod;
     case kInterpEntryThrow:
         goto exceptionThrown;
@@ -3900,6 +3907,12 @@
          */
         PERIODIC_CHECKS(kInterpEntryThrow, 0);
 
+#if defined(WITH_JIT)
+        // Something threw during trace selection - abort the current trace
+        if (interpState->jitState == kJitTSelect) {
+            interpState->jitState = kJitTSelectEnd;
+        }
+#endif
         /*
          * We save off the exception and clear the exception status.  While
          * processing the exception we might need to load some Throwable
@@ -4131,10 +4144,11 @@
             bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
             if (bottom < self->interpStackEnd) {
                 /* stack overflow */
-                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n",
+                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
                     self->interpStackStart, self->interpStackEnd, bottom,
-                    self->interpStackSize, methodToCall->name);
-                dvmHandleStackOverflow(self);
+                    (u1*) fp - bottom, self->interpStackSize,
+                    methodToCall->name);
+                dvmHandleStackOverflow(self, methodToCall);
                 assert(dvmCheckException(self));
                 GOTO_exceptionThrown();
             }
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index 1db6e87..a092da0 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -419,7 +419,7 @@
 
 #define CHECK_DEBUG_AND_PROF() ((void)0)
 
-#define CHECK_JIT() ((void)0)
+#define CHECK_JIT() (0)
 
 /* File: portable/stubdefs.c */
 /*
@@ -452,7 +452,7 @@
         inst = FETCH(0);                                                    \
         CHECK_DEBUG_AND_PROF();                                             \
         CHECK_TRACKED_REFS();                                               \
-        CHECK_JIT();                                                        \
+        if (CHECK_JIT()) GOTO_bail_switch();                                \
         goto *handlerTable[INST_INST(inst)];                                \
     }
 #else
@@ -513,7 +513,6 @@
         }                                                                   \
     }
 
-
 /* File: c/opcommon.c */
 /* forward declarations of goto targets */
 GOTO_TARGET_DECL(filledNewArray, bool methodCallRange);
@@ -1212,13 +1211,22 @@
     /* Check to see if we've got a trace selection request.  If we do,
      * but something is amiss, revert to the fast interpreter.
      */
+#if !defined(WITH_SELF_VERIFICATION)
     if (dvmJitCheckTraceRequest(self,interpState)) {
         interpState->nextMode = INTERP_STD;
         //LOGD("** something wrong, exiting\n");
         return true;
     }
-#endif
-#endif
+#else
+    if (interpState->jitState != kJitSelfVerification &&
+        dvmJitCheckTraceRequest(self,interpState)) {
+        interpState->nextMode = INTERP_STD;
+        //LOGD("** something wrong, exiting\n");
+        return true;
+    }
+#endif /* WITH_SELF_VERIFICATION */
+#endif /* INTERP_TYPE == INTERP_DBG */
+#endif /* WITH_JIT */
 
     /* copy state in */
     curMethod = interpState->method;
@@ -1251,6 +1259,7 @@
         /* just fall through to instruction loop or threaded kickstart */
         break;
     case kInterpEntryReturn:
+        CHECK_JIT();
         goto returnFromMethod;
     case kInterpEntryThrow:
         goto exceptionThrown;
@@ -3614,6 +3623,12 @@
          */
         PERIODIC_CHECKS(kInterpEntryThrow, 0);
 
+#if defined(WITH_JIT)
+        // Something threw during trace selection - abort the current trace
+        if (interpState->jitState == kJitTSelect) {
+            interpState->jitState = kJitTSelectEnd;
+        }
+#endif
         /*
          * We save off the exception and clear the exception status.  While
          * processing the exception we might need to load some Throwable
@@ -3845,10 +3860,11 @@
             bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
             if (bottom < self->interpStackEnd) {
                 /* stack overflow */
-                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n",
+                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
                     self->interpStackStart, self->interpStackEnd, bottom,
-                    self->interpStackSize, methodToCall->name);
-                dvmHandleStackOverflow(self);
+                    (u1*) fp - bottom, self->interpStackSize,
+                    methodToCall->name);
+                dvmHandleStackOverflow(self, methodToCall);
                 assert(dvmCheckException(self));
                 GOTO_exceptionThrown();
             }
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c
index 07536c4..fa2dfa8 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.c
@@ -1764,6 +1764,12 @@
          */
         PERIODIC_CHECKS(kInterpEntryThrow, 0);
 
+#if defined(WITH_JIT)
+        // Something threw during trace selection - abort the current trace
+        if (interpState->jitState == kJitTSelect) {
+            interpState->jitState = kJitTSelectEnd;
+        }
+#endif
         /*
          * We save off the exception and clear the exception status.  While
          * processing the exception we might need to load some Throwable
@@ -1995,10 +2001,11 @@
             bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
             if (bottom < self->interpStackEnd) {
                 /* stack overflow */
-                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n",
+                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
                     self->interpStackStart, self->interpStackEnd, bottom,
-                    self->interpStackSize, methodToCall->name);
-                dvmHandleStackOverflow(self);
+                    (u1*) fp - bottom, self->interpStackSize,
+                    methodToCall->name);
+                dvmHandleStackOverflow(self, methodToCall);
                 assert(dvmCheckException(self));
                 GOTO_exceptionThrown();
             }
diff --git a/vm/mterp/portable/entry.c b/vm/mterp/portable/entry.c
index 9c7c2d6..4a6ed4e 100644
--- a/vm/mterp/portable/entry.c
+++ b/vm/mterp/portable/entry.c
@@ -47,13 +47,22 @@
     /* Check to see if we've got a trace selection request.  If we do,
      * but something is amiss, revert to the fast interpreter.
      */
+#if !defined(WITH_SELF_VERIFICATION)
     if (dvmJitCheckTraceRequest(self,interpState)) {
         interpState->nextMode = INTERP_STD;
         //LOGD("** something wrong, exiting\n");
         return true;
     }
-#endif
-#endif
+#else
+    if (interpState->jitState != kJitSelfVerification &&
+        dvmJitCheckTraceRequest(self,interpState)) {
+        interpState->nextMode = INTERP_STD;
+        //LOGD("** something wrong, exiting\n");
+        return true;
+    }
+#endif /* WITH_SELF_VERIFICATION */
+#endif /* INTERP_TYPE == INTERP_DBG */
+#endif /* WITH_JIT */
 
     /* copy state in */
     curMethod = interpState->method;
@@ -86,6 +95,7 @@
         /* just fall through to instruction loop or threaded kickstart */
         break;
     case kInterpEntryReturn:
+        CHECK_JIT();
         goto returnFromMethod;
     case kInterpEntryThrow:
         goto exceptionThrown;
diff --git a/vm/mterp/portable/portdbg.c b/vm/mterp/portable/portdbg.c
index 04132cb..014d866 100644
--- a/vm/mterp/portable/portdbg.c
+++ b/vm/mterp/portable/portdbg.c
@@ -5,9 +5,7 @@
     checkDebugAndProf(pc, fp, self, curMethod, &debugIsMethodEntry)
 
 #if defined(WITH_JIT)
-#define CHECK_JIT() \
-    if (dvmCheckJit(pc, self, interpState)) GOTO_bail_switch()
+#define CHECK_JIT() (dvmCheckJit(pc, self, interpState))
 #else
-#define CHECK_JIT() \
-    ((void)0)
+#define CHECK_JIT() (0)
 #endif
diff --git a/vm/mterp/portable/portstd.c b/vm/mterp/portable/portstd.c
index f55e8e7..f13bca7 100644
--- a/vm/mterp/portable/portstd.c
+++ b/vm/mterp/portable/portstd.c
@@ -3,4 +3,4 @@
 
 #define CHECK_DEBUG_AND_PROF() ((void)0)
 
-#define CHECK_JIT() ((void)0)
+#define CHECK_JIT() (0)
diff --git a/vm/mterp/portable/stubdefs.c b/vm/mterp/portable/stubdefs.c
index 305aebb..717e746 100644
--- a/vm/mterp/portable/stubdefs.c
+++ b/vm/mterp/portable/stubdefs.c
@@ -28,7 +28,7 @@
         inst = FETCH(0);                                                    \
         CHECK_DEBUG_AND_PROF();                                             \
         CHECK_TRACKED_REFS();                                               \
-        CHECK_JIT();                                                        \
+        if (CHECK_JIT()) GOTO_bail_switch();                                \
         goto *handlerTable[INST_INST(inst)];                                \
     }
 #else
@@ -88,4 +88,3 @@
             GOTO_bail_switch();                                             \
         }                                                                   \
     }
-
diff --git a/vm/mterp/x86/footer.S b/vm/mterp/x86/footer.S
index c39fa16..8ed6c66 100644
--- a/vm/mterp/x86/footer.S
+++ b/vm/mterp/x86/footer.S
@@ -227,11 +227,12 @@
     ADVANCE_PC(3)
     GOTO_NEXT                           # jump to next instruction
 
-.LstackOverflow:
+.LstackOverflow:    # eax=methodToCall
+    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
     GET_GLUE(%eax)                      # %eax<- pMterpGlue
     movl        offGlue_self(%eax), %eax # %eax<- glue->self
     movl        %eax, OUT_ARG0(%esp)    # push parameter self
-    call        dvmHandleStackOverflow  # call: (Thread* self)
+    call        dvmHandleStackOverflow  # call: (Thread* self, Method* meth)
     UNSPILL(rPC)                        # return: void
     jmp         common_exceptionThrown  # handle exception
 
diff --git a/vm/native/java_lang_Runtime.c b/vm/native/java_lang_Runtime.c
index 1278f03..b5c0aee 100644
--- a/vm/native/java_lang_Runtime.c
+++ b/vm/native/java_lang_Runtime.c
@@ -53,6 +53,9 @@
         LOGW("JNI exit hook returned\n");
     }
     LOGD("Calling exit(%d)\n", status);
+#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
+    dvmCompilerDumpStats();
+#endif
     exit(status);
 }
 
@@ -161,4 +164,3 @@
         Dalvik_java_lang_Runtime_totalMemory },
     { NULL, NULL, NULL },
 };
-
diff --git a/vm/native/java_lang_Throwable.c b/vm/native/java_lang_Throwable.c
index 3cd0e2e..cb94f0f 100644
--- a/vm/native/java_lang_Throwable.c
+++ b/vm/native/java_lang_Throwable.c
@@ -47,6 +47,11 @@
     Object* stackState = (Object*) args[0];
     ArrayObject* elements = NULL;
 
+    if (stackState == NULL) {
+        LOGW("getStackTrace() called but no trace available\n");
+        RETURN_PTR(NULL);   /* could throw NPE; currently caller will do so */
+    }
+
     elements = dvmGetStackTrace(stackState);
     RETURN_PTR(elements);
 }
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index 115a122..cc461e7 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -1395,7 +1395,7 @@
      * making it an informative abort rather than an assert).
      */
     if (dvmCheckException(self)) {
-        LOGE("Class lookup %s attemped while exception %s pending\n",
+        LOGE("Class lookup %s attempted while exception %s pending\n",
             descriptor, dvmGetException(self)->clazz->descriptor);
         dvmDumpAllThreads(false);
         dvmAbort();
@@ -2418,7 +2418,7 @@
            * f->byteOffset is the offset from the beginning of
            * obj, not the offset into obj->instanceData.
            */
-          assert(f->byteOffset >= CLASS_SMALLEST_OFFSET);
+          assert(f->byteOffset >= (int) CLASS_SMALLEST_OFFSET);
           assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
           if (CLASS_CAN_ENCODE_OFFSET(f->byteOffset)) {
               u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
diff --git a/vm/test/TestIndirectRefTable.c b/vm/test/TestIndirectRefTable.c
index 64d843c..25f1dd1 100644
--- a/vm/test/TestIndirectRefTable.c
+++ b/vm/test/TestIndirectRefTable.c
@@ -245,12 +245,15 @@
     dvmRemoveFromIndirectRefTable(&irt, cookie, iref0);
     iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
     if (iref0 != iref1) {
+        /* try 0, should not work */
         if (dvmRemoveFromIndirectRefTable(&irt, cookie, iref0)) {
             LOGE("temporal del succeeded (%p vs %p)\n", iref0, iref1);
             goto bail;
         }
-    } else {
-        dvmRemoveFromIndirectRefTable(&irt, cookie, iref1);
+    }
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref1)) {
+        LOGE("temporal cleanup failed\n");
+        goto bail;
     }
     if (dvmIndirectRefTableEntries(&irt) != 0) {
         LOGE("temporal del not empty\n");