am 216438fc: (-s ours) am 83859891: am 3dc6a811: (-s ours) DO NOT MERGE. CTS test cleanup. Mark tests as KnownFailures and BrokenTests.

Merge commit '216438fc405d78069b1042cc21fc43dc85f860a9'

* commit '216438fc405d78069b1042cc21fc43dc85f860a9':
  DO NOT MERGE. CTS test cleanup. Mark tests as KnownFailures and BrokenTests.
diff --git a/Android.mk b/Android.mk
index 7de73be..31db2f4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,163 +1,29 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# The core library is divided into modules. Each module has a separate Java
-# source directory, and some (hopefully eventually all) also have a directory
-# for tests. The two sections below define separate targets to build the
-# core and the associated tests.
-
-define all-core-java-files
-$(patsubst ./%,%,$(shell cd $(LOCAL_PATH) && find */src/$(1)/java -name "*.java"))
-endef
-
-# Redirect ls stderr to /dev/null because the corresponding resources
-# directory doesn't always exist.
-define all-core-resource-dirs
-$(shell cd $(LOCAL_PATH) && ls -d */src/$(1)/{java,resources} 2> /dev/null)
-endef
-
-LOCAL_SRC_FILES := $(call all-core-java-files,main)
-LOCAL_JAVA_RESOURCE_DIRS := $(call all-core-resource-dirs,main)
-
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_DX_FLAGS := --core-library
-
-LOCAL_NO_EMMA_INSTRUMENT := true
-LOCAL_NO_EMMA_COMPILE := true
-
-LOCAL_MODULE := core
-
-include $(BUILD_JAVA_LIBRARY)
-
-core-intermediates := ${intermediates}
-
-# Definitions to make the core-tests library.
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-core-java-files,test)
-LOCAL_JAVA_RESOURCE_DIRS := $(call all-core-resource-dirs,test)
-
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core
-LOCAL_DX_FLAGS := --core-library
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := core-tests
-
-include $(BUILD_JAVA_LIBRARY)
-
-# This one's tricky. One of our tests needs to have a
-# resource with a "#" in its name, but Perforce doesn't
-# allow us to submit such a file. So we create it here
-# on-the-fly.
-TMP_RESOURCE_DIR := $(OUT_DIR)/tmp/
-TMP_RESOURCE_FILE := org/apache/harmony/luni/tests/java/lang/test\#.properties
-
-$(TMP_RESOURCE_DIR)$(TMP_RESOURCE_FILE):
-	@mkdir -p $(dir $@)
-	@echo "Hello, world!" > $@
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_EXTRA_JAR_ARGS := $(extra_jar_args) -C $(TMP_RESOURCE_DIR) $(TMP_RESOURCE_FILE)
-$(LOCAL_INTERMEDIATE_TARGETS): $(TMP_RESOURCE_DIR)$(TMP_RESOURCE_FILE)
-
-# Definitions for building a version of the core-tests.jar
-# that is suitable for execution on the RI. This JAR would
-# be better located in $HOST_OUT_JAVA_LIBRARIES, but it is
-# not possible to refer to that from a shell script (the
-# variable is not exported from envsetup.sh). There is also
-# some trickery involved: we need to include some classes
-# that reside in core.jar, but since we cannot incldue the
-# whole core.jar in the RI classpath, we copy those classses
-# over to our new file.
-HOST_CORE_JAR := $(HOST_COMMON_OUT_ROOT)/core-tests.jar
-
-$(HOST_CORE_JAR): PRIVATE_LOCAL_BUILT_MODULE := $(LOCAL_BUILT_MODULE)
-$(HOST_CORE_JAR): PRIVATE_CORE_INTERMEDIATES := $(core-intermediates)
-$(HOST_CORE_JAR): $(LOCAL_BUILT_MODULE)
-	@rm -rf $(dir $<)/hostctsclasses
-	$(call unzip-jar-files,$(dir $<)classes.jar,$(dir $<)hostctsclasses)
-	@unzip -qx -o $(PRIVATE_CORE_INTERMEDIATES)/classes.jar dalvik/annotation/* -d $(dir $<)hostctsclasses
-	@cp $< $@
-	@jar uf $@ -C $(dir $<)hostctsclasses .
-
-$(LOCAL_INSTALLED_MODULE): $(HOST_CORE_JAR)
-
-$(LOCAL_INSTALLED_MODULE): run-core-tests
-
-# Definitions to copy the core-tests runner script.
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := run-core-tests
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := run-core-tests
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := run-core-tests-on-ri
-LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := run-core-tests-on-ri
-include $(BUILD_PREBUILT)
-
-# Build all of the native code, if any is present.
-
-include $(CLEAR_VARS)
-
-# Get the list of all native directories that contain sub.mk files.
-# We're using "sub.mk" to make it clear that these are not typical
-# android makefiles.
-define all-core-native-dirs
-$(patsubst %/sub.mk,%,$(shell cd $(LOCAL_PATH) && ls -d */src/$(1)/native/sub.mk 2> /dev/null))
-endef
-
-core_magic_local_target := ...//::default:://...
-core_local_path := $(LOCAL_PATH)
-
-# Include a submakefile, resolve its source file locations,
-# and stick them on core_src_files.  The submakefiles are
-# free to append to LOCAL_C_INCLUDES, LOCAL_SHARED_LIBRARIES, etc.
+# Copyright (C) 2009 The Android Open Source Project
 #
-# $(1): directory containing the makefile to include
-define include-core-native-dir
-    LOCAL_SRC_FILES :=
-    include $(LOCAL_PATH)/$(1)/sub.mk
-    ifneq ($$(LOCAL_MODULE),$(core_magic_local_target))
-        $$(error $(LOCAL_PATH)/$(1)/sub.mk should not include CLEAR_VARS \
-            or define LOCAL_MODULE)
-    endif
-    ifneq ($$(LOCAL_PATH),$(core_local_path))
-        $$(error $(LOCAL_PATH)/$(1)/sub.mk should not define LOCAL_PATH)
-    endif
-    core_src_files += $$(addprefix $(1)/,$$(LOCAL_SRC_FILES))
-    LOCAL_SRC_FILES :=
-endef
+# 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.
 
-# Find any native directories containing sub.mk files.
-core_native_dirs := $(strip $(call all-core-native-dirs,main))
-ifeq ($(core_native_dirs),)
-    $(error No native code defined for libcore)
-endif
+LOCAL_PATH := $(call my-dir)
 
-# Set up the default state.
-LOCAL_C_INCLUDES += $(JNI_H_INCLUDE)
-LOCAL_MODULE := $(core_magic_local_target)
-core_src_files :=
 
-# Include the sub.mk files.
-$(foreach dir, \
-    $(core_native_dirs), \
-    $(eval $(call include-core-native-dir,$(dir))))
+#
+# Include the definitions to build the Java code.
+#
 
-# Define the rules.
-LOCAL_SRC_FILES := $(core_src_files)
-LOCAL_MODULE := libjavacore
-include $(BUILD_STATIC_LIBRARY)
+include $(LOCAL_PATH)/JavaLibrary.mk
 
-# Deal with keystores required for security. Note: The path to this file
-# is hardcoded in TrustManagerFactoryImpl.java.
-ALL_PREBUILT += $(TARGET_OUT)/etc/security/cacerts.bks
-$(TARGET_OUT)/etc/security/cacerts.bks : $(LOCAL_PATH)/security/src/main/files/cacerts.bks | $(ACP)
-	$(transform-prebuilt-to-target)
+
+#
+# Include the definitions to build the native code.
+#
+
+include $(LOCAL_PATH)/NativeCode.mk
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
new file mode 100644
index 0000000..d1015f5
--- /dev/null
+++ b/JavaLibrary.mk
@@ -0,0 +1,184 @@
+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+
+#
+# Definitions for building the Java library and associated tests.
+#
+
+#
+# Common definitions for host and target.
+#
+
+# The core library is divided into modules. Each module has a separate
+# Java source directory, and some (hopefully eventually all) also have
+# a directory for tests.
+
+define all-core-java-files
+$(patsubst ./%,%,$(shell cd $(LOCAL_PATH) && find */src/$(1)/java -name "*.java"))
+endef
+
+# Redirect ls stderr to /dev/null because the corresponding resources
+# directories don't always exist.
+define all-core-resource-dirs
+$(shell cd $(LOCAL_PATH) && ls -d */src/$(1)/{java,resources} 2> /dev/null)
+endef
+
+# The core Java files and associated resources.
+core_src_files := $(call all-core-java-files,main)
+core_resource_dirs := $(call all-core-resource-dirs,main)
+
+# The test Java files and associated resources.
+test_src_files := $(call all-core-java-files,test)
+test_resource_dirs := $(call all-core-resource-dirs,test)
+
+
+#
+# Build for the target (device).
+#
+
+# Definitions to make the core library.
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(core_src_files)
+LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
+
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_DX_FLAGS := --core-library
+
+LOCAL_NO_EMMA_INSTRUMENT := true
+LOCAL_NO_EMMA_COMPILE := true
+
+LOCAL_MODULE := core
+
+include $(BUILD_JAVA_LIBRARY)
+
+core-intermediates := ${intermediates}
+
+
+# Definitions to make the core-tests library.
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(test_src_files)
+LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
+
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core
+LOCAL_DX_FLAGS := --core-library
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := core-tests
+
+include $(BUILD_JAVA_LIBRARY)
+
+
+
+# This one's tricky. One of our tests needs to have a
+# resource with a "#" in its name, but Perforce doesn't
+# allow us to submit such a file. So we create it here
+# on-the-fly.
+TMP_RESOURCE_DIR := $(OUT_DIR)/tmp/
+TMP_RESOURCE_FILE := org/apache/harmony/luni/tests/java/lang/test\#.properties
+
+$(TMP_RESOURCE_DIR)$(TMP_RESOURCE_FILE):
+	@mkdir -p $(dir $@)
+	@echo "Hello, world!" > $@
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_EXTRA_JAR_ARGS := $(extra_jar_args) -C $(TMP_RESOURCE_DIR) $(TMP_RESOURCE_FILE)
+$(LOCAL_INTERMEDIATE_TARGETS): $(TMP_RESOURCE_DIR)$(TMP_RESOURCE_FILE)
+
+# Definitions for building a version of the core-tests.jar
+# that is suitable for execution on the RI. This JAR would
+# be better located in $HOST_OUT_JAVA_LIBRARIES, but it is
+# not possible to refer to that from a shell script (the
+# variable is not exported from envsetup.sh). There is also
+# some trickery involved: we need to include some classes
+# that reside in core.jar, but since we cannot incldue the
+# whole core.jar in the RI classpath, we copy those classses
+# over to our new file.
+HOST_CORE_JAR := $(HOST_COMMON_OUT_ROOT)/core-tests.jar
+
+$(HOST_CORE_JAR): PRIVATE_LOCAL_BUILT_MODULE := $(LOCAL_BUILT_MODULE)
+$(HOST_CORE_JAR): PRIVATE_CORE_INTERMEDIATES := $(core-intermediates)
+$(HOST_CORE_JAR): $(LOCAL_BUILT_MODULE)
+	@rm -rf $(dir $<)/hostctsclasses
+	$(call unzip-jar-files,$(dir $<)classes.jar,$(dir $<)hostctsclasses)
+	@unzip -qx -o $(PRIVATE_CORE_INTERMEDIATES)/classes.jar dalvik/annotation/* -d $(dir $<)hostctsclasses
+	@cp $< $@
+	@jar uf $@ -C $(dir $<)hostctsclasses .
+
+$(LOCAL_INSTALLED_MODULE): $(HOST_CORE_JAR)
+
+$(LOCAL_INSTALLED_MODULE): run-core-tests
+
+# Definitions to copy the core-tests runner script.
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := run-core-tests
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := run-core-tests
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := run-core-tests-on-ri
+LOCAL_IS_HOST_MODULE := true
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := run-core-tests-on-ri
+include $(BUILD_PREBUILT)
+
+
+#
+# Build for the host.
+#
+
+ifeq ($(WITH_HOST_DALVIK),true)
+
+    # Definitions to make the core library.
+
+    include $(CLEAR_VARS)
+
+    LOCAL_SRC_FILES := $(core_src_files)
+    LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
+
+    LOCAL_NO_STANDARD_LIBRARIES := true
+    LOCAL_DX_FLAGS := --core-library
+
+    LOCAL_NO_EMMA_INSTRUMENT := true
+    LOCAL_NO_EMMA_COMPILE := true
+
+    LOCAL_MODULE := core
+
+    include $(BUILD_HOST_JAVA_LIBRARY)
+
+
+    # Definitions to make the core-tests library.
+
+    include $(CLEAR_VARS)
+
+    LOCAL_SRC_FILES := $(test_src_files)
+    LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
+
+    LOCAL_NO_STANDARD_LIBRARIES := true
+    LOCAL_JAVA_LIBRARIES := core
+    LOCAL_DX_FLAGS := --core-library
+
+    LOCAL_MODULE_TAGS := tests
+    LOCAL_MODULE := core-tests
+
+    include $(BUILD_HOST_JAVA_LIBRARY)
+
+endif
\ No newline at end of file
diff --git a/NativeCode.mk b/NativeCode.mk
new file mode 100644
index 0000000..0dfad3b
--- /dev/null
+++ b/NativeCode.mk
@@ -0,0 +1,121 @@
+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+
+#
+# Definitions for building the native code needed for the core library.
+#
+
+#
+# Common definitions for host and target.
+#
+
+# Get the list of all native directories that contain sub.mk files.
+# We're using "sub.mk" to make it clear that these are not typical
+# android makefiles.
+define all-core-native-dirs
+$(patsubst %/sub.mk,%,$(shell cd $(LOCAL_PATH) && ls -d */src/$(1)/native/sub.mk 2> /dev/null))
+endef
+
+# These two definitions are used to help sanity check what's put in
+# sub.mk. See, the "error" directives immediately below.
+core_magic_local_target := ...//::default:://...
+core_local_path := $(LOCAL_PATH)
+
+# Include a submakefile, resolve its source file locations,
+# and stick them on core_src_files.  The submakefiles are
+# free to append to LOCAL_SRC_FILES, LOCAL_C_INCLUDES,
+# LOCAL_SHARED_LIBRARIES, or LOCAL_STATIC_LIBRARIES, but nothing
+# else. All other LOCAL_* variables will be ignored.
+#
+# $(1): directory containing the makefile to include
+define include-core-native-dir
+    LOCAL_SRC_FILES :=
+    include $(LOCAL_PATH)/$(1)/sub.mk
+    ifneq ($$(LOCAL_MODULE),$(core_magic_local_target))
+        $$(error $(LOCAL_PATH)/$(1)/sub.mk should not include CLEAR_VARS \
+            or define LOCAL_MODULE)
+    endif
+    ifneq ($$(LOCAL_PATH),$(core_local_path))
+        $$(error $(LOCAL_PATH)/$(1)/sub.mk should not define LOCAL_PATH)
+    endif
+    core_src_files += $$(addprefix $(1)/,$$(LOCAL_SRC_FILES))
+    LOCAL_SRC_FILES :=
+endef
+
+# Find any native directories containing sub.mk files.
+core_native_dirs := $(strip $(call all-core-native-dirs,main))
+ifeq ($(core_native_dirs),)
+    $(error No native code defined for libcore)
+endif
+
+# Set up the default state. Note: We use CLEAR_VARS here, even though
+# we aren't quite defining a new rule yet, to make sure that the
+# sub.mk files don't see anything stray from the last rule that was
+# set up.
+include $(CLEAR_VARS)
+LOCAL_MODULE := $(core_magic_local_target)
+core_src_files :=
+
+# Include the sub.mk files.
+$(foreach dir, \
+    $(core_native_dirs), \
+    $(eval $(call include-core-native-dir,$(dir))))
+
+# Extract out the allowed LOCAL_* variables. Note: $(sort) also
+# removes duplicates.
+core_c_includes := $(sort $(LOCAL_C_INCLUDES) $(JNI_H_INCLUDE))
+core_shared_libraries := $(sort $(LOCAL_SHARED_LIBRARIES))
+core_static_libraries := $(sort $(LOCAL_STATIC_LIBRARIES))
+
+
+#
+# Build for the target (device).
+#
+
+include $(CLEAR_VARS)
+
+# Define the rules.
+LOCAL_SRC_FILES := $(core_src_files)
+LOCAL_C_INCLUDES := $(core_c_includes)
+LOCAL_SHARED_LIBRARIES := $(core_shared_libraries)
+LOCAL_STATIC_LIBRARIES := $(core_static_libraries)
+LOCAL_MODULE := libjavacore
+include $(BUILD_STATIC_LIBRARY)
+
+# Deal with keystores required for security. Note: The path to this file
+# is hardcoded in TrustManagerFactoryImpl.java.
+ALL_PREBUILT += $(TARGET_OUT)/etc/security/cacerts.bks
+$(TARGET_OUT)/etc/security/cacerts.bks : $(LOCAL_PATH)/security/src/main/files/cacerts.bks | $(ACP)
+	$(transform-prebuilt-to-target)
+
+
+#
+# Build for the host.
+#
+
+ifeq ($(WITH_HOST_DALVIK),true)
+
+    include $(CLEAR_VARS)
+
+    # Define the rules.
+    LOCAL_SRC_FILES := $(core_src_files)
+    LOCAL_C_INCLUDES := $(core_c_includes)
+    LOCAL_SHARED_LIBRARIES := $(core_shared_libraries)
+    LOCAL_STATIC_LIBRARIES := $(core_static_libraries)
+    LOCAL_MODULE := libjavacore-host
+    include $(BUILD_HOST_STATIC_LIBRARY)
+
+    # TODO: Figure out cacerts.bks for the host.
+
+endif
\ No newline at end of file
diff --git a/archive/src/main/java/java/util/jar/Attributes.java b/archive/src/main/java/java/util/jar/Attributes.java
index 4ee94df..159a0cd 100644
--- a/archive/src/main/java/java/util/jar/Attributes.java
+++ b/archive/src/main/java/java/util/jar/Attributes.java
@@ -437,7 +437,7 @@
         try {
             clone = (Attributes) super.clone();
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
         clone.map = (Map<Object, Object>) ((HashMap) map).clone();
         return clone;
diff --git a/archive/src/main/java/java/util/zip/Deflater.java b/archive/src/main/java/java/util/zip/Deflater.java
index ee9c3ea..48ae479 100644
--- a/archive/src/main/java/java/util/zip/Deflater.java
+++ b/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/archive/src/main/java/java/util/zip/ZipFile.java b/archive/src/main/java/java/util/zip/ZipFile.java
index 653b2c9..b5f3678 100644
--- a/archive/src/main/java/java/util/zip/ZipFile.java
+++ b/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/archive/src/main/native/java_util_zip_Adler32.c b/archive/src/main/native/java_util_zip_Adler32.c
index 1b02a11..0fcf549 100644
--- a/archive/src/main/native/java_util_zip_Adler32.c
+++ b/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/archive/src/main/native/java_util_zip_CRC32.c b/archive/src/main/native/java_util_zip_CRC32.c
index cee25e5..fe50fca 100644
--- a/archive/src/main/native/java_util_zip_CRC32.c
+++ b/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/archive/src/main/native/java_util_zip_Deflater.c b/archive/src/main/native/java_util_zip_Deflater.c
index 2e0e268..af0bfcc 100644
--- a/archive/src/main/native/java_util_zip_Deflater.c
+++ b/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/archive/src/main/native/java_util_zip_Inflater.c b/archive/src/main/native/java_util_zip_Inflater.c
index 4b30d4e..c04a223 100644
--- a/archive/src/main/native/java_util_zip_Inflater.c
+++ b/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/archive/src/main/native/sieb.c b/archive/src/main/native/sieb.c
index 6881cf6..4529307 100644
--- a/archive/src/main/native/sieb.c
+++ b/archive/src/main/native/sieb.c
@@ -1,38 +1,52 @@
+/*
+ * 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 "sieb.h"
 #include "JNIHelp.h"
 #include "jni.h"
 
-#include <malloc.h>
+#include <stdlib.h>
 
 // Throw java.lang.OutOfMemoryError
-void throwNewOutOfMemoryError (JNIEnv * env, const char *message)
-{
+void throwNewOutOfMemoryError(JNIEnv *env, const char *message) {
     jniThrowException(env, "java/lang/OutOfMemoryError", message);
 }
 
-void * sieb_malloc (JNIEnv * env, size_t byteCnt) {
-    void * adr = malloc(byteCnt);
+void *sieb_malloc(JNIEnv *env, size_t byteCnt) {
+    void *adr = malloc(byteCnt);
     if (adr == 0) {
-         if (byteCnt == 0)
-             throwNewOutOfMemoryError(env, "sieb_malloc(0) NOT ALLOWED");
-         else
-             throwNewOutOfMemoryError(env, "sieb_malloc");
+        if (byteCnt == 0) {
+            throwNewOutOfMemoryError(env, "sieb_malloc(0) NOT ALLOWED");
+        } else {
+            throwNewOutOfMemoryError(env, "sieb_malloc");
+        }
     }
     return adr;
 }
 
-void sieb_free (JNIEnv * env, void * adr) {
+void sieb_free(JNIEnv *env, void *adr) {
     free(adr);
 }
 
-
-
-void sieb_convertToPlatform (char *path) {
+void sieb_convertToPlatform(char *path) {
     char *pathIndex;
 
     pathIndex = path;
     while (*pathIndex != '\0') {
-        if(*pathIndex == '\\') {
+        if (*pathIndex == '\\') {
             *pathIndex = '/';
         }
         pathIndex++;
diff --git a/archive/src/main/native/sieb.h b/archive/src/main/native/sieb.h
index 541ad90..c32da04 100644
--- a/archive/src/main/native/sieb.h
+++ b/archive/src/main/native/sieb.h
@@ -1,21 +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.
+ */
+
 #if !defined(sieb_h)
 #define sieb_h
 
-
 #include "JNIHelp.h"
 #include "jni.h"
 
-
-
-void throwNewOutOfMemoryError (JNIEnv * env,
-                               const char *message);
-
-
-void * sieb_malloc (JNIEnv * env, size_t byteCnt);
-void sieb_free (JNIEnv * env, void * adr);
-
-void sieb_convertToPlatform (char *path);
-
-
+void throwNewOutOfMemoryError(JNIEnv *env, const char *message);
+void *sieb_malloc(JNIEnv *env, size_t byteCnt);
+void sieb_free(JNIEnv *env, void *adr);
+void sieb_convertToPlatform(char *path);
 
 #endif /* sieb_h */
diff --git a/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java b/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java
index 77fbb15..601fe42 100644
--- a/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java
+++ b/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/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java b/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java
index 4c209d1..01f5a8c 100644
--- a/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java
+++ b/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/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java b/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java
index acdad71..b2ecdec 100644
--- a/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java
+++ b/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/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java b/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java
index c6f07de..013974c 100644
--- a/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java
+++ b/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/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java b/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java
index b025e11..fb326a6 100644
--- a/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java
+++ b/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java
@@ -23,6 +23,7 @@
 import dalvik.annotation.TestTargetNew;
 import tests.support.Support_PlatformFile;
 import tests.support.resource.Support_Resources;
+import tests.util.TestEnvironment;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -142,7 +143,6 @@
         args = {java.lang.String.class}
     )
     public void test_ConstructorLjava_lang_String() throws IOException {
-        String oldUserDir = System.getProperty("user.dir");
         System.setProperty("user.dir", System.getProperty("java.io.tmpdir"));
 
         zfile.close(); // about to reopen the same temp file
@@ -167,7 +167,6 @@
             // expected
         } finally {
             System.setSecurityManager(oldSm);
-            System.setProperty("user.dir", oldUserDir);
         }
     }
 
@@ -271,14 +270,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 +357,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 +438,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) {
         }
     }
 
@@ -582,6 +582,7 @@
      */
     @Override
     protected void tearDown() {
+        TestEnvironment.reset();
         try {
             if (zfile != null) {
                 // Note zfile is a user-defined zip file used by other tests and
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
index ee21b13..312c76d 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/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/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
index d96f4c2..187acbc 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/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/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
index 9a484e6..fff6a1e 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
+++ b/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/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherTest.java b/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherTest.java
index 1245eb3..c7c1a5d 100644
--- a/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherTest.java
+++ b/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherTest.java
@@ -25,6 +25,7 @@
 import org.apache.harmony.crypto.tests.support.MyCipher;
 
 import tests.support.resource.Support_Resources;
+import tests.util.TestEnvironment;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -86,7 +87,12 @@
             fail("No key " + e);
         }
     }
-    
+
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+    }
+
     /**
      * @tests javax.crypto.Cipher#getInstance(java.lang.String)
      */
diff --git a/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/EncryptedPrivateKeyInfoTest.java b/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/EncryptedPrivateKeyInfoTest.java
index d3d0857..63ed789 100644
--- a/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/EncryptedPrivateKeyInfoTest.java
+++ b/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/EncryptedPrivateKeyInfoTest.java
@@ -57,6 +57,7 @@
 import org.apache.harmony.crypto.tests.support.EncryptedPrivateKeyInfoData;
 
 import junit.framework.TestCase;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(EncryptedPrivateKeyInfo.class)
 /**
@@ -195,7 +196,12 @@
     //            {"RSA",null}, // 1.2.840.113549.1.1.1
     //            {"1.2.840.113549.1.1.1", null},
     };
-    
+
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+    }
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
diff --git a/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherAesWrapTest.java b/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherAesWrapTest.java
index d196edc..a5d8d90 100644
--- a/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherAesWrapTest.java
+++ b/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherAesWrapTest.java
@@ -22,10 +22,17 @@
 import junit.framework.TestCase;
 
 import targets.Cipher;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(Cipher.AESWrap.class)
 public class CipherAesWrapTest extends TestCase {
-// 3 cases checked
+
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+    }
+
+    // 3 cases checked
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
diff --git a/dalvik/src/main/java/dalvik/system/DalvikLogHandler.java b/dalvik/src/main/java/dalvik/system/DalvikLogHandler.java
new file mode 100644
index 0000000..a62ca3b
--- /dev/null
+++ b/dalvik/src/main/java/dalvik/system/DalvikLogHandler.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 dalvik.system;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * An optimized handler for efficient publishing of basic log messages.
+ * Implementers should also be subclasses of {@link java.util.logging.Handler}.
+ *
+ * <p>Unlike the default log handler, this API doesn't require intermediate
+ * objects to be allocated for log handling. It also includes a short tag, which
+ * may otherwise need to be calculated for each published message.
+ *
+ * @hide
+ */
+public interface DalvikLogHandler {
+
+    /**
+     * Publishes a log message. Unlike {@link
+     * java.util.logging.Handler#publish(java.util.logging.LogRecord)}, this
+     * method includes only the raw log message. Log messages that were created
+     * with additional fields (parameters, source methods, etc.) will flow
+     * through the conventional channels instead.
+     *
+     * @param tag the short (23 characters or fewer) logger tag identifying
+     *      {@code logger}.
+     */
+    void publish(Logger source, String tag, Level level, String message);
+
+    // TODO: support messages with throwables?
+}
\ No newline at end of file
diff --git a/dalvik/src/main/java/dalvik/system/DalvikLogging.java b/dalvik/src/main/java/dalvik/system/DalvikLogging.java
new file mode 100644
index 0000000..b5c7ad5
--- /dev/null
+++ b/dalvik/src/main/java/dalvik/system/DalvikLogging.java
@@ -0,0 +1,48 @@
+/*
+ * 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 dalvik.system;
+
+/**
+ * Utility methods for logging to {@code DalvikHandlers}.
+ *
+ * @hide
+ */
+public final class DalvikLogging {
+    private DalvikLogging() {}
+
+    /**
+     * Returns the short logger tag (up to 23 chars) for the given logger name.
+     * Traditionally loggers are named by fully-qualified Java classes; this
+     * method attempts to return a concise identifying part of such names.
+     */
+    public static String loggerNameToTag(String loggerName) {
+        // Anonymous logger.
+        if (loggerName == null) {
+            return "null";
+        }
+
+        int length = loggerName.length();
+        if (length <= 23) {
+            return loggerName;
+        }
+
+        int lastPeriod = loggerName.lastIndexOf(".");
+        return length - (lastPeriod + 1) <= 23
+                ? loggerName.substring(lastPeriod + 1)
+                : loggerName.substring(loggerName.length() - 23);
+    }
+}
diff --git a/dalvik/src/main/java/dalvik/system/DexClassLoader.java b/dalvik/src/main/java/dalvik/system/DexClassLoader.java
index 73e6fe4..4a440b5 100644
--- a/dalvik/src/main/java/dalvik/system/DexClassLoader.java
+++ b/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/dalvik/src/main/java/dalvik/system/VMDebug.java b/dalvik/src/main/java/dalvik/system/VMDebug.java
index 365388a..f9411ca 100644
--- a/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -284,10 +284,18 @@
     public static native boolean cacheRegisterMap(String classAndMethodDesc);
 
     /**
-     * Crashes the VM.  Seriously.  Dumps the stack trace for the current
-     * thread and then aborts the VM so you can see the native stack trace.
-     * Useful for figuring out how you got somewhere when lots of native
-     * code is involved.
+     * Dumps the contents of the VM reference tables (e.g. JNI locals and
+     * globals) to the log file.
+     *
+     * @hide
+     */
+    public static native void dumpReferenceTables();
+
+    /**
+     * Crashes the VM.  Seriously.  Dumps the interpreter stack trace for
+     * the current thread and then aborts the VM so you can see the native
+     * stack trace.  Useful for figuring out how you got somewhere when
+     * lots of native code is involved.
      *
      * @hide
      */
diff --git a/icu/src/main/java/com/ibm/icu4jni/charset/CharsetDecoderICU.java b/icu/src/main/java/com/ibm/icu4jni/charset/CharsetDecoderICU.java
index 919d865..9c74d68 100644
--- a/icu/src/main/java/com/ibm/icu4jni/charset/CharsetDecoderICU.java
+++ b/icu/src/main/java/com/ibm/icu4jni/charset/CharsetDecoderICU.java
@@ -286,9 +286,11 @@
 
     private final int getArray(CharBuffer out){
         if(out.hasArray()){
+            // BEGIN android-changed: take arrayOffset into account
             output = out.array();
-            outEnd = out.limit();
-            return out.position();
+            outEnd = out.arrayOffset() + out.limit();
+            return out.arrayOffset() + out.position();
+            // END android-changed
         }else{
             outEnd = out.remaining();
             // BEGIN android-added
@@ -306,9 +308,11 @@
     }
     private  final int getArray(ByteBuffer in){
         if(in.hasArray()){
+            // BEGIN android-changed: take arrayOffset into account
             input = in.array();
-            inEnd = in.limit();
-            return in.position()+savedInputHeldLen;/*exclude the number fo bytes held in previous conversion*/
+            inEnd = in.arrayOffset() + in.limit();
+            return in.arrayOffset() + in.position() + savedInputHeldLen;/*exclude the number fo bytes held in previous conversion*/
+            // END android-changed
         }else{
             inEnd = in.remaining();
             // BEGIN android-added
@@ -331,7 +335,9 @@
     }
     private final void setPosition(CharBuffer out){
         if(out.hasArray()){
-            out.position(out.position() + data[OUTPUT_OFFSET]);
+            // BEGIN android-changed: take arrayOffset into account
+            out.position(out.position() + data[OUTPUT_OFFSET] - out.arrayOffset());
+            // END android-changed
         }else{
             out.put(output,0,data[OUTPUT_OFFSET]);
         }
diff --git a/icu/src/main/java/com/ibm/icu4jni/charset/CharsetEncoderICU.java b/icu/src/main/java/com/ibm/icu4jni/charset/CharsetEncoderICU.java
index ec169f4..eada080 100644
--- a/icu/src/main/java/com/ibm/icu4jni/charset/CharsetEncoderICU.java
+++ b/icu/src/main/java/com/ibm/icu4jni/charset/CharsetEncoderICU.java
@@ -328,9 +328,11 @@
     //------------------------------------------
     private final int getArray(ByteBuffer out) {
         if(out.hasArray()){
+            // BEGIN android-changed: take arrayOffset into account
             output = out.array();
-            outEnd = out.limit();
-            return out.position();
+            outEnd = out.arrayOffset() + out.limit();
+            return out.arrayOffset() + out.position();
+            // END android-changed
         }else{
             outEnd = out.remaining();
             // BEGIN android-added
@@ -348,9 +350,11 @@
 
     private final int getArray(CharBuffer in) {
         if(in.hasArray()){
+            // BEGIN android-changed: take arrayOffset into account
             input = in.array();
-            inEnd = in.limit();
-            return in.position()+savedInputHeldLen;/*exclude the number fo bytes held in previous conversion*/
+            inEnd = in.arrayOffset() + in.limit();
+            return in.arrayOffset() + in.position() + savedInputHeldLen;/*exclude the number fo bytes held in previous conversion*/
+            // END android-changed
         }else{
             inEnd = in.remaining();
             // BEGIN android-added
@@ -378,7 +382,9 @@
             // array backing the buffer directly and wrote to 
             // it, so just just set the position and return.
             // This is done to avoid the creation of temp array.
-            out.position(out.position() + data[OUTPUT_OFFSET] );
+            // BEGIN android-changed: take arrayOffset into account
+            out.position(out.position() + data[OUTPUT_OFFSET] - out.arrayOffset());
+            // END android-changed
         } else {
             out.put(output, 0, data[OUTPUT_OFFSET]);
         }
diff --git a/icu/src/main/java/com/ibm/icu4jni/text/BreakIterator.java b/icu/src/main/java/com/ibm/icu4jni/text/BreakIterator.java
index c8f5372..5ef1161 100644
--- a/icu/src/main/java/com/ibm/icu4jni/text/BreakIterator.java
+++ b/icu/src/main/java/com/ibm/icu4jni/text/BreakIterator.java
@@ -22,10 +22,10 @@
 
 public abstract class BreakIterator implements Cloneable
 {
-    protected static int BI_CHAR_INSTANCE = 1;
-    protected static int BI_WORD_INSTANCE = 2;
-    protected static int BI_LINE_INSTANCE = 3;
-    protected static int BI_SENT_INSTANCE = 4;
+    protected static final int BI_CHAR_INSTANCE = 1;
+    protected static final int BI_WORD_INSTANCE = 2;
+    protected static final int BI_LINE_INSTANCE = 3;
+    protected static final int BI_SENT_INSTANCE = 4;
     
     protected int type = 0;
     
diff --git a/icu/src/main/java/com/ibm/icu4jni/text/CollationKey.java b/icu/src/main/java/com/ibm/icu4jni/text/CollationKey.java
index 7e8a000..9e9401d 100644
--- a/icu/src/main/java/com/ibm/icu4jni/text/CollationKey.java
+++ b/icu/src/main/java/com/ibm/icu4jni/text/CollationKey.java
@@ -122,7 +122,7 @@
   {
     if (m_hash_ == 0)
     {
-      if (m_bytes_ != null || m_bytes_.length != 0) 
+      if (m_bytes_ != null && m_bytes_.length != 0)
       {                        
         int len = m_bytes_.length;
         int inc = ((len - 32) / 32) + 1;  
diff --git a/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java b/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
index 5bee1fd..104336e 100644
--- a/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
+++ b/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/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java b/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
index 98463e4..ebda335 100644
--- a/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
+++ b/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
@@ -24,7 +24,7 @@
 import java.util.Locale;
 import java.util.ResourceBundle;
 
-public class DecimalFormatSymbols {
+public class DecimalFormatSymbols implements Cloneable {
     
     private int addr;
     
diff --git a/icu/src/main/java/com/ibm/icu4jni/util/Resources.java b/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
index 0460fde..086f8d4 100644
--- a/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
+++ b/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/icu/src/main/native/BidiWrapperInterface.c b/icu/src/main/native/BidiWrapperInterface.c
index 2c6b3cd..19ac520 100644
--- a/icu/src/main/native/BidiWrapperInterface.c
+++ b/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/icu/src/main/native/CollationInterface.c b/icu/src/main/native/CollationInterface.c
index 86246ac..c669649 100644
--- a/icu/src/main/native/CollationInterface.c
+++ b/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/icu/src/main/native/DecimalFormatInterface.cpp b/icu/src/main/native/DecimalFormatInterface.cpp
index 7e37d6c..f553e0a 100644
--- a/icu/src/main/native/DecimalFormatInterface.cpp
+++ b/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/icu/src/main/native/ErrorCode.c b/icu/src/main/native/ErrorCode.c
index b3e43cd..94c4239 100644
--- a/icu/src/main/native/ErrorCode.c
+++ b/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/icu/src/main/native/ErrorCode.h b/icu/src/main/native/ErrorCode.h
index a5bbfc6..e42a519 100644
--- a/icu/src/main/native/ErrorCode.h
+++ b/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/icu/src/main/native/RBNFInterface.cpp b/icu/src/main/native/RBNFInterface.cpp
index d9bf460..c7486e1 100644
--- a/icu/src/main/native/RBNFInterface.cpp
+++ b/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/icu/src/main/native/RegExInterface.cpp b/icu/src/main/native/RegExInterface.cpp
index afa5cc4..0ca3d06 100644
--- a/icu/src/main/native/RegExInterface.cpp
+++ b/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/icu/src/main/native/ResourceInterface.cpp b/icu/src/main/native/ResourceInterface.cpp
index a88e15c..731cf3f 100644
--- a/icu/src/main/native/ResourceInterface.cpp
+++ b/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/icu/src/test/java/com/ibm/icu4jni/util/AllTests.java b/icu/src/test/java/com/ibm/icu4jni/util/AllTests.java
new file mode 100644
index 0000000..1b95075
--- /dev/null
+++ b/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/icu/src/test/java/com/ibm/icu4jni/util/ResourcesTest.java b/icu/src/test/java/com/ibm/icu4jni/util/ResourcesTest.java
new file mode 100644
index 0000000..4112d0b
--- /dev/null
+++ b/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/logging/src/main/java/java/util/logging/FileHandler.java b/logging/src/main/java/java/util/logging/FileHandler.java
index e1eba9e..dd7790e 100644
--- a/logging/src/main/java/java/util/logging/FileHandler.java
+++ b/logging/src/main/java/java/util/logging/FileHandler.java
@@ -571,7 +571,7 @@
      *            the log record to publish.
      */
     @Override
-    public void publish(LogRecord record) {
+    public synchronized void publish(LogRecord record) {
         super.publish(record);
         flush();
         if (limit > 0 && output.getLength() >= limit) {
diff --git a/logging/src/main/java/java/util/logging/LogManager.java b/logging/src/main/java/java/util/logging/LogManager.java
index 308daaf..413efb3 100644
--- a/logging/src/main/java/java/util/logging/LogManager.java
+++ b/logging/src/main/java/java/util/logging/LogManager.java
@@ -17,6 +17,14 @@
 
 package java.util.logging;
 
+// BEGIN android-note
+// this file contains cleaned up documentation and style for contribution
+// upstream.
+// javax.management support (MBeans) has been dropped.
+// END android-note
+
+import org.apache.harmony.logging.internal.nls.Messages;
+
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
 import java.io.BufferedInputStream;
@@ -24,28 +32,14 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-// BEGIN android-removed
-//import java.lang.management.ManagementFactory;
-//import java.lang.reflect.Method;
-// END android-removed
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.Properties;
-import java.util.Set;
 import java.util.StringTokenizer;
 
-// BEGIN android-removed
-//import javax.management.MBeanServer;
-//import javax.management.ObjectInstance;
-//import javax.management.ObjectName;
-// END android-removed
-
-import org.apache.harmony.logging.internal.nls.Messages;
-
 /**
  * {@code LogManager} is used to maintain configuration properties of the
  * logging framework, and to manage a hierarchical namespace of all named
@@ -126,20 +120,19 @@
  * the property file. The root logger's level can be defined by the property
  * named as ".level".
  * <p>
- * All methods on this type can be taken as being thread safe.
- *
+ * This class is thread safe. It is an error to synchronize on a
+ * {@code LogManager} while synchronized on a {@code Logger}.
  */
 public class LogManager {
 
-    // The line separator of the underlying OS
-    // Use privileged code to read the line.separator system property
+    /** The line separator of the underlying OS. */
     private static final String lineSeparator = getPrivilegedSystemProperty("line.separator"); //$NON-NLS-1$
 
-    // The shared logging permission
+    /** The shared logging permission. */
     private static final LoggingPermission perm = new LoggingPermission(
             "control", null); //$NON-NLS-1$
 
-    // the singleton instance
+    /** The singleton instance. */
     static LogManager manager;
 
     /**
@@ -192,10 +185,10 @@
     // FIXME: use weak reference to avoid heap memory leak
     private Hashtable<String, Logger> loggers;
 
-    // the configuration properties
+    /** The configuration properties */
     private Properties props;
 
-    // the property change listener
+    /** the property change listener */
     private PropertyChangeSupport listeners;
 
     static {
@@ -234,7 +227,7 @@
     /**
      * Default constructor. This is not public because there should be only one
      * {@code LogManager} instance, which can be get by
-     * {@code LogManager.getLogManager(}. This is protected so that
+     * {@code LogManager.getLogManager()}. This is protected so that
      * application can subclass the object.
      */
     protected LogManager() {
@@ -318,17 +311,17 @@
             parentName = parentName.substring(0, lastSeparator);
             parent = loggers.get(parentName);
             if (parent != null) {
-                logger.internalSetParent(parent);
+                setParent(logger, parent);
                 break;
             } else if (getProperty(parentName + ".level") != null || //$NON-NLS-1$
                     getProperty(parentName + ".handlers") != null) { //$NON-NLS-1$
                 parent = Logger.getLogger(parentName);
-                logger.internalSetParent(parent);
+                setParent(logger, parent);
                 break;
             }
         }
         if (parent == null && null != (parent = loggers.get(""))) { //$NON-NLS-1$
-            logger.internalSetParent(parent);
+            setParent(logger, parent);
         }
 
         // find children
@@ -348,7 +341,7 @@
                 });
                 if (null != oldParent) {
                     // -- remove from old parent as the parent has been changed
-                    oldParent.removeChild(child);
+                    oldParent.children.remove(child);
                 }
             }
         }
@@ -408,7 +401,6 @@
      *             not have the required permissions to perform this action.
      */
     public void readConfiguration() throws IOException {
-        checkAccess();
         // check config class
         String configClassName = System
                 .getProperty("java.util.logging.config.class"); //$NON-NLS-1$
@@ -443,7 +435,7 @@
                                     "logging.properties"), 8192);
                 }
                 // END android-added
-                readConfigurationImpl(input);
+                readConfiguration(input);
             } finally {
                 if (input != null) {
                     try {
@@ -491,6 +483,13 @@
         reset();
         props.load(ins);
 
+        // The RI treats the root logger as special. For compatibility, always
+        // update the root logger's handlers.
+        Logger root = loggers.get("");
+        if (root != null) {
+            root.setManager(this);
+        }
+
         // parse property "config" and apply setting
         String configs = props.getProperty("config"); //$NON-NLS-1$
         if (null != configs) {
@@ -544,7 +543,7 @@
      *             if security manager exists and it determines that caller does
      *             not have the required permissions to perform this action.
      */
-    public void reset() {
+    public synchronized void reset() {
         checkAccess();
         props = new Properties();
         Enumeration<String> names = getLoggerNames();
@@ -593,4 +592,67 @@
         checkAccess();
         listeners.removePropertyChangeListener(l);
     }
+
+    /**
+     * Returns a named logger associated with the supplied resource bundle.
+     *
+     * @param resourceBundleName the resource bundle to associate, or null for
+     *      no associated resource bundle.
+     */
+    synchronized Logger getOrCreate(String name, String resourceBundleName) {
+        Logger result = getLogger(name);
+        if (result == null) {
+            result = new Logger(name, resourceBundleName);
+            addLogger(result);
+        }
+        return result;
+    }
+
+
+    /**
+     * Sets the parent of this logger in the namespace. Callers must first
+     * {@link #checkAccess() check security}.
+     *
+     * @param newParent
+     *            the parent logger to set.
+     */
+    synchronized void setParent(Logger logger, Logger newParent) {
+        logger.parent = newParent;
+
+        if (logger.levelObjVal == null) {
+            setLevelRecursively(logger, null);
+        }
+        newParent.children.add(logger);
+        logger.updateDalvikLogHandler(); // android-only
+    }
+
+    /**
+     * Sets the level on {@code logger} to {@code newLevel}. Any child loggers
+     * currently inheriting their level from {@code logger} will be updated
+     * recursively.
+     *
+     * @param newLevel the new minimum logging threshold. If null, the logger's
+     *      parent level will be used; or {@code Level.INFO} for loggers with no
+     *      parent.
+     */
+    synchronized void setLevelRecursively(Logger logger, Level newLevel) {
+        int previous = logger.levelIntVal;
+        logger.levelObjVal = newLevel;
+
+        if (newLevel == null) {
+            logger.levelIntVal = logger.parent != null
+                    ? logger.parent.levelIntVal
+                    : Level.INFO.intValue();
+        } else {
+            logger.levelIntVal = newLevel.intValue();
+        }
+
+        if (previous != logger.levelIntVal) {
+            for (Logger child : logger.children) {
+                if (child.levelObjVal == null) {
+                    setLevelRecursively(child, null);
+                }
+            }
+        }
+    }
 }
diff --git a/logging/src/main/java/java/util/logging/Logger.java b/logging/src/main/java/java/util/logging/Logger.java
index fe124d3..e4f317d 100644
--- a/logging/src/main/java/java/util/logging/Logger.java
+++ b/logging/src/main/java/java/util/logging/Logger.java
@@ -17,15 +17,26 @@
 
 package java.util.logging;
 
+// BEGIN android-note
+// this file contains cleaned up documentation and style for contribution
+// upstream
+// It also contains Android-specific optimizations that aren't appropriate for
+// general purpose platforms
+// END android-note
+
+import dalvik.system.DalvikLogHandler;
+import dalvik.system.DalvikLogging;
+import org.apache.harmony.logging.internal.nls.Messages;
+
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
-
-import org.apache.harmony.logging.internal.nls.Messages;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * Loggers are used to log records to certain outputs, including file, console,
@@ -67,51 +78,158 @@
  */
 public class Logger {
 
-    /**
-     * The global logger is provided as convenience for casual use.
-     */
+    // BEGIN android-only
+    /** A handler for use when no handler optimization is possible. */
+    private static final DalvikLogHandler GENERAL_LOG_HANDLER = new DalvikLogHandler() {
+        public void publish(Logger source, String tag, Level level, String message) {
+            LogRecord record = new LogRecord(level, message);
+            record.setLoggerName(source.name);
+            source.setResourceBundle(record);
+            source.log(record);
+        }
+    };
+    // END android-only
+
+    /** The global logger is provided as convenience for casual use. */
     public final static Logger global = new Logger("global", null); //$NON-NLS-1$
 
-    // the name of this logger
+    /**
+     * When converting the concurrent collection of handlers to an array, we
+     * always pass a zero-length array to avoid size miscalculations. Passing
+     * properly-sized arrays is non-atomic, and risks a null element in the
+     * result.
+     */
+    private static final Handler[] EMPTY_HANDLERS_ARRAY = new Handler[0];
+
+    /** The name of this logger. */
     private volatile String name;
 
-    // the parent logger of this logger
-    private Logger parent;
+    /** The parent logger of this logger. */
+    Logger parent;
 
-    // the logging level of this logger
-    private volatile Level levelObjVal;
+    /** The logging level of this logger, or null if none is set. */
+    volatile Level levelObjVal;
 
-    // the logging level as int of this logger
-    private volatile int levelIntVal;
+    /**
+     * The effective logging level of this logger. In order of preference this
+     * is the first applicable of:
+     * <ol>
+     * <li>the int value of this logger's {@link #levelObjVal}
+     * <li>the logging level of the parent
+     * <li>the default level ({@link Level#INFO})
+     * </ol>
+     */
+    volatile int levelIntVal = Level.INFO.intValue();
 
-    // the filter
+    /** The filter. */
     private Filter filter;
 
-    // the name of the resource bundle used to localize logging messages
-    private String resBundleName;
-
-    // the loaded resource bundle according to the specified name
-    private ResourceBundle resBundle;
-
-    // the handlers attached to this logger
-    private List<Handler> handlers;
-
-    /*
-     * flag indicating whether to notify parent's handlers on receiving a log
-     * request
+    /**
+     * The resource bundle used to localize logging messages. If null, no
+     * localization will be performed.
      */
-    private boolean notifyParentHandlers;
+    private volatile String resourceBundleName;
 
-    // flag indicating whether this logger is named or anonymous
-    private boolean isNamed;
+    /** The loaded resource bundle according to the specified name. */
+    private volatile ResourceBundle resourceBundle;
 
-    private List<Logger> childs;
+    /**
+     * The handlers attached to this logger. Eagerly initialized and
+     * concurrently modified.
+     */
+    private final List<Handler> handlers = new CopyOnWriteArrayList<Handler>();
 
-    private LogManager manager;
+    /** True to notify the parent's handlers of each log message. */
+    private boolean notifyParentHandlers = true;
 
-    // BEGIN android-changed
-    private volatile boolean handlerInited;
-    // END android-changed
+    /**
+     * Indicates whether this logger is named. Only {@link #getAnonymousLogger
+     * anonymous loggers} are unnamed.
+     */
+    private boolean isNamed = true;
+
+    /**
+     * Child loggers. Should be accessed only while synchronized on {@code
+     * LogManager.getLogManager()}.
+     */
+    final List<Logger> children = new ArrayList<Logger>();
+
+    // BEGIN android-only
+    /** the tag used for optimized logging. Derived from the logger name. */
+    private final String androidTag;
+
+    /** Handler delegate for either optimized or standard logging. */
+    private volatile DalvikLogHandler dalvikLogHandler = GENERAL_LOG_HANDLER;
+
+    /**
+     * We've optimized for the common case: logging to a single handler that
+     * implements {@link DalvikLogHandler}. This is how Android framework
+     * applications are configured by default.
+     *
+     * <p>This optimization has been measured to show a 2.75x improvement in
+     * throughput in the common case: 154ns vs. 56ns per message on a Cortex-A8.
+     * Direct use of {@code android.util.Log} takes 29ns per message.
+     *
+     * <p>Each time the handler configuration changes, either directly or
+     * indirectly, it's necessary to either turn on or off this optimization.
+     * When the optimization is off, {@link #dalvikLogHandler} is assigned to
+     * {@link #GENERAL_LOG_HANDLER} which can satisfy arbitrary configuration.
+     * When the optimization is possible, {@link #dalvikLogHandler} is assigned
+     * to the user's efficient implementation. In pratice this is usually the
+     * {@code com.android.internal.logging.AndroidHandler}.
+     */
+    void updateDalvikLogHandler() {
+        DalvikLogHandler newLogHandler = GENERAL_LOG_HANDLER;
+
+        Logger parent = this.parent;
+
+        if (getClass() != Logger.class) {
+            /*
+             * Do nothing. Subclasses aren't eligible for the optimization
+             * because they may override methods like getHandlers() or
+             * log(LogRecord).
+             */
+
+        } else if (parent == null) {
+            // we use an iterator rather than size()+get() for safe concurrency
+            Iterator<Handler> h = handlers.iterator();
+            if (h.hasNext()) {
+                Handler firstHandler = h.next();
+                if (!h.hasNext() && firstHandler instanceof DalvikLogHandler) {
+                    /*
+                     * At this point, we're eligible for the optimization. We've
+                     * satisfied these constraints:
+                     *   1. This is not a subclass of logger
+                     *   2. This is a root logger (no parent)
+                     *   3. There is exactly one handler installed
+                     *   4. That handler is a DalvikLogHandler
+                     */
+                    newLogHandler = (DalvikLogHandler) firstHandler;
+                }
+            }
+        } else if (handlers.isEmpty() && notifyParentHandlers) {
+            /*
+             * At this point, we're eligible for the optimization if our parent
+             * logger is eligible. We've satisfied these constraints:
+             *   1. This is not a subclass of logger
+             *   2. our parent exists
+             *   3. we have no handlers of our own
+             *   4. we notify our parent's handlers
+             */
+            newLogHandler = parent.dalvikLogHandler;
+        }
+
+        if (newLogHandler == this.dalvikLogHandler) {
+            return;
+        }
+
+        this.dalvikLogHandler = newLogHandler;
+
+        for (Logger logger : children) {
+            logger.updateDalvikLogHandler();
+        }
+    }
+    // END android-only
 
     /**
      * Constructs a {@code Logger} object with the supplied name and resource
@@ -129,55 +247,12 @@
      *             if the specified resource bundle can not be loaded.
      */
     protected Logger(String name, String resourceBundleName) {
-        // try to load the specified resource bundle first
-        if (null == resourceBundleName) {
-            this.resBundleName = null;
-            this.resBundle = null;
-        } else {
-            this.resBundle = loadResourceBundle(resourceBundleName);
-            this.resBundleName = resourceBundleName;
-        }
         this.name = name;
-        this.parent = null;
-        this.filter = null;
-        this.childs = new ArrayList<Logger>();
-        this.notifyParentHandlers = true;
-        // any logger is not anonymous by default
-        this.isNamed = true;
-
-        // -- 'null' means that level will be inherited from parent (see
-        // getLevel)
-        // -- Level.INFO is default level if we don't set it. It will be
-        // -- changed to parent level or to configLevel after adding to the
-        // -- family tree. As of this, actually, setting to Level.INFO is
-        // -- not needed here.
-        this.levelObjVal = null;
-        this.levelIntVal = Level.INFO.intValue();
-    }
-
-    // -- should be called under the lm lock
-    private void setLevelImpl(Level newLevel) {
-        // update levels for the whole hierarchy
-        int oldVal = levelIntVal;
-        levelObjVal = newLevel;
-        if (null == newLevel) {
-            levelIntVal = null != parent ? parent.levelIntVal : Level.INFO
-                    .intValue();
-        } else {
-            levelIntVal = newLevel.intValue();
-        }
-        if (oldVal != levelIntVal) {
-            forceChildsToInherit();
-        }
-    }
-
-    // -- should be called under the lm lock
-    private void forceChildsToInherit() {
-        for (Logger child : childs) {
-            if (null == child.levelObjVal) { // should inherit
-                child.setLevelImpl(null);
-            }
-        }
+        initResourceBundle(resourceBundleName);
+        // BEGIN android-only
+        this.androidTag = DalvikLogging.loggerNameToTag(name);
+        updateDalvikLogHandler();
+        // END android-only
     }
 
     /**
@@ -197,7 +272,7 @@
                         return Thread.currentThread().getContextClassLoader();
                     }
                 });
-        if (null != cl) {
+        if (cl != null) {
             try {
                 return ResourceBundle.getBundle(resourceBundleName, Locale
                         .getDefault(), cl);
@@ -211,7 +286,7 @@
                 return ClassLoader.getSystemClassLoader();
             }
         });
-        if (null != cl) {
+        if (cl != null) {
             try {
                 return ResourceBundle.getBundle(resourceBundleName, Locale
                         .getDefault(), cl);
@@ -237,7 +312,7 @@
                                 return classes[index].getClassLoader();
                             }
                         });
-                if (null == cl) {
+                if (cl == null) {
                     continue;
                 }
                 return ResourceBundle.getBundle(resourceBundleName, Locale
@@ -280,66 +355,38 @@
      *             if the specified resource bundle can not be loaded.
      */
     public static Logger getAnonymousLogger(String resourceBundleName) {
-        final Logger l = new Logger(null, resourceBundleName);
-        l.isNamed = false;
-        l.internalSetParent(LogManager.getLogManager().getLogger("")); //$NON-NLS-1$
-        return l;
+        Logger result = new Logger(null, resourceBundleName);
+        result.isNamed = false;
+        LogManager logManager = LogManager.getLogManager();
+        logManager.setParent(result, logManager.getLogger(""));
+        return result;
     }
 
-    /*
-     * Check whether the same resource bundle has been specified.
-     * Synchronize to ensure the consistency between resource bundle
-     * and its name.
+    /**
+     * Initializes this logger's resource bundle.
+     *
+     * @throws IllegalArgumentException if this logger's resource bundle already
+     *      exists and is different from the resource bundle specified.
      */
-    private static void updateResourceBundle(Logger l, String resourceBundleName) {
-        synchronized (l) {
-            if (null == l.getResourceBundleName()) {
-                if (null == resourceBundleName) {
-                    return;
-                }
-                /*
-                 * load the resource bundle if none is specified before
-                 */
-                l.resBundle = loadResourceBundle(resourceBundleName);
-                l.resBundleName = resourceBundleName;
-            } else if (!l.getResourceBundleName().equals(resourceBundleName)) {
-                /*
-                 * throw exception if the specified resource bundles are
-                 * inconsistent with each other, i.e., different names
-                 */
+    private synchronized void initResourceBundle(String resourceBundleName) {
+        String current = this.resourceBundleName;
+
+        if (current != null) {
+            if (current.equals(resourceBundleName)) {
+                return;
+            } else {
                 // logging.9=The specified resource bundle name "{0}" is
                 // inconsistent with the existing one "{1}".
                 throw new IllegalArgumentException(Messages.getString(
                         "logging.9", //$NON-NLS-1$
-                        resourceBundleName, l.getResourceBundleName()));
+                        resourceBundleName, current));
             }
         }
-    }
 
-    /*
-     * Gets a named logger associated with the supplied resource bundle. This
-     * method accepts null resource bundle name. The method body is synchronized
-     * on the instance of the LogManager to insure the consistency of the whole
-     * operation.
-     */
-    private static Logger getLoggerWithRes(String name,
-            String resourceBundleName, boolean hasResourceName) {
-        LogManager man = LogManager.getLogManager();
-        Logger l = null;
-        synchronized (man) {
-            // Try to find an existing logger with the specified name
-            l = man.getLogger(name);
-            // If no existing logger with the same name, create a new one
-            if (null == l) {
-                l = new Logger(name, resourceBundleName);
-                man.addLogger(l);
-                return l;
-            }
+        if (resourceBundleName != null) {
+            this.resourceBundle = loadResourceBundle(resourceBundleName);
+            this.resourceBundleName = resourceBundleName;
         }
-        if (hasResourceName) {
-            updateResourceBundle(l, resourceBundleName);
-        }
-        return l;
     }
 
     /**
@@ -354,7 +401,7 @@
      *             If the specified resource bundle can not be loaded.
      */
     public static Logger getLogger(String name) {
-        return getLoggerWithRes(name, null, false);
+        return LogManager.getLogManager().getOrCreate(name, null);
     }
 
     /**
@@ -374,7 +421,10 @@
      * @return a named logger.
      */
     public static Logger getLogger(String name, String resourceBundleName) {
-        return getLoggerWithRes(name, resourceBundleName, true);
+        Logger result = LogManager.getLogManager()
+                .getOrCreate(name, resourceBundleName);
+        result.initResourceBundle(resourceBundleName);
+        return result;
     }
 
     /**
@@ -388,7 +438,7 @@
      *             have the required permission.
      */
     public void addHandler(Handler handler) {
-        if (null == handler) {
+        if (handler == null) {
             // logging.A=The 'handler' parameter is null.
             throw new NullPointerException(Messages.getString("logging.A")); //$NON-NLS-1$
         }
@@ -396,64 +446,55 @@
         if (this.isNamed) {
             LogManager.getLogManager().checkAccess();
         }
-        initHandler();
-        synchronized (this) {
-            this.handlers.add(handler);
-        }
+        this.handlers.add(handler);
+        updateDalvikLogHandler(); // android-only
     }
 
-    /*
-     * Be cautious to avoid deadlock when using this method, it gets lock on manager
-     * at first, and then gets lock on this Logger, so any methods should not hold
-     * lock on this Logger when invoking this method.
+    /**
+     * Set the logger's manager and initializes its configuration from the
+     * manager's properties.
      */
-    private void initHandler() {
-        if (!handlerInited) {
-            synchronized (this) {
-                if (!handlerInited) {
-                    // BEGIN android-added
-                    /*
-                     * Force LogManager to be initialized, since its
-                     * class init code performs necessary one-time setup.
-                     */
-                    LogManager.getLogManager();
-                    // END android-added
-                    if (handlers == null) {
-                        handlers = new ArrayList<Handler>();
-                    }
-                    if (manager == null) {
-                        return;
-                    }
-
-                    String handlerStr = manager
-                            .getProperty("".equals(name) ? "handlers" : name + ".handlers"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-                    if (null == handlerStr) {
-                        return;
-                    }
-                  String[] strs = handlerStr.split(",|\\s"); //$NON-NLS-1$
-                  for (int i = 0; i < strs.length; i++) {
-                    String handlerName = strs[i];
-                    if (handlerName.equals("")) { //$NON-NLS-1$
-                      continue;
-                    }
-                    // BEGIN android-changed
-                    // deal with non-existing handler
-                    try {
-                      Handler handler = (Handler) LogManager.getInstanceByClass(handlerName);
-                      handlers.add(handler);
-                      String level = manager.getProperty(handlerName + ".level"); //$NON-NLS-1$
-                      if (null != level) {
-                        handler.setLevel(Level.parse(level));
-                      }
-                    } catch (Exception ex) {
-                      ex.printStackTrace();
-                    }
-                    // END android-changed
-                  }
-                  handlerInited = true;
-                }
+    @SuppressWarnings("nls")
+    void setManager(LogManager manager) {
+        String levelProperty = manager.getProperty(name + ".level");
+        if (levelProperty != null) {
+            try {
+                manager.setLevelRecursively(Logger.this, Level.parse(levelProperty));
+            } catch (IllegalArgumentException invalidLevel) {
+                invalidLevel.printStackTrace();
             }
         }
+
+        String handlersPropertyName = "".equals(name) ? "handlers" : name + ".handlers";
+        String handlersProperty = manager.getProperty(handlersPropertyName);
+        if (handlersProperty != null) {
+            for (String handlerName : handlersProperty.split(",|\\s")) {
+                if (handlerName.equals("")) {
+                    continue;
+                }
+
+                final Handler handler;
+                try {
+                    handler = (Handler) LogManager.getInstanceByClass(handlerName);
+                } catch (Exception invalidHandlerName) {
+                    invalidHandlerName.printStackTrace();
+                    continue;
+                }
+
+                try {
+                    String level = manager.getProperty(handlerName + ".level");
+                    if (level != null) {
+                        handler.setLevel(Level.parse(level));
+                    }
+                } catch (Exception invalidLevel) {
+                    invalidLevel.printStackTrace();
+                }
+
+                handlers.add(handler);
+            }
+        }
+
+        updateDalvikLogHandler(); // android-only
     }
 
     /**
@@ -462,10 +503,7 @@
      * @return an array of all the handlers associated with this logger.
      */
     public Handler[] getHandlers() {
-        initHandler();
-        synchronized (this) {
-            return handlers.toArray(new Handler[handlers.size()]);
-        }
+        return handlers.toArray(EMPTY_HANDLERS_ARRAY);
     }
 
     /**
@@ -483,13 +521,11 @@
         if (this.isNamed) {
             LogManager.getLogManager().checkAccess();
         }
-        if (null == handler) {
+        if (handler == null) {
             return;
         }
-        initHandler();
-        synchronized (this) {
-            this.handlers.remove(handler);
-        }
+        this.handlers.remove(handler);
+        updateDalvikLogHandler(); // android-only
     }
 
     /**
@@ -540,12 +576,11 @@
      */
     public void setLevel(Level newLevel) {
         // Anonymous loggers can always set the level
+        LogManager logManager = LogManager.getLogManager();
         if (this.isNamed) {
-            LogManager.getLogManager().checkAccess();
+            logManager.checkAccess();
         }
-        synchronized (LogManager.getLogManager()) {
-            setLevelImpl(newLevel);
-        }
+        logManager.setLevelRecursively(this, newLevel);
     }
 
     /**
@@ -576,6 +611,7 @@
             LogManager.getLogManager().checkAccess();
         }
         this.notifyParentHandlers = notifyParentHandlers;
+        updateDalvikLogHandler(); // android-only
     }
 
     /**
@@ -589,28 +625,6 @@
     }
 
     /**
-     * Sets the parent of this logger in the namespace. This method should
-     * usually be used by the {@code LogManager} object only. This method does
-     * not check security.
-     *
-     * @param newParent
-     *            the parent logger to set.
-     */
-    void internalSetParent(Logger newParent) {
-        // All hierarchy related modifications should get LogManager lock at
-        // first
-        synchronized (LogManager.getLogManager()) {
-            parent = newParent;
-            // -- update level after setting a parent.
-            // -- if level == null we should inherit the parent's level
-            if (null == levelObjVal) {
-                setLevelImpl(levelObjVal);
-            }
-            newParent.addChild(this);
-        }
-    }
-
-    /**
      * Sets the parent of this logger in the namespace. This method should be
      * used by the {@code LogManager} object only.
      *
@@ -621,21 +635,15 @@
      *             have the required permission.
      */
     public void setParent(Logger parent) {
-        if (null == parent) {
+        if (parent == null) {
             // logging.B=The 'parent' parameter is null.
             throw new NullPointerException(Messages.getString("logging.B")); //$NON-NLS-1$
         }
+
         // even anonymous loggers are checked
-        LogManager.getLogManager().checkAccess();
-        internalSetParent(parent);
-    }
-
-    final void addChild(Logger logger) {
-        childs.add(logger);
-    }
-
-    final void removeChild(Logger child) {
-        childs.remove(child);
+        LogManager logManager = LogManager.getLogManager();
+        logManager.checkAccess();
+        logManager.setParent(this, parent);
     }
 
     /**
@@ -655,7 +663,7 @@
      * @return the loaded resource bundle used by this logger.
      */
     public ResourceBundle getResourceBundle() {
-        return this.resBundle;
+        return this.resourceBundle;
     }
 
     /**
@@ -666,7 +674,7 @@
      * @return the name of the loaded resource bundle used by this logger.
      */
     public String getResourceBundleName() {
-        return this.resBundleName;
+        return this.resourceBundleName;
     }
 
     /**
@@ -698,28 +706,19 @@
         return internalIsLoggable(l);
     }
 
-    /*
+    /**
      * Sets the resource bundle and its name for a supplied LogRecord object.
      * This method first tries to use this logger's resource bundle if any,
      * otherwise try to inherit from this logger's parent, recursively up the
-     * namespace. Synchronize to ensure the consistency between resource bundle
-     * and its name.
+     * namespace.
      */
     private void setResourceBundle(LogRecord record) {
-        if (null != this.resBundleName) {
-            record.setResourceBundle(this.resBundle);
-            record.setResourceBundleName(this.resBundleName);
-        } else {
-            Logger anyParent = this.parent;
-            // no need to synchronize here, because if resBundleName
-            // is not null, there is no chance to modify it
-            while (null != anyParent) {
-                if (null != anyParent.resBundleName) {
-                    record.setResourceBundle(anyParent.resBundle);
-                    record.setResourceBundleName(anyParent.resBundleName);
-                    return;
-                }
-                anyParent = anyParent.parent;
+        for (Logger p = this; p != null; p = p.parent) {
+            String resourceBundleName = p.resourceBundleName;
+            if (resourceBundleName != null) {
+                record.setResourceBundle(p.resourceBundle);
+                record.setResourceBundleName(resourceBundleName);
+                return;
             }
         }
     }
@@ -735,14 +734,16 @@
      *            the method name.
      */
     public void entering(String sourceClass, String sourceMethod) {
-        if (internalIsLoggable(Level.FINER)) {
-            LogRecord record = new LogRecord(Level.FINER, "ENTRY"); //$NON-NLS-1$
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(Level.FINER)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(Level.FINER, "ENTRY"); //$NON-NLS-1$
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -759,15 +760,17 @@
      *            the parameter for the method call.
      */
     public void entering(String sourceClass, String sourceMethod, Object param) {
-        if (internalIsLoggable(Level.FINER)) {
-            LogRecord record = new LogRecord(Level.FINER, "ENTRY" + " {0}"); //$NON-NLS-1$ //$NON-NLS-2$
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            record.setParameters(new Object[] { param });
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(Level.FINER)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(Level.FINER, "ENTRY" + " {0}"); //$NON-NLS-1$ //$NON-NLS-2$
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        record.setParameters(new Object[] { param });
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -783,25 +786,28 @@
      * @param params
      *            an array of parameters for the method call.
      */
+    @SuppressWarnings("nls")
     public void entering(String sourceClass, String sourceMethod,
             Object[] params) {
-        if (internalIsLoggable(Level.FINER)) {
-            String msg = "ENTRY"; //$NON-NLS-1$
-            if (null != params) {
-                StringBuilder msgBuffer = new StringBuilder("ENTRY"); //$NON-NLS-1$
-                for (int i = 0; i < params.length; i++) {
-                    msgBuffer.append(" {" + i + "}"); //$NON-NLS-1$ //$NON-NLS-2$
-                }
-                msg = msgBuffer.toString();
-            }
-            LogRecord record = new LogRecord(Level.FINER, msg);
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            record.setParameters(params);
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(Level.FINER)) {
+            return;
         }
+
+        String msg = "ENTRY";
+        if (params != null) {
+            StringBuilder msgBuffer = new StringBuilder("ENTRY");
+            for (int i = 0; i < params.length; i++) {
+                msgBuffer.append(" {").append(i).append("}");
+            }
+            msg = msgBuffer.toString();
+        }
+        LogRecord record = new LogRecord(Level.FINER, msg);
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        record.setParameters(params);
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -815,14 +821,16 @@
      *            the method name.
      */
     public void exiting(String sourceClass, String sourceMethod) {
-        if (internalIsLoggable(Level.FINER)) {
-            LogRecord record = new LogRecord(Level.FINER, "RETURN"); //$NON-NLS-1$
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(Level.FINER)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(Level.FINER, "RETURN"); //$NON-NLS-1$
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -838,15 +846,17 @@
      *            the return value of the method call.
      */
     public void exiting(String sourceClass, String sourceMethod, Object result) {
-        if (internalIsLoggable(Level.FINER)) {
-            LogRecord record = new LogRecord(Level.FINER, "RETURN" + " {0}"); //$NON-NLS-1$ //$NON-NLS-2$
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            record.setParameters(new Object[] { result });
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(Level.FINER)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(Level.FINER, "RETURN" + " {0}"); //$NON-NLS-1$ //$NON-NLS-2$
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        record.setParameters(new Object[] { result });
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -864,15 +874,17 @@
      */
     public void throwing(String sourceClass, String sourceMethod,
             Throwable thrown) {
-        if (internalIsLoggable(Level.FINER)) {
-            LogRecord record = new LogRecord(Level.FINER, "THROW"); //$NON-NLS-1$
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            record.setThrown(thrown);
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(Level.FINER)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(Level.FINER, "THROW"); //$NON-NLS-1$
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        record.setThrown(thrown);
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -883,12 +895,7 @@
      *            the message to log.
      */
     public void severe(String msg) {
-        if (internalIsLoggable(Level.SEVERE)) {
-            LogRecord record = new LogRecord(Level.SEVERE, msg);
-            record.setLoggerName(this.name);
-            setResourceBundle(record);
-            log(record);
-        }
+        log(Level.SEVERE, msg);
     }
 
     /**
@@ -899,12 +906,7 @@
      *            the message to log.
      */
     public void warning(String msg) {
-        if (internalIsLoggable(Level.WARNING)) {
-            LogRecord record = new LogRecord(Level.WARNING, msg);
-            record.setLoggerName(this.name);
-            setResourceBundle(record);
-            log(record);
-        }
+        log(Level.WARNING, msg);
     }
 
     /**
@@ -915,12 +917,7 @@
      *            the message to log.
      */
     public void info(String msg) {
-        if (internalIsLoggable(Level.INFO)) {
-            LogRecord record = new LogRecord(Level.INFO, msg);
-            record.setLoggerName(this.name);
-            setResourceBundle(record);
-            log(record);
-        }
+        log(Level.INFO, msg);
     }
 
     /**
@@ -931,12 +928,7 @@
      *            the message to log.
      */
     public void config(String msg) {
-        if (internalIsLoggable(Level.CONFIG)) {
-            LogRecord record = new LogRecord(Level.CONFIG, msg);
-            record.setLoggerName(this.name);
-            setResourceBundle(record);
-            log(record);
-        }
+        log(Level.CONFIG, msg);
     }
 
     /**
@@ -947,12 +939,7 @@
      *            the message to log.
      */
     public void fine(String msg) {
-        if (internalIsLoggable(Level.FINE)) {
-            LogRecord record = new LogRecord(Level.FINE, msg);
-            record.setLoggerName(this.name);
-            setResourceBundle(record);
-            log(record);
-        }
+        log(Level.FINE, msg);
     }
 
     /**
@@ -963,12 +950,7 @@
      *            the message to log.
      */
     public void finer(String msg) {
-        if (internalIsLoggable(Level.FINER)) {
-            LogRecord record = new LogRecord(Level.FINER, msg);
-            record.setLoggerName(this.name);
-            setResourceBundle(record);
-            log(record);
-        }
+        log(Level.FINER, msg);
     }
 
     /**
@@ -979,12 +961,7 @@
      *            the message to log.
      */
     public void finest(String msg) {
-        if (internalIsLoggable(Level.FINEST)) {
-            LogRecord record = new LogRecord(Level.FINEST, msg);
-            record.setLoggerName(this.name);
-            setResourceBundle(record);
-            log(record);
-        }
+        log(Level.FINEST, msg);
     }
 
     /**
@@ -997,12 +974,13 @@
      *            the message to log.
      */
     public void log(Level logLevel, String msg) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            record.setLoggerName(this.name);
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        // BEGIN android-only
+        dalvikLogHandler.publish(this, androidTag, logLevel, msg);
+        // END android-only
     }
 
     /**
@@ -1017,13 +995,15 @@
      *            the parameter associated with the event that is logged.
      */
     public void log(Level logLevel, String msg, Object param) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            record.setLoggerName(this.name);
-            record.setParameters(new Object[] { param });
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        record.setLoggerName(this.name);
+        record.setParameters(new Object[] { param });
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -1038,13 +1018,15 @@
      *            the parameter array associated with the event that is logged.
      */
     public void log(Level logLevel, String msg, Object[] params) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            record.setLoggerName(this.name);
-            record.setParameters(params);
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        record.setLoggerName(this.name);
+        record.setParameters(params);
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -1060,13 +1042,15 @@
      *            logged.
      */
     public void log(Level logLevel, String msg, Throwable thrown) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            record.setLoggerName(this.name);
-            record.setThrown(thrown);
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        record.setLoggerName(this.name);
+        record.setThrown(thrown);
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -1085,31 +1069,33 @@
      *            the log record to be logged.
      */
     public void log(LogRecord record) {
-        if (internalIsLoggable(record.getLevel())) {
-            // apply the filter if any
-            Filter f = filter;
-            if (null != f && !f.isLoggable(record)) {
-                return;
-            }
-            initHandler();
-            /*
-             * call the handlers of this logger, throw any exception that occurs
-             */
-            Handler[] allHandlers = getHandlers();
-            for (Handler element : allHandlers) {
+        if (!internalIsLoggable(record.getLevel())) {
+            return;
+        }
+
+        // apply the filter if any
+        Filter f = filter;
+        if (f != null && !f.isLoggable(record)) {
+            return;
+        }
+
+        /*
+         * call the handlers of this logger, throw any exception that occurs
+         */
+        Handler[] allHandlers = getHandlers();
+        for (Handler element : allHandlers) {
+            element.publish(record);
+        }
+        // call the parent's handlers if set useParentHandlers
+        Logger temp = this;
+        Logger theParent = temp.parent;
+        while (theParent != null && temp.getUseParentHandlers()) {
+            Handler[] ha = theParent.getHandlers();
+            for (Handler element : ha) {
                 element.publish(record);
             }
-            // call the parent's handlers if set useParentHandlers
-            Logger temp = this;
-            Logger theParent = temp.parent;
-            while (theParent != null && temp.getUseParentHandlers()) {
-                Handler[] ha = theParent.getHandlers();
-                for (Handler element : ha) {
-                    element.publish(record);
-                }
-                temp = theParent;
-                theParent = temp.parent;
-            }
+            temp = theParent;
+            theParent = temp.parent;
         }
     }
 
@@ -1128,14 +1114,16 @@
      */
     public void logp(Level logLevel, String sourceClass, String sourceMethod,
             String msg) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -1155,15 +1143,17 @@
      */
     public void logp(Level logLevel, String sourceClass, String sourceMethod,
             String msg, Object param) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            record.setParameters(new Object[] { param });
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        record.setParameters(new Object[] { param });
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -1183,15 +1173,17 @@
      */
     public void logp(Level logLevel, String sourceClass, String sourceMethod,
             String msg, Object[] params) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            record.setParameters(params);
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        record.setParameters(params);
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -1211,15 +1203,17 @@
      */
     public void logp(Level logLevel, String sourceClass, String sourceMethod,
             String msg, Throwable thrown) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            record.setThrown(thrown);
-            setResourceBundle(record);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        record.setThrown(thrown);
+        setResourceBundle(record);
+        log(record);
     }
 
     /**
@@ -1241,21 +1235,23 @@
      */
     public void logrb(Level logLevel, String sourceClass, String sourceMethod,
             String bundleName, String msg) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            if (null != bundleName) {
-                try {
-                    record.setResourceBundle(loadResourceBundle(bundleName));
-                } catch (MissingResourceException e) {
-                    // ignore
-                }
-                record.setResourceBundleName(bundleName);
-            }
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        if (bundleName != null) {
+            try {
+                record.setResourceBundle(loadResourceBundle(bundleName));
+            } catch (MissingResourceException e) {
+                // ignore
+            }
+            record.setResourceBundleName(bundleName);
+        }
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        log(record);
     }
 
     /**
@@ -1279,22 +1275,24 @@
      */
     public void logrb(Level logLevel, String sourceClass, String sourceMethod,
             String bundleName, String msg, Object param) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            if (null != bundleName) {
-                try {
-                    record.setResourceBundle(loadResourceBundle(bundleName));
-                } catch (MissingResourceException e) {
-                    // ignore
-                }
-                record.setResourceBundleName(bundleName);
-            }
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            record.setParameters(new Object[] { param });
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        if (bundleName != null) {
+            try {
+                record.setResourceBundle(loadResourceBundle(bundleName));
+            } catch (MissingResourceException e) {
+                // ignore
+            }
+            record.setResourceBundleName(bundleName);
+        }
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        record.setParameters(new Object[] { param });
+        log(record);
     }
 
     /**
@@ -1318,22 +1316,24 @@
      */
     public void logrb(Level logLevel, String sourceClass, String sourceMethod,
             String bundleName, String msg, Object[] params) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            if (null != bundleName) {
-                try {
-                    record.setResourceBundle(loadResourceBundle(bundleName));
-                } catch (MissingResourceException e) {
-                    // ignore
-                }
-                record.setResourceBundleName(bundleName);
-            }
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            record.setParameters(params);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        if (bundleName != null) {
+            try {
+                record.setResourceBundle(loadResourceBundle(bundleName));
+            } catch (MissingResourceException e) {
+                // ignore
+            }
+            record.setResourceBundleName(bundleName);
+        }
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        record.setParameters(params);
+        log(record);
     }
 
     /**
@@ -1357,22 +1357,24 @@
      */
     public void logrb(Level logLevel, String sourceClass, String sourceMethod,
             String bundleName, String msg, Throwable thrown) {
-        if (internalIsLoggable(logLevel)) {
-            LogRecord record = new LogRecord(logLevel, msg);
-            if (null != bundleName) {
-                try {
-                    record.setResourceBundle(loadResourceBundle(bundleName));
-                } catch (MissingResourceException e) {
-                    // ignore
-                }
-                record.setResourceBundleName(bundleName);
-            }
-            record.setLoggerName(this.name);
-            record.setSourceClassName(sourceClass);
-            record.setSourceMethodName(sourceMethod);
-            record.setThrown(thrown);
-            log(record);
+        if (!internalIsLoggable(logLevel)) {
+            return;
         }
+
+        LogRecord record = new LogRecord(logLevel, msg);
+        if (bundleName != null) {
+            try {
+                record.setResourceBundle(loadResourceBundle(bundleName));
+            } catch (MissingResourceException e) {
+                // ignore
+            }
+            record.setResourceBundleName(bundleName);
+        }
+        record.setLoggerName(this.name);
+        record.setSourceClassName(sourceClass);
+        record.setSourceMethodName(sourceMethod);
+        record.setThrown(thrown);
+        log(record);
     }
 
     /*
@@ -1384,42 +1386,19 @@
         }
     }
 
-    void setManager(LogManager manager) {
-        if (this.manager != manager) {
-            this.manager = manager;
-            handlerInited = false;
-        }
-        // init level here, but let handlers be for lazy loading
-        final String configedLevel = manager.getProperty(name + ".level"); //$NON-NLS-1$
-        if (null != configedLevel) {
-            try {
-                AccessController.doPrivileged(new PrivilegedAction<Object>() {
-                    public Object run() {
-                        setLevel(Level.parse(configedLevel));
-                        return null;
-                    }
-                });
-            } catch (IllegalArgumentException e) {
-                // ignore
-            }
-        }
-    }
-
-    synchronized void reset() {
+    void reset() {
         levelObjVal = null;
         levelIntVal = Level.INFO.intValue();
-        if (handlers != null) {
-            for (Handler element : handlers) {
-                // close all handlers, when unknown exceptions happen,
-                // ignore them and go on
-                try {
-                    element.close();
-                } catch (Exception e) {
-                    // Ignored.
+
+        for (Handler handler : handlers) {
+            try {
+                if (handlers.remove(handler)) {
+                    handler.close();
                 }
+            } catch (Exception ignored) {
             }
-            handlers.clear();
         }
-        handlerInited = false;
+
+        updateDalvikLogHandler(); // android-only
     }
 }
diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FileHandlerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FileHandlerTest.java
index 3ff1fc9..e4ef413 100644
--- a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FileHandlerTest.java
+++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/FileHandlerTest.java
@@ -50,6 +50,7 @@
 
 import org.apache.harmony.logging.tests.java.util.logging.HandlerTest.NullOutputStream;
 import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper;
+import tests.util.TestEnvironment;
 
 /**
  */
@@ -62,18 +63,11 @@
 
     final static String className = FileHandlerTest.class.getName();
 
-    final static StringWriter writer = new StringWriter();
-
-    final static SecurityManager securityManager = new MockLogSecurityManager();
-
     final static String SEP = File.separator;
 
-    private String oldHomePath = System.getProperty("user.home");
-    
-    // The HOMEPATH can't be used in android.
-    final static String HOMEPATH = System.getProperty("java.io.tmpdir") + SEP + "home";
+    String HOMEPATH;
 
-    final static String TEMPPATH = System.getProperty("java.io.tmpdir");
+    String TEMPPATH;
 
     private final PrintStream err = System.err;
 
@@ -88,6 +82,7 @@
      */
     protected void setUp() throws Exception {
         super.setUp();
+        TestEnvironment.reset();
         manager.reset();
         
         //initProp
@@ -106,19 +101,10 @@
         props.put("java.util.logging.FileHandler.append", "true");
         props.put("java.util.logging.FileHandler.pattern",
                         "%t/log/java%u.test");
-        
-        File home = new File(HOMEPATH);
-        if (!home.exists()) {
-            home.mkdirs();
-        } else if (!home.isDirectory()) {
-            home.delete();
-            home.mkdirs();
-        }
-        if(!home.isDirectory()) {
-            fail("unable to create temp path");
-        }
-        System.setProperty("user.home", HOMEPATH);
-        
+
+        HOMEPATH = System.getProperty("user.home");
+        TEMPPATH = System.getProperty("java.io.tmpdir");
+
         File file = new File(TEMPPATH + SEP + "log");
         file.mkdir();
         manager.readConfiguration(EnvironmentHelper
@@ -140,8 +126,7 @@
         }
         reset(TEMPPATH + SEP + "log", "");
         System.setErr(err);
-        System.setProperty("user.home", oldHomePath);
-        new File(HOMEPATH).delete();
+        TestEnvironment.reset();
         super.tearDown();
     }
 
@@ -634,8 +619,6 @@
         assertFileContent(TEMPPATH, "testLimitCount0.0",
                 new LogRecord[] { rs[9] }, handler.getFormatter());
 
-        String oldUserDir = System.getProperty("user.dir");
-        System.setProperty("user.dir", System.getProperty("java.io.tmpdir"));
         FileHandler h1 = null;
         FileHandler h2 = null;
         try {
@@ -656,7 +639,6 @@
             } catch (Exception e) {
             }
             reset("log", "");
-            System.setProperty("user.dir", oldUserDir);
         }
     }
     @TestTargets({
@@ -1000,14 +982,6 @@
             fail("should throw IllegalArgumentException");
         } catch (IllegalArgumentException e) {
         }
-        
-        // always parse special pattern
-        System.setProperty("user.home", "home");
-        try {
-            h1 = new FileHandler("%t/%h.txt");
-        } catch (Exception e) {
-            fail("Unexpected exception " + e.toString());
-        }
     }
 
     /*
diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogManagerTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogManagerTest.java
index cf608bc..3083dc9 100644
--- a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogManagerTest.java
+++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogManagerTest.java
@@ -45,6 +45,7 @@
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
+import tests.util.TestEnvironment;
 
 /**
  * 
@@ -107,6 +108,7 @@
      */
     @Override
     protected void tearDown() throws Exception {
+        TestEnvironment.reset();
         super.tearDown();
         handler = null;
     }
@@ -835,6 +837,16 @@
         assertNull(m.getProperty("java.util.logging.FileHandler.pattern"));
     }
 
+    public void testReadConfiguration() throws SecurityException,
+            IOException {
+
+        MockConfigLogManager lm = new MockConfigLogManager();
+        assertFalse(lm.isCalled);
+
+        lm.readConfiguration();
+        assertTrue(lm.isCalled);
+    }
+
     private static void checkProperty(LogManager m) {
         // assertEquals(m.getProperty(".level"), "INFO");
         assertEquals(m.getProperty("java.util.logging.FileHandler.limit"), "50000");
@@ -1194,24 +1206,17 @@
         args = {}
     )
     public void testValidConfigClass() throws Exception {
-        String oldProperty = System.getProperty("java.util.logging.config.class");
-        try {
-            //            System.setProperty("java.util.logging.config.class", "org.apache.harmony.logging.tests.java.util.logging.LogManagerTest$ConfigClass");
-            System.setProperty("java.util.logging.config.class", this.getClass().getName()
-                    + "$ConfigClass");
-            assertNull(manager.getLogger("testConfigClass.foo"));
+        //            System.setProperty("java.util.logging.config.class", "org.apache.harmony.logging.tests.java.util.logging.LogManagerTest$ConfigClass");
+        System.setProperty("java.util.logging.config.class", this.getClass().getName()
+                + "$ConfigClass");
+        assertNull(manager.getLogger("testConfigClass.foo"));
 
-            manager.readConfiguration();
-            assertNull(manager.getLogger("testConfigClass.foo"));
-            Logger l = Logger.getLogger("testConfigClass.foo.child");
-            assertSame(Level.FINEST, manager.getLogger("").getLevel());
-            assertEquals(0, manager.getLogger("").getHandlers().length);
-            assertEquals("testConfigClass.foo", l.getParent().getName());
-        } finally {
-            if (oldProperty != null) {
-                System.setProperty("java.util.logging.config.class", oldProperty);
-            }
-        }
+        manager.readConfiguration();
+        assertNull(manager.getLogger("testConfigClass.foo"));
+        Logger l = Logger.getLogger("testConfigClass.foo.child");
+        assertSame(Level.FINEST, manager.getLogger("").getLevel());
+        assertEquals(0, manager.getLogger("").getHandlers().length);
+        assertEquals("testConfigClass.foo", l.getParent().getName());
     }
 
     /*
@@ -1368,6 +1373,15 @@
     public static class MockLogManager extends LogManager {
     }
 
+	public static class MockConfigLogManager extends LogManager {
+        public boolean isCalled = false;
+
+        public void readConfiguration(InputStream ins) throws IOException {
+            isCalled = true;
+            super.readConfiguration(ins);
+        }
+    }
+
     public static class MockHandler extends Handler {
         static int number = 0;
 
diff --git a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogRecordTest.java b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogRecordTest.java
index 5b21099..6d4f784 100644
--- a/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogRecordTest.java
+++ b/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LogRecordTest.java
@@ -295,7 +295,7 @@
         assertNull(lr.getSourceClassName());
 
         // find class and method who called logger
-        Logger logger = Logger.global;
+        Logger logger = Logger.getLogger("testGetSourceDefaultValue");
         MockHandler handler = new MockHandler();
         logger.addHandler(handler);
         logger.log(Level.SEVERE, MSG);
diff --git a/luni-kernel/src/main/java/java/lang/Package.java b/luni-kernel/src/main/java/java/lang/Package.java
index 2817404..4d98959 100644
--- a/luni-kernel/src/main/java/java/lang/Package.java
+++ b/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/luni-kernel/src/main/java/java/lang/ProcessManager.java b/luni-kernel/src/main/java/java/lang/ProcessManager.java
index 1e21b57..318fe9a 100644
--- a/luni-kernel/src/main/java/java/lang/ProcessManager.java
+++ b/luni-kernel/src/main/java/java/lang/ProcessManager.java
@@ -169,15 +169,45 @@
      * Executes a native process. Fills in in, out, and err and returns the
      * new process ID upon success.
      */
-    static native int exec(String[] commands, String[] environment,
+    static native int exec(String[] command, String[] environment,
             String workingDirectory, FileDescriptor in, FileDescriptor out,
-            FileDescriptor err) throws IOException;
+            FileDescriptor err, boolean redirectErrorStream) throws IOException;
 
     /**
      * Executes a process and returns an object representing it.
      */
-    Process exec(String[] commands, String[] environment,
-            File workingDirectory) throws IOException {
+    Process exec(String[] taintedCommand, String[] taintedEnvironment, File workingDirectory,
+            boolean redirectErrorStream) throws IOException {
+        // Make sure we throw the same exceptions as the RI.
+        if (taintedCommand == null) {
+            throw new NullPointerException();
+        }
+        if (taintedCommand.length == 0) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        // Handle security and safety by copying mutable inputs and checking them.
+        String[] command = taintedCommand.clone();
+        String[] environment = taintedEnvironment != null ? taintedEnvironment.clone() : null;
+        SecurityManager securityManager = System.getSecurityManager();
+        if (securityManager != null) {
+            securityManager.checkExec(command[0]);
+        }
+        // Check we're not passing null Strings to the native exec.
+        for (String arg : command) {
+            if (arg == null) {
+                throw new NullPointerException();
+            }
+        }
+        // The environment is allowed to be null or empty, but no element may be null.
+        if (environment != null) {
+            for (String env : environment) {
+                if (env == null) {
+                    throw new NullPointerException();
+                }
+            }
+        }
+
         FileDescriptor in = new FileDescriptor();
         FileDescriptor out = new FileDescriptor();
         FileDescriptor err = new FileDescriptor();
@@ -191,10 +221,10 @@
         synchronized (processReferences) {
             int pid;
             try {
-                pid = exec(commands, environment, workingPath, in, out, err);
+                pid = exec(command, environment, workingPath, in, out, err, redirectErrorStream);
             } catch (IOException e) {
                 IOException wrapper = new IOException("Error running exec()." 
-                        + " Commands: " + Arrays.toString(commands)
+                        + " Command: " + Arrays.toString(command)
                         + " Working Directory: " + workingDirectory
                         + " Environment: " + Arrays.toString(environment));
                 wrapper.initCause(e);
diff --git a/luni-kernel/src/main/java/java/lang/Runtime.java b/luni-kernel/src/main/java/java/lang/Runtime.java
index 28cc96f..8560399 100644
--- a/luni-kernel/src/main/java/java/lang/Runtime.java
+++ b/luni-kernel/src/main/java/java/lang/Runtime.java
@@ -190,39 +190,11 @@
      *             execution.
      * @see SecurityManager#checkExec
      * @since Android 1.0
-     */    
-    public Process exec(String[] progArray, String[] envp, File directory)
-            throws java.io.IOException {
-        
-        // Sanity checks
-        if (progArray == null) {
-            throw new NullPointerException();
-        } else if (progArray.length == 0) {
-            throw new IndexOutOfBoundsException();
-        } else {
-            for (int i = 0; i < progArray.length; i++) {
-                if (progArray[i] == null) {
-                    throw new NullPointerException();
-                }
-            }
-        }
-        
-        if (envp != null) {
-            for (int i = 0; i < envp.length; i++) {
-                if (envp[i] == null) {
-                    throw new NullPointerException();
-                }
-            }
-        }
-        
-        // Security checks
-        SecurityManager smgr = System.getSecurityManager();
-        if (smgr != null) {
-            smgr.checkExec(progArray[0]);
-        }
-        
-        // Delegate the execution
-        return ProcessManager.getInstance().exec(progArray, envp, directory);
+     */
+    public Process exec(String[] progArray, String[] envp, File directory) throws IOException {
+        // BEGIN android-changed: push responsibility for argument checking into ProcessManager
+        return ProcessManager.getInstance().exec(progArray, envp, directory, false);
+        // END android-changed
     }
 
     /**
diff --git a/luni-kernel/src/main/java/java/lang/ref/Reference.java b/luni-kernel/src/main/java/java/lang/ref/Reference.java
index ca7290b..c695830 100644
--- a/luni-kernel/src/main/java/java/lang/ref/Reference.java
+++ b/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/luni-kernel/src/main/java/java/lang/reflect/Constructor.java b/luni-kernel/src/main/java/java/lang/reflect/Constructor.java
index c6927eb..3918d7e 100644
--- a/luni-kernel/src/main/java/java/lang/reflect/Constructor.java
+++ b/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/luni-kernel/src/main/java/java/lang/reflect/Method.java b/luni-kernel/src/main/java/java/lang/reflect/Method.java
index 473726d..dabf9a4 100644
--- a/luni-kernel/src/main/java/java/lang/reflect/Method.java
+++ b/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/luni-kernel/src/main/native/java_lang_ProcessManager.c b/luni-kernel/src/main/native/java_lang_ProcessManager.cpp
similarity index 81%
rename from luni-kernel/src/main/native/java_lang_ProcessManager.c
rename to luni-kernel/src/main/native/java_lang_ProcessManager.cpp
index eaefc9f..045d980 100644
--- a/luni-kernel/src/main/native/java_lang_ProcessManager.c
+++ b/luni-kernel/src/main/native/java_lang_ProcessManager.cpp
@@ -51,21 +51,11 @@
 #define WAIT_STATUS_STRANGE_ERRNO (-3) // observed an undocumented errno
 
 /** Closes a file descriptor. */
-static int closeNow(int fd) {
-    int result;
-    do {
-        result = close(fd);
-    } while (result == -1 && errno == EINTR);
-    return result;
-}
-
-/** Closes a file descriptor. */
 static void java_lang_ProcessManager_close(JNIEnv* env,
-        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));
+        jclass, jobject javaDescriptor) {
+    int fd = env->GetIntField(javaDescriptor, descriptorField);
+    if (TEMP_FAILURE_RETRY(close(fd)) == -1) {
+        jniThrowIOException(env, errno);
     }
 }
 
@@ -144,9 +134,8 @@
             }
         }
 
-        (*env)->CallVoidMethod(env, o, onExitMethod, pid, status);
-
-        if ((*env)->ExceptionOccurred(env)) {
+        env->CallVoidMethod(o, onExitMethod, pid, status);
+        if (env->ExceptionOccurred()) {
             /*
              * The callback threw, so break out of the loop and return,
              * letting the exception percolate up.
@@ -158,11 +147,11 @@
 
 /** Close all open fds > 2 (i.e. everything but stdin/out/err), != skipFd. */
 static void closeNonStandardFds(int skipFd) {
+    // TODO: rather than close all these non-open files, we could look in /proc/self/fd.
     struct rlimit rlimit;
     getrlimit(RLIMIT_NOFILE, &rlimit);
-
-    int fd;
-    for (fd = 3; fd < rlimit.rlim_max; fd++) {
+    const int max_fd = rlimit.rlim_max;
+    for (int fd = 3; fd < max_fd; ++fd) {
         if (fd != skipFd
 #ifdef ANDROID
                 && fd != androidSystemPropertiesFd
@@ -192,7 +181,8 @@
 /** Executes a command in a child process. */
 static pid_t executeProcess(JNIEnv* env, char** commands, char** environment,
         const char* workingDirectory, jobject inDescriptor,
-        jobject outDescriptor, jobject errDescriptor) {
+        jobject outDescriptor, jobject errDescriptor,
+        jboolean redirectErrorStream) {
     int i, result, error;
 
     // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe.
@@ -233,7 +223,11 @@
         // Replace stdin, out, and err with pipes.
         dup2(stdinIn, 0);
         dup2(stdoutOut, 1);
-        dup2(stderrOut, 2);
+        if (redirectErrorStream) {
+            dup2(stdoutOut, 2);
+        } else {
+            dup2(stderrOut, 2);
+        }
 
         // Close all but statusOut. This saves some work in the next step.
         closePipes(pipes, statusOut);
@@ -307,15 +301,14 @@
     }
 
     char** array = NULL;
-    jsize length = (*env)->GetArrayLength(env, javaArray);
+    jsize length = env->GetArrayLength(javaArray);
     array = (char**) malloc(sizeof(char*) * (length + 1));
     array[length] = 0;
     jsize index;
     for (index = 0; index < length; index++) {
-        jstring javaEntry = (jstring) (*env)->GetObjectArrayElement(
-                env, javaArray, index);
-        char* entry = (char*) (*env)->GetStringUTFChars(
-                env, javaEntry, NULL);
+        jstring javaEntry =
+                (jstring) env->GetObjectArrayElement(javaArray, index);
+        char* entry = (char*) env->GetStringUTFChars(javaEntry, NULL);
         array[index] = entry;
     }
 
@@ -328,12 +321,12 @@
         return;
     }
 
-    jsize length = (*env)->GetArrayLength(env, javaArray);
+    jsize length = env->GetArrayLength(javaArray);
     jsize index;
     for (index = 0; index < length; index++) {
-        jstring javaEntry = (jstring) (*env)->GetObjectArrayElement(
-                env, javaArray, index);
-        (*env)->ReleaseStringUTFChars(env, javaEntry, array[index]);
+        jstring javaEntry =
+                (jstring) env->GetObjectArrayElement(javaArray, index);
+        env->ReleaseStringUTFChars(javaEntry, array[index]);
     }
 
     free(array);
@@ -345,7 +338,8 @@
 static pid_t java_lang_ProcessManager_exec(
         JNIEnv* env, jclass clazz, jobjectArray javaCommands,
         jobjectArray javaEnvironment, jstring javaWorkingDirectory,
-        jobject inDescriptor, jobject outDescriptor, jobject errDescriptor) {
+        jobject inDescriptor, jobject outDescriptor, jobject errDescriptor,
+        jboolean redirectErrorStream) {
 
     // Copy commands into char*[].
     char** commands = convertStrings(env, javaCommands);
@@ -353,8 +347,7 @@
     // Extract working directory string.
     const char* workingDirectory = NULL;
     if (javaWorkingDirectory != NULL) {
-        workingDirectory = (const char*) (*env)->GetStringUTFChars(
-                env, javaWorkingDirectory, NULL);
+        workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL);
     }
 
     // Convert environment array.
@@ -362,25 +355,24 @@
 
     pid_t result = executeProcess(
             env, commands, environment, workingDirectory, 
-            inDescriptor, outDescriptor, errDescriptor);
+            inDescriptor, outDescriptor, errDescriptor, redirectErrorStream);
 
     // Temporarily clear exception so we can clean up.
-    jthrowable exception = (*env)->ExceptionOccurred(env);
-    (*env)->ExceptionClear(env);
+    jthrowable exception = env->ExceptionOccurred();
+    env->ExceptionClear();
 
     freeStrings(env, javaEnvironment, environment);
 
     // Clean up working directory string.
     if (javaWorkingDirectory != NULL) {
-        (*env)->ReleaseStringUTFChars(
-                env, javaWorkingDirectory, workingDirectory);
+        env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory);
     }
 
     freeStrings(env, javaCommands, commands);
 
     // Re-throw exception if present.
     if (exception != NULL) {
-        if ((*env)->Throw(env, exception) < 0) {
+        if (env->Throw(exception) < 0) {
             LOGE("Error rethrowing exception!");
         }
     }
@@ -400,33 +392,28 @@
     }
 #endif
 
-    onExitMethod = (*env)->GetMethodID(env, clazz, "onExit", "(II)V");
+    onExitMethod = env->GetMethodID(clazz, "onExit", "(II)V");
     if (onExitMethod == NULL) {
         return;
     }
 
-    jclass fileDescriptorClass
-            = (*env)->FindClass(env, "java/io/FileDescriptor");
+    jclass fileDescriptorClass = env->FindClass("java/io/FileDescriptor");
     if (fileDescriptorClass == NULL) {
         return;
     }
-    descriptorField = (*env)->GetFieldID(env, fileDescriptorClass,
-            "descriptor", "I");
+    descriptorField = env->GetFieldID(fileDescriptorClass, "descriptor", "I");
     if (descriptorField == NULL) {
         return;
     }
 }
 
 static JNINativeMethod methods[] = {
-    { "kill", "(I)V", (void*) java_lang_ProcessManager_kill },
-    { "watchChildren", "()V", (void*) java_lang_ProcessManager_watchChildren },
-    { "exec", "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;"
-        "Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
-        "Ljava/io/FileDescriptor;)I", (void*) java_lang_ProcessManager_exec },
-    { "staticInitialize", "()V",
-        (void*) java_lang_ProcessManager_staticInitialize },
-    { "close", "(Ljava/io/FileDescriptor;)V",
-        (void*) java_lang_ProcessManager_close },
+    { "close",            "(Ljava/io/FileDescriptor;)V", (void*) java_lang_ProcessManager_close },
+    { "kill",             "(I)V",                        (void*) java_lang_ProcessManager_kill },
+    { "staticInitialize", "()V",                         (void*) java_lang_ProcessManager_staticInitialize },
+    { "watchChildren",    "()V",                         (void*) java_lang_ProcessManager_watchChildren },
+    { "exec",             "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Z)I",
+                                                         (void*) java_lang_ProcessManager_exec },
 };
 
 int register_java_lang_ProcessManager(JNIEnv* env) {
diff --git a/luni-kernel/src/main/native/java_lang_System.c b/luni-kernel/src/main/native/java_lang_System.c
deleted file mode 100644
index 1c06a40..0000000
--- a/luni-kernel/src/main/native/java_lang_System.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "JNIHelp.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-
-/*
- * public static native String getEnvByName(String name)
- *
- * (Calling it plain "getenv" might confuse GDB if you try to put a breakpoint
- * on the libc version.)
- */
-static jstring java_getEnvByName(JNIEnv* env, jclass clazz, jstring nameStr)
-{
-    jstring valueStr = NULL;
-
-    if (nameStr != NULL) {
-        const char* name;
-        const char* val;
-
-        name = (*env)->GetStringUTFChars(env, nameStr, NULL);
-        val = getenv(name);
-        if (val != NULL)
-            valueStr = (*env)->NewStringUTF(env, val);
-
-        (*env)->ReleaseStringUTFChars(env, nameStr, name);
-    } else {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
-    }
-
-    return valueStr;
-}
-
-/*
- * Pointer to complete environment, from Posix.
- */
-extern char** environ;
-
-/*
- * public static native String getEnvByIndex()
- *
- * (Calling it plain "getenv" might confuse GDB if you try to put a breakpoint
- * on the libc version.)
- */
-static jstring java_getEnvByIndex(JNIEnv* env, jclass clazz, jint index)
-{
-    jstring valueStr = NULL;
-
-    char* entry = environ[index];
-    if (entry != NULL) {
-        valueStr = (*env)->NewStringUTF(env, entry);
-    }
-
-    return valueStr;
-}
-
-/*
- * public static native String setFieldImpl()
- *
- * Sets a field via JNI. Used for the standard streams, which are r/o
- * otherwise.
- */
-static void java_setFieldImpl(JNIEnv* env, jclass clazz, jstring name, jstring sig, jobject object)
-{
-    const char* fieldName = (*env)->GetStringUTFChars(env, name, NULL);
-    const char* fieldSig = (*env)->GetStringUTFChars(env, sig, NULL);
-
-    jfieldID fieldID = (*env)->GetStaticFieldID(env, clazz, fieldName, fieldSig);
-    (*env)->SetStaticObjectField(env, clazz, fieldID, object);
-    
-    (*env)->ReleaseStringUTFChars(env, name, fieldName);
-    (*env)->ReleaseStringUTFChars(env, sig, fieldSig);
-}
-
-/*
- * JNI registration
- */
-static JNINativeMethod gMethods[] = {
-    /* name, signature, funcPtr */
-    { "getEnvByName",   "(Ljava/lang/String;)Ljava/lang/String;",  java_getEnvByName  },
-    { "getEnvByIndex",  "(I)Ljava/lang/String;",                   java_getEnvByIndex },
-    { "setFieldImpl",   "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V", java_setFieldImpl  },
-};
-
-int register_java_lang_System(JNIEnv* env)
-{
-	return jniRegisterNativeMethods(env, "java/lang/System",
-                gMethods, NELEM(gMethods));
-}
-
diff --git a/luni-kernel/src/main/native/java_lang_System.cpp b/luni-kernel/src/main/native/java_lang_System.cpp
new file mode 100644
index 0000000..d02481c
--- /dev/null
+++ b/luni-kernel/src/main/native/java_lang_System.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AndroidSystemNatives.h"
+#include "JNIHelp.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+/*
+ * public static native String getEnvByName(String name)
+ *
+ * (Calling it plain "getenv" might confuse GDB if you try to put a breakpoint
+ * on the libc version.)
+ */
+static jstring java_getEnvByName(JNIEnv* env, jclass, jstring nameStr) {
+    jstring valueStr = NULL;
+
+    if (nameStr != NULL) {
+        const char* name = env->GetStringUTFChars(nameStr, NULL);
+        const char* val = getenv(name);
+        if (val != NULL) {
+            valueStr = env->NewStringUTF(val);
+        }
+        env->ReleaseStringUTFChars(nameStr, name);
+    } else {
+        jniThrowException(env, "java/lang/NullPointerException", NULL);
+    }
+
+    return valueStr;
+}
+
+/*
+ * Pointer to complete environment, from Posix.
+ */
+extern char** environ;
+
+/*
+ * public static native String getEnvByIndex()
+ *
+ * (Calling it plain "getenv" might confuse GDB if you try to put a breakpoint
+ * on the libc version.)
+ */
+static jstring java_getEnvByIndex(JNIEnv* env, jclass, jint index) {
+    jstring valueStr = NULL;
+
+    char* entry = environ[index];
+    if (entry != NULL) {
+        valueStr = env->NewStringUTF(entry);
+    }
+
+    return valueStr;
+}
+
+/*
+ * public static native String setFieldImpl()
+ *
+ * Sets a field via JNI. Used for the standard streams, which are r/o
+ * otherwise.
+ */
+static void java_setFieldImpl(JNIEnv* env, jclass clazz,
+        jstring name, jstring sig, jobject object) {
+    const char* fieldName = env->GetStringUTFChars(name, NULL);
+    const char* fieldSig = env->GetStringUTFChars(sig, NULL);
+
+    jfieldID fieldID = env->GetStaticFieldID(clazz, fieldName, fieldSig);
+    env->SetStaticObjectField(clazz, fieldID, object);
+    
+    env->ReleaseStringUTFChars(name, fieldName);
+    env->ReleaseStringUTFChars(sig, fieldSig);
+}
+
+/*
+ * JNI registration
+ */
+static JNINativeMethod gMethods[] = {
+    /* name, signature, funcPtr */
+    { "getEnvByName",   "(Ljava/lang/String;)Ljava/lang/String;",                    (void*) java_getEnvByName  },
+    { "getEnvByIndex",  "(I)Ljava/lang/String;",                                     (void*) java_getEnvByIndex },
+    { "setFieldImpl",   "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V", (void*) java_setFieldImpl },
+};
+
+int register_java_lang_System(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "java/lang/System",
+            gMethods, NELEM(gMethods));
+}
diff --git a/luni-kernel/src/main/native/sub.mk b/luni-kernel/src/main/native/sub.mk
index cd4ce92..fcb7d0d 100644
--- a/luni-kernel/src/main/native/sub.mk
+++ b/luni-kernel/src/main/native/sub.mk
@@ -3,8 +3,8 @@
 # or BUILD_*_LIBRARY.
 
 LOCAL_SRC_FILES := \
-	java_lang_ProcessManager.c \
-	java_lang_System.c
+	java_lang_ProcessManager.cpp \
+	java_lang_System.cpp
 
 LOCAL_C_INCLUDES +=
 
diff --git a/luni-kernel/src/test/java/java/lang/reflect/AllTests.java b/luni-kernel/src/test/java/java/lang/reflect/AllTests.java
new file mode 100644
index 0000000..7cf1475
--- /dev/null
+++ b/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/luni-kernel/src/test/java/java/lang/reflect/ConstructorTest.java b/luni-kernel/src/test/java/java/lang/reflect/ConstructorTest.java
new file mode 100644
index 0000000..e2672a8
--- /dev/null
+++ b/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/luni-kernel/src/test/java/java/lang/reflect/MethodTest.java b/luni-kernel/src/test/java/java/lang/reflect/MethodTest.java
new file mode 100644
index 0000000..ed41de9
--- /dev/null
+++ b/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/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/AllTests.java b/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/AllTests.java
new file mode 100644
index 0000000..a59cc3e
--- /dev/null
+++ b/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/luni/src/main/java/java/io/BufferedOutputStream.java b/luni/src/main/java/java/io/BufferedOutputStream.java
index 6d52dee..8b7c4f5 100644
--- a/luni/src/main/java/java/io/BufferedOutputStream.java
+++ b/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/luni/src/main/java/java/io/BufferedReader.java b/luni/src/main/java/java/io/BufferedReader.java
index 77f1975..cfdc4aa 100644
--- a/luni/src/main/java/java/io/BufferedReader.java
+++ b/luni/src/main/java/java/io/BufferedReader.java
@@ -17,6 +17,11 @@
 
 package java.io;
 
+// BEGIN android-note
+// lots of tidying up of implementation, including renaming fields and changing
+// the implementation of read(char[], int, int)
+// END android-note
+
 import org.apache.harmony.luni.util.Msg;
 
 // BEGIN android-added
@@ -44,16 +49,36 @@
 
     private Reader in;
 
+    /**
+     * The characters that can be read and refilled in bulk. We maintain three
+     * indices into this buffer:<pre>
+     *     { X X X X X X X X X X X X - - }
+     *           ^     ^             ^
+     *           |     |             |
+     *         mark   pos           end</pre>
+     * Pos points to the next readable character. End is one greater than the
+     * last readable character. When {@code pos == end}, the buffer is empty and
+     * must be {@link #fillBuf() filled} before characters can be read.
+     *
+     * <p>Mark is the value pos will be set to on calls to {@link #reset}. Its
+     * value is in the range {@code [0...pos]}. If the mark is {@code -1}, the
+     * buffer cannot be reset.
+     *
+     * <p>MarkLimit limits the distance between the mark and the pos. When this
+     * limit is exceeded, {@link #reset} is permitted (but not required) to
+     * throw an exception. For shorter distances, {@link #reset} shall not throw
+     * (unless the reader is closed).
+     */
     private char[] buf;
 
-    private int marklimit = -1;
-
-    private int count;
-
-    private int markpos = -1;
-
     private int pos;
 
+    private int end;
+
+    private int mark = -1;
+
+    private int markLimit = -1;
+
     /**
      * Constructs a new BufferedReader on the Reader {@code in}. The
      * buffer gets the default size (8 KB).
@@ -66,7 +91,7 @@
         this.in = in;
         buf = new char[8192];
 
-        // BEGIN android-added
+        // BEGIN android-only
         /*
          * For Android, we want to discourage the use of this
          * constructor (with its arguably too-large default), so we
@@ -79,7 +104,7 @@
                 "Default buffer size used in BufferedReader " +
                 "constructor. It would be " +
                 "better to be explicit if an 8k-char buffer is required.");
-        // END android-added
+        // END android-only
     }
 
     /**
@@ -120,36 +145,50 @@
         }
     }
 
-    private int fillbuf() throws IOException {
-        if (markpos == -1 || (pos - markpos >= marklimit)) {
-            /* Mark position not set or exceeded readlimit */
+    /**
+     * Populates the buffer with data. It is an error to call this method when
+     * the buffer still contains data; ie. if {@code pos < end}.
+     *
+     * @return the number of bytes read into the buffer, or -1 if the end of the
+     *      source stream has been reached.
+     */
+    private int fillBuf() throws IOException {
+        // assert(pos == end);
+
+        if (mark == -1 || (pos - mark >= markLimit)) {
+            /* mark isn't set or has exceeded its limit. use the whole buffer */
             int result = in.read(buf, 0, buf.length);
             if (result > 0) {
-                markpos = -1;
+                mark = -1;
                 pos = 0;
-                count = result == -1 ? 0 : result;
+                end = result;
             }
             return result;
         }
-        if (markpos == 0 && marklimit > buf.length) {
-            /* Increase buffer size to accommodate the readlimit */
+
+        if (mark == 0 && markLimit > buf.length) {
+            /* the only way to make room when mark=0 is by growing the buffer */
             int newLength = buf.length * 2;
-            if (newLength > marklimit) {
-                newLength = marklimit;
+            if (newLength > markLimit) {
+                newLength = markLimit;
             }
             char[] newbuf = new char[newLength];
             System.arraycopy(buf, 0, newbuf, 0, buf.length);
             buf = newbuf;
-        } else if (markpos > 0) {
-            System.arraycopy(buf, markpos, buf, 0, buf.length - markpos);
+        } else if (mark > 0) {
+            /* make room by shifting the buffered data to left mark positions */
+            System.arraycopy(buf, mark, buf, 0, buf.length - mark);
+            pos -= mark;
+            end -= mark;
+            mark = 0;
         }
 
         /* Set the new position and mark position */
-        pos -= markpos;
-        count = markpos = 0;
-        int charsread = in.read(buf, pos, buf.length - pos);
-        count = charsread == -1 ? pos : pos + charsread;
-        return charsread;
+        int count = in.read(buf, pos, buf.length - pos);
+        if (count != -1) {
+            end += count;
+        }
+        return count;
     }
 
     /**
@@ -163,32 +202,32 @@
     }
 
     /**
-     * Sets a mark position in this reader. The parameter {@code readlimit}
+     * Sets a mark position in this reader. The parameter {@code markLimit}
      * indicates how many characters can be read before the mark is invalidated.
      * Calling {@code reset()} will reposition the reader back to the marked
-     * position if {@code readlimit} has not been surpassed.
+     * position if {@code markLimit} has not been surpassed.
      * 
-     * @param readlimit
+     * @param markLimit
      *            the number of characters that can be read before the mark is
      *            invalidated.
      * @throws IllegalArgumentException
-     *             if {@code readlimit < 0}.
+     *             if {@code markLimit < 0}.
      * @throws IOException
      *             if an error occurs while setting a mark in this reader.
      * @see #markSupported()
      * @see #reset()
      */
     @Override
-    public void mark(int readlimit) throws IOException {
-        if (readlimit < 0) {
+    public void mark(int markLimit) throws IOException {
+        if (markLimit < 0) {
             throw new IllegalArgumentException();
         }
         synchronized (lock) {
             if (isClosed()) {
                 throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
             }
-            marklimit = readlimit;
-            markpos = pos;
+            this.markLimit = markLimit;
+            mark = pos;
         }
     }
 
@@ -224,10 +263,9 @@
                 throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
             }
             /* Are there buffered characters available? */
-            if (pos < count || fillbuf() != -1) {
+            if (pos < end || fillBuf() != -1) {
                 return buf[pos++];
             }
-            markpos = -1;
             return -1;
         }
     }
@@ -276,52 +314,59 @@
                 throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
             }
             // END android-changed
-            if (length == 0) {
-                return 0;
-            }
-            int required;
-            if (pos < count) {
-                /* There are bytes available in the buffer. */
-                int copylength = count - pos >= length ? length : count - pos;
-                System.arraycopy(buf, pos, buffer, offset, copylength);
-                pos += copylength;
-                if (copylength == length || !in.ready()) {
-                    return copylength;
+
+            int outstanding = length;
+            while (outstanding > 0) {
+
+                /*
+                 * If there are bytes in the buffer, grab those first.
+                 */
+                int available = end - pos;
+                if (available > 0) {
+                    int count = available >= outstanding ? outstanding : available;
+                    System.arraycopy(buf, pos, buffer, offset, count);
+                    pos += count;
+                    offset += count;
+                    outstanding -= count;
                 }
-                offset += copylength;
-                required = length - copylength;
-            } else {
-                required = length;
+
+                /*
+                 * Before attempting to read from the underlying stream, make
+                 * sure we really, really want to. We won't bother if we're
+                 * done, or if we've already got some bytes and reading from the
+                 * underlying stream would block.
+                 */
+                if (outstanding == 0 || (outstanding < length && !in.ready())) {
+                    break;
+                }
+
+                // assert(pos == end);
+
+                /*
+                 * If we're unmarked and the requested size is greater than our
+                 * buffer, read the bytes directly into the caller's buffer. We
+                 * don't read into smaller buffers because that could result in
+                 * a many reads.
+                 */
+                if ((mark == -1 || (pos - mark >= markLimit))
+                        && outstanding >= buf.length) {
+                    int count = in.read(buffer, offset, outstanding);
+                    if (count > 0) {
+                        offset += count;
+                        outstanding -= count;
+                        mark = -1;
+                    }
+
+                    break; // assume the source stream gave us all that it could
+                }
+
+                if (fillBuf() == -1) {
+                    break; // source is exhausted
+                }
             }
 
-            while (true) {
-                int read;
-                /*
-                 * If we're not marked and the required size is greater than the
-                 * buffer, simply read the bytes directly bypassing the buffer.
-                 */
-                if (markpos == -1 && required >= buf.length) {
-                    read = in.read(buffer, offset, required);
-                    if (read == -1) {
-                        return required == length ? -1 : length - required;
-                    }
-                } else {
-                    if (fillbuf() == -1) {
-                        return required == length ? -1 : length - required;
-                    }
-                    read = count - pos >= required ? required : count - pos;
-                    System.arraycopy(buf, pos, buffer, offset, read);
-                    pos += read;
-                }
-                required -= read;
-                if (required == 0) {
-                    return length;
-                }
-                if (!in.ready()) {
-                    return length - required;
-                }
-                offset += read;
-            }
+            int count = length - outstanding;
+            return (count > 0 || count == length) ? count : -1;
         }
     }
 
@@ -341,11 +386,11 @@
             if (isClosed()) {
                 throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
             }
-            /* Are there buffered characters available? */
-            if ((pos >= count) && (fillbuf() == -1)) {
+            /* has the underlying stream been exhausted? */
+            if (pos == end && fillBuf() == -1) {
                 return null;
             }
-            for (int charPos = pos; charPos < count; charPos++) {
+            for (int charPos = pos; charPos < end; charPos++) {
                 char ch = buf[charPos];
                 // BEGIN android-note
                 // a switch statement may be more efficient
@@ -360,7 +405,7 @@
                 } else if (ch == '\r') {
                     String res = new String(buf, pos, charPos - pos);
                     pos = charPos + 1;
-                    if (((pos < count) || (fillbuf() != -1))
+                    if (((pos < end) || (fillBuf() != -1))
                             && (buf[pos] == '\n')) {
                         pos++;
                     }
@@ -372,30 +417,28 @@
             StringBuilder result = new StringBuilder(80);
             /* Typical Line Length */
 
-            result.append(buf, pos, count - pos);
-            pos = count;
+            result.append(buf, pos, end - pos);
             while (true) {
+                pos = end;
+
                 /* Are there buffered characters available? */
-                if (pos >= count) {
-                    if (eol == '\n') {
-                        return result.toString();
-                    }
-                    // attempt to fill buffer
-                    if (fillbuf() == -1) {
-                        // characters or null.
-                        return result.length() > 0 || eol != '\0' ? result
-                                .toString() : null;
-                    }
+                if (eol == '\n') {
+                    return result.toString();
                 }
-                for (int charPos = pos; charPos < count; charPos++) {
-                    // BEGIN android-note
-                    // use a local variable for buf[charPos] and a switch statement
-                    // END android-note
+                // attempt to fill buffer
+                if (fillBuf() == -1) {
+                    // characters or null.
+                    return result.length() > 0 || eol != '\0'
+                            ? result.toString()
+                            : null;
+                }
+                for (int charPos = pos; charPos < end; charPos++) {
+                    char c = buf[charPos];
                     if (eol == '\0') {
-                        if ((buf[charPos] == '\n' || buf[charPos] == '\r')) {
-                            eol = buf[charPos];
+                        if ((c == '\n' || c == '\r')) {
+                            eol = c;
                         }
-                    } else if (eol == '\r' && (buf[charPos] == '\n')) {
+                    } else if (eol == '\r' && c == '\n') {
                         if (charPos > pos) {
                             result.append(buf, pos, charPos - pos - 1);
                         }
@@ -410,11 +453,10 @@
                     }
                 }
                 if (eol == '\0') {
-                    result.append(buf, pos, count - pos);
+                    result.append(buf, pos, end - pos);
                 } else {
-                    result.append(buf, pos, count - pos - 1);
+                    result.append(buf, pos, end - pos - 1);
                 }
-                pos = count;
             }
         }
 
@@ -437,7 +479,7 @@
             if (isClosed()) {
                 throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
             }
-            return ((count - pos) > 0) || in.ready();
+            return ((end - pos) > 0) || in.ready();
         }
     }
 
@@ -457,17 +499,17 @@
             if (isClosed()) {
                 throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
             }
-            if (markpos == -1) {
+            if (mark == -1) {
                 throw new IOException(Msg.getString("K005c")); //$NON-NLS-1$
             }
-            pos = markpos;
+            pos = mark;
         }
     }
 
     /**
      * Skips {@code amount} characters in this reader. Subsequent
      * {@code read()}s will not return these characters unless {@code reset()}
-     * is used. Skipping characters may invalidate a mark if {@code readlimit}
+     * is used. Skipping characters may invalidate a mark if {@code markLimit}
      * is surpassed.
      * 
      * @param amount
@@ -493,24 +535,24 @@
             if (amount < 1) {
                 return 0;
             }
-            if (count - pos >= amount) {
+            if (end - pos >= amount) {
                 pos += amount;
                 return amount;
             }
 
-            long read = count - pos;
-            pos = count;
+            long read = end - pos;
+            pos = end;
             while (read < amount) {
-                if (fillbuf() == -1) {
+                if (fillBuf() == -1) {
                     return read;
                 }
-                if (count - pos >= amount - read) {
+                if (end - pos >= amount - read) {
                     pos += amount - read;
                     return amount;
                 }
                 // Couldn't get all the characters, skip what we read
-                read += (count - pos);
-                pos = count;
+                read += (end - pos);
+                pos = end;
             }
             return amount;
         }
diff --git a/luni/src/main/java/java/io/CharArrayReader.java b/luni/src/main/java/java/io/CharArrayReader.java
index d2757f6..6753faa 100644
--- a/luni/src/main/java/java/io/CharArrayReader.java
+++ b/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/luni/src/main/java/java/io/DataOutputStream.java b/luni/src/main/java/java/io/DataOutputStream.java
index 18e04a5..4152173 100644
--- a/luni/src/main/java/java/io/DataOutputStream.java
+++ b/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/luni/src/main/java/java/io/EmulatedFieldsForDumping.java b/luni/src/main/java/java/io/EmulatedFieldsForDumping.java
index 16c7986..c3743dd 100644
--- a/luni/src/main/java/java/io/EmulatedFieldsForDumping.java
+++ b/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/luni/src/main/java/java/io/File.java b/luni/src/main/java/java/io/File.java
index c802995..521623d 100644
--- a/luni/src/main/java/java/io/File.java
+++ b/luni/src/main/java/java/io/File.java
@@ -25,7 +25,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.harmony.luni.internal.io.FileCanonPathCache;
 import org.apache.harmony.luni.util.DeleteOnExit;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
@@ -497,11 +496,15 @@
     public String getCanonicalPath() throws IOException {
         byte[] result = properPath(false);
         String absPath = Util.toUTF8String(result);
-        String canonPath = FileCanonPathCache.get(absPath);
 
-        if (canonPath != null) {
-            return canonPath;
-        }
+        // BEGIN android-removed
+        //     caching the canonical path is completely bogus
+        // String canonPath = FileCanonPathCache.get(absPath);
+        // if (canonPath != null) {
+        //     return canonPath;
+        // }
+        // END android-removed
+
         if(separatorChar == '/') {
             // resolve the full path first
             result = resolveLink(result, result.length, false);
@@ -573,9 +576,13 @@
         newResult[newLength] = 0;
         newResult = getCanonImpl(newResult);
         newLength = newResult.length;
-        canonPath = Util.toUTF8String(newResult, 0, newLength);
-        FileCanonPathCache.put(absPath, canonPath);
-        return canonPath;
+
+        // BEGIN android-changed
+        //     caching the canonical path is completely bogus
+        return Util.toUTF8String(newResult, 0, newLength);
+        // FileCanonPathCache.put(absPath, canonPath);
+        // return canonPath;
+        // END android-changed
     }
 
     /*
@@ -761,9 +768,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 +781,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 +1360,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 +1384,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/luni/src/main/java/java/io/FileInputStream.java b/luni/src/main/java/java/io/FileInputStream.java
index 1243262..077cd23 100644
--- a/luni/src/main/java/java/io/FileInputStream.java
+++ b/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/luni/src/main/java/java/io/FilterOutputStream.java b/luni/src/main/java/java/io/FilterOutputStream.java
index 66765f9..fa837ee 100644
--- a/luni/src/main/java/java/io/FilterOutputStream.java
+++ b/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/luni/src/main/java/java/io/InputStream.java b/luni/src/main/java/java/io/InputStream.java
index f20ce7d..33a5cfd 100644
--- a/luni/src/main/java/java/io/InputStream.java
+++ b/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/luni/src/main/java/java/io/LineNumberInputStream.java b/luni/src/main/java/java/io/LineNumberInputStream.java
index 1a40177..3df3a05 100644
--- a/luni/src/main/java/java/io/LineNumberInputStream.java
+++ b/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/luni/src/main/java/java/io/NotSerializableException.java b/luni/src/main/java/java/io/NotSerializableException.java
index f6e93a7..d85586a 100644
--- a/luni/src/main/java/java/io/NotSerializableException.java
+++ b/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/luni/src/main/java/java/io/ObjectInputStream.java b/luni/src/main/java/java/io/ObjectInputStream.java
index 6d24eb2..df6d9a2 100644
--- a/luni/src/main/java/java/io/ObjectInputStream.java
+++ b/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/luni/src/main/java/java/io/ObjectOutputStream.java b/luni/src/main/java/java/io/ObjectOutputStream.java
index e3c1471..7c85d4b 100644
--- a/luni/src/main/java/java/io/ObjectOutputStream.java
+++ b/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/luni/src/main/java/java/io/PipedInputStream.java b/luni/src/main/java/java/io/PipedInputStream.java
index a6b0336..6d1c007 100644
--- a/luni/src/main/java/java/io/PipedInputStream.java
+++ b/luni/src/main/java/java/io/PipedInputStream.java
@@ -15,6 +15,13 @@
  *  limitations under the License.
  */
 
+// BEGIN android-note
+// We've made several changes including:
+//  - delayed buffer creation until pipe connection
+//  - throw an IOException when a pipe is closed during a write
+//  - improved consistency with PipedReader
+// END android-note
+
 package java.io;
 
 import org.apache.harmony.luni.util.Msg;
@@ -28,9 +35,11 @@
  */
 public class PipedInputStream extends InputStream {
 
-    private Thread lastReader, lastWriter;
+    private Thread lastReader;
 
-    private boolean isClosed = false;
+    private Thread lastWriter;
+
+    private boolean isClosed;
 
     /**
      * The circular buffer through which data is passed. Data is read from the
@@ -60,7 +69,7 @@
     /**
      * The index in {@code buffer} where the next byte will be read.
      */
-    protected int out = 0;
+    protected int out;
 
     /**
      * The size of the default pipe in bytes.
@@ -70,16 +79,14 @@
     /**
      * Indicates if this pipe is connected.
      */
-    boolean isConnected = false;
+    boolean isConnected;
 
     /**
      * Constructs a new unconnected {@code PipedInputStream}. The resulting
      * stream must be connected to a {@link PipedOutputStream} before data may
      * be read from it.
      */
-    public PipedInputStream() {
-        /* empty */
-    }
+    public PipedInputStream() {}
 
     /**
      * Constructs a new {@code PipedInputStream} connected to the
@@ -120,14 +127,9 @@
      *             if an error occurs while closing this stream.
      */
     @Override
-    public void close() throws IOException {
-        synchronized (this) {
-            /* No exception thrown if already closed */
-            if (buffer != null) {
-                /* Release buffer to indicate closed. */
-                buffer = null;
-            }
-        }
+    public synchronized void close() throws IOException {
+        buffer = null;
+        notifyAll();
     }
 
     /**
@@ -145,6 +147,20 @@
     }
 
     /**
+     * Establishes the connection to the PipedOutputStream.
+     *
+     * @throws IOException
+     *             If this Reader is already connected.
+     */
+    synchronized void establishConnection() throws IOException {
+        if (isConnected) {
+            throw new IOException(Msg.getString("K007a")); //$NON-NLS-1$
+        }
+        buffer = new byte[PipedInputStream.PIPE_SIZE];
+        isConnected = true;
+    }
+
+    /**
      * Reads a single byte from this stream and returns it as an integer in the
      * range from 0 to 255. Returns -1 if the end of this stream has been
      * reached. If there is no data in the pipe, this method blocks until data
@@ -408,20 +424,21 @@
         } catch (InterruptedException e) {
             throw new InterruptedIOException();
         }
-        if (buffer != null) {
-            if (in == -1) {
-                in = 0;
-            }
-            buffer[in++] = (byte) oneByte;
-            if (in == buffer.length) {
-                in = 0;
-            }
-
-            // BEGIN android-added
-            // let blocked readers read the newly available data
-            notifyAll();
-            // END android-added
+        if (buffer == null) {
+            throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
         }
+        if (in == -1) {
+            in = 0;
+        }
+        buffer[in++] = (byte) oneByte;
+        if (in == buffer.length) {
+            in = 0;
+        }
+
+        // BEGIN android-added
+        // let blocked readers read the newly available data
+        notifyAll();
+        // END android-added
     }
 
     synchronized void done() {
diff --git a/luni/src/main/java/java/io/PipedOutputStream.java b/luni/src/main/java/java/io/PipedOutputStream.java
index 15ee930..4b640d4 100644
--- a/luni/src/main/java/java/io/PipedOutputStream.java
+++ b/luni/src/main/java/java/io/PipedOutputStream.java
@@ -15,6 +15,12 @@
  *  limitations under the License.
  */
 
+// BEGIN android-note
+// We've made several changes including:
+//  - avoid shallow concurrency problems
+//  - improved consistency with PipedWriter
+// END android-note
+
 package java.io;
 
 import org.apache.harmony.luni.util.Msg;
@@ -67,8 +73,9 @@
     @Override
     public void close() throws IOException {
         // Is the pipe connected?
-        if (dest != null) {
-            dest.done();
+        PipedInputStream stream = dest;
+        if (stream != null) {
+            stream.done();
             dest = null;
         }
     }
@@ -83,18 +90,17 @@
      *             if either stream is already connected.
      */
     public void connect(PipedInputStream stream) throws IOException {
-        if (null == stream) {
+        if (stream == null) {
             throw new NullPointerException();
         }
-        if (this.dest != null) {
-            throw new IOException(Msg.getString("K0079")); //$NON-NLS-1$
-        }
         synchronized (stream) {
+            if (this.dest != null) {
+                throw new IOException(Msg.getString("K0079")); //$NON-NLS-1$
+            }
             if (stream.isConnected) {
                 throw new IOException(Msg.getString("K007a")); //$NON-NLS-1$
             }
-            stream.buffer = new byte[PipedInputStream.PIPE_SIZE];
-            stream.isConnected = true;
+            stream.establishConnection();
             this.dest = stream;
         }
     }
@@ -108,10 +114,13 @@
      */
     @Override
     public void flush() throws IOException {
-        if (dest != null) {
-            synchronized (dest) {
-                dest.notifyAll();
-            }
+        PipedInputStream stream = dest;
+        if (stream == null) {
+            return;
+        }
+
+        synchronized (stream) {
+            stream.notifyAll();
         }
     }
 
@@ -145,13 +154,6 @@
      */
     @Override
     public void write(byte[] buffer, int offset, int count) throws IOException {
-        // BEGIN android-note
-        // changed array notation to be consistent with the rest of harmony
-        // END android-note
-        if (dest == null) {
-            // K007b=Pipe Not Connected
-            throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
-        }
         super.write(buffer, offset, count);
     }
 
@@ -177,9 +179,11 @@
      */
     @Override
     public void write(int oneByte) throws IOException {
-        if (dest == null) {
+        PipedInputStream stream = dest;
+        if (stream == null) {
+            // K007b=Pipe Not Connected
             throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
         }
-        dest.receive(oneByte);
+        stream.receive(oneByte);
     }
 }
diff --git a/luni/src/main/java/java/io/PipedReader.java b/luni/src/main/java/java/io/PipedReader.java
index 251ac90..d137a0d 100644
--- a/luni/src/main/java/java/io/PipedReader.java
+++ b/luni/src/main/java/java/io/PipedReader.java
@@ -17,6 +17,13 @@
 
 package java.io;
 
+// BEGIN android-note
+// We've made several changes including:
+//  - throw an IOException when a pipe is closed during a write
+//  - fix shallow concurrency problems, always lock on 'this'
+//  - improved consistency with PipedInputStream
+// END android-note
+
 import org.apache.harmony.luni.util.Msg;
 
 /**
@@ -35,13 +42,27 @@
     private boolean isClosed;
 
     /**
-     * The circular buffer through which data is passed.
+     * The circular buffer through which data is passed. Data is read from the
+     * range {@code [out, in)} and written to the range {@code [in, out)}.
+     * Data in the buffer is either sequential: <pre>
+     *     { - - - X X X X X X X - - - - - }
+     *             ^             ^
+     *             |             |
+     *            out           in</pre>
+     * ...or wrapped around the buffer's end: <pre>
+     *     { X X X X - - - - - - - - X X X }
+     *               ^               ^
+     *               |               |
+     *              in              out</pre>
+     * When the buffer is empty, {@code in == -1}. Reading when the buffer is
+     * empty will block until data is available. When the buffer is full,
+     * {@code in == out}. Writing when the buffer is full will block until free
+     * space is available.
      */
-    private char data[];
+    private char[] buffer;
 
     /**
-     * The index in {@code buffer} where the next character will be
-     * written.
+     * The index in {@code buffer} where the next character will be written.
      */
     private int in = -1;
 
@@ -58,18 +79,14 @@
     /**
      * Indicates if this pipe is connected
      */
-    private boolean isConnected;
+    boolean isConnected;
 
     /**
      * Constructs a new unconnected {@code PipedReader}. The resulting reader
      * must be connected to a {@code PipedWriter} before data may be read from
      * it.
-     *
-     * @see PipedWriter
      */
-    public PipedReader() {
-        data = new char[PIPE_SIZE];
-    }
+    public PipedReader() {}
 
     /**
      * Constructs a new {@code PipedReader} connected to the {@link PipedWriter}
@@ -82,7 +99,6 @@
      *             if {@code out} is already connected.
      */
     public PipedReader(PipedWriter out) throws IOException {
-        this();
         connect(out);
     }
 
@@ -94,14 +110,9 @@
      *             if an error occurs while closing this reader.
      */
     @Override
-    public void close() throws IOException {
-        synchronized (lock) {
-            /* No exception thrown if already closed */
-            if (data != null) {
-                /* Release buffer to indicate closed. */
-                data = null;
-            }
-        }
+    public synchronized void close() throws IOException {
+        buffer = null;
+        notifyAll();
     }
 
     /**
@@ -115,9 +126,7 @@
      *             src} is already connected.
      */
     public void connect(PipedWriter src) throws IOException {
-        synchronized (lock) {
-            src.connect(this);
-        }
+        src.connect(this);
     }
 
     /**
@@ -126,16 +135,12 @@
      * @throws IOException
      *             If this Reader is already connected.
      */
-    void establishConnection() throws IOException {
-        synchronized (lock) {
-            if (data == null) {
-                throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
-            }
-            if (isConnected) {
-                throw new IOException(Msg.getString("K007a")); //$NON-NLS-1$
-            }
-            isConnected = true;
+    synchronized void establishConnection() throws IOException {
+        if (isConnected) {
+            throw new IOException(Msg.getString("K007a")); //$NON-NLS-1$
         }
+        buffer = new char[PIPE_SIZE];
+        isConnected = true;
     }
 
     /**
@@ -192,95 +197,93 @@
      *             alive.
      */
     @Override
-    public int read(char[] buffer, int offset, int count) throws IOException {
-        synchronized (lock) {
-            if (!isConnected) {
-                throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
-            }
-            if (data == null) {
-                throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
-            }
-            // 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,
-            // 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$
-            }
-            if ((offset | count) < 0 || count > buffer.length - offset) {
-                throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
-            }
-            // END android-changed
-            if (count == 0) {
-                return 0;
-            }
-            /**
-             * Set the last thread to be reading on this PipedReader. If
-             * lastReader dies while someone is waiting to write an IOException
-             * of "Pipe broken" will be thrown in receive()
-             */
-            lastReader = Thread.currentThread();
-            try {
-                boolean first = true;
-                while (in == -1) {
-                    // Are we at end of stream?
-                    if (isClosed) {
-                        return -1;
-                    }
-                    if (!first && lastWriter != null && !lastWriter.isAlive()) {
-                        throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
-                    }
-                    first = false;
-                    // Notify callers of receive()
-                    lock.notifyAll();
-                    lock.wait(1000);
+    public synchronized int read(char[] buffer, int offset, int count) throws IOException {
+        if (!isConnected) {
+            throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
+        }
+        if (this.buffer == null) {
+            throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
+        }
+        // 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,
+        // 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$
+        }
+        if ((offset | count) < 0 || count > buffer.length - offset) {
+            throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+        }
+        // END android-changed
+        if (count == 0) {
+            return 0;
+        }
+        /**
+         * Set the last thread to be reading on this PipedReader. If
+         * lastReader dies while someone is waiting to write an IOException
+         * of "Pipe broken" will be thrown in receive()
+         */
+        lastReader = Thread.currentThread();
+        try {
+            boolean first = true;
+            while (in == -1) {
+                // Are we at end of stream?
+                if (isClosed) {
+                    return -1;
                 }
-            } catch (InterruptedException e) {
-                throw new InterruptedIOException();
-            }
-
-            int copyLength = 0;
-            /* Copy chars from out to end of buffer first */
-            if (out >= in) {
-                copyLength = count > data.length - out ? data.length - out
-                        : count;
-                System.arraycopy(data, out, buffer, offset, copyLength);
-                out += copyLength;
-                if (out == data.length) {
-                    out = 0;
+                if (!first && lastWriter != null && !lastWriter.isAlive()) {
+                    throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
                 }
-                if (out == in) {
-                    // empty buffer
-                    in = -1;
-                    out = 0;
-                }
+                first = false;
+                // Notify callers of receive()
+                notifyAll();
+                wait(1000);
             }
+        } catch (InterruptedException e) {
+            throw new InterruptedIOException();
+        }
 
-            /*
-             * Did the read fully succeed in the previous copy or is the buffer
-             * empty?
-             */
-            if (copyLength == count || in == -1) {
-                return copyLength;
-            }
-
-            int charsCopied = copyLength;
-            /* Copy bytes from 0 to the number of available bytes */
-            copyLength = in - out > count - copyLength ? count - copyLength
-                    : in - out;
-            System.arraycopy(data, out, buffer, offset + charsCopied,
-                    copyLength);
+        int copyLength = 0;
+        /* Copy chars from out to end of buffer first */
+        if (out >= in) {
+            copyLength = count > this.buffer.length - out ? this.buffer.length - out
+                    : count;
+            System.arraycopy(this.buffer, out, buffer, offset, copyLength);
             out += copyLength;
+            if (out == this.buffer.length) {
+                out = 0;
+            }
             if (out == in) {
                 // empty buffer
                 in = -1;
                 out = 0;
             }
-            return charsCopied + copyLength;
         }
+
+        /*
+         * Did the read fully succeed in the previous copy or is the buffer
+         * empty?
+         */
+        if (copyLength == count || in == -1) {
+            return copyLength;
+        }
+
+        int charsCopied = copyLength;
+        /* Copy bytes from 0 to the number of available bytes */
+        copyLength = in - out > count - copyLength ? count - copyLength
+                : in - out;
+        System.arraycopy(this.buffer, out, buffer, offset + charsCopied,
+                copyLength);
+        out += copyLength;
+        if (out == in) {
+            // empty buffer
+            in = -1;
+            out = 0;
+        }
+        return charsCopied + copyLength;
     }
 
     /**
@@ -298,16 +301,14 @@
      * @see #read(char[], int, int)
      */
     @Override
-    public boolean ready() throws IOException {
-        synchronized (lock) {
-            if (!isConnected) {
-                throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
-            }
-            if (data == null) {
-                throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
-            }
-            return in != -1;
+    public synchronized boolean ready() throws IOException {
+        if (!isConnected) {
+            throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
         }
+        if (buffer == null) {
+            throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
+        }
+        return in != -1;
     }
 
     /**
@@ -324,43 +325,41 @@
      *             If the stream is already closed or another IOException
      *             occurs.
      */
-    void receive(char oneChar) throws IOException {
-        synchronized (lock) {
-            if (data == null) {
-                throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
-            }
-            if (lastReader != null && !lastReader.isAlive()) {
-                throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
-            }
-            /*
-             * Set the last thread to be writing on this PipedWriter. If
-             * lastWriter dies while someone is waiting to read an IOException
-             * of "Pipe broken" will be thrown in read()
-             */
-            lastWriter = Thread.currentThread();
-            try {
-                while (data != null && out == in) {
-                    lock.notifyAll();
-                    // BEGIN android-changed
-                    lock.wait(1000);
-                    // END android-changed
-                    if (lastReader != null && !lastReader.isAlive()) {
-                        throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
-                    }
+    synchronized void receive(char oneChar) throws IOException {
+        if (buffer == null) {
+            throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
+        }
+        if (lastReader != null && !lastReader.isAlive()) {
+            throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
+        }
+        /*
+        * Set the last thread to be writing on this PipedWriter. If
+        * lastWriter dies while someone is waiting to read an IOException
+        * of "Pipe broken" will be thrown in read()
+        */
+        lastWriter = Thread.currentThread();
+        try {
+            while (buffer != null && out == in) {
+                notifyAll();
+                // BEGIN android-changed
+                wait(1000);
+                // END android-changed
+                if (lastReader != null && !lastReader.isAlive()) {
+                    throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
                 }
-            } catch (InterruptedException e) {
-                throw new InterruptedIOException();
             }
-            if (data != null) {
-                if (in == -1) {
-                    in = 0;
-                }
-                data[in++] = oneChar;
-                if (in == data.length) {
-                    in = 0;
-                }
-                return;
-            }
+        } catch (InterruptedException e) {
+            throw new InterruptedIOException();
+        }
+        if (buffer == null) {
+            throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
+        }
+        if (in == -1) {
+            in = 0;
+        }
+        buffer[in++] = oneChar;
+        if (in == buffer.length) {
+            in = 0;
         }
     }
 
@@ -382,80 +381,73 @@
      *             If the stream is already closed or another IOException
      *             occurs.
      */
-    void receive(char[] chars, int offset, int count) throws IOException {
-        synchronized (lock) {
-            if (data == null) {
+    synchronized void receive(char[] chars, int offset, int count) throws IOException {
+        if (chars == null) {
+            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+        }
+        if ((offset | count) < 0 || count > chars.length - offset) {
+            throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+        }
+        if (buffer == null) {
+            throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
+        }
+        if (lastReader != null && !lastReader.isAlive()) {
+            throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
+        }
+        /**
+         * Set the last thread to be writing on this PipedWriter. If
+         * lastWriter dies while someone is waiting to read an IOException
+         * of "Pipe broken" will be thrown in read()
+         */
+        lastWriter = Thread.currentThread();
+        while (count > 0) {
+            try {
+                while (buffer != null && out == in) {
+                    notifyAll();
+                    // BEGIN android-changed
+                    wait(1000);
+                    // END android-changed
+                    if (lastReader != null && !lastReader.isAlive()) {
+                        throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
+                    }
+                }
+            } catch (InterruptedException e) {
+                throw new InterruptedIOException();
+            }
+            if (buffer == null) {
                 throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
             }
-            if (lastReader != null && !lastReader.isAlive()) {
-                throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
+            if (in == -1) {
+                in = 0;
             }
-            /**
-             * Set the last thread to be writing on this PipedWriter. If
-             * lastWriter dies while someone is waiting to read an IOException
-             * of "Pipe broken" will be thrown in read()
-             */
-            lastWriter = Thread.currentThread();
-            while (count > 0) {
-                try {
-                    while (data != null && out == in) {
-                        lock.notifyAll();
-                        // BEGIN android-changed
-                        lock.wait(1000);
-                        // END android-changed
-                        if (lastReader != null && !lastReader.isAlive()) {
-                            throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
-                        }
-                    }
-                } catch (InterruptedException e) {
-                    throw new InterruptedIOException();
+            if (in >= out) {
+                int length = buffer.length - in;
+                if (count < length) {
+                    length = count;
                 }
-                if (data == null) {
-                    break;
-                }
-                if (in == -1) {
+                System.arraycopy(chars, offset, buffer, in, length);
+                offset += length;
+                count -= length;
+                in += length;
+                if (in == buffer.length) {
                     in = 0;
                 }
-                if (in >= out) {
-                    int length = data.length - in;
-                    if (count < length) {
-                        length = count;
-                    }
-                    System.arraycopy(chars, offset, data, in, length);
-                    offset += length;
-                    count -= length;
-                    in += length;
-                    if (in == data.length) {
-                        in = 0;
-                    }
-                }
-                if (count > 0 && in != out) {
-                    int length = out - in;
-                    if (count < length) {
-                        length = count;
-                    }
-                    System.arraycopy(chars, offset, data, in, length);
-                    offset += length;
-                    count -= length;
-                    in += length;
-                }
             }
-            if (count == 0) {
-                return;
+            if (count > 0 && in != out) {
+                int length = out - in;
+                if (count < length) {
+                    length = count;
+                }
+                System.arraycopy(chars, offset, buffer, in, length);
+                offset += length;
+                count -= length;
+                in += length;
             }
         }
     }
 
-    void done() {
-        synchronized (lock) {
-            isClosed = true;
-            lock.notifyAll();
-        }
-    }
-
-    void flush() {
-        synchronized (lock) {
-            lock.notifyAll();
-        }
+    synchronized void done() {
+        isClosed = true;
+        notifyAll();
     }
 }
diff --git a/luni/src/main/java/java/io/PipedWriter.java b/luni/src/main/java/java/io/PipedWriter.java
index 5fc968d..b0bfa98 100644
--- a/luni/src/main/java/java/io/PipedWriter.java
+++ b/luni/src/main/java/java/io/PipedWriter.java
@@ -15,6 +15,14 @@
  *  limitations under the License.
  */
 
+// BEGIN android-note
+// We've made several changes including:
+//  - move checks into the synchronized method in PipedReader
+//  - reply on PipedReader's isClosed field (rather than having 2 flags)
+//  - avoid shallow concurrency problems
+//  - improved consistency with PipedOutputStream
+// END android-note
+
 package java.io;
 
 import org.apache.harmony.luni.util.Msg;
@@ -32,8 +40,6 @@
      */
     private PipedReader dest;
 
-    private boolean closed;
-
     /**
      * Constructs a new unconnected {@code PipedWriter}. The resulting writer
      * must be connected to a {@code PipedReader} before data may be written to
@@ -70,13 +76,10 @@
      */
     @Override
     public void close() throws IOException {
-        synchronized (lock) {
-            /* Is the pipe connected? */
-            if (dest != null) {
-                dest.done();
-                dest = null;
-            }
-            closed = true;
+        PipedReader reader = dest;
+        if (reader != null) {
+            reader.done();
+            dest = null;
         }
     }
 
@@ -84,22 +87,26 @@
      * Connects this {@code PipedWriter} to a {@link PipedReader}. Any data
      * written to this writer becomes readable in the reader.
      *
-     * @param stream
+     * @param reader
      *            the reader to connect to.
      * @throws IOException
      *             if this writer is closed or already connected, or if {@code
-     *             stream} is already connected.
+     *             reader} is already connected.
      */
-    public void connect(PipedReader stream) throws IOException {
-        synchronized (lock) {
+    public void connect(PipedReader reader) throws IOException {
+        if (reader == null) {
+            throw new NullPointerException();
+        }
+        synchronized (reader) {
             if (this.dest != null) {
                 throw new IOException(Msg.getString("K0079")); //$NON-NLS-1$
             }
-            if (closed) {
+            if (reader.isConnected) {
                 throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
             }
-            stream.establishConnection();
-            this.dest = stream;
+            reader.establishConnection();
+            this.lock = reader;
+            this.dest = reader;
         }
     }
 
@@ -112,8 +119,13 @@
      */
     @Override
     public void flush() throws IOException {
-        if (dest != null) {
-            dest.flush();
+        PipedReader reader = dest;
+        if (reader == null) {
+            return;
+        }
+
+        synchronized (reader) {
+            reader.notifyAll();
         }
     }
 
@@ -150,32 +162,12 @@
      */
     @Override
     public void write(char[] buffer, int offset, int count) throws IOException {
-        // BEGIN android-note
-        // changed array notation to be consistent with the rest of harmony
-        // END android-note
-        synchronized (lock) {
-            if (closed) {
-                throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
-            }
-            if (dest == null) {
-                throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
-            }
-            if (buffer == 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 | count) < 0
-            // instead of (offset < 0) || (count < 0) to safe one operation
-            if ((offset | count) < 0 || count > buffer.length - offset) {
-                throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
-            }
-            // END android-changed
-            dest.receive(buffer, offset, count);
+        PipedReader reader = dest;
+        if (reader == null) {
+            // K007b=Pipe Not Connected
+            throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
         }
+        reader.receive(buffer, offset, count);
     }
 
     /**
@@ -200,14 +192,11 @@
      */
     @Override
     public void write(int c) throws IOException {
-        synchronized (lock) {
-            if (closed) {
-                throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
-            }
-            if (dest == null) {
-                throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
-            }
-            dest.receive((char) c);
+        PipedReader reader = dest;
+        if (reader == null) {
+            // K007b=Pipe Not Connected
+            throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
         }
+        reader.receive((char) c);
     }
 }
diff --git a/luni/src/main/java/java/io/PrintStream.java b/luni/src/main/java/java/io/PrintStream.java
index 29d460e..8b6464b 100644
--- a/luni/src/main/java/java/io/PrintStream.java
+++ b/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/luni/src/main/java/java/io/PushbackInputStream.java b/luni/src/main/java/java/io/PushbackInputStream.java
index 4600fa2..932a896 100644
--- a/luni/src/main/java/java/io/PushbackInputStream.java
+++ b/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/luni/src/main/java/java/io/PushbackReader.java b/luni/src/main/java/java/io/PushbackReader.java
index 606ecb4..016cd2f 100644
--- a/luni/src/main/java/java/io/PushbackReader.java
+++ b/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/luni/src/main/java/java/io/StringBufferInputStream.java b/luni/src/main/java/java/io/StringBufferInputStream.java
index cc4ab81..037cc60 100644
--- a/luni/src/main/java/java/io/StringBufferInputStream.java
+++ b/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/luni/src/main/java/java/io/StringReader.java b/luni/src/main/java/java/io/StringReader.java
index 0a9e9bb..9f8671a 100644
--- a/luni/src/main/java/java/io/StringReader.java
+++ b/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/luni/src/main/java/java/lang/AbstractStringBuilder.java b/luni/src/main/java/java/lang/AbstractStringBuilder.java
index c481e11..869c694 100644
--- a/luni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/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/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java b/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
index d43a7e6..6bb67fc 100644
--- a/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
+++ b/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/luni/src/main/java/java/lang/Enum.java b/luni/src/main/java/java/lang/Enum.java
index 395c825..e2ee32a 100644
--- a/luni/src/main/java/java/lang/Enum.java
+++ b/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/luni/src/main/java/java/lang/Integer.java b/luni/src/main/java/java/lang/Integer.java
index 570120b..5dcf217 100644
--- a/luni/src/main/java/java/lang/Integer.java
+++ b/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/luni/src/main/java/java/lang/Math.java b/luni/src/main/java/java/lang/Math.java
index d06e6e4..f7b49b2 100644
--- a/luni/src/main/java/java/lang/Math.java
+++ b/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/luni/src/main/java/java/lang/ProcessBuilder.java b/luni/src/main/java/java/lang/ProcessBuilder.java
index f649fec..245ed9c 100644
--- a/luni/src/main/java/java/lang/ProcessBuilder.java
+++ b/luni/src/main/java/java/lang/ProcessBuilder.java
@@ -191,24 +191,15 @@
      *             if an I/O error happens.
      */
     public Process start() throws IOException {
-        if (command.isEmpty()) {
-            throw new IndexOutOfBoundsException();
-        }
-        String[] cmdArray = new String[command.size()];
-        for (int i = 0; i < cmdArray.length; i++) {
-            if ((cmdArray[i] = command.get(i)) == null) {
-                throw new NullPointerException();
-            }
-        }
+        // BEGIN android-changed: push responsibility for argument checking into ProcessManager
+        String[] cmdArray = command.toArray(new String[command.size()]);
         String[] envArray = new String[environment.size()];
         int i = 0;
         for (Map.Entry<String, String> entry : environment.entrySet()) {
             envArray[i++] = entry.getKey() + "=" + entry.getValue(); //$NON-NLS-1$
         }
-        Process process = Runtime.getRuntime().exec(cmdArray, envArray,
-                directory);
-        // TODO implement support for redirectErrorStream
-        return process;
+        return ProcessManager.getInstance().exec(cmdArray, envArray, directory, redirectErrorStream);
+        // END android-changed
     }
 
     private static List<String> toList(String[] strings) {
diff --git a/luni/src/main/java/java/lang/SecurityManager.java b/luni/src/main/java/java/lang/SecurityManager.java
index 9125850..8a04e92 100644
--- a/luni/src/main/java/java/lang/SecurityManager.java
+++ b/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/luni/src/main/java/java/net/DatagramSocketImpl.java b/luni/src/main/java/java/net/DatagramSocketImpl.java
index db3b9ec..12b2079 100644
--- a/luni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/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/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java
index 33c25f3..e88d8b3 100644
--- a/luni/src/main/java/java/net/InetAddress.java
+++ b/luni/src/main/java/java/net/InetAddress.java
@@ -303,22 +303,18 @@
 
     // BEGIN android-added
     /**
-     * Convenience method to convert a byte array to a string, converting
-     * exceptions to runtime exceptions. This is used when passing in byte
-     * arrays that have been verified to be correct and is necessary because
-     * some methods, such as getHostName(), are not allowed to throw exceptions
-     * but are implemented using byteArrayToIpString(), which throws
-     * UnknownHostException. Exceptions should never occur when the address is
-     * valid, but they cannot be simply ignored because they could be due to
-     * runtime errors such as out-of-memory conditions.
+     * Returns the numeric string form of the given IP address.
      *
-     * @param ipaddress the byte array to convert
+     * @param ipAddress
+     *         the byte array to convert; length 4 for IPv4, 16 for IPv6.
+     * @throws IllegalArgumentException
+     *         if ipAddress is of length other than 4 or 16.
      */
-    private static String ipAddressToString(byte[] ipaddress) {
+    private static String ipAddressToString(byte[] ipAddress) {
         try {
-            return NETIMPL.byteArrayToIpString(ipaddress);
-        } catch(UnknownHostException e) {
-            throw new RuntimeException(e);
+            return NETIMPL.byteArrayToIpString(ipAddress);
+        } catch (IOException ex) {
+            throw new IllegalArgumentException("byte[] neither 4 nor 16 bytes", ex);
         }
     }
     // END android-added
@@ -1320,6 +1316,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/luni/src/main/java/java/net/JarURLConnection.java b/luni/src/main/java/java/net/JarURLConnection.java
index da39d9c..f41ef64 100644
--- a/luni/src/main/java/java/net/JarURLConnection.java
+++ b/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/luni/src/main/java/java/net/NetworkInterface.java b/luni/src/main/java/java/net/NetworkInterface.java
index 091eb9f..f921b07 100644
--- a/luni/src/main/java/java/net/NetworkInterface.java
+++ b/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/luni/src/main/java/java/net/SocketAddress.java b/luni/src/main/java/java/net/SocketAddress.java
index 32a4c36..e84ebfd 100644
--- a/luni/src/main/java/java/net/SocketAddress.java
+++ b/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/luni/src/main/java/java/net/URL.java b/luni/src/main/java/java/net/URL.java
index 9b0fdc4..b9e657d 100644
--- a/luni/src/main/java/java/net/URL.java
+++ b/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/luni/src/main/java/java/net/URLClassLoader.java b/luni/src/main/java/java/net/URLClassLoader.java
index 6dfa385..61841e6 100644
--- a/luni/src/main/java/java/net/URLClassLoader.java
+++ b/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/luni/src/main/java/java/util/ArrayList.java b/luni/src/main/java/java/util/ArrayList.java
index b8c7056..7c46e89 100644
--- a/luni/src/main/java/java/util/ArrayList.java
+++ b/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/luni/src/main/java/java/util/Arrays.java b/luni/src/main/java/java/util/Arrays.java
index 4fc1e85..b6a4ec5 100644
--- a/luni/src/main/java/java/util/Arrays.java
+++ b/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$
         }
     }
 
@@ -2630,7 +2575,7 @@
         if (array.length == 0) {
             return "[]"; //$NON-NLS-1$
         }
-        StringBuilder sb = new StringBuilder(2 + array.length * 5);
+        StringBuilder sb = new StringBuilder(array.length * 7); // android-changed
         sb.append('[');
         sb.append(array[0]);
         for (int i = 1; i < array.length; i++) {
@@ -2660,7 +2605,7 @@
         if (array.length == 0) {
             return "[]"; //$NON-NLS-1$
         }
-        StringBuilder sb = new StringBuilder(2 + array.length * 3);
+        StringBuilder sb = new StringBuilder(array.length * 6); // android-changed
         sb.append('[');
         sb.append(array[0]);
         for (int i = 1; i < array.length; i++) {
@@ -2690,7 +2635,7 @@
         if (array.length == 0) {
             return "[]"; //$NON-NLS-1$
         }
-        StringBuilder sb = new StringBuilder(2 + array.length * 2);
+        StringBuilder sb = new StringBuilder(array.length * 3); // android-changed
         sb.append('[');
         sb.append(array[0]);
         for (int i = 1; i < array.length; i++) {
@@ -2720,7 +2665,7 @@
         if (array.length == 0) {
             return "[]"; //$NON-NLS-1$
         }
-        StringBuilder sb = new StringBuilder(2 + array.length * 5);
+        StringBuilder sb = new StringBuilder(array.length * 7); // android-changed
         sb.append('[');
         sb.append(array[0]);
         for (int i = 1; i < array.length; i++) {
@@ -2750,7 +2695,7 @@
         if (array.length == 0) {
             return "[]"; //$NON-NLS-1$
         }
-        StringBuilder sb = new StringBuilder(2 + array.length * 5);
+        StringBuilder sb = new StringBuilder(array.length * 7); // android-changed
         sb.append('[');
         sb.append(array[0]);
         for (int i = 1; i < array.length; i++) {
@@ -2780,7 +2725,7 @@
         if (array.length == 0) {
             return "[]"; //$NON-NLS-1$
         }
-        StringBuilder sb = new StringBuilder(2 + array.length * 4);
+        StringBuilder sb = new StringBuilder(array.length * 6); // android-changed
         sb.append('[');
         sb.append(array[0]);
         for (int i = 1; i < array.length; i++) {
@@ -2810,7 +2755,7 @@
         if (array.length == 0) {
             return "[]"; //$NON-NLS-1$
         }
-        StringBuilder sb = new StringBuilder(2 + array.length * 4);
+        StringBuilder sb = new StringBuilder(array.length * 6); // android-changed
         sb.append('[');
         sb.append(array[0]);
         for (int i = 1; i < array.length; i++) {
@@ -2840,7 +2785,7 @@
         if (array.length == 0) {
             return "[]"; //$NON-NLS-1$
         }
-        StringBuilder sb = new StringBuilder(2 + array.length * 4);
+        StringBuilder sb = new StringBuilder(array.length * 6); // android-changed
         sb.append('[');
         sb.append(array[0]);
         for (int i = 1; i < array.length; i++) {
@@ -2870,7 +2815,7 @@
         if (array.length == 0) {
             return "[]"; //$NON-NLS-1$
         }
-        StringBuilder sb = new StringBuilder(2 + array.length * 5);
+        StringBuilder sb = new StringBuilder(array.length * 7); // android-changed
         sb.append('[');
         sb.append(array[0]);
         for (int i = 1; i < array.length; i++) {
@@ -2904,7 +2849,7 @@
             return "null"; //$NON-NLS-1$
         }
         // delegate this to the recursive method
-        StringBuilder buf = new StringBuilder(2 + array.length * 5);
+        StringBuilder buf = new StringBuilder(array.length * 9); // android-changed
         deepToStringImpl(array, new Object[] { array }, buf);
         return buf.toString();
     }
diff --git a/luni/src/main/java/java/util/BitSet.java b/luni/src/main/java/java/util/BitSet.java
index 4e01cbf..f88ca7d 100644
--- a/luni/src/main/java/java/util/BitSet.java
+++ b/luni/src/main/java/java/util/BitSet.java
@@ -131,7 +131,7 @@
             clone.bits = bits.clone();
             return clone;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/Calendar.java b/luni/src/main/java/java/util/Calendar.java
index 0ac574c..49a8c3f 100644
--- a/luni/src/main/java/java/util/Calendar.java
+++ b/luni/src/main/java/java/util/Calendar.java
@@ -790,7 +790,7 @@
             clone.zone = (TimeZone) zone.clone();
             return clone;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/Collection.java b/luni/src/main/java/java/util/Collection.java
index 6447e39..1b5cff5 100644
--- a/luni/src/main/java/java/util/Collection.java
+++ b/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/luni/src/main/java/java/util/Collections.java b/luni/src/main/java/java/util/Collections.java
index 767d98b..77cafea 100644
--- a/luni/src/main/java/java/util/Collections.java
+++ b/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/luni/src/main/java/java/util/Date.java b/luni/src/main/java/java/util/Date.java
index 80610d3..37f5b6a 100644
--- a/luni/src/main/java/java/util/Date.java
+++ b/luni/src/main/java/java/util/Date.java
@@ -193,7 +193,7 @@
         try {
             return super.clone();
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/EnumMap.java b/luni/src/main/java/java/util/EnumMap.java
index 975fdad..2b33175 100644
--- a/luni/src/main/java/java/util/EnumMap.java
+++ b/luni/src/main/java/java/util/EnumMap.java
@@ -470,7 +470,7 @@
             enumMap.initialization(this);
             return enumMap;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/EnumSet.java b/luni/src/main/java/java/util/EnumSet.java
index d49d900..c2c3fc0 100644
--- a/luni/src/main/java/java/util/EnumSet.java
+++ b/luni/src/main/java/java/util/EnumSet.java
@@ -322,7 +322,7 @@
             Object set = super.clone();
             return (EnumSet<E>) set;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/Formatter.java b/luni/src/main/java/java/util/Formatter.java
index d1dd417..912a15e 100644
--- a/luni/src/main/java/java/util/Formatter.java
+++ b/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/luni/src/main/java/java/util/GregorianCalendar.java b/luni/src/main/java/java/util/GregorianCalendar.java
index d8cd556..7339151 100644
--- a/luni/src/main/java/java/util/GregorianCalendar.java
+++ b/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/luni/src/main/java/java/util/HashMap.java b/luni/src/main/java/java/util/HashMap.java
index 28978d4..f79601f 100644
--- a/luni/src/main/java/java/util/HashMap.java
+++ b/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/luni/src/main/java/java/util/HashSet.java b/luni/src/main/java/java/util/HashSet.java
index 4c97ca5..aa5c3fb 100644
--- a/luni/src/main/java/java/util/HashSet.java
+++ b/luni/src/main/java/java/util/HashSet.java
@@ -121,7 +121,7 @@
             clone.backingMap = (HashMap<E, HashSet<E>>) backingMap.clone();
             return clone;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/IdentityHashMap.java b/luni/src/main/java/java/util/IdentityHashMap.java
index 053de1d..8d0f036 100644
--- a/luni/src/main/java/java/util/IdentityHashMap.java
+++ b/luni/src/main/java/java/util/IdentityHashMap.java
@@ -758,7 +758,7 @@
                     elementData.length);
             return cloneHashMap;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/LinkedList.java b/luni/src/main/java/java/util/LinkedList.java
index 64326e3..7a7e81f 100644
--- a/luni/src/main/java/java/util/LinkedList.java
+++ b/luni/src/main/java/java/util/LinkedList.java
@@ -402,7 +402,7 @@
             l.addAll(this);
             return l;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/Locale.java b/luni/src/main/java/java/util/Locale.java
index b1a1821..22cda76 100644
--- a/luni/src/main/java/java/util/Locale.java
+++ b/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.
@@ -275,7 +277,7 @@
         try {
             return super.clone();
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
@@ -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/luni/src/main/java/java/util/MapEntry.java b/luni/src/main/java/java/util/MapEntry.java
index 6a5bf0f..b84697b 100644
--- a/luni/src/main/java/java/util/MapEntry.java
+++ b/luni/src/main/java/java/util/MapEntry.java
@@ -43,7 +43,7 @@
         try {
             return super.clone();
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/Random.java b/luni/src/main/java/java/util/Random.java
index be27258..f893020 100644
--- a/luni/src/main/java/java/util/Random.java
+++ b/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/luni/src/main/java/java/util/Scanner.java b/luni/src/main/java/java/util/Scanner.java
index dd5c024..f1ca423 100644
--- a/luni/src/main/java/java/util/Scanner.java
+++ b/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/luni/src/main/java/java/util/TimeZone.java b/luni/src/main/java/java/util/TimeZone.java
index b4878ca..09dcae2 100644
--- a/luni/src/main/java/java/util/TimeZone.java
+++ b/luni/src/main/java/java/util/TimeZone.java
@@ -149,7 +149,7 @@
             TimeZone zone = (TimeZone) super.clone();
             return zone;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/TreeMap.java b/luni/src/main/java/java/util/TreeMap.java
index b97821f..67b39e8 100644
--- a/luni/src/main/java/java/util/TreeMap.java
+++ b/luni/src/main/java/java/util/TreeMap.java
@@ -61,7 +61,7 @@
 	        try {
 	            return super.clone();
 	        } catch (CloneNotSupportedException e) {
-	            return null;
+                throw new AssertionError(e); // android-changed
 	        }
 	    }
 
@@ -1065,7 +1065,7 @@
             }
             return clone;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/TreeSet.java b/luni/src/main/java/java/util/TreeSet.java
index 375b9c8..fcd6224 100644
--- a/luni/src/main/java/java/util/TreeSet.java
+++ b/luni/src/main/java/java/util/TreeSet.java
@@ -160,7 +160,7 @@
             }
             return clone;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/java/util/UnknownFormatFlagsException.java b/luni/src/main/java/java/util/UnknownFormatFlagsException.java
index 2a1b075..66d9076 100644
--- a/luni/src/main/java/java/util/UnknownFormatFlagsException.java
+++ b/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/luni/src/main/java/java/util/Vector.java b/luni/src/main/java/java/util/Vector.java
index 6a4060a..9a1b81c 100644
--- a/luni/src/main/java/java/util/Vector.java
+++ b/luni/src/main/java/java/util/Vector.java
@@ -265,7 +265,7 @@
             vector.elementData = elementData.clone();
             return vector;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java b/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java
deleted file mode 100644
index e3ea7b5..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.internal.io;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-
-/**
- * A simple cache implementation for file's canonical path. The cache has fixed
- * size <code> CACHE_SIZE </code> and cached elements would be expired. If
- * <code>put<code> method is invoked when cache is full, the oldest element will be removed.
- *
- */
-public class FileCanonPathCache {
-
-    static private class CacheElement {
-        String canonicalPath;
-
-        long timestamp;
-
-        public CacheElement(String path) {
-            this.canonicalPath = path;
-            this.timestamp = System.currentTimeMillis();
-        }
-    }
-
-    /**
-     * Max elemnts could be hold in the cache.
-     */
-    public static final int CACHE_SIZE = 256;
-
-    private static HashMap<String, CacheElement> cache = new HashMap<String, CacheElement>(
-            CACHE_SIZE);
-
-    /**
-     * FIFO queue for tracking age of elements.
-     */
-    private static LinkedList<String> list = new LinkedList<String>();
-
-    private static Object lock = new Object();
-
-    /**
-     * Expired time.
-     */
-    private static long timeout = 600000;
-
-    /**
-     * Retrieve element from cache.
-     * 
-     * @param path
-     *            absolute path.
-     * @return canonical path of <code>path</code> if it's in cache.
-     * 
-     */
-    public static String get(String path) {
-        CacheElement element = null;
-        synchronized (lock) {
-            element = cache.get(path);
-        }
-
-        if (element == null) {
-            return null;
-        }
-
-        long time = System.currentTimeMillis();
-        if (time - element.timestamp > timeout) {
-            // remove all elements older than this one
-            synchronized (lock) {
-                if (cache.get(path) != null) {
-                    String oldest = null;
-                    do {
-                        oldest = list.removeFirst();
-                        cache.remove(path);
-                    } while (!path.equals(oldest));
-                }
-            }
-            return null;
-        }
-
-        return element.canonicalPath;
-    }
-
-    /**
-     * Put element to cache.
-     * 
-     * @param path
-     *            absolute path.
-     * @param canonicalPath
-     *            the canonical path of <code>path</code>.
-     */
-    public static void put(String path, String canonicalPath) {
-        CacheElement element = new CacheElement(canonicalPath);
-        synchronized (lock) {
-            if (cache.size() >= CACHE_SIZE) {
-                // cache is full
-                String oldest = list.removeFirst();
-                cache.remove(oldest);
-            }
-            cache.put(path, element);
-            list.addLast(path);
-        }
-    }
-
-    /**
-     * Remove all elements from cache.
-     */
-    public static void clear() {
-        synchronized (lock) {
-            cache.clear();
-            list.clear();
-        }
-    }
-
-    public static long getTimeout() {
-        return timeout;
-    }
-
-    public static void setTimeout(long timeout) {
-        FileCanonPathCache.timeout = timeout;
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java
index 25d1e69..94719fe 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java
+++ b/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/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
index 24be092..bdd1d0a 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
@@ -88,7 +88,7 @@
             }
             return clone;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
rename to luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
index 2dea92b..1ba7d8c 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/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/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java
index ef68a71..c6bf994 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java
+++ b/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/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnectionImpl.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java
rename to luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnectionImpl.java
index 4d0aff7..2ad5b13 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/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/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
index 4db9910..b31cb39 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
@@ -42,7 +42,7 @@
      */
     @Override
     protected URLConnection openConnection(URL u) throws IOException {
-        return new JarURLConnection(u);
+        return new JarURLConnectionImpl(u);
     }
 
     /**
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnectionImpl.java
similarity index 70%
rename from luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java
rename to luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnectionImpl.java
index 34e7d07..493b768 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/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/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java b/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java
index 110a0fd..01319e1 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java
+++ b/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/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
index ac0c877..cbecab5 100644
--- a/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
@@ -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
@@ -344,7 +342,9 @@
 
     @Override
     public void setTimeToLive(int ttl) throws java.io.IOException {
-        setOption(IP_MULTICAST_TTL, Byte.valueOf((byte) (ttl & 0xFF)));
+        // BEGIN android-changed: native code wants an int anyway
+        setOption(IP_MULTICAST_TTL, Integer.valueOf(ttl));
+        // END android-changed
         if ((netImpl.getSocketFlags() & MULTICAST_TTL) != 0) {
             this.ttl = ttl;
         }
@@ -352,10 +352,9 @@
 
     @Override
     public void setTTL(byte ttl) throws java.io.IOException {
-        setOption(IP_MULTICAST_TTL, Byte.valueOf(ttl));
-        if ((netImpl.getSocketFlags() & MULTICAST_TTL) != 0) {
-            this.ttl = ttl;
-        }
+        // BEGIN android-changed: remove duplication
+        setTimeToLive(ttl);
+        // END android-changed
     }
 
     @Override
diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
index 9a3ae6e..6773fd4 100644
--- a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
@@ -560,10 +560,7 @@
         if (shutdownInput) {
             return -1;
         }
-        // BEGIN android-changed
-        // call receiveStream() instead of read()
-        int read = netImpl.receiveStream(fd, buffer, offset, count, receiveTimeout);
-        // END android-changed
+        int read = netImpl.read(fd, buffer, offset, count, receiveTimeout);
         // Return of zero bytes for a blocking socket means a timeout occurred
         if (read == 0) {
             throw new SocketTimeoutException();
@@ -580,9 +577,6 @@
             return netImpl.sendDatagram2(fd, buffer, offset, count, port,
                     address);
         }
-        // BEGIN android-changed
-        // call sendStream() instead of write()
-        return netImpl.sendStream(fd, buffer, offset, count);
-        // END android-changed
+        return netImpl.write(fd, buffer, offset, count);
     }
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java b/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java
index 4b0b4b4..d19206d 100644
--- a/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java
+++ b/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/luni/src/main/java/org/apache/harmony/luni/platform/FileDescriptorHandler.java b/luni/src/main/java/org/apache/harmony/luni/platform/FileDescriptorHandler.java
index 94dbba3..9afee7e 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/FileDescriptorHandler.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/FileDescriptorHandler.java
@@ -20,14 +20,14 @@
 import java.io.FileDescriptor;
 
 /**
- * This interface declares method to get wrapped <code>FileDescritpor</code>.
+ * This interface declares method to get wrapped <code>FileDescriptor</code>.
  */
 public interface FileDescriptorHandler {
 
     /**
-     * Get the wrapped <code>FileDescritpor</code>.
+     * Get the wrapped <code>FileDescriptor</code>.
      * 
-     * @return the wrapped <code>FileDescritpor</code>.
+     * @return the wrapped <code>FileDescriptor</code>.
      */
     FileDescriptor getFD();
 
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
index 7613f0e..bee1557 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
@@ -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/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java
index 6e8028a..f7a0209 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java
@@ -515,7 +515,7 @@
      *
      * @param fileDescriptor
      *            a handle to the file that is to be memory mapped.
-     * @param alignment
+     * @param offset
      *            the offset in the file where the mapping should begin.
      * @param size
      *            the number of bytes that are requested to map.
@@ -528,8 +528,10 @@
      * @throws IOException
      *             if an exception occurs mapping the file into memory.
      */
-    public int mmap(int fileDescriptor, long alignment, long size,  int mapMode)
+    // BEGIN android-changed: rename 'alignment' to 'offset'.
+    public int mmap(int fileDescriptor, long offset, long size, int mapMode)
             throws IOException;
+    // END android-changed
 
     /**
      * TODO: JavaDoc
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
index fb47f0d..71a272a 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
@@ -57,7 +57,7 @@
     public int read(FileDescriptor aFD, byte[] data, int offset, int count,
             int timeout) throws IOException;
 
-    public int readDirect(FileDescriptor aFD, int address, int offset, int count,
+    public int readDirect(FileDescriptor aFD, int address, int count,
             int timeout) throws IOException;
 
     public int write(FileDescriptor fd, byte[] data, int offset, int count)
@@ -66,11 +66,18 @@
     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;
 
-    public int connect(FileDescriptor aFD, int trafficClass,
+    // BEGIN android-changed (we always throw on error, the value returned was always 0)
+    public void connect(FileDescriptor aFD, int trafficClass,
             InetAddress inetAddress, int port) throws IOException;
+    // END android-changed
 
     // BEGIN android-changed
     public int connectWithTimeout(FileDescriptor aFD, int timeout,
@@ -119,18 +126,6 @@
     public void connectDatagram(FileDescriptor aFD, int port, int trafficClass,
             InetAddress inetAddress) throws SocketException;
 
-    /**
-     * @deprecated Use {@link #read(FileDescriptor, byte[], int, int, int)}
-     */
-    @Deprecated
-    public int receiveStream(FileDescriptor aFD, byte[] data, int offset,
-            int count, int timeout) throws IOException;
-
-    // BEGIN android-added
-    public int sendStream(FileDescriptor fd, byte[] data, int offset, int count)
-            throws IOException;
-    // END android-added
-
     public void shutdownInput(FileDescriptor descriptor) throws IOException;
 
     public void shutdownOutput(FileDescriptor descriptor) throws IOException;
@@ -166,9 +161,42 @@
     public InetAddress getSocketLocalAddress(FileDescriptor aFD,
             boolean preferIPv6Addresses);
 
-    public int[] select(FileDescriptor[] readFDs,
-            FileDescriptor[] writeFDs, long timeout)
+    // BEGIN android-changed
+    //     copied from a newer version of Harmony
+    /**
+     * Select the given file descriptors for read and write operations.
+     *
+     * <p>The first {@code numReadable} file descriptors of {@code readFDs} will
+     * be selected for read-ready operations. The first {@code numWritable} file
+     * descriptors in {@code writeFDs} will be selected for write-ready
+     * operations. A file descriptor can appear in either or both and must not
+     * be null. If the file descriptor is closed during the select the behavior
+     * depends upon the underlying OS.
+     *
+     * @param readFDs
+     *            all sockets interested in read and accept
+     * @param writeFDs
+     *            all sockets interested in write and connect
+     * @param numReadable
+     *            the size of the subset of readFDs to read or accept.
+     * @param numWritable
+     *            the size of the subset of writeFDs to write or connect
+     * @param timeout
+     *            timeout in milliseconds
+     * @param flags
+     *            for output. Length must be at least {@code numReadable
+     *            + numWritable}. Upon returning, each element describes the
+     *            state of the descriptor in the corresponding read or write
+     *            array. See {@code SelectorImpl.READABLE} and {@code
+     *            SelectorImpl.WRITEABLE}
+     * @return true
+     *            unless selection timed out or was interrupted
+     * @throws SocketException
+     */
+    public boolean select(FileDescriptor[] readFDs, FileDescriptor[] writeFDs,
+            int numReadable, int numWritable, long timeout, int[] flags)
             throws SocketException;
+    // END android-changed
 
     /*
      * Query the IP stack for the local port to which this socket is bound.
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
index 08bdac6..b7a62e2 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
@@ -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/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
index 0061d2a..b490da5 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
@@ -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
@@ -612,20 +608,17 @@
      */
     public native void setAddress(int address, int value);
 
-    /*
-         * Memory mapped file
-         */
-    private native int mmapImpl(int fileDescriptor, long alignment,
-            long size, int mapMode);
+    // BEGIN android-changed: more error checking, rename 'alignment' to 'offset'.
+    private native int mmapImpl(int fd, long offset, long size, int mapMode);
 
-    public int mmap(int fileDescriptor, long alignment, long size,
-            int mapMode) throws IOException {
-        int address = mmapImpl(fileDescriptor, alignment, size, mapMode);
-        if (address == -1) {
-            throw new IOException();
+    public int mmap(int fd, long offset, long size, int mapMode) throws IOException {
+        // Check just those errors mmap(2) won't detect.
+        if (offset < 0 || size < 0 || offset > Integer.MAX_VALUE || size > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("offset=" + offset + " size=" + size);
         }
-        return address;
+        return mmapImpl(fd, offset, size, mapMode);
     }
+    // END android-changed
 
     private native void unmapImpl(int addr, long size);
 
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
index bd6a6097..9901412 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
@@ -109,13 +109,12 @@
 
     static native void socketBindImpl(FileDescriptor aFD, int port, InetAddress inetAddress) throws SocketException;
 
-    public int connect(FileDescriptor fd, int trafficClass,
+    // BEGIN android-changed (removed unused return value and useless native method)
+    public void connect(FileDescriptor fd, int trafficClass,
             InetAddress inetAddress, int port) throws IOException{
-        return connectSocketImpl(fd, trafficClass, inetAddress, port);
+        connectStreamWithTimeoutSocketImpl(fd, port, 0, trafficClass, inetAddress);
     }
-
-    static native int connectSocketImpl(FileDescriptor aFD,
-            int trafficClass, InetAddress inetAddress, int port);
+    // END android-changed
 
     public void connectDatagram(FileDescriptor fd, int port,
             int trafficClass, InetAddress inetAddress) throws SocketException {
@@ -290,11 +289,7 @@
     static native Object getSocketOptionImpl(FileDescriptor aFD, int opt)
             throws SocketException;
 
-    public Channel inheritedChannel() {
-        return inheritedChannelImpl();
-    }
-
-    native Channel inheritedChannelImpl();
+    public native Channel inheritedChannel();
 
     // BEGIN android-removed
     // public boolean isReachableByICMP(final InetAddress dest,
@@ -376,6 +371,12 @@
      */
     public int read(FileDescriptor fd, byte[] data, int offset, int count,
             int timeout) throws IOException {
+        // BEGIN android-added safety!
+        if (offset < 0 || count < 0 || offset > data.length - count) {
+            throw new IllegalArgumentException("data.length=" + data.length + " offset=" + offset +
+                    " count=" + count);
+        }
+        // END android-added
         return readSocketImpl(fd, data, offset, count, timeout);
     }
 
@@ -400,12 +401,12 @@
      * @throws IOException
      *             if an underlying socket exception occurred
      */
-    public int readDirect(FileDescriptor fd, int address, int offset, int count,
+    public int readDirect(FileDescriptor fd, int address, int count,
             int timeout) throws IOException {
-        return readSocketDirectImpl(fd, address, offset, count, timeout);
+        return readSocketDirectImpl(fd, address, count, timeout);
     }
 
-    static native int readSocketDirectImpl(FileDescriptor aFD, int address, int offset, int count,
+    static native int readSocketDirectImpl(FileDescriptor aFD, int address, int count,
             int timeout) throws IOException;
 
     /**
@@ -454,56 +455,7 @@
             int receiveTimeout, boolean peek) throws IOException;
 
     /**
-     * Receive at most <code>count</code> bytes into the buffer
-     * <code>data</code> at the <code>offset</code> on the socket.
-     *
-     * @param aFD
-     *            the socket FileDescriptor
-     * @param data
-     *            the receive buffer
-     * @param offset
-     *            the offset into the buffer
-     * @param count
-     *            the max number of bytes to receive
-     * @param timeout
-     *            the max time the read operation should block waiting for data
-     * @return the actual number of bytes read
-     * @throws IOException
-     * @throws SocketException
-     *             if an error occurs while reading
-     * @deprecated use {@link #read(FileDescriptor, byte[], int, int, int)}
-     */
-    public int receiveStream(FileDescriptor aFD, byte[] data,
-            int offset, int count, int timeout) throws IOException {
-        return receiveStreamImpl(aFD, data, offset, count, timeout);
-    }
-
-    static native int receiveStreamImpl(FileDescriptor aFD, byte[] data,
-            int offset, int count, int timeout) throws IOException;
-
-    // BEGIN android-added
-    /**
-     * Send <code>count</code> bytes from the buffer <code>data</code> at
-     * the <code>offset</code>, on the socket.
-     *
-     * @param fd
-     *
-     * @param data the send buffer @param offset the offset into the buffer
-     * @param count the number of bytes to receive @return int the actual number
-     * of bytes sent @throws IOException @exception SocketException if an error
-     * occurs while writing
-     */
-    public int sendStream(FileDescriptor fd, byte[] data, int offset, int count)
-            throws IOException {
-        return sendStreamImpl(fd, data, offset, count);
-    }
-
-    static native int sendStreamImpl(FileDescriptor fd, byte[] data,
-            int offset, int count) throws IOException;
-    // END android-added
-
-    /**
-     * Recieve data on the connected socket into the specified buffer. The
+     * Receive data on the connected socket into the specified buffer. The
      * packet fields <code>data</code> and <code>length</code> are passed in
      * addition to <code>packet</code> to eliminate the JNI field access calls.
      *
@@ -546,58 +498,33 @@
             DatagramPacket packet, int address, int offset, int length,
             int receiveTimeout, boolean peek) throws IOException;
 
-    /**
-     * Select the given file descriptors for read and write operations.
-     *
-     * The file descriptors passed in as readFDs will be selected for read-ready
-     * operations, and those in the writeFDs will be selected for write-ready
-     * operations. A file descriptor can appear in either or both array, and
-     * must not be <code>null</code>. If the file descriptor is closed during
-     * the select the behavior depends upon the underlying OS.
-     *
-     * Upon return the result is a single array of length
-     * <code>readFDs.length</code> + <code>writeFDs.length</code> laid out as
-     * the result of the select operation on the corresponding file descriptors.
-     *
-     * @param readFDs
-     *            all sockets interested in read and accept
-     * @param writeFDs
-     *            all sockets interested in write and connect
-     * @param timeout
-     *            timeout in milliseconds
-     * @return each element describes the corresponding state of the descriptor
-     *         in the read and write arrays.
-     * @throws SocketException
-     */
-    public int[] select(FileDescriptor[] readFDs, FileDescriptor[] writeFDs,
-            long timeout) throws SocketException {
-        int countRead = readFDs.length;
-        int countWrite = writeFDs.length;
-        int result = 0;
-        if (0 == countRead + countWrite) {
-            return (new int[0]);
+    // BEGIN android-changed
+    //     copied from a newer version of Harmony
+    public boolean select(FileDescriptor[] readFDs, FileDescriptor[] writeFDs,
+            int numReadable, int numWritable, long timeout, int[] flags)
+            throws SocketException {
+        if (numReadable < 0 || numWritable < 0) {
+            throw new IllegalArgumentException();
         }
-        int[] flags = new int[countRead + countWrite];
 
-        assert validateFDs(readFDs, writeFDs) : "Invalid file descriptor arrays"; //$NON-NLS-1$
-
-        // handle timeout in native
-        result = selectImpl(readFDs, writeFDs, countRead, countWrite, flags,
-                timeout);
-
-        if (0 <= result) {
-            return flags;
+        int total = numReadable + numWritable;
+        if (total == 0) {
+            return true;
         }
-        if (ERRORCODE_SOCKET_TIMEOUT == result ||
-                ERRORCODE_SOCKET_INTERRUPTED == result) {
-            return new int[0];
-        }
-        throw new SocketException();
+
+        assert validateFDs(readFDs, writeFDs, numReadable, numWritable) : "Invalid file descriptor arrays"; //$NON-NLS-1$
+
+        // BEGIN android-changed: handle errors in native code
+        return selectImpl(readFDs, writeFDs, numReadable, numWritable, flags, timeout);
+        // END android-changed
     }
+    // END android-changed
 
-    static native int selectImpl(FileDescriptor[] readfd,
+    // BEGIN android-changed: return type (we throw in native code, with descriptive errors)
+    static native boolean selectImpl(FileDescriptor[] readfd,
             FileDescriptor[] writefd, int cread, int cwirte, int[] flags,
             long timeout);
+    // END android-changed
 
     /**
      * Send the <code>data</code> to the address and port to which the was
@@ -781,6 +708,25 @@
         return true;
     }
 
+    // BEGIN android-changed
+    //     copied from a newer version of Harmony
+    private boolean validateFDs(FileDescriptor[] readFDs,
+            FileDescriptor[] writeFDs, int countRead, int countWrite) {
+        for (int i = 0; i < countRead; ++i) {
+            // Also checks fd not null
+            if (!readFDs[i].valid()) {
+                return false;
+            }
+        }
+        for (int i = 0; i < countWrite; ++i) {
+            if (!writeFDs[i].valid()) {
+                return false;
+            }
+        }
+        return true;
+    }
+    // END android-changed
+
     /**
      * Write bytes from a byte array to a socket.
      *
@@ -829,4 +775,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/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java b/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java
index 43702b2..0149cac 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java
+++ b/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/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java b/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java
index 9ac8064..3590604 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java
+++ b/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/luni/src/main/java/org/apache/harmony/luni/util/ErrorCodeException.java b/luni/src/main/java/org/apache/harmony/luni/util/ErrorCodeException.java
deleted file mode 100644
index 92258ef..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/util/ErrorCodeException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.luni.util;
-
-public class ErrorCodeException extends Exception {
-
-    private static final long serialVersionUID = -8716868971626579265L;
-   
-    private int errorCode;
-  
-    public ErrorCodeException(int errorCode){
-        this.errorCode = errorCode;
-    }
-    
-    public int getErrorCode(){
-        return errorCode;
-    }
-
-}
diff --git a/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties b/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
index 280a8f5..b6cbcef 100644
--- a/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
+++ b/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
@@ -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/luni/src/main/native/cbigint.c b/luni/src/main/native/cbigint.c
index d327940..92b2992 100644
--- a/luni/src/main/native/cbigint.c
+++ b/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/luni/src/main/native/fltconst.h b/luni/src/main/native/fltconst.h
index 03a97cd..940d5fc 100644
--- a/luni/src/main/native/fltconst.h
+++ b/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/luni/src/main/native/java_net_InetAddress.cpp b/luni/src/main/native/java_net_InetAddress.cpp
index d7b4931..2af493c 100644
--- a/luni/src/main/native/java_net_InetAddress.cpp
+++ b/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/luni/src/main/native/java_net_NetworkInterface.c b/luni/src/main/native/java_net_NetworkInterface.c
deleted file mode 100644
index db6d503..0000000
--- a/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/luni/src/main/native/java_net_NetworkInterface.cpp b/luni/src/main/native/java_net_NetworkInterface.cpp
new file mode 100644
index 0000000..3ea6657
--- /dev/null
+++ b/luni/src/main/native/java_net_NetworkInterface.cpp
@@ -0,0 +1,268 @@
+/*
+ *  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 <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <net/if.h> // Note: Can't appear before <sys/socket.h> on OS X.
+
+// There are several ways that an interface index might be referenced
+// out of an ifreq struct, depending on the platform.
+#if defined(ifr_ifindex)
+// Linux: No need to do anything.
+#elif defined(ifr_index)
+#define ifr_ifindex ifr_index // BSD
+#elif defined(ifr_intval)
+#define ifr_ifindex ifr_intval // OS X
+#else
+#error "Unknown how to refer to an interface index on this platform."
+#endif
+
+// 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");
+}
+
+// TODO(enh): move to JNIHelp.h
+static void jniThrowSocketException(JNIEnv* env) {
+    char buf[BUFSIZ];
+    jniThrowException(env, "java/net/SocketException",
+            jniStrError(errno, buf, sizeof(buf)));
+}
+
+// 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/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
index 38f3d36..1e1893e 100644
--- a/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
+++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
@@ -14,401 +14,327 @@
  *  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 <stdlib.h>
-#include <sys/sendfile.h>
-#include <sys/uio.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/ioctl.h>
+#include <sys/uio.h>
 
-typedef struct socket_struct {
-    int sock;
-    unsigned short family;
-} socket_struct;
+#if HAVE_SYS_SENDFILE_H
+#include <sys/sendfile.h>
+#else
+/*
+ * Define a small adapter function: sendfile() isn't part of a standard,
+ * and its definition differs between Linux, BSD, and OS X. This version
+ * works for OS X but will probably not work on other BSDish systems.
+ * Note: We rely on function overloading here to define a same-named
+ * function with different arguments.
+ */
+#include <sys/socket.h>
+#include <sys/types.h>
+static inline ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
+        size_t count) {
+    off_t len = count;
+    int result = sendfile(in_fd, out_fd, *offset, &len, NULL, 0);
+    if (result < 0) {
+        return -1;
+    }
+    return len;
+}
+#endif
 
 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 +342,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 +434,7 @@
               mode = 0600;
               break;
       case 256:
-              flags = HyOpenWrite | HyOpenCreate | HyOpenAppend; 
+              flags = HyOpenWrite | HyOpenCreate | HyOpenAppend;
               mode = 0600;
               break;
     }
@@ -596,116 +442,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 +500,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/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
index 2e814cc..1d63faf 100644
--- a/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
+++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
@@ -34,12 +34,9 @@
     jobject runtimeInstance;
 } gIDCache;
 
-#undef MMAP_READ_ONLY
-#define MMAP_READ_ONLY 1L
-#undef MMAP_READ_WRITE
-#define MMAP_READ_WRITE 2L
-#undef MMAP_WRITE_COPY
-#define MMAP_WRITE_COPY 4L
+static const int MMAP_READ_ONLY = 1;
+static const int MMAP_READ_WRITE = 2;
+static const int MMAP_WRITE_COPY = 4;
 
 /*
  * Class:     org_apache_harmony_luni_platform_OSMemory
@@ -144,9 +141,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 +162,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
@@ -431,36 +426,33 @@
  * Method:    mmapImpl
  * Signature: (IJJI)I
  */
-static jint harmony_nio_mmapImpl(JNIEnv *_env, jobject _this, jint fd, 
-        jlong alignment, jlong size, jint mmode) {
-    void *mapAddress = NULL;
+static jint harmony_nio_mmapImpl(JNIEnv* env, jobject, jint fd, 
+        jlong offset, jlong size, jint mapMode) {
     int prot, flags;
-          
-    // Convert from Java mapping mode to port library mapping mode.
-    switch (mmode) {
-      case MMAP_READ_ONLY:
-              prot = PROT_READ;
-              flags = MAP_SHARED;
-              break;
-      case MMAP_READ_WRITE:
-              prot = PROT_READ|PROT_WRITE;
-              flags = MAP_SHARED;
-              break;
-      case MMAP_WRITE_COPY:
-              prot = PROT_READ|PROT_WRITE;
-              flags = MAP_PRIVATE;
-              break;
-      default:
-              return -1;
-    }
-
-    mapAddress = mmap(0, (size_t)(size&0x7fffffff), prot, flags,fd,
-            (off_t)(alignment&0x7fffffff));
-    if (mapAddress == MAP_FAILED) {
+    switch (mapMode) {
+    case MMAP_READ_ONLY:
+        prot = PROT_READ;
+        flags = MAP_SHARED;
+        break;
+    case MMAP_READ_WRITE:
+        prot = PROT_READ|PROT_WRITE;
+        flags = MAP_SHARED;
+        break;
+    case MMAP_WRITE_COPY:
+        prot = PROT_READ|PROT_WRITE;
+        flags = MAP_PRIVATE;
+        break;
+    default:
+        jniThrowIOException(env, EINVAL);
+        LOGE("bad mapMode %i", mapMode);
         return -1;
     }
-    
-    return (jint) mapAddress;
+
+    void* mapAddress = mmap(0, size, prot, flags, fd, offset);
+    if (mapAddress == MAP_FAILED) {
+        jniThrowIOException(env, errno);
+    }
+    return reinterpret_cast<uintptr_t>(mapAddress);
 }
 
 /*
@@ -496,15 +488,6 @@
     return -1;
 }
 
-int getPageSize() {
-    static int page_size = 0;
-    if(page_size==0)
-    {
-        page_size=getpagesize();
-    }
-    return page_size;
-}
-
 /*
  * Class:     org_apache_harmony_luni_platform_OSMemory
  * Method:    isLoadedImpl
@@ -513,18 +496,16 @@
 static jboolean harmony_nio_isLoadedImpl(JNIEnv *_env, jobject _this, 
         jint address, jlong size) {
 
+    static int page_size = getpagesize();
     jboolean result = 0;
     jint m_addr = (jint)address;
-    int page_size = getPageSize();
-    unsigned char* vec = NULL;
-    int page_count = 0;
     
     int align_offset = m_addr%page_size;// addr should align with the boundary of a page.
     m_addr -= align_offset;
     size   += align_offset;
-    page_count = (size+page_size-1)/page_size;
+    int page_count = (size+page_size-1)/page_size;
     
-    vec = (unsigned char *) malloc(page_count*sizeof(char));
+    unsigned char* vec = (unsigned char *) malloc(page_count*sizeof(char));
     
     if (mincore((void *)m_addr, size, (MINCORE_POINTER_TYPE) vec)==0) {
         // or else there is error about the mincore and return false;
diff --git a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index 635e1af..af2e08a 100644
--- a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -23,29 +23,40 @@
 
 #define LOG_TAG "OSNetworkSystem"
 
+#include "AndroidSystemNatives.h"
 #include "JNIHelp.h"
 #include "jni.h"
-#include "errno.h"
 
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <netdb.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <sys/time.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
 #include <sys/un.h>
-
-#include <cutils/properties.h>
-#include <cutils/adb_networking.h>
-#include "AndroidSystemNatives.h"
+#include <unistd.h>
 
 // Temporary hack to build on systems that don't have up-to-date libc headers.
 #ifndef IPV6_TCLASS
-#define IPV6_TCLASS 67
+#ifdef __linux__
+#define IPV6_TCLASS 67 // Linux
+#else
+#define IPV6_TCLASS -1 // BSD(-like); TODO: Something better than this!
+#endif
+#endif
+
+/*
+ * TODO: The multicast code is highly platform-dependent, and for now
+ * we just punt on anything but Linux.
+ */
+#ifdef __linux__
+#define ENABLE_MULTICAST
 #endif
 
 /**
@@ -54,7 +65,6 @@
  *
  * @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 */
@@ -69,7 +79,6 @@
 #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 */
@@ -113,9 +122,7 @@
 #define JAVASOCKOPT_IP_TOS 3
 #define JAVASOCKOPT_SO_REUSEADDR 4
 #define JAVASOCKOPT_SO_KEEPALIVE 8
-#define JAVASOCKOPT_MCAST_TIME_TO_LIVE 10 /* Currently unused */
-#define JAVASOCKOPT_SO_BINDADDR 15
-#define JAVASOCKOPT_MCAST_INTERFACE 16
+#define JAVASOCKOPT_IP_MULTICAST_IF 16
 #define JAVASOCKOPT_MCAST_TTL 17
 #define JAVASOCKOPT_IP_MULTICAST_LOOP 18
 #define JAVASOCKOPT_MCAST_ADD_MEMBERSHIP 19
@@ -144,19 +151,9 @@
 #define SOCKET_OP_NONE 0
 #define SOCKET_OP_READ 1
 #define SOCKET_OP_WRITE 2
-#define SOCKET_READ_WRITE 3
-
-#define SOCKET_MSG_PEEK 1
-#define SOCKET_MSG_OOB 2
 
 #define SOCKET_NOFLAGS 0
 
-#undef BUFFERSIZE
-#define BUFFERSIZE 2048
-
-// wait for 500000 usec = 0.5 second
-#define SEND_RETRY_TIME 500000
-
 // Local constants for getOrSetSocketOption
 #define SOCKOPT_GET 1
 #define SOCKOPT_SET 2
@@ -178,8 +175,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,50 +184,72 @@
     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);
 
 /**
  * Throws an SocketException with the message affiliated with the errorCode.
+ * 
+ * @deprecated: 'errorCode' is one of the bogus SOCKERR_ values, *not* errno.
+ * jniThrowSocketException is the better choice.
  */
 static void throwSocketException(JNIEnv *env, int errorCode) {
     jniThrowException(env, "java/net/SocketException",
         netLookupErrorString(errorCode));
 }
 
-/**
- * Throws an IOException with the given message.
- */
-static void throwIOExceptionStr(JNIEnv *env, const char *message) {
-    jniThrowException(env, "java/io/IOException", message);
+// TODO(enh): move to JNIHelp.h
+static void jniThrowExceptionWithErrno(JNIEnv* env,
+        const char* exceptionClassName, int error) {
+    char buf[BUFSIZ];
+    jniThrowException(env, exceptionClassName,
+            jniStrError(error, buf, sizeof(buf)));
 }
 
-/**
- * Throws a NullPointerException.
- */
+static void jniThrowBindException(JNIEnv* env, int error) {
+    jniThrowExceptionWithErrno(env, "java/net/BindException", error);
+}
+
+static void jniThrowSocketException(JNIEnv* env, int error) {
+    jniThrowExceptionWithErrno(env, "java/net/SocketException", error);
+}
+
+static void jniThrowSocketTimeoutException(JNIEnv* env, int error) {
+    jniThrowExceptionWithErrno(env, "java/net/SocketTimeoutException", error);
+}
+
+// TODO(enh): move to JNIHelp.h
 static void throwNullPointerException(JNIEnv *env) {
     jniThrowException(env, "java/lang/NullPointerException", NULL);
 }
 
+// Used by functions that shouldn't throw SocketException. (These functions
+// aren't meant to see bad addresses, so seeing one really does imply an
+// internal error.)
+// TODO: fix the code (native and Java) so we don't paint ourselves into this corner.
+static void jniThrowBadAddressFamily(JNIEnv* env) {
+    jniThrowException(env, "java/lang/IllegalArgumentException", "Bad address family");
+}
+
+static bool jniGetFd(JNIEnv* env, jobject fileDescriptor, int& fd) {
+    fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+    if (fd == -1) {
+        jniThrowSocketException(env, EBADF);
+        return false;
+    }
+    return true;
+}
+
 /**
- * Converts a native address structure to a Java 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.
- *
- * @param address the sockaddr_storage structure to convert
- *
- * @exception SocketException the address family is unknown, or out of memory
- *
+ * Converts a native address structure to a Java byte array.
  */
 static jbyteArray socketAddressToByteArray(JNIEnv *env,
         struct sockaddr_storage *address) {
@@ -248,13 +265,12 @@
         rawAddress = &sin6->sin6_addr.s6_addr;
         addressLength = 16;
     } else {
-        throwSocketException(env, SOCKERR_BADAF);
+        jniThrowBadAddressFamily(env);
         return NULL;
     }
 
     jbyteArray byteArray = env->NewByteArray(addressLength);
     if (byteArray == NULL) {
-        throwSocketException(env, SOCKERR_NOBUFFERS);
         return NULL;
     }
     env->SetByteArrayRegion(byteArray, 0, addressLength, (jbyte *) rawAddress);
@@ -281,208 +297,124 @@
 }
 
 /**
- * Checks whether a socket address structure contains an IPv4-mapped address.
- *
- * @param address the socket address structure to check
- * @return true if address contains an IPv4-mapped address, false otherwise.
+ * Obtain the socket address family from an existing socket.
+ * 
+ * @param socket the file descriptor of the socket to examine
+ * @return an integer, the address family of the socket
  */
-static bool isMappedAddress(sockaddr *address) {
-    if (! address || address->sa_family != AF_INET6) {
-        return false;
+static int getSocketAddressFamily(int socket) {
+    sockaddr_storage ss;
+    socklen_t namelen = sizeof(ss);
+    int ret = getsockname(socket, (sockaddr*) &ss, &namelen);
+    if (ret != 0) {
+        return AF_UNSPEC;
+    } else {
+        return ss.ss_family;
     }
-    in6_addr addr = ((sockaddr_in6 *) address)->sin6_addr;
-    return (addr.s6_addr32[0] == 0 &&
-            addr.s6_addr32[1] == 0 &&
-            addr.s6_addr32[2] == htonl(0xffff));
 }
 
-/**
- * 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.
- *
- * @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 byteArrayToInetAddress(JNIEnv* env, jbyteArray byteArray) {
+    if (byteArray == NULL) {
         return NULL;
-
+    }
     return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
             gCachedFields.iaddr_getbyaddress, byteArray);
 }
 
 /**
- * Converts an IPv4-mapped IPv6 address to an IPv4 address. Performs no error
- * checking.
+ * Converts a native address structure to an InetAddress object.
+ * Throws a NullPointerException or an IOException in case of
+ * error.
  *
- * @param address the address to convert. Must contain an IPv4-mapped address.
- * @param outputAddress the converted address. Will contain an IPv4 address.
+ * @param sockAddress the sockaddr_storage structure to convert
+ *
+ * @return a jobject representing an InetAddress
  */
-static void convertMappedToIpv4(sockaddr_in6 *sin6, sockaddr_in *sin) {
-  memset(sin, 0, sizeof(*sin));
-  sin->sin_family = AF_INET;
-  sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
-  sin->sin_port = sin6->sin6_port;
+jobject socketAddressToInetAddress(JNIEnv* env, sockaddr_storage* sockAddress) {
+    jbyteArray byteArray = socketAddressToByteArray(env, sockAddress);
+    return byteArrayToInetAddress(env, byteArray);
 }
 
 /**
- * Converts an IPv4 address to an IPv4-mapped IPv6 address. Performs no error
- * checking.
- *
- * @param address the address to convert. Must contain an IPv4 address.
- * @param outputAddress the converted address. Will contain an IPv6 address.
+ * Converts an IPv4 address to an IPv4-mapped IPv6 address if fd is an IPv6
+ * socket.
+ * @param fd the socket.
+ * @param sin_ss the address.
+ * @param sin6_ss scratch space where we can store the mapped address if necessary.
  * @param mapUnspecified if true, convert 0.0.0.0 to ::ffff:0:0; if false, to ::
+ * @return either sin_ss or sin6_ss, depending on which the caller should use.
  */
-static void convertIpv4ToMapped(struct sockaddr_in *sin,
-        struct sockaddr_in6 *sin6, bool mapUnspecified) {
-  memset(sin6, 0, sizeof(*sin6));
-  sin6->sin6_family = AF_INET6;
-  sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
-  if (sin->sin_addr.s_addr != 0  || mapUnspecified) {
-      sin6->sin6_addr.s6_addr32[2] = htonl(0xffff);
-  }
-  sin6->sin6_port = sin->sin_port;
+static const sockaddr* convertIpv4ToMapped(int fd,
+        const sockaddr_storage* sin_ss, sockaddr_storage* sin6_ss, bool mapUnspecified) {
+    // We need to map if we have an IPv4 address but an IPv6 socket.
+    bool needsMapping = (sin_ss->ss_family == AF_INET && getSocketAddressFamily(fd) == AF_INET6);
+    if (!needsMapping) {
+        return reinterpret_cast<const sockaddr*>(sin_ss);
+    }
+    // Map the IPv4 address in sin_ss into an IPv6 address in sin6_ss.
+    const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(sin_ss);
+    sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(sin6_ss);
+    memset(sin6, 0, sizeof(*sin6));
+    sin6->sin6_family = AF_INET6;
+    sin6->sin6_port = sin->sin_port;
+    if (sin->sin_addr.s_addr != 0 || mapUnspecified) {
+        memset(&(sin6->sin6_addr.s6_addr[10]), 0xff, 2);
+    }
+    memcpy(&sin6->sin6_addr.s6_addr[12], &sin->sin_addr.s_addr, 4);
+    return reinterpret_cast<const sockaddr*>(sin6_ss);
 }
 
 /**
  * Converts an InetAddress object and port number to a native address structure.
  * Throws a NullPointerException or a SocketException in case of
- * error. This is signaled by a return value of -1. The normal
- * return value is 0.
- *
- * @param inetaddress the InetAddress object to convert
- * @param port the port number
- * @param sockaddress the sockaddr_storage structure to write to
- *
- * @return 0 on success, a system error code on failure
- *
- * @exception SocketError if the address family is unknown
+ * error.
  */
-static int byteArrayToSocketAddress(JNIEnv *env,
-        jbyteArray addressByteArray, int port, sockaddr_storage *sockaddress) {
-    if (addressByteArray == NULL) {
-      throwNullPointerException(env);
-      return EFAULT;
+static bool byteArrayToSocketAddress(JNIEnv *env,
+        jbyteArray addressBytes, int port, sockaddr_storage *sockaddress) {
+    if (addressBytes == NULL) {
+        throwNullPointerException(env);
+        return false;
     }
-    size_t addressLength = env->GetArrayLength(addressByteArray);
 
     // Convert the IP address bytes to the proper IP address type.
+    size_t addressLength = env->GetArrayLength(addressBytes);
+    memset(sockaddress, 0, sizeof(*sockaddress));
     if (addressLength == 4) {
         // IPv4 address.
-        sockaddr_in *sin = (sockaddr_in *) sockaddress;
-        memset(sin, 0, sizeof(sockaddr_in));
+        sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(sockaddress);
         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;
-        memset(sin6, 0, sizeof(sockaddr_in6));
+        sockaddr_in6 *sin6 = reinterpret_cast<sockaddr_in6*>(sockaddress);
         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);
-        return EAFNOSUPPORT;
+        jniThrowBadAddressFamily(env);
+        return false;
     }
-    return 0;
+    return true;
 }
 
 /**
  * Converts an InetAddress object and port number to a native address structure.
- * Throws a NullPointerException or a SocketException in case of
- * error. This is signaled by a return value of -1. The normal
- * return value is 0.
- *
- * @param inetaddress the InetAddress object to convert
- * @param port the port number
- * @param sockaddress the sockaddr_storage structure to write to
- *
- * @return 0 on success, -1 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 bool 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);
-
-    return byteArrayToSocketAddress(env, addressByteArray, port, sockaddress);
-}
-
-/**
- * Convert a sockaddr_storage structure to a Java string.
- *
- * @param address pointer to sockaddr_storage structure to convert.
- * @param withPort whether to include the port number in the output as well.
- *
- * @return 0 on success, a getnameinfo return code on failure.
- *
- * @throws SocketException the address family was unknown.
- */
-static int socketAddressToString(sockaddr_storage *address, char *ipString,
-        int len, bool withPort) {
-    // TODO: getnameinfo seems to want its length parameter to be exactly
-    // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
-    // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
-    // then remove this hack.
-    int size;
-    if (address->ss_family == AF_INET) {
-        size = sizeof(sockaddr_in);
-    } else if (address->ss_family == AF_INET6) {
-        size = sizeof(sockaddr_in6);
-    } else {
-        errno = EAFNOSUPPORT;
-        return EAI_SYSTEM;
+    if (inetaddress == NULL) {
+        throwNullPointerException(env);
+        return false;
     }
+    jbyteArray addressBytes =
+        reinterpret_cast<jbyteArray>(env->GetObjectField(inetaddress,
+            gCachedFields.iaddr_ipaddress));
 
-    char tmp[INET6_ADDRSTRLEN];
-    int result = getnameinfo((sockaddr *)address, size, tmp, sizeof(tmp), NULL,
-            0, NI_NUMERICHOST);
-    if (result != 0) {
-        return result;
-    }
-
-    int port;
-    if (withPort) {
-        if (address->ss_family == AF_INET6) {
-            sockaddr_in6 *sin6 = (sockaddr_in6 *) address;
-            port = ntohs(sin6->sin6_port);
-            snprintf(ipString, len, "[%s]:%d", tmp, port);
-        } else {
-            sockaddr_in *sin = (sockaddr_in *) address;
-            port = ntohs(sin->sin_port);
-            snprintf(ipString, len, "%s:%d", tmp, port);
-        }
-    } else {
-        strncpy(ipString, tmp, len);
-    }
-    return 0;
+    return byteArrayToSocketAddress(env, addressBytes, port, sockaddress);
 }
 
 /**
@@ -491,30 +423,35 @@
  * @param addressByteArray the byte array to convert.
  *
  * @return a string with the textual representation of the address.
- *
- * @throws SocketException the address family was unknown.
  */
-static jstring osNetworkSystem_byteArrayToIpString(JNIEnv *env, jclass clazz,
+static jstring osNetworkSystem_byteArrayToIpString(JNIEnv* env, jclass,
         jbyteArray byteArray) {
-    // For compatibility, ensure that an UnknownHostException is thrown if the
-    // address is null.
     if (byteArray == NULL) {
-        jniThrowException(env, "java/net/UnknownHostException",
-                strerror(EFAULT));
+        throwNullPointerException(env);
         return NULL;
     }
-    struct sockaddr_storage ss;
-    int ret = byteArrayToSocketAddress(env, byteArray, 0, &ss);
-    if (ret) {
-        jniThrowException(env, "java/net/UnknownHostException", strerror(ret));
+    sockaddr_storage ss;
+    if (!byteArrayToSocketAddress(env, byteArray, 0, &ss)) {
+        return NULL;
+    }
+    // TODO: getnameinfo seems to want its length parameter to be exactly
+    // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
+    // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
+    // then remove this hack.
+    int sa_size;
+    if (ss.ss_family == AF_INET) {
+        sa_size = sizeof(sockaddr_in);
+    } else if (ss.ss_family == AF_INET6) {
+        sa_size = sizeof(sockaddr_in6);
+    } else {
+        jniThrowBadAddressFamily(env);
         return NULL;
     }
     char ipString[INET6_ADDRSTRLEN];
-    ret = socketAddressToString(&ss, ipString, sizeof(ipString), false);
-    if (ret) {
-        env->ExceptionClear();
-        jniThrowException(env, "java/net/UnknownHostException",
-                gai_strerror(ret));
+    int rc = getnameinfo(reinterpret_cast<sockaddr*>(&ss), sa_size,
+            ipString, sizeof(ipString), NULL, 0, NI_NUMERICHOST);
+    if (rc != 0) {
+        jniThrowException(env, "java/net/UnknownHostException", gai_strerror(rc));
         return NULL;
     }
     return env->NewStringUTF(ipString);
@@ -541,7 +478,7 @@
  *
  * @throws UnknownHostException the IP address was invalid.
  */
-static jbyteArray osNetworkSystem_ipStringToByteArray(JNIEnv *env, jclass clazz,
+static jbyteArray osNetworkSystem_ipStringToByteArray(JNIEnv* env, jclass,
         jstring javaString) {
     if (javaString == NULL) {
         throwNullPointerException(env);
@@ -564,27 +501,34 @@
     memset(&hints, 0, sizeof(hints));
     hints.ai_flags = AI_NUMERICHOST;
 
-    sockaddr_in sin;
-    addrinfo *res = NULL;
+    sockaddr_storage ss;
+    memset(&ss, 0, sizeof(ss));
+    
+    addrinfo* res = NULL;
     int ret = getaddrinfo(ipString, NULL, &hints, &res);
     if (ret == 0 && res) {
-        // Convert mapped addresses to IPv4 addresses if necessary.
-        if (res->ai_family == AF_INET6 && isMappedAddress(res->ai_addr)) {
-            convertMappedToIpv4((sockaddr_in6 *) res->ai_addr, &sin);
-            result = socketAddressToByteArray(env, (sockaddr_storage *) &sin);
+        // Convert IPv4-mapped addresses to IPv4 addresses.
+        // The RI states "Java will never return an IPv4-mapped address".
+        sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(res->ai_addr);
+        if (res->ai_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+            sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(&ss);
+            sin->sin_family = AF_INET;
+            sin->sin_port = sin6->sin6_port;
+            memcpy(&sin->sin_addr.s_addr, &sin6->sin6_addr.s6_addr[12], 4);
+            result = socketAddressToByteArray(env, &ss);
         } else {
-            result = socketAddressToByteArray(env,
-                    (sockaddr_storage *) res->ai_addr);
+            result = socketAddressToByteArray(env, reinterpret_cast<sockaddr_storage*>(res->ai_addr));
         }
     } else {
         // For backwards compatibility, deal with address formats that
         // getaddrinfo does not support. For example, 1.2.3, 1.3, and even 3 are
         // valid IPv4 addresses according to the Java API. If getaddrinfo fails,
         // try to use inet_aton.
-        if (inet_aton(ipString, &sin.sin_addr)) {
-            sin.sin_port = 0;
-            sin.sin_family = AF_INET;
-            result = socketAddressToByteArray(env, (sockaddr_storage *) &sin);
+        sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(&ss);
+        if (inet_aton(ipString, &sin->sin_addr)) {
+            sin->sin_family = AF_INET;
+            sin->sin_port = 0;
+            result = socketAddressToByteArray(env, &ss);
         }
     }
 
@@ -609,8 +553,7 @@
  *
  * @return  the new Boolean
  */
-
-jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
+static jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
     jclass tempClass;
     jmethodID tempMethod;
 
@@ -627,8 +570,7 @@
  *
  * @return  the new Byte
  */
-
-jobject newJavaLangByte(JNIEnv * env, jbyte val) {
+static jobject newJavaLangByte(JNIEnv * env, jbyte val) {
     jclass tempClass;
     jmethodID tempMethod;
 
@@ -645,32 +587,21 @@
  *
  * @return  the new Integer
  */
-
-jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
-    jclass tempClass;
-    jmethodID tempMethod;
-
-    tempClass = gCachedFields.integer_class;
-    tempMethod = gCachedFields.integer_class_init;
-    return env->NewObject(tempClass, tempMethod, anInt);
+static jobject newJavaLangInteger(JNIEnv* env, jint anInt) {
+    return env->NewObject(gCachedFields.integer_class, gCachedFields.integer_class_init, 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 +618,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);
 }
 
 /**
@@ -740,8 +639,6 @@
 
 static const char * netLookupErrorString(int anErrorNum) {
     switch (anErrorNum) {
-        case SOCKERR_BADSOCKET:
-            return "Bad socket";
         case SOCKERR_NOTINITIALIZED:
             return "Socket library uninitialized";
         case SOCKERR_BADAF:
@@ -770,8 +667,6 @@
             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:
@@ -907,12 +802,24 @@
     }
 }
 
-static int sockSelect(int nfds, fd_set *readfds, fd_set *writefds,
-        fd_set *exceptfds, struct timeval *timeout) {
+static int selectWait(int fd, int uSecTime) {
+    timeval tv;
+    timeval* tvp;
+    if (uSecTime >= 0) {
+        /* Use a timeout if uSecTime >= 0 */
+        memset(&tv, 0, sizeof(tv));
+        tv.tv_usec = uSecTime;
+        tvp = &tv;
+    } else {
+        /* Infinite timeout if uSecTime < 0 */
+        tvp = NULL;
+    }
 
-    int result = select(nfds, readfds, writefds, exceptfds, timeout);
-
-    if (result < 0) {
+    fd_set readFds;
+    FD_ZERO(&readFds);
+    FD_SET(fd, &readFds);
+    int result = select(fd + 1, &readFds, NULL, NULL, tvp);
+    if (result == -1) {
         if (errno == EINTR) {
             result = SOCKERR_INTERRUPTED;
         } else {
@@ -924,39 +831,10 @@
     return result;
 }
 
-#define SELECT_READ_TYPE 0
-#define SELECT_WRITE_TYPE 1
-
-static int selectWait(int handle, int uSecTime, int type) {
-    fd_set fdset;
-    struct timeval time, *timePtr;
-    int result = 0;
-    int size = handle + 1;
-
-    FD_ZERO(&fdset);
-    FD_SET(handle, &fdset);
-
-    if (0 <= uSecTime) {
-        /* Use a timeout if uSecTime >= 0 */
-        memset(&time, 0, sizeof(time));
-        time.tv_usec = uSecTime;
-        timePtr = &time;
-    } else {
-        /* Infinite timeout if uSecTime < 0 */
-        timePtr = NULL;
-    }
-
-    if (type == SELECT_READ_TYPE) {
-        result = sockSelect(size, &fdset, NULL, NULL, timePtr);
-    } else {
-        result = sockSelect(size, NULL, &fdset, NULL, timePtr);
-    }
-    return result;
-}
-
-static int pollSelectWait(JNIEnv *env, jobject fileDescriptor, int timeout, int type) {
-    /* now try reading the socket for the timespan timeout.
-     * if timeout is 0 try forever until the soclets gets ready or until an
+// Returns 0 on success, not obviously meaningful negative values on error.
+static int pollSelectWait(JNIEnv *env, jobject fileDescriptor, int timeout) {
+    /* now try reading the socket for the timeout.
+     * if timeout is 0 try forever until the sockets gets ready or until an
      * exception occurs.
      */
     int pollTimeoutUSec = 100000, pollMsec = 100;
@@ -978,9 +856,8 @@
          * Fetch the handle every time in case the socket is closed.
          */
         handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-        if (handle == 0 || handle == -1) {
-            throwSocketException(env, SOCKERR_INTERRUPTED);
+        if (handle == -1) {
+            jniThrowSocketException(env, EINTR);
             return -1;
         }
 
@@ -990,7 +867,7 @@
                 pollTimeoutUSec = timeLeft <= 0 ? 0 : (timeLeft * 1000);
             }
 
-            result = selectWait(handle, pollTimeoutUSec, type);
+            result = selectWait(handle, pollTimeoutUSec);
 
             /*
              * because we are polling at a time smaller than timeout
@@ -1008,8 +885,7 @@
                      * effectively what has happened, even if we happen to
                      * have been interrupted.
                      */
-                    jniThrowException(env, "java/net/SocketTimeoutException",
-                            netLookupErrorString(SOCKERR_TIMEOUT));
+                    jniThrowSocketTimeoutException(env, ETIMEDOUT);
                 } else {
                     continue; // try again
                 }
@@ -1021,7 +897,7 @@
 
         } else { /* polling with no timeout (why would you do this?)*/
 
-            result = selectWait(handle, pollTimeoutUSec, type);
+            result = selectWait(handle, pollTimeoutUSec);
 
             /*
              *  if interrupted (or a timeout) just retry
@@ -1041,121 +917,16 @@
 }
 
 /**
- * Obtain the socket address family from an existing socket.
- *
- * @param socket the filedescriptor of the socket to examine
- *
- * @return an integer, the address family of the socket
- */
-static int getSocketAddressFamily(int socket) {
-  struct sockaddr_storage ss;
-  socklen_t namelen = sizeof(ss);
-  int ret = getsockname(socket, (struct sockaddr*) &ss, &namelen);
-  if (ret != 0) {
-    return AF_UNSPEC;
-  } else {
-    return ss.ss_family;
-  }
-}
-
-/**
- * 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.
  *
- * @param socket the filedescriptor of the socket to connect
+ * @param socket the file descriptor of the socket to connect
  * @param socketAddress the address to connect to
  */
-static int doConnect(int socket, struct sockaddr_storage *socketAddress) {
-    sockaddr_storage mappedAddress;
-    sockaddr_storage *realAddress;
-    if (socketAddress->ss_family == AF_INET &&
-        getSocketAddressFamily(socket) == AF_INET6) {
-        convertIpv4ToMapped((sockaddr_in *) socketAddress,
-                (sockaddr_in6 *) &mappedAddress, true);
-        realAddress = &mappedAddress;
-    } else {
-        realAddress = socketAddress;
-    }
-    int ret;
-    do {
-        ret = connect(socket, (struct sockaddr *) realAddress,
-                sizeof(struct sockaddr_storage));
-    } while (ret < 0 && errno == EINTR);
-    return ret;
-}
-
-/**
- * Wrapper for bind() that converts IPv4 addresses to IPv4-mapped IPv6
- * addresses if necessary.
- *
- * @param socket the filedescriptor of the socket to connect
- * @param socketAddress the address to connect to
- */
-static int doBind(int socket, struct sockaddr_storage *socketAddress) {
-    struct sockaddr_storage mappedAddress;
-    struct sockaddr_storage *realAddress;
-    if (socketAddress->ss_family == AF_INET &&
-        getSocketAddressFamily(socket) == AF_INET6) {
-        convertIpv4ToMapped((sockaddr_in *) socketAddress,
-                (sockaddr_in6 *) &mappedAddress, false);
-        realAddress = &mappedAddress;
-    } else {
-        realAddress = socketAddress;
-    }
-    int ret;
-    do {
-        ret = bind(socket, (struct sockaddr *) realAddress,
-                sizeof(struct sockaddr_storage));
-    } while (ret < 0 && errno == EINTR);
-    return ret;
+static int doConnect(int fd, const sockaddr_storage* socketAddress) {
+    sockaddr_storage tmp;
+    const sockaddr* realAddress = convertIpv4ToMapped(fd, socketAddress, &tmp, true);
+    return TEMP_FAILURE_RETRY(connect(fd, realAddress, sizeof(sockaddr_storage)));
 }
 
 /**
@@ -1179,43 +950,30 @@
  *
  * @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) {
+// TODO: do we really want to pass 'addr' by value?
+static int sockConnectWithTimeout(int handle, sockaddr_storage addr,
+                                  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 +994,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 +1018,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) {
@@ -1331,10 +1087,10 @@
     switch(level) {
         case SOL_SOCKET:
             return "SOL_SOCKET";
-        case SOL_IP:
-            return "SOL_IP";
-        case SOL_IPV6:
-            return "SOL_IPV6";
+        case IPPROTO_IP:
+            return "IPPROTO_IP";
+        case IPPROTO_IPV6:
+            return "IPPROTO_IPV6";
         default:
             return "SOL_???";
     }
@@ -1363,14 +1119,14 @@
     switch (family) {
         case AF_INET:
             option = ipv4Option;
-            protocol = SOL_IP;
+            protocol = IPPROTO_IP;
             break;
         case AF_INET6:
             option = ipv6Option;
-            protocol = SOL_IPV6;
+            protocol = IPPROTO_IPV6;
             break;
         default:
-            // TODO: throw Java exceptions from this method instead of just
+            // TODO(enh): throw Java exceptions from this method instead of just
             // returning error codes.
             errno = EAFNOSUPPORT;
             return -1;
@@ -1401,6 +1157,7 @@
     return ret;
 }
 
+#ifdef ENABLE_MULTICAST
 /*
  * Find the interface index that was set for this socket by the IP_MULTICAST_IF
  * or IPV6_MULTICAST_IF socket option.
@@ -1413,20 +1170,19 @@
  */
 static int interfaceIndexFromMulticastSocket(int socket) {
     int family = getSocketAddressFamily(socket);
-    socklen_t requestLength;
     int interfaceIndex;
     int result;
     if (family == AF_INET) {
         // IP_MULTICAST_IF returns a pointer to a struct ip_mreqn.
         struct ip_mreqn tempRequest;
-        requestLength = sizeof(tempRequest);
-        result = getsockopt(socket, SOL_IP, IP_MULTICAST_IF, &tempRequest,
+        socklen_t requestLength = sizeof(tempRequest);
+        result = getsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &tempRequest,
             &requestLength);
         interfaceIndex = tempRequest.imr_ifindex;
     } else if (family == AF_INET6) {
         // IPV6_MULTICAST_IF returns a pointer to an integer.
-        requestLength = sizeof(interfaceIndex);
-        result = getsockopt(socket, SOL_IPV6, IPV6_MULTICAST_IF,
+        socklen_t requestLength = sizeof(interfaceIndex);
+        result = getsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
                 &interfaceIndex, &requestLength);
     } else {
         errno = EAFNOSUPPORT;
@@ -1460,7 +1216,7 @@
  *
  * @exception SocketException if an error occurs during the call
  */
-static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
+static void mcastAddDropMembership(JNIEnv *env, int handle, jobject optVal,
         int ignoreIF, int setSockOptVal) {
     struct sockaddr_storage sockaddrP;
     int result;
@@ -1487,26 +1243,26 @@
             interfaceIndex = interfaceIndexFromMulticastSocket(handle);
             multicastRequest.imr_ifindex = interfaceIndex;
             if (interfaceIndex == -1) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return;
             }
         }
 
         // Convert the inetAddress to an IPv4 address structure.
-        result = inetAddressToSocketAddress(env, optVal, 0, &sockaddrP);
-        if (result < 0)  // Exception has already been thrown.
+        if (!inetAddressToSocketAddress(env, optVal, 0, &sockaddrP)) {
             return;
+        }
         if (sockaddrP.ss_family != AF_INET) {
-            throwSocketException(env, SOCKERR_BADAF);
+            jniThrowSocketException(env, EAFNOSUPPORT);
             return;
         }
         struct sockaddr_in *sin = (struct sockaddr_in *) &sockaddrP;
         multicastRequest.imr_multiaddr = sin->sin_addr;
 
-        result = setsockopt(handle, SOL_IP, setSockOptVal,
+        result = setsockopt(handle, IPPROTO_IP, setSockOptVal,
                             &multicastRequest, length);
         if (0 != result) {
-            throwSocketException (env, convertError(errno));
+            jniThrowSocketException(env, errno);
             return;
         }
     } else {
@@ -1531,9 +1287,9 @@
             interfaceIndex = env->GetIntField(optVal, interfaceIdxID);
         }
 
-        result = inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP);
-        if (result < 0)  // Exception has already been thrown.
+        if (!inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP)) {
             return;
+        }
 
         int family = getSocketAddressFamily(handle);
 
@@ -1555,7 +1311,7 @@
                         ((struct sockaddr_in *) &sockaddrP)->sin_addr;
                 ipv4Request.imr_ifindex = interfaceIndex;
                 multicastRequest = &ipv4Request;
-                level = SOL_IP;
+                level = IPPROTO_IP;
                 break;
             case AF_INET6:
                 // setSockOptVal is passed in by the caller and may be IPv4-only
@@ -1571,38 +1327,28 @@
                         ((struct sockaddr_in6 *) &sockaddrP)->sin6_addr;
                 ipv6Request.ipv6mr_interface = interfaceIndex;
                 multicastRequest = &ipv6Request;
-                level = SOL_IPV6;
+                level = IPPROTO_IPV6;
                 break;
            default:
-               throwSocketException (env, SOCKERR_BADAF);
-               return;
+                jniThrowSocketException(env, EAFNOSUPPORT);
+                return;
         }
 
         /* join/drop the multicast address */
         result = setsockopt(handle, level, setSockOptVal, multicastRequest,
                             requestLength);
         if (0 != result) {
-            throwSocketException (env, convertError(errno));
+            jniThrowSocketException(env, errno);
             return;
         }
     }
 }
+#endif // def ENABLE_MULTICAST
 
 static void osNetworkSystem_oneTimeInitializationImpl(JNIEnv* env, jobject obj,
         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 +1362,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 +1383,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}
     };
@@ -1703,8 +1447,7 @@
         sock = socket(PF_INET, type, 0);
     }
     if (sock < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
+        jniThrowSocketException(env, errno);
         return sock;
     }
     jniSetFileDescriptorOfFD(env, fileDescriptor, sock);
@@ -1724,77 +1467,53 @@
 }
 
 static jint osNetworkSystem_readSocketDirectImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jint address, jint offset, jint count,
-        jint timeout) {
+        jobject fileDescriptor, jint address, jint count, jint timeout) {
     // LOGD("ENTER readSocketDirectImpl");
 
-    int handle;
-    jbyte *message = (jbyte *)address + offset;
-    int result, ret, localCount;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
         return 0;
     }
 
-    result = selectWait(handle, timeout, SELECT_READ_TYPE);
-
-    if (0 > result) {
-        return 0;
+    if (timeout != 0) {
+        int result = selectWait(fd, timeout * 1000);
+        if (result < 0) {
+            return 0;
+        }
     }
 
-    localCount = (count < 65536) ? count : 65536;
-
-    do {
-        ret = recv(handle, (jbyte *) message, localCount, SOCKET_NOFLAGS);
-    } while (ret < 0 && errno == EINTR);
-
-    if (0 == ret) {
+    jbyte* dst = reinterpret_cast<jbyte*>(static_cast<uintptr_t>(address));
+    ssize_t bytesReceived =
+            TEMP_FAILURE_RETRY(recv(fd, dst, count, SOCKET_NOFLAGS));
+    if (bytesReceived == 0) {
         return -1;
-    } else if (ret == -1) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
-        return 0;
+    } else if (bytesReceived == -1) {
+        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+            // We were asked to read a non-blocking socket with no data
+            // available, so report "no bytes read".
+            return 0;
+        } else {
+            jniThrowSocketException(env, errno);
+            return 0;
+        }
     }
-    return ret;
+    return bytesReceived;
 }
 
 static jint osNetworkSystem_readSocketImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jbyteArray data, jint offset, jint count,
+        jobject fileDescriptor, jbyteArray byteArray, jint offset, jint count,
         jint timeout) {
     // LOGD("ENTER readSocketImpl");
 
-    jbyte *message;
-    int result, localCount;
-
-    jbyte internalBuffer[BUFFERSIZE];
-
-    localCount = (count < 65536) ? count : 65536;
-
-    if (localCount > BUFFERSIZE) {
-        message = (jbyte*)malloc(localCount * sizeof(jbyte));
-        if (message == NULL) {
-            jniThrowException(env, "java/lang/OutOfMemoryError",
-                    "couldn't allocate enough memory for readSocket");
-            return 0;
-        }
-    } else {
-        message = (jbyte *)internalBuffer;
+    jbyte* bytes = env->GetByteArrayElements(byteArray, NULL);
+    if (bytes == NULL) {
+        return -1;
     }
-
-    result = osNetworkSystem_readSocketDirectImpl(env, clazz, fileDescriptor,
-            (jint) message, 0, localCount, timeout);
-
-    if (result > 0) {
-        env->SetByteArrayRegion(data, offset, result, (jbyte *)message);
-    }
-
-    if (((jbyte *)message) != internalBuffer) {
-        free(( jbyte *)message);
-    }
-
+    jint address =
+            static_cast<jint>(reinterpret_cast<uintptr_t>(bytes + offset));
+    int result = osNetworkSystem_readSocketDirectImpl(env, clazz,
+            fileDescriptor, address, count, timeout);
+    env->ReleaseByteArrayElements(byteArray, bytes, 0);
     return result;
 }
 
@@ -1802,95 +1521,42 @@
         jobject fileDescriptor, jint address, jint offset, jint count) {
     // LOGD("ENTER writeSocketDirectImpl");
 
-    int handle;
-    jbyte *message = (jbyte *)address + offset;
-    int result = 0, sent = 0;
-
     if (count <= 0) {
         return 0;
     }
 
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
         return 0;
     }
 
-    result = send(handle, (jbyte *) message, (int) count, SOCKET_NOFLAGS);
-    if (result < 0) {
-        int err = convertError(errno);
-
-        if (SOCKERR_WOULDBLOCK == err){
-            jclass socketExClass,errorCodeExClass;
-            jmethodID errorCodeExConstructor, socketExConstructor,socketExCauseMethod;
-            jobject errorCodeEx, socketEx;
-            const char* errorMessage = netLookupErrorString(err);
-            jstring errorMessageString = env->NewStringUTF(errorMessage);
-
-            errorCodeExClass = env->FindClass("org/apache/harmony/luni/util/ErrorCodeException");
-            if (!errorCodeExClass){
-                return 0;
-            }
-            errorCodeExConstructor = env->GetMethodID(errorCodeExClass,"<init>","(I)V");
-            if (!errorCodeExConstructor){
-                return 0;
-            }
-            errorCodeEx = env->NewObject(errorCodeExClass,errorCodeExConstructor,err);
-
-            socketExClass = env->FindClass("java/net/SocketException");
-            if (!socketExClass) {
-                return 0;
-            }
-            socketExConstructor = env->GetMethodID(socketExClass,"<init>","(Ljava/lang/String;)V");
-            if (!socketExConstructor) {
-                return 0;
-            }
-            socketEx = env->NewObject(socketExClass, socketExConstructor, errorMessageString);
-            socketExCauseMethod = env->GetMethodID(socketExClass,"initCause","(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
-            env->CallObjectMethod(socketEx,socketExCauseMethod,errorCodeEx);
-            env->Throw((jthrowable)socketEx);
+    jbyte* message = reinterpret_cast<jbyte*>(static_cast<uintptr_t>(address + offset));
+    int bytesSent = send(fd, message, count, SOCKET_NOFLAGS);
+    if (bytesSent == -1) {
+        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+            // We were asked to write to a non-blocking socket, but were told
+            // it would block, so report "no bytes written".
+            return 0;
+        } else {
+            jniThrowSocketException(env, errno);
             return 0;
         }
-        throwSocketException(env, err);
-        return 0;
     }
-
-    return result;
+    return bytesSent;
 }
 
 static jint osNetworkSystem_writeSocketImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
+        jobject fileDescriptor, jbyteArray byteArray, jint offset, jint count) {
     // LOGD("ENTER writeSocketImpl");
 
-    jbyte *message;
-    int sent = 0;
-    jint result = 0;
-
-/* TODO: ARRAY PINNING */
-#define INTERNAL_SEND_BUFFER_MAX 512
-    jbyte internalBuffer[INTERNAL_SEND_BUFFER_MAX];
-
-    if (count > INTERNAL_SEND_BUFFER_MAX) {
-        message = (jbyte*)malloc(count * sizeof( jbyte));
-        if (message == NULL) {
-            jniThrowException(env, "java/lang/OutOfMemoryError",
-                    "couldn't allocate enough memory for writeSocket");
-            return 0;
-        }
-    } else {
-        message = (jbyte *)internalBuffer;
+    jbyte* bytes = env->GetByteArrayElements(byteArray, NULL);
+    if (bytes == NULL) {
+        return -1;
     }
-
-    env->GetByteArrayRegion(data, offset, count, message);
-
-    result = osNetworkSystem_writeSocketDirectImpl(env, clazz, fileDescriptor,
-            (jint) message, 0, count);
-
-    if (( jbyte *)message != internalBuffer) {
-        free(( jbyte *)message);
-    }
-#undef INTERNAL_SEND_BUFFER_MAX
+    jint address = static_cast<jint>(reinterpret_cast<uintptr_t>(bytes));
+    int result = osNetworkSystem_writeSocketDirectImpl(env, clazz,
+            fileDescriptor, address, offset, count);
+    env->ReleaseByteArrayElements(byteArray, bytes, 0);
     return result;
 }
 
@@ -1899,69 +1565,49 @@
     // LOGD("ENTER setNonBlockingImpl");
 
     int handle;
-    int result;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    if (!jniGetFd(env, fileDescriptor, handle)) {
         return;
     }
 
     int block = nonblocking;
-
-    result = ioctl(handle, FIONBIO, &block);
-
-    if (result == -1) {
-        throwSocketException(env, convertError(errno));
+    int rc = ioctl(handle, FIONBIO, &block);
+    if (rc == -1) {
+        jniThrowSocketException(env, errno);
     }
 }
 
-static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port);
-
 static jint osNetworkSystem_connectWithTimeoutSocketImpl(JNIEnv* env,
         jclass clazz, jobject fileDescriptor, jint timeout, jint trafficClass,
         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)
-        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) {
-        throwSocketException(env, SOCKERR_BADDESC);
+    sockaddr_storage address;
+    if (!inetAddressToSocketAddress(env, inetAddr, port, &address)) {
         return -1;
     }
 
-    context = (jbyte *)env->GetPrimitiveArrayCritical(passContext, NULL);
-
-    switch (step) {
-        case SOCKET_CONNECT_STEP_START:
-            result = sockConnectWithTimeout(handle, address, 0,
-                    SOCKET_STEP_START, context);
-            break;
-        case SOCKET_CONNECT_STEP_CHECK:
-            result = sockConnectWithTimeout(handle, address, timeout,
-                    SOCKET_STEP_CHECK, context);
-            break;
+    int handle;
+    if (!jniGetFd(env, fileDescriptor, handle)) {
+        return -1;
     }
 
-    env->ReleasePrimitiveArrayCritical(passContext, context, JNI_ABORT);
+    jbyte* context = env->GetByteArrayElements(passContext, NULL);
+    int result = 0;
+    switch (step) {
+    case SOCKET_CONNECT_STEP_START:
+        result = sockConnectWithTimeout(handle, address, 0,
+                SOCKET_STEP_START, context);
+        break;
+    case SOCKET_CONNECT_STEP_CHECK:
+        result = sockConnectWithTimeout(handle, address, timeout,
+                SOCKET_STEP_CHECK, context);
+        break;
+    default:
+        assert(false);
+    }
+    env->ReleaseByteArrayElements(passContext, context, 0);
 
-    if (0 == result) {
+    if (result == 0) {
         /* connected , so stop here */
         sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
     } else if (result != SOCKERR_NOTCONNECTED) {
@@ -1985,7 +1631,6 @@
     // LOGD("ENTER connectStreamWithTimeoutSocketImpl");
 
     int result = 0;
-    int handle;
     struct sockaddr_storage address;
     jbyte *context = NULL;
     int remainingTimeout = timeout;
@@ -1999,23 +1644,12 @@
         finishTime = time_msec_clock() + (int) timeout;
     }
 
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADDESC);
+    int handle;
+    if (!jniGetFd(env, fileDescriptor, handle)) {
         return;
     }
 
-    result = inetAddressToSocketAddress(env, inetAddr, remotePort, &address);
-    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);
-        }
+    if (!inetAddressToSocketAddress(env, inetAddr, remotePort, &address)) {
         return;
     }
 
@@ -2024,8 +1658,8 @@
      * the descriptor sets that we will use
      */
     context =(jbyte *) malloc(sizeof(struct selectFDSet));
-    if (NULL == context) {
-        throwSocketException(env, SOCKERR_NOBUFFERS);
+    if (context == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", "native heap");
         return;
     }
 
@@ -2063,10 +1697,10 @@
          * are connected if the socket is closed on them.
          */
         handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-        if (handle == 0 || handle == -1) {
+        if (handle == -1) {
             sockConnectWithTimeout(handle, address, 0,
                     SOCKET_STEP_DONE, context);
-            throwSocketException(env, SOCKERR_BADSOCKET);
+            jniThrowSocketException(env, EBADF);
             goto bail;
         }
 
@@ -2091,9 +1725,7 @@
                 if (remainingTimeout <= 0) {
                     sockConnectWithTimeout(handle, address, 0,
                             SOCKET_STEP_DONE, context);
-                    jniThrowException(env,
-                            "java/net/SocketTimeoutException",
-                            netLookupErrorString(result));
+                    jniThrowSocketTimeoutException(env, ENOTCONN);
                     goto bail;
                 }
             } else {
@@ -2127,98 +1759,40 @@
     }
 }
 
-static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port) {
-    //LOGD("ENTER direct-call connectSocketImpl\n");
-
-    struct sockaddr_storage address;
-    int ret;
-    int handle;
-
-    ret = inetAddressToSocketAddress(env, inetAddr, port, &address);
-    if (ret < 0)
-        return ret;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADDESC);
-        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);
-
-    } 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;
-        }
-
-    }
-
-    if (ret < 0) {
-        jniThrowException(env, "java/net/ConnectException",
-                netLookupErrorString(convertError(errno)));
-        return ret;
-    }
-
-    return ret;
-}
-
 static void osNetworkSystem_socketBindImpl(JNIEnv* env, jclass clazz,
         jobject fileDescriptor, jint port, jobject inetAddress) {
     // LOGD("ENTER socketBindImpl");
 
-    struct sockaddr_storage sockaddress;
-    int ret;
-    int handle;
-
-    ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
-    if (ret < 0)
-        return;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADDESC);
+    sockaddr_storage socketAddress;
+    if (!inetAddressToSocketAddress(env, inetAddress, port, &socketAddress)) {
         return;
     }
 
-    ret = doBind(handle, &sockaddress);
-    if (ret < 0) {
-        jniThrowException(env, "java/net/BindException",
-                netLookupErrorString(convertError(errno)));
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
         return;
     }
+
+    sockaddr_storage tmp;
+    const sockaddr* realAddress = convertIpv4ToMapped(fd, &socketAddress, &tmp, false);
+    int rc = TEMP_FAILURE_RETRY(bind(fd, realAddress, sizeof(sockaddr_storage)));
+    if (rc == -1) {
+        jniThrowBindException(env, errno);
+    }
 }
 
 static void osNetworkSystem_listenStreamSocketImpl(JNIEnv* env, jclass clazz,
         jobject fileDescriptor, jint backlog) {
     // LOGD("ENTER listenStreamSocketImpl");
 
-    int ret;
     int handle;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    if (!jniGetFd(env, fileDescriptor, handle)) {
         return;
     }
 
-    ret = listen(handle, backlog);
-
-    if (ret < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
+    int rc = listen(handle, backlog);
+    if (rc == -1) {
+        jniThrowSocketException(env, errno);
         return;
     }
 }
@@ -2228,18 +1802,13 @@
     // LOGD("ENTER availableStreamImpl");
 
     int handle;
-    char message[BUFFERSIZE];
-
-    int result;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADDESC);
+    if (!jniGetFd(env, fileDescriptor, handle)) {
         return 0;
     }
 
+    int result;
     do {
-        result = selectWait(handle, 1, SELECT_READ_TYPE);
+        result = selectWait(handle, 1);
 
         if (SOCKERR_TIMEOUT == result) {
             // The read operation timed out, so answer 0 bytes available
@@ -2252,67 +1821,54 @@
         }
     } while (SOCKERR_INTERRUPTED == result);
 
-    result = recv(handle, (jbyte *) message, BUFFERSIZE, MSG_PEEK);
+    char message[2048];
+    result = recv(handle, (jbyte *) message, sizeof(message), MSG_PEEK);
 
     if (0 > result) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
+        jniThrowSocketException(env, errno);
         return 0;
     }
     return result;
 }
 
-static void osNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass clazz,
-        jobject fdServer, jobject newSocket, jobject fdnewSocket, jint timeout) {
+static void osNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass,
+        jobject serverFileDescriptor,
+        jobject newSocket, jobject clientFileDescriptor, jint timeout) {
     // LOGD("ENTER acceptSocketImpl");
 
-    struct sockaddr_storage sa;
-
-    int ret;
-    int retFD;
-    int result;
-    int handle;
-    socklen_t addrlen;
-
     if (newSocket == NULL) {
         throwNullPointerException(env);
         return;
     }
 
-    result = pollSelectWait(env, fdServer, timeout, SELECT_READ_TYPE);
-    if (0 > result) {
+    int rc = pollSelectWait(env, serverFileDescriptor, timeout);
+    if (rc < 0) {
         return;
     }
 
-    handle = jniGetFDFromFileDescriptor(env, fdServer);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADDESC);
+    int serverFd;
+    if (!jniGetFd(env, serverFileDescriptor, serverFd)) {
         return;
     }
 
-    do {
-        addrlen = sizeof(sa);
-        ret = accept(handle, (struct sockaddr *) &sa, &addrlen);
-    } while (ret < 0 && errno == EINTR);
-
-    if (ret < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
+    sockaddr_storage sa;
+    socklen_t addrlen = sizeof(sa);
+    int clientFd = TEMP_FAILURE_RETRY(accept(serverFd,
+            reinterpret_cast<sockaddr*>(&sa), &addrlen));
+    if (clientFd == -1) {
+        jniThrowSocketException(env, errno);
         return;
     }
 
-    retFD = ret;
-
     /*
      * For network sockets, put the peer address and port in instance variables.
      * We don't bother to do this for UNIX domain sockets, since most peers are
      * anonymous anyway.
      */
     if (sa.ss_family == AF_INET || sa.ss_family == AF_INET6) {
-        jobject inetAddress =  socketAddressToInetAddress(env, &sa);
-        if (ret == -1) {
-            close(retFD);
-            newSocket = NULL;  // Exception has already been thrown.
+        jobject inetAddress = socketAddressToInetAddress(env, &sa);
+        if (inetAddress == NULL) {
+            close(clientFd);
             return;
         }
 
@@ -2323,21 +1879,16 @@
         env->SetIntField(newSocket, gCachedFields.socketimpl_port, port);
     }
 
-    jniSetFileDescriptorOfFD(env, fdnewSocket, retFD);
+    jniSetFileDescriptorOfFD(env, clientFileDescriptor, clientFd);
 }
 
 static jboolean osNetworkSystem_supportsUrgentDataImpl(JNIEnv* env,
         jclass clazz, jobject fileDescriptor) {
     // LOGD("ENTER supportsUrgentDataImpl");
 
-    int handle;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        return JNI_FALSE;
-    }
-
-    return JNI_TRUE;
+    // TODO(enh): do we really need to exclude the invalid file descriptor case?
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+    return (fd == -1) ? JNI_FALSE : JNI_TRUE;
 }
 
 static void osNetworkSystem_sendUrgentDataImpl(JNIEnv* env, jclass clazz,
@@ -2345,132 +1896,128 @@
     // LOGD("ENTER sendUrgentDataImpl");
 
     int handle;
-    int result;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    if (!jniGetFd(env, fileDescriptor, handle)) {
         return;
     }
 
-    result = send(handle, (jbyte *) &value, 1, MSG_OOB);
-    if (result < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
+    int rc = send(handle, &value, 1, MSG_OOB);
+    if (rc == -1) {
+        jniThrowSocketException(env, errno);
     }
 }
 
-static void osNetworkSystem_connectDatagramImpl2(JNIEnv* env, jclass clazz,
-        jobject fd, jint port, jint trafficClass, jobject inetAddress) {
+static void osNetworkSystem_connectDatagramImpl2(JNIEnv* env, jclass,
+        jobject fileDescriptor, jint port, jint trafficClass, jobject inetAddress) {
     // LOGD("ENTER connectDatagramImpl2");
 
-    int handle = jniGetFDFromFileDescriptor(env, fd);
-
-    struct sockaddr_storage sockAddr;
-    int ret;
-
-    ret = inetAddressToSocketAddress(env, inetAddress, port, &sockAddr);
-    if (ret < 0)  // Exception has already been thrown.
+    sockaddr_storage sockAddr;
+    if (!inetAddressToSocketAddress(env, inetAddress, port, &sockAddr)) {
         return;
+    }
 
-    ret = doConnect(handle, &sockAddr);
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
+        return;
+    }
+
+    int ret = doConnect(fd, &sockAddr);
     if (ret < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
+        jniThrowSocketException(env, errno);
     }
 }
 
-static void osNetworkSystem_disconnectDatagramImpl(JNIEnv* env, jclass clazz,
-        jobject fd) {
+static void osNetworkSystem_disconnectDatagramImpl(JNIEnv* env, jclass,
+        jobject fileDescriptor) {
     // LOGD("ENTER disconnectDatagramImpl");
 
-    int handle = jniGetFDFromFileDescriptor(env, fd);
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
+        return;
+    }
 
-    struct sockaddr_storage sockAddr;
+    sockaddr_storage sockAddr;
     memset(&sockAddr, 0, sizeof(sockAddr));
     sockAddr.ss_family = AF_UNSPEC;
 
-    int result = doConnect(handle, &sockAddr);
+    int result = doConnect(fd, &sockAddr);
     if (result < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
+        jniThrowSocketException(env, errno);
     }
 }
 
+static void osNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject,
+        jobject sender, jbyteArray address) {
+    // LOGD("ENTER setInetAddressImpl");
+    
+    env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address);
+}
+
 static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
-        jobject fd, jobject sender, jint receiveTimeout) {
+        jobject fileDescriptor, jobject sender, jint receiveTimeout) {
     // LOGD("ENTER peekDatagramImpl");
 
-    int port = -1;
-
-    int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
-    if (0> result) {
-        return (jint) 0;
-    }
-
-    int handle = jniGetFDFromFileDescriptor(env, fd);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADDESC);
+    int result = pollSelectWait(env, fileDescriptor, receiveTimeout);
+    if (result < 0) {
         return 0;
     }
 
-    struct sockaddr_storage sockAddr;
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
+        return 0;
+    }
+    
+    sockaddr_storage sockAddr;
     socklen_t sockAddrLen = sizeof(sockAddr);
-    ssize_t length;
-    do {
-        length = recvfrom(handle, NULL, 0, MSG_PEEK,
-                (struct sockaddr *)&sockAddr, &sockAddrLen);
-    } while (length < 0 && errno == EINTR);
-    if (length < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
+    ssize_t length = TEMP_FAILURE_RETRY(recvfrom(fd, NULL, 0, MSG_PEEK,
+            reinterpret_cast<sockaddr*>(&sockAddr), &sockAddrLen));
+    if (length == -1) {
+        jniThrowSocketException(env, errno);
         return 0;
     }
 
-    sender = socketAddressToInetAddress(env, &sockAddr);
-    if (sender == NULL)  // Exception has already been thrown.
+    // We update the byte[] in the 'sender' InetAddress, and return the port.
+    // This awful API is public in the RI, so there's no point returning
+    // InetSocketAddress here instead.
+    jbyteArray senderAddressArray = socketAddressToByteArray(env, &sockAddr);
+    if (sender == NULL) {
         return -1;
-
-    port = getSocketAddressPort(&sockAddr);
-    return port;
+    }
+    osNetworkSystem_setInetAddressImpl(env, NULL, sender, senderAddressArray);
+    return getSocketAddressPort(&sockAddr);
 }
 
 static jint osNetworkSystem_receiveDatagramDirectImpl(JNIEnv* env, jclass clazz,
-        jobject fd, jobject packet, jint address, jint offset, jint length,
-        jint receiveTimeout, jboolean peek) {
+        jobject fileDescriptor, jobject packet, jint address, jint offset,
+        jint length, jint receiveTimeout, jboolean peek) {
     // LOGD("ENTER receiveDatagramDirectImpl");
 
-    int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
-    if (0 > result) {
-        return (jint) 0;
-    }
-
-    int handle = jniGetFDFromFileDescriptor(env, fd);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADDESC);
+    int result = pollSelectWait(env, fileDescriptor, receiveTimeout);
+    if (result < 0) {
         return 0;
     }
 
-    struct sockaddr_storage sockAddr;
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
+        return 0;
+    }
+
+    char* buf =
+            reinterpret_cast<char*>(static_cast<uintptr_t>(address + offset));
+    const int mode = peek ? MSG_PEEK : 0;
+    sockaddr_storage sockAddr;
     socklen_t sockAddrLen = sizeof(sockAddr);
-
-    int mode = peek ? MSG_PEEK : 0;
-
-    ssize_t actualLength;
-    do {
-        actualLength = recvfrom(handle, (char*)(address + offset), length, mode,
-                (struct sockaddr *)&sockAddr, &sockAddrLen);
-    } while (actualLength < 0 && errno == EINTR);
-    if (actualLength < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
+    ssize_t actualLength = TEMP_FAILURE_RETRY(recvfrom(fd, buf, length, mode,
+            reinterpret_cast<sockaddr*>(&sockAddr), &sockAddrLen));
+    if (actualLength == -1) {
+        jniThrowSocketException(env, errno);
         return 0;
     }
 
     if (packet != NULL) {
         jbyteArray addr = socketAddressToByteArray(env, &sockAddr);
-        if (addr == NULL)  // Exception has already been thrown.
+        if (addr == NULL) {
             return 0;
+        }
         int port = getSocketAddressPort(&sockAddr);
         jobject sender = env->CallStaticObjectMethod(
                 gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress,
@@ -2508,34 +2055,30 @@
 }
 
 static jint osNetworkSystem_recvConnectedDatagramDirectImpl(JNIEnv* env,
-        jclass clazz, jobject fd, jobject packet, jint address, jint offset,
-        jint length, jint receiveTimeout, jboolean peek) {
+        jclass clazz, jobject fileDescriptor, jobject packet,
+        jint address, jint offset, jint length,
+        jint receiveTimeout, jboolean peek) {
     // LOGD("ENTER receiveConnectedDatagramDirectImpl");
 
-    int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
-
-    if (0 > result) {
+    int result = pollSelectWait(env, fileDescriptor, receiveTimeout);
+    if (result < 0) {
         return 0;
     }
 
-    int handle = jniGetFDFromFileDescriptor(env, fd);
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
         return 0;
     }
-
+    
+    char* buf = reinterpret_cast<char*>(static_cast<uintptr_t>(address + offset));
     int mode = peek ? MSG_PEEK : 0;
-
-    int actualLength = recvfrom(handle,
-            (char*)(address + offset), length, mode, NULL, NULL);
-
+    int actualLength = recvfrom(fd, buf, length, mode, NULL, NULL);
     if (actualLength < 0) {
         jniThrowException(env, "java/net/PortUnreachableException", "");
         return 0;
     }
 
-    if ( packet != NULL) {
+    if (packet != NULL) {
         env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
     }
     return actualLength;
@@ -2567,39 +2110,34 @@
 }
 
 static jint osNetworkSystem_sendDatagramDirectImpl(JNIEnv* env, jclass clazz,
-        jobject fd, jint address, jint offset, jint length, jint port,
+        jobject fileDescriptor, jint address, jint offset, jint length,
+        jint port,
         jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
     // LOGD("ENTER sendDatagramDirectImpl");
 
-    int handle = jniGetFDFromFileDescriptor(env, fd);
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
-        return 0;
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
+        return -1;
     }
 
-    struct sockaddr_storage receiver;
-    if (inetAddressToSocketAddress(env, inetAddress, port, &receiver) < 0) {
-        // Exception has already been thrown.
-        return 0;
+    sockaddr_storage receiver;
+    if (!inetAddressToSocketAddress(env, inetAddress, port, &receiver)) {
+        return -1;
     }
 
-    ssize_t result = 0;
-    do {
-        result = sendto(handle, (char*)(address + offset), length,
-                SOCKET_NOFLAGS, (struct sockaddr*)&receiver, sizeof(receiver));
-    } while (result < 0 && errno == EINTR);
-    if (result < 0) {
-        int err = convertError(errno);
-        if ((SOCKERR_CONNRESET == err)
-                || (SOCKERR_CONNECTION_REFUSED == err)) {
+    char* buf =
+            reinterpret_cast<char*>(static_cast<uintptr_t>(address + offset));
+    ssize_t bytesSent = TEMP_FAILURE_RETRY(sendto(fd, buf, length,
+            SOCKET_NOFLAGS,
+            reinterpret_cast<sockaddr*>(&receiver), sizeof(receiver)));
+    if (bytesSent == -1) {
+        if (errno == ECONNRESET || errno == ECONNREFUSED) {
             return 0;
         } else {
-            throwSocketException(env, err);
-            return 0;
+            jniThrowSocketException(env, errno);
         }
     }
-    return (jint) result;
+    return bytesSent;
 }
 
 static jint osNetworkSystem_sendDatagramImpl(JNIEnv* env, jclass clazz,
@@ -2617,29 +2155,27 @@
 }
 
 static jint osNetworkSystem_sendConnectedDatagramDirectImpl(JNIEnv* env,
-        jclass clazz, jobject fd, jint address, jint offset, jint length,
+        jclass clazz, jobject fileDescriptor,
+        jint address, jint offset, jint length,
         jboolean bindToDevice) {
     // LOGD("ENTER sendConnectedDatagramDirectImpl");
 
-    int handle = jniGetFDFromFileDescriptor(env, fd);
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
         return 0;
     }
 
-    int result = send(handle, (char*)(address + offset), length, 0);
-
-    if (result < 0) {
-        int err = convertError(errno);
-        if ((SOCKERR_CONNRESET == err) || (SOCKERR_CONNECTION_REFUSED == err)) {
+    char* buf =
+            reinterpret_cast<char*>(static_cast<uintptr_t>(address + offset));
+    ssize_t bytesSent = TEMP_FAILURE_RETRY(send(fd, buf, length, 0));
+    if (bytesSent == -1) {
+        if (errno == ECONNRESET || errno == ECONNREFUSED) {
             return 0;
         } else {
-            throwSocketException(env, err);
-            return 0;
+            jniThrowSocketException(env, errno);
         }
     }
-    return result;
+    return bytesSent;
 }
 
 static jint osNetworkSystem_sendConnectedDatagramImpl(JNIEnv* env, jclass clazz,
@@ -2660,186 +2196,53 @@
     // LOGD("ENTER createServerStreamSocketImpl");
 
     int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
-    if (handle < 0)
+    if (handle < 0) {
         return;
+    }
 
     int value = 1;
     setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
 }
 
-/*
- * @param timeout in milliseconds.  If zero, block until data received
- */
-static jint osNetworkSystem_receiveStreamImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jbyteArray data, jint offset, jint count,
-        jint timeout) {
-    // LOGD("ENTER receiveStreamImpl");
-
-    int result;
-    int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
-        return 0;
+static void doShutdown(JNIEnv* env, jobject fileDescriptor, int how) {
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
+        return;
     }
-
-    // Cap read length to available buf size
-    int spaceAvailable = env->GetArrayLength(data) - offset;
-    int localCount = count < spaceAvailable? count : spaceAvailable;
-
-    jboolean isCopy;
-    jbyte *body = env->GetByteArrayElements(data, &isCopy);
-
-    // set timeout
-    struct timeval tv;
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
-    setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
-               sizeof(struct timeval));
-
-    do {
-        result = recv(handle, body + offset, localCount, SOCKET_NOFLAGS);
-    } while (result < 0 && errno == EINTR);
-
-    env->ReleaseByteArrayElements(data, body, 0);
-
-    /*
-     * If no bytes are read, return -1 to signal 'endOfFile'
-     * to the Java input stream
-     */
-    if (0 < result) {
-        return result;
-    } else if (0 == result) {
-        return -1;
-    } else {
-        // If EAGAIN or EWOULDBLOCK, read timed out
-        if (errno == EAGAIN || errno == EWOULDBLOCK) {
-            jniThrowException(env, "java/net/SocketTimeoutException",
-                              netLookupErrorString(SOCKERR_TIMEOUT));
-        } else {
-            int err = convertError(errno);
-            throwSocketException(env, err);
-        }
-        return 0;
+    int rc = shutdown(fd, how);
+    if (rc == -1) {
+        jniThrowSocketException(env, errno);
     }
 }
 
-static jint osNetworkSystem_sendStreamImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
-    // LOGD("ENTER sendStreamImpl");
-
-    int handle = 0;
-    int result = 0, sent = 0;
-
-    jboolean isCopy;
-    jbyte *message = env->GetByteArrayElements(data, &isCopy);
-
-    // Cap write length to available buf size
-    int spaceAvailable = env->GetArrayLength(data) - offset;
-    if (count > spaceAvailable) count = spaceAvailable;
-
-    while (sent < count) {
-
-        handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-        if (handle == 0 || handle == -1) {
-            throwSocketException(env,
-                    sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
-            env->ReleaseByteArrayElements(data, message, 0);
-            return 0;
-        }
-
-        // LOGD("before select %d", count);
-        selectWait(handle, SEND_RETRY_TIME, SELECT_WRITE_TYPE);
-        result = send(handle, (jbyte *)message + offset + sent,
-                (int) count - sent, SOCKET_NOFLAGS);
-
-        if (result < 0) {
-            result = errno;
-            if (result == EAGAIN ||result == EWOULDBLOCK) {
-                // LOGD("write blocked %d", sent);
-                continue;
-            }
-            env->ReleaseByteArrayElements(data, message, 0);
-            int err = convertError(result);
-            throwSocketException(env, err);
-            return 0;
-        }
-        sent += result;
-    }
-
-    env->ReleaseByteArrayElements(data, message, 0);
-    return sent;
-}
-
-static void osNetworkSystem_shutdownInputImpl(JNIEnv* env, jobject obj,
+static void osNetworkSystem_shutdownInputImpl(JNIEnv* env, jobject,
         jobject fileDescriptor) {
-    // LOGD("ENTER shutdownInputImpl");
-
-    int ret;
-    int handle;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
-        return;
-    }
-
-    ret = shutdown(handle, SHUT_RD);
-
-    if (ret < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
-        return;
-    }
+    doShutdown(env, fileDescriptor, SHUT_RD);
 }
 
-static void osNetworkSystem_shutdownOutputImpl(JNIEnv* env, jobject obj,
+static void osNetworkSystem_shutdownOutputImpl(JNIEnv* env, jobject,
         jobject fileDescriptor) {
-    // LOGD("ENTER shutdownOutputImpl");
-
-    int ret;
-    int handle;
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-    if (handle == 0 || handle == -1) {
-        return;
-    }
-
-    ret = shutdown(handle, SHUT_WR);
-
-    if (ret < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
-        return;
-    }
+    doShutdown(env, fileDescriptor, SHUT_WR);
 }
 
 static jint osNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz,
-        jobject fd, jbyteArray data, jint offset, jint length, jint port,
-        jobject inetAddress) {
+        jobject fileDescriptor, jbyteArray data, jint offset, jint length,
+        jint port, jobject inetAddress) {
     // LOGD("ENTER sendDatagramImpl2");
 
-    jbyte *message;
-    unsigned short nPort;
-    int ret = 0, sent = 0;
-    int handle = 0;
-    struct sockaddr_storage sockaddrP;
-
+    sockaddr_storage sockAddr;
     if (inetAddress != NULL) {
-        ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddrP);
-        if (ret < 0)  // Exception has already been thrown.
-            return 0;
-
-        handle = jniGetFDFromFileDescriptor(env, fd);
-        if (handle == 0 || handle == -1) {
-            throwSocketException(env, SOCKERR_BADDESC);
-            return 0;
+        if (!inetAddressToSocketAddress(env, inetAddress, port, &sockAddr)) {
+            return -1;
         }
     }
 
-    message = (jbyte*) malloc(length * sizeof(jbyte));
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
+        return 0;
+    }
+
+    jbyte* message = (jbyte*) malloc(length * sizeof(jbyte));
     if (message == NULL) {
         jniThrowException(env, "java/lang/OutOfMemoryError",
                 "couldn't allocate enough memory for readSocket");
@@ -2848,208 +2251,182 @@
 
     env->GetByteArrayRegion(data, offset, length, message);
 
-    while (sent < length) {
-        handle = jniGetFDFromFileDescriptor(env, fd);
-
-        if (handle == 0 || handle == -1) {
-            throwSocketException(env,
-                    sent == 0 ? SOCKERR_BADDESC : SOCKERR_INTERRUPTED);
+    int totalBytesSent = 0;
+    while (totalBytesSent < length) {
+        ssize_t bytesSent = TEMP_FAILURE_RETRY(sendto(fd,
+                message + totalBytesSent, length - totalBytesSent,
+                SOCKET_NOFLAGS,
+                reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr)));
+        if (bytesSent == -1) {
+            jniThrowSocketException(env, errno);
             free(message);
             return 0;
         }
 
-        ssize_t result;
-        do {
-            result = sendto(handle, (char *) (message + sent),
-                    (int) (length - sent), SOCKET_NOFLAGS,
-                    (struct sockaddr *) &sockaddrP, sizeof(sockaddrP));
-        } while (result < 0 && errno == EINTR);
-        if (result < 0) {
-            int err = convertError(errno);
-            throwSocketException(env, err);
-            free(message);
-            return 0;
-        }
-
-        sent += result;
+        totalBytesSent += bytesSent;
     }
 
     free(message);
-    return sent;
+    return totalBytesSent;
 }
 
-static jint osNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
-        jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
-        jint countWriteC, jintArray outFlags, jlong timeout) {
-    // 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;
+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: ignoring invalid fd %i", fd);
+            continue;
+        }
+        
+        FD_SET(fd, fdSet);
+        
+        if (fd > *maxFd) {
+            *maxFd = fd;
         }
     }
+    return true;
+}
 
-    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;
+/*
+ * Note: fdSet has to be non-const because although on Linux FD_ISSET() is sane
+ * and takes a const fd_set*, it takes fd_set* on Mac OS. POSIX is not on our
+ * side here:
+ *   http://www.opengroup.org/onlinepubs/000095399/functions/select.html
+ */
+static bool translateFdSet(JNIEnv* env, jobjectArray fdArray, jint count, 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;
 
-    /* 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);
-
+        if (valid && FD_ISSET(fd, &fdSet)) {
+            flagArray[i + offset] = op;
         } else {
-            result = sockSelect(size, fdset_read, fdset_write, NULL, NULL);
+            flagArray[i + offset] = SOCKET_OP_NONE;
         }
     }
+    return true;
+}
 
-    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);
+static jboolean osNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
+        jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
+        jint countWriteC, jintArray outFlags, jlong timeoutMs) {
+    // LOGD("ENTER selectImpl");
+    
+    // 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;
     }
-
-    free(fdset_write);
-    free(fdset_read);
-
-    /* return both correct and error result, let java handle the exception*/
-    return result;
+    
+    // Initialize the timeout, if any.
+    timeval tv;
+    timeval* tvp = NULL;
+    if (timeoutMs >= 0) {
+        tv = toTimeval(timeoutMs);
+        tvp = &tv;
+    }
+    
+    // Perform the select.
+    int result = select(maxFd + 1, &readFds, &writeFds, NULL, tvp);
+    if (result == 0) {
+        // Timeout.
+        return JNI_FALSE;
+    } else if (result == -1) {
+        // Error.
+        if (errno == EINTR) {
+            return JNI_FALSE;
+        } else {
+            jniThrowSocketException(env, errno);
+            return JNI_FALSE;
+        }
+    }
+    
+    // Translate the result into the int[] we're supposed to fill in.
+    jint* flagArray = env->GetIntArrayElements(outFlags, NULL);
+    if (flagArray == NULL) {
+        return JNI_FALSE;
+    }
+    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;
 }
 
 static jobject osNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env,
-        jclass clazz, jobject fileDescriptor, jboolean preferIPv6Addresses) {
+        jclass, jobject fileDescriptor, jboolean preferIPv6Addresses) {
     // LOGD("ENTER getSocketLocalAddressImpl");
 
-    struct sockaddr_storage addr;
-    socklen_t addrLen = sizeof(addr);
-
-    memset(&addr, 0, addrLen);
-
-
-    int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
         return NULL;
     }
 
-    int result;
-    result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
-
-    // Spec says ignore all errors
+    sockaddr_storage addr;
+    socklen_t addrLen = sizeof(addr);
+    memset(&addr, 0, addrLen);
+    int rc = getsockname(fd, (sockaddr*) &addr, &addrLen);
+    if (rc == -1) {
+        // TODO: the public API doesn't allow failure, so this whole method
+        // represents a broken design. In practice, though, getsockname can't
+        // fail unless we give it invalid arguments.
+        LOGE("getsockname failed: %s (errno=%i)", strerror(errno), errno);
+        return NULL;
+    }
     return socketAddressToInetAddress(env, &addr);
 }
 
-static jint osNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass clazz,
+static jint osNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass,
         jobject fileDescriptor, jboolean preferIPv6Addresses) {
     // LOGD("ENTER getSocketLocalPortImpl");
 
-    struct sockaddr_storage addr;
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
+        return 0;
+    }
+
+    sockaddr_storage addr;
     socklen_t addrLen = sizeof(addr);
-
-    int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    int result;
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
+    memset(&addr, 0, addrLen);
+    int rc = getsockname(fd, (sockaddr*) &addr, &addrLen);
+    if (rc == -1) {
+        // TODO: the public API doesn't allow failure, so this whole method
+        // represents a broken design. In practice, though, getsockname can't
+        // fail unless we give it invalid arguments.
+        LOGE("getsockname failed: %s (errno=%i)", strerror(errno), errno);
         return 0;
     }
-
-    result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
-
-    if (0 != result) {
-        // The java spec does not indicate any exceptions on this call
-        return 0;
-    } else {
-        return getSocketAddressPort(&addr);
-    }
+    return getSocketAddressPort(&addr);
 }
 
 static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
         jobject fileDescriptor, jint anOption) {
     // LOGD("ENTER getSocketOptionImpl");
 
-    int handle;
     int intValue = 0;
     socklen_t intSize = sizeof(int);
-    unsigned char byteValue = 0;
-    socklen_t byteSize = sizeof(unsigned char);
     int result;
     struct sockaddr_storage sockVal;
     socklen_t sockSize = sizeof(sockVal);
 
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADDESC);
-        return NULL;
+    int handle;
+    if (!jniGetFd(env, fileDescriptor, handle)) {
+        return 0;
     }
 
     switch ((int) anOption & 0xffff) {
@@ -3058,7 +2435,7 @@
             socklen_t size = sizeof(struct linger);
             result = getsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr, &size);
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return NULL;
             }
             if (!lingr.l_onoff) {
@@ -3068,17 +2445,95 @@
             }
             return newJavaLangInteger(env, intValue);
         }
+
         case JAVASOCKOPT_TCP_NODELAY: {
             if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
                 return NULL;
             }
             result = getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intValue, &intSize);
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return NULL;
             }
             return newJavaLangBoolean(env, intValue);
         }
+
+        case JAVASOCKOPT_SO_SNDBUF: {
+            result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return NULL;
+            }
+            return newJavaLangInteger(env, intValue);
+        }
+
+        case JAVASOCKOPT_SO_RCVBUF: {
+            result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return NULL;
+            }
+            return newJavaLangInteger(env, intValue);
+        }
+
+        case JAVASOCKOPT_SO_BROADCAST: {
+            result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return NULL;
+            }
+            return newJavaLangBoolean(env, intValue);
+        }
+
+        case JAVASOCKOPT_SO_REUSEADDR: {
+            result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return NULL;
+            }
+            return newJavaLangBoolean(env, intValue);
+        }
+
+        case JAVASOCKOPT_SO_KEEPALIVE: {
+            result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return NULL;
+            }
+            return newJavaLangBoolean(env, intValue);
+        }
+
+        case JAVASOCKOPT_SO_OOBINLINE: {
+            result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return NULL;
+            }
+            return newJavaLangBoolean(env, intValue);
+        }
+
+        case JAVASOCKOPT_IP_TOS: {
+            result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
+                                          IPV6_TCLASS, &intValue, &intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return NULL;
+            }
+            return newJavaLangInteger(env, intValue);
+        }
+
+        case JAVASOCKOPT_SO_RCVTIMEOUT: {
+            struct timeval timeout;
+            socklen_t size = sizeof(timeout);
+            result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return NULL;
+            }
+            return newJavaLangInteger(env, toMs(timeout));
+        }
+
+#ifdef ENABLE_MULTICAST
         case JAVASOCKOPT_MCAST_TTL: {
             if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
                 return newJavaLangByte(env, 0);
@@ -3088,137 +2543,86 @@
                                           IPV6_MULTICAST_HOPS, &intValue,
                                           &intSize);
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return NULL;
             }
             return newJavaLangByte(env, (jbyte)(intValue & 0xFF));
         }
-        case JAVASOCKOPT_MCAST_INTERFACE: {
+
+        case JAVASOCKOPT_IP_MULTICAST_IF: {
             if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
                 return NULL;
             }
-            result = getsockopt(handle, SOL_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
+            result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
+                &sockVal, &sockSize);
+            if (result == -1) {
+                jniThrowSocketException(env, errno);
                 return NULL;
             }
-            // This option is IPv4-only.
-            sockVal.ss_family = AF_INET;
+            if (sockVal.ss_family != AF_INET) {
+                // Java expects an AF_INET INADDR_ANY, but Linux just returns AF_UNSPEC.
+                jbyteArray inAddrAny = env->NewByteArray(4); // { 0, 0, 0, 0 }
+                return byteArrayToInetAddress(env, inAddrAny);
+            }
             return socketAddressToInetAddress(env, &sockVal);
         }
+
         case JAVASOCKOPT_IP_MULTICAST_IF2: {
             if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
                 return NULL;
             }
             struct ip_mreqn multicastRequest;
-            int interfaceIndex;
+            int interfaceIndex = 0;
             socklen_t optionLength;
             int addressFamily = getSocketAddressFamily(handle);
             switch (addressFamily) {
                 case AF_INET:
                     optionLength = sizeof(multicastRequest);
-                    result = getsockopt(handle, SOL_IP, IP_MULTICAST_IF,
+                    result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
                                         &multicastRequest, &optionLength);
                     if (result == 0)
                         interfaceIndex = multicastRequest.imr_ifindex;
                     break;
                 case AF_INET6:
                     optionLength = sizeof(interfaceIndex);
-                    result = getsockopt(handle, SOL_IPV6, IPV6_MULTICAST_IF,
+                    result = getsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF,
                                         &interfaceIndex, &optionLength);
                     break;
                 default:
-                    throwSocketException(env, SOCKERR_BADAF);
+                    jniThrowSocketException(env, EAFNOSUPPORT);
                     return NULL;
             }
 
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return NULL;
             }
-
             return newJavaLangInteger(env, interfaceIndex);
         }
-        case JAVASOCKOPT_SO_SNDBUF: {
-            result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return NULL;
-            }
-            return newJavaLangInteger(env, intValue);
-        }
-        case JAVASOCKOPT_SO_RCVBUF: {
-            result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return NULL;
-            }
-            return newJavaLangInteger(env, intValue);
-        }
-        case JAVASOCKOPT_SO_BROADCAST: {
-            result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return NULL;
-            }
-            return newJavaLangBoolean(env, intValue);
-        }
-        case JAVASOCKOPT_SO_REUSEADDR: {
-            result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return NULL;
-            }
-            return newJavaLangBoolean(env, intValue);
-        }
-        case JAVASOCKOPT_SO_KEEPALIVE: {
-            result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return NULL;
-            }
-            return newJavaLangBoolean(env, intValue);
-        }
-        case JAVASOCKOPT_SO_OOBINLINE: {
-            result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return NULL;
-            }
-            return newJavaLangBoolean(env, intValue);
-        }
+
         case JAVASOCKOPT_IP_MULTICAST_LOOP: {
             result = getOrSetSocketOption(SOCKOPT_GET, handle,
                                           IP_MULTICAST_LOOP,
                                           IPV6_MULTICAST_LOOP, &intValue,
                                           &intSize);
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return NULL;
             }
             return newJavaLangBoolean(env, intValue);
         }
-        case JAVASOCKOPT_IP_TOS: {
-            result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
-                                          IPV6_TCLASS, &intValue, &intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return NULL;
-            }
-            return newJavaLangInteger(env, intValue);
+#else
+        case JAVASOCKOPT_MCAST_TTL:
+        case JAVASOCKOPT_IP_MULTICAST_IF:
+        case JAVASOCKOPT_IP_MULTICAST_IF2:
+        case JAVASOCKOPT_IP_MULTICAST_LOOP: {
+            jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
+            return NULL;
         }
-        case JAVASOCKOPT_SO_RCVTIMEOUT: {
-            struct timeval timeout;
-            socklen_t size = sizeof(timeout);
-            result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return NULL;
-            }
-            return newJavaLangInteger(env, timeout.tv_sec * 1000 + timeout.tv_usec/1000);
-        }
+#endif // def ENABLE_MULTICAST
+
         default: {
-            throwSocketException(env, SOCKERR_OPTUNSUPP);
+            jniThrowSocketException(env, ENOPROTOOPT);
             return NULL;
         }
     }
@@ -3229,11 +2633,9 @@
         jobject fileDescriptor, jint anOption, jobject optVal) {
     // LOGD("ENTER setSocketOptionImpl");
 
-    int handle, result;
+    int result;
     int intVal;
     socklen_t intSize = sizeof(int);
-    unsigned char byteVal;
-    socklen_t byteSize = sizeof(unsigned char);
     struct sockaddr_storage sockVal;
     int sockSize = sizeof(sockVal);
 
@@ -3242,22 +2644,21 @@
     } else if (env->IsInstanceOf(optVal, gCachedFields.boolean_class)) {
         intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value);
     } else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) {
-        byteVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
+        // TTL uses a byte in Java, but the kernel still wants an int.
+        intVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
     } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
-        if (inetAddressToSocketAddress(env, optVal, 0, &sockVal) < 0) {
-            // Exception has already been thrown.
+        if (!inetAddressToSocketAddress(env, optVal, 0, &sockVal)) {
             return;
         }
     } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) {
         // we'll use optVal directly
     } else {
-        throwSocketException(env, SOCKERR_OPTUNSUPP);
+        jniThrowSocketException(env, ENOPROTOOPT);
         return;
     }
 
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADDESC);
+    int handle;
+    if (!jniGetFd(env, fileDescriptor, handle)) {
         return;
     }
 
@@ -3269,7 +2670,7 @@
             result = setsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr,
                     sizeof(struct linger));
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return;
             }
             break;
@@ -3281,23 +2682,106 @@
             }
             result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intVal, intSize);
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return;
             }
             break;
         }
 
+        case JAVASOCKOPT_SO_SNDBUF: {
+            result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return;
+            }
+            break;
+        }
+
+        case JAVASOCKOPT_SO_RCVBUF: {
+            result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return;
+            }
+            break;
+        }
+
+        case JAVASOCKOPT_SO_BROADCAST: {
+            result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return;
+            }
+            break;
+        }
+
+        case JAVASOCKOPT_SO_REUSEADDR: {
+            result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return;
+            }
+            break;
+        }
+        case JAVASOCKOPT_SO_KEEPALIVE: {
+            result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return;
+            }
+            break;
+        }
+
+        case JAVASOCKOPT_SO_OOBINLINE: {
+            result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return;
+            }
+            break;
+        }
+
+        case JAVASOCKOPT_IP_TOS: {
+            result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS,
+                                          IPV6_TCLASS, &intVal, &intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return;
+            }
+            break;
+        }
+
+        case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
+            // SO_REUSEPORT doesn't need to get set on this System
+            result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return;
+            }
+            break;
+        }
+
+        case JAVASOCKOPT_SO_RCVTIMEOUT: {
+            timeval timeout(toTimeval(intVal));
+            result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
+                    sizeof(struct timeval));
+            if (0 != result) {
+                jniThrowSocketException(env, errno);
+                return;
+            }
+            break;
+        }
+
+#ifdef ENABLE_MULTICAST
         case JAVASOCKOPT_MCAST_TTL: {
             if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
                 return;
             }
-            // Java uses a byte to store the TTL, but the kernel uses an int.
-            intVal = byteVal;
             result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL,
                                           IPV6_MULTICAST_HOPS, &intVal,
                                           &intSize);
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return;
             }
             break;
@@ -3315,24 +2799,24 @@
             break;
         }
 
-        case JAVASOCKOPT_MCAST_INTERFACE: {
+        case JAVASOCKOPT_IP_MULTICAST_IF: {
             if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
                 return;
             }
             // This call is IPv4 only. The socket may be IPv6, but the address
             // that identifies the interface to join must be an IPv4 address.
             if (sockVal.ss_family != AF_INET) {
-                throwSocketException(env, SOCKERR_BADAF);
+                jniThrowSocketException(env, EAFNOSUPPORT);
                 return;
             }
             struct ip_mreqn mcast_req;
             memset(&mcast_req, 0, sizeof(mcast_req));
             struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal;
             mcast_req.imr_address = sin->sin_addr;
-            result = setsockopt(handle, SOL_IP, IP_MULTICAST_IF,
+            result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
                                 &mcast_req, sizeof(mcast_req));
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return;
             }
             break;
@@ -3361,67 +2845,14 @@
                     optionLength = sizeof(interfaceIndex);
                     break;
                 default:
-                    throwSocketException(env, SOCKERR_BADAF);
+                    jniThrowSocketException(env, EAFNOSUPPORT);
                     return;
             }
             result = getOrSetSocketOption(SOCKOPT_SET, handle,
                     IP_MULTICAST_IF, IPV6_MULTICAST_IF, optionValue,
                     &optionLength);
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return;
-            }
-            break;
-        }
-
-        case JAVASOCKOPT_SO_SNDBUF: {
-            result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return;
-            }
-            break;
-        }
-
-        case JAVASOCKOPT_SO_RCVBUF: {
-            result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return;
-            }
-            break;
-        }
-
-        case JAVASOCKOPT_SO_BROADCAST: {
-            result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return;
-            }
-            break;
-        }
-
-        case JAVASOCKOPT_SO_REUSEADDR: {
-            result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return;
-            }
-            break;
-        }
-        case JAVASOCKOPT_SO_KEEPALIVE: {
-            result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return;
-            }
-            break;
-        }
-
-        case JAVASOCKOPT_SO_OOBINLINE: {
-            result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return;
             }
             break;
@@ -3433,47 +2864,25 @@
                                           IPV6_MULTICAST_LOOP, &intVal,
                                           &intSize);
             if (0 != result) {
-                throwSocketException(env, convertError(errno));
+                jniThrowSocketException(env, errno);
                 return;
             }
             break;
         }
-
-        case JAVASOCKOPT_IP_TOS: {
-            result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS,
-                                          IPV6_TCLASS, &intVal, &intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return;
-            }
-            break;
+#else
+        case JAVASOCKOPT_MCAST_TTL:
+        case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP:
+        case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP:
+        case JAVASOCKOPT_IP_MULTICAST_IF:
+        case JAVASOCKOPT_IP_MULTICAST_IF2:
+        case JAVASOCKOPT_IP_MULTICAST_LOOP: {
+            jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
+            return;
         }
-
-        case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
-            // SO_REUSEPORT doesn't need to get set on this System
-            result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return;
-            }
-            break;
-        }
-
-        case JAVASOCKOPT_SO_RCVTIMEOUT: {
-            struct timeval timeout;
-            timeout.tv_sec = intVal / 1000;
-            timeout.tv_usec = (intVal % 1000) * 1000;
-            result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
-                    sizeof(struct timeval));
-            if (0 != result) {
-                throwSocketException(env, convertError(errno));
-                return;
-            }
-            break;
-        }
+#endif // def ENABLE_MULTICAST
 
         default: {
-            throwSocketException(env, SOCKERR_OPTUNSUPP);
+            jniThrowSocketException(env, ENOPROTOOPT);
         }
     }
 }
@@ -3489,285 +2898,19 @@
         jobject fileDescriptor) {
     // LOGD("ENTER socketCloseImpl");
 
-    int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    int fd;
+    if (!jniGetFd(env, fileDescriptor, fd)) {
         return;
     }
 
     jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
 
-    close(handle);
+    close(fd);
 }
 
-static void osNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject obj,
-        jobject sender, jbyteArray address) {
-    // LOGD("ENTER setInetAddressImpl");
-
-    env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address);
-}
-
-// TODO: rewrite this method in Java and make it support IPv6.
-static jobject osNetworkSystem_inheritedChannelImpl(JNIEnv* env, jobject obj) {
-    // LOGD("ENTER inheritedChannelImpl");
-
-    int socket = 0;
-    int opt;
-    socklen_t length = sizeof(opt);
-    int socket_type;
-    struct sockaddr_in local_addr;
-    struct sockaddr_in remote_addr;
-    jclass channel_class, socketaddr_class, serverSocket_class, socketImpl_class;
-    jobject channel_object = NULL, socketaddr_object, serverSocket_object;
-    jobject fd_object, addr_object, localAddr_object, socketImpl_object;
-    jfieldID port_field, socketaddr_field, bound_field, fd_field;
-    jfieldID serverSocket_field, socketImpl_field, addr_field, localAddr_field;
-    jmethodID channel_new;
-    jbyteArray addr_array;
-    struct sockaddr_in *sock;
-    jbyte * address;
-    jbyte * localAddr;
-    jboolean jtrue = JNI_TRUE;
-
-    if (0 != getsockopt(socket, SOL_SOCKET, SO_TYPE, &opt, &length)) {
-        return NULL;
-    }
-    if (SOCK_STREAM !=opt && SOCK_DGRAM !=opt) {
-        return NULL;
-    }
-    socket_type = opt;
-
-    length  = sizeof(struct sockaddr);
-    if (0 != getsockname(socket, (struct sockaddr *)&local_addr, &length)) {
-        return NULL;
-    } else {
-        if (AF_INET != local_addr.sin_family || length != sizeof(struct sockaddr)) {
-            return NULL;
-        }
-        localAddr = (jbyte*) malloc(sizeof(jbyte)*4);
-        if (NULL == localAddr) {
-            return NULL;
-        }
-        memcpy (localAddr, &(local_addr.sin_addr.s_addr), 4);
-    }
-    if (0 != getpeername(socket, (struct sockaddr *)&remote_addr, &length)) {
-        remote_addr.sin_port = 0;
-        remote_addr.sin_addr.s_addr = 0;
-        address = (jbyte*) malloc(sizeof(jbyte)*4);
-        bzero(address, sizeof(jbyte)*4);
-    } else {
-        if (AF_INET != remote_addr.sin_family
-                || length != sizeof(struct sockaddr)) {
-            return NULL;
-        }
-        address = (jbyte*) malloc(sizeof(jbyte)*4);
-        memcpy (address, &(remote_addr.sin_addr.s_addr), 4);
-    }
-
-    // analysis end, begin pack to java
-    if (SOCK_STREAM == opt) {
-        if (remote_addr.sin_port!=0) {
-            //socket
-            channel_class = env->FindClass(
-                    "org/apache/harmony/nio/internal/SocketChannelImpl");
-            if (NULL == channel_class) {
-                goto clean;
-            }
-
-            channel_new = env->GetMethodID(channel_class, "<init>", "()V");
-            if (NULL == channel_new) {
-                goto clean;
-            }
-            channel_object = env->NewObject(channel_class, channel_new);
-            if (NULL == channel_object) {
-                goto clean;
-            }
-            // new and set FileDescript
-
-            fd_field = env->GetFieldID(channel_class, "fd",
-                    "java/io/FielDescriptor");
-            fd_object = env->GetObjectField(channel_object, fd_field);
-            if (NULL == fd_object) {
-                goto clean;
-            }
-
-            jniSetFileDescriptorOfFD(env, fd_object, socket);
-
-            // local port
-            port_field = env->GetFieldID(channel_class, "localPort", "I");
-            env->SetIntField(channel_object, port_field,
-                    ntohs(local_addr.sin_port));
-
-            // new and set remote addr
-            addr_array = env->NewByteArray((jsize)4);
-            env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
-            addr_object = env->NewObject(gCachedFields.i4addr_class,
-                    gCachedFields.i4addr_class_init, addr_array);
-            if (NULL == addr_object) {
-                goto clean;
-            }
-            socketaddr_class = env->FindClass("java/net/InetSocketAddress");
-            socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
-                    "Ljava/net/InetSocketAddress;");
-            socketaddr_object = env->GetObjectField(channel_object,
-                    socketaddr_field);
-            if (NULL == socketaddr_object) {
-                goto clean;
-            }
-
-            // localAddr
-            socketaddr_class = env->FindClass("java/net/InetSocketAddress");
-            socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
-                     "Ljava/net/InetSocketAddress;");
-            socketaddr_object = env->GetObjectField(channel_object,
-                     socketaddr_field);
-
-            localAddr_field = env->GetFieldID(channel_class, "localAddress",
-                     "Ljava/net/Inet4Address;");
-            addr_array = env->NewByteArray((jsize)4);
-            env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
-            localAddr_object = env->NewObject(gCachedFields.i4addr_class,
-                     gCachedFields.i4addr_class_init, addr_array);
-            jfieldID socketaddr_field = env->GetFieldID(channel_class,
-                     "connectAddress", "Ljava/net/InetSocketAddress;");
-            jobject socketaddr_object = env->GetObjectField(channel_object,
-                     socketaddr_field);
-            env->SetObjectField(socketaddr_object, localAddr_field,
-                     localAddr_object);
-            if (NULL == localAddr_object) {
-                goto clean;
-            }
-
-
-            // set port
-            port_field = env->GetFieldID(socketaddr_class, "port", "I");
-            env->SetIntField(socketaddr_object, port_field,
-                    ntohs(remote_addr.sin_port));
-
-            // set bound
-            if (0 != local_addr.sin_port) {
-                bound_field = env->GetFieldID(channel_class, "isBound", "Z");
-                env->SetBooleanField(channel_object, bound_field, jtrue);
-            }
-
-        } else {
-            //serverSocket
-            channel_class = env->FindClass(
-                    "org/apache/harmony/nio/internal/ServerSocketChannelImpl");
-            if (NULL == channel_class) {
-                goto clean;
-            }
-
-            channel_new = env->GetMethodID(channel_class, "<init>", "()V");
-            if (NULL == channel_new) {
-                goto clean;
-            }
-            channel_object = env->NewObject(channel_class, channel_new);
-            if (NULL == channel_object) {
-                goto clean;
-            }
-
-            serverSocket_field = env->GetFieldID(channel_class, "socket",
-                    "Ljava/net/ServerSocket;");
-            serverSocket_class = env->FindClass("Ljava/net/ServerSocket;");
-            serverSocket_object = env->GetObjectField(channel_object,
-                    serverSocket_field);
-            // set bound
-            if (0 != local_addr.sin_port) {
-                bound_field = env->GetFieldID(channel_class, "isBound", "Z");
-                env->SetBooleanField(channel_object, bound_field, jtrue);
-                bound_field = env->GetFieldID(serverSocket_class, "isBound", "Z");
-                env->SetBooleanField(serverSocket_object, bound_field, jtrue);
-            }
-            // localAddr
-            socketImpl_class = env->FindClass("java/net/SocketImpl");
-            socketImpl_field = env->GetFieldID(channel_class, "impl",
-                    "Ljava/net/SocketImpl;");
-            socketImpl_object =  env->GetObjectField(channel_object,
-                    socketImpl_field);
-            if (NULL == socketImpl_object) {
-                 goto clean;
-            }
-
-            addr_array = env->NewByteArray((jsize)4);
-            localAddr_field = env->GetFieldID(channel_class, "localAddress",
-                    "Ljava/net/InetAddress;");
-            memset(address, 0, 4);
-            env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
-            localAddr_object = env->NewObject(gCachedFields.i4addr_class,
-                    gCachedFields.i4addr_class_init, addr_array);
-            if (NULL == localAddr_object) {
-                 goto clean;
-            }
-            env->SetObjectField(socketImpl_object, localAddr_field,
-                    localAddr_object);
-            addr_array = env->NewByteArray((jsize)4);
-            env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
-            env->SetObjectField(localAddr_object,
-                    gCachedFields.iaddr_ipaddress, addr_array);
-
-            // set port
-            port_field = env->GetFieldID(socketImpl_class, "localport", "I");
-            env->SetIntField(socketImpl_object, port_field,
-                    ntohs(local_addr.sin_port));
-        }
-    } else {
-        //Datagram Socket
-        // new DatagramChannel
-        channel_class = env->FindClass(
-                "org/apache/harmony/nio/internal/DatagramChannelImpl");
-        if (NULL == channel_class) {
-            goto clean;
-        }
-
-        channel_new = env->GetMethodID(channel_class, "<init>", "()V");
-        if (NULL == channel_new) {
-            goto clean;
-        }
-        channel_object = env->NewObject(channel_class, channel_new);
-        if (NULL == channel_object) {
-            goto clean;
-        }
-
-        // new and set FileDescript
-        fd_field = env->GetFieldID(channel_class, "fd", "java/io/FileDescriptor");
-        fd_object = env->GetObjectField(channel_object, fd_field);
-        if (NULL == fd_object) {
-            goto clean;
-        }
-
-        jniSetFileDescriptorOfFD(env, fd_object, socket);
-
-        port_field = env->GetFieldID(channel_class, "localPort", "I");
-        env->SetIntField(channel_object, port_field, ntohs(local_addr.sin_port));
-
-        // new and set remote addr
-        addr_array = env->NewByteArray((jsize)4);
-        env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
-        addr_object = env->NewObject(gCachedFields.iaddr_class,
-                gCachedFields.i4addr_class_init, addr_array);
-        if (NULL == addr_object) {
-            goto clean;
-        }
-        socketaddr_class = env->FindClass("java/net/InetSocketAddress");
-        socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
-                "Ljava/net/InetSocketAddress;");
-        socketaddr_object = env->GetObjectField(channel_object, socketaddr_field);
-        if (NULL == socketaddr_object) {
-            goto clean;
-        }
-
-        // set bound
-        if (0 != local_addr.sin_port) {
-            bound_field = env->GetFieldID(channel_class, "isBound", "Z");
-            env->SetBooleanField(channel_object, bound_field, jtrue);
-        }
-    }
-clean:
-    free(address);
-    free(localAddr);
-    return channel_object;
+static jobject osNetworkSystem_inheritedChannel(JNIEnv* env, jobject obj) {
+    // Android never has stdin/stdout connected to a socket.
+    return NULL;
 }
 
 /*
@@ -3779,11 +2922,10 @@
     { "createStreamSocketImpl",            "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createStreamSocketImpl             },
     { "createDatagramSocketImpl",          "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createDatagramSocketImpl           },
     { "readSocketImpl",                    "(Ljava/io/FileDescriptor;[BIII)I",                                         (void*) osNetworkSystem_readSocketImpl                     },
-    { "readSocketDirectImpl",              "(Ljava/io/FileDescriptor;IIII)I",                                          (void*) osNetworkSystem_readSocketDirectImpl               },
+    { "readSocketDirectImpl",              "(Ljava/io/FileDescriptor;III)I",                                           (void*) osNetworkSystem_readSocketDirectImpl               },
     { "writeSocketImpl",                   "(Ljava/io/FileDescriptor;[BII)I",                                          (void*) osNetworkSystem_writeSocketImpl                    },
     { "writeSocketDirectImpl",             "(Ljava/io/FileDescriptor;III)I",                                           (void*) osNetworkSystem_writeSocketDirectImpl              },
     { "setNonBlockingImpl",                "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_setNonBlockingImpl                 },
-    { "connectSocketImpl",                 "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;I)I",                      (void*) osNetworkSystem_connectSocketImpl                  },
     { "connectWithTimeoutSocketImpl",      "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;II[B)I",                  (void*) osNetworkSystem_connectWithTimeoutSocketImpl       },
     { "connectStreamWithTimeoutSocketImpl","(Ljava/io/FileDescriptor;IIILjava/net/InetAddress;)V",                     (void*) osNetworkSystem_connectStreamWithTimeoutSocketImpl },
     { "socketBindImpl",                    "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;)V",                       (void*) osNetworkSystem_socketBindImpl                     },
@@ -3804,12 +2946,10 @@
     { "sendConnectedDatagramImpl",         "(Ljava/io/FileDescriptor;[BIIZ)I",                                         (void*) osNetworkSystem_sendConnectedDatagramImpl          },
     { "sendConnectedDatagramDirectImpl",   "(Ljava/io/FileDescriptor;IIIZ)I",                                          (void*) osNetworkSystem_sendConnectedDatagramDirectImpl    },
     { "createServerStreamSocketImpl",      "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createServerStreamSocketImpl       },
-    { "receiveStreamImpl",                 "(Ljava/io/FileDescriptor;[BIII)I",                                         (void*) osNetworkSystem_receiveStreamImpl                  },
-    { "sendStreamImpl",                    "(Ljava/io/FileDescriptor;[BII)I",                                          (void*) osNetworkSystem_sendStreamImpl                     },
     { "shutdownInputImpl",                 "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_shutdownInputImpl                  },
     { "shutdownOutputImpl",                "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_shutdownOutputImpl                 },
     { "sendDatagramImpl2",                 "(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;)I",                   (void*) osNetworkSystem_sendDatagramImpl2                  },
-    { "selectImpl",                        "([Ljava/io/FileDescriptor;[Ljava/io/FileDescriptor;II[IJ)I",               (void*) osNetworkSystem_selectImpl                         },
+    { "selectImpl",                        "([Ljava/io/FileDescriptor;[Ljava/io/FileDescriptor;II[IJ)Z",               (void*) osNetworkSystem_selectImpl                         },
     { "getSocketLocalAddressImpl",         "(Ljava/io/FileDescriptor;Z)Ljava/net/InetAddress;",                        (void*) osNetworkSystem_getSocketLocalAddressImpl          },
     { "getSocketLocalPortImpl",            "(Ljava/io/FileDescriptor;Z)I",                                             (void*) osNetworkSystem_getSocketLocalPortImpl             },
     { "getSocketOptionImpl",               "(Ljava/io/FileDescriptor;I)Ljava/lang/Object;",                            (void*) osNetworkSystem_getSocketOptionImpl                },
@@ -3817,7 +2957,7 @@
     { "getSocketFlagsImpl",                "()I",                                                                      (void*) osNetworkSystem_getSocketFlagsImpl                 },
     { "socketCloseImpl",                   "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_socketCloseImpl                    },
     { "setInetAddressImpl",                "(Ljava/net/InetAddress;[B)V",                                              (void*) osNetworkSystem_setInetAddressImpl                 },
-    { "inheritedChannelImpl",              "()Ljava/nio/channels/Channel;",                                            (void*) osNetworkSystem_inheritedChannelImpl               },
+    { "inheritedChannel",                  "()Ljava/nio/channels/Channel;",                                            (void*) osNetworkSystem_inheritedChannel                   },
     { "byteArrayToIpString",               "([B)Ljava/lang/String;",                                                   (void*) osNetworkSystem_byteArrayToIpString                },
     { "ipStringToByteArray",               "(Ljava/lang/String;)[B",                                                   (void*) osNetworkSystem_ipStringToByteArray                },
 };
diff --git a/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c b/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
index e92b776..80f2bee 100644
--- a/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
+++ b/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
@@ -229,7 +229,6 @@
   jfloat result;
 
   numBits = highestSetBitHighPrecision (f, length) + 1;
-  numBits -= lowestSetBitHighPrecision (f, length);
   if (numBits < 25 && e >= 0 && e < LOG5_OF_TWO_TO_THE_N)
     {
       return ((jfloat) LOW_I32_FROM_PTR (f)) * tenToTheE (e);
@@ -240,7 +239,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 +259,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;
@@ -606,4 +605,3 @@
                "org/apache/harmony/luni/util/FloatingPointParser",
                 gMethods, NELEM(gMethods));
 }
-
diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk
index d277f82..184a13d 100644
--- a/luni/src/main/native/sub.mk
+++ b/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/luni/src/test/java/com/google/coretests/CoreTestRunner.java b/luni/src/test/java/com/google/coretests/CoreTestRunner.java
index d469c86..ad766aa 100644
--- a/luni/src/test/java/com/google/coretests/CoreTestRunner.java
+++ b/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/luni/src/test/java/com/google/coretests/CoreTestSuite.java b/luni/src/test/java/com/google/coretests/CoreTestSuite.java
index 3c9e7fa..fd7531f 100644
--- a/luni/src/test/java/com/google/coretests/CoreTestSuite.java
+++ b/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/luni/src/test/java/com/google/coretests/Main.java b/luni/src/test/java/com/google/coretests/Main.java
index 1dcebc5..4a91a95 100644
--- a/luni/src/test/java/com/google/coretests/Main.java
+++ b/luni/src/test/java/com/google/coretests/Main.java
@@ -27,7 +27,7 @@
     public static void main(String[] args) {
         if (args.length == 0) {
             System.out.println("Running all tests...");
-            TestRunner.run(AllTests.suite());
+            CoreTestRunner.main(new String[] { "tests.AllTests" });
         } else if ("--stats".equals(args[0])) {
             // Delegate to new stats test runner
             String[] args2 = new String[args.length - 1];
diff --git a/luni/src/test/java/com/google/coretests/XmlReportPrinter.java b/luni/src/test/java/com/google/coretests/XmlReportPrinter.java
new file mode 100644
index 0000000..315371f
--- /dev/null
+++ b/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/luni/src/test/java/java/lang/AllTests.java b/luni/src/test/java/java/lang/AllTests.java
new file mode 100644
index 0000000..a40ef3a
--- /dev/null
+++ b/luni/src/test/java/java/lang/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;
+
+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.FloatTest.class);
+        suite.addTestSuite(java.lang.ProcessBuilderTest.class);
+        return suite;
+    }
+}
diff --git a/luni/src/test/java/java/lang/FloatTest.java b/luni/src/test/java/java/lang/FloatTest.java
new file mode 100644
index 0000000..bd8c197
--- /dev/null
+++ b/luni/src/test/java/java/lang/FloatTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class FloatTest extends junit.framework.TestCase {
+    public void test_valueOf_String1() throws Exception {
+        // This threw OutOfMemoryException.
+        // http://code.google.com/p/android/issues/detail?id=4185
+        assertEquals(2358.166016f, Float.valueOf("2358.166016"));
+    }
+    public void test_valueOf_String2() throws Exception {
+        // This threw OutOfMemoryException.
+        // http://code.google.com/p/android/issues/detail?id=3156
+        assertEquals(-2.14748365E9f, Float.valueOf(String.valueOf(Integer.MIN_VALUE)));
+    }
+}
diff --git a/luni/src/test/java/java/lang/ProcessBuilderTest.java b/luni/src/test/java/java/lang/ProcessBuilderTest.java
new file mode 100644
index 0000000..53acf01
--- /dev/null
+++ b/luni/src/test/java/java/lang/ProcessBuilderTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+import static tests.support.Support_Exec.execAndCheckOutput;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import java.io.InputStream;
+import java.util.Arrays;
+
+public class ProcessBuilderTest extends junit.framework.TestCase {
+    private static String shell() {
+        return "Dalvik".equals(System.getProperty("java.vm.name")) ? "/system/bin/sh" : "/bin/sh";
+    }
+
+    public void testRedirectErrorStream(boolean doRedirect,
+            String expectedOut, String expectedErr) throws Exception {
+        ProcessBuilder pb = new ProcessBuilder(shell(), "-c", "echo out; echo err 1>&2");
+        pb.redirectErrorStream(doRedirect);
+        execAndCheckOutput(pb, expectedOut, expectedErr);
+    }
+
+    public void test_redirectErrorStream_true() throws Exception {
+        testRedirectErrorStream(true, "out\nerr\n", "");
+    }
+
+    public void test_redirectErrorStream_false() throws Exception {
+        testRedirectErrorStream(false, "out\n", "err\n");
+    }
+}
diff --git a/luni/src/test/java/java/net/AllTests.java b/luni/src/test/java/java/net/AllTests.java
new file mode 100644
index 0000000..6d26f0d
--- /dev/null
+++ b/luni/src/test/java/java/net/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 java.net;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+    public static final Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+        suite.addTestSuite(java.net.SocketTest.class);
+        return suite;
+    }
+}
diff --git a/luni/src/test/java/java/net/SocketTest.java b/luni/src/test/java/java/net/SocketTest.java
new file mode 100644
index 0000000..b0e278f
--- /dev/null
+++ b/luni/src/test/java/java/net/SocketTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.net;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class SocketTest extends junit.framework.TestCase {
+    /**
+     * Our getLocalAddress and getLocalPort currently use getsockname(3).
+     * This means they give incorrect results on closed sockets (as well
+     * as requiring an unnecessary call into native code).
+     */
+    public void test_getLocalAddress_after_close() throws Exception {
+        Socket s = new Socket();
+        try {
+            // Bind to an ephemeral local port.
+            s.bind(new InetSocketAddress("localhost", 0));
+            assertTrue(s.getLocalAddress().isLoopbackAddress());
+            // What local port did we get?
+            int localPort = s.getLocalPort();
+            assertTrue(localPort > 0);
+            // Now close the socket...
+            s.close();
+            // The RI returns the ANY address but the original local port after close.
+            assertTrue(s.getLocalAddress().isAnyLocalAddress());
+            assertEquals(localPort, s.getLocalPort());
+        } finally {
+            s.close();
+        }
+    }
+}
diff --git a/luni/src/test/java/java/nio/charset/AllTests.java b/luni/src/test/java/java/nio/charset/AllTests.java
new file mode 100644
index 0000000..6f45162
--- /dev/null
+++ b/luni/src/test/java/java/nio/charset/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 java.nio.charset;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+    public static final Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+        suite.addTestSuite(java.nio.charset.CharsetDecoderTest.class);
+        return suite;
+    }
+}
diff --git a/luni/src/test/java/java/nio/charset/CharsetDecoderTest.java b/luni/src/test/java/java/nio/charset/CharsetDecoderTest.java
new file mode 100644
index 0000000..23184dd
--- /dev/null
+++ b/luni/src/test/java/java/nio/charset/CharsetDecoderTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class CharsetDecoderTest extends junit.framework.TestCase {
+    private static final String CHARSET = "UTF-16";
+    
+    private static final String SAMPLE_STRING = "Android";
+    
+    // http://code.google.com/p/android/issues/detail?id=4237
+    public void test_ByteArray_decode_no_offset() throws Exception {
+        CharsetDecoder decoder = getCharsetDecoderUnderTest();
+        byte[] arr = getEncodedByteArrayFixture();
+        ByteBuffer inBuffer = ByteBuffer.wrap(arr, 0, arr.length).slice();
+        CharBuffer outBuffer = CharBuffer.allocate(arr.length);
+        decoder.reset();
+        CoderResult coderResult = decoder.decode(inBuffer, outBuffer, true);
+        assertFalse(coderResult.toString(), coderResult.isError());
+        decoder.flush(outBuffer);
+        outBuffer.flip();
+        assertEquals(SAMPLE_STRING, outBuffer.toString().trim());
+    }
+    
+    // http://code.google.com/p/android/issues/detail?id=4237
+    public void test_ByteArray_decode_with_offset() throws Exception {
+        CharsetDecoder decoder = getCharsetDecoderUnderTest();
+        byte[] arr = getEncodedByteArrayFixture();
+        arr = prependByteToByteArray(arr, new Integer(1).byteValue());
+        int offset = 1;
+        ByteBuffer inBuffer = ByteBuffer.wrap(arr, offset, arr.length - offset).slice();
+        CharBuffer outBuffer = CharBuffer.allocate(arr.length - offset);
+        decoder.reset();
+        CoderResult coderResult = decoder.decode(inBuffer, outBuffer, true);
+        assertFalse(coderResult.toString(), coderResult.isError());
+        decoder.flush(outBuffer);
+        outBuffer.flip();
+        assertEquals(SAMPLE_STRING, outBuffer.toString().trim());
+    }
+    
+    // http://code.google.com/p/android/issues/detail?id=4237
+    public void test_ByteArray_decode_with_offset_using_facade_method() throws Exception {
+        CharsetDecoder decoder = getCharsetDecoderUnderTest();
+        byte[] arr = getEncodedByteArrayFixture();
+        arr = prependByteToByteArray(arr, new Integer(1).byteValue());
+        int offset = 1;
+        CharBuffer outBuffer = decoder.decode(ByteBuffer.wrap(arr, offset, arr.length - offset));
+        assertEquals(SAMPLE_STRING, outBuffer.toString().trim());
+    }
+    
+    private static byte[] prependByteToByteArray(byte[] arr, byte b) {
+        byte[] result = new byte[arr.length + 1];
+        result[0] = b;
+        System.arraycopy(arr, 0, result, 1, arr.length);
+        return result;
+    }
+    
+    private static CharsetDecoder getCharsetDecoderUnderTest() {
+        return Charset.forName(CHARSET).newDecoder();
+    }
+    
+    private byte[] getEncodedByteArrayFixture() throws CharacterCodingException {
+        CharsetEncoder encoder = Charset.forName(CHARSET).newEncoder();
+        return encoder.encode(CharBuffer.wrap(SAMPLE_STRING)).array();
+    }
+}
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
index c99a0c1..e26cf74 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
@@ -20,11 +20,22 @@
 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 tests.util.TestEnvironment;
 
+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 +52,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.
@@ -95,19 +100,6 @@
     // Proxy authentication required response code
     private static final int AUTHENTICATION_REQUIRED_CODE = 407;
 
-    // fields keeping the system values of corresponding properties
-    private static String systemKeyStoreType;
-
-    private static String systemKeyStore;
-
-    private static String systemKeyStorePassword;
-
-    private static String systemTrustStoreType;
-
-    private static String systemTrustStore;
-
-    private static String systemTrustStorePassword;
-    
     private static File store;
     
     static {
@@ -132,19 +124,14 @@
         // set up the properties defining the default values needed by SSL stuff
         setUpStoreProperties();
 
-        try {
-            SSLSocketFactory defaultSSLSF = HttpsURLConnection
-                    .getDefaultSSLSocketFactory();
-            ServerSocket ss = new ServerSocket(0);
-            Socket s = defaultSSLSF
-                    .createSocket("localhost", ss.getLocalPort());
-            ss.accept();
-            s.close();
-            ss.close();
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
-        }
+        SSLSocketFactory defaultSSLSF = HttpsURLConnection
+                .getDefaultSSLSocketFactory();
+        ServerSocket ss = new ServerSocket(0);
+        Socket s = defaultSSLSF
+                .createSocket("localhost", ss.getLocalPort());
+        ss.accept();
+        s.close();
+        ss.close();
     }
 
     /**
@@ -167,33 +154,28 @@
         // set up the properties defining the default values needed by SSL stuff
         setUpStoreProperties();
 
-        try {
-            // create the SSL server socket acting as a server
-            SSLContext ctx = getContext();
-            ServerSocket ss = ctx.getServerSocketFactory()
-                    .createServerSocket(0);
+        // create the SSL server socket acting as a server
+        SSLContext ctx = getContext();
+        ServerSocket ss = ctx.getServerSocketFactory()
+                .createServerSocket(0);
 
-            // create the HostnameVerifier to check hostname verification
-            TestHostnameVerifier hnv = new TestHostnameVerifier();
-            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+        // create the HostnameVerifier to check hostname verification
+        TestHostnameVerifier hnv = new TestHostnameVerifier();
+        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
 
-            // create url connection to be tested
-            URL url = new URL("https://localhost:" + ss.getLocalPort());
-            HttpsURLConnection connection = (HttpsURLConnection) url
-                    .openConnection();
+        // create url connection to be tested
+        URL url = new URL("https://localhost:" + ss.getLocalPort());
+        HttpsURLConnection connection = (HttpsURLConnection) url
+                .openConnection();
 
-            // perform the interaction between the peers
-            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
+        // perform the interaction between the peers
+        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
 
-            // check the connection state
-            checkConnectionStateParameters(connection, peerSocket);
+        // check the connection state
+        checkConnectionStateParameters(connection, peerSocket);
 
-            // should silently exit
-            connection.connect();
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
-        }
+        // should silently exit
+        connection.connect();
     }
 
     /**
@@ -227,37 +209,32 @@
         // set up the properties defining the default values needed by SSL stuff
         setUpStoreProperties();
 
+        // create the SSL server socket acting as a server
+        SSLContext ctx = getContext();
+        ServerSocket ss = ctx.getServerSocketFactory()
+                .createServerSocket(0);
+
+        // create the HostnameVerifier to check hostname verification
+        TestHostnameVerifier hnv = new TestHostnameVerifier();
+        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+
+        // create url connection to be tested
+        URL url = new URL("https://localhost:" + ss.getLocalPort());
+        HttpsURLConnection connection = (HttpsURLConnection) url
+                .openConnection();
+
         try {
-            // create the SSL server socket acting as a server
-            SSLContext ctx = getContext();
-            ServerSocket ss = ctx.getServerSocketFactory()
-                    .createServerSocket(0);
-
-            // create the HostnameVerifier to check hostname verification
-            TestHostnameVerifier hnv = new TestHostnameVerifier();
-            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
-
-            // create url connection to be tested
-            URL url = new URL("https://localhost:" + ss.getLocalPort());
-            HttpsURLConnection connection = (HttpsURLConnection) url
-                    .openConnection();
-
-            try {
-                doInteraction(connection, ss, NOT_FOUND_CODE);
-                fail("Expected exception was not thrown.");
-            } catch (FileNotFoundException e) {
-                if (DO_LOG) {
-                    System.out.println("Expected exception was thrown: "
-                            + e.getMessage());
-                }
+            doInteraction(connection, ss, NOT_FOUND_CODE);
+            fail("Expected exception was not thrown.");
+        } catch (FileNotFoundException e) {
+            if (DO_LOG) {
+                System.out.println("Expected exception was thrown: "
+                        + e.getMessage());
             }
-
-            // should silently exit
-            connection.connect();
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
         }
+
+        // should silently exit
+        connection.connect();
     }
 
     /**
@@ -454,39 +431,34 @@
         // setting up the properties pointing to the key/trust stores
         setUpStoreProperties();
 
-        try {
-            // create the SSLServerSocket which will be used by server side
-            SSLServerSocket ss = (SSLServerSocket) getContext()
-                    .getServerSocketFactory().createServerSocket(0);
+        // create the SSLServerSocket which will be used by server side
+        SSLServerSocket ss = (SSLServerSocket) getContext()
+                .getServerSocketFactory().createServerSocket(0);
 
-            // create the HostnameVerifier to check that Hostname verification
-            // is done
-            TestHostnameVerifier hnv = new TestHostnameVerifier();
-            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+        // create the HostnameVerifier to check that Hostname verification
+        // is done
+        TestHostnameVerifier hnv = new TestHostnameVerifier();
+        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
 
-            // create HttpsURLConnection to be tested
-            URL url = new URL("https://localhost:" + ss.getLocalPort());
-            HttpsURLConnection connection = (HttpsURLConnection) url
-                    .openConnection();
+        // create HttpsURLConnection to be tested
+        URL url = new URL("https://localhost:" + ss.getLocalPort());
+        HttpsURLConnection connection = (HttpsURLConnection) url
+                .openConnection();
 
-            TestHostnameVerifier hnv_late = new TestHostnameVerifier();
-            // replace default verifier
-            connection.setHostnameVerifier(hnv_late);
+        TestHostnameVerifier hnv_late = new TestHostnameVerifier();
+        // replace default verifier
+        connection.setHostnameVerifier(hnv_late);
 
-            // perform the interaction between the peers and check the results
-            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
-            assertTrue("Hostname verification was not done", hnv_late.verified);
-            assertFalse(
-                    "Hostname verification should not be done by this verifier",
-                    hnv.verified);
-            checkConnectionStateParameters(connection, peerSocket);
+        // perform the interaction between the peers and check the results
+        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
+        assertTrue("Hostname verification was not done", hnv_late.verified);
+        assertFalse(
+                "Hostname verification should not be done by this verifier",
+                hnv.verified);
+        checkConnectionStateParameters(connection, peerSocket);
 
-            // should silently exit
-            connection.connect();
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
-        }
+        // should silently exit
+        connection.connect();
     }
 
     /**
@@ -505,32 +477,27 @@
         // setting up the properties pointing to the key/trust stores
         setUpStoreProperties();
 
-        try {
-            // create the SSLServerSocket which will be used by server side
-            SSLServerSocket ss = (SSLServerSocket) getContext()
-                    .getServerSocketFactory().createServerSocket(0);
+        // create the SSLServerSocket which will be used by server side
+        SSLServerSocket ss = (SSLServerSocket) getContext()
+                .getServerSocketFactory().createServerSocket(0);
 
-            // create the HostnameVerifier to check that Hostname verification
-            // is done
-            TestHostnameVerifier hnv = new TestHostnameVerifier();
-            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+        // create the HostnameVerifier to check that Hostname verification
+        // is done
+        TestHostnameVerifier hnv = new TestHostnameVerifier();
+        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
 
-            // create HttpsURLConnection to be tested
-            URL url = new URL("https://localhost:" + ss.getLocalPort());
-            HttpsURLConnection connection = (HttpsURLConnection) url
-                    .openConnection();
-            connection.setDoOutput(true);
+        // create HttpsURLConnection to be tested
+        URL url = new URL("https://localhost:" + ss.getLocalPort());
+        HttpsURLConnection connection = (HttpsURLConnection) url
+                .openConnection();
+        connection.setDoOutput(true);
 
-            // perform the interaction between the peers and check the results
-            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
-            checkConnectionStateParameters(connection, peerSocket);
+        // perform the interaction between the peers and check the results
+        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
+        checkConnectionStateParameters(connection, peerSocket);
 
-            // should silently exit
-            connection.connect();
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
-        }
+        // should silently exit
+        connection.connect();
     }
 
     /**
@@ -562,32 +529,27 @@
         // setting up the properties pointing to the key/trust stores
         setUpStoreProperties();
 
-        try {
-            // create the SSLServerSocket which will be used by server side
-            ServerSocket ss = new ServerSocket(0);
+        // create the SSLServerSocket which will be used by server side
+        ServerSocket ss = new ServerSocket(0);
 
-            // create the HostnameVerifier to check that Hostname verification
-            // is done
-            TestHostnameVerifier hnv = new TestHostnameVerifier();
-            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+        // create the HostnameVerifier to check that Hostname verification
+        // is done
+        TestHostnameVerifier hnv = new TestHostnameVerifier();
+        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
 
-            // create HttpsURLConnection to be tested
-            URL url = new URL("https://requested.host:55556/requested.data");
-            HttpsURLConnection connection = (HttpsURLConnection) url
-                    .openConnection(new Proxy(Proxy.Type.HTTP,
-                            new InetSocketAddress("localhost", ss
-                                    .getLocalPort())));
+        // create HttpsURLConnection to be tested
+        URL url = new URL("https://requested.host:55556/requested.data");
+        HttpsURLConnection connection = (HttpsURLConnection) url
+                .openConnection(new Proxy(Proxy.Type.HTTP,
+                        new InetSocketAddress("localhost", ss
+                                .getLocalPort())));
 
-            // perform the interaction between the peers and check the results
-            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
-            checkConnectionStateParameters(connection, peerSocket);
+        // perform the interaction between the peers and check the results
+        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
+        checkConnectionStateParameters(connection, peerSocket);
 
-            // should silently exit
-            connection.connect();
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
-        }
+        // should silently exit
+        connection.connect();
     }
 
     /**
@@ -620,40 +582,35 @@
         // setting up the properties pointing to the key/trust stores
         setUpStoreProperties();
 
-        try {
-            // create the SSLServerSocket which will be used by server side
-            ServerSocket ss = new ServerSocket(0);
+        // create the SSLServerSocket which will be used by server side
+        ServerSocket ss = new ServerSocket(0);
 
-            // create the HostnameVerifier to check that Hostname verification
-            // is done
-            TestHostnameVerifier hnv = new TestHostnameVerifier();
-            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+        // create the HostnameVerifier to check that Hostname verification
+        // is done
+        TestHostnameVerifier hnv = new TestHostnameVerifier();
+        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
 
-            Authenticator.setDefault(new Authenticator() {
+        Authenticator.setDefault(new Authenticator() {
 
-                protected PasswordAuthentication getPasswordAuthentication() {
-                    return new PasswordAuthentication("user", "password"
-                            .toCharArray());
-                }
-            });
+            protected PasswordAuthentication getPasswordAuthentication() {
+                return new PasswordAuthentication("user", "password"
+                        .toCharArray());
+            }
+        });
 
-            // create HttpsURLConnection to be tested
-            URL url = new URL("https://requested.host:55555/requested.data");
-            HttpsURLConnection connection = (HttpsURLConnection) url
-                    .openConnection(new Proxy(Proxy.Type.HTTP,
-                            new InetSocketAddress("localhost", ss
-                                    .getLocalPort())));
+        // create HttpsURLConnection to be tested
+        URL url = new URL("https://requested.host:55555/requested.data");
+        HttpsURLConnection connection = (HttpsURLConnection) url
+                .openConnection(new Proxy(Proxy.Type.HTTP,
+                        new InetSocketAddress("localhost", ss
+                                .getLocalPort())));
 
-            // perform the interaction between the peers and check the results
-            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
-            checkConnectionStateParameters(connection, peerSocket);
+        // perform the interaction between the peers and check the results
+        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
+        checkConnectionStateParameters(connection, peerSocket);
 
-            // should silently exit
-            connection.connect();
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
-        }
+        // should silently exit
+        connection.connect();
     }
 
     /**
@@ -688,40 +645,35 @@
         // setting up the properties pointing to the key/trust stores
         setUpStoreProperties();
 
-        try {
-            // create the SSLServerSocket which will be used by server side
-            ServerSocket ss = new ServerSocket(0);
+        // create the SSLServerSocket which will be used by server side
+        ServerSocket ss = new ServerSocket(0);
 
-            // create the HostnameVerifier to check that Hostname verification
-            // is done
-            TestHostnameVerifier hnv = new TestHostnameVerifier();
-            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+        // create the HostnameVerifier to check that Hostname verification
+        // is done
+        TestHostnameVerifier hnv = new TestHostnameVerifier();
+        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
 
-            // create HttpsURLConnection to be tested
-            URL url = new URL("https://requested.host:55555/requested.data");
-            HttpsURLConnection connection = (HttpsURLConnection) url
-                    .openConnection(new Proxy(Proxy.Type.HTTP,
-                            new InetSocketAddress("localhost", ss
-                                    .getLocalPort())));
+        // create HttpsURLConnection to be tested
+        URL url = new URL("https://requested.host:55555/requested.data");
+        HttpsURLConnection connection = (HttpsURLConnection) url
+                .openConnection(new Proxy(Proxy.Type.HTTP,
+                        new InetSocketAddress("localhost", ss
+                                .getLocalPort())));
 
-            // perform the interaction between the peers and check the results
-            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
-            checkConnectionStateParameters(connection, peerSocket);
+        // perform the interaction between the peers and check the results
+        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
+        checkConnectionStateParameters(connection, peerSocket);
 
-            // create another SSLServerSocket which will be used by server side
-            ss = new ServerSocket(0);
+        // create another SSLServerSocket which will be used by server side
+        ss = new ServerSocket(0);
 
-            connection = (HttpsURLConnection) url.openConnection(new Proxy(
-                    Proxy.Type.HTTP, new InetSocketAddress("localhost", ss
-                            .getLocalPort())));
+        connection = (HttpsURLConnection) url.openConnection(new Proxy(
+                Proxy.Type.HTTP, new InetSocketAddress("localhost", ss
+                        .getLocalPort())));
 
-            // perform the interaction between the peers and check the results
-            peerSocket = (SSLSocket) doInteraction(connection, ss);
-            checkConnectionStateParameters(connection, peerSocket);
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
-        }
+        // perform the interaction between the peers and check the results
+        peerSocket = (SSLSocket) doInteraction(connection, ss);
+        checkConnectionStateParameters(connection, peerSocket);
     }
 
     /**
@@ -761,39 +713,34 @@
         // setting up the properties pointing to the key/trust stores
         setUpStoreProperties();
 
-        try {
-            // create the SSLServerSocket which will be used by server side
-            ServerSocket ss = new ServerSocket(0);
+        // create the SSLServerSocket which will be used by server side
+        ServerSocket ss = new ServerSocket(0);
 
-            // create the HostnameVerifier to check that Hostname verification
-            // is done
-            TestHostnameVerifier hnv = new TestHostnameVerifier();
-            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+        // create the HostnameVerifier to check that Hostname verification
+        // is done
+        TestHostnameVerifier hnv = new TestHostnameVerifier();
+        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
 
-            Authenticator.setDefault(new Authenticator() {
+        Authenticator.setDefault(new Authenticator() {
 
-                protected PasswordAuthentication getPasswordAuthentication() {
-                    return new PasswordAuthentication("user", "password"
-                            .toCharArray());
-                }
-            });
+            protected PasswordAuthentication getPasswordAuthentication() {
+                return new PasswordAuthentication("user", "password"
+                        .toCharArray());
+            }
+        });
 
-            // create HttpsURLConnection to be tested
-            URL url = new URL("https://requested.host:55554/requested.data");
-            HttpsURLConnection connection = (HttpsURLConnection) url
-                    .openConnection(new Proxy(Proxy.Type.HTTP,
-                            new InetSocketAddress("localhost", ss
-                                    .getLocalPort())));
-            connection.setDoOutput(true);
+        // create HttpsURLConnection to be tested
+        URL url = new URL("https://requested.host:55554/requested.data");
+        HttpsURLConnection connection = (HttpsURLConnection) url
+                .openConnection(new Proxy(Proxy.Type.HTTP,
+                        new InetSocketAddress("localhost", ss
+                                .getLocalPort())));
+        connection.setDoOutput(true);
 
-            // perform the interaction between the peers and check the results
-            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss,
-                    OK_CODE, true);
-            checkConnectionStateParameters(connection, peerSocket);
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
-        }
+        // perform the interaction between the peers and check the results
+        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss,
+                OK_CODE, true);
+        checkConnectionStateParameters(connection, peerSocket);
     }
 
     /**
@@ -826,36 +773,31 @@
         // setting up the properties pointing to the key/trust stores
         setUpStoreProperties();
 
+        // create the SSLServerSocket which will be used by server side
+        ServerSocket ss = new ServerSocket(0);
+
+        // create the HostnameVerifier to check that Hostname verification
+        // is done
+        TestHostnameVerifier hnv = new TestHostnameVerifier();
+        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+
+        // create HttpsURLConnection to be tested
+        URL url = new URL("https://requested.host:55555/requested.data");
+        HttpURLConnection connection = (HttpURLConnection) url
+                .openConnection(new Proxy(Proxy.Type.HTTP,
+                        new InetSocketAddress("localhost", ss
+                                .getLocalPort())));
+
+        // perform the interaction between the peers and check the results
         try {
-            // create the SSLServerSocket which will be used by server side
-            ServerSocket ss = new ServerSocket(0);
-
-            // create the HostnameVerifier to check that Hostname verification
-            // is done
-            TestHostnameVerifier hnv = new TestHostnameVerifier();
-            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
-
-            // create HttpsURLConnection to be tested
-            URL url = new URL("https://requested.host:55555/requested.data");
-            HttpURLConnection connection = (HttpURLConnection) url
-                    .openConnection(new Proxy(Proxy.Type.HTTP,
-                            new InetSocketAddress("localhost", ss
-                                    .getLocalPort())));
-
-            // perform the interaction between the peers and check the results
-            try {
-                doInteraction(connection, ss, AUTHENTICATION_REQUIRED_CODE,
-                        true);
-            } catch (IOException e) {
-                // SSL Tunnelling failed
-                if (DO_LOG) {
-                    System.out.println("Got expected IOException: "
-                            + e.getMessage());
-                }
+            doInteraction(connection, ss, AUTHENTICATION_REQUIRED_CODE,
+                    true);
+        } catch (IOException e) {
+            // SSL Tunnelling failed
+            if (DO_LOG) {
+                System.out.println("Got expected IOException: "
+                        + e.getMessage());
             }
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
         }
     }
 
@@ -889,34 +831,29 @@
         // setting up the properties pointing to the key/trust stores
         setUpStoreProperties();
 
+        // create the SSLServerSocket which will be used by server side
+        ServerSocket ss = new ServerSocket(0);
+
+        // create the HostnameVerifier to check that Hostname verification
+        // is done
+        TestHostnameVerifier hnv = new TestHostnameVerifier();
+        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+
+        // create HttpsURLConnection to be tested
+        URL url = new URL("https://localhost:" + ss.getLocalPort());
+        HttpURLConnection connection = (HttpURLConnection) url
+                .openConnection(new Proxy(Proxy.Type.HTTP,
+                        new InetSocketAddress("localhost", ss
+                                .getLocalPort())));
+
         try {
-            // create the SSLServerSocket which will be used by server side
-            ServerSocket ss = new ServerSocket(0);
-
-            // create the HostnameVerifier to check that Hostname verification
-            // is done
-            TestHostnameVerifier hnv = new TestHostnameVerifier();
-            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
-
-            // create HttpsURLConnection to be tested
-            URL url = new URL("https://localhost:" + ss.getLocalPort());
-            HttpURLConnection connection = (HttpURLConnection) url
-                    .openConnection(new Proxy(Proxy.Type.HTTP,
-                            new InetSocketAddress("localhost", ss
-                                    .getLocalPort())));
-
-            try {
-                doInteraction(connection, ss, NOT_FOUND_CODE); // NOT FOUND
-                fail("Expected exception was not thrown.");
-            } catch (FileNotFoundException e) {
-                if (DO_LOG) {
-                    System.out.println("Expected exception was thrown: "
-                            + e.getMessage());
-                }
+            doInteraction(connection, ss, NOT_FOUND_CODE); // NOT FOUND
+            fail("Expected exception was not thrown.");
+        } catch (FileNotFoundException e) {
+            if (DO_LOG) {
+                System.out.println("Expected exception was thrown: "
+                        + e.getMessage());
             }
-        } finally {
-            // roll the properties back to system values
-            tearDownStoreProperties();
         }
     }
 
@@ -928,6 +865,9 @@
      * Log the name of the test case to be executed.
      */
     public void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+
         if (DO_LOG) {
             System.out.println();
             System.out.println("------------------------");
@@ -955,6 +895,7 @@
     }
 
     public void tearDown() {
+        TestEnvironment.reset();
         if (store != null) {
             store.delete();
         }
@@ -994,7 +935,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() {
@@ -1038,17 +979,6 @@
     private static void setUpStoreProperties() throws Exception {
         String type = KeyStore.getDefaultType();
 
-        systemKeyStoreType = System.getProperty("javax.net.ssl.keyStoreType");
-        systemKeyStore = System.getProperty("javax.net.ssl.keyStore");
-        systemKeyStorePassword = System
-                .getProperty("javax.net.ssl.keyStorePassword");
-
-        systemTrustStoreType = System
-                .getProperty("javax.net.ssl.trustStoreType");
-        systemTrustStore = System.getProperty("javax.net.ssl.trustStore");
-        systemTrustStorePassword = System
-                .getProperty("javax.net.ssl.trustStorePassword");
-
         System.setProperty("javax.net.ssl.keyStoreType", type);
         System.setProperty("javax.net.ssl.keyStore", getKeyStoreFileName());
         System.setProperty("javax.net.ssl.keyStorePassword", KS_PASSWORD);
@@ -1059,48 +989,6 @@
     }
 
     /**
-     * Rolls back the values of system properties.
-     */
-    private static void tearDownStoreProperties() {
-        if (systemKeyStoreType == null) {
-            System.clearProperty("javax.net.ssl.keyStoreType");
-        } else {
-            System
-                    .setProperty("javax.net.ssl.keyStoreType",
-                            systemKeyStoreType);
-        }
-        if (systemKeyStore == null) {
-            System.clearProperty("javax.net.ssl.keyStore");
-        } else {
-            System.setProperty("javax.net.ssl.keyStore", systemKeyStore);
-        }
-        if (systemKeyStorePassword == null) {
-            System.clearProperty("javax.net.ssl.keyStorePassword");
-        } else {
-            System.setProperty("javax.net.ssl.keyStorePassword",
-                    systemKeyStorePassword);
-        }
-
-        if (systemTrustStoreType == null) {
-            System.clearProperty("javax.net.ssl.trustStoreType");
-        } else {
-            System.setProperty("javax.net.ssl.trustStoreType",
-                    systemTrustStoreType);
-        }
-        if (systemTrustStore == null) {
-            System.clearProperty("javax.net.ssl.trustStore");
-        } else {
-            System.setProperty("javax.net.ssl.trustStore", systemTrustStore);
-        }
-        if (systemTrustStorePassword == null) {
-            System.clearProperty("javax.net.ssl.trustStorePassword");
-        } else {
-            System.setProperty("javax.net.ssl.trustStorePassword",
-                    systemTrustStorePassword);
-        }
-    }
-
-    /**
      * Performs interaction between client's HttpURLConnection and
      * servers side (ServerSocket).
      */
@@ -1145,28 +1033,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 +1069,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 +1121,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 +1131,7 @@
          */
         public synchronized void log(String message) {
             if (DO_LOG && (out != null)) {
-                System.out.println("[" + getName() + "]: " + message);
+                out.println("[" + this + "]: " + message);
             }
         }
     }
@@ -1265,7 +1139,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 +1188,6 @@
                 this.actAsProxy = true;
             }
             this.actAsProxy = !(serverSocket instanceof SSLServerSocket);
-            setName(this.actAsProxy ? "Proxy Server" : "Server");
         }
 
         /**
@@ -1337,7 +1210,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 +1244,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 +1261,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 +1327,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 +1335,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 +1356,6 @@
          */
         public ClientConnectionWork(HttpURLConnection connection) {
             this.connection = connection;
-            setName("Client Connection");
             log("Created over connection: " + connection.getClass());
         }
 
@@ -1493,42 +1364,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/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java
index 056b521..778e527 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java
@@ -34,7 +34,6 @@
         TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for java.io");
 
         suite.addTestSuite(BufferedReaderTest.class);
-        suite.addTestSuite(FileCanonPathCacheTest.class);
         suite.addTestSuite(FilePermissionTest.class);
         suite.addTestSuite(FileTest.class);
         suite.addTestSuite(InputStreamReaderTest.class);
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java
deleted file mode 100644
index f2ac7f3..0000000
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.harmony.luni.tests.java.io;
-
-import java.io.File;
-
-import org.apache.harmony.luni.internal.io.FileCanonPathCache;
-
-import junit.framework.TestCase;
-
-public class FileCanonPathCacheTest extends TestCase {
-
-    private static int DEFAULT_TIMEOUT = 600000;
-
-    @Override
-    public void setUp() throws Exception {
-        FileCanonPathCache.clear();
-        FileCanonPathCache.setTimeout(DEFAULT_TIMEOUT);
-    }
-
-    public void testGetSet() throws Exception {
-        File file1 = new File("test/hello~1");
-        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
-        FileCanonPathCache.put(file1.getAbsolutePath(), file1
-                .getCanonicalPath());
-        assertEquals(file1.getCanonicalPath(), FileCanonPathCache.get(file1
-                .getAbsolutePath()));
-
-        File file2 = new File("test/world~1");
-        assertNull(FileCanonPathCache.get(file2.getAbsolutePath()));
-        FileCanonPathCache.put(file2.getAbsolutePath(), file2
-                .getCanonicalPath());
-        assertEquals(file2.getCanonicalPath(), FileCanonPathCache.get(file2
-                .getAbsolutePath()));
-
-        assertNull(FileCanonPathCache.get("notexist"));
-    }
-
-    public void testGetTimeout01() throws Exception {
-        FileCanonPathCache.setTimeout(10);
-
-        File file1 = new File("test/hello~1");
-        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
-        FileCanonPathCache.put(file1.getAbsolutePath(), file1
-                .getCanonicalPath());
-        Thread.sleep(50);
-        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
-    }
-
-    public void testGetTimeout02() throws Exception {
-        FileCanonPathCache.setTimeout(10);
-
-        File file1 = new File("test/hello~1");
-        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
-        FileCanonPathCache.put(file1.getAbsolutePath(), file1
-                .getCanonicalPath());
-        File file2 = new File("test/hello~2");
-        assertNull(FileCanonPathCache.get(file2.getAbsolutePath()));
-        FileCanonPathCache.put(file2.getAbsolutePath(), file2
-                .getCanonicalPath());
-        File file3 = new File("test/hello~3");
-        assertNull(FileCanonPathCache.get(file3.getAbsolutePath()));
-        FileCanonPathCache.put(file3.getAbsolutePath(), file3
-                .getCanonicalPath());
-        File file4 = new File("test/hello~4");
-        assertNull(FileCanonPathCache.get(file4.getAbsolutePath()));
-        FileCanonPathCache.put(file4.getAbsolutePath(), file4
-                .getCanonicalPath());
-        File file5 = new File("test/hello~5");
-        assertNull(FileCanonPathCache.get(file5.getAbsolutePath()));
-        FileCanonPathCache.put(file5.getAbsolutePath(), file5
-                .getCanonicalPath());
-
-        Thread.sleep(50);
-
-        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
-        assertNull(FileCanonPathCache.get(file2.getAbsolutePath()));
-        assertNull(FileCanonPathCache.get(file3.getAbsolutePath()));
-        assertNull(FileCanonPathCache.get(file4.getAbsolutePath()));
-        assertNull(FileCanonPathCache.get(file5.getAbsolutePath()));
-    }
-
-    public void testCacheFull() throws Exception {
-        int cacheSize = FileCanonPathCache.CACHE_SIZE;
-        File[] files = new File[cacheSize];
-        for (int i = 0; i < cacheSize; ++i) {
-            files[i] = new File("test/world" + i);
-            FileCanonPathCache.put(files[i].getAbsolutePath(), files[i]
-                    .getCanonicalPath());
-        }
-
-        for (int i = cacheSize; i < files.length; ++i) {
-            assertEquals(files[i - cacheSize].getCanonicalPath(),
-                    FileCanonPathCache.get(files[i - cacheSize]
-                            .getAbsolutePath()));
-            files[i] = new File("test/world" + i);
-            FileCanonPathCache.put(files[i].getAbsolutePath(), files[i]
-                    .getCanonicalPath());
-            assertEquals(files[i].getCanonicalPath(), FileCanonPathCache
-                    .get(files[i].getAbsolutePath()));
-            assertNull(FileCanonPathCache.get(files[i - cacheSize]
-                    .getAbsolutePath()));
-        }
-    }
-}
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java
index 84cddf2..53ce506 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java
@@ -25,10 +25,21 @@
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(File.class)
 public class FileTest extends TestCase {
 
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+    }
+
+    @Override protected void tearDown() throws Exception {
+        TestEnvironment.reset();
+        super.tearDown();
+    }
+
     /**
      * @tests java.io.File#File(java.io.File, java.lang.String)
      */
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java
index b1ad88a..6ffa471 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java
@@ -999,6 +999,19 @@
     }
 
     /**
+     * @tests java.lang.Float#parseFloat(java.lang.String)
+     */
+    public void test_parseFloat_LString_Harmony6261() {
+        // Regression test for HARMONY-6261
+        float f = new Float("2147483648");
+        assertEquals("2.1474836E9", Float.toString(f));
+
+        doTestCompareRawBits("123456790528.000000000000000f", 0x51e5f4c9, "1.2345679E11");
+        doTestCompareRawBits("8589934592", 0x50000000, "8.5899346E9");
+        doTestCompareRawBits("8606711808", 0x50004000, "8.606712E9");
+    }
+    
+    /**
      * @tests java.lang.Float#shortValue()
      */
     @TestTargetNew(
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java
index cb35324..283c1db 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java
+++ b/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/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/RuntimeTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/RuntimeTest.java
index b1de669..1b61d6f 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/RuntimeTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/RuntimeTest.java
@@ -33,6 +33,7 @@
 import java.util.Vector;
 
 import tests.support.resource.Support_Resources;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(Runtime.class) 
 public class RuntimeTest extends junit.framework.TestCase {
@@ -72,6 +73,11 @@
         return new RuntimeTest("FT");
     }
 
+    @Override protected void tearDown() throws Exception {
+        TestEnvironment.reset();
+        super.tearDown();
+    }
+
     /**
      * @tests java.lang.Runtime#exec(java.lang.String)
      */
@@ -864,7 +870,6 @@
         byte[] expected = {72, 0, 101, 0, 97, 0, 114, 0, 116, 0, 32, 0, 60, 47};
         byte[] returned = new byte[expected.length];
 
-        String oldEncoding = System.getProperty("file.encoding");
         System.setProperty("file.encoding", "UTF-16LE");
 
         try {
@@ -883,8 +888,6 @@
                     Arrays.equals(expected, returned));
         } catch (UnsupportedEncodingException e) {
             fail("UnsupportedEncodingException was thrown.");
-        } finally {
-            System.setProperty("file.encoding", oldEncoding);
         }
     }
  
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SystemTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SystemTest.java
index f17c3d8..9bad94f 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SystemTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SystemTest.java
@@ -22,6 +22,7 @@
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
+import tests.util.TestEnvironment;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -1080,10 +1081,9 @@
         method = "load",
         args = {java.lang.String.class}
     )
-    @AndroidOnly("No x86 version of this library")
     public void test_load() {
         try {
-            new TestLibrary().checkString();
+            Runtime.getRuntime().load("nonExistentLibrary");
             fail("UnsatisfiedLinkError was not thrown.");
         } catch(UnsatisfiedLinkError  e) {
             //expected
@@ -1117,7 +1117,7 @@
         SecurityManager oldSm = System.getSecurityManager();
         System.setSecurityManager(sm);
         try {
-            System.load("libTestLibrary.so");
+            System.load("/nonExistentLibrary.so");
             fail("SecurityException should be thrown.");
         } catch (SecurityException e) {
             // expected
@@ -1161,7 +1161,7 @@
          SecurityManager oldSm = System.getSecurityManager();
          System.setSecurityManager(sm);
          try {
-             System.loadLibrary("libTestLibrary.so");
+             System.loadLibrary("nonExistentLibrary.so");
              fail("SecurityException should be thrown.");
          } catch (SecurityException e) {
              // expected
@@ -1207,10 +1207,16 @@
 
     @Override
     protected void setUp() {
+        TestEnvironment.reset();
         flag = false;
         ranFinalize = false;
     }
 
+    @Override protected void tearDown() throws Exception {
+        TestEnvironment.reset();
+        super.tearDown();
+    }
+
     protected SystemTest createInstance() {
         return new SystemTest("FT");
     }
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/TestLibrary.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/TestLibrary.java
deleted file mode 100644
index 2748223..0000000
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/TestLibrary.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.luni.tests.java.lang;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-class TestLibrary {
-    private native String printName();
-    
-    boolean checkString() {
-        if(printName().equals("TestLibrary"))
-            return true;
-        return false;
-    }
-    
-    TestLibrary() {
-        InputStream in = TestLibrary.class.getResourceAsStream("/libTestLibrary.so");
-        try {
-            File tmp = File.createTempFile("libTestLibrary", "so");
-            tmp.deleteOnExit();
-            FileOutputStream out = new FileOutputStream(tmp);
-            while (in.available() > 0) {
-                out.write(in.read()); // slow
-            }
-            in.close();
-            out.close();
-            Runtime.getRuntime().load(tmp.getAbsolutePath());
-        } catch (FileNotFoundException e) {
-        } catch (IOException e) {
-        }
-    }        
-}
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetAddressTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetAddressTest.java
index 5635ecb..4053271 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetAddressTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetAddressTest.java
@@ -39,6 +39,7 @@
 import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
 
 import tests.support.Support_Configuration;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(InetAddress.class) 
 public class InetAddressTest extends junit.framework.TestCase {
@@ -49,6 +50,16 @@
 
     protected static String threadedTestErrorString;
 
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+    }
+
+    @Override protected void tearDown() throws Exception {
+        TestEnvironment.reset();
+        super.tearDown();
+    }
+
     /**
      * This class is used to test inet_ntoa, gethostbyaddr and gethostbyname
      * functions in the VM to make sure they're threadsafe. getByName will cause
@@ -391,60 +402,47 @@
         }
 
         // Make sure there is no caching
-        String originalPropertyValue = System
-                .getProperty("networkaddress.cache.ttl");
         System.setProperty("networkaddress.cache.ttl", "0");
 
         // Test for threadsafety
-        try {
-            InetAddress lookup1 = InetAddress
-                    .getByName(Support_Configuration.InetTestAddress);
-            assertTrue(lookup1 + " expected "
-                    + Support_Configuration.InetTestIP,
-                    Support_Configuration.InetTestIP.equals(lookup1
-                            .getHostAddress()));
-            InetAddress lookup2 = InetAddress
-                    .getByName(Support_Configuration.InetTestAddress2);
-            assertTrue(lookup2 + " expected "
-                    + Support_Configuration.InetTestIP2,
-                    Support_Configuration.InetTestIP2.equals(lookup2
-                            .getHostAddress()));
-            threadsafeTestThread thread1 = new threadsafeTestThread("1",
-                    lookup1.getHostName(), lookup1, 0);
-            threadsafeTestThread thread2 = new threadsafeTestThread("2",
-                    lookup2.getHostName(), lookup2, 0);
-            threadsafeTestThread thread3 = new threadsafeTestThread("3",
-                    lookup1.getHostAddress(), lookup1, 1);
-            threadsafeTestThread thread4 = new threadsafeTestThread("4",
-                    lookup2.getHostAddress(), lookup2, 1);
+        InetAddress lookup1 = InetAddress
+                .getByName(Support_Configuration.InetTestAddress);
+        assertTrue(lookup1 + " expected "
+                + Support_Configuration.InetTestIP,
+                Support_Configuration.InetTestIP.equals(lookup1
+                        .getHostAddress()));
+        InetAddress lookup2 = InetAddress
+                .getByName(Support_Configuration.InetTestAddress2);
+        assertTrue(lookup2 + " expected "
+                + Support_Configuration.InetTestIP2,
+                Support_Configuration.InetTestIP2.equals(lookup2
+                        .getHostAddress()));
+        threadsafeTestThread thread1 = new threadsafeTestThread("1",
+                lookup1.getHostName(), lookup1, 0);
+        threadsafeTestThread thread2 = new threadsafeTestThread("2",
+                lookup2.getHostName(), lookup2, 0);
+        threadsafeTestThread thread3 = new threadsafeTestThread("3",
+                lookup1.getHostAddress(), lookup1, 1);
+        threadsafeTestThread thread4 = new threadsafeTestThread("4",
+                lookup2.getHostAddress(), lookup2, 1);
 
-            // initialize the flags
-            threadedTestSucceeded = true;
-            synchronized (someoneDone) {
-                thread1.start();
-                thread2.start();
-                thread3.start();
-                thread4.start();
-            }
-            thread1.join();
-            thread2.join();
-            thread3.join();
-            thread4.join();
-            /* FIXME: comment the assertion below because it is platform/configuration dependent
-             * Please refer to HARMONY-1664 (https://issues.apache.org/jira/browse/HARMONY-1664)
-             * for details
-             */
-//            assertTrue(threadedTestErrorString, threadedTestSucceeded);
-        } finally {
-            // restore the old value of the property
-            if (originalPropertyValue == null)
-                // setting the property to -1 has the same effect as having the
-                // property be null
-                System.setProperty("networkaddress.cache.ttl", "-1");
-            else
-                System.setProperty("networkaddress.cache.ttl",
-                        originalPropertyValue);
+        // initialize the flags
+        threadedTestSucceeded = true;
+        synchronized (someoneDone) {
+            thread1.start();
+            thread2.start();
+            thread3.start();
+            thread4.start();
         }
+        thread1.join();
+        thread2.join();
+        thread3.join();
+        thread4.join();
+        /* FIXME: comment the assertion below because it is platform/configuration dependent
+        * Please refer to HARMONY-1664 (https://issues.apache.org/jira/browse/HARMONY-1664)
+        * for details
+        */
+//            assertTrue(threadedTestErrorString, threadedTestSucceeded);
     }
 
     /**
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLTest.java
index b4eb0ad..188d88d 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLTest.java
@@ -27,6 +27,7 @@
 import tests.support.Support_Configuration;
 import tests.support.Support_PortManager;
 import tests.support.resource.Support_Resources;
+import tests.util.TestEnvironment;
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
@@ -60,6 +61,17 @@
 public class URLTest extends TestCase {
    
     private static final String helloWorldString = "Hello World";
+
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+    }
+
+    @Override protected void tearDown() throws Exception {
+        TestEnvironment.reset();
+        super.tearDown();
+    }
+
     /**
      * @tests java.net.URL#getHost()
      */
@@ -137,19 +149,12 @@
     public void test_java_protocol_handler_pkgs_prop() throws MalformedURLException {
         // Regression test for Harmony-3094
         final String HANDLER_PKGS = "java.protocol.handler.pkgs";
-        String pkgs = System.getProperty(HANDLER_PKGS);
         System.setProperty(HANDLER_PKGS, "fake|org.apache.harmony.luni.tests.java.net");
 
         try {
             new URL("test_protocol", "", "fake.jar");
         } catch (MalformedURLException e) {
             // expected
-        } finally {
-            if (pkgs == null) {
-                System.clearProperty(HANDLER_PKGS);
-            } else {
-                System.setProperty(HANDLER_PKGS, pkgs);
-            }
         }
     }
     
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/util/AbstractMapTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/util/AbstractMapTest.java
index e5e3c11..9bd09b4 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/util/AbstractMapTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/util/AbstractMapTest.java
@@ -212,7 +212,7 @@
                 try {
                     return super.clone();
                 } catch (CloneNotSupportedException e) {
-                    return null;
+                    throw new AssertionError(e); // android-changed
                 }
             }
         }
diff --git a/luni/src/test/java/tests/AllTests.java b/luni/src/test/java/tests/AllTests.java
index 893cdf0..c54d388 100644
--- a/luni/src/test/java/tests/AllTests.java
+++ b/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,15 @@
         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.AllTests.suite());
+        suite.addTest(java.lang.reflect.AllTests.suite());
+        suite.addTest(java.net.AllTests.suite());
+        suite.addTest(java.nio.charset.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/luni/src/test/java/tests/api/java/io/BufferedReaderTest.java b/luni/src/test/java/tests/api/java/io/BufferedReaderTest.java
index b1a5755..f88b3f5 100644
--- a/luni/src/test/java/tests/api/java/io/BufferedReaderTest.java
+++ b/luni/src/test/java/tests/api/java/io/BufferedReaderTest.java
@@ -24,12 +24,14 @@
 import java.io.InputStreamReader;
 import java.io.PipedReader;
 import java.io.Reader;
+import java.io.StringReader;
 
 import tests.support.Support_ASimpleReader;
 import tests.support.Support_StringReader;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
+import tests.support.ThrowingReader;
 
 @TestTargetClass(BufferedReader.class) 
 public class BufferedReaderTest extends junit.framework.TestCase {
@@ -502,6 +504,33 @@
         ssr.throwExceptionOnNextUse = false;
     }
 
+    public void testReadZeroLengthArray() throws IOException {
+        br = new BufferedReader(new Support_StringReader("ABCDEF"));
+        br.read();
+        br.read();
+        assertEquals(0, br.read(new char[6], 3, 0));
+    }
+
+    public void testSourceThrowsWithMark() throws IOException {
+        br = new BufferedReader(new ThrowingReader(
+                new StringReader("ABCDEFGHI"), 4));
+
+        br.read();
+        br.read();
+        br.mark(10);
+        br.read();
+        br.read();
+
+        try {
+            br.read();
+            fail();
+        } catch (IOException fromThrowingReader) {
+        }
+
+        assertEquals('E', br.read());
+        assertEquals('F', br.read());
+    }
+
     /**
      * Tears down the fixture, for example, close a network connection. This
      * method is called after a test is executed.
diff --git a/luni/src/test/java/tests/api/java/io/FilePermissionTest.java b/luni/src/test/java/tests/api/java/io/FilePermissionTest.java
index 27f416d..2fa0828 100644
--- a/luni/src/test/java/tests/api/java/io/FilePermissionTest.java
+++ b/luni/src/test/java/tests/api/java/io/FilePermissionTest.java
@@ -17,28 +17,34 @@
 
 package tests.api.java.io;
 
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import tests.util.TestEnvironment;
+
 import java.io.File;
 import java.io.FilePermission;
 import java.security.PermissionCollection;
 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-
 @TestTargetClass(FilePermission.class) 
 public class FilePermissionTest extends junit.framework.TestCase {
 
-    FilePermission readAllFiles = new FilePermission("<<ALL FILES>>", "read");
+    FilePermission readAllFiles;
+    FilePermission alsoReadAllFiles;
+    FilePermission allInCurrent;
+    FilePermission readInCurrent;
+    FilePermission readInFile;
 
-    FilePermission alsoReadAllFiles = new FilePermission("<<ALL FILES>>",
-            "read");
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
 
-    FilePermission allInCurrent = new FilePermission("*",
-            "read, write, execute,delete");
-
-    FilePermission readInCurrent = new FilePermission("*", "read");
-
-    FilePermission readInFile = new FilePermission("aFile.file", "read");
+        readAllFiles = new FilePermission("<<ALL FILES>>", "read");
+        alsoReadAllFiles = new FilePermission("<<ALL FILES>>", "read");
+        allInCurrent = new FilePermission("*", "read, write, execute,delete");
+        readInCurrent = new FilePermission("*", "read");
+        readInFile = new FilePermission("aFile.file", "read");
+    }
 
     /**
      * @tests java.io.FilePermission#FilePermission(java.lang.String,
@@ -58,9 +64,9 @@
                 "write");
         assertEquals("action given to the constructor did not correspond - constructor failed",
                 "write", constructFile.getActions());
-        assertTrue(
-                "name given to the construcotr did not correspond - construcotr failed",
-                constructFile.getName() == "test constructor");
+        assertEquals(
+                "name given to the constructor did not correspond - constructor failed",
+                "test constructor", constructFile.getName());
 
         // Regression test for HARMONY-1050
         try {
@@ -244,18 +250,4 @@
                 readInCurrent.hashCode() != allInCurrent.hashCode());
 
     }
-
-    /**
-     * 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/luni/src/test/java/tests/api/java/io/FileTest.java b/luni/src/test/java/tests/api/java/io/FileTest.java
index 81f14e0..adcaccd 100644
--- a/luni/src/test/java/tests/api/java/io/FileTest.java
+++ b/luni/src/test/java/tests/api/java/io/FileTest.java
@@ -31,13 +31,15 @@
 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;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(File.class) 
 public class FileTest extends junit.framework.TestCase {
@@ -96,7 +98,6 @@
     public void test_ConstructorLjava_io_FileLjava_lang_String() throws Exception {
         String error;
         String dirName = System.getProperty("java.io.tmpdir");
-        String oldUserDir = System.getProperty("user.dir");
         System.setProperty("user.dir", dirName);
         
         File d = new File(dirName);
@@ -126,8 +127,6 @@
         d = new File(s, "/abc");
         assertEquals("Test 4: Incorrect file created;", 
                 f.getAbsolutePath(), d.getAbsolutePath());
-        
-        System.setProperty("user.dir", oldUserDir);
     }
 
     /**
@@ -172,7 +171,6 @@
         String fileName = "input.tst";
 
         String userDir = System.getProperty("java.io.tmpdir");
-        String oldUserDir = System.getProperty("user.dir");
         System.setProperty("user.dir", userDir);
         
         File f = new File(dirName, fileName);
@@ -205,8 +203,6 @@
                 .getAbsolutePath());
         assertEquals("Test3: Created Incorrect File", "/abc", f
                 .getAbsolutePath());
-
-        System.setProperty("user.dir", oldUserDir);
     }
 
     /**
@@ -689,8 +685,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
@@ -932,7 +926,6 @@
         String expected;
         String error;
         String tmpDir = System.getProperty("java.io.tmpdir");
-        String oldUserDir = System.getProperty("user.dir");
         System.setProperty("user.dir", tmpDir);
         try {
             String base = new File(tmpDir).getCanonicalPath();
@@ -979,8 +972,6 @@
 
         } catch (IOException e) {
             fail("Unexpected IOException During Test : " + e.getMessage());
-        } finally {
-            System.setProperty("user.dir", oldUserDir);
         }
     }
 
@@ -1095,7 +1086,6 @@
         args = {}
     )    
     public void test_getPath() {
-        String oldUserDir = System.getProperty("java.io.tmpdir");
         System.setProperty("user.dir", System.getProperty("java.io.tmpdir"));
         String base = System.getProperty("user.dir");
         String fname;
@@ -1121,7 +1111,6 @@
         f2.delete();
         f3.delete();
         f4.delete();
-        System.setProperty("user.dir", oldUserDir);
     }
 
     /**
@@ -2467,12 +2456,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());
     }
@@ -2502,6 +2493,9 @@
      * is called before a test is executed.
      */
     protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+
         // Make sure that system properties are set correctly
         String userDir = System.getProperty("java.io.tmpdir");
         if (userDir == null)
@@ -2533,6 +2527,8 @@
      * method is called after a test is executed.
      */
     protected void tearDown() {
+        TestEnvironment.reset();
+
         if (tempFile.exists() && !tempFile.delete())
             System.out
                     .println("FileTest.tearDown() failed, could not delete file!");
diff --git a/luni/src/test/java/tests/api/java/io/PrintStreamTest.java b/luni/src/test/java/tests/api/java/io/PrintStreamTest.java
index 2ec5feb..a249b38 100644
--- a/luni/src/test/java/tests/api/java/io/PrintStreamTest.java
+++ b/luni/src/test/java/tests/api/java/io/PrintStreamTest.java
@@ -987,7 +987,6 @@
         method = "format",
         args = {java.util.Locale.class, java.lang.String.class, java.lang.Object[].class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_formatLjava_util_Locale_Ljava_lang_String_$Ljava_lang_Object() {
         PrintStream tobj;
 
@@ -1100,7 +1099,6 @@
         method = "printf",
         args = {java.util.Locale.class, java.lang.String.class, java.lang.Object[].class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_printfLjava_util_Locale_Ljava_lang_String_$Ljava_lang_Object() {
         PrintStream tobj;
 
diff --git a/luni/src/test/java/tests/api/java/io/PrintWriterTest.java b/luni/src/test/java/tests/api/java/io/PrintWriterTest.java
index c275525..0c17a73 100644
--- a/luni/src/test/java/tests/api/java/io/PrintWriterTest.java
+++ b/luni/src/test/java/tests/api/java/io/PrintWriterTest.java
@@ -1107,7 +1107,6 @@
         method = "format",
         args = {java.util.Locale.class, java.lang.String.class, java.lang.Object[].class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_formatLjava_util_Locale_Ljava_lang_String_$Ljava_lang_Object() {
         PrintWriter tobj;
 
@@ -1219,7 +1218,6 @@
         method = "printf",
         args = {java.util.Locale.class, java.lang.String.class, java.lang.Object[].class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_printfLjava_util_Locale_Ljava_lang_String_$Ljava_lang_Object() {
         PrintWriter tobj;
 
diff --git a/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java b/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java
index 3b545e3..dc35610 100644
--- a/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java
+++ b/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/luni/src/test/java/tests/api/java/lang/Process2Test.java b/luni/src/test/java/tests/api/java/lang/Process2Test.java
index 51b29d8..2e60e77 100644
--- a/luni/src/test/java/tests/api/java/lang/Process2Test.java
+++ b/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/luni/src/test/java/tests/api/java/net/AllTests.java b/luni/src/test/java/tests/api/java/net/AllTests.java
index 5bcb484..10dd9d8 100644
--- a/luni/src/test/java/tests/api/java/net/AllTests.java
+++ b/luni/src/test/java/tests/api/java/net/AllTests.java
@@ -68,6 +68,7 @@
         suite.addTestSuite(SocketPermissionTest.class);
         suite.addTestSuite(SocketTest.class);
         suite.addTestSuite(SocketTimeoutExceptionTest.class);
+        suite.addTestSuite(UnixSocketTest.class);
         suite.addTestSuite(URISyntaxExceptionTest.class);
         suite.addTestSuite(URITest.class);
         suite.addTestSuite(URLClassLoaderTest.class);
diff --git a/luni/src/test/java/tests/api/java/net/DatagramSocketTest.java b/luni/src/test/java/tests/api/java/net/DatagramSocketTest.java
index 3f35b29..853f6a6 100644
--- a/luni/src/test/java/tests/api/java/net/DatagramSocketTest.java
+++ b/luni/src/test/java/tests/api/java/net/DatagramSocketTest.java
@@ -1584,7 +1584,7 @@
         
         try {
             new java.net.DatagramSocket(isa);
-            fail("SocketException was thrown.");
+            fail("SocketException was not thrown.");
         } catch(SocketException se) {
             //expected
         }
diff --git a/luni/src/test/java/tests/api/java/net/ExcludedProxyTest.java b/luni/src/test/java/tests/api/java/net/ExcludedProxyTest.java
index ae76723..eeb46db 100644
--- a/luni/src/test/java/tests/api/java/net/ExcludedProxyTest.java
+++ b/luni/src/test/java/tests/api/java/net/ExcludedProxyTest.java
@@ -36,6 +36,7 @@
 import tests.support.Support_Configuration;
 import tests.support.resource.Support_Resources;
 import junit.framework.TestCase;
+import tests.util.TestEnvironment;
 
 /*
  * This test is designed for collecting all the testcases which needs a proxy
@@ -46,6 +47,12 @@
 
 @TestTargetClass(Proxy.class) 
 public class ExcludedProxyTest extends TestCase {
+
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+    }
+
     /**
      * @tests java.net.HttpURLConnection#usingProxy()
      */
diff --git a/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java b/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
index 1429063..018d58a 100644
--- a/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
+++ b/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
@@ -17,11 +17,6 @@
 
 package tests.api.java.net;
 
-import dalvik.annotation.KnownFailure; 
-import dalvik.annotation.TestTargetClass; 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
 import java.io.IOException;
 import java.net.BindException;
 import java.net.DatagramPacket;
@@ -34,290 +29,205 @@
 import java.net.SocketAddress;
 import java.net.SocketException;
 import java.net.UnknownHostException;
-import java.security.Permission;
+import java.util.ArrayList;
 import java.util.Enumeration;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.TimeUnit;
 
 import tests.support.Support_NetworkInterface;
 import tests.support.Support_PortManager;
 
-@TestTargetClass(MulticastSocket.class) 
 public class MulticastSocketTest extends SocketTestCase {
 
-    Thread t;
+	Thread t;
 
-    MulticastSocket mss;
+	MulticastSocket mss;
 
-    MulticastServer server;
+	MulticastServer server;
 
-    // private member variables used for tests
-    boolean atLeastOneInterface = false;
+	// private member variables used for tests
+	boolean atLeastOneInterface = false;
 
-    boolean atLeastTwoInterfaces = false;
+	boolean atLeastTwoInterfaces = false;
 
-    private NetworkInterface networkInterface1 = null;
+	private NetworkInterface networkInterface1 = null;
 
-    private NetworkInterface networkInterface2 = null;
+	private NetworkInterface networkInterface2 = null;
 
-    private NetworkInterface IPV6networkInterface1 = null;
+	private NetworkInterface IPV6networkInterface1 = null;
 
-    static class MulticastServer extends Thread {
+	static class MulticastServer extends Thread {
 
-        public MulticastSocket ms;
+		public MulticastSocket ms;
 
-        volatile boolean running = true;
+		boolean running = true;
 
-        private final BlockingQueue<DatagramPacket> queue
-                = new ArrayBlockingQueue<DatagramPacket>(1);
+		volatile public byte[] rbuf = new byte[512];
+
+        volatile DatagramPacket rdp = null;
+        
+        private InetAddress groupAddr = null;
+        private SocketAddress groupSockAddr = null;
+        private NetworkInterface groupNI = null;
 
         public void run() {
-            try {
+			try {
+                byte[] tmpbuf = new byte[512];
+                DatagramPacket tmpPack =
+                        new DatagramPacket(tmpbuf, tmpbuf.length);
+                
                 while (running) {
-                    try {
-                        byte[] rbuf = new byte[512];
-                        rbuf[0] = -1;
-                        DatagramPacket rdp = new DatagramPacket(rbuf, rbuf.length);
-                        ms.receive(rdp);
-                        queue.put(rdp);
+					try {
+                        ms.receive(tmpPack);
+                        
+                        System.arraycopy(tmpPack.getData(), 0, rdp.getData(),
+                                rdp.getOffset(), tmpPack.getLength());
+                        rdp.setLength(tmpPack.getLength());
+                        rdp.setAddress(tmpPack.getAddress());
+                        rdp.setPort(tmpPack.getPort());
                     } catch (java.io.InterruptedIOException e) {
-                    } catch (InterruptedException e) {
-                    }
-                }
-            } catch (java.io.IOException e) {
-                System.out.println("Multicast server failed: " + e);
-            } finally {
-                ms.close();
-            }
-        }
+                        Thread.yield();
+					}
+				}
+			} catch (java.io.IOException e) {
+				System.out.println("Multicast server failed: " + e);
+			} finally {
+				ms.close();
+			}
+		}
 
-        public synchronized void leaveGroup(InetAddress aGroup)
-                throws java.io.IOException {
-            ms.leaveGroup(aGroup);
+		public void stopServer() {
+			running = false;
+            try {
+                if (groupAddr != null) {
+                    ms.leaveGroup(groupAddr);
+                } else if (groupSockAddr != null) {
+                    ms.leaveGroup(groupSockAddr, groupNI);
+                }
+            } catch (IOException e) {}
         }
 
         public MulticastServer(InetAddress anAddress, int aPort)
                 throws java.io.IOException {
+            rbuf = new byte[512];
+            rbuf[0] = -1;
+            rdp = new DatagramPacket(rbuf, rbuf.length);
             ms = new MulticastSocket(aPort);
             ms.setSoTimeout(2000);
-            ms.joinGroup(anAddress);
+            groupAddr = anAddress;
+            ms.joinGroup(groupAddr);
         }
-
+        
+        
         public MulticastServer(SocketAddress anAddress, int aPort,
-                NetworkInterface netInterface) throws java.io.IOException {
-            ms = new MulticastSocket(aPort);
-            ms.setSoTimeout(2000);
-            ms.joinGroup(anAddress, netInterface);
-        }
+				NetworkInterface netInterface) throws java.io.IOException {
+			rbuf = new byte[512];
+			rbuf[0] = -1;
+			rdp = new DatagramPacket(rbuf, rbuf.length);
+			ms = new MulticastSocket(aPort);
+			ms.setSoTimeout(2000);
+            groupSockAddr = anAddress;
+            groupNI = netInterface;
+            ms.joinGroup(groupSockAddr, groupNI);
+		}
+	}
 
-        public DatagramPacket receive() throws InterruptedException {
-            return queue.poll(1000, TimeUnit.MILLISECONDS);
-        }
-
-        public void stopServer() throws InterruptedException {
-            running = false;
-            interrupt();
-            join();
-        }
-    }
-
-    /**
-     * @tests java.net.MulticastSocket#MulticastSocket()
-     */
-    @TestTargetNew(
-        level = TestLevel.SUFFICIENT,
-        notes = "IOException exception checking missed.",
-        method = "MulticastSocket",
-        args = {}
-    )
-    public void test_Constructor() throws IOException {
-        // regression test for 497
+	/**
+	 * @tests java.net.MulticastSocket#MulticastSocket()
+	 */
+	public void test_Constructor() throws IOException {
+		// regression test for 497
         MulticastSocket s = new MulticastSocket();
         // regression test for Harmony-1162
         assertTrue(s.getReuseAddress());
-        
-        SecurityManager sm = new SecurityManager() {
+	}
 
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkListen(int port) {
-                throw new SecurityException();
-            }
-        };
-
-        SecurityManager oldSm = System.getSecurityManager();
-        System.setSecurityManager(sm);
-        try {
-            new MulticastSocket();
-            fail("SecurityException should be thrown.");
-        } catch (SecurityException e) {
-            // expected
-        } catch (SocketException e) {
-            fail("SocketException was thrown.");
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-            e.printStackTrace();
-        } finally {
-            System.setSecurityManager(oldSm);
-        } 
-    }
-
-    /**
-     * @tests java.net.MulticastSocket#MulticastSocket(int)
-     */
-    @TestTargetNew(
-        level = TestLevel.SUFFICIENT,
-        notes = "IOException exception checking missed.",
-        method = "MulticastSocket",
-        args = {int.class}
-    )
-    public void test_ConstructorI() {
-        // Test for method java.net.MulticastSocket(int)
-        // Used in tests
-        MulticastSocket dup = null;
-        try {
-            mss = new MulticastSocket();
-            int port = mss.getLocalPort();
-            dup = new MulticastSocket(port);
+	/**
+	 * @tests java.net.MulticastSocket#MulticastSocket(int)
+	 */
+	public void test_ConstructorI() throws IOException {
+	    MulticastSocket orig = new MulticastSocket();
+        int port = orig.getLocalPort();
+        orig.close();
+		MulticastSocket dup = null;
+		try {
+			dup = new MulticastSocket(port);
             // regression test for Harmony-1162
             assertTrue(dup.getReuseAddress());
-        } catch (IOException e) {
-            fail("duplicate binding not allowed: " + e);
-        }
-        
-        
-        
-        if (dup != null)
-            dup.close();
-        
-        SecurityManager sm = new SecurityManager() {
+		} catch (IOException e) {
+			fail("duplicate binding not allowed: " + e);
+		}
+		if (dup != null)
+			dup.close();
+	}
 
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkListen(int port) {
-                throw new SecurityException();
-            }
-        };
+	/**
+	 * @tests java.net.MulticastSocket#getInterface()
+	 */
+	public void test_getInterface() throws Exception {
+		// Test for method java.net.InetAddress
+		// java.net.MulticastSocket.getInterface()
+		assertTrue("Used for testing.", true);
 
-        SecurityManager oldSm = System.getSecurityManager();
-        System.setSecurityManager(sm);
-        try {
-            new MulticastSocket(1);
-            fail("SecurityException should be thrown.");
-        } catch (SecurityException e) {
-            // expected
-        } catch (SocketException e) {
-            fail("SocketException was thrown.");
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-            e.printStackTrace();
-        } finally {
-            System.setSecurityManager(oldSm);
-        } 
-    }
+		int groupPort = Support_PortManager.getNextPortForUDP();
 
-    /**
-     * @tests java.net.MulticastSocket#getInterface()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getInterface",
-        args = {}
-    )
-    @KnownFailure("No interfaces if there's no debugger connected")
-    public void test_getInterface() {
-        // Test for method java.net.InetAddress
-        // java.net.MulticastSocket.getInterface()
-        assertTrue("Used for testing.", true);
+                if (atLeastOneInterface) {
+                        // validate that we get the expected response when one was not
+                        // set
+                        mss = new MulticastSocket(groupPort);
+                        String preferIPv4StackValue = System
+                                        .getProperty("java.net.preferIPv4Stack");
+                        String preferIPv6AddressesValue = System
+                                        .getProperty("java.net.preferIPv6Addresses");
+                        if (((preferIPv4StackValue == null) || preferIPv4StackValue
+                                        .equalsIgnoreCase("false"))
+                                        && (preferIPv6AddressesValue != null)
+                                        && (preferIPv6AddressesValue.equals("true"))) {
+                                // we expect an IPv6 ANY in this case
+                                assertEquals("inet Address returned when not set",
+                                             InetAddress.getByName("::0"),
+                                             mss.getInterface());
+                        } else {
+                                // we expect an IPv4 ANY in this case
+                                assertEquals("inet Address returned when not set",
+                                             InetAddress.getByName("0.0.0.0"),
+                                             mss.getInterface());
+                        }
 
-        int groupPort = Support_PortManager.getNextPortForUDP();
-        try {
-            if (atLeastOneInterface) {
-                // validate that we get the expected response when one was not
-                // set
-                mss = new MulticastSocket(groupPort);
-                String preferIPv4StackValue = System
-                        .getProperty("java.net.preferIPv4Stack");
-                String preferIPv6AddressesValue = System
-                        .getProperty("java.net.preferIPv6Addresses");
-                if (((preferIPv4StackValue == null) || preferIPv4StackValue
-                        .equalsIgnoreCase("false"))
-                        && (preferIPv6AddressesValue != null)
-                        && (preferIPv6AddressesValue.equals("true"))) {
-                    // we expect an IPv6 ANY in this case
-                    assertTrue("inet Address returned when not set:"
-                            + mss.getInterface().toString(), InetAddress
-                            .getByName("::0").equals(mss.getInterface()));
-                } else {
-                    // we expect an IPv4 ANY in this case
-                    assertNotNull("inet Address returned when not set:", 
-                            mss.getInterface());
+                        // validate that we get the expected response when we set via
+                        // setInterface
+                        Enumeration addresses = networkInterface1.getInetAddresses();
+                        if (addresses.hasMoreElements()) {
+                                InetAddress firstAddress = (InetAddress) addresses
+                                                .nextElement();
+                                mss.setInterface(firstAddress);
+                                assertEquals("getNetworkInterface did not return interface set by setInterface",
+                                             firstAddress, mss.getInterface());
+
+                                groupPort = Support_PortManager.getNextPortForUDP();
+                                mss = new MulticastSocket(groupPort);
+                                mss.setNetworkInterface(networkInterface1);
+                                assertEquals("getInterface did not return interface set by setNetworkInterface",
+                                             networkInterface1,
+                                             NetworkInterface.getByInetAddress(mss.getInterface()));
+                        }
+
                 }
+	}
 
-                // validate that we get the expected response when we set via
-                // setInterface
-                Enumeration addresses = networkInterface1.getInetAddresses();
-                if (addresses != null) {
-                    InetAddress firstAddress = (InetAddress) addresses
-                            .nextElement();
-                    mss.setInterface(firstAddress);
-                    assertTrue(
-                            "getNetworkInterface did not return interface set " +
-                            "by setInterface.  Expected:"
-                                    + firstAddress + " Got:"
-                                    + mss.getInterface(), firstAddress
-                                    .equals(mss.getInterface()));
-
-                    groupPort = Support_PortManager.getNextPortForUDP();
-                    mss = new MulticastSocket(groupPort);
-                    mss.setNetworkInterface(networkInterface1);
-                    InetAddress addr = mss.getInterface();
-                    NetworkInterface if1 = NetworkInterface.getByInetAddress(addr);
-                    assertEquals(
-                            "getInterface did not return interface set by " +
-                            "setNeworkInterface Expected: " + firstAddress
-                                    + "Got:" + mss.getInterface(),
-                                    networkInterface1, if1);
-                }
-                mss.close();
-                try {
-                    mss.getInterface();
-                    fail("SocketException was not thrown.");
-                } catch(SocketException ioe) {
-                    //expected
-                }
-            }
-        } catch (Exception e) {
-            fail("Exception during getInterface test: " + e.toString());
-        }
-    }
-
-    /**
-     * @throws IOException 
-     * @tests java.net.MulticastSocket#getNetworkInterface()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getNetworkInterface",
-        args = {}
-    )
-    @KnownFailure("No interfaces if there's no debugger connected")
-    public void test_getNetworkInterface() throws IOException {
+	/**
+	 * @throws IOException
+	 * @tests java.net.MulticastSocket#getNetworkInterface()
+	 */
+	public void test_getNetworkInterface() throws IOException {
         int groupPort = Support_PortManager.getNextPortForUDP();
         if (atLeastOneInterface) {
             // validate that we get the expected response when one was not
             // set
             mss = new MulticastSocket(groupPort);
             NetworkInterface theInterface = mss.getNetworkInterface();
-            assertNotNull(
-                    "network interface returned wrong network interface when " +
-                    "not set:"
-                            + theInterface, theInterface.getInetAddresses());
+            assertTrue(
+                    "network interface returned wrong network interface when not set:"
+                            + theInterface, theInterface.getInetAddresses()
+                            .hasMoreElements());
             InetAddress firstAddress = (InetAddress) theInterface
                     .getInetAddresses().nextElement();
             // validate we the first address in the network interface is the
@@ -330,42 +240,34 @@
                     .equalsIgnoreCase("false"))
                     && (preferIPv6AddressesValue != null)
                     && (preferIPv6AddressesValue.equals("true"))) {
-                assertTrue(
-                        "network interface returned wrong network interface " +
-                        "when not set:"
-                                + theInterface, InetAddress.getByName("::0")
-                                .equals(firstAddress));
+                assertEquals("network interface returned wrong network interface when not set:"
+                             + theInterface,
+                             firstAddress, InetAddress.getByName("::0"));
 
             } else {
-                assertTrue(
-                        "network interface returned wrong network interface " +
-                        "when not set:"
-                                + theInterface, InetAddress
-                                .getByName("0.0.0.0").equals(firstAddress));
+                assertEquals("network interface returned wrong network interface when not set:"
+                             + theInterface,
+                             InetAddress.getByName("0.0.0.0"),
+                             firstAddress);
             }
 
             mss.setNetworkInterface(networkInterface1);
-            assertTrue(
-                    "getNetworkInterface did not return interface set by " +
-                    "setNeworkInterface",
-                    networkInterface1.equals(mss.getNetworkInterface()));
+            assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
+                         networkInterface1, mss.getNetworkInterface());
 
             if (atLeastTwoInterfaces) {
                 mss.setNetworkInterface(networkInterface2);
-                assertTrue(
-                        "getNetworkInterface did not return network interface " +
-                        "set by second setNetworkInterface call",
-                        networkInterface2.equals(mss.getNetworkInterface()));
+                assertEquals("getNetworkInterface did not return network interface set by second setNetworkInterface call",
+                             networkInterface2, mss.getNetworkInterface());
             }
 
             groupPort = Support_PortManager.getNextPortForUDP();
             mss = new MulticastSocket(groupPort);
             if (IPV6networkInterface1 != null) {
                 mss.setNetworkInterface(IPV6networkInterface1);
-                assertTrue(
-                        "getNetworkInterface did not return interface set " +
-                        "by setNeworkInterface",
-                        IPV6networkInterface1.equals(mss.getNetworkInterface()));
+                assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
+                             IPV6networkInterface1,
+                             mss.getNetworkInterface());
             }
 
             // validate that we get the expected response when we set via
@@ -373,191 +275,100 @@
             groupPort = Support_PortManager.getNextPortForUDP();
             mss = new MulticastSocket(groupPort);
             Enumeration addresses = networkInterface1.getInetAddresses();
-            if (addresses != null) {
+            if (addresses.hasMoreElements()) {
                 firstAddress = (InetAddress) addresses.nextElement();
                 mss.setInterface(firstAddress);
-                assertTrue(
-                        "getNetworkInterface did not return interface set " +
-                        "by setInterface",
-                        networkInterface1.equals(mss.getNetworkInterface()));
-            }
-            
-            mss.close();
-            try {
-                mss.getNetworkInterface();
-                fail("SocketException was not thrown.");
-            } catch(SocketException ioe) {
-                //expected
+                assertEquals("getNetworkInterface did not return interface set by setInterface",
+                             networkInterface1,
+                             mss.getNetworkInterface());
             }
         }
     }
 
-    /**
-     * @tests java.net.MulticastSocket#getTimeToLive()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getTimeToLive",
-        args = {}
-    )
-    public void test_getTimeToLive() {
-        try {
-            mss = new MulticastSocket();
-            mss.setTimeToLive(120);
-            assertTrue("Returned incorrect 1st TTL: " + mss.getTimeToLive(),
-                    mss.getTimeToLive() == 120);
-            mss.setTimeToLive(220);
-            assertTrue("Returned incorrect 2nd TTL: " + mss.getTimeToLive(),
-                    mss.getTimeToLive() == 220);
-            mss.close();
-            try {
-                mss.getTimeToLive();
-                fail("IOException was not thrown.");
-            } catch(IOException ioe) {
-                //expected
-            }
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-        }
-    }
+	/**
+	 * @tests java.net.MulticastSocket#getTimeToLive()
+	 */
+	public void test_getTimeToLive() {
+		try {
+			mss = new MulticastSocket();
+			mss.setTimeToLive(120);
+			assertEquals("Returned incorrect 1st TTL",
+                                     120, mss.getTimeToLive());
+			mss.setTimeToLive(220);
+			assertEquals("Returned incorrect 2nd TTL",
+                                     220, mss.getTimeToLive());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+		}
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#getTTL()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getTTL",
-        args = {}
-    )
-    public void test_getTTL() {
-        // Test for method byte java.net.MulticastSocket.getTTL()
+	/**
+	 * @tests java.net.MulticastSocket#getTTL()
+	 */
+	public void test_getTTL() {
+		// Test for method byte java.net.MulticastSocket.getTTL()
 
-        try {
-            mss = new MulticastSocket();
-            mss.setTTL((byte) 120);
-            assertTrue("Returned incorrect TTL: " + mss.getTTL(),
-                    mss.getTTL() == 120);
-            mss.close();
-            try {
-                mss.getTTL();
-                fail("IOException was not thrown.");
-            } catch(IOException ioe) {
-                //expected
-            }
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-        }
-    }
+		try {
+			mss = new MulticastSocket();
+			mss.setTTL((byte) 120);
+			assertEquals("Returned incorrect TTL",
+                                     120, mss.getTTL());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+		}
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#joinGroup(java.net.InetAddress)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "joinGroup",
-        args = {java.net.InetAddress.class}
-    )
-    public void test_joinGroupLjava_net_InetAddress() throws InterruptedException {
-        // Test for method void
-        // java.net.MulticastSocket.joinGroup(java.net.InetAddress)
-        String msg = null;
-        InetAddress group = null;
-        int[] ports = Support_PortManager.getNextPortsForUDP(2);
-        int groupPort = ports[0];
-        try {
-            group = InetAddress.getByName("224.0.0.3");
-            server = new MulticastServer(group, groupPort);
-            server.start();
-            Thread.sleep(1000);
-            msg = "Hello World";
-            mss = new MulticastSocket(ports[1]);
-            DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
-                    .length(), group, groupPort);
-            mss.joinGroup(group);
-            mss.send(sdp, (byte) 10);
+	/**
+	 * @tests java.net.MulticastSocket#joinGroup(java.net.InetAddress)
+	 */
+	public void test_joinGroupLjava_net_InetAddress() throws Exception {
+		// Test for method void
+		// java.net.MulticastSocket.joinGroup(java.net.InetAddress)
+                String msg = null;
+		InetAddress group = null;
+		int[] ports = Support_PortManager.getNextPortsForUDP(2);
+		int groupPort = ports[0];
+                group = InetAddress.getByName("224.0.0.3");
+                server = new MulticastServer(group, groupPort);
+                server.start();
+                Thread.sleep(1000);
+                msg = "Hello World";
+                mss = new MulticastSocket(ports[1]);
+                DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
+                                .length(), group, groupPort);
+                mss.send(sdp, (byte) 10);
+                Thread.sleep(1000);
 
-            SecurityManager sm = new SecurityManager() {
+                assertEquals("Group member did not recv data",
+                             msg,
+                             new String(server.rdp.getData(), 0, server.rdp.getLength()));
+	}
 
-                public void checkPermission(Permission perm) {
-                }
-                
-                public void checkMulticast(InetAddress maddr) {
-                    throw new SecurityException();
-                }
-            };
+	/**
+	 * @throws IOException 
+	 * @throws InterruptedException 
+	 * @tests java.net.MulticastSocket#joinGroup(java.net.SocketAddress,java.net.NetworkInterface)
+	 */
+	public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws IOException, InterruptedException {
+		// security manager that allows us to check that we only return the
+		// addresses that we should
+		class mySecurityManager extends SecurityManager {
 
-            SecurityManager oldSm = System.getSecurityManager();
-            System.setSecurityManager(sm);
-            try {
-                mss.joinGroup(group);
-                fail("SecurityException should be thrown.");
-            } catch (SecurityException e) {
-                // expected
-            } catch (SocketException e) {
-                fail("SocketException was thrown.");
-            } catch (IOException e) {
-                fail("IOException was thrown.");
-                e.printStackTrace();
-            } finally {
-                System.setSecurityManager(oldSm);
-            } 
-            
-            mss.close();
-            try {
-                mss.joinGroup(group);
-                fail("SocketException was not thrown.");
-            } catch(SocketException ioe) {
-                //expected
-            }
-        } catch (Exception e) {
-            fail("Exception during joinGroup test: " + e.toString());
-        }
-        DatagramPacket rdb = server.receive();
+			public void checkMulticast(InetAddress address) {
+				throw new SecurityException("not allowed");
+			}
+		}
 
-        assertEquals("Group member did not recv data: ", msg,
-                new String(rdb.getData(), 0, rdb.getLength()));
+		String msg = null;
+		InetAddress group = null;
+		SocketAddress groupSockAddr = null;
+		int[] ports = Support_PortManager.getNextPortsForUDP(2);
+		int groupPort = ports[0];
+		int serverPort = ports[1];
 
-    }
-
-    /**
-     * @throws IOException 
-     * @throws InterruptedException 
-     * @tests java.net.MulticastSocket#joinGroup(java.net.SocketAddress,
-     *                                              java.net.NetworkInterface)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "joinGroup",
-        args = {java.net.SocketAddress.class, java.net.NetworkInterface.class}
-    )
-    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() 
-                                    throws IOException, InterruptedException {
-        // security manager that allows us to check that we only return the
-        // addresses that we should
-        class mySecurityManager extends SecurityManager {
-
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkMulticast(InetAddress address) {
-                throw new SecurityException("not allowed");
-            }
-        }
-
-        String msg = null;
-        InetAddress group = null;
-        SocketAddress groupSockAddr = null;
-        int[] ports = Support_PortManager.getNextPortsForUDP(2);
-        int groupPort = ports[0];
-        int serverPort = ports[1];
-
-            Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
+        Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
 
         // first validate that we handle a null group ok
         mss = new MulticastSocket(groupPort);
@@ -613,11 +424,11 @@
                     .length(), group, serverPort);
             mss.setTimeToLive(2);
             mss.send(sdp);
-            DatagramPacket rdp = server.receive();
-
+            Thread.sleep(1000);
             // now vaildate that we received the data as expected
-            assertEquals("Group member did not recv data: ", msg,
-                    new String(rdp.getData(), 0, rdp.getLength()));
+            assertEquals("Group member did not recv data",
+                         msg,
+                         new String(server.rdp.getData(), 0, server.rdp.getLength()));
             server.stopServer();
 
             // now validate that we handled the case were we join a
@@ -638,9 +449,11 @@
             sdp = new DatagramPacket(msg.getBytes(), msg.length(), group2,
                     serverPort);
             mss.send(sdp);
-            rdp = server.receive();
-            assertNull("Group member received data when sent on different group",
-                    rdp);
+            Thread.sleep(1000);
+            assertFalse(
+                    "Group member received data when sent on different group: ",
+                    new String(server.rdp.getData(), 0, server.rdp.getLength())
+                            .equals(msg));
             server.stopServer();
 
             // if there is more than one network interface then check that
@@ -651,39 +464,47 @@
                 NetworkInterface loopbackInterface = NetworkInterface
                         .getByInetAddress(InetAddress.getByName("127.0.0.1"));
 
+                boolean anyLoop = networkInterface1.equals(loopbackInterface) || networkInterface2.equals(loopbackInterface);
+                
+                ArrayList<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
                 theInterfaces = NetworkInterface.getNetworkInterfaces();
                 while (theInterfaces.hasMoreElements()) {
-
-                    NetworkInterface thisInterface = (NetworkInterface) 
-                                                    theInterfaces.nextElement();
-                    if ((thisInterface.getInetAddresses() != null && thisInterface
-                            .getInetAddresses().hasMoreElements())
+                    NetworkInterface thisInterface = (NetworkInterface) theInterfaces.nextElement();
+                    if (thisInterface.getInetAddresses().hasMoreElements()
                             && (Support_NetworkInterface
-                                    .useInterface(thisInterface) == true)) {
+                                    .useInterface(thisInterface) == true)){
+                        realInterfaces.add(thisInterface);
+                    }
+                }
+                
+                for (int i = 0; i < realInterfaces.size(); i++) {
+                    final int SECOND = 1;
+                    NetworkInterface thisInterface = realInterfaces.get(i);
+                   
                         // get the first address on the interface
 
                         // start server which is joined to the group and has
                         // only asked for packets on this interface
-                        Enumeration addresses = thisInterface
-                                .getInetAddresses();
+                        Enumeration<InetAddress> addresses = thisInterface.getInetAddresses();
 
                         NetworkInterface sendingInterface = null;
-                        boolean isLoopback = false;
-                        if (addresses != null) {
-                            InetAddress firstAddress = (InetAddress) addresses
-                                    .nextElement();
-                            if (firstAddress.isLoopbackAddress()) {
-                                isLoopback = true;
-                            }
+                        if (addresses.hasMoreElements()) {
+                            InetAddress firstAddress = (InetAddress) addresses.nextElement();
                             if (firstAddress instanceof Inet4Address) {
                                 group = InetAddress.getByName("224.0.0.4");
-                                if (networkInterface1.equals(NetworkInterface
-                                        .getByInetAddress(InetAddress
-                                                .getByName("127.0.0.1")))) {
-                                    sendingInterface = networkInterface2;
+                                if (anyLoop) {
+                                    if (networkInterface1.equals(loopbackInterface)) {
+                                        sendingInterface = networkInterface2;
+                                    } else {
+                                        sendingInterface = networkInterface1;
+                                    }
                                 } else {
-                                    sendingInterface = networkInterface1;
+                                    if(i == SECOND){
+                                        sendingInterface = networkInterface2;
+                                    } else {
+                                        sendingInterface = networkInterface1;
                                 }
+                               }
                             } else {
                                 // if this interface only seems to support
                                 // IPV6 addresses
@@ -693,13 +514,6 @@
                             }
                         }
 
-                        InetAddress useAddress = null;
-                        addresses = sendingInterface.getInetAddresses();
-                        if ((addresses != null)
-                                && (addresses.hasMoreElements())) {
-                            useAddress = (InetAddress) addresses.nextElement();
-                        }
-
                         ports = Support_PortManager.getNextPortsForUDP(2);
                         serverPort = ports[0];
                         groupPort = ports[1];
@@ -712,33 +526,27 @@
                         // Now send out a package on interface
                         // networkInterface 1. We should
                         // only see the packet if we send it on interface 1
-                        InetSocketAddress theAddress = new InetSocketAddress(
-                                useAddress, groupPort);
                         mss = new MulticastSocket(groupPort);
                         mss.setNetworkInterface(sendingInterface);
                         msg = "Hello World - Again" + thisInterface.getName();
                         sdp = new DatagramPacket(msg.getBytes(), msg.length(),
                                 group, serverPort);
                         mss.send(sdp);
-                        rdp = server.receive();
-
+                        Thread.sleep(1000);
                         if (thisInterface.equals(sendingInterface)) {
-                            assertEquals(
-                                    "Group member did not recv data when " +
-                                    "bound on specific interface: ", msg,
-                                    new String(rdp.getData(), 0, rdp.getLength()));
+                            assertEquals("Group member did not recv data when bound on specific interface",
+                                         msg,
+                                         new String(server.rdp.getData(), 0, server.rdp.getLength()));
                         } else {
                             assertFalse(
-                                    "Group member received data on other " +
-                                    "interface when only asked for it on one " +
-                                    "interface: ",
-                                    new String(rdp.getData(), 0,
-                                            rdp.getLength()).equals(msg));
+                                    "Group member received data on other interface when only asked for it on one interface: ",
+                                    new String(server.rdp.getData(), 0,
+                                            server.rdp.getLength()).equals(msg));
                         }
 
                         server.stopServer();
                     }
-                }
+                
 
                 // validate that we can join the same address on two
                 // different interfaces but not on the same interface
@@ -748,373 +556,252 @@
                 mss.joinGroup(groupSockAddr, networkInterface2);
                 try {
                     mss.joinGroup(groupSockAddr, networkInterface1);
-                    fail("Did not get expected exception when joining for " +
-                            "second time on same interface");
+                    fail("Did not get expected exception when joining for second time on same interface");
                 } catch (IOException e) {
                 }
             }
         }
-        System.setSecurityManager(null);
-    }
+		System.setSecurityManager(null);
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#leaveGroup(java.net.InetAddress)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "leaveGroup",
-        args = {java.net.InetAddress.class}
-    )
-    public void test_leaveGroupLjava_net_InetAddress() {
-        // Test for method void
-        // java.net.MulticastSocket.leaveGroup(java.net.InetAddress)
-        String msg = null;
-        boolean except = false;
-        InetAddress group = null;
-        int[] ports = Support_PortManager.getNextPortsForUDP(2);
-        int groupPort = ports[0];
+	/**
+	 * @tests java.net.MulticastSocket#leaveGroup(java.net.InetAddress)
+	 */
+	public void test_leaveGroupLjava_net_InetAddress() {
+		// Test for method void
+		// java.net.MulticastSocket.leaveGroup(java.net.InetAddress)
+		String msg = null;
+		boolean except = false;
+		InetAddress group = null;
+		int[] ports = Support_PortManager.getNextPortsForUDP(2);
+		int groupPort = ports[0];
 
-        try {
-            group = InetAddress.getByName("224.0.0.3");
-            msg = "Hello World";
-            mss = new MulticastSocket(ports[1]);
-            DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
-                    .length(), group, groupPort);
-            mss.send(sdp, (byte) 10);
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-        }
-        try {
-            // Try to leave s group that mss is not a member of
-            mss.leaveGroup(group);
-        } catch (java.io.IOException e) {
-            // Correct
-            except = true;
-        }
-        assertTrue("Failed to throw exception leaving non-member group", except);
-        
-        SecurityManager sm = new SecurityManager() {
+		try {
+			group = InetAddress.getByName("224.0.0.3");
+			msg = "Hello World";
+			mss = new MulticastSocket(ports[1]);
+			DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
+					.length(), group, groupPort);
+			mss.send(sdp, (byte) 10);
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+		}
+		try {
+			// Try to leave s group that mss is not a member of
+			mss.leaveGroup(group);
+		} catch (java.io.IOException e) {
+			// Correct
+			except = true;
+		}
+		assertTrue("Failed to throw exception leaving non-member group", except);
+	}
 
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkMulticast(InetAddress maddr) {
-                throw new SecurityException();
-            }
-        };
+	/**
+	 * @tests java.net.MulticastSocket#leaveGroup(java.net.SocketAddress,java.net.NetworkInterface)
+	 */
+	public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws Exception {
+		// security manager that allows us to check that we only return the
+		// addresses that we should
+		class mySecurityManager extends SecurityManager {
 
-        SecurityManager oldSm = System.getSecurityManager();
-        System.setSecurityManager(sm);
-        try {
-            mss.leaveGroup(group);
-            fail("SecurityException should be thrown.");
-        } catch (SecurityException e) {
-            // expected
-        } catch (SocketException e) {
-            fail("SocketException was thrown.");
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-            e.printStackTrace();
-        } finally {
-            System.setSecurityManager(oldSm);
-        } 
-    }
+			public void checkMulticast(InetAddress address) {
+				throw new SecurityException("not allowed");
+			}
+		}
 
-    /**
-     * @tests java.net.MulticastSocket#leaveGroup(java.net.SocketAddress,
-     * java.net.NetworkInterface)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "leaveGroup",
-        args = {java.net.SocketAddress.class, java.net.NetworkInterface.class}
-    )
-    public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface() {
-        // security manager that allows us to check that we only return the
-        // addresses that we should
-        class mySecurityManager extends SecurityManager {
-            
-            public void checkPermission(Permission p) {
-            }
+		String msg = null;
+		InetAddress group = null;
+		int groupPort = Support_PortManager.getNextPortForUDP();
+		SocketAddress groupSockAddr = null;
+		SocketAddress groupSockAddr2 = null;
 
-            public void checkMulticast(InetAddress address) {
-                throw new SecurityException("not allowed");
-            }
-        }
+                Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
 
-        String msg = null;
-        InetAddress group = null;
-        int groupPort = Support_PortManager.getNextPortForUDP();
-        SocketAddress groupSockAddr = null;
-        SocketAddress groupSockAddr2 = null;
-
-        try {
-            Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
-
-            // first validate that we handle a null group ok
-            mss = new MulticastSocket(groupPort);
-            try {
-                mss.leaveGroup(null, null);
-                fail("Did not get exception when group was null");
-            } catch (IllegalArgumentException e) {
-            }
-
-            // now validate we get the expected error if the address specified
-            // is not a multicast group
-            try {
-                group = InetAddress.getByName("255.255.255.255");
-                groupSockAddr = new InetSocketAddress(group, groupPort);
-                mss.leaveGroup(groupSockAddr, null);
-                fail("Did not get exception when group is not a " +
-                        "multicast address");
-            } catch (IOException e) {
-            }
-
-            // now try to leave a group if we are not authorized
-            // set the security manager that will make the first address not
-            // visible
-            System.setSecurityManager(new mySecurityManager());
-            try {
-                group = InetAddress.getByName("224.0.0.3");
-                groupSockAddr = new InetSocketAddress(group, groupPort);
-                mss.leaveGroup(groupSockAddr, null);
-                fail("Did not get exception when joining group is " +
-                        "not allowed");
-            } catch (SecurityException e) {
-            }
-            System.setSecurityManager(null);
-
-            if (atLeastOneInterface) {
-
-                // now test that we can join and leave a group successfully
-                groupPort = Support_PortManager.getNextPortForUDP();
+                // first validate that we handle a null group ok
                 mss = new MulticastSocket(groupPort);
-                groupSockAddr = new InetSocketAddress(group, groupPort);
-                mss.joinGroup(groupSockAddr, null);
-                mss.leaveGroup(groupSockAddr, null);
                 try {
-                    mss.leaveGroup(groupSockAddr, null);
-                    fail(
-                            "Did not get exception when trying to leave " +
-                            "group that was allready left");
+                        mss.leaveGroup(null, null);
+                        fail("Did not get exception when group was null");
+                } catch (IllegalArgumentException e) {
+                }
+
+                // now validate we get the expected error if the address specified
+                // is not a multicast group
+                try {
+                        group = InetAddress.getByName("255.255.255.255");
+                        groupSockAddr = new InetSocketAddress(group, groupPort);
+                        mss.leaveGroup(groupSockAddr, null);
+                        fail("Did not get exception when group is not a multicast address");
                 } catch (IOException e) {
                 }
 
-                InetAddress group2 = InetAddress.getByName("224.0.0.4");
-                groupSockAddr2 = new InetSocketAddress(group2, groupPort);
-                mss.joinGroup(groupSockAddr, networkInterface1);
+                // now try to leave a group if we are not authorized
+                // set the security manager that will make the first address not
+                // visible
+                System.setSecurityManager(new mySecurityManager());
                 try {
-                    mss.leaveGroup(groupSockAddr2, networkInterface1);
-                    fail(
-                            "Did not get exception when trying to leave " +
-                            "group that was never joined");
-                } catch (IOException e) {
+                        group = InetAddress.getByName("224.0.0.3");
+                        groupSockAddr = new InetSocketAddress(group, groupPort);
+                        mss.leaveGroup(groupSockAddr, null);
+                        fail("Did not get exception when joining group is not allowed");
+                } catch (SecurityException e) {
+                }
+                System.setSecurityManager(null);
+
+                if (atLeastOneInterface) {
+
+                        // now test that we can join and leave a group successfully
+                        groupPort = Support_PortManager.getNextPortForUDP();
+                        mss = new MulticastSocket(groupPort);
+                        groupSockAddr = new InetSocketAddress(group, groupPort);
+                        mss.joinGroup(groupSockAddr, null);
+                        mss.leaveGroup(groupSockAddr, null);
+                        try {
+                                mss.leaveGroup(groupSockAddr, null);
+                                fail(
+                                                "Did not get exception when trying to leave group that was allready left");
+                        } catch (IOException e) {
+                        }
+
+                        InetAddress group2 = InetAddress.getByName("224.0.0.4");
+                        groupSockAddr2 = new InetSocketAddress(group2, groupPort);
+                        mss.joinGroup(groupSockAddr, networkInterface1);
+                        try {
+                                mss.leaveGroup(groupSockAddr2, networkInterface1);
+                                fail(
+                                                "Did not get exception when trying to leave group that was never joined");
+                        } catch (IOException e) {
+                        }
+
+                        mss.leaveGroup(groupSockAddr, networkInterface1);
+                        if (atLeastTwoInterfaces) {
+                                mss.joinGroup(groupSockAddr, networkInterface1);
+                                try {
+                                        mss.leaveGroup(groupSockAddr, networkInterface2);
+                                        fail(
+                                                        "Did not get exception when trying to leave group on wrong interface joined on ["
+                                                                        + networkInterface1
+                                                                        + "] left on ["
+                                                                        + networkInterface2 + "]");
+                                } catch (IOException e) {
+                                }
+                        }
                 }
 
-                mss.leaveGroup(groupSockAddr, networkInterface1);
-                if (atLeastTwoInterfaces) {
-                    mss.joinGroup(groupSockAddr, networkInterface1);
-                    try {
-                        mss.leaveGroup(groupSockAddr, networkInterface2);
-                        fail(
-                                "Did not get exception when trying to leave " +
-                                "group on wrong interface joined on ["
-                                        + networkInterface1
-                                        + "] left on ["
-                                        + networkInterface2 + "]");
-                    } catch (IOException e) {
-                    }
-                }
-            }
-        } catch (Exception e) {
-            fail("Exception during leaveGroup test: " + e.toString());
-        } finally {
-            System.setSecurityManager(null);
-        }
-    }
+                System.setSecurityManager(null);
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#send(java.net.DatagramPacket, byte)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "send",
-        args = {java.net.DatagramPacket.class, byte.class}
-    )
-    public void test_sendLjava_net_DatagramPacketB() throws InterruptedException {
-        // Test for method void
-        // java.net.MulticastSocket.send(java.net.DatagramPacket, byte)
+	/**
+	 * @tests java.net.MulticastSocket#send(java.net.DatagramPacket, byte)
+	 */
+	public void test_sendLjava_net_DatagramPacketB() {
+		// Test for method void
+		// java.net.MulticastSocket.send(java.net.DatagramPacket, byte)
 
-        String msg = "Hello World";
-        InetAddress group = null;
-        int[] ports = Support_PortManager.getNextPortsForUDP(2);
-        int groupPort = ports[0];
+		String msg = "Hello World";
+		InetAddress group = null;
+		int[] ports = Support_PortManager.getNextPortsForUDP(2);
+		int groupPort = ports[0];
 
-        try {
-            group = InetAddress.getByName("224.0.0.3");
-            mss = new MulticastSocket(ports[1]);
-            server = new MulticastServer(group, groupPort);
-            server.start();
-            Thread.sleep(200);
-            DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
-                    .length(), group, groupPort);
-            mss.send(sdp, (byte) 10);
-            Thread.sleep(1000);
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-            try {
-                mss.close();
-            } catch (Exception ex) {
-            }
-            
-            return;
-        }
-        
-        DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
-                .length(), group, groupPort);
+		try {
+			group = InetAddress.getByName("224.0.0.3");
+			mss = new MulticastSocket(ports[1]);
+			server = new MulticastServer(group, groupPort);
+			server.start();
+			Thread.sleep(200);
+			DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
+					.length(), group, groupPort);
+			mss.send(sdp, (byte) 10);
+			Thread.sleep(1000);
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+			try {
+				mss.close();
+			} catch (Exception ex) {
+			}
+			;
+			return;
+		}
+		mss.close();
+		byte[] data = server.rdp.getData();
+		int length = server.rdp.getLength();
+		assertEquals("Failed to send data. Received " + length,
+                             msg, new String(data, 0, length));
+	}
 
-        
-        SecurityManager sm = new SecurityManager() {
+	/**
+	 * @tests java.net.MulticastSocket#setInterface(java.net.InetAddress)
+	 */
+	public void test_setInterfaceLjava_net_InetAddress() throws UnknownHostException {
+		// Test for method void
+		// java.net.MulticastSocket.setInterface(java.net.InetAddress)
+		// Note that the machine is not multi-homed
 
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkConnect(String host,
-                    int port) {
-                throw new SecurityException();
-            }
-            
-            public void checkMulticast(InetAddress maddr) {
-                throw new SecurityException();
-            }
-        };
+		try {
+			mss = new MulticastSocket();
+			mss.setInterface(InetAddress.getLocalHost());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST_INTERFACE);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST_INTERFACE);
+			return;
+		}
+		try {
+			InetAddress theInterface = mss.getInterface();
+			// under IPV6 we are not guarrenteed to get the same address back as
+			// the address, all we should be guaranteed is that we get an
+			// address on the same interface
+			if (theInterface instanceof Inet6Address) {
+				assertTrue(
+						"Failed to return correct interface IPV6",
+						NetworkInterface
+								.getByInetAddress(mss.getInterface())
+								.equals(
+										NetworkInterface
+												.getByInetAddress(theInterface)));
+			} else {
+				assertTrue("Failed to return correct interface IPV4 got:"
+						+ mss.getInterface() + " excpeted: "
+						+ InetAddress.getLocalHost(), mss.getInterface()
+						.equals(InetAddress.getLocalHost()));
+			}
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (SocketException e) {
+			handleException(e, SO_MULTICAST);
+		}
 
-        SecurityManager oldSm = System.getSecurityManager();
-        System.setSecurityManager(sm);
-        try {
-            mss.send(sdp);
-            fail("SecurityException should be thrown.");
-        } catch (SecurityException e) {
-            // expected
-        } catch (SocketException e) {
-            fail("SocketException was thrown.");
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-            e.printStackTrace();
-        } finally {
-            System.setSecurityManager(oldSm);
-        } 
-        
-        mss.close();
-        
-        try {
-            mss.send(sdp);
-            fail("IOException should be thrown.");
-        } catch(IOException ioe) {
-            //expected
-        }
+		// Regression test for Harmony-2410
+		try {
+			mss = new MulticastSocket();
+			mss.setInterface(InetAddress.getByName("224.0.0.5"));
+		} catch (SocketException se) {
+			// expected
+		} catch (IOException ioe) {
+			handleException(ioe, SO_MULTICAST_INTERFACE);
+			return;
+		}
+	}
 
-        DatagramPacket rdp = server.receive();
-        assertEquals("Failed to send data. Received " + rdp.getLength(), msg,
-                new String(rdp.getData(), 0, rdp.getLength()));
-    }
-
-    /**
-     * @tests java.net.MulticastSocket#setInterface(java.net.InetAddress)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "setInterface",
-        args = {java.net.InetAddress.class}
-    )
-    public void test_setInterfaceLjava_net_InetAddress() {
-        // Test for method void
-        // java.net.MulticastSocket.setInterface(java.net.InetAddress)
-        // Note that the machine is not multi-homed
-
-        try {
-            mss = new MulticastSocket();
-            mss.setInterface(InetAddress.getLocalHost());
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST_INTERFACE);
-        } catch (Exception e) {
-            //handleException(e, SO_MULTICAST_INTERFACE);
-            return;
-        }
-        try {
-            InetAddress theInterface = mss.getInterface();
-            // under IPV6 we are not guarrenteed to get the same address back as
-            // the address, all we should be guaranteed is that we get an
-            // address on the same interface
-            if (theInterface instanceof Inet6Address) {
-                assertTrue(
-                        "Failed to return correct interface IPV6",
-                        NetworkInterface
-                                .getByInetAddress(mss.getInterface())
-                                .equals(
-                                        NetworkInterface
-                                                .getByInetAddress(theInterface)));
-            } else {
-                assertTrue("Failed to return correct interface IPV4 got:"
-                        + mss.getInterface() + " excpeted: "
-                        + InetAddress.getLocalHost(), mss.getInterface()
-                        .equals(InetAddress.getLocalHost()));
-            }
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (SocketException e) {
-            handleException(e, SO_MULTICAST);
-        } catch (UnknownHostException e) {
-            fail("Exception during setInterface test: " + e.toString());
-        }
-
-        // Regression test for Harmony-2410
-        try {
-            mss = new MulticastSocket();
-            mss.setInterface(InetAddress.getByName("224.0.0.5"));
-        } catch (UnknownHostException uhe) {
-            fail("Unable to get InetAddress by name from '224.0.0.5' addr: " 
-                    + uhe.toString());
-        } catch (SocketException se) {
-            // expected
-        } catch (IOException ioe) {
-            handleException(ioe, SO_MULTICAST_INTERFACE);
-            return;
-        }
-    }
-
-    /**
-     * @throws IOException 
-     * @throws InterruptedException 
-     * @tests java.net.MulticastSocket#setNetworkInterface(
-     *                                              java.net.NetworkInterface)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "setNetworkInterface",
-        args = {java.net.NetworkInterface.class}
-    )
-    public void test_setNetworkInterfaceLjava_net_NetworkInterface() 
-                                    throws IOException, InterruptedException {
-        String msg = null;
-        InetAddress group = null;
-        int[] ports = Support_PortManager.getNextPortsForUDP(2);
-        int groupPort = ports[0];
-        int serverPort = ports[1];
-        if (atLeastOneInterface) {
+	/**
+	 * @throws IOException 
+	 * @throws InterruptedException 
+	 * @tests java.net.MulticastSocket#setNetworkInterface(java.net.NetworkInterface)
+	 */
+	public void test_setNetworkInterfaceLjava_net_NetworkInterface() throws IOException, InterruptedException {
+		String msg = null;
+		InetAddress group = null;
+		int[] ports = Support_PortManager.getNextPortsForUDP(2);
+		int groupPort = ports[0];
+		int serverPort = ports[1];
+		if (atLeastOneInterface) {
             // validate that null interface is handled ok
             mss = new MulticastSocket(groupPort);
 
             // this should through a socket exception to be compatible
             try {
                 mss.setNetworkInterface(null);
-                fail("No socket exception when we set then network " +
-                        "interface with NULL");
+                fail("No socket exception when we set then network interface with NULL");
             } catch (SocketException ex) {
             }
 
@@ -1122,9 +809,8 @@
             groupPort = Support_PortManager.getNextPortForUDP();
             mss = new MulticastSocket(groupPort);
             mss.setNetworkInterface(networkInterface1);
-            assertTrue(
-                    "Interface did not seem to be set by setNeworkInterface",
-                    networkInterface1.equals(mss.getNetworkInterface()));
+            assertEquals("Interface did not seem to be set by setNeworkInterface",
+                         networkInterface1, mss.getNetworkInterface());
 
             // set up the server and join the group
             group = InetAddress.getByName("224.0.0.3");
@@ -1133,8 +819,7 @@
             while (theInterfaces.hasMoreElements()) {
                 NetworkInterface thisInterface = (NetworkInterface) theInterfaces
                         .nextElement();
-                if (thisInterface.getInetAddresses() != null
-                        && thisInterface.getInetAddresses().hasMoreElements()) {
+                if (thisInterface.getInetAddresses().hasMoreElements()) {
                     if ((!((InetAddress) thisInterface.getInetAddresses()
                             .nextElement()).isLoopbackAddress())
                             &&
@@ -1163,95 +848,57 @@
                         DatagramPacket sdp = new DatagramPacket(theBytes,
                                 theBytes.length, group, serverPort);
                         mss.send(sdp);
-                        DatagramPacket rdp = server.receive();
-
-                        String receivedMessage = new String(rdp.getData(), 0, rdp.getLength());
-                        assertEquals("Group member did not recv data when send on "
-                                + "a specific interface: ", msg, receivedMessage);
-                        assertEquals("Datagram was not received as expected.",
-                                thisInterface, NetworkInterface.getByInetAddress(rdp.getAddress()));
-
+                        Thread.sleep(1000);
+                        String receivedMessage = new String(server.rdp
+                                .getData(), 0, server.rdp.getLength());
+                        assertEquals("Group member did not recv data sent on a specific interface",
+                                     msg, receivedMessage);
                         // stop the server
                         server.stopServer();
                     }
                 }
             }
         }
-    }
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#setTimeToLive(int)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "setTimeToLive",
-        args = {int.class}
-    )
-    public void test_setTimeToLiveI() {
-        try {
-            mss = new MulticastSocket();
-            mss.setTimeToLive(120);
-            assertTrue("Returned incorrect 1st TTL: " + mss.getTimeToLive(),
-                    mss.getTimeToLive() == 120);
-            mss.setTimeToLive(220);
-            assertTrue("Returned incorrect 2nd TTL: " + mss.getTimeToLive(),
-                    mss.getTimeToLive() == 220);
-            mss.close();
-            try {
-                mss.setTimeToLive(1);
-                fail("IOException was not thrown.");
-            }catch(IOException ioe) {
-                //expected
-            } 
-            
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-        }
-    }
+	/**
+	 * @tests java.net.MulticastSocket#setTimeToLive(int)
+	 */
+	public void test_setTimeToLiveI() {
+		try {
+			mss = new MulticastSocket();
+			mss.setTimeToLive(120);
+			assertEquals("Returned incorrect 1st TTL",
+                                     120, mss.getTimeToLive());
+			mss.setTimeToLive(220);
+			assertEquals("Returned incorrect 2nd TTL",
+                                     220, mss.getTimeToLive());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+		}
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#setTTL(byte)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "setTTL",
-        args = {byte.class}
-    )
-    public void test_setTTLB() {
-        // Test for method void java.net.MulticastSocket.setTTL(byte)
-        try {
-            mss = new MulticastSocket();
-            mss.setTTL((byte) 120);
-            assertTrue("Failed to set TTL: " + mss.getTTL(),
-                    mss.getTTL() == 120);
-            
-            mss.close();
-            try {
-                mss.setTTL((byte) 1);
-                fail("IOException was not thrown.");
-            } catch(IOException ioe) {
-                //expected
-            } 
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-        }
-    }
+	/**
+	 * @tests java.net.MulticastSocket#setTTL(byte)
+	 */
+	public void test_setTTLB() {
+		// Test for method void java.net.MulticastSocket.setTTL(byte)
+		try {
+			mss = new MulticastSocket();
+			mss.setTTL((byte) 120);
+			assertEquals("Failed to set TTL", 120, mss.getTTL());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+		}
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#MulticastSocket(java.net.SocketAddress)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "MulticastSocket",
-        args = {java.net.SocketAddress.class}
-    )
-    public void test_ConstructorLjava_net_SocketAddress() throws Exception {    
-        MulticastSocket ms = new MulticastSocket((SocketAddress) null);
+	/**
+	 * @tests java.net.MulticastSocket#MulticastSocket(java.net.SocketAddress)
+	 */
+	public void test_ConstructorLjava_net_SocketAddress() throws Exception {	
+		MulticastSocket ms = new MulticastSocket((SocketAddress) null);
         assertTrue("should not be bound", !ms.isBound() && !ms.isClosed()
                 && !ms.isConnected());
         ms.bind(new InetSocketAddress(InetAddress.getLocalHost(),
@@ -1285,109 +932,48 @@
         InetSocketAddress addr = new InetSocketAddress("0.0.0.0", 0);
         MulticastSocket s = new MulticastSocket(addr);
         assertTrue(s.getReuseAddress()); 
-        
-        InetSocketAddress isa = new InetSocketAddress(InetAddress
-                .getLocalHost(), Support_PortManager.getNextPortForUDP());
-        
-        SecurityManager sm = new SecurityManager() {
+	}
 
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkListen(int port) {
-                throw new SecurityException();
-            }
-        };
-        
-        SecurityManager oldSm = System.getSecurityManager();
-        System.setSecurityManager(sm);
-        try {
-            new MulticastSocket(isa);
-            fail("SecurityException should be thrown.");
-        } catch (SecurityException e) {
-            // expected
-        } catch (SocketException e) {
-            fail("SocketException was thrown.");
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-            e.printStackTrace();
-        } finally {
-            System.setSecurityManager(oldSm);
-        }  
-    }
+	/**
+	 * @tests java.net.MulticastSocket#getLoopbackMode()
+	 */
+	public void test_getLoopbackMode() {
+		try {
+			MulticastSocket ms = new MulticastSocket((SocketAddress) null);
+			assertTrue("should not be bound", !ms.isBound() && !ms.isClosed()
+					&& !ms.isConnected());
+			ms.getLoopbackMode();
+			assertTrue("should not be bound", !ms.isBound() && !ms.isClosed()
+					&& !ms.isConnected());
+			ms.close();
+			assertTrue("should be closed", ms.isClosed());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_USELOOPBACK);
+		} catch (IOException e) {
+			handleException(e, SO_USELOOPBACK);
+		}
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#getLoopbackMode()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getLoopbackMode",
-        args = {}
-    )
-    public void test_getLoopbackMode() {
-        try {
-            MulticastSocket ms = new MulticastSocket((SocketAddress) null);
-            assertTrue("should not be bound", !ms.isBound() && !ms.isClosed()
-                    && !ms.isConnected());
-            ms.getLoopbackMode();
-            assertTrue("should not be bound", !ms.isBound() && !ms.isClosed()
-                    && !ms.isConnected());
-            ms.close();
-            assertTrue("should be closed", ms.isClosed());
-            try {
-                ms.getLoopbackMode();
-                fail("SocketException was not thrown.");
-            } catch(SocketException ioe) {
-                //expected
-            }
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_USELOOPBACK);
-        } catch (IOException e) {
-            handleException(e, SO_USELOOPBACK);
-        }
-    }
-
-    /**
-     * @tests java.net.MulticastSocket#setLoopbackMode(boolean)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "setLoopbackMode",
-        args = {boolean.class}
-    )
-    public void test_setLoopbackModeZ() {
-        try {
-            MulticastSocket ms = new MulticastSocket();
-            ms.setLoopbackMode(true);
-            assertTrue("loopback should be true", ms.getLoopbackMode());
-            ms.setLoopbackMode(false);
-            assertTrue("loopback should be false", !ms.getLoopbackMode());
-            ms.close();
-            assertTrue("should be closed", ms.isClosed());
-            
-            try {
-                ms.setLoopbackMode(true);
-                fail("SocketException was not thrown.");
-            } catch(SocketException se) {
-                //expected
-            }
-            
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_USELOOPBACK);
-        } catch (IOException e) {
-            handleException(e, SO_USELOOPBACK);
-        }
-    }
+	/**
+	 * @tests java.net.MulticastSocket#setLoopbackMode(boolean)
+	 */
+	public void test_setLoopbackModeZ() {
+		try {
+			MulticastSocket ms = new MulticastSocket();
+			ms.setLoopbackMode(true);
+			assertTrue("loopback should be true", ms.getLoopbackMode());
+			ms.setLoopbackMode(false);
+			assertTrue("loopback should be false", !ms.getLoopbackMode());
+			ms.close();
+			assertTrue("should be closed", ms.isClosed());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_USELOOPBACK);
+		} catch (IOException e) {
+			handleException(e, SO_USELOOPBACK);
+		}
+	}
     
     /**
      * @tests java.net.MulticastSocket#setLoopbackMode(boolean)
      */
-    @TestTargetNew(
-        level = TestLevel.ADDITIONAL,
-        notes = "SocketException checking missed",
-        method = "setLoopbackMode",
-        args = {boolean.class}
-    )
     public void test_setLoopbackModeSendReceive() throws IOException{
         final String ADDRESS = "224.1.2.3";
         final int PORT = Support_PortManager.getNextPortForUDP();
@@ -1418,120 +1004,99 @@
             String recvMessage = new String(recvData, 0, recvDatagram
                     .getLength());
             assertEquals(message, recvMessage);
-        } finally {
+        }finally {
             if (socket != null)
                 socket.close();
         }
     }
     
     
-    /**
-     * @tests java.net.MulticastSocket#setReuseAddress(boolean)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "SocketException checking missesd. Method inherited from " +
-                "class java.net.DatagramSocket",
-        method = "setReuseAddress",
-        args = {boolean.class}
-    )
-    public void test_setReuseAddressZ() {
-        try {
-            // test case were we set it to false
-            MulticastSocket theSocket1 = null;
-            MulticastSocket theSocket2 = null;
-            try {
-                InetSocketAddress theAddress = new InetSocketAddress(
-                        InetAddress.getLocalHost(), Support_PortManager
-                                .getNextPortForUDP());
-                theSocket1 = new MulticastSocket(null);
-                theSocket2 = new MulticastSocket(null);
-                theSocket1.setReuseAddress(false);
-                theSocket2.setReuseAddress(false);
-                theSocket1.bind(theAddress);
-                theSocket2.bind(theAddress);
-                fail(
-                        "No exception when trying to connect to do " +
-                        "duplicate socket bind with re-useaddr set to false");
-            } catch (BindException e) {
+	/**
+	 * @tests java.net.MulticastSocket#setReuseAddress(boolean)
+	 */
+	public void test_setReuseAddressZ() throws Exception {
+		try {
+			// test case were we set it to false
+			MulticastSocket theSocket1 = null;
+			MulticastSocket theSocket2 = null;
+			try {
+				InetSocketAddress theAddress = new InetSocketAddress(
+						InetAddress.getLocalHost(), Support_PortManager
+								.getNextPortForUDP());
+				theSocket1 = new MulticastSocket(null);
+				theSocket2 = new MulticastSocket(null);
+				theSocket1.setReuseAddress(false);
+				theSocket2.setReuseAddress(false);
+				theSocket1.bind(theAddress);
+				theSocket2.bind(theAddress);
+				fail(
+						"No exception when trying to connect to do duplicate socket bind with re-useaddr set to false");
+			} catch (BindException e) {
 
-            }
-            if (theSocket1 != null)
-                theSocket1.close();
-            if (theSocket2 != null)
-                theSocket2.close();
+			}
+			if (theSocket1 != null)
+				theSocket1.close();
+			if (theSocket2 != null)
+				theSocket2.close();
 
-            // test case were we set it to true
-            try {
-                InetSocketAddress theAddress = new InetSocketAddress(
-                        InetAddress.getLocalHost(), Support_PortManager
-                                .getNextPortForUDP());
-                theSocket1 = new MulticastSocket(null);
-                theSocket2 = new MulticastSocket(null);
-                theSocket1.setReuseAddress(true);
-                theSocket2.setReuseAddress(true);
-                theSocket1.bind(theAddress);
-                theSocket2.bind(theAddress);
-            } catch (Exception e) {
-                fail(
-                        "unexpected exception when trying to connect " +
-                        "to do duplicate socket bind with re-useaddr set " +
-                        "to true");
-            }
-            if (theSocket1 != null)
-                theSocket1.close();
-            if (theSocket2 != null)
-                theSocket2.close();
+			// test case were we set it to true
+                        InetSocketAddress theAddress = new InetSocketAddress(
+                                        InetAddress.getLocalHost(), Support_PortManager
+                                                        .getNextPortForUDP());
+                        theSocket1 = new MulticastSocket(null);
+                        theSocket2 = new MulticastSocket(null);
+                        theSocket1.setReuseAddress(true);
+                        theSocket2.setReuseAddress(true);
+                        theSocket1.bind(theAddress);
+                        theSocket2.bind(theAddress);
 
-            // test the default case which we expect to be the same on all
-            // platforms
-            try {
-                InetSocketAddress theAddress = new InetSocketAddress(
-                        InetAddress.getLocalHost(), Support_PortManager
-                                .getNextPortForUDP());
-                theSocket1 = new MulticastSocket(null);
-                theSocket2 = new MulticastSocket(null);
-                theSocket1.bind(theAddress);
-                theSocket2.bind(theAddress);
-            } catch (BindException e) {
-                fail(
-                        "unexpected exception when trying to connect to do " +
-                        "duplicate socket bind with re-useaddr left as default");
-            }
-            if (theSocket1 != null)
-                theSocket1.close();
-            if (theSocket2 != null)
-                theSocket2.close();
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_REUSEADDR);
-        } catch (Exception e) {
-            handleException(e, SO_REUSEADDR);
-        }
-    }
+                        if (theSocket1 != null)
+				theSocket1.close();
+			if (theSocket2 != null)
+				theSocket2.close();
 
-    /**
-     * Sets up the fixture, for example, open a network connection. This method
-     * is called before a test is executed.
-     */
-    protected void setUp() {
+			// test the default case which we expect to be
+			// the same on all platforms
+                        theAddress =
+                            new InetSocketAddress(
+                                    InetAddress.getLocalHost(),
+                                    Support_PortManager.getNextPortForUDP());
+                        theSocket1 = new MulticastSocket(null);
+                        theSocket2 = new MulticastSocket(null);
+                        theSocket1.bind(theAddress);
+                        theSocket2.bind(theAddress);
+			if (theSocket1 != null)
+				theSocket1.close();
+			if (theSocket2 != null)
+				theSocket2.close();
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_REUSEADDR);
+		} catch (Exception e) {
+			handleException(e, SO_REUSEADDR);
+		}
+	}
 
-        Enumeration theInterfaces = null;
-        try {
-            theInterfaces = NetworkInterface.getNetworkInterfaces();
-        } catch (Exception e) {
-        }
+	/**
+	 * Sets up the fixture, for example, open a network connection. This method
+	 * is called before a test is executed.
+	 */
+	protected void setUp() {
 
-        // only consider interfaces that have addresses associated with them.
-        // Otherwise tests don't work so well
-        if (theInterfaces != null) {
+		Enumeration theInterfaces = null;
+		try {
+			theInterfaces = NetworkInterface.getNetworkInterfaces();
+		} catch (Exception e) {
+		}
 
-            atLeastOneInterface = false;
-            while (theInterfaces.hasMoreElements()
+		// only consider interfaces that have addresses associated with them.
+		// Otherwise tests don't work so well
+		if (theInterfaces != null) {
+
+			atLeastOneInterface = false;
+			while (theInterfaces.hasMoreElements()
                     && (atLeastOneInterface == false)) {
                 networkInterface1 = (NetworkInterface) theInterfaces
                         .nextElement();
-                if ((networkInterface1.getInetAddresses() != null)
-                        && networkInterface1.getInetAddresses()
-                                .hasMoreElements() &&
+                if (networkInterface1.getInetAddresses().hasMoreElements() &&
                         // we only want real interfaces
                         (Support_NetworkInterface
                                 .useInterface(networkInterface1) == true)) {
@@ -1539,15 +1104,14 @@
                 }
             }
 
-            atLeastTwoInterfaces = false;
-            if (theInterfaces.hasMoreElements()) {
+			atLeastTwoInterfaces = false;
+			if (theInterfaces.hasMoreElements()) {
                 while (theInterfaces.hasMoreElements()
                         && (atLeastTwoInterfaces == false)) {
                     networkInterface2 = (NetworkInterface) theInterfaces
                             .nextElement();
-                    if ((networkInterface2.getInetAddresses() != null)
-                            && networkInterface2.getInetAddresses()
-                                    .hasMoreElements() &&
+                    if (networkInterface2.getInetAddresses().hasMoreElements()
+                            &&
                             // we only want real interfaces
                             (Support_NetworkInterface
                                     .useInterface(networkInterface2) == true)) {
@@ -1556,44 +1120,44 @@
                 }
             }
 
-            Enumeration addresses;
+			Enumeration addresses;
 
-            // first the first interface that supports IPV6 if one exists
-            try {
-                theInterfaces = NetworkInterface.getNetworkInterfaces();
-            } catch (Exception e) {
-            }
-            boolean found = false;
-            while (theInterfaces.hasMoreElements() && !found) {
-                NetworkInterface nextInterface = (NetworkInterface) theInterfaces
-                        .nextElement();
-                addresses = nextInterface.getInetAddresses();
-                if (addresses != null) {
-                    while (addresses.hasMoreElements()) {
-                        InetAddress nextAddress = (InetAddress) addresses
-                                .nextElement();
-                        if (nextAddress instanceof Inet6Address) {
-                            IPV6networkInterface1 = nextInterface;
-                            found = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-    }
+			// first the first interface that supports IPV6 if one exists
+			try {
+				theInterfaces = NetworkInterface.getNetworkInterfaces();
+			} catch (Exception e) {
+			}
+			boolean found = false;
+			while (theInterfaces.hasMoreElements() && !found) {
+				NetworkInterface nextInterface = (NetworkInterface) theInterfaces
+						.nextElement();
+				addresses = nextInterface.getInetAddresses();
+				if (addresses.hasMoreElements()) {
+					while (addresses.hasMoreElements()) {
+						InetAddress nextAddress = (InetAddress) addresses
+								.nextElement();
+						if (nextAddress instanceof Inet6Address) {
+							IPV6networkInterface1 = nextInterface;
+							found = true;
+							break;
+						}
+					}
+				}
+			}
+		}
+	}
 
-    /**
-     * Tears down the fixture, for example, close a network connection. This
-     * method is called after a test is executed.
-     */
-    protected void tearDown() throws InterruptedException {
+	/**
+	 * Tears down the fixture, for example, close a network connection. This
+	 * method is called after a test is executed.
+	 */
+	protected void tearDown() {
 
-        if (t != null)
-            t.interrupt();
-        if (mss != null)
-            mss.close();
-        if (server != null)
-            server.stopServer();
-    }
+		if (t != null)
+			t.interrupt();
+		if (mss != null)
+			mss.close();
+		if (server != null)
+			server.stopServer();
+	}
 }
diff --git a/luni/src/test/java/tests/api/java/net/ProxySelectorTest.java b/luni/src/test/java/tests/api/java/net/ProxySelectorTest.java
index f208954..ee8195b 100644
--- a/luni/src/test/java/tests/api/java/net/ProxySelectorTest.java
+++ b/luni/src/test/java/tests/api/java/net/ProxySelectorTest.java
@@ -34,6 +34,7 @@
 import java.util.Properties;
 
 import junit.framework.TestCase;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(ProxySelector.class) 
 public class ProxySelectorTest extends TestCase {
@@ -77,11 +78,6 @@
         }
     }
 
-    /*
-     * Original system properties must be restored after running each test case.
-     */
-    private Properties orignalSystemProperties;
-
     /**
      * @tests java.net.ProxySelector#getDefault()
      */
@@ -722,16 +718,14 @@
      */
     protected void setUp() throws Exception {
         super.setUp();
-        // save original system properties
-        orignalSystemProperties = (Properties) System.getProperties().clone();
+        TestEnvironment.reset();
     }
 
     /*
      * @see junit.framework.TestCase#tearDown()
      */
     protected void tearDown() throws Exception {
-        // restore orignal system properties
-        System.setProperties(orignalSystemProperties);
+        TestEnvironment.reset();
         super.tearDown();
     }
 }
diff --git a/luni/src/test/java/tests/api/java/net/ServerSocketTest.java b/luni/src/test/java/tests/api/java/net/ServerSocketTest.java
index ecdfd01..a750536 100644
--- a/luni/src/test/java/tests/api/java/net/ServerSocketTest.java
+++ b/luni/src/test/java/tests/api/java/net/ServerSocketTest.java
@@ -45,6 +45,7 @@
 
 import tests.support.Support_Configuration;
 import tests.support.Support_PortManager;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(value = ServerSocket.class) 
 public class ServerSocketTest extends SocketTestCase {
@@ -1289,7 +1290,7 @@
      * method is called after a test is executed.
      */
     protected void tearDown() {
-
+        TestEnvironment.reset();
         try {
             if (s != null)
                 s.close();
diff --git a/luni/src/test/java/tests/api/java/net/SocketTest.java b/luni/src/test/java/tests/api/java/net/SocketTest.java
index 7cc31a0..b8184a5 100644
--- a/luni/src/test/java/tests/api/java/net/SocketTest.java
+++ b/luni/src/test/java/tests/api/java/net/SocketTest.java
@@ -501,72 +501,14 @@
         args = {}
     )
     public void test_getInputStream() throws IOException {
-        System.setSecurityManager(null);
-        
-        // Test for method java.io.InputStream java.net.Socket.getInputStream()
-        int sport = startServer("SServer getInputStream");
-        int portNumber = Support_PortManager.getNextPort();
-        s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber);
-        (t = new SServer()).start();
-        java.io.InputStream is = s.getInputStream();
+        // Simple fetch test
+        ServerSocket server = new ServerSocket(0);
+        Socket client = new Socket(InetAddress.getLocalHost(), server.getLocalPort());
+        InputStream is = client.getInputStream();
         assertNotNull("Failed to get stream", is);
-        s.setSoTimeout(6000);
-        is.read();
-        s.close();
-        assertEquals("Invalid after close", -1, is.read());
-
-        interrupted = false;
-        int portNum = Support_PortManager.getNextPort();
-        final ServerSocket ss = new ServerSocket(portNum);
-        Socket sock = new Socket(InetAddress.getLocalHost(), portNum);
-        Runnable runnable = new Runnable() {
-            public void run() {
-                try {
-                    Socket as = ss.accept();
-                    ss.close();
-                    as.setSoTimeout(12000);
-                    InputStream in = as.getInputStream();
-                    in.read();
-                    in.close();
-                } catch (InterruptedIOException e) {
-                    interrupted = true;
-                } catch (IOException e) {
-                }
-            }
-        };
-        Thread thread = new Thread(runnable, "Socket.getInputStream");
-        thread.start();
-        try {
-            do {
-                Thread.sleep(200);
-            } while (!thread.isAlive());
-        } catch (InterruptedException e) {
-        }
-        try {
-            Thread.sleep(200);
-        } catch (InterruptedException e) {
-        }
-        sock.close();
-        try {
-            sock.getInputStream();
-            fail("IOException was not thrown.");
-        } catch(IOException ioe) {
-            //expected
-        }
-        int c = 0;
-        do {
-            try {
-                Thread.sleep(200);
-            } catch (InterruptedException e) {
-            }
-            if (interrupted) {
-                fail("read interrupted");
-            }
-            if (++c > 4) {
-                fail("read call did not exit");
-            }
-        } while (thread.isAlive());
-
+        is.close();
+        client.close();
+        server.close();
     }
 
     /**
diff --git a/luni/src/test/java/tests/api/java/net/UnixSocketTest.java b/luni/src/test/java/tests/api/java/net/UnixSocketTest.java
new file mode 100644
index 0000000..4688e34
--- /dev/null
+++ b/luni/src/test/java/tests/api/java/net/UnixSocketTest.java
@@ -0,0 +1,135 @@
+/*
+ *  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.
+ */
+
+// BEGIN android-changed
+package tests.api.java.net;
+//package org.apache.harmony.luni.tests.java.net;
+// END android-changed
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+
+import junit.framework.TestCase;
+
+public class UnixSocketTest extends TestCase {
+
+    /**
+     * @tests java.net.Socket#getInputStream()
+     */
+    public void test_getInputStream() throws IOException {
+        // Simple read/write test over the IO streams
+        final ServerSocket pingServer = new ServerSocket(0);
+        Runnable runnable = new Runnable() {
+            public void run() {
+                try {
+                    Socket worker = pingServer.accept();
+                    pingServer.close();
+                    InputStream in = worker.getInputStream();
+                    in.read();
+                    OutputStream out = worker.getOutputStream();
+                    out.write(new byte[42]);
+                    worker.close();
+                } catch (IOException e) {
+                    fail(e.getMessage());
+                }
+            }
+        };
+        Thread thread = new Thread(runnable, "UnixSocket.getInputStream");
+        thread.start();
+
+        Socket pingClient = new Socket(InetAddress.getLocalHost(), pingServer
+                .getLocalPort());
+
+        // Busy wait until the client is connected.
+        int c = 0;
+        while (!pingClient.isConnected()) {
+            try {
+                Thread.sleep(200);
+            } catch (InterruptedException e) {
+                // ignore
+            }
+            if (++c > 4) {
+                fail("thread is not alive");
+            }
+        }
+
+        // Write some data to the server to provoke it
+        OutputStream out = pingClient.getOutputStream();
+        out.write(new byte[256]);
+
+        InputStream in = pingClient.getInputStream();
+        in.read(new byte[42]);
+        try {
+            in.read();
+            fail("Should throw SocketException");
+        } catch (SocketException e) {
+            // expected
+        }
+        in.close();
+
+        try {
+            in.read();
+            fail("Should throw SocketException");
+        } catch (SocketException e) {
+            // expected
+        }
+        try {
+            in.read(new byte[5]);
+            fail("Should throw SocketException");
+        } catch (SocketException e) {
+            // expected
+        }
+
+        pingClient.close();
+        pingServer.close();
+    }
+
+    public void test_connectLjava_net_SocketAddressI() throws Exception {
+        // Now validate that we get a interrupted exception if we try to connect
+        // to an address on which nobody is accepting connections and the
+        // timeout expired
+        Socket theSocket = new Socket();
+        try {
+            theSocket.connect(new InetSocketAddress(InetAddress.getLocalHost(),
+                    1), 200);
+            fail("No interrupted exception when connecting to address nobody listening on with short timeout 200");
+        } catch (ConnectException e) {
+            // Expected
+        }
+        theSocket.close();
+    }
+
+    public void test_getOutputStream() throws Exception {
+        // Regression test for HARMONY-2934
+        Socket socket = new Socket("127.0.0.1", 0, false);
+        OutputStream o = socket.getOutputStream();
+        try {
+            o.write(1);
+        } catch (SocketException e) {
+            // expected
+        } finally {
+            socket.close();
+        }
+    }
+}
diff --git a/luni/src/test/java/tests/api/java/util/AbstractMapTest.java b/luni/src/test/java/tests/api/java/util/AbstractMapTest.java
index c6a612c..7feb001 100644
--- a/luni/src/test/java/tests/api/java/util/AbstractMapTest.java
+++ b/luni/src/test/java/tests/api/java/util/AbstractMapTest.java
@@ -211,7 +211,7 @@
                 try {
                     return super.clone();
                 } catch (CloneNotSupportedException e) {
-                    return null;
+                    throw new AssertionError(e); // android-changed
                 }
             }
         }
diff --git a/luni/src/test/java/tests/api/java/util/ArrayListTest.java b/luni/src/test/java/tests/api/java/util/ArrayListTest.java
index 8aa77cc..0356731 100644
--- a/luni/src/test/java/tests/api/java/util/ArrayListTest.java
+++ b/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/luni/src/test/java/tests/api/java/util/CalendarTest.java b/luni/src/test/java/tests/api/java/util/CalendarTest.java
index af43096..285fa56 100644
--- a/luni/src/test/java/tests/api/java/util/CalendarTest.java
+++ b/luni/src/test/java/tests/api/java/util/CalendarTest.java
@@ -900,7 +900,6 @@
             args = {}
         )
     })
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getFirstDayOfWeek() {
         Calendar cal = Calendar.getInstance();
 
@@ -917,7 +916,6 @@
         method = "getInstance",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getInstanceLjava_util_Locale() {
         Calendar cal1 = Calendar.getInstance(Locale.FRANCE);
         Locale.setDefault(Locale.FRANCE);
@@ -946,7 +944,6 @@
         method = "getInstance",
         args = {java.util.TimeZone.class, java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getInstanceLjava_util_TimeZoneLjava_util_Locale() {
         Calendar cal1 = Calendar.getInstance(TimeZone.getTimeZone("GMT-6"), Locale.FRANCE);
         Locale.setDefault(Locale.FRANCE);
@@ -965,7 +962,6 @@
         method = "getMinimalDaysInFirstWeek",
         args = {}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getMinimalDaysInFirstWeek() {
         Calendar cal = Calendar.getInstance();
         assertTrue(cal.getMinimalDaysInFirstWeek()==1);
@@ -1011,7 +1007,6 @@
         method = "hashCode",
         args = {}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_hashCode() {
         Calendar cal1 = Calendar.getInstance();
         Locale.setDefault(Locale.FRANCE);
diff --git a/luni/src/test/java/tests/api/java/util/CollectionsTest.java b/luni/src/test/java/tests/api/java/util/CollectionsTest.java
index 2b1b47e..7fc60d8 100644
--- a/luni/src/test/java/tests/api/java/util/CollectionsTest.java
+++ b/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/luni/src/test/java/tests/api/java/util/FormatterTest.java b/luni/src/test/java/tests/api/java/util/FormatterTest.java
index b2030c9..94113e1 100644
--- a/luni/src/test/java/tests/api/java/util/FormatterTest.java
+++ b/luni/src/test/java/tests/api/java/util/FormatterTest.java
@@ -59,6 +59,7 @@
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(Formatter.class) 
 public class FormatterTest extends TestCase {
@@ -800,6 +801,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()
      */
@@ -1238,8 +1269,6 @@
         } catch (IllegalFormatPrecisionException e) {
             // expected
         }
-        
-        System.setProperty("line.separator", oldSeparator);
     }
 
     /**
@@ -1765,7 +1794,6 @@
         method = "format",
         args = {java.lang.String.class, java.lang.Object[].class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_formatLjava_lang_String$Ljava_lang_Object_ByteShortIntegerLongConversionD() {
         final Object[][] triple = { 
                 { 0,                "%d",                  "0" }, 
@@ -2030,7 +2058,6 @@
         args = {java.lang.String.class, java.lang.Object[].class}
     )
     @AndroidOnly("ICU data is different from RI data")
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_formatLjava_lang_String$Ljava_lang_Object_DateTimeConversion() {
         /*
          * Implementation note: For a millisecond date based on Long.MAX_VALUE,
@@ -2808,7 +2835,6 @@
         method = "format",
         args = {java.lang.String.class, java.lang.Object[].class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_formatLjava_lang_String$LBigInteger() {
         final Object[][] tripleD = {
                 {new BigInteger("123456789012345678901234567890"),          "%d",       "123456789012345678901234567890"}, //$NON-NLS-2$
@@ -2911,7 +2937,6 @@
         method = "format",
         args = {java.lang.String.class, java.lang.Object[].class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_formatLjava_lang_String$Ljava_lang_Object_BigIntegerPaddingConversion() {
         Formatter f = null;
 
@@ -4028,7 +4053,6 @@
         method = "format",
         args = {java.lang.String.class, java.lang.Object[].class}
     )
-    @KnownFailure("Formatting of BigDecimal lost precission sometimes")
     public void test_formatLjava_lang_String$Ljava_lang_Object_BigDecimalConversionE() {
         Formatter f = null;
         final Object[][] tripleE = {
@@ -4617,7 +4641,6 @@
         method = "format",
         args = {java.util.Locale.class, java.lang.String.class, java.lang.Object[].class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_formatLjava_util_LocaleLjava_lang_StringLjava_lang_Object() {
         Double val = new Double(3.14);
         Calendar cal = Calendar.getInstance();
@@ -4695,6 +4718,7 @@
      * Setup resource files for testing
      */
     protected void setUp() throws IOException {
+        TestEnvironment.reset();
         notExist = File.createTempFile("notexist", null);
         notExist.delete();
 
@@ -4718,6 +4742,7 @@
      * Delete the resource files if they exist
      */
     protected void tearDown() {
+        TestEnvironment.reset();
         if (notExist.exists()) {
             notExist.delete();
         }
diff --git a/luni/src/test/java/tests/api/java/util/GregorianCalendarTest.java b/luni/src/test/java/tests/api/java/util/GregorianCalendarTest.java
index c5ccde1..6d2ef74 100644
--- a/luni/src/test/java/tests/api/java/util/GregorianCalendarTest.java
+++ b/luni/src/test/java/tests/api/java/util/GregorianCalendarTest.java
@@ -148,7 +148,6 @@
         method = "GregorianCalendar",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_ConstructorLjava_util_Locale() {
         // Test for method java.util.GregorianCalendar(java.util.Locale)
         Date date = new Date();
diff --git a/luni/src/test/java/tests/api/java/util/LocaleTest.java b/luni/src/test/java/tests/api/java/util/LocaleTest.java
index d45c5be..01203a3 100644
--- a/luni/src/test/java/tests/api/java/util/LocaleTest.java
+++ b/luni/src/test/java/tests/api/java/util/LocaleTest.java
@@ -258,7 +258,6 @@
         method = "getDisplayCountry",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getDisplayCountryLjava_util_Locale() {
         // Test for method java.lang.String
         // java.util.Locale.getDisplayCountry(java.util.Locale)
@@ -296,7 +295,6 @@
         method = "getDisplayLanguage",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getDisplayLanguageLjava_util_Locale() {
         // Test for method java.lang.String
         // java.util.Locale.getDisplayLanguage(java.util.Locale)
@@ -329,7 +327,6 @@
         method = "getDisplayName",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getDisplayNameLjava_util_Locale() {
         // Test for method java.lang.String
         // java.util.Locale.getDisplayName(java.util.Locale)
@@ -646,5 +643,3 @@
         Locale.setDefault(defaultLocale);
     }
 }
-
-
diff --git a/luni/src/test/java/tests/api/java/util/ScannerTest.java b/luni/src/test/java/tests/api/java/util/ScannerTest.java
index 84f41d6..ce35005 100644
--- a/luni/src/test/java/tests/api/java/util/ScannerTest.java
+++ b/luni/src/test/java/tests/api/java/util/ScannerTest.java
@@ -2146,7 +2146,6 @@
         method = "nextShort",
         args = {int.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_nextShortI() throws IOException {
         s = new Scanner("123 456");
         assertEquals(123, s.nextShort(10));
@@ -2304,7 +2303,6 @@
         method = "nextShort",
         args = {}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_nextShort() throws IOException {
         s = new Scanner("123 456");
         assertEquals(123, s.nextShort());
@@ -2465,7 +2463,6 @@
         method = "nextLong",
         args = {int.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_nextLongI() throws IOException {
         s = new Scanner("123 456");
         assertEquals(123, s.nextLong(10));
@@ -2623,7 +2620,6 @@
         method = "nextLong",
         args = {}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_nextLong() throws IOException {
         s = new Scanner("123 456");
         assertEquals(123, s.nextLong());
@@ -4287,7 +4283,6 @@
         method = "hasNextShort",
         args = {int.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_hasNextShortI() throws IOException {
         s = new Scanner("123 456");
         assertTrue(s.hasNextShort(10));
@@ -4464,7 +4459,6 @@
         method = "hasNextShort",
         args = {}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_hasNextShort() throws IOException {
         s = new Scanner("123 456");
         assertTrue(s.hasNextShort());
@@ -4692,7 +4686,6 @@
         method = "hasNextLong",
         args = {int.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_hasNextLongI() throws IOException {
         s = new Scanner("123 456");
         assertTrue(s.hasNextLong(10));
@@ -4910,7 +4903,6 @@
         method = "hasNextLong",
         args = {}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_hasNextLong() throws IOException {
         s = new Scanner("123 456");
         assertTrue(s.hasNextLong());
@@ -5097,7 +5089,6 @@
         method = "hasNextDouble",
         args = {}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_hasNextDouble() throws IOException {
         s = new Scanner("123 45\u0666. 123.4 .123 ");
         s.useLocale(Locale.ENGLISH);
@@ -5211,7 +5202,6 @@
         method = "hasNextBigDecimal",
         args = {}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_hasNextBigDecimal() throws IOException {
         s = new Scanner("123 45\u0666. 123.4 .123 ");
         s.useLocale(Locale.ENGLISH);
@@ -6344,7 +6334,6 @@
         method = "nextDouble",
         args = {}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_nextDouble() throws IOException {
         s = new Scanner("123 45\u0666. 123.4 .123 ");
         s.useLocale(Locale.ENGLISH);
@@ -6437,7 +6426,6 @@
         method = "nextBigDecimal",
         args = {}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_nextBigDecimal() throws IOException {
         s = new Scanner("123 45\u0666. 123.4 .123 ");
         s.useLocale(Locale.ENGLISH);
diff --git a/luni/src/test/java/tests/api/java/util/TimeZoneTest.java b/luni/src/test/java/tests/api/java/util/TimeZoneTest.java
index efdb8a1..86f5b9e 100644
--- a/luni/src/test/java/tests/api/java/util/TimeZoneTest.java
+++ b/luni/src/test/java/tests/api/java/util/TimeZoneTest.java
@@ -306,7 +306,6 @@
         method = "getDisplayName",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getDisplayNameLjava_util_Locale() {
         TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
         assertEquals("Pacific Standard Time", tz.getDisplayName(new Locale("US")));
@@ -333,7 +332,6 @@
         args = {boolean.class, int.class, java.util.Locale.class}
     )
     @AndroidOnly("fail on RI. See comment below")
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getDisplayNameZILjava_util_Locale() {
         TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
         assertEquals("PST",                   tz.getDisplayName(false, 0, Locale.US));
@@ -383,6 +381,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/luni/src/test/resources/libTestLibrary.so b/luni/src/test/resources/libTestLibrary.so
deleted file mode 100755
index 81acfd5..0000000
--- a/luni/src/test/resources/libTestLibrary.so
+++ /dev/null
Binary files differ
diff --git a/math/src/main/java/java/math/BigInt.java b/math/src/main/java/java/math/BigInt.java
index cb7990a..3ba1da2 100644
--- a/math/src/main/java/java/math/BigInt.java
+++ b/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);
     }
@@ -240,9 +234,9 @@
         else if (val < 0) NativeBN.BN_set_negative(this.bignum, 1);
     }
 
-
-    public boolean twosCompFitsIntoBytes(int byteCnt) {
-        return NativeBN.twosCompFitsIntoBytes(this.bignum, byteCnt);
+    public boolean twosCompFitsIntoBytes(int desiredByteCount) {
+        int actualByteCount = (NativeBN.bitLength(this.bignum) + 7) / 8;
+        return actualByteCount <= desiredByteCount;
     }
 
     public int bitLength() {
diff --git a/math/src/test/java/tests/api/java/math/BigIntegerTest.java b/math/src/test/java/tests/api/java/math/BigIntegerTest.java
index d04f742..b84aa17 100644
--- a/math/src/test/java/tests/api/java/math/BigIntegerTest.java
+++ b/math/src/test/java/tests/api/java/math/BigIntegerTest.java
@@ -1299,7 +1299,7 @@
             try {
                 return super.clone();
             } catch (CloneNotSupportedException e) {
-                return null;
+                throw new AssertionError(e); // android-changed
             }
         }
     }
diff --git a/nio/src/main/java/java/nio/BaseByteBuffer.java b/nio/src/main/java/java/nio/BaseByteBuffer.java
index 009bcb7..a4acc08 100644
--- a/nio/src/main/java/java/nio/BaseByteBuffer.java
+++ b/nio/src/main/java/java/nio/BaseByteBuffer.java
@@ -16,11 +16,9 @@
 
 package java.nio;
 
-
 /**
  * Serves as the root of other byte buffer impl classes, implements common
  * methods that can be shared by child classes.
- * 
  */
 abstract class BaseByteBuffer extends ByteBuffer {
 
@@ -28,42 +26,52 @@
         super(capacity);
     }
 
+    @Override
     public final CharBuffer asCharBuffer() {
         return CharToByteBufferAdapter.wrap(this);
     }
 
+    @Override
     public final DoubleBuffer asDoubleBuffer() {
         return DoubleToByteBufferAdapter.wrap(this);
     }
 
+    @Override
     public final FloatBuffer asFloatBuffer() {
         return FloatToByteBufferAdapter.wrap(this);
     }
 
+    @Override
     public final IntBuffer asIntBuffer() {
         return IntToByteBufferAdapter.wrap(this);
     }
 
+    @Override
     public final LongBuffer asLongBuffer() {
         return LongToByteBufferAdapter.wrap(this);
     }
 
+    @Override
     public final ShortBuffer asShortBuffer() {
         return ShortToByteBufferAdapter.wrap(this);
     }
 
+    @Override
     public final char getChar() {
         return (char) getShort();
     }
 
+    @Override
     public final char getChar(int index) {
         return (char) getShort(index);
     }
 
+    @Override
     public final ByteBuffer putChar(char value) {
         return putShort((short) value);
     }
 
+    @Override
     public final ByteBuffer putChar(int index, char value) {
         return putShort(index, (short) value);
     }
diff --git a/nio/src/main/java/java/nio/Buffer.java b/nio/src/main/java/java/nio/Buffer.java
index 19d8969..b4bdc1c 100644
--- a/nio/src/main/java/java/nio/Buffer.java
+++ b/nio/src/main/java/java/nio/Buffer.java
@@ -16,7 +16,6 @@
 
 package java.nio;
 
-
 /**
  * A buffer is a list of elements of a specific primitive type.
  * <p>
@@ -40,14 +39,10 @@
  * take advantage of native memory APIs and it may not stay in the Java heap,
  * thus it is not affected by garbage collection.</li>
  * </ul>
- * </p>
  * <p>
  * Buffers are not thread-safe. If concurrent access to a buffer instance is
  * required, then the callers are responsible to take care of the
  * synchronization issues.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class Buffer {
 
@@ -125,9 +120,9 @@
 
     /**
      * Construct a buffer with the specified capacity.
-     *
+     * 
      * @param capacity
-     *            the capacity of this buffer.
+     *            The capacity of this buffer
      */
     Buffer(int capacity) {
         super();
@@ -141,7 +136,6 @@
      * Returns the capacity of this buffer.
      * 
      * @return the number of elements that are contained in this buffer.
-     * @since Android 1.0
      */
     public final int capacity() {
         return capacity;
@@ -154,10 +148,8 @@
      * changes take place: the current position is reset back to the start of
      * the buffer, the value of the buffer limit is made equal to the capacity
      * and mark is cleared.
-     * </p>
-     * 
+     *
      * @return this buffer.
-     * @since Android 1.0
      */
     public final Buffer clear() {
         position = 0;
@@ -171,13 +163,10 @@
      * <p>
      * The limit is set to the current position, then the position is set to
      * zero, and the mark is cleared.
-     * </p>
      * <p>
      * The content of this buffer is not changed.
-     * </p>
-     * 
+     *
      * @return this buffer.
-     * @since Android 1.0
      */
     public final Buffer flip() {
         limit = position;
@@ -192,7 +181,6 @@
      * 
      * @return {@code true} if there are elements remaining in this buffer,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean hasRemaining() {
         return position < limit;
@@ -203,7 +191,6 @@
      * 
      * @return {@code true} if this buffer is read-only, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isReadOnly();
 
@@ -211,7 +198,6 @@
      * Returns the limit of this buffer.
      * 
      * @return the limit of this buffer.
-     * @since Android 1.0
      */
     public final int limit() {
         return limit;
@@ -224,15 +210,13 @@
      * <code>newLimit</code> then, on returning from this call, it will have
      * been adjusted to be equivalent to <code>newLimit</code>. If the mark
      * is set and is greater than the new limit, then it is cleared.
-     * </p>
-     * 
+     *
      * @param newLimit
      *            the new limit, must not be negative and not greater than
      *            capacity.
      * @return this buffer.
      * @exception IllegalArgumentException
      *                if <code>newLimit</code> is invalid.
-     * @since Android 1.0
      */
     public final Buffer limit(int newLimit) {
         if (newLimit < 0 || newLimit > capacity) {
@@ -254,7 +238,6 @@
      * later by calling <code>reset()</code>.
      * 
      * @return this buffer.
-     * @since Android 1.0
      */
     public final Buffer mark() {
         mark = position;
@@ -265,7 +248,6 @@
      * Returns the position of this buffer.
      * 
      * @return the value of this buffer's current position.
-     * @since Android 1.0
      */
     public final int position() {
         return position;
@@ -276,15 +258,13 @@
      * <p>
      * If the mark is set and it is greater than the new position, then it is
      * cleared.
-     * </p>
-     * 
+     *
      * @param newPosition
      *            the new position, must be not negative and not greater than
      *            limit.
      * @return this buffer.
      * @exception IllegalArgumentException
      *                if <code>newPosition</code> is invalid.
-     * @since Android 1.0
      */
     public final Buffer position(int newPosition) {
         if (newPosition < 0 || newPosition > limit) {
@@ -303,7 +283,6 @@
      * {@code limit - position}.
      * 
      * @return the number of remaining elements in this buffer.
-     * @since Android 1.0
      */
     public final int remaining() {
         return limit - position;
@@ -315,7 +294,6 @@
      * @return this buffer.
      * @exception InvalidMarkException
      *                if the mark is not set.
-     * @since Android 1.0
      */
     public final Buffer reset() {
         if (mark == UNSET_MARK) {
@@ -330,10 +308,8 @@
      * <p>
      * The position is set to zero, and the mark is cleared. The content of this
      * buffer is not changed.
-     * </p>
-     * 
+     *
      * @return this buffer.
-     * @since Android 1.0
      */
     public final Buffer rewind() {
         position = 0;
diff --git a/nio/src/main/java/java/nio/BufferFactory.java b/nio/src/main/java/java/nio/BufferFactory.java
index acb2400..94f23ed 100644
--- a/nio/src/main/java/java/nio/BufferFactory.java
+++ b/nio/src/main/java/java/nio/BufferFactory.java
@@ -17,7 +17,6 @@
 
 package java.nio;
 
-
 /**
  * Provide factory service of buffer classes.
  * <p>
@@ -25,7 +24,6 @@
  * this factory is the only entrance to access buffer functions from outside of
  * the impl package.
  * </p>
- * 
  */
 final class BufferFactory {
 
diff --git a/nio/src/main/java/java/nio/BufferOverflowException.java b/nio/src/main/java/java/nio/BufferOverflowException.java
index a9ec60d..a1f7792 100644
--- a/nio/src/main/java/java/nio/BufferOverflowException.java
+++ b/nio/src/main/java/java/nio/BufferOverflowException.java
@@ -16,12 +16,9 @@
 
 package java.nio;
 
-
 /**
  * A <code>BufferOverflowException</code> is thrown when elements are written
  * to a buffer but there is not enough remaining space in the buffer.
- * 
- * @since Android 1.0
  */
 public class BufferOverflowException extends RuntimeException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs a <code>BufferOverflowException</code>.
-     * 
-     * @since Android 1.0
      */
     public BufferOverflowException() {
         super();
diff --git a/nio/src/main/java/java/nio/BufferUnderflowException.java b/nio/src/main/java/java/nio/BufferUnderflowException.java
index f15a8db..14d413b 100644
--- a/nio/src/main/java/java/nio/BufferUnderflowException.java
+++ b/nio/src/main/java/java/nio/BufferUnderflowException.java
@@ -16,12 +16,9 @@
 
 package java.nio;
 
-
 /**
  * A <code>BufferUnderflowException</code> is thrown when elements are read
  * from a buffer but there are not enough remaining elements in the buffer.
- * 
- * @since Android 1.0
  */
 public class BufferUnderflowException extends RuntimeException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs a <code>BufferUnderflowException</code>.
-     * 
-     * @since Android 1.0
      */
     public BufferUnderflowException() {
         super();
diff --git a/nio/src/main/java/java/nio/ByteBuffer.java b/nio/src/main/java/java/nio/ByteBuffer.java
index a033298..821bbed 100644
--- a/nio/src/main/java/java/nio/ByteBuffer.java
+++ b/nio/src/main/java/java/nio/ByteBuffer.java
@@ -17,14 +17,12 @@
 
 package java.nio;
 
-
 import org.apache.harmony.luni.platform.Endianness;
 
 /**
  * A buffer for bytes.
  * <p>
  * A byte buffer can be created in either one of the following ways:
- * </p>
  * <ul>
  * <li>{@link #allocate(int) Allocate} a new byte array and create a buffer
  * based on it;</li>
@@ -33,9 +31,10 @@
  * <li>{@link #wrap(byte[]) Wrap} an existing byte array to create a new
  * buffer.</li>
  * </ul>
- * @since Android 1.0
+ *
  */
-public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer> {
+public abstract class ByteBuffer extends Buffer implements
+        Comparable<ByteBuffer> {
 
     /**
      * Creates a byte buffer based on a newly allocated byte array.
@@ -45,7 +44,6 @@
      * @return the created byte buffer.
      * @throws IllegalArgumentException
      *             if {@code capacity < 0}.
-     * @since Android 1.0
      */
     public static ByteBuffer allocate(int capacity) {
         if (capacity < 0) {
@@ -62,7 +60,6 @@
      * @return the created byte buffer.
      * @throws IllegalArgumentException
      *             if {@code capacity < 0}.
-     * @since Android 1.0
      */
     public static ByteBuffer allocateDirect(int capacity) {
         if (capacity < 0) {
@@ -76,12 +73,10 @@
      * <p>
      * Calling this method has the same effect as
      * {@code wrap(array, 0, array.length)}.
-     * </p>
-     * 
+     *
      * @param array
      *            the byte array which the new buffer will be based on
      * @return the created byte buffer.
-     * @since Android 1.0
      */
     public static ByteBuffer wrap(byte[] array) {
         return BufferFactory.newByteBuffer(array);
@@ -92,8 +87,7 @@
      * <p>
      * The new buffer's position will be {@code start}, limit will be
      * {@code start + len}, capacity will be the length of the array.
-     * </p>
-     * 
+     *
      * @param array
      *            the byte array which the new buffer will be based on.
      * @param start
@@ -105,7 +99,6 @@
      * @return the created byte buffer.
      * @exception IndexOutOfBoundsException
      *                if either {@code start} or {@code len} is invalid.
-     * @since Android 1.0
      */
     public static ByteBuffer wrap(byte[] array, int start, int len) {
         int length = array.length;
@@ -130,7 +123,6 @@
      * 
      * @param capacity
      *            the capacity of the buffer.
-     * @since Android 1.0
      */
     ByteBuffer(int capacity) {
         super(capacity);
@@ -147,7 +139,6 @@
      *                if this buffer is based on a read-only array.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final byte[] array() {
         return protectedArray();
@@ -159,21 +150,19 @@
      * <p>
      * The offset is the index of the array which corresponds to the zero
      * position of the buffer.
-     * </p>
-     * 
+     *
      * @return the offset of the byte array which this buffer is based on.
      * @exception ReadOnlyBufferException
      *                if this buffer is based on a read-only array.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final int arrayOffset() {
         return protectedArrayOffset();
     }
 
     // BEGIN android-added
-    @Override 
+    @Override
     Object _array() {
         if (hasArray()) {
             return array();
@@ -181,7 +170,7 @@
         return null;
     }
 
-    @Override 
+    @Override
     int _arrayOffset() {
         if (hasArray()) {
             return arrayOffset();
@@ -198,15 +187,12 @@
      * of remaining bytes divided by two, and its mark is not set. The new
      * buffer's read-only property and byte order are the same as this buffer's.
      * The new buffer is direct if this byte buffer is direct.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a char buffer which is based on the content of this byte buffer.
-     * @since Android 1.0
      */
     public abstract CharBuffer asCharBuffer();
 
@@ -218,16 +204,13 @@
      * of remaining bytes divided by eight, and its mark is not set. The new
      * buffer's read-only property and byte order are the same as this buffer's.
      * The new buffer is direct if this byte buffer is direct.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a double buffer which is based on the content of this byte
      *         buffer.
-     * @since Android 1.0
      */
     public abstract DoubleBuffer asDoubleBuffer();
 
@@ -239,15 +222,12 @@
      * of remaining bytes divided by four, and its mark is not set. The new
      * buffer's read-only property and byte order are the same as this buffer's.
      * The new buffer is direct if this byte buffer is direct.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a float buffer which is based on the content of this byte buffer.
-     * @since Android 1.0
      */
     public abstract FloatBuffer asFloatBuffer();
 
@@ -259,15 +239,12 @@
      * of remaining bytes divided by four, and its mark is not set. The new
      * buffer's read-only property and byte order are the same as this buffer's.
      * The new buffer is direct if this byte buffer is direct.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a int buffer which is based on the content of this byte buffer.
-     * @since Android 1.0
      */
     public abstract IntBuffer asIntBuffer();
 
@@ -279,15 +256,12 @@
      * of remaining bytes divided by eight, and its mark is not set. The new
      * buffer's read-only property and byte order are the same as this buffer's.
      * The new buffer is direct if this byte buffer is direct.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a long buffer which is based on the content of this byte buffer.
-     * @since Android 1.0
      */
     public abstract LongBuffer asLongBuffer();
 
@@ -297,15 +271,12 @@
      * The returned buffer is guaranteed to be a new instance, even if this
      * buffer is read-only itself. The new buffer's position, limit, capacity
      * and mark are the same as this buffer.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means this
      * buffer's change of content will be visible to the new buffer. The two
      * buffer's position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a read-only version of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer asReadOnlyBuffer();
 
@@ -317,15 +288,12 @@
      * of remaining bytes divided by two, and its mark is not set. The new
      * buffer's read-only property and byte order are the same as this buffer's.
      * The new buffer is direct if this byte buffer is direct.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a short buffer which is based on the content of this byte buffer.
-     * @since Android 1.0
      */
     public abstract ShortBuffer asShortBuffer();
 
@@ -336,12 +304,10 @@
      * buffer, starting from position zero. Then the position is set to
      * {@code remaining()}; the limit is set to capacity; the mark is
      * cleared.
-     * </p>
-     * 
+     *
      * @return this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer compact();
 
@@ -356,7 +322,6 @@
      *         than {@code other}.
      * @exception ClassCastException
      *                if {@code other} is not a byte buffer.
-     * @since Android 1.0
      */
     public int compareTo(ByteBuffer otherBuffer) {
         int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
@@ -383,15 +348,12 @@
      * The duplicated buffer's position, limit, capacity and mark are the same
      * as this buffer's. The duplicated buffer's read-only property and byte
      * order are the same as this buffer's too.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a duplicated buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer duplicate();
 
@@ -401,14 +363,13 @@
      * If {@code other} is not a byte buffer then {@code false} is returned. Two
      * byte buffers are equal if and only if their remaining bytes are exactly
      * the same. Position, limit, capacity and mark are not considered.
-     * </p>
-     * 
+     *
      * @param other
      *            the object to compare with this byte buffer.
      * @return {@code true} if this byte buffer is equal to {@code other},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object other) {
         if (!(other instanceof ByteBuffer)) {
             return false;
@@ -435,7 +396,6 @@
      * @return the byte at the current position.
      * @exception BufferUnderflowException
      *                if the position is equal or greater than limit.
-     * @since Android 1.0
      */
     public abstract byte get();
 
@@ -445,14 +405,12 @@
      * <p>
      * Calling this method has the same effect as
      * {@code get(dest, 0, dest.length)}.
-     * </p>
-     * 
+     *
      * @param dest
      *            the destination byte array.
      * @return this buffer.
      * @exception BufferUnderflowException
      *                if {@code dest.length} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public ByteBuffer get(byte[] dest) {
         return get(dest, 0, dest.length);
@@ -476,11 +434,10 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception BufferUnderflowException
      *                if {@code len} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public ByteBuffer get(byte[] dest, int off, int len) {
         int length = dest.length;
-        if ((off < 0 ) || (len < 0) || ((long)off + (long)len > length)) {
+        if ((off < 0) || (len < 0) || ((long) off + (long) len > length)) {
             throw new IndexOutOfBoundsException();
         }
 
@@ -501,7 +458,6 @@
      * @return the byte at the specified index.
      * @exception IndexOutOfBoundsException
      *                if index is invalid.
-     * @since Android 1.0
      */
     public abstract byte get(int index);
 
@@ -510,12 +466,10 @@
      * <p>
      * The 2 bytes starting at the current position are composed into a char
      * according to the current byte order and returned.
-     * </p>
-     * 
+     *
      * @return the char at the current position.
      * @exception BufferUnderflowException
      *                if the position is greater than {@code limit - 2}.
-     * @since Android 1.0
      */
     public abstract char getChar();
 
@@ -525,7 +479,6 @@
      * The 2 bytes starting from the specified index are composed into a char
      * according to the current byte order and returned. The position is not
      * changed.
-     * </p>
      * 
      * @param index
      *            the index, must not be negative and equal or less than
@@ -533,7 +486,6 @@
      * @return the char at the specified index.
      * @exception IndexOutOfBoundsException
      *                if {@code index} is invalid.
-     * @since Android 1.0
      */
     public abstract char getChar(int index);
 
@@ -542,13 +494,11 @@
      * 8.
      * <p>
      * The 8 bytes starting from the current position are composed into a double
-     * according to the current byte order and returned. 
-     * </p>
-     * 
+     * according to the current byte order and returned.
+     *
      * @return the double at the current position.
      * @exception BufferUnderflowException
      *                if the position is greater than {@code limit - 8}.
-     * @since Android 1.0
      */
     public abstract double getDouble();
 
@@ -558,15 +508,13 @@
      * The 8 bytes starting at the specified index are composed into a double
      * according to the current byte order and returned. The position is not
      * changed.
-     * </p>
-     * 
+     *
      * @param index
      *            the index, must not be negative and equal or less than
      *            {@code limit - 8}.
      * @return the double at the specified index.
      * @exception IndexOutOfBoundsException
      *                if {@code index} is invalid.
-     * @since Android 1.0
      */
     public abstract double getDouble(int index);
 
@@ -576,12 +524,10 @@
      * <p>
      * The 4 bytes starting at the current position are composed into a float
      * according to the current byte order and returned.
-     * </p>
-     * 
+     *
      * @return the float at the current position.
      * @exception BufferUnderflowException
      *                if the position is greater than {@code limit - 4}.
-     * @since Android 1.0
      */
     public abstract float getFloat();
 
@@ -591,15 +537,13 @@
      * The 4 bytes starting at the specified index are composed into a float
      * according to the current byte order and returned. The position is not
      * changed.
-     * </p>
-     * 
+     *
      * @param index
      *            the index, must not be negative and equal or less than
      *            {@code limit - 4}.
      * @return the float at the specified index.
      * @exception IndexOutOfBoundsException
      *                if {@code index} is invalid.
-     * @since Android 1.0
      */
     public abstract float getFloat(int index);
 
@@ -608,12 +552,10 @@
      * <p>
      * The 4 bytes starting at the current position are composed into a int
      * according to the current byte order and returned.
-     * </p>
-     * 
+     *
      * @return the int at the current position.
      * @exception BufferUnderflowException
      *                if the position is greater than {@code limit - 4}.
-     * @since Android 1.0
      */
     public abstract int getInt();
 
@@ -623,15 +565,13 @@
      * The 4 bytes starting at the specified index are composed into a int
      * according to the current byte order and returned. The position is not
      * changed.
-     * </p>
-     * 
+     *
      * @param index
      *            the index, must not be negative and equal or less than
      *            {@code limit - 4}.
      * @return the int at the specified index.
      * @exception IndexOutOfBoundsException
      *                if {@code index} is invalid.
-     * @since Android 1.0
      */
     public abstract int getInt(int index);
 
@@ -640,12 +580,10 @@
      * <p>
      * The 8 bytes starting at the current position are composed into a long
      * according to the current byte order and returned.
-     * </p>
-     * 
+     *
      * @return the long at the current position.
      * @exception BufferUnderflowException
      *                if the position is greater than {@code limit - 8}.
-     * @since Android 1.0
      */
     public abstract long getLong();
 
@@ -655,7 +593,6 @@
      * The 8 bytes starting at the specified index are composed into a long
      * according to the current byte order and returned. The position is not
      * changed.
-     * </p>
      *
      * @param index
      *            the index, must not be negative and equal or less than
@@ -663,7 +600,6 @@
      * @return the long at the specified index.
      * @exception IndexOutOfBoundsException
      *                if {@code index} is invalid.
-     * @since Android 1.0
      */
     public abstract long getLong(int index);
 
@@ -672,12 +608,10 @@
      * <p>
      * The 2 bytes starting at the current position are composed into a short
      * according to the current byte order and returned.
-     * </p>
-     * 
+     *
      * @return the short at the current position.
      * @exception BufferUnderflowException
      *                if the position is greater than {@code limit - 2}.
-     * @since Android 1.0
      */
     public abstract short getShort();
 
@@ -687,15 +621,13 @@
      * The 2 bytes starting at the specified index are composed into a short
      * according to the current byte order and returned. The position is not
      * changed.
-     * </p>
-     * 
+     *
      * @param index
      *            the index, must not be negative and equal or less than
      *            {@code limit - 2}.
      * @return the short at the specified index.
      * @exception IndexOutOfBoundsException
      *                if {@code index} is invalid.
-     * @since Android 1.0
      */
     public abstract short getShort(int index);
 
@@ -705,7 +637,6 @@
      * 
      * @return {@code true} if this buffer is based on a byte array and provides
      *         read/write access, {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean hasArray() {
         return protectedHasArray();
@@ -714,10 +645,10 @@
     /**
      * Calculates this buffer's hash code from the remaining chars. The
      * position, limit, capacity and mark don't affect the hash code.
-     * 
+     *
      * @return the hash code calculated from the remaining bytes.
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         int myPosition = position;
         int hash = 0;
@@ -729,9 +660,8 @@
 
     /**
      * Indicates whether this buffer is direct.
-     * 
+     *
      * @return {@code true} if this buffer is direct, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isDirect();
 
@@ -741,11 +671,9 @@
      * <p>
      * The default byte order of byte buffer is always
      * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
-     * </p>
-     * 
+     *
      * @return the byte order used by this buffer when converting bytes from/to
      *         other primitive types.
-     * @since Android 1.0
      */
     public final ByteOrder order() {
         return order == Endianness.BIG_ENDIAN ? ByteOrder.BIG_ENDIAN
@@ -760,7 +688,6 @@
      *            will be {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}.
      * @return this buffer.
      * @see ByteOrder
-     * @since Android 1.0
      */
     public final ByteBuffer order(ByteOrder byteOrder) {
         return orderImpl(byteOrder);
@@ -776,7 +703,6 @@
      * Child class implements this method to realize {@code array()}.
      * 
      * @see #array()
-     * @since Android 1.0
      */
     abstract byte[] protectedArray();
 
@@ -784,7 +710,6 @@
      * Child class implements this method to realize {@code arrayOffset()}.
      * 
      * @see #arrayOffset()
-     * @since Android 1.0
      */
     abstract int protectedArrayOffset();
 
@@ -792,7 +717,6 @@
      * Child class implements this method to realize {@code hasArray()}.
      * 
      * @see #hasArray()
-     * @since Android 1.0
      */
     abstract boolean protectedHasArray();
 
@@ -807,7 +731,6 @@
      *                if position is equal or greater than limit.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer put(byte b);
 
@@ -817,8 +740,7 @@
      * <p>
      * Calling this method has the same effect as
      * {@code put(src, 0, src.length)}.
-     * </p>
-     * 
+     *
      * @param src
      *            the source byte array.
      * @return this buffer.
@@ -826,7 +748,6 @@
      *                if {@code remaining()} is less than {@code src.length}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public final ByteBuffer put(byte[] src) {
         return put(src, 0, src.length);
@@ -852,7 +773,6 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public ByteBuffer put(byte[] src, int off, int len) {
         int length = src.length;
@@ -884,7 +804,6 @@
      *                if {@code src} is this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public ByteBuffer put(ByteBuffer src) {
         if (src == this) {
@@ -912,7 +831,6 @@
      *                if {@code index} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer put(int index, byte b);
 
@@ -921,8 +839,7 @@
      * by 2.
      * <p>
      * The char is converted to bytes using the current byte order.
-     * </p>
-     * 
+     *
      * @param value
      *            the char to write.
      * @return this buffer.
@@ -930,7 +847,6 @@
      *                if position is greater than {@code limit - 2}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putChar(char value);
 
@@ -939,8 +855,7 @@
      * <p>
      * The char is converted to bytes using the current byte order. The position
      * is not changed.
-     * </p>
-     * 
+     *
      * @param index
      *            the index, must not be negative and equal or less than
      *            {@code limit - 2}.
@@ -951,7 +866,6 @@
      *                if {@code index} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putChar(int index, char value);
 
@@ -960,8 +874,7 @@
      * by 8.
      * <p>
      * The double is converted to bytes using the current byte order.
-     * </p>
-     * 
+     *
      * @param value
      *            the double to write.
      * @return this buffer.
@@ -969,7 +882,6 @@
      *                if position is greater than {@code limit - 8}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putDouble(double value);
 
@@ -978,8 +890,7 @@
      * <p>
      * The double is converted to bytes using the current byte order. The
      * position is not changed.
-     * </p>
-     * 
+     *
      * @param index
      *            the index, must not be negative and equal or less than
      *            {@code limit - 8}.
@@ -990,7 +901,6 @@
      *                if {@code index} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putDouble(int index, double value);
 
@@ -999,8 +909,7 @@
      * by 4.
      * <p>
      * The float is converted to bytes using the current byte order.
-     * </p>
-     * 
+     *
      * @param value
      *            the float to write.
      * @return this buffer.
@@ -1008,7 +917,6 @@
      *                if position is greater than {@code limit - 4}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putFloat(float value);
 
@@ -1017,8 +925,7 @@
      * <p>
      * The float is converted to bytes using the current byte order. The
      * position is not changed.
-     * </p>
-     * 
+     *
      * @param index
      *            the index, must not be negative and equal or less than
      *            {@code limit - 4}.
@@ -1029,7 +936,6 @@
      *                if {@code index} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putFloat(int index, float value);
 
@@ -1038,8 +944,7 @@
      * 4.
      * <p>
      * The int is converted to bytes using the current byte order.
-     * </p>
-     * 
+     *
      * @param value
      *            the int to write.
      * @return this buffer.
@@ -1047,7 +952,6 @@
      *                if position is greater than {@code limit - 4}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putInt(int value);
 
@@ -1056,8 +960,7 @@
      * <p>
      * The int is converted to bytes using the current byte order. The position
      * is not changed.
-     * </p>
-     * 
+     *
      * @param index
      *            the index, must not be negative and equal or less than
      *            {@code limit - 4}.
@@ -1068,7 +971,6 @@
      *                if {@code index} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putInt(int index, int value);
 
@@ -1077,8 +979,7 @@
      * by 8.
      * <p>
      * The long is converted to bytes using the current byte order.
-     * </p>
-     * 
+     *
      * @param value
      *            the long to write.
      * @return this buffer.
@@ -1086,7 +987,6 @@
      *                if position is greater than {@code limit - 8}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putLong(long value);
 
@@ -1095,8 +995,7 @@
      * <p>
      * The long is converted to bytes using the current byte order. The position
      * is not changed.
-     * </p>
-     * 
+     *
      * @param index
      *            the index, must not be negative and equal or less than
      *            {@code limit - 8}.
@@ -1107,7 +1006,6 @@
      *                if {@code index} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putLong(int index, long value);
 
@@ -1116,8 +1014,7 @@
      * by 2.
      * <p>
      * The short is converted to bytes using the current byte order.
-     * </p>
-     * 
+     *
      * @param value
      *            the short to write.
      * @return this buffer.
@@ -1125,7 +1022,6 @@
      *                if position is greater than {@code limit - 2}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putShort(short value);
 
@@ -1134,8 +1030,7 @@
      * <p>
      * The short is converted to bytes using the current byte order. The
      * position is not changed.
-     * </p>
-     * 
+     *
      * @param index
      *            the index, must not be negative and equal or less than
      *            {@code limit - 2}.
@@ -1146,7 +1041,6 @@
      *                if {@code index} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer putShort(int index, short value);
 
@@ -1158,15 +1052,12 @@
      * this buffer's current position. The new buffer's position will be 0,
      * limit will be its capacity, and its mark is cleared. The new buffer's
      * read-only property and byte order are the same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a sliced buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract ByteBuffer slice();
 
@@ -1174,10 +1065,10 @@
      * Returns a string representing the state of this byte buffer.
      * 
      * @return a string representing the state of this byte buffer.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         buf.append(getClass().getName());
         buf.append(", status: capacity="); //$NON-NLS-1$
         buf.append(capacity());
diff --git a/nio/src/main/java/java/nio/ByteOrder.java b/nio/src/main/java/java/nio/ByteOrder.java
index 870216f..c7c92ee 100644
--- a/nio/src/main/java/java/nio/ByteOrder.java
+++ b/nio/src/main/java/java/nio/ByteOrder.java
@@ -16,27 +16,20 @@
 
 package java.nio;
 
-
 import org.apache.harmony.luni.platform.Platform;
 
 /**
  * Defines byte order constants.
- * 
- * @since Android 1.0
  */
 public final class ByteOrder {
 
     /**
      * This constant represents big endian.
-     * 
-     * @since Android 1.0
      */
     public static final ByteOrder BIG_ENDIAN = new ByteOrder("BIG_ENDIAN"); //$NON-NLS-1$
 
     /**
      * This constant represents little endian.
-     * 
-     * @since Android 1.0
      */
     public static final ByteOrder LITTLE_ENDIAN = new ByteOrder("LITTLE_ENDIAN"); //$NON-NLS-1$
 
@@ -55,7 +48,6 @@
      * 
      * @return the byte order object, which is either LITTLE_ENDIAN or
      *         BIG_ENDIAN.
-     * @since Android 1.0
      */
     public static ByteOrder nativeOrder() {
         return NATIVE_ORDER;
@@ -74,8 +66,8 @@
      * @return "BIG_ENDIAN" for {@link #BIG_ENDIAN ByteOrder.BIG_ENDIAN}
      *         objects, "LITTLE_ENDIAN" for
      *         {@link #LITTLE_ENDIAN ByteOrder.LITTLE_ENDIAN} objects.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         return name;
     }
diff --git a/nio/src/main/java/java/nio/CharArrayBuffer.java b/nio/src/main/java/java/nio/CharArrayBuffer.java
index 516aada..0228eb7 100644
--- a/nio/src/main/java/java/nio/CharArrayBuffer.java
+++ b/nio/src/main/java/java/nio/CharArrayBuffer.java
@@ -49,6 +49,7 @@
         this.offset = offset;
     }
 
+    @Override
     public final char get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -56,6 +57,7 @@
         return backingArray[offset + position++];
     }
 
+    @Override
     public final char get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -63,38 +65,43 @@
         return backingArray[offset + index];
     }
 
+    @Override
     public final CharBuffer get(char[] dest, int off, int len) {
         int length = dest.length;
-        if ((off < 0 ) || (len < 0) || (long)off + (long)len > length) {
+        if ((off < 0) || (len < 0) || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
-        System.arraycopy(backingArray, offset+position, dest, off, len);
+        System.arraycopy(backingArray, offset + position, dest, off, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public final boolean isDirect() {
         return false;
     }
 
+    @Override
     public final ByteOrder order() {
         return ByteOrder.nativeOrder();
     }
 
+    @Override
     public final CharSequence subSequence(int start, int end) {
         if (start < 0 || end < start || end > remaining()) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         CharBuffer result = duplicate();
         result.limit(position + end);
         result.position(position + start);
         return result;
     }
 
+    @Override
     public final String toString() {
         return String.copyValueOf(backingArray, offset + position, remaining());
     }
diff --git a/nio/src/main/java/java/nio/CharBuffer.java b/nio/src/main/java/java/nio/CharBuffer.java
index 289965a..4506614 100644
--- a/nio/src/main/java/java/nio/CharBuffer.java
+++ b/nio/src/main/java/java/nio/CharBuffer.java
@@ -23,7 +23,6 @@
  * A buffer of chars.
  * <p>
  * A char buffer can be created in either one of the following ways:
- * </p>
  * <ul>
  * <li>{@link #allocate(int) Allocate} a new char array and create a buffer
  * based on it;</li>
@@ -34,11 +33,9 @@
  * <li>Use {@link java.nio.ByteBuffer#asCharBuffer() ByteBuffer.asCharBuffer}
  * to create a char buffer based on a byte buffer.</li>
  * </ul>
- * 
- * @since Android 1.0
  */
-public abstract class CharBuffer extends Buffer implements Comparable<CharBuffer>,
-        CharSequence, Appendable, Readable {
+public abstract class CharBuffer extends Buffer implements
+        Comparable<CharBuffer>, CharSequence, Appendable, Readable {
 
     /**
      * Creates a char buffer based on a newly allocated char array.
@@ -48,7 +45,6 @@
      * @return the created char buffer.
      * @throws IllegalArgumentException
      *             if {@code capacity} is less than zero.
-     * @since Android 1.0
      */
     public static CharBuffer allocate(int capacity) {
         if (capacity < 0) {
@@ -62,12 +58,10 @@
      * <p>
      * Calling this method has the same effect as
      * {@code wrap(array, 0, array.length)}.
-     * </p>
-     * 
+     *
      * @param array
      *            the char array which the new buffer will be based on.
      * @return the created char buffer.
-     * @since Android 1.0
      */
     public static CharBuffer wrap(char[] array) {
         return wrap(array, 0, array.length);
@@ -78,8 +72,7 @@
      * <p>
      * The new buffer's position will be {@code start}, limit will be
      * {@code start + len}, capacity will be the length of the array.
-     * </p>
-     * 
+     *
      * @param array
      *            the char array which the new buffer will be based on.
      * @param start
@@ -91,12 +84,10 @@
      * @return the created char buffer.
      * @exception IndexOutOfBoundsException
      *                if either {@code start} or {@code len} is invalid.
-     * @since Android 1.0
      */
     public static CharBuffer wrap(char[] array, int start, int len) {
         int length = array.length;
-        if ((start < 0) || (len < 0)
-                || (long) start + (long) len > length) {
+        if ((start < 0) || (len < 0) || (long) start + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
 
@@ -112,12 +103,10 @@
      * <p>
      * Calling this method has the same effect as
      * {@code wrap(chseq, 0, chseq.length())}.
-     * </p>
-     * 
+     *
      * @param chseq
      *            the char sequence which the new buffer will be based on.
      * @return the created char buffer.
-     * @since Android 1.0
      */
     public static CharBuffer wrap(CharSequence chseq) {
         return BufferFactory.newCharBuffer(chseq);
@@ -129,8 +118,7 @@
      * The new buffer's position will be {@code start}, limit will be
      * {@code end}, capacity will be the length of the char sequence. The new
      * buffer is read-only.
-     * </p>
-     * 
+     *
      * @param chseq
      *            the char sequence which the new buffer will be based on.
      * @param start
@@ -142,7 +130,6 @@
      * @return the created char buffer.
      * @exception IndexOutOfBoundsException
      *                if either {@code start} or {@code end} is invalid.
-     * @since Android 1.0
      */
     public static CharBuffer wrap(CharSequence chseq, int start, int end) {
         if (chseq == null) {
@@ -151,7 +138,7 @@
         if (start < 0 || end < start || end > chseq.length()) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         CharBuffer result = BufferFactory.newCharBuffer(chseq);
         result.position = start;
         result.limit = end;
@@ -163,7 +150,6 @@
      * 
      * @param capacity
      *            the capacity of the buffer.
-     * @since Android 1.0
      */
     CharBuffer(int capacity) {
         super(capacity);
@@ -180,7 +166,6 @@
      *                if this buffer is based on an array, but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final char[] array() {
         return protectedArray();
@@ -192,21 +177,19 @@
      * <p>
      * The offset is the index of the array corresponds to the zero position of
      * the buffer.
-     * </p>
-     * 
+     *
      * @return the offset of the char array which this buffer is based on.
      * @exception ReadOnlyBufferException
      *                if this buffer is based on an array but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final int arrayOffset() {
         return protectedArrayOffset();
     }
 
     // BEGIN android-added
-    @Override 
+    @Override
     Object _array() {
         if (hasArray()) {
             return array();
@@ -214,7 +197,7 @@
         return null;
     }
 
-    @Override 
+    @Override
     int _arrayOffset() {
         if (hasArray()) {
             return arrayOffset();
@@ -229,15 +212,12 @@
      * The returned buffer is guaranteed to be a new instance, even if this
      * buffer is read-only itself. The new buffer's position, limit, capacity
      * and mark are the same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means this
      * buffer's change of content will be visible to the new buffer. The two
      * buffer's position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a read-only version of this buffer.
-     * @since Android 1.0
      */
     public abstract CharBuffer asReadOnlyBuffer();
 
@@ -253,7 +233,6 @@
      *         current position) in the buffer.
      * @exception IndexOutOfBoundsException
      *                if the index is invalid.
-     * @since Android 1.0
      */
     public final char charAt(int index) {
         if (index < 0 || index >= remaining()) {
@@ -268,12 +247,10 @@
      * The remaining chars will be moved to the head of the buffer,
      * starting from position zero. Then the position is set to
      * {@code remaining()}; the limit is set to capacity; the mark is cleared.
-     * </p>
-     * 
+     *
      * @return this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract CharBuffer compact();
 
@@ -288,7 +265,6 @@
      *         greater than {@code otherBuffer}.
      * @exception ClassCastException
      *                if {@code otherBuffer} is not a char buffer.
-     * @since Android 1.0
      */
     public int compareTo(CharBuffer otherBuffer) {
         int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
@@ -315,15 +291,12 @@
      * The duplicated buffer's initial position, limit, capacity and mark are
      * the same as this buffer's. The duplicated buffer's read-only property and
      * byte order are the same as this buffer's, too.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a duplicated buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract CharBuffer duplicate();
 
@@ -333,14 +306,13 @@
      * If {@code other} is not a char buffer then {@code false} is returned. Two
      * char buffers are equal if and only if their remaining chars are exactly
      * the same. Position, limit, capacity and mark are not considered.
-     * </p>
-     * 
+     *
      * @param other
      *            the object to compare with this char buffer.
      * @return {@code true} if this char buffer is equal to {@code other},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object other) {
         if (!(other instanceof CharBuffer)) {
             return false;
@@ -367,7 +339,6 @@
      * @return the char at the current position.
      * @exception BufferUnderflowException
      *                if the position is equal or greater than limit.
-     * @since Android 1.0
      */
     public abstract char get();
 
@@ -377,14 +348,12 @@
      * <p>
      * Calling this method has the same effect as
      * {@code get(dest, 0, dest.length)}.
-     * </p>
-     * 
+     *
      * @param dest
      *            the destination char array.
      * @return this buffer.
      * @exception BufferUnderflowException
      *                if {@code dest.length} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public CharBuffer get(char[] dest) {
         return get(dest, 0, dest.length);
@@ -408,14 +377,13 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception BufferUnderflowException
      *                if {@code len} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public CharBuffer get(char[] dest, int off, int len) {
         int length = dest.length;
-        if ((off < 0 ) || (len < 0) || (long)off + (long)len > length) {
+        if ((off < 0) || (len < 0) || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
@@ -433,16 +401,14 @@
      * @return a char at the specified index.
      * @exception IndexOutOfBoundsException
      *                if index is invalid.
-     * @since Android 1.0
      */
     public abstract char get(int index);
 
     /**
      * Indicates whether this buffer is based on a char array and is read/write.
-     * 
+     *
      * @return {@code true} if this buffer is based on a byte array and provides
      *         read/write access, {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean hasArray() {
         return protectedHasArray();
@@ -451,10 +417,10 @@
     /**
      * Calculates this buffer's hash code from the remaining chars. The
      * position, limit, capacity and mark don't affect the hash code.
-     * 
+     *
      * @return the hash code calculated from the remaining chars.
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         int myPosition = position;
         int hash = 0;
@@ -471,10 +437,8 @@
      * <p>
      * A char buffer is direct if it is based on a byte buffer and the byte
      * buffer is direct.
-     * </p>
-     * 
+     *
      * @return {@code true} if this buffer is direct, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isDirect();
 
@@ -482,7 +446,6 @@
      * Returns the number of remaining chars.
      * 
      * @return the number of remaining chars.
-     * @since Android 1.0
      */
     public final int length() {
         return remaining();
@@ -494,11 +457,9 @@
      * <p>
      * If this buffer is not based on a byte buffer, then this always returns
      * the platform's native byte order.
-     * </p>
-     * 
+     *
      * @return the byte order used by this buffer when converting chars from/to
      *         bytes.
-     * @since Android 1.0
      */
     public abstract ByteOrder order();
 
@@ -534,7 +495,6 @@
      *                if position is equal or greater than limit.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract CharBuffer put(char c);
 
@@ -544,8 +504,7 @@
      * <p>
      * Calling this method has the same effect as
      * {@code put(src, 0, src.length)}.
-     * </p>
-     * 
+     *
      * @param src
      *            the source char array.
      * @return this buffer.
@@ -553,7 +512,6 @@
      *                if {@code remaining()} is less than {@code src.length}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public final CharBuffer put(char[] src) {
         return put(src, 0, src.length);
@@ -579,14 +537,13 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public CharBuffer put(char[] src, int off, int len) {
         int length = src.length;
-        if ((off < 0 ) || (len < 0) || (long)off + (long)len > length) {
+        if ((off < 0) || (len < 0) || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
@@ -611,7 +568,6 @@
      *                if {@code src} is this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public CharBuffer put(CharBuffer src) {
         if (src == this) {
@@ -620,7 +576,7 @@
         if (src.remaining() > remaining()) {
             throw new BufferOverflowException();
         }
-        
+
         char[] contents = new char[src.remaining()];
         src.get(contents);
         put(contents);
@@ -640,7 +596,6 @@
      *                if index is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract CharBuffer put(int index, char c);
 
@@ -650,8 +605,7 @@
      * <p>
      * Calling this method has the same effect as
      * {@code put(str, 0, str.length())}.
-     * </p>
-     * 
+     *
      * @param str
      *            the string to write.
      * @return this buffer.
@@ -659,7 +613,6 @@
      *                if {@code remaining()} is less than the length of string.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public final CharBuffer put(String str) {
         return put(str, 0, str.length());
@@ -684,14 +637,13 @@
      *                if either {@code start} or {@code end} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public CharBuffer put(String str, int start, int end) {
         int length = str.length();
         if (start < 0 || end < start || end > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (end - start > remaining()) {
             throw new BufferOverflowException();
         }
@@ -709,15 +661,12 @@
      * The new buffer's position will be 0, limit will be its capacity, and its
      * mark is cleared. The new buffer's read-only property and byte order are
      * same as this buffer.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a sliced buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract CharBuffer slice();
 
@@ -729,13 +678,11 @@
      * be {@code position() + end}, capacity will be the same as this buffer.
      * The new buffer's read-only property and byte order are the same as this
      * buffer.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @param start
      *            the start index of the sub-sequence, referenced from the
      *            current buffer position. Must not be less than zero and not
@@ -750,7 +697,6 @@
      *         current remaining content.
      * @exception IndexOutOfBoundsException
      *                if either {@code start} or {@code end} is invalid.
-     * @since Android 1.0
      */
     public abstract CharSequence subSequence(int start, int end);
 
@@ -758,8 +704,8 @@
      * Returns a string representing the current remaining chars of this buffer.
      * 
      * @return a string representing the current remaining chars of this buffer.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         StringBuffer strbuf = new StringBuffer();
         for (int i = position; i < limit; i++) {
@@ -771,7 +717,7 @@
     /**
      * Writes the given char to the current position and increases the position
      * by 1.
-     * 
+     *
      * @param c
      *            the char to write.
      * @return this buffer.
@@ -779,9 +725,8 @@
      *                if position is equal or greater than limit.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
-    public CharBuffer append(char c){
+    public CharBuffer append(char c) {
         return put(c);
     }
 
@@ -791,10 +736,9 @@
      * of the csq.
      * <p>
      * Calling this method has the same effect as {@code append(csq.toString())}.
-     * </p>
      * If the {@code CharSequence} is {@code null} the string "null" will be
      * written to the buffer.
-     * 
+     *
      * @param csq
      *            the {@code CharSequence} to write.
      * @return this buffer.
@@ -802,9 +746,8 @@
      *                if {@code remaining()} is less than the length of csq.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
-    public CharBuffer append(CharSequence csq){
+    public CharBuffer append(CharSequence csq) {
         if (csq != null) {
             return put(csq.toString());
         }
@@ -814,7 +757,7 @@
     /**
      * Writes chars of the given {@code CharSequence} to the current position of
      * this buffer, and increases the position by the number of chars written.
-     * 
+     *
      * @param csq
      *            the {@code CharSequence} to write.
      * @param start
@@ -830,9 +773,8 @@
      *                if either {@code start} or {@code end} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
-    public CharBuffer append(CharSequence csq, int start, int end){
+    public CharBuffer append(CharSequence csq, int start, int end) {
         if (csq == null) {
             csq = "null"; //$NON-NLS-1$
         }
@@ -848,7 +790,7 @@
      * number of chars that are copied is either the number of remaining chars
      * in this buffer or the number of remaining chars in {@code target},
      * whichever is smaller.
-     * 
+     *
      * @param target
      *            the target char buffer.
      * @throws IllegalArgumentException
@@ -859,19 +801,24 @@
      *             if no changes may be made to the contents of {@code target}.
      * @return the number of chars copied or -1 if there are no chars left to be
      *         read from this buffer.
-     * @since Android 1.0
      */
     public int read(CharBuffer target) throws IOException {
-        if(target == this){
+        int remaining = remaining();
+        if (target == this) {
+            if (remaining == 0) {
+                return -1;
+            }
             throw new IllegalArgumentException();
         }
-        if (remaining() == 0) {
-            return target.remaining()==0?0:-1;
+        if (remaining == 0) {
+            return limit > 0 && target.remaining() == 0 ? 0 : -1;
         }
-        int result = Math.min(target.remaining(), remaining());
-        char[] chars = new char[result];
-        get(chars);
-        target.put(chars);
-        return result;
-    }    
+        remaining = Math.min(target.remaining(), remaining);
+        if (remaining > 0) {
+            char[] chars = new char[remaining];
+            get(chars);
+            target.put(chars);
+        }
+        return remaining;
+    }
 }
diff --git a/nio/src/main/java/java/nio/CharSequenceAdapter.java b/nio/src/main/java/java/nio/CharSequenceAdapter.java
index 32edc18..3f738b2 100644
--- a/nio/src/main/java/java/nio/CharSequenceAdapter.java
+++ b/nio/src/main/java/java/nio/CharSequenceAdapter.java
@@ -44,18 +44,22 @@
         sequence = chseq;
     }
 
+    @Override
     public CharBuffer asReadOnlyBuffer() {
         return duplicate();
     }
 
+    @Override
     public CharBuffer compact() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public CharBuffer duplicate() {
         return copy(this);
     }
 
+    @Override
     public char get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -63,6 +67,7 @@
         return sequence.charAt(position++);
     }
 
+    @Override
     public char get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -70,9 +75,10 @@
         return sequence.charAt(index);
     }
 
+    @Override
     public final CharBuffer get(char[] dest, int off, int len) {
         int length = dest.length;
-        if ((off < 0 ) || (len < 0) || (long)off + (long)len > length) {
+        if ((off < 0) || (len < 0) || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
@@ -84,66 +90,79 @@
         return this;
     }
 
+    @Override
     public boolean isDirect() {
         return false;
     }
 
+    @Override
     public boolean isReadOnly() {
         return true;
     }
 
+    @Override
     public ByteOrder order() {
         return ByteOrder.nativeOrder();
     }
 
+    @Override
     protected char[] protectedArray() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public CharBuffer put(char c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public CharBuffer put(int index, char c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public final CharBuffer put(char[] src, int off, int len) {
-        if ((off < 0 ) || (len < 0) || (long)off + (long)len > src.length) {
+        if ((off < 0) || (len < 0) || (long) off + (long) len > src.length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
-        
+
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public CharBuffer put(String src, int start, int end) {
-        if ((start < 0 ) || (end < 0) || (long)start + (long)end > src.length()) {
+        if ((start < 0) || (end < 0)
+                || (long) start + (long) end > src.length()) {
             throw new IndexOutOfBoundsException();
         }
         throw new ReadOnlyBufferException();
-    }  
+    }
 
+    @Override
     public CharBuffer slice() {
         return new CharSequenceAdapter(sequence.subSequence(position, limit));
     }
 
+    @Override
     public CharSequence subSequence(int start, int end) {
         if (end < start || start < 0 || end > remaining()) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         CharSequenceAdapter result = copy(this);
         result.position = position + start;
         result.limit = position + end;
diff --git a/nio/src/main/java/java/nio/CharToByteBufferAdapter.java b/nio/src/main/java/java/nio/CharToByteBufferAdapter.java
index bd340be..e92ea57 100644
--- a/nio/src/main/java/java/nio/CharToByteBufferAdapter.java
+++ b/nio/src/main/java/java/nio/CharToByteBufferAdapter.java
@@ -16,11 +16,8 @@
 
 package java.nio;
 
-// BEGIN android-added
-// Copied from newer version of harmony
 import org.apache.harmony.nio.internal.DirectBuffer;
 import org.apache.harmony.luni.platform.PlatformAddress;
-// END android-added
 
 /**
  * This class wraps a byte buffer to be a char buffer.
@@ -35,10 +32,7 @@
  * </p>
  * 
  */
-// BEGIN android-changed
-// Copied from newer version of harmony
 final class CharToByteBufferAdapter extends CharBuffer implements DirectBuffer {
-// END android-changed
 
     static CharBuffer wrap(ByteBuffer byteBuffer) {
         return new CharToByteBufferAdapter(byteBuffer.slice());
@@ -51,18 +45,15 @@
         this.byteBuffer = byteBuffer;
         this.byteBuffer.clear();
     }
-        
-    // BEGIN android-added
-    // Copied from newer version of harmony
+
     public int getByteCapacity() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getByteCapacity();
-        } else {
-            assert false : byteBuffer;
-            return -1;
-        }            
+            return ((DirectBuffer) byteBuffer).getByteCapacity();
+        }
+        assert false : byteBuffer;
+        return -1;
     }
-        
+
     public PlatformAddress getEffectiveAddress() {
         if (byteBuffer instanceof DirectBuffer) {
             // BEGIN android-changed
@@ -70,47 +61,44 @@
             effectiveDirectAddress = addr.toInt();
             return addr;
             // END android-changed
-        } else {
-            assert false : byteBuffer;
-            return null;
         }
+        assert false : byteBuffer;
+        return null;
     }
 
     public PlatformAddress getBaseAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getBaseAddress();
-        } else {
-            assert false : byteBuffer;
-            return null;
+            return ((DirectBuffer) byteBuffer).getBaseAddress();
         }
+        assert false : byteBuffer;
+        return null;
     }
-            
+
     public boolean isAddressValid() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).isAddressValid();
-        } else {
-            assert false : byteBuffer;
-            return false;
+            return ((DirectBuffer) byteBuffer).isAddressValid();
         }
+        assert false : byteBuffer;
+        return false;
     }
 
     public void addressValidityCheck() {
         if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).addressValidityCheck();
+            ((DirectBuffer) byteBuffer).addressValidityCheck();
         } else {
             assert false : byteBuffer;
         }
     }
-          
+
     public void free() {
         if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).free();
+            ((DirectBuffer) byteBuffer).free();
         } else {
             assert false : byteBuffer;
-        }   
+        }
     }
-    // END android-added
 
+    @Override
     public CharBuffer asReadOnlyBuffer() {
         CharToByteBufferAdapter buf = new CharToByteBufferAdapter(byteBuffer
                 .asReadOnlyBuffer());
@@ -120,6 +108,7 @@
         return buf;
     }
 
+    @Override
     public CharBuffer compact() {
         if (byteBuffer.isReadOnly()) {
             throw new ReadOnlyBufferException();
@@ -134,6 +123,7 @@
         return this;
     }
 
+    @Override
     public CharBuffer duplicate() {
         CharToByteBufferAdapter buf = new CharToByteBufferAdapter(byteBuffer
                 .duplicate());
@@ -143,6 +133,7 @@
         return buf;
     }
 
+    @Override
     public char get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -150,6 +141,7 @@
         return byteBuffer.getChar(position++ << 1);
     }
 
+    @Override
     public char get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -157,30 +149,37 @@
         return byteBuffer.getChar(index << 1);
     }
 
+    @Override
     public boolean isDirect() {
         return byteBuffer.isDirect();
     }
 
+    @Override
     public boolean isReadOnly() {
         return byteBuffer.isReadOnly();
     }
 
+    @Override
     public ByteOrder order() {
         return byteBuffer.order();
     }
 
+    @Override
     protected char[] protectedArray() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public CharBuffer put(char c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -189,6 +188,7 @@
         return this;
     }
 
+    @Override
     public CharBuffer put(int index, char c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -197,6 +197,7 @@
         return this;
     }
 
+    @Override
     public CharBuffer slice() {
         byteBuffer.limit(limit << 1);
         byteBuffer.position(position << 1);
@@ -205,11 +206,12 @@
         return result;
     }
 
+    @Override
     public CharSequence subSequence(int start, int end) {
         if (start < 0 || end < start || end > remaining()) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         CharBuffer result = duplicate();
         result.limit(position + end);
         result.position(position + start);
diff --git a/nio/src/main/java/java/nio/DirectByteBuffer.java b/nio/src/main/java/java/nio/DirectByteBuffer.java
index dcdb3c1..9bf6813 100644
--- a/nio/src/main/java/java/nio/DirectByteBuffer.java
+++ b/nio/src/main/java/java/nio/DirectByteBuffer.java
@@ -22,7 +22,6 @@
 import org.apache.harmony.nio.internal.DirectBuffer;
 import org.apache.harmony.nio.internal.nls.Messages;
 
-
 /**
  * DirectByteBuffer, ReadWriteDirectByteBuffer and ReadOnlyDirectByteBuffer
  * compose the implementation of platform memory based byte buffers.
@@ -58,13 +57,14 @@
 
     /*
      * Constructs a new direct byte buffer of the given capacity on newly
-     * allocated OS memory.  The memory will have been zeroed.  When the
-     * instance is discarded the OS memory will be freed if it has not
-     * already been done so by an explicit call to #free().  Callers are
-     * encouraged to explicitly free the memory where possible.
+     * allocated OS memory. The memory will have been zeroed. When the instance
+     * is discarded the OS memory will be freed if it has not already been done
+     * so by an explicit call to #free(). Callers are encouraged to explicitly
+     * free the memory where possible.
      */
     DirectByteBuffer(int capacity) {
-        this(new SafeAddress(PlatformAddressFactory.alloc(capacity, (byte)0)), capacity, 0);
+        this(new SafeAddress(PlatformAddressFactory.alloc(capacity, (byte) 0)),
+                capacity, 0);
         safeAddress.address.autoFree();
     }
 
@@ -79,7 +79,7 @@
             throw new IllegalArgumentException("slice out of range");
         }
         // END android-added
-        
+
         this.safeAddress = address;
         this.offset = offset;
     }
@@ -88,21 +88,24 @@
      * Override ByteBuffer.get(byte[], int, int) to improve performance.
      * 
      * (non-Javadoc)
+     * 
      * @see java.nio.ByteBuffer#get(byte[], int, int)
      */
+    @Override
     public final ByteBuffer get(byte[] dest, int off, int len) {
         int length = dest.length;
-        if ((off < 0 ) || (len < 0) || (long)off + (long)len > length) {
+        if ((off < 0) || (len < 0) || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
-        getBaseAddress().getByteArray(offset+position, dest, off, len);
+        getBaseAddress().getByteArray(offset + position, dest, off, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public final byte get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -110,6 +113,7 @@
         return getBaseAddress().getByte(offset + position++);
     }
 
+    @Override
     public final byte get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -117,6 +121,7 @@
         return getBaseAddress().getByte(offset + index);
     }
 
+    @Override
     public final double getDouble() {
         int newPosition = position + 8;
         if (newPosition > limit) {
@@ -127,13 +132,15 @@
         return result;
     }
 
+    @Override
     public final double getDouble(int index) {
-        if (index < 0 || (long)index + 8 > limit) {
+        if (index < 0 || (long) index + 8 > limit) {
             throw new IndexOutOfBoundsException();
         }
         return getBaseAddress().getDouble(offset + index, order);
     }
 
+    @Override
     public final float getFloat() {
         int newPosition = position + 4;
         if (newPosition > limit) {
@@ -144,13 +151,15 @@
         return result;
     }
 
+    @Override
     public final float getFloat(int index) {
-        if (index < 0 || (long)index + 4 > limit) {
+        if (index < 0 || (long) index + 4 > limit) {
             throw new IndexOutOfBoundsException();
         }
         return getBaseAddress().getFloat(offset + index, order);
     }
 
+    @Override
     public final int getInt() {
         int newPosition = position + 4;
         if (newPosition > limit) {
@@ -161,13 +170,15 @@
         return result;
     }
 
+    @Override
     public final int getInt(int index) {
-        if (index < 0 || (long)index + 4 > limit) {
+        if (index < 0 || (long) index + 4 > limit) {
             throw new IndexOutOfBoundsException();
         }
         return getBaseAddress().getInt(offset + index, order);
     }
 
+    @Override
     public final long getLong() {
         int newPosition = position + 8;
         if (newPosition > limit) {
@@ -178,13 +189,15 @@
         return result;
     }
 
+    @Override
     public final long getLong(int index) {
-        if (index < 0 || (long)index + 8 > limit) {
+        if (index < 0 || (long) index + 8 > limit) {
             throw new IndexOutOfBoundsException();
         }
         return getBaseAddress().getLong(offset + index, order);
     }
 
+    @Override
     public final short getShort() {
         int newPosition = position + 2;
         if (newPosition > limit) {
@@ -195,13 +208,15 @@
         return result;
     }
 
+    @Override
     public final short getShort(int index) {
-        if (index < 0 || (long)index + 2 > limit) {
+        if (index < 0 || (long) index + 2 > limit) {
             throw new IndexOutOfBoundsException();
         }
         return getBaseAddress().getShort(offset + index, order);
     }
 
+    @Override
     public final boolean isDirect() {
         return true;
     }
@@ -212,9 +227,9 @@
 
     public final void addressValidityCheck() {
         if (!isAddressValid()) {
-            // nio.08=Cannot use the direct byte buffer after it has been explicitly freed.
-            throw new IllegalStateException(
-                    Messages.getString("nio.08"));  //$NON-NLS-1$
+            // nio.08=Cannot use the direct byte buffer after it has been
+            // explicitly freed.
+            throw new IllegalStateException(Messages.getString("nio.08")); //$NON-NLS-1$
         }
     }
 
@@ -271,23 +286,23 @@
             safeAddress.address.free();
         }
     }
-    
+
+    @Override
     final protected byte[] protectedArray() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     final protected int protectedArrayOffset() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     final protected boolean protectedHasArray() {
         return false;
     }
 
-    // BEGIN android-added
-    // copied from newer version of harmony
     public final int getByteCapacity() {
         return capacity;
     }
-    // END android-added
 }
diff --git a/nio/src/main/java/java/nio/DirectByteBuffers.java b/nio/src/main/java/java/nio/DirectByteBuffers.java
index 03a0df7..77b6ebd 100644
--- a/nio/src/main/java/java/nio/DirectByteBuffers.java
+++ b/nio/src/main/java/java/nio/DirectByteBuffers.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package java.nio; 
+package java.nio;
 
 import org.apache.harmony.luni.platform.PlatformAddress;
 
@@ -31,13 +31,11 @@
      * If the memory is known to already have been freed then this is a no-op.
      * Once the memory has been freed then operations requiring access to the
      * memory will throw an <code>IllegalStateException</code>.
-     * </p>
      * <p>
      * Note this is is possible that the memory is freed by code that reaches
      * into the address and explicitly frees it 'beneith' us -- this is bad
      * form.
-     * </p>
-     * 
+     *
      * @param directBuffer
      *            the direct byte buffer memory to free
      * @throws IllegalArgumentException
@@ -61,8 +59,7 @@
      * If you can guarantee that you want to free the underlying memory call the
      * #free() method on this instance -- generally applications will rely on
      * the garbage collector to autofree this memory.
-     * </p>
-     * 
+     *
      * @param directBuffer
      *            the direct byte buffer
      * @return the effective address of the start of the buffer.
diff --git a/nio/src/main/java/java/nio/DoubleArrayBuffer.java b/nio/src/main/java/java/nio/DoubleArrayBuffer.java
index ad488ea..ce1e3a6 100644
--- a/nio/src/main/java/java/nio/DoubleArrayBuffer.java
+++ b/nio/src/main/java/java/nio/DoubleArrayBuffer.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package java.nio; 
+package java.nio;
 
 /**
  * DoubleArrayBuffer, ReadWriteDoubleArrayBuffer and ReadOnlyDoubleArrayBuffer
@@ -49,6 +49,7 @@
         this.offset = offset;
     }
 
+    @Override
     public final double get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -56,6 +57,7 @@
         return backingArray[offset + position++];
     }
 
+    @Override
     public final double get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -63,24 +65,26 @@
         return backingArray[offset + index];
     }
 
+    @Override
     public final DoubleBuffer get(double[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
-        System.arraycopy(backingArray, offset + position, dest,
-                off, len);
+        System.arraycopy(backingArray, offset + position, dest, off, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public final boolean isDirect() {
         return false;
     }
 
+    @Override
     public final ByteOrder order() {
         return ByteOrder.nativeOrder();
     }
diff --git a/nio/src/main/java/java/nio/DoubleBuffer.java b/nio/src/main/java/java/nio/DoubleBuffer.java
index b3c261d..4e0ab01 100644
--- a/nio/src/main/java/java/nio/DoubleBuffer.java
+++ b/nio/src/main/java/java/nio/DoubleBuffer.java
@@ -21,7 +21,6 @@
  * A buffer of doubles.
  * <p>
  * A double buffer can be created in either one of the following ways:
- * </p>
  * <ul>
  * <li>{@link #allocate(int) Allocate} a new double array and create a buffer
  * based on it;</li>
@@ -31,10 +30,9 @@
  * {@link java.nio.ByteBuffer#asDoubleBuffer() ByteBuffer.asDoubleBuffer} to
  * create a double buffer based on a byte buffer.</li>
  * </ul>
- * 
- * @since Android 1.0
  */
-public abstract class DoubleBuffer extends Buffer implements Comparable<DoubleBuffer> {
+public abstract class DoubleBuffer extends Buffer implements
+        Comparable<DoubleBuffer> {
 
     /**
      * Creates a double buffer based on a newly allocated double array.
@@ -44,7 +42,6 @@
      * @return the created double buffer.
      * @throws IllegalArgumentException
      *             if {@code capacity} is less than zero.
-     * @since Android 1.0
      */
     public static DoubleBuffer allocate(int capacity) {
         if (capacity < 0) {
@@ -58,12 +55,10 @@
      * <p>
      * Calling this method has the same effect as
      * {@code wrap(array, 0, array.length)}.
-     * </p>
-     * 
+     *
      * @param array
      *            the double array which the new buffer will be based on.
      * @return the created double buffer.
-     * @since Android 1.0
      */
     public static DoubleBuffer wrap(double[] array) {
         return wrap(array, 0, array.length);
@@ -74,8 +69,7 @@
      * <p>
      * The new buffer's position will be {@code start}, limit will be
      * {@code start + len}, capacity will be the length of the array.
-     * </p>
-     * 
+     *
      * @param array
      *            the double array which the new buffer will be based on.
      * @param start
@@ -87,11 +81,10 @@
      * @return the created double buffer.
      * @exception IndexOutOfBoundsException
      *                if either {@code start} or {@code len} is invalid.
-     * @since Android 1.0
      */
     public static DoubleBuffer wrap(double[] array, int start, int len) {
         int length = array.length;
-        if (start < 0 || len < 0 || (long)start + (long)len > length) {
+        if (start < 0 || len < 0 || (long) start + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
 
@@ -123,7 +116,6 @@
      *                if this buffer is based on an array but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final double[] array() {
         return protectedArray();
@@ -135,21 +127,19 @@
      * <p>
      * The offset is the index of the array corresponding to the zero position
      * of the buffer.
-     * </p>
-     * 
+     *
      * @return the offset of the double array which this buffer is based on.
      * @exception ReadOnlyBufferException
      *                if this buffer is based on an array, but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final int arrayOffset() {
         return protectedArrayOffset();
     }
 
     // BEGIN android-added
-    @Override 
+    @Override
     Object _array() {
         if (hasArray()) {
             return array();
@@ -157,7 +147,7 @@
         return null;
     }
 
-    @Override 
+    @Override
     int _arrayOffset() {
         if (hasArray()) {
             return arrayOffset();
@@ -172,15 +162,12 @@
      * The returned buffer is guaranteed to be a new instance, even if this
      * buffer is read-only itself. The new buffer's position, limit, capacity
      * and mark are the same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means that this
      * buffer's change of content will be visible to the new buffer. The two
      * buffer's position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a read-only version of this buffer.
-     * @since Android 1.0
      */
     public abstract DoubleBuffer asReadOnlyBuffer();
 
@@ -190,12 +177,10 @@
      * The remaining doubles will be moved to the head of the buffer, staring
      * from position zero. Then the position is set to {@code remaining()}; the
      * limit is set to capacity; the mark is cleared.
-     * </p>
-     * 
+     *
      * @return this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract DoubleBuffer compact();
 
@@ -210,14 +195,12 @@
      *         than {@code other}.
      * @exception ClassCastException
      *                if {@code other} is not a double buffer.
-     * @since Android 1.0
      */
     public int compareTo(DoubleBuffer otherBuffer) {
         int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
                 : otherBuffer.remaining();
         int thisPos = position;
         int otherPos = otherBuffer.position;
-        // BEGIN android-changed
         double thisDouble, otherDouble;
         while (compareRemaining > 0) {
             thisDouble = get(thisPos);
@@ -231,7 +214,6 @@
             otherPos++;
             compareRemaining--;
         }
-        // END android-changed
         return remaining() - otherBuffer.remaining();
     }
 
@@ -241,15 +223,12 @@
      * The duplicated buffer's position, limit, capacity and mark are the same
      * as this buffer's. The duplicated buffer's read-only property and byte
      * order are the same as this buffer's, too.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a duplicated buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract DoubleBuffer duplicate();
 
@@ -259,14 +238,13 @@
      * If {@code other} is not a double buffer then {@code false} is returned.
      * Two double buffers are equal if and only if their remaining doubles are
      * exactly the same. Position, limit, capacity and mark are not considered.
-     * </p>
-     * 
+     *
      * @param other
      *            the object to compare with this double buffer.
      * @return {@code true} if this double buffer is equal to {@code other},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object other) {
         if (!(other instanceof DoubleBuffer)) {
             return false;
@@ -294,7 +272,6 @@
      * @return the double at the current position.
      * @exception BufferUnderflowException
      *                if the position is equal or greater than limit.
-     * @since Android 1.0
      */
     public abstract double get();
 
@@ -304,14 +281,12 @@
      * <p>
      * Calling this method has the same effect as
      * {@code get(dest, 0, dest.length)}.
-     * </p>
-     * 
+     *
      * @param dest
      *            the destination double array.
      * @return this buffer.
      * @exception BufferUnderflowException
      *                if {@code dest.length} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public DoubleBuffer get(double[] dest) {
         return get(dest, 0, dest.length);
@@ -335,14 +310,13 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception BufferUnderflowException
      *                if {@code len} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public DoubleBuffer get(double[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
@@ -360,17 +334,15 @@
      * @return a double at the specified index.
      * @exception IndexOutOfBoundsException
      *                if index is invalid.
-     * @since Android 1.0
      */
     public abstract double get(int index);
 
     /**
      * Indicates whether this buffer is based on a double array and is
      * read/write.
-     * 
+     *
      * @return {@code true} if this buffer is based on a double array and
      *         provides read/write access, {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean hasArray() {
         return protectedHasArray();
@@ -379,10 +351,10 @@
     /**
      * Calculates this buffer's hash code from the remaining chars. The
      * position, limit, capacity and mark don't affect the hash code.
-     * 
+     *
      * @return the hash code calculated from the remaining chars.
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         int myPosition = position;
         int hash = 0;
@@ -401,10 +373,8 @@
      * <p>
      * A double buffer is direct if it is based on a byte buffer and the byte
      * buffer is direct.
-     * </p>
      * 
      * @return {@code true} if this buffer is direct, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isDirect();
 
@@ -414,11 +384,9 @@
      * <p>
      * If this buffer is not based on a byte buffer, then this always returns
      * the platform's native byte order.
-     * </p>
-     * 
+     *
      * @return the byte order used by this buffer when converting doubles
      *         from/to bytes.
-     * @since Android 1.0
      */
     public abstract ByteOrder order();
 
@@ -454,7 +422,6 @@
      *                if position is equal or greater than limit.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract DoubleBuffer put(double d);
 
@@ -464,8 +431,7 @@
      * <p>
      * Calling this method has the same effect as
      * {@code put(src, 0, src.length)}.
-     * </p>
-     * 
+     *
      * @param src
      *            the source double array.
      * @return this buffer.
@@ -473,7 +439,6 @@
      *                if {@code remaining()} is less than {@code src.length}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public final DoubleBuffer put(double[] src) {
         return put(src, 0, src.length);
@@ -499,14 +464,13 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public DoubleBuffer put(double[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
@@ -531,7 +495,6 @@
      *                if {@code src} is this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public DoubleBuffer put(DoubleBuffer src) {
         if (src == this) {
@@ -559,7 +522,6 @@
      *                if index is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract DoubleBuffer put(int index, double d);
 
@@ -571,15 +533,12 @@
      * The new buffer's position will be 0, limit will be its capacity, and its
      * mark is cleared. The new buffer's read-only property and byte order are
      * the same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a sliced buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract DoubleBuffer slice();
 
@@ -587,16 +546,16 @@
      * Returns a string representing the state of this double buffer.
      * 
      * @return A string representing the state of this double buffer.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         buf.append(getClass().getName());
         buf.append(", status: capacity="); //$NON-NLS-1$
         buf.append(capacity());
         buf.append(" position="); //$NON-NLS-1$
         buf.append(position());
-        buf.append(" limit="); //$NON-NLS-1$    
+        buf.append(" limit="); //$NON-NLS-1$
         buf.append(limit());
         return buf.toString();
     }
diff --git a/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java b/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java
index 70406ba..da53bdc 100644
--- a/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java
+++ b/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java
@@ -16,11 +16,8 @@
 
 package java.nio;
 
-// BEGIN android-added
-// Copied from newer version of harmony
 import org.apache.harmony.nio.internal.DirectBuffer;
 import org.apache.harmony.luni.platform.PlatformAddress;
-// END android-added
 
 /**
  * This class wraps a byte buffer to be a double buffer.
@@ -35,10 +32,8 @@
  * </p>
  * 
  */
-// BEGIN android-changed
-// Copied from newer version of harmony
-final class DoubleToByteBufferAdapter extends DoubleBuffer implements DirectBuffer {
-// END android-changed
+final class DoubleToByteBufferAdapter extends DoubleBuffer implements
+        DirectBuffer {
 
     static DoubleBuffer wrap(ByteBuffer byteBuffer) {
         return new DoubleToByteBufferAdapter(byteBuffer.slice());
@@ -52,15 +47,12 @@
         this.byteBuffer.clear();
     }
 
-    // BEGIN android-added
-    // Copied from newer version of harmony
     public int getByteCapacity() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getByteCapacity();
-        } else {
-            assert false : byteBuffer;
-            return -1;
-        }            
+            return ((DirectBuffer) byteBuffer).getByteCapacity();
+        }
+        assert false : byteBuffer;
+        return -1;
     }
 
     public PlatformAddress getEffectiveAddress() {
@@ -70,47 +62,44 @@
             effectiveDirectAddress = addr.toInt();
             return addr;
             // END android-changed
-        } else {
-            assert false : byteBuffer;
-            return null;
         }
+        assert false : byteBuffer;
+        return null;
     }
 
     public PlatformAddress getBaseAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getBaseAddress();
-        } else {
-            assert false : byteBuffer;
-            return null;
+            return ((DirectBuffer) byteBuffer).getBaseAddress();
         }
+        assert false : byteBuffer;
+        return null;
     }
-            
+
     public boolean isAddressValid() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).isAddressValid();
-        } else {
-            assert false : byteBuffer;
-            return false;
+            return ((DirectBuffer) byteBuffer).isAddressValid();
         }
+        assert false : byteBuffer;
+        return false;
     }
 
     public void addressValidityCheck() {
         if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).addressValidityCheck();
+            ((DirectBuffer) byteBuffer).addressValidityCheck();
         } else {
             assert false : byteBuffer;
         }
     }
-            
+
     public void free() {
         if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).free();
+            ((DirectBuffer) byteBuffer).free();
         } else {
             assert false : byteBuffer;
-        }   
+        }
     }
-    // END android-added
-        
+
+    @Override
     public DoubleBuffer asReadOnlyBuffer() {
         DoubleToByteBufferAdapter buf = new DoubleToByteBufferAdapter(
                 byteBuffer.asReadOnlyBuffer());
@@ -120,6 +109,7 @@
         return buf;
     }
 
+    @Override
     public DoubleBuffer compact() {
         if (byteBuffer.isReadOnly()) {
             throw new ReadOnlyBufferException();
@@ -134,6 +124,7 @@
         return this;
     }
 
+    @Override
     public DoubleBuffer duplicate() {
         DoubleToByteBufferAdapter buf = new DoubleToByteBufferAdapter(
                 byteBuffer.duplicate());
@@ -143,6 +134,7 @@
         return buf;
     }
 
+    @Override
     public double get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -150,6 +142,7 @@
         return byteBuffer.getDouble(position++ << 3);
     }
 
+    @Override
     public double get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -157,30 +150,37 @@
         return byteBuffer.getDouble(index << 3);
     }
 
+    @Override
     public boolean isDirect() {
         return byteBuffer.isDirect();
     }
 
+    @Override
     public boolean isReadOnly() {
         return byteBuffer.isReadOnly();
     }
 
+    @Override
     public ByteOrder order() {
         return byteBuffer.order();
     }
 
+    @Override
     protected double[] protectedArray() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public DoubleBuffer put(double c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -189,6 +189,7 @@
         return this;
     }
 
+    @Override
     public DoubleBuffer put(int index, double c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -197,6 +198,7 @@
         return this;
     }
 
+    @Override
     public DoubleBuffer slice() {
         byteBuffer.limit(limit << 3);
         byteBuffer.position(position << 3);
diff --git a/nio/src/main/java/java/nio/FloatArrayBuffer.java b/nio/src/main/java/java/nio/FloatArrayBuffer.java
index bb07e97..0dcc89c 100644
--- a/nio/src/main/java/java/nio/FloatArrayBuffer.java
+++ b/nio/src/main/java/java/nio/FloatArrayBuffer.java
@@ -49,6 +49,7 @@
         this.offset = offset;
     }
 
+    @Override
     public final float get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -56,6 +57,7 @@
         return backingArray[offset + position++];
     }
 
+    @Override
     public final float get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -63,23 +65,26 @@
         return backingArray[offset + index];
     }
 
+    @Override
     public final FloatBuffer get(float[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
-        System.arraycopy(backingArray, offset+position, dest, off, len);
+        System.arraycopy(backingArray, offset + position, dest, off, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public final boolean isDirect() {
         return false;
     }
 
+    @Override
     public final ByteOrder order() {
         return ByteOrder.nativeOrder();
     }
diff --git a/nio/src/main/java/java/nio/FloatBuffer.java b/nio/src/main/java/java/nio/FloatBuffer.java
index f7ee917..cab94c3 100644
--- a/nio/src/main/java/java/nio/FloatBuffer.java
+++ b/nio/src/main/java/java/nio/FloatBuffer.java
@@ -21,7 +21,6 @@
  * A buffer of floats.
  * <p>
  * A float buffer can be created in either of the following ways:
- * </p>
  * <ul>
  * <li>{@link #allocate(int) Allocate} a new float array and create a buffer
  * based on it;</li>
@@ -30,10 +29,9 @@
  * <li>Use {@link java.nio.ByteBuffer#asFloatBuffer() ByteBuffer.asFloatBuffer}
  * to create a float buffer based on a byte buffer.</li>
  * </ul>
- * 
- * @since Android 1.0
  */
-public abstract class FloatBuffer extends Buffer implements Comparable<FloatBuffer> {
+public abstract class FloatBuffer extends Buffer implements
+        Comparable<FloatBuffer> {
 
     /**
      * Creates a float buffer based on a newly allocated float array.
@@ -43,7 +41,6 @@
      * @return the created float buffer.
      * @throws IllegalArgumentException
      *             if {@code capacity} is less than zero.
-     * @since Android 1.0
      */
     public static FloatBuffer allocate(int capacity) {
         if (capacity < 0) {
@@ -57,12 +54,10 @@
      * <p>
      * Calling this method has the same effect as
      * {@code wrap(array, 0, array.length)}.
-     * </p>
-     * 
+     *
      * @param array
      *            the float array which the new buffer will be based on.
      * @return the created float buffer.
-     * @since Android 1.0
      */
     public static FloatBuffer wrap(float[] array) {
         return wrap(array, 0, array.length);
@@ -73,8 +68,7 @@
      * <p>
      * The new buffer's position will be {@code start}, limit will be
      * {@code start + len}, capacity will be the length of the array.
-     * </p>
-     * 
+     *
      * @param array
      *            the float array which the new buffer will be based on.
      * @param start
@@ -88,15 +82,14 @@
      *                if either {@code start} or {@code len} is invalid.
      * @exception NullPointerException
      *                if {@code array} is null.
-     * @since Android 1.0
      */
     public static FloatBuffer wrap(float[] array, int start, int len) {
-                if (array == null) {
-                        throw new NullPointerException();
-                }
-                if (start < 0 || len < 0 || (long)start + (long)len > array.length) {
-                        throw new IndexOutOfBoundsException();
-                }
+        if (array == null) {
+            throw new NullPointerException();
+        }
+        if (start < 0 || len < 0 || (long) start + (long) len > array.length) {
+            throw new IndexOutOfBoundsException();
+        }
 
         FloatBuffer buf = BufferFactory.newFloatBuffer(array);
         buf.position = start;
@@ -125,7 +118,6 @@
      *                if this buffer is based on an array, but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final float[] array() {
         return protectedArray();
@@ -137,14 +129,12 @@
      * <p>
      * The offset is the index of the array and corresponds to the zero position
      * of the buffer.
-     * </p>
-     * 
+     *
      * @return the offset of the float array which this buffer is based on.
      * @exception ReadOnlyBufferException
      *                if this buffer is based on an array, but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final int arrayOffset() {
         return protectedArrayOffset();
@@ -172,15 +162,12 @@
      * The returned buffer is guaranteed to be a new instance, even if this
      * buffer is read-only itself. The new buffer's position, limit, capacity
      * and mark are the same as this buffer.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means this
      * buffer's change of content will be visible to the new buffer. The two
      * buffer's position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a read-only version of this buffer.
-     * @since Android 1.0
      */
     public abstract FloatBuffer asReadOnlyBuffer();
 
@@ -190,12 +177,10 @@
      * The remaining floats will be moved to the head of the buffer, starting
      * from position zero. Then the position is set to {@code remaining()}; the
      * limit is set to capacity; the mark is cleared.
-     * </p>
-     * 
+     *
      * @return this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract FloatBuffer compact();
 
@@ -210,14 +195,12 @@
      *         greater than {@code otherBuffer}.
      * @exception ClassCastException
      *                if {@code otherBuffer} is not a float buffer.
-     * @since Android 1.0
      */
     public int compareTo(FloatBuffer otherBuffer) {
         int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
                 : otherBuffer.remaining();
         int thisPos = position;
         int otherPos = otherBuffer.position;
-        // BEGIN android-changed
         float thisFloat, otherFloat;
         while (compareRemaining > 0) {
             thisFloat = get(thisPos);
@@ -231,7 +214,6 @@
             otherPos++;
             compareRemaining--;
         }
-        // END android-changed
         return remaining() - otherBuffer.remaining();
     }
 
@@ -241,15 +223,12 @@
      * The duplicated buffer's position, limit, capacity and mark are the same
      * as this buffer. The duplicated buffer's read-only property and byte order
      * are same as this buffer too.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a duplicated buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract FloatBuffer duplicate();
 
@@ -259,14 +238,13 @@
      * If {@code other} is not a float buffer then {@code false} is returned.
      * Two float buffers are equal if and only if their remaining floats are
      * exactly the same. Position, limit, capacity and mark are not considered.
-     * </p>
-     * 
+     *
      * @param other
      *            the object to compare with this float buffer.
      * @return {@code true} if this float buffer is equal to {@code other},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object other) {
         if (!(other instanceof FloatBuffer)) {
             return false;
@@ -294,7 +272,6 @@
      * @return the float at the current position.
      * @exception BufferUnderflowException
      *                if the position is equal or greater than limit.
-     * @since Android 1.0
      */
     public abstract float get();
 
@@ -304,14 +281,12 @@
      * <p>
      * Calling this method has the same effect as
      * {@code get(dest, 0, dest.length)}.
-     * </p>
-     * 
+     *
      * @param dest
      *            the destination float array.
      * @return this buffer.
      * @exception BufferUnderflowException
      *                if {@code dest.length} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public FloatBuffer get(float[] dest) {
         return get(dest, 0, dest.length);
@@ -335,14 +310,13 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception BufferUnderflowException
      *                if {@code len} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public FloatBuffer get(float[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
@@ -360,17 +334,15 @@
      * @return a float at the specified index.
      * @exception IndexOutOfBoundsException
      *                if index is invalid.
-     * @since Android 1.0
      */
     public abstract float get(int index);
 
     /**
      * Indicates whether this buffer is based on a float array and is
      * read/write.
-     * 
+     *
      * @return {@code true} if this buffer is based on a float array and
      *         provides read/write access, {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean hasArray() {
         return protectedHasArray();
@@ -379,10 +351,10 @@
     /**
      * Calculates this buffer's hash code from the remaining chars. The
      * position, limit, capacity and mark don't affect the hash code.
-     * 
+     *
      * @return the hash code calculated from the remaining floats.
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         int myPosition = position;
         int hash = 0;
@@ -399,10 +371,8 @@
      * <p>
      * A float buffer is direct if it is based on a byte buffer and the byte
      * buffer is direct.
-     * </p>
-     * 
+     *
      * @return {@code true} if this buffer is direct, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isDirect();
 
@@ -412,11 +382,9 @@
      * <p>
      * If this buffer is not based on a byte buffer, then always return the
      * platform's native byte order.
-     * </p>
-     * 
+     *
      * @return the byte order used by this buffer when converting floats from/to
      *         bytes.
-     * @since Android 1.0
      */
     public abstract ByteOrder order();
 
@@ -452,7 +420,6 @@
      *                if position is equal or greater than limit.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract FloatBuffer put(float f);
 
@@ -462,8 +429,7 @@
      * <p>
      * Calling this method has the same effect as
      * {@code put(src, 0, src.length)}.
-     * </p>
-     * 
+     *
      * @param src
      *            the source float array.
      * @return this buffer.
@@ -471,7 +437,6 @@
      *                if {@code remaining()} is less than {@code src.length}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public final FloatBuffer put(float[] src) {
         return put(src, 0, src.length);
@@ -497,14 +462,13 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public FloatBuffer put(float[] src, int off, int len) {
         int length = src.length;
         if (off < 0 || len < 0 || (long)off + (long)len > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
@@ -529,7 +493,6 @@
      *                if {@code src} is this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public FloatBuffer put(FloatBuffer src) {
         if (src == this) {
@@ -557,7 +520,6 @@
      *                if index is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract FloatBuffer put(int index, float f);
 
@@ -569,15 +531,12 @@
      * The new buffer's position will be 0, limit will be its capacity, and its
      * mark is cleared. The new buffer's read-only property and byte order are
      * same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
      * 
      * @return a sliced buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract FloatBuffer slice();
 
@@ -585,10 +544,10 @@
      * Returns a string representing the state of this float buffer.
      * 
      * @return a string representing the state of this float buffer.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         buf.append(getClass().getName());
         buf.append(", status: capacity="); //$NON-NLS-1$
         buf.append(capacity());
diff --git a/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java b/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java
index 75b9d84..d91ad0d 100644
--- a/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java
+++ b/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java
@@ -16,11 +16,8 @@
 
 package java.nio;
 
-// BEGIN android-added
-// copied from newer version of harmony
 import org.apache.harmony.nio.internal.DirectBuffer;
 import org.apache.harmony.luni.platform.PlatformAddress;
-// END android-added
 
 /**
  * This class wraps a byte buffer to be a float buffer.
@@ -35,10 +32,8 @@
  * </p>
  * 
  */
-// BEGIN android-changed
-// copied from newer version of harmony
-final class FloatToByteBufferAdapter extends FloatBuffer implements DirectBuffer {
-// END android-changed
+final class FloatToByteBufferAdapter extends FloatBuffer implements
+        DirectBuffer {
 
     static FloatBuffer wrap(ByteBuffer byteBuffer) {
         return new FloatToByteBufferAdapter(byteBuffer.slice());
@@ -52,15 +47,12 @@
         this.byteBuffer.clear();
     }
 
-    // BEGIN android-added
-    // copied from newer version of harmony
     public int getByteCapacity() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getByteCapacity();
-        } else {
-            assert false : byteBuffer;
-            return -1;
-        }            
+            return ((DirectBuffer) byteBuffer).getByteCapacity();
+        }
+        assert false : byteBuffer;
+        return -1;
     }
 
     public PlatformAddress getEffectiveAddress() {
@@ -70,47 +62,44 @@
             effectiveDirectAddress = addr.toInt();
             return addr;
             // END android-changed
-        } else {
-            assert false : byteBuffer;
-            return null;
         }
+        assert false : byteBuffer;
+        return null;
     }
 
     public PlatformAddress getBaseAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getBaseAddress();
-        } else {
-            assert false : byteBuffer;
-            return null;
+            return ((DirectBuffer) byteBuffer).getBaseAddress();
         }
+        assert false : byteBuffer;
+        return null;
     }
-            
+
     public boolean isAddressValid() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).isAddressValid();
-        } else {
-            assert false : byteBuffer;
-            return false;
+            return ((DirectBuffer) byteBuffer).isAddressValid();
         }
+        assert false : byteBuffer;
+        return false;
     }
 
     public void addressValidityCheck() {
         if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).addressValidityCheck();
+            ((DirectBuffer) byteBuffer).addressValidityCheck();
         } else {
             assert false : byteBuffer;
         }
     }
-        
+
     public void free() {
         if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).free();
+            ((DirectBuffer) byteBuffer).free();
         } else {
             assert false : byteBuffer;
-        }   
+        }
     }
-    // END android-added
 
+    @Override
     public FloatBuffer asReadOnlyBuffer() {
         FloatToByteBufferAdapter buf = new FloatToByteBufferAdapter(byteBuffer
                 .asReadOnlyBuffer());
@@ -120,6 +109,7 @@
         return buf;
     }
 
+    @Override
     public FloatBuffer compact() {
         if (byteBuffer.isReadOnly()) {
             throw new ReadOnlyBufferException();
@@ -134,6 +124,7 @@
         return this;
     }
 
+    @Override
     public FloatBuffer duplicate() {
         FloatToByteBufferAdapter buf = new FloatToByteBufferAdapter(byteBuffer
                 .duplicate());
@@ -143,6 +134,7 @@
         return buf;
     }
 
+    @Override
     public float get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -150,6 +142,7 @@
         return byteBuffer.getFloat(position++ << 2);
     }
 
+    @Override
     public float get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -157,30 +150,37 @@
         return byteBuffer.getFloat(index << 2);
     }
 
+    @Override
     public boolean isDirect() {
         return byteBuffer.isDirect();
     }
 
+    @Override
     public boolean isReadOnly() {
         return byteBuffer.isReadOnly();
     }
 
+    @Override
     public ByteOrder order() {
         return byteBuffer.order();
     }
 
+    @Override
     protected float[] protectedArray() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public FloatBuffer put(float c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -189,6 +189,7 @@
         return this;
     }
 
+    @Override
     public FloatBuffer put(int index, float c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -197,6 +198,7 @@
         return this;
     }
 
+    @Override
     public FloatBuffer slice() {
         byteBuffer.limit(limit << 2);
         byteBuffer.position(position << 2);
diff --git a/nio/src/main/java/java/nio/HeapByteBuffer.java b/nio/src/main/java/java/nio/HeapByteBuffer.java
index 49c4038..a87d5b3 100644
--- a/nio/src/main/java/java/nio/HeapByteBuffer.java
+++ b/nio/src/main/java/java/nio/HeapByteBuffer.java
@@ -62,9 +62,10 @@
      * 
      * @see java.nio.ByteBuffer#get(byte[], int, int)
      */
+    @Override
     public final ByteBuffer get(byte[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
@@ -74,7 +75,8 @@
         position += len;
         return this;
     }
-    
+
+    @Override
     public final byte get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -82,6 +84,7 @@
         return backingArray[offset + position++];
     }
 
+    @Override
     public final byte get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -89,22 +92,27 @@
         return backingArray[offset + index];
     }
 
+    @Override
     public final double getDouble() {
         return Double.longBitsToDouble(getLong());
     }
 
+    @Override
     public final double getDouble(int index) {
         return Double.longBitsToDouble(getLong(index));
     }
 
+    @Override
     public final float getFloat() {
         return Float.intBitsToFloat(getInt());
     }
 
+    @Override
     public final float getFloat(int index) {
         return Float.intBitsToFloat(getInt(index));
     }
 
+    @Override
     public final int getInt() {
         int newPosition = position + 4;
         if (newPosition > limit) {
@@ -115,6 +123,7 @@
         return result;
     }
 
+    @Override
     public final int getInt(int index) {
         if (index < 0 || index + 4 > limit) {
             throw new IndexOutOfBoundsException();
@@ -122,6 +131,7 @@
         return loadInt(index);
     }
 
+    @Override
     public final long getLong() {
         int newPosition = position + 8;
         if (newPosition > limit) {
@@ -132,6 +142,7 @@
         return result;
     }
 
+    @Override
     public final long getLong(int index) {
         if (index < 0 || index + 8 > limit) {
             throw new IndexOutOfBoundsException();
@@ -139,6 +150,7 @@
         return loadLong(index);
     }
 
+    @Override
     public final short getShort() {
         int newPosition = position + 2;
         if (newPosition > limit) {
@@ -149,6 +161,7 @@
         return result;
     }
 
+    @Override
     public final short getShort(int index) {
         if (index < 0 || index + 2 > limit) {
             throw new IndexOutOfBoundsException();
@@ -156,6 +169,7 @@
         return loadShort(index);
     }
 
+    @Override
     public final boolean isDirect() {
         return false;
     }
@@ -163,12 +177,12 @@
     protected final int loadInt(int index) {
         int baseOffset = offset + index;
         int bytes = 0;
-        if(order == Endianness.BIG_ENDIAN){
+        if (order == Endianness.BIG_ENDIAN) {
             for (int i = 0; i < 4; i++) {
                 bytes = bytes << 8;
                 bytes = bytes | (backingArray[baseOffset + i] & 0xFF);
-            }    
-        }else{
+            }
+        } else {
             for (int i = 3; i >= 0; i--) {
                 bytes = bytes << 8;
                 bytes = bytes | (backingArray[baseOffset + i] & 0xFF);
@@ -180,12 +194,12 @@
     protected final long loadLong(int index) {
         int baseOffset = offset + index;
         long bytes = 0;
-        if(order == Endianness.BIG_ENDIAN){
+        if (order == Endianness.BIG_ENDIAN) {
             for (int i = 0; i < 8; i++) {
                 bytes = bytes << 8;
                 bytes = bytes | (backingArray[baseOffset + i] & 0xFF);
-            }    
-        }else{
+            }
+        } else {
             for (int i = 7; i >= 0; i--) {
                 bytes = bytes << 8;
                 bytes = bytes | (backingArray[baseOffset + i] & 0xFF);
@@ -196,12 +210,12 @@
 
     protected final short loadShort(int index) {
         int baseOffset = offset + index;
-        short bytes  = 0;
-        if(order == Endianness.BIG_ENDIAN){
+        short bytes = 0;
+        if (order == Endianness.BIG_ENDIAN) {
             bytes = (short) (backingArray[baseOffset] << 8);
-            bytes |= (backingArray[baseOffset + 1] & 0xFF);   
-        }else{
-            bytes = (short) (backingArray[baseOffset+1] << 8);
+            bytes |= (backingArray[baseOffset + 1] & 0xFF);
+        } else {
+            bytes = (short) (backingArray[baseOffset + 1] << 8);
             bytes |= (backingArray[baseOffset] & 0xFF);
         }
         return bytes;
@@ -243,7 +257,7 @@
             backingArray[baseOffset] = (byte) ((value >> 8) & 0xFF);
             backingArray[baseOffset + 1] = (byte) (value & 0xFF);
         } else {
-            backingArray[baseOffset+1] = (byte) ((value >> 8) & 0xFF);
+            backingArray[baseOffset + 1] = (byte) ((value >> 8) & 0xFF);
             backingArray[baseOffset] = (byte) (value & 0xFF);
         }
     }
diff --git a/nio/src/main/java/java/nio/IntArrayBuffer.java b/nio/src/main/java/java/nio/IntArrayBuffer.java
index d77268e..0352a0f 100644
--- a/nio/src/main/java/java/nio/IntArrayBuffer.java
+++ b/nio/src/main/java/java/nio/IntArrayBuffer.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package java.nio; 
+package java.nio;
 
 /**
  * IntArrayBuffer, ReadWriteIntArrayBuffer and ReadOnlyIntArrayBuffer compose
@@ -49,6 +49,7 @@
         this.offset = offset;
     }
 
+    @Override
     public final int get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -56,6 +57,7 @@
         return backingArray[offset + position++];
     }
 
+    @Override
     public final int get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -63,23 +65,26 @@
         return backingArray[offset + index];
     }
 
+    @Override
     public final IntBuffer get(int[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)len + (long)off > length) {
+        if (off < 0 || len < 0 || (long) len + (long) off > length) {
             throw new IndexOutOfBoundsException();
-        }       
+        }
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
-        System.arraycopy(backingArray, offset+position, dest, off, len);
+        System.arraycopy(backingArray, offset + position, dest, off, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public final boolean isDirect() {
         return false;
     }
 
+    @Override
     public final ByteOrder order() {
         return ByteOrder.nativeOrder();
     }
diff --git a/nio/src/main/java/java/nio/IntBuffer.java b/nio/src/main/java/java/nio/IntBuffer.java
index 7a19dfd..d95783b 100644
--- a/nio/src/main/java/java/nio/IntBuffer.java
+++ b/nio/src/main/java/java/nio/IntBuffer.java
@@ -21,7 +21,6 @@
  * A buffer of ints.
  * <p>
  * A int buffer can be created in either of the following ways:
- * </p>
  * <ul>
  * <li>{@link #allocate(int) Allocate} a new int array and create a buffer
  * based on it;</li>
@@ -29,8 +28,6 @@
  * <li>Use {@link java.nio.ByteBuffer#asIntBuffer() ByteBuffer.asIntBuffer} to
  * create a int buffer based on a byte buffer.</li>
  * </ul>
- * 
- * @since Android 1.0
  */
 public abstract class IntBuffer extends Buffer implements Comparable<IntBuffer> {
 
@@ -42,7 +39,6 @@
      * @return the created int buffer.
      * @throws IllegalArgumentException
      *             if {@code capacity} is less than zero.
-     * @since Android 1.0
      */
     public static IntBuffer allocate(int capacity) {
         if (capacity < 0) {
@@ -56,12 +52,10 @@
      * <p>
      * Calling this method has the same effect as
      * {@code wrap(array, 0, array.length)}.
-     * </p>
-     * 
+     *
      * @param array
      *            the int array which the new buffer will be based on.
      * @return the created int buffer.
-     * @since Android 1.0
      */
     public static IntBuffer wrap(int[] array) {
         return wrap(array, 0, array.length);
@@ -72,8 +66,7 @@
      * <p>
      * The new buffer's position will be {@code start}, limit will be
      * {@code start + len}, capacity will be the length of the array.
-     * </p>
-     * 
+     *
      * @param array
      *            the int array which the new buffer will be based on.
      * @param start
@@ -85,15 +78,14 @@
      * @return the created int buffer.
      * @exception IndexOutOfBoundsException
      *                if either {@code start} or {@code len} is invalid.
-     * @since Android 1.0
      */
     public static IntBuffer wrap(int[] array, int start, int len) {
-                if (array == null) {
-                        throw new NullPointerException();
-                }
-                if (start < 0 || len < 0 || (long)len + (long)start > array.length) {
-                        throw new IndexOutOfBoundsException();
-                }
+        if (array == null) {
+            throw new NullPointerException();
+        }
+        if (start < 0 || len < 0 || (long) len + (long) start > array.length) {
+            throw new IndexOutOfBoundsException();
+        }
 
         IntBuffer buf = BufferFactory.newIntBuffer(array);
         buf.position = start;
@@ -123,7 +115,6 @@
      *                if this buffer is based on an array, but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final int[] array() {
         return protectedArray();
@@ -135,14 +126,12 @@
      * <p>
      * The offset is the index of the array corresponds to the zero position of
      * the buffer.
-     * </p>
-     * 
+     *
      * @return the offset of the int array which this buffer is based on.
      * @exception ReadOnlyBufferException
      *                if this buffer is based on an array, but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final int arrayOffset() {
         return protectedArrayOffset();
@@ -170,15 +159,12 @@
      * The returned buffer is guaranteed to be a new instance, even this buffer
      * is read-only itself. The new buffer's position, limit, capacity and mark
      * are the same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means this
      * buffer's change of content will be visible to the new buffer. The two
      * buffer's position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a read-only version of this buffer.
-     * @since Android 1.0
      */
     public abstract IntBuffer asReadOnlyBuffer();
 
@@ -188,12 +174,10 @@
      * The remaining ints will be moved to the head of the buffer, starting from
      * position zero. Then the position is set to {@code remaining()}; the
      * limit is set to capacity; the mark is cleared.
-     * </p>
-     * 
+     *
      * @return this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract IntBuffer compact();
 
@@ -208,7 +192,6 @@
      *         than {@code other}.
      * @exception ClassCastException
      *                if {@code other} is not an int buffer.
-     * @since Android 1.0
      */
     public int compareTo(IntBuffer otherBuffer) {
         int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
@@ -237,15 +220,12 @@
      * The duplicated buffer's position, limit, capacity and mark are the same
      * as this buffer. The duplicated buffer's read-only property and byte order
      * are the same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a duplicated buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract IntBuffer duplicate();
 
@@ -255,14 +235,13 @@
      * If {@code other} is not a int buffer then {@code false} is returned. Two
      * int buffers are equal if and only if their remaining ints are exactly the
      * same. Position, limit, capacity and mark are not considered.
-     * </p>
-     * 
+     *
      * @param other
      *            the object to compare with this int buffer.
      * @return {@code true} if this int buffer is equal to {@code other},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object other) {
         if (!(other instanceof IntBuffer)) {
             return false;
@@ -289,7 +268,6 @@
      * @return the int at the current position.
      * @exception BufferUnderflowException
      *                if the position is equal or greater than limit.
-     * @since Android 1.0
      */
     public abstract int get();
 
@@ -299,14 +277,12 @@
      * <p>
      * Calling this method has the same effect as
      * {@code get(dest, 0, dest.length)}.
-     * </p>
-     * 
+     *
      * @param dest
      *            the destination int array.
      * @return this buffer.
      * @exception BufferUnderflowException
      *                if {@code dest.length} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public IntBuffer get(int[] dest) {
         return get(dest, 0, dest.length);
@@ -330,11 +306,10 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception BufferUnderflowException
      *                if {@code len} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public IntBuffer get(int[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)len + (long)off > length) {
+        if (off < 0 || len < 0 || (long) len + (long) off > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
@@ -354,16 +329,14 @@
      * @return an int at the specified index.
      * @exception IndexOutOfBoundsException
      *                if index is invalid.
-     * @since Android 1.0
      */
     public abstract int get(int index);
 
     /**
      * Indicates whether this buffer is based on a int array and is read/write.
-     * 
+     *
      * @return {@code true} if this buffer is based on a int array and provides
      *         read/write access, {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean hasArray() {
         return protectedHasArray();
@@ -372,10 +345,10 @@
     /**
      * Calculates this buffer's hash code from the remaining chars. The
      * position, limit, capacity and mark don't affect the hash code.
-     * 
+     *
      * @return the hash code calculated from the remaining ints.
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         int myPosition = position;
         int hash = 0;
@@ -392,11 +365,9 @@
      * <p>
      * An int buffer is direct if it is based on a byte buffer and the byte
      * buffer is direct.
-     * </p>
-     * 
+     *
      * @return {@code true} if this buffer is direct, {@code false} otherwise.
-     * @since Android 1.0
-     */    
+     */
     public abstract boolean isDirect();
 
     /**
@@ -405,11 +376,9 @@
      * <p>
      * If this buffer is not based on a byte buffer, then always return the
      * platform's native byte order.
-     * </p>
-     * 
+     *
      * @return the byte order used by this buffer when converting ints from/to
      *         bytes.
-     * @since Android 1.0
      */
     public abstract ByteOrder order();
 
@@ -445,7 +414,6 @@
      *                if position is equal or greater than limit.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract IntBuffer put(int i);
 
@@ -455,8 +423,7 @@
      * <p>
      * Calling this method has the same effect as
      * {@code put(src, 0, src.length)}.
-     * </p>
-     * 
+     *
      * @param src
      *            the source int array.
      * @return this buffer.
@@ -464,7 +431,6 @@
      *                if {@code remaining()} is less than {@code src.length}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public final IntBuffer put(int[] src) {
         return put(src, 0, src.length);
@@ -490,14 +456,13 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public IntBuffer put(int[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)len + (long)off > length) {
+        if (off < 0 || len < 0 || (long) len + (long) off > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
@@ -522,7 +487,6 @@
      *                if {@code src} is this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public IntBuffer put(IntBuffer src) {
         if (src == this) {
@@ -550,7 +514,6 @@
      *                if index is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract IntBuffer put(int index, int i);
 
@@ -562,15 +525,12 @@
      * The new buffer's position will be 0, limit will be its capacity, and its
      * mark is cleared. The new buffer's read-only property and byte order are
      * same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
      * 
      * @return a sliced buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract IntBuffer slice();
 
@@ -578,10 +538,10 @@
      * Returns a string represents of the state of this int buffer.
      * 
      * @return a string represents of the state of this int buffer.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         buf.append(getClass().getName());
         buf.append(", status: capacity="); //$NON-NLS-1$
         buf.append(capacity());
diff --git a/nio/src/main/java/java/nio/IntToByteBufferAdapter.java b/nio/src/main/java/java/nio/IntToByteBufferAdapter.java
index e77bec6..0631de4 100644
--- a/nio/src/main/java/java/nio/IntToByteBufferAdapter.java
+++ b/nio/src/main/java/java/nio/IntToByteBufferAdapter.java
@@ -16,11 +16,8 @@
 
 package java.nio;
 
-// BEGIN android-added
-// copied from newer version of harmony
 import org.apache.harmony.nio.internal.DirectBuffer;
 import org.apache.harmony.luni.platform.PlatformAddress;
-// END android-added
 
 /**
  * This class wraps a byte buffer to be a int buffer.
@@ -35,10 +32,7 @@
  * </p>
  * 
  */
-// BEGIN android-changed
-// copied from newer version of harmony
 final class IntToByteBufferAdapter extends IntBuffer implements DirectBuffer {
-// END android-changed
 
     static IntBuffer wrap(ByteBuffer byteBuffer) {
         return new IntToByteBufferAdapter(byteBuffer.slice());
@@ -52,15 +46,12 @@
         this.byteBuffer.clear();
     }
 
-    // BEGIN android-added
-    // copied from newer version of harmony
     public int getByteCapacity() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getByteCapacity();
-        } else {
-            assert false : byteBuffer;
-            return -1;
-        }            
+            return ((DirectBuffer) byteBuffer).getByteCapacity();
+        }
+        assert false : byteBuffer;
+        return -1;
     }
 
     public PlatformAddress getEffectiveAddress() {
@@ -70,47 +61,44 @@
             effectiveDirectAddress = addr.toInt();
             return addr;
             // END android-changed
-        } else {
-            assert false : byteBuffer;
-            return null;
         }
+        assert false : byteBuffer;
+        return null;
     }
-            
+
     public PlatformAddress getBaseAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getBaseAddress();
-        } else {
-            assert false : byteBuffer;
-            return null;
+            return ((DirectBuffer) byteBuffer).getBaseAddress();
         }
+        assert false : byteBuffer;
+        return null;
     }
-            
+
     public boolean isAddressValid() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).isAddressValid();
-        } else {
-            assert false : byteBuffer;
-            return false;
+            return ((DirectBuffer) byteBuffer).isAddressValid();
         }
+        assert false : byteBuffer;
+        return false;
     }
 
     public void addressValidityCheck() {
         if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).addressValidityCheck();
+            ((DirectBuffer) byteBuffer).addressValidityCheck();
         } else {
             assert false : byteBuffer;
         }
     }
-            
+
     public void free() {
         if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).free();
+            ((DirectBuffer) byteBuffer).free();
         } else {
             assert false : byteBuffer;
-        }   
+        }
     }
-    // END android-added
 
+    @Override
     public IntBuffer asReadOnlyBuffer() {
         IntToByteBufferAdapter buf = new IntToByteBufferAdapter(byteBuffer
                 .asReadOnlyBuffer());
@@ -120,6 +108,7 @@
         return buf;
     }
 
+    @Override
     public IntBuffer compact() {
         if (byteBuffer.isReadOnly()) {
             throw new ReadOnlyBufferException();
@@ -134,6 +123,7 @@
         return this;
     }
 
+    @Override
     public IntBuffer duplicate() {
         IntToByteBufferAdapter buf = new IntToByteBufferAdapter(byteBuffer
                 .duplicate());
@@ -143,6 +133,7 @@
         return buf;
     }
 
+    @Override
     public int get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -150,6 +141,7 @@
         return byteBuffer.getInt(position++ << 2);
     }
 
+    @Override
     public int get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -157,30 +149,37 @@
         return byteBuffer.getInt(index << 2);
     }
 
+    @Override
     public boolean isDirect() {
         return byteBuffer.isDirect();
     }
 
+    @Override
     public boolean isReadOnly() {
         return byteBuffer.isReadOnly();
     }
 
+    @Override
     public ByteOrder order() {
         return byteBuffer.order();
     }
 
+    @Override
     protected int[] protectedArray() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public IntBuffer put(int c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -189,6 +188,7 @@
         return this;
     }
 
+    @Override
     public IntBuffer put(int index, int c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -212,6 +212,7 @@
     }
     // END android-added
 
+    @Override
     public IntBuffer slice() {
         byteBuffer.limit(limit << 2);
         byteBuffer.position(position << 2);
diff --git a/nio/src/main/java/java/nio/InvalidMarkException.java b/nio/src/main/java/java/nio/InvalidMarkException.java
index 530d9cf..ff41705 100644
--- a/nio/src/main/java/java/nio/InvalidMarkException.java
+++ b/nio/src/main/java/java/nio/InvalidMarkException.java
@@ -16,12 +16,9 @@
 
 package java.nio;
 
-
 /**
  * An {@code InvalidMarkException} is thrown when {@code reset()} is called on a
  * buffer, but no mark has been set previously.
- * 
- * @since Android 1.0
  */
 public class InvalidMarkException extends IllegalStateException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs an {@code InvalidMarkException}.
-     * 
-     * @since Android 1.0
      */
     public InvalidMarkException() {
         super();
diff --git a/nio/src/main/java/java/nio/LongArrayBuffer.java b/nio/src/main/java/java/nio/LongArrayBuffer.java
index efd259c..46c36e4 100644
--- a/nio/src/main/java/java/nio/LongArrayBuffer.java
+++ b/nio/src/main/java/java/nio/LongArrayBuffer.java
@@ -49,6 +49,7 @@
         this.offset = offset;
     }
 
+    @Override
     public final long get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -56,6 +57,7 @@
         return backingArray[offset + position++];
     }
 
+    @Override
     public final long get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -63,23 +65,26 @@
         return backingArray[offset + index];
     }
 
+    @Override
     public final LongBuffer get(long[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)len + (long)off > length) {
+        if (off < 0 || len < 0 || (long) len + (long) off > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
-        System.arraycopy(backingArray, offset+position, dest, off, len);
+        System.arraycopy(backingArray, offset + position, dest, off, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public final boolean isDirect() {
         return false;
     }
 
+    @Override
     public final ByteOrder order() {
         return ByteOrder.nativeOrder();
     }
diff --git a/nio/src/main/java/java/nio/LongBuffer.java b/nio/src/main/java/java/nio/LongBuffer.java
index b0bf7ea..eecbf5e 100644
--- a/nio/src/main/java/java/nio/LongBuffer.java
+++ b/nio/src/main/java/java/nio/LongBuffer.java
@@ -21,7 +21,6 @@
  * A buffer of longs.
  * <p>
  * A long buffer can be created in either of the following ways:
- * </p>
  * <ul>
  * <li>{@link #allocate(int) Allocate} a new long array and create a buffer
  * based on it;</li>
@@ -30,10 +29,9 @@
  * <li>Use {@link java.nio.ByteBuffer#asLongBuffer() ByteBuffer.asLongBuffer}
  * to create a long buffer based on a byte buffer.</li>
  * </ul>
- * 
- * @since Android 1.0
  */
-public abstract class LongBuffer extends Buffer implements Comparable<LongBuffer> {
+public abstract class LongBuffer extends Buffer implements
+        Comparable<LongBuffer> {
 
     /**
      * Creates a long buffer based on a newly allocated long array.
@@ -43,7 +41,6 @@
      * @return the created long buffer.
      * @throws IllegalArgumentException
      *             if {@code capacity} is less than zero.
-     * @since Android 1.0
      */
     public static LongBuffer allocate(int capacity) {
         if (capacity < 0) {
@@ -57,12 +54,10 @@
      * <p>
      * Calling this method has the same effect as
      * {@code wrap(array, 0, array.length)}.
-     * </p>
-     * 
+     *
      * @param array
      *            the long array which the new buffer will be based on.
      * @return the created long buffer.
-     * @since Android 1.0
      */
     public static LongBuffer wrap(long[] array) {
         return wrap(array, 0, array.length);
@@ -73,8 +68,7 @@
      * <p>
      * The new buffer's position will be {@code start}, limit will be
      * {@code start + len}, capacity will be the length of the array.
-     * </p>
-     * 
+     *
      * @param array
      *            the long array which the new buffer will be based on.
      * @param start
@@ -86,15 +80,14 @@
      * @return the created long buffer.
      * @exception IndexOutOfBoundsException
      *                if either {@code start} or {@code len} is invalid.
-     * @since Android 1.0
      */
     public static LongBuffer wrap(long[] array, int start, int len) {
-                if (array == null) {
-                        throw new NullPointerException();
-                }
-                if (start < 0 || len < 0 || (long)len + (long)start > array.length) {
-                        throw new IndexOutOfBoundsException();
-                }
+        if (array == null) {
+            throw new NullPointerException();
+        }
+        if (start < 0 || len < 0 || (long) len + (long) start > array.length) {
+            throw new IndexOutOfBoundsException();
+        }
 
         LongBuffer buf = BufferFactory.newLongBuffer(array);
         buf.position = start;
@@ -124,7 +117,6 @@
      *                if this buffer is based on an array, but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final long[] array() {
         return protectedArray();
@@ -136,14 +128,12 @@
      * <p>
      * The offset is the index of the array and corresponds to the zero position
      * of the buffer.
-     * </p>
-     * 
+     *
      * @return the offset of the long array which this buffer is based on.
      * @exception ReadOnlyBufferException
      *                if this buffer is based on an array, but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final int arrayOffset() {
         return protectedArrayOffset();
@@ -171,15 +161,12 @@
      * The returned buffer is guaranteed to be a new instance, even if this
      * buffer is read-only itself. The new buffer's position, limit, capacity
      * and mark are the same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means this
      * buffer's change of content will be visible to the new buffer. The two
      * buffer's position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a read-only version of this buffer.
-     * @since Android 1.0
      */
     public abstract LongBuffer asReadOnlyBuffer();
 
@@ -189,12 +176,10 @@
      * The remaining longs will be moved to the head of the buffer, staring from
      * position zero. Then the position is set to {@code remaining()}; the
      * limit is set to capacity; the mark is cleared.
-     * </p>
-     * 
+     *
      * @return this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract LongBuffer compact();
 
@@ -209,7 +194,6 @@
      *         greater than {@code otherBuffer}
      * @exception ClassCastException
      *                if {@code otherBuffer} is not a long buffer.
-     * @since Android 1.0
      */
     public int compareTo(LongBuffer otherBuffer) {
         int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
@@ -238,15 +222,12 @@
      * The duplicated buffer's position, limit, capacity and mark are the same
      * as this buffer. The duplicated buffer's read-only property and byte order
      * are same as this buffer's, too.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a duplicated buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract LongBuffer duplicate();
 
@@ -256,14 +237,13 @@
      * If {@code other} is not a long buffer then {@code false} is returned. Two
      * long buffers are equal if and only if their remaining longs are exactly
      * the same. Position, limit, capacity and mark are not considered.
-     * </p>
-     * 
+     *
      * @param other
      *            the object to compare with this long buffer.
      * @return {@code true} if this long buffer is equal to {@code other},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object other) {
         if (!(other instanceof LongBuffer)) {
             return false;
@@ -290,7 +270,6 @@
      * @return the long at the current position.
      * @exception BufferUnderflowException
      *                if the position is equal or greater than limit.
-     * @since Android 1.0
      */
     public abstract long get();
 
@@ -300,14 +279,12 @@
      * <p>
      * Calling this method has the same effect as
      * {@code get(dest, 0, dest.length)}.
-     * </p>
      * 
      * @param dest
      *            the destination long array.
      * @return this buffer.
      * @exception BufferUnderflowException
      *                if {@code dest.length} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public LongBuffer get(long[] dest) {
         return get(dest, 0, dest.length);
@@ -331,14 +308,13 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception BufferUnderflowException
      *                if {@code len} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public LongBuffer get(long[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)len + (long)off > length) {
+        if (off < 0 || len < 0 || (long) len + (long) off > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
@@ -356,16 +332,14 @@
      * @return the long at the specified index.
      * @exception IndexOutOfBoundsException
      *                if index is invalid.
-     * @since Android 1.0
      */
     public abstract long get(int index);
 
     /**
      * Indicates whether this buffer is based on a long array and is read/write.
-     * 
+     *
      * @return {@code true} if this buffer is based on a long array and provides
      *         read/write access, {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean hasArray() {
         return protectedHasArray();
@@ -374,10 +348,10 @@
     /**
      * Calculates this buffer's hash code from the remaining chars. The
      * position, limit, capacity and mark don't affect the hash code.
-     * 
+     *
      * @return the hash code calculated from the remaining longs.
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         int myPosition = position;
         int hash = 0;
@@ -396,10 +370,8 @@
      * <p>
      * A long buffer is direct if it is based on a byte buffer and the byte
      * buffer is direct.
-     * </p>
-     * 
+     *
      * @return {@code true} if this buffer is direct, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isDirect();
 
@@ -409,11 +381,9 @@
      * <p>
      * If this buffer is not based on a byte buffer, then always return the
      * platform's native byte order.
-     * </p>
-     * 
+     *
      * @return the byte order used by this buffer when converting longs from/to
      *         bytes.
-     * @since Android 1.0
      */
     public abstract ByteOrder order();
 
@@ -449,7 +419,6 @@
      *                if position is equal or greater than limit.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract LongBuffer put(long l);
 
@@ -459,8 +428,7 @@
      * <p>
      * Calling this method has the same effect as
      * {@code put(src, 0, src.length)}.
-     * </p>
-     * 
+     *
      * @param src
      *            the source long array.
      * @return this buffer.
@@ -468,7 +436,6 @@
      *                if {@code remaining()} is less than {@code src.length}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public final LongBuffer put(long[] src) {
         return put(src, 0, src.length);
@@ -494,14 +461,13 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public LongBuffer put(long[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)len + (long)off > length) {
+        if (off < 0 || len < 0 || (long) len + (long) off > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
@@ -526,7 +492,6 @@
      *                if {@code src} is this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public LongBuffer put(LongBuffer src) {
         if (src == this) {
@@ -554,7 +519,6 @@
      *                if index is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract LongBuffer put(int index, long l);
 
@@ -566,15 +530,12 @@
      * The new buffer's position will be 0, limit will be its capacity, and its
      * mark is cleared. The new buffer's read-only property and byte order are
      * same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a sliced buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract LongBuffer slice();
 
@@ -582,10 +543,10 @@
      * Returns a string representing the state of this long buffer.
      * 
      * @return a string representing the state of this long buffer.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         buf.append(getClass().getName());
         buf.append(", status: capacity="); //$NON-NLS-1$
         buf.append(capacity());
diff --git a/nio/src/main/java/java/nio/LongToByteBufferAdapter.java b/nio/src/main/java/java/nio/LongToByteBufferAdapter.java
index bcdeb2b..8b07ac5 100644
--- a/nio/src/main/java/java/nio/LongToByteBufferAdapter.java
+++ b/nio/src/main/java/java/nio/LongToByteBufferAdapter.java
@@ -16,11 +16,8 @@
 
 package java.nio;
 
-// BEGIN android-added
-// copied from newer version of harmony
 import org.apache.harmony.nio.internal.DirectBuffer;
 import org.apache.harmony.luni.platform.PlatformAddress;
-// END android-added
 
 /**
  * This class wraps a byte buffer to be a long buffer.
@@ -33,12 +30,9 @@
  * The adapter extends Buffer, thus has its own position and limit.</li>
  * </ul>
  * </p>
- * 
+ *
  */
-// BEGIN android-changed
-// copied from newer version of harmony
 final class LongToByteBufferAdapter extends LongBuffer implements DirectBuffer {
-// END android-changed
 
     static LongBuffer wrap(ByteBuffer byteBuffer) {
         return new LongToByteBufferAdapter(byteBuffer.slice());
@@ -52,15 +46,12 @@
         this.byteBuffer.clear();
     }
 
-    // BEGIN android-added
-    // copied from newer version of harmony
     public int getByteCapacity() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getByteCapacity();
-        } else {
-            assert false : byteBuffer;
-            return -1;
-        }            
+            return ((DirectBuffer) byteBuffer).getByteCapacity();
+        }
+        assert false : byteBuffer;
+        return -1;
     }
 
     public PlatformAddress getEffectiveAddress() {
@@ -70,47 +61,44 @@
             effectiveDirectAddress = addr.toInt();
             return addr;
             // END android-changed
-        } else {
-            assert false : byteBuffer;
-            return null;
         }
+        assert false : byteBuffer;
+        return null;
     }
 
     public PlatformAddress getBaseAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getBaseAddress();
-        } else {
-            assert false : byteBuffer;
-            return null;
+            return ((DirectBuffer) byteBuffer).getBaseAddress();
         }
+        assert false : byteBuffer;
+        return null;
     }
-            
+
     public boolean isAddressValid() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).isAddressValid();
+            return ((DirectBuffer) byteBuffer).isAddressValid();
+        }
+        assert false : byteBuffer;
+        return false;
+    }
+
+    public void addressValidityCheck() {
+        if (byteBuffer instanceof DirectBuffer) {
+            ((DirectBuffer) byteBuffer).addressValidityCheck();
         } else {
             assert false : byteBuffer;
-            return false;
         }
     }
 
-  public void addressValidityCheck() {
-        if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).addressValidityCheck();
-        } else {
-            assert false : byteBuffer;
-        }
-    }
-            
     public void free() {
         if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).free();
+            ((DirectBuffer) byteBuffer).free();
         } else {
             assert false : byteBuffer;
-        }   
+        }
     }
-    // END android-added
 
+    @Override
     public LongBuffer asReadOnlyBuffer() {
         LongToByteBufferAdapter buf = new LongToByteBufferAdapter(byteBuffer
                 .asReadOnlyBuffer());
@@ -120,6 +108,7 @@
         return buf;
     }
 
+    @Override
     public LongBuffer compact() {
         if (byteBuffer.isReadOnly()) {
             throw new ReadOnlyBufferException();
@@ -134,6 +123,7 @@
         return this;
     }
 
+    @Override
     public LongBuffer duplicate() {
         LongToByteBufferAdapter buf = new LongToByteBufferAdapter(byteBuffer
                 .duplicate());
@@ -143,6 +133,7 @@
         return buf;
     }
 
+    @Override
     public long get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -150,6 +141,7 @@
         return byteBuffer.getLong(position++ << 3);
     }
 
+    @Override
     public long get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -157,30 +149,37 @@
         return byteBuffer.getLong(index << 3);
     }
 
+    @Override
     public boolean isDirect() {
         return byteBuffer.isDirect();
     }
 
+    @Override
     public boolean isReadOnly() {
         return byteBuffer.isReadOnly();
     }
 
+    @Override
     public ByteOrder order() {
         return byteBuffer.order();
     }
 
+    @Override
     protected long[] protectedArray() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public LongBuffer put(long c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -189,6 +188,7 @@
         return this;
     }
 
+    @Override
     public LongBuffer put(int index, long c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -197,6 +197,7 @@
         return this;
     }
 
+    @Override
     public LongBuffer slice() {
         byteBuffer.limit(limit << 3);
         byteBuffer.position(position << 3);
diff --git a/nio/src/main/java/java/nio/MappedByteBuffer.java b/nio/src/main/java/java/nio/MappedByteBuffer.java
index 8f6727d..e995f67 100644
--- a/nio/src/main/java/java/nio/MappedByteBuffer.java
+++ b/nio/src/main/java/java/nio/MappedByteBuffer.java
@@ -21,7 +21,6 @@
 import org.apache.harmony.luni.platform.PlatformAddress;
 import org.apache.harmony.nio.internal.DirectBuffer;
 
-
 /**
  * {@code MappedByteBuffer} is a special kind of direct byte buffer which maps a
  * region of file to memory.
@@ -30,15 +29,11 @@
  * {@link java.nio.channels.FileChannel#map(java.nio.channels.FileChannel.MapMode, long, long) FileChannel.map}.
  * Once created, the mapping between the byte buffer and the file region remains
  * valid until the byte buffer is garbage collected.
- * </p>
  * <p>
  * All or part of a {@code MappedByteBuffer}'s content may change or become
  * inaccessible at any time, since the mapped file region can be modified by
  * another thread or process at any time. If this happens, the behavior of the
  * {@code MappedByteBuffer} is undefined.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class MappedByteBuffer extends ByteBuffer {
 
@@ -59,15 +54,15 @@
         super(capa);
         mapMode = mode;
         switch (mapMode) {
-        case IMemorySystem.MMAP_READ_ONLY:
-            wrapped = new ReadOnlyDirectByteBuffer(addr, capa, offset);
-            break;
-        case IMemorySystem.MMAP_READ_WRITE:
-        case IMemorySystem.MMAP_WRITE_COPY:
-            wrapped = new ReadWriteDirectByteBuffer(addr, capa, offset);
-            break;
-        default:
-            throw new IllegalArgumentException();
+            case IMemorySystem.MMAP_READ_ONLY:
+                wrapped = new ReadOnlyDirectByteBuffer(addr, capa, offset);
+                break;
+            case IMemorySystem.MMAP_READ_WRITE:
+            case IMemorySystem.MMAP_WRITE_COPY:
+                wrapped = new ReadWriteDirectByteBuffer(addr, capa, offset);
+                break;
+            default:
+                throw new IllegalArgumentException();
         }
         addr.autoFree();
     }
@@ -79,10 +74,10 @@
      * 
      * @return {@code true} if this buffer's content is loaded, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public final boolean isLoaded() {
-        return ((MappedPlatformAddress)((DirectBuffer) wrapped).getBaseAddress()).mmapIsLoaded();
+        return ((MappedPlatformAddress) ((DirectBuffer) wrapped)
+                .getBaseAddress()).mmapIsLoaded();
     }
 
     /**
@@ -90,10 +85,10 @@
      * succeed.
      * 
      * @return this buffer.
-     * @since Android 1.0
      */
     public final MappedByteBuffer load() {
-        ((MappedPlatformAddress)((DirectBuffer) wrapped).getBaseAddress()).mmapLoad();
+        ((MappedPlatformAddress) ((DirectBuffer) wrapped).getBaseAddress())
+                .mmapLoad();
         return this;
     }
 
@@ -104,11 +99,11 @@
      * a remote device.
      * 
      * @return this buffer.
-     * @since Android 1.0
      */
     public final MappedByteBuffer force() {
         if (mapMode == IMemorySystem.MMAP_READ_WRITE) {
-            ((MappedPlatformAddress)((DirectBuffer) wrapped).getBaseAddress()).mmapFlush();
+            ((MappedPlatformAddress) ((DirectBuffer) wrapped).getBaseAddress())
+                    .mmapFlush();
         }
         return this;
     }
diff --git a/nio/src/main/java/java/nio/MappedByteBufferAdapter.java b/nio/src/main/java/java/nio/MappedByteBufferAdapter.java
index 84866dc..54e009b 100644
--- a/nio/src/main/java/java/nio/MappedByteBufferAdapter.java
+++ b/nio/src/main/java/java/nio/MappedByteBufferAdapter.java
@@ -16,7 +16,6 @@
  */
 
 // BEGIN android-note
-// updated to a newer version of harmony
 // added some missing updates on position and limit
 // END android-note
 
@@ -25,8 +24,8 @@
 import org.apache.harmony.luni.platform.PlatformAddress;
 import org.apache.harmony.nio.internal.DirectBuffer;
 
-
-final class MappedByteBufferAdapter extends MappedByteBuffer implements DirectBuffer {
+final class MappedByteBufferAdapter extends MappedByteBuffer implements
+        DirectBuffer {
 
     private static final int CHAR_SIZE = 2;
 
@@ -39,7 +38,7 @@
     private static final int FLOAT_SIZE = 4;
 
     private static final int DOUBLE_SIZE = 8;
-    
+
     public MappedByteBufferAdapter(ByteBuffer buffer) {
         super(buffer);
     }
@@ -49,26 +48,32 @@
         super(addr, capa, offset, mode);
     }
 
+    @Override
     public CharBuffer asCharBuffer() {
         return this.wrapped.asCharBuffer();
     }
 
+    @Override
     public DoubleBuffer asDoubleBuffer() {
         return this.wrapped.asDoubleBuffer();
     }
 
+    @Override
     public FloatBuffer asFloatBuffer() {
         return this.wrapped.asFloatBuffer();
     }
 
+    @Override
     public IntBuffer asIntBuffer() {
         return this.wrapped.asIntBuffer();
     }
 
+    @Override
     public LongBuffer asLongBuffer() {
         return this.wrapped.asLongBuffer();
     }
 
+    @Override
     public ByteBuffer asReadOnlyBuffer() {
         MappedByteBufferAdapter buf = new MappedByteBufferAdapter(this.wrapped
                 .asReadOnlyBuffer());
@@ -78,10 +83,12 @@
         return buf;
     }
 
+    @Override
     public ShortBuffer asShortBuffer() {
         return this.wrapped.asShortBuffer();
     }
 
+    @Override
     public ByteBuffer compact() {
         if (this.wrapped.isReadOnly()) {
             throw new ReadOnlyBufferException();
@@ -96,6 +103,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer duplicate() {
         MappedByteBufferAdapter buf = new MappedByteBufferAdapter(this.wrapped
                 .duplicate());
@@ -105,20 +113,23 @@
         return buf;
     }
 
+    @Override
     public byte get() {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
-        byte result = this.wrapped.get(); 
+        byte result = this.wrapped.get();
         this.position++;
         return result;
     }
 
+    @Override
     public byte get(int index) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
         return this.wrapped.get(index);
     }
 
+    @Override
     public char getChar() {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -127,12 +138,14 @@
         return result;
     }
 
+    @Override
     public char getChar(int index) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
         return this.wrapped.getChar(index);
     }
 
+    @Override
     public double getDouble() {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -141,6 +154,7 @@
         return result;
     }
 
+    @Override
     public double getDouble(int index) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -155,6 +169,7 @@
         // END android-changed
     }
 
+    @Override
     public float getFloat() {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -163,12 +178,14 @@
         return result;
     }
 
+    @Override
     public float getFloat(int index) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
         return this.wrapped.getFloat(index);
     }
 
+    @Override
     public int getInt() {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -177,12 +194,14 @@
         return result;
     }
 
+    @Override
     public int getInt(int index) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
         return this.wrapped.getInt(index);
     }
 
+    @Override
     public long getLong() {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -191,12 +210,14 @@
         return result;
     }
 
+    @Override
     public long getLong(int index) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
         return this.wrapped.getLong(index);
     }
 
+    @Override
     public short getShort() {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -205,25 +226,30 @@
         return result;
     }
 
+    @Override
     public short getShort(int index) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
         return this.wrapped.getShort(index);
     }
 
+    @Override
     public boolean isDirect() {
         return true;
     }
 
+    @Override
     public boolean isReadOnly() {
         return this.wrapped.isReadOnly();
     }
 
+    @Override
     ByteBuffer orderImpl(ByteOrder byteOrder) {
         super.orderImpl(byteOrder);
         return this.wrapped.order(byteOrder);
     }
 
+    @Override
     public ByteBuffer put(byte b) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -232,6 +258,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer put(byte[] src, int off, int len) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -240,6 +267,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer put(int index, byte b) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -247,6 +275,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putChar(char value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -255,6 +284,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putChar(int index, char value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -262,6 +292,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putDouble(double value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -270,6 +301,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putDouble(int index, double value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -277,6 +309,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putFloat(float value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -285,6 +318,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putFloat(int index, float value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -292,6 +326,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putInt(int index, int value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -299,6 +334,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putInt(int value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -307,6 +343,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putLong(int index, long value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -314,6 +351,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putLong(long value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -322,6 +360,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putShort(int index, short value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -329,6 +368,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putShort(short value) {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -337,6 +377,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer slice() {
         this.wrapped.limit(this.limit);
         this.wrapped.position(this.position);
@@ -346,14 +387,17 @@
         return result;
     }
 
+    @Override
     byte[] protectedArray() {
         return this.wrapped.protectedArray();
     }
 
+    @Override
     int protectedArrayOffset() {
         return this.wrapped.protectedArrayOffset();
     }
 
+    @Override
     boolean protectedHasArray() {
         return this.wrapped.protectedHasArray();
     }
diff --git a/nio/src/main/java/java/nio/ReadOnlyBufferException.java b/nio/src/main/java/java/nio/ReadOnlyBufferException.java
index 62e2d5f..f860e3c 100644
--- a/nio/src/main/java/java/nio/ReadOnlyBufferException.java
+++ b/nio/src/main/java/java/nio/ReadOnlyBufferException.java
@@ -16,12 +16,9 @@
 
 package java.nio;
 
-
 /**
  * A {@code ReadOnlyBufferException} is thrown when some write operation is
  * called on a read-only buffer.
- * 
- * @since Android 1.0
  */
 public class ReadOnlyBufferException extends UnsupportedOperationException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs a {@code ReadOnlyBufferException}.
-     * 
-     * @since Android 1.0
      */
     public ReadOnlyBufferException() {
         super();
diff --git a/nio/src/main/java/java/nio/ReadOnlyCharArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyCharArrayBuffer.java
index 461ea4f..54ef89f 100644
--- a/nio/src/main/java/java/nio/ReadOnlyCharArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadOnlyCharArrayBuffer.java
@@ -44,57 +44,71 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public CharBuffer asReadOnlyBuffer() {
         return duplicate();
     }
 
+    @Override
     public CharBuffer compact() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public CharBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return true;
     }
 
+    @Override
     protected char[] protectedArray() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public CharBuffer put(char c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public CharBuffer put(int index, char c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public final CharBuffer put(char[] src, int off, int len) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public final CharBuffer put(CharBuffer src) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public CharBuffer put(String src, int start, int end) {
-        if ((start < 0 ) || (end < 0) || (long)start + (long)end > src.length()) {
+        if ((start < 0) || (end < 0)
+                || (long) start + (long) end > src.length()) {
             throw new IndexOutOfBoundsException();
         }
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public CharBuffer slice() {
         return new ReadOnlyCharArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadOnlyDirectByteBuffer.java b/nio/src/main/java/java/nio/ReadOnlyDirectByteBuffer.java
index bc0e1cc..ffa6e41 100644
--- a/nio/src/main/java/java/nio/ReadOnlyDirectByteBuffer.java
+++ b/nio/src/main/java/java/nio/ReadOnlyDirectByteBuffer.java
@@ -52,79 +52,98 @@
             int offset) {
         super(new SafeAddress(address), capacity, offset);
     }
-    
+
+    @Override
     public ByteBuffer asReadOnlyBuffer() {
         return copy(this, mark);
     }
 
+    @Override
     public ByteBuffer compact() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return true;
     }
 
+    @Override
     public ByteBuffer put(byte value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer put(int index, byte value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer put(byte[] src, int off, int len) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public ByteBuffer putDouble(double value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putDouble(int index, double value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putFloat(float value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putFloat(int index, float value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putInt(int value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putInt(int index, int value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putLong(int index, long value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putLong(long value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putShort(int index, short value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putShort(short value) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public ByteBuffer put(ByteBuffer buf) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer slice() {
         ReadOnlyDirectByteBuffer buf = new ReadOnlyDirectByteBuffer(
                 safeAddress, remaining(), offset + position);
diff --git a/nio/src/main/java/java/nio/ReadOnlyDoubleArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyDoubleArrayBuffer.java
index 4f0b5d2..f71899b 100644
--- a/nio/src/main/java/java/nio/ReadOnlyDoubleArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadOnlyDoubleArrayBuffer.java
@@ -46,50 +46,62 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public DoubleBuffer asReadOnlyBuffer() {
         return duplicate();
     }
 
+    @Override
     public DoubleBuffer compact() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public DoubleBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return true;
     }
 
+    @Override
     protected double[] protectedArray() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public DoubleBuffer put(double c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public DoubleBuffer put(int index, double c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public final DoubleBuffer put(double[] src, int off, int len) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public final DoubleBuffer put(DoubleBuffer buf) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public DoubleBuffer slice() {
         return new ReadOnlyDoubleArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadOnlyFloatArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyFloatArrayBuffer.java
index 7559ffa..e8fb7d8 100644
--- a/nio/src/main/java/java/nio/ReadOnlyFloatArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadOnlyFloatArrayBuffer.java
@@ -44,50 +44,62 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public FloatBuffer asReadOnlyBuffer() {
         return duplicate();
     }
 
+    @Override
     public FloatBuffer compact() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public FloatBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return true;
     }
 
+    @Override
     protected float[] protectedArray() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public FloatBuffer put(float c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public FloatBuffer put(int index, float c) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public FloatBuffer put(FloatBuffer buf) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public final FloatBuffer put(float[] src, int off, int len) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public FloatBuffer slice() {
         return new ReadOnlyFloatArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadOnlyHeapByteBuffer.java b/nio/src/main/java/java/nio/ReadOnlyHeapByteBuffer.java
index 857ecff..fba5e04 100644
--- a/nio/src/main/java/java/nio/ReadOnlyHeapByteBuffer.java
+++ b/nio/src/main/java/java/nio/ReadOnlyHeapByteBuffer.java
@@ -45,90 +45,112 @@
         super(backingArray, capacity, arrayOffset);
     }
 
+    @Override
     public ByteBuffer asReadOnlyBuffer() {
         return copy(this, mark);
     }
 
+    @Override
     public ByteBuffer compact() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return true;
     }
 
+    @Override
     protected byte[] protectedArray() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public ByteBuffer put(byte b) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer put(int index, byte b) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer put(byte[] src, int off, int len) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public ByteBuffer putDouble(double value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putDouble(int index, double value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putFloat(float value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putFloat(int index, float value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putInt(int value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putInt(int index, int value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putLong(int index, long value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putLong(long value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putShort(int index, short value) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer putShort(short value) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public ByteBuffer put(ByteBuffer buf) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ByteBuffer slice() {
         ReadOnlyHeapByteBuffer slice = new ReadOnlyHeapByteBuffer(backingArray,
                 remaining(), offset + position);
diff --git a/nio/src/main/java/java/nio/ReadOnlyIntArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyIntArrayBuffer.java
index ba9380e..cece133 100644
--- a/nio/src/main/java/java/nio/ReadOnlyIntArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadOnlyIntArrayBuffer.java
@@ -44,50 +44,62 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public IntBuffer asReadOnlyBuffer() {
         return duplicate();
     }
 
+    @Override
     public IntBuffer compact() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public IntBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return true;
     }
 
+    @Override
     protected int[] protectedArray() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public IntBuffer put(int c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public IntBuffer put(int index, int c) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public IntBuffer put(IntBuffer buf) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public final IntBuffer put(int[] src, int off, int len) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public IntBuffer slice() {
         return new ReadOnlyIntArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadOnlyLongArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyLongArrayBuffer.java
index 76c1a4a..671f84f 100644
--- a/nio/src/main/java/java/nio/ReadOnlyLongArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadOnlyLongArrayBuffer.java
@@ -44,50 +44,62 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public LongBuffer asReadOnlyBuffer() {
         return duplicate();
     }
 
+    @Override
     public LongBuffer compact() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public LongBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return true;
     }
 
+    @Override
     protected long[] protectedArray() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public LongBuffer put(long c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public LongBuffer put(int index, long c) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public LongBuffer put(LongBuffer buf) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public final LongBuffer put(long[] src, int off, int len) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public LongBuffer slice() {
         return new ReadOnlyLongArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadOnlyShortArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyShortArrayBuffer.java
index 1a3bfd3..9730eb5 100644
--- a/nio/src/main/java/java/nio/ReadOnlyShortArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadOnlyShortArrayBuffer.java
@@ -44,50 +44,62 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public ShortBuffer asReadOnlyBuffer() {
         return duplicate();
     }
 
+    @Override
     public ShortBuffer compact() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ShortBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return true;
     }
 
+    @Override
     protected short[] protectedArray() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
-    
+
+    @Override
     public ShortBuffer put(ShortBuffer buf) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ShortBuffer put(short c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public ShortBuffer put(int index, short c) {
         throw new ReadOnlyBufferException();
     }
 
+    @Override
     public final ShortBuffer put(short[] src, int off, int len) {
         throw new ReadOnlyBufferException();
     }
-    
+
+    @Override
     public ShortBuffer slice() {
         return new ReadOnlyShortArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadWriteCharArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteCharArrayBuffer.java
index 08f79b2..584df53 100644
--- a/nio/src/main/java/java/nio/ReadWriteCharArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadWriteCharArrayBuffer.java
@@ -51,10 +51,12 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public CharBuffer asReadOnlyBuffer() {
         return ReadOnlyCharArrayBuffer.copy(this, mark);
     }
 
+    @Override
     public CharBuffer compact() {
         System.arraycopy(backingArray, position + offset, backingArray, offset,
                 remaining());
@@ -64,26 +66,32 @@
         return this;
     }
 
+    @Override
     public CharBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return false;
     }
 
+    @Override
     protected char[] protectedArray() {
         return backingArray;
     }
 
+    @Override
     protected int protectedArrayOffset() {
         return offset;
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return true;
     }
 
+    @Override
     public CharBuffer put(char c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -92,6 +100,7 @@
         return this;
     }
 
+    @Override
     public CharBuffer put(int index, char c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -100,19 +109,21 @@
         return this;
     }
 
+    @Override
     public CharBuffer put(char[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)len + (long)off > length) {
+        if (off < 0 || len < 0 || (long) len + (long) off > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
-        System.arraycopy(src, off, backingArray, offset+position, len);
+        System.arraycopy(src, off, backingArray, offset + position, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public CharBuffer slice() {
         return new ReadWriteCharArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadWriteDirectByteBuffer.java b/nio/src/main/java/java/nio/ReadWriteDirectByteBuffer.java
index 95b4ebc..d976994 100644
--- a/nio/src/main/java/java/nio/ReadWriteDirectByteBuffer.java
+++ b/nio/src/main/java/java/nio/ReadWriteDirectByteBuffer.java
@@ -65,17 +65,19 @@
             int anOffset) {
         super(new SafeAddress(address), aCapacity, anOffset);
     }
-    
+
     // BEGIN android-added
     int getAddress() {
         return this.safeAddress.address.toInt();
     }
     // END android-added
-    
+
+    @Override
     public ByteBuffer asReadOnlyBuffer() {
         return ReadOnlyDirectByteBuffer.copy(this, mark);
     }
 
+    @Override
     public ByteBuffer compact() {
         PlatformAddress effectiveAddress = getEffectiveAddress();
         effectiveAddress.offsetBytes(position).moveTo(effectiveAddress,
@@ -86,14 +88,17 @@
         return this;
     }
 
+    @Override
     public ByteBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return false;
     }
 
+    @Override
     public ByteBuffer put(byte value) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -102,6 +107,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer put(int index, byte value) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -117,29 +123,26 @@
      * 
      * @see java.nio.ByteBuffer#put(byte[], int, int)
      */
+    @Override
     public ByteBuffer put(byte[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
-        if (isReadOnly()) {
-            throw new ReadOnlyBufferException();
-        }
-        getBaseAddress().setByteArray(offset + position, src, off,
-                len);
+        getBaseAddress().setByteArray(offset + position, src, off, len);
         position += len;
         return this;
     }
-    
+
     // BEGIN android-added
     /**
      * Writes <code>short</code>s in the given short array, starting from the
      * specified offset, to the current position and increase the position by
      * the number of <code>short</code>s written.
-     * 
+     *
      * @param src
      *            The source short array
      * @param off
@@ -179,7 +182,7 @@
      * Writes <code>int</code>s in the given int array, starting from the
      * specified offset, to the current position and increase the position by
      * the number of <code>int</code>s written.
-     * 
+     *
      * @param src
      *            The source int array
      * @param off
@@ -215,7 +218,8 @@
         return this;
     }
     // END android-added
-    
+
+    @Override
     public ByteBuffer putDouble(double value) {
         int newPosition = position + 8;
         if (newPosition > limit) {
@@ -226,14 +230,16 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putDouble(int index, double value) {
-        if (index < 0 || (long)index + 8 > limit) {
+        if (index < 0 || (long) index + 8 > limit) {
             throw new IndexOutOfBoundsException();
         }
         getBaseAddress().setDouble(offset + index, value, order);
         return this;
     }
 
+    @Override
     public ByteBuffer putFloat(float value) {
         int newPosition = position + 4;
         if (newPosition > limit) {
@@ -244,14 +250,16 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putFloat(int index, float value) {
-        if (index < 0 || (long)index + 4 > limit) {
+        if (index < 0 || (long) index + 4 > limit) {
             throw new IndexOutOfBoundsException();
         }
         getBaseAddress().setFloat(offset + index, value, order);
         return this;
     }
 
+    @Override
     public ByteBuffer putInt(int value) {
         int newPosition = position + 4;
         if (newPosition > limit) {
@@ -262,14 +270,16 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putInt(int index, int value) {
-        if (index < 0 || (long)index + 4 > limit) {
+        if (index < 0 || (long) index + 4 > limit) {
             throw new IndexOutOfBoundsException();
         }
         getBaseAddress().setInt(offset + index, value, order);
         return this;
     }
 
+    @Override
     public ByteBuffer putLong(long value) {
         int newPosition = position + 8;
         if (newPosition > limit) {
@@ -280,14 +290,16 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putLong(int index, long value) {
-        if (index < 0 || (long)index + 8 > limit) {
+        if (index < 0 || (long) index + 8 > limit) {
             throw new IndexOutOfBoundsException();
         }
         getBaseAddress().setLong(offset + index, value, order);
         return this;
     }
 
+    @Override
     public ByteBuffer putShort(short value) {
         int newPosition = position + 2;
         if (newPosition > limit) {
@@ -298,14 +310,16 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putShort(int index, short value) {
-        if (index < 0 || (long)index + 2 > limit) {
+        if (index < 0 || (long) index + 2 > limit) {
             throw new IndexOutOfBoundsException();
         }
         getBaseAddress().setShort(offset + index, value, order);
         return this;
     }
 
+    @Override
     public ByteBuffer slice() {
         ReadWriteDirectByteBuffer buf = new ReadWriteDirectByteBuffer(
                 safeAddress, remaining(), offset + position);
diff --git a/nio/src/main/java/java/nio/ReadWriteDoubleArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteDoubleArrayBuffer.java
index 2933178..689f3a1 100644
--- a/nio/src/main/java/java/nio/ReadWriteDoubleArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadWriteDoubleArrayBuffer.java
@@ -54,10 +54,12 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public DoubleBuffer asReadOnlyBuffer() {
         return ReadOnlyDoubleArrayBuffer.copy(this, mark);
     }
 
+    @Override
     public DoubleBuffer compact() {
         System.arraycopy(backingArray, position + offset, backingArray, offset,
                 remaining());
@@ -67,26 +69,32 @@
         return this;
     }
 
+    @Override
     public DoubleBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return false;
     }
 
+    @Override
     protected double[] protectedArray() {
         return backingArray;
     }
 
+    @Override
     protected int protectedArrayOffset() {
         return offset;
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return true;
     }
 
+    @Override
     public DoubleBuffer put(double c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -95,6 +103,7 @@
         return this;
     }
 
+    @Override
     public DoubleBuffer put(int index, double c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -103,20 +112,21 @@
         return this;
     }
 
+    @Override
     public DoubleBuffer put(double[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
-        System.arraycopy(src, off, backingArray, offset
-                + position, len);
+        System.arraycopy(src, off, backingArray, offset + position, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public DoubleBuffer slice() {
         return new ReadWriteDoubleArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadWriteFloatArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteFloatArrayBuffer.java
index 49b0b11..50e8ce5 100644
--- a/nio/src/main/java/java/nio/ReadWriteFloatArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadWriteFloatArrayBuffer.java
@@ -54,10 +54,12 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public FloatBuffer asReadOnlyBuffer() {
         return ReadOnlyFloatArrayBuffer.copy(this, mark);
     }
 
+    @Override
     public FloatBuffer compact() {
         System.arraycopy(backingArray, position + offset, backingArray, offset,
                 remaining());
@@ -67,26 +69,32 @@
         return this;
     }
 
+    @Override
     public FloatBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return false;
     }
 
+    @Override
     protected float[] protectedArray() {
         return backingArray;
     }
 
+    @Override
     protected int protectedArrayOffset() {
         return offset;
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return true;
     }
 
+    @Override
     public FloatBuffer put(float c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -95,6 +103,7 @@
         return this;
     }
 
+    @Override
     public FloatBuffer put(int index, float c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -103,20 +112,21 @@
         return this;
     }
 
+    @Override
     public FloatBuffer put(float[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
-        System.arraycopy(src, off, backingArray, offset
-                + position, len);
+        System.arraycopy(src, off, backingArray, offset + position, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public FloatBuffer slice() {
         return new ReadWriteFloatArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadWriteHeapByteBuffer.java b/nio/src/main/java/java/nio/ReadWriteHeapByteBuffer.java
index af74054..677b439 100644
--- a/nio/src/main/java/java/nio/ReadWriteHeapByteBuffer.java
+++ b/nio/src/main/java/java/nio/ReadWriteHeapByteBuffer.java
@@ -16,8 +16,6 @@
 
 package java.nio;
 
-
-
 /**
  * HeapByteBuffer, ReadWriteHeapByteBuffer and ReadOnlyHeapByteBuffer compose
  * the implementation of array based byte buffers.
@@ -53,10 +51,12 @@
         super(backingArray, capacity, arrayOffset);
     }
 
+    @Override
     public ByteBuffer asReadOnlyBuffer() {
         return ReadOnlyHeapByteBuffer.copy(this, mark);
     }
 
+    @Override
     public ByteBuffer compact() {
         System.arraycopy(backingArray, position + offset, backingArray, offset,
                 remaining());
@@ -66,26 +66,32 @@
         return this;
     }
 
+    @Override
     public ByteBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return false;
     }
 
+    @Override
     protected byte[] protectedArray() {
         return backingArray;
     }
 
+    @Override
     protected int protectedArrayOffset() {
         return offset;
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return true;
     }
 
+    @Override
     public ByteBuffer put(byte b) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -94,6 +100,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer put(int index, byte b) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -109,8 +116,9 @@
      * 
      * @see java.nio.ByteBuffer#put(byte[], int, int)
      */
+    @Override
     public ByteBuffer put(byte[] src, int off, int len) {
-        if (off < 0 || len < 0 || (long)off + (long)len > src.length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > src.length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
@@ -119,28 +127,32 @@
         if (isReadOnly()) {
             throw new ReadOnlyBufferException();
         }
-        System.arraycopy(src, off, backingArray, offset
-                + position, len);
+        System.arraycopy(src, off, backingArray, offset + position, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public ByteBuffer putDouble(double value) {
         return putLong(Double.doubleToRawLongBits(value));
     }
 
+    @Override
     public ByteBuffer putDouble(int index, double value) {
         return putLong(index, Double.doubleToRawLongBits(value));
     }
 
+    @Override
     public ByteBuffer putFloat(float value) {
         return putInt(Float.floatToIntBits(value));
     }
 
+    @Override
     public ByteBuffer putFloat(int index, float value) {
         return putInt(index, Float.floatToIntBits(value));
     }
 
+    @Override
     public ByteBuffer putInt(int value) {
         int newPosition = position + 4;
         if (newPosition > limit) {
@@ -151,22 +163,25 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putInt(int index, int value) {
-        if (index < 0 || (long)index + 4 > limit) {
+        if (index < 0 || (long) index + 4 > limit) {
             throw new IndexOutOfBoundsException();
         }
         store(index, value);
         return this;
     }
 
+    @Override
     public ByteBuffer putLong(int index, long value) {
-        if (index < 0 || (long)index + 8 > limit) {
+        if (index < 0 || (long) index + 8 > limit) {
             throw new IndexOutOfBoundsException();
         }
         store(index, value);
         return this;
     }
 
+    @Override
     public ByteBuffer putLong(long value) {
         int newPosition = position + 8;
         if (newPosition > limit) {
@@ -177,14 +192,16 @@
         return this;
     }
 
+    @Override
     public ByteBuffer putShort(int index, short value) {
-        if (index < 0 || (long)index + 2 > limit) {
+        if (index < 0 || (long) index + 2 > limit) {
             throw new IndexOutOfBoundsException();
         }
         store(index, value);
         return this;
     }
 
+    @Override
     public ByteBuffer putShort(short value) {
         int newPosition = position + 2;
         if (newPosition > limit) {
@@ -195,6 +212,7 @@
         return this;
     }
 
+    @Override
     public ByteBuffer slice() {
         ReadWriteHeapByteBuffer slice = new ReadWriteHeapByteBuffer(
                 backingArray, remaining(), offset + position);
diff --git a/nio/src/main/java/java/nio/ReadWriteIntArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteIntArrayBuffer.java
index 005e45b..a4be0b5 100644
--- a/nio/src/main/java/java/nio/ReadWriteIntArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadWriteIntArrayBuffer.java
@@ -51,10 +51,12 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public IntBuffer asReadOnlyBuffer() {
         return ReadOnlyIntArrayBuffer.copy(this, mark);
     }
 
+    @Override
     public IntBuffer compact() {
         System.arraycopy(backingArray, position + offset, backingArray, offset,
                 remaining());
@@ -64,26 +66,32 @@
         return this;
     }
 
+    @Override
     public IntBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return false;
     }
 
+    @Override
     protected int[] protectedArray() {
         return backingArray;
     }
 
+    @Override
     protected int protectedArrayOffset() {
         return offset;
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return true;
     }
 
+    @Override
     public IntBuffer put(int c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -92,6 +100,7 @@
         return this;
     }
 
+    @Override
     public IntBuffer put(int index, int c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -100,20 +109,21 @@
         return this;
     }
 
+    @Override
     public IntBuffer put(int[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
-        System.arraycopy(src, off, backingArray, offset
-                + position, len);
+        System.arraycopy(src, off, backingArray, offset + position, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public IntBuffer slice() {
         return new ReadWriteIntArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadWriteLongArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteLongArrayBuffer.java
index ff2c588..2d8cdb0 100644
--- a/nio/src/main/java/java/nio/ReadWriteLongArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadWriteLongArrayBuffer.java
@@ -51,10 +51,12 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public LongBuffer asReadOnlyBuffer() {
         return ReadOnlyLongArrayBuffer.copy(this, mark);
     }
 
+    @Override
     public LongBuffer compact() {
         System.arraycopy(backingArray, position + offset, backingArray, offset,
                 remaining());
@@ -64,26 +66,32 @@
         return this;
     }
 
+    @Override
     public LongBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return false;
     }
 
+    @Override
     protected long[] protectedArray() {
         return backingArray;
     }
 
+    @Override
     protected int protectedArrayOffset() {
         return offset;
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return true;
     }
 
+    @Override
     public LongBuffer put(long c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -92,6 +100,7 @@
         return this;
     }
 
+    @Override
     public LongBuffer put(int index, long c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -100,20 +109,21 @@
         return this;
     }
 
+    @Override
     public LongBuffer put(long[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
-        System.arraycopy(src, off, backingArray, offset
-                + position, len);
+        System.arraycopy(src, off, backingArray, offset + position, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public LongBuffer slice() {
         return new ReadWriteLongArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ReadWriteShortArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteShortArrayBuffer.java
index 193bdb3..0abbaf4 100644
--- a/nio/src/main/java/java/nio/ReadWriteShortArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ReadWriteShortArrayBuffer.java
@@ -54,10 +54,12 @@
         super(capacity, backingArray, arrayOffset);
     }
 
+    @Override
     public ShortBuffer asReadOnlyBuffer() {
         return ReadOnlyShortArrayBuffer.copy(this, mark);
     }
 
+    @Override
     public ShortBuffer compact() {
         System.arraycopy(backingArray, position + offset, backingArray, offset,
                 remaining());
@@ -67,26 +69,32 @@
         return this;
     }
 
+    @Override
     public ShortBuffer duplicate() {
         return copy(this, mark);
     }
 
+    @Override
     public boolean isReadOnly() {
         return false;
     }
 
+    @Override
     protected short[] protectedArray() {
         return backingArray;
     }
 
+    @Override
     protected int protectedArrayOffset() {
         return offset;
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return true;
     }
 
+    @Override
     public ShortBuffer put(short c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -95,6 +103,7 @@
         return this;
     }
 
+    @Override
     public ShortBuffer put(int index, short c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -103,19 +112,21 @@
         return this;
     }
 
+    @Override
     public ShortBuffer put(short[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
-        System.arraycopy(src, off, backingArray, offset+position, len);
+        System.arraycopy(src, off, backingArray, offset + position, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public ShortBuffer slice() {
         return new ReadWriteShortArrayBuffer(remaining(), backingArray, offset
                 + position);
diff --git a/nio/src/main/java/java/nio/ShortArrayBuffer.java b/nio/src/main/java/java/nio/ShortArrayBuffer.java
index 54f8adb4..e7d42a0 100644
--- a/nio/src/main/java/java/nio/ShortArrayBuffer.java
+++ b/nio/src/main/java/java/nio/ShortArrayBuffer.java
@@ -49,6 +49,7 @@
         this.offset = offset;
     }
 
+    @Override
     public final short get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -56,6 +57,7 @@
         return backingArray[offset + position++];
     }
 
+    @Override
     public final short get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -63,24 +65,26 @@
         return backingArray[offset + index];
     }
 
+    @Override
     public final ShortBuffer get(short[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
             throw new BufferUnderflowException();
         }
-        System.arraycopy(backingArray, offset + position, dest,
-                off, len);
+        System.arraycopy(backingArray, offset + position, dest, off, len);
         position += len;
         return this;
     }
-    
+
+    @Override
     public final boolean isDirect() {
         return false;
     }
 
+    @Override
     public final ByteOrder order() {
         return ByteOrder.nativeOrder();
     }
diff --git a/nio/src/main/java/java/nio/ShortBuffer.java b/nio/src/main/java/java/nio/ShortBuffer.java
index 39f9ddf..22d1b25 100644
--- a/nio/src/main/java/java/nio/ShortBuffer.java
+++ b/nio/src/main/java/java/nio/ShortBuffer.java
@@ -21,7 +21,6 @@
  * A buffer of shorts.
  * <p>
  * A short buffer can be created in either of the following ways:
- * </p>
  * <ul>
  * <li>{@link #allocate(int) Allocate} a new short array and create a buffer
  * based on it;</li>
@@ -30,10 +29,9 @@
  * <li>Use {@link java.nio.ByteBuffer#asShortBuffer() ByteBuffer.asShortBuffer}
  * to create a short buffer based on a byte buffer.</li>
  * </ul>
- * 
- * @since Android 1.0
  */
-public abstract class ShortBuffer extends Buffer implements Comparable<ShortBuffer> {
+public abstract class ShortBuffer extends Buffer implements
+        Comparable<ShortBuffer> {
 
     /**
      * Creates a short buffer based on a newly allocated short array.
@@ -43,7 +41,6 @@
      * @return the created short buffer.
      * @throws IllegalArgumentException
      *             if {@code capacity} is less than zero.
-     * @since Android 1.0
      */
     public static ShortBuffer allocate(int capacity) {
         if (capacity < 0) {
@@ -57,12 +54,10 @@
      * <p>
      * Calling this method has the same effect as
      * {@code wrap(array, 0, array.length)}.
-     * </p>
-     * 
+     *
      * @param array
      *            the short array which the new buffer will be based on.
      * @return the created short buffer.
-     * @since Android 1.0
      */
     public static ShortBuffer wrap(short[] array) {
         return wrap(array, 0, array.length);
@@ -73,8 +68,7 @@
      * <p>
      * The new buffer's position will be {@code start}, limit will be
      * {@code start + len}, capacity will be the length of the array.
-     * </p>
-     * 
+     *
      * @param array
      *            the short array which the new buffer will be based on.
      * @param start
@@ -86,15 +80,14 @@
      * @return the created short buffer.
      * @exception IndexOutOfBoundsException
      *                if either {@code start} or {@code len} is invalid.
-     * @since Android 1.0
      */
     public static ShortBuffer wrap(short[] array, int start, int len) {
-                if (array == null) {
-                        throw new NullPointerException();
-                }
-                if (start< 0 || len < 0 || (long)start + (long)len > array.length) {
-                        throw new IndexOutOfBoundsException();
-                }
+        if (array == null) {
+            throw new NullPointerException();
+        }
+        if (start < 0 || len < 0 || (long) start + (long) len > array.length) {
+            throw new IndexOutOfBoundsException();
+        }
 
         ShortBuffer buf = BufferFactory.newShortBuffer(array);
         buf.position = start;
@@ -124,7 +117,6 @@
      *                if this buffer is based on an array, but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final short[] array() {
         return protectedArray();
@@ -136,14 +128,12 @@
      * <p>
      * The offset is the index of the array corresponding to the zero position
      * of the buffer.
-     * </p>
-     * 
+     *
      * @return the offset of the short array which this buffer is based on.
      * @exception ReadOnlyBufferException
      *                if this buffer is based on an array, but it is read-only.
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
-     * @since Android 1.0
      */
     public final int arrayOffset() {
         return protectedArrayOffset();
@@ -171,15 +161,12 @@
      * The returned buffer is guaranteed to be a new instance, even if this
      * buffer is read-only itself. The new buffer's position, limit, capacity
      * and mark are the same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means this
      * buffer's change of content will be visible to the new buffer. The two
      * buffer's position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a read-only version of this buffer.
-     * @since Android 1.0
      */
     public abstract ShortBuffer asReadOnlyBuffer();
 
@@ -189,12 +176,10 @@
      * The remaining shorts will be moved to the head of the buffer, starting
      * from position zero. Then the position is set to {@code remaining()}; the
      * limit is set to capacity; the mark is cleared.
-     * </p>
-     * 
+     *
      * @return this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ShortBuffer compact();
 
@@ -209,7 +194,6 @@
      *         greater than {@code otherBuffer}.
      * @exception ClassCastException
      *                if {@code otherBuffer} is not a short buffer.
-     * @since Android 1.0
      */
     public int compareTo(ShortBuffer otherBuffer) {
         int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
@@ -236,15 +220,12 @@
      * The duplicated buffer's position, limit, capacity and mark are the same
      * as this buffer. The duplicated buffer's read-only property and byte order
      * are the same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
-     * 
+     *
      * @return a duplicated buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract ShortBuffer duplicate();
 
@@ -254,14 +235,13 @@
      * If {@code other} is not a short buffer then {@code false} is returned.
      * Two short buffers are equal if and only if their remaining shorts are
      * exactly the same. Position, limit, capacity and mark are not considered.
-     * </p>
-     * 
+     *
      * @param other
      *            the object to compare with this short buffer.
      * @return {@code true} if this short buffer is equal to {@code other},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
+    @Override
     public boolean equals(Object other) {
         if (!(other instanceof ShortBuffer)) {
             return false;
@@ -289,7 +269,6 @@
      * @return the short at the current position.
      * @exception BufferUnderflowException
      *                if the position is equal or greater than limit.
-     * @since Android 1.0
      */
     public abstract short get();
 
@@ -299,14 +278,12 @@
      * <p>
      * Calling this method has the same effect as
      * {@code get(dest, 0, dest.length)}.
-     * </p>
-     * 
+     *
      * @param dest
      *            the destination short array.
      * @return this buffer.
      * @exception BufferUnderflowException
      *                if {@code dest.length} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public ShortBuffer get(short[] dest) {
         return get(dest, 0, dest.length);
@@ -330,11 +307,10 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception BufferUnderflowException
      *                if {@code len} is greater than {@code remaining()}.
-     * @since Android 1.0
      */
     public ShortBuffer get(short[] dest, int off, int len) {
         int length = dest.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
         if (len > remaining()) {
@@ -354,17 +330,15 @@
      * @return a short at the specified index.
      * @exception IndexOutOfBoundsException
      *                if index is invalid.
-     * @since Android 1.0
      */
     public abstract short get(int index);
 
     /**
      * Indicates whether this buffer is based on a short array and is
      * read/write.
-     * 
+     *
      * @return {@code true} if this buffer is based on a short array and
      *         provides read/write access, {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean hasArray() {
         return protectedHasArray();
@@ -373,10 +347,10 @@
     /**
      * Calculates this buffer's hash code from the remaining chars. The
      * position, limit, capacity and mark don't affect the hash code.
-     * 
+     *
      * @return the hash code calculated from the remaining shorts.
-     * @since Android 1.0
      */
+    @Override
     public int hashCode() {
         int myPosition = position;
         int hash = 0;
@@ -393,10 +367,8 @@
      * <p>
      * A short buffer is direct if it is based on a byte buffer and the byte
      * buffer is direct.
-     * </p>
-     * 
+     *
      * @return {@code true} if this buffer is direct, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isDirect();
 
@@ -406,11 +378,9 @@
      * <p>
      * If this buffer is not based on a byte buffer, then always return the
      * platform's native byte order.
-     * </p>
-     * 
+     *
      * @return the byte order used by this buffer when converting shorts from/to
      *         bytes.
-     * @since Android 1.0
      */
     public abstract ByteOrder order();
 
@@ -446,7 +416,6 @@
      *                if position is equal or greater than limit.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ShortBuffer put(short s);
 
@@ -456,8 +425,7 @@
      * <p>
      * Calling this method has the same effect as
      * {@code put(src, 0, src.length)}.
-     * </p>
-     * 
+     *
      * @param src
      *            the source short array.
      * @return this buffer.
@@ -465,7 +433,6 @@
      *                if {@code remaining()} is less than {@code src.length}.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public final ShortBuffer put(short[] src) {
         return put(src, 0, src.length);
@@ -491,14 +458,13 @@
      *                if either {@code off} or {@code len} is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public ShortBuffer put(short[] src, int off, int len) {
         int length = src.length;
-        if (off < 0 || len < 0 || (long)off + (long)len > length) {
+        if (off < 0 || len < 0 || (long) off + (long) len > length) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         if (len > remaining()) {
             throw new BufferOverflowException();
         }
@@ -523,7 +489,6 @@
      *                if {@code src} is this buffer.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public ShortBuffer put(ShortBuffer src) {
         if (src == this) {
@@ -551,7 +516,6 @@
      *                if index is invalid.
      * @exception ReadOnlyBufferException
      *                if no changes may be made to the contents of this buffer.
-     * @since Android 1.0
      */
     public abstract ShortBuffer put(int index, short s);
 
@@ -563,15 +527,12 @@
      * The new buffer's position will be 0, limit will be its capacity, and its
      * mark is cleared. The new buffer's read-only property and byte order are
      * same as this buffer's.
-     * </p>
      * <p>
      * The new buffer shares its content with this buffer, which means either
      * buffer's change of content will be visible to the other. The two buffer's
      * position, limit and mark are independent.
-     * </p>
      * 
      * @return a sliced buffer that shares its content with this buffer.
-     * @since Android 1.0
      */
     public abstract ShortBuffer slice();
 
@@ -579,10 +540,10 @@
      * Returns a string representing the state of this short buffer.
      * 
      * @return a string representing the state of this short buffer.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         buf.append(getClass().getName());
         buf.append(", status: capacity="); //$NON-NLS-1$
         buf.append(capacity());
diff --git a/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java b/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java
index a608bc9..f2a795f 100644
--- a/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java
+++ b/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java
@@ -16,11 +16,8 @@
 
 package java.nio;
 
-// BEGIN android-added
-// Copied from newer version of harmony
 import org.apache.harmony.nio.internal.DirectBuffer;
 import org.apache.harmony.luni.platform.PlatformAddress;
-// END android-added
 
 /**
  * This class wraps a byte buffer to be a short buffer.
@@ -33,12 +30,9 @@
  * The adapter extends Buffer, thus has its own position and limit.</li>
  * </ul>
  * </p>
- * 
  */
-// BEGIN android-changed
-// Copied from newer version of harmony
-final class ShortToByteBufferAdapter extends ShortBuffer implements DirectBuffer {
-// END android-changed
+final class ShortToByteBufferAdapter extends ShortBuffer implements
+        DirectBuffer {
 
     static ShortBuffer wrap(ByteBuffer byteBuffer) {
         return new ShortToByteBufferAdapter(byteBuffer.slice());
@@ -52,15 +46,12 @@
         this.byteBuffer.clear();
     }
 
-// BEGIN android-added
-// Copied from newer version of harmony
     public int getByteCapacity() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getByteCapacity();
-        } else {
-            assert false : byteBuffer;
-            return -1;
-        }            
+            return ((DirectBuffer) byteBuffer).getByteCapacity();
+        }
+        assert false : byteBuffer;
+        return -1;
     }
 
     public PlatformAddress getEffectiveAddress() {
@@ -70,47 +61,44 @@
             effectiveDirectAddress = addr.toInt();
             return addr;
             // END android-changed
-        } else {
-            assert false : byteBuffer;
-            return null;
         }
+        assert false : byteBuffer;
+        return null;
     }
 
     public PlatformAddress getBaseAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getBaseAddress();
-        } else {
-            assert false : byteBuffer;
-            return null;
+            return ((DirectBuffer) byteBuffer).getBaseAddress();
         }
+        assert false : byteBuffer;
+        return null;
     }
-            
+
     public boolean isAddressValid() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).isAddressValid();
-        } else {
-            assert false : byteBuffer;
-            return false;
+            return ((DirectBuffer) byteBuffer).isAddressValid();
         }
+        assert false : byteBuffer;
+        return false;
     }
 
     public void addressValidityCheck() {
         if (byteBuffer instanceof DirectBuffer) {
-           ((DirectBuffer)byteBuffer).addressValidityCheck();
+            ((DirectBuffer) byteBuffer).addressValidityCheck();
         } else {
             assert false : byteBuffer;
         }
     }
-            
+
     public void free() {
         if (byteBuffer instanceof DirectBuffer) {
-            ((DirectBuffer)byteBuffer).free();
+            ((DirectBuffer) byteBuffer).free();
         } else {
             assert false : byteBuffer;
-        }   
+        }
     }
-    // END android-added
 
+    @Override
     public ShortBuffer asReadOnlyBuffer() {
         ShortToByteBufferAdapter buf = new ShortToByteBufferAdapter(byteBuffer
                 .asReadOnlyBuffer());
@@ -120,6 +108,7 @@
         return buf;
     }
 
+    @Override
     public ShortBuffer compact() {
         if (byteBuffer.isReadOnly()) {
             throw new ReadOnlyBufferException();
@@ -134,6 +123,7 @@
         return this;
     }
 
+    @Override
     public ShortBuffer duplicate() {
         ShortToByteBufferAdapter buf = new ShortToByteBufferAdapter(byteBuffer
                 .duplicate());
@@ -143,6 +133,7 @@
         return buf;
     }
 
+    @Override
     public short get() {
         if (position == limit) {
             throw new BufferUnderflowException();
@@ -150,6 +141,7 @@
         return byteBuffer.getShort(position++ << 1);
     }
 
+    @Override
     public short get(int index) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -157,30 +149,37 @@
         return byteBuffer.getShort(index << 1);
     }
 
+    @Override
     public boolean isDirect() {
         return byteBuffer.isDirect();
     }
 
+    @Override
     public boolean isReadOnly() {
         return byteBuffer.isReadOnly();
     }
 
+    @Override
     public ByteOrder order() {
         return byteBuffer.order();
     }
 
+    @Override
     protected short[] protectedArray() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected int protectedArrayOffset() {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     protected boolean protectedHasArray() {
         return false;
     }
 
+    @Override
     public ShortBuffer put(short c) {
         if (position == limit) {
             throw new BufferOverflowException();
@@ -189,6 +188,7 @@
         return this;
     }
 
+    @Override
     public ShortBuffer put(int index, short c) {
         if (index < 0 || index >= limit) {
             throw new IndexOutOfBoundsException();
@@ -196,7 +196,7 @@
         byteBuffer.putShort(index << 1, c);
         return this;
     }
-    
+
     // BEGIN android-added
     @Override
     public ShortBuffer put(short[] s, int off, int len) {
@@ -212,6 +212,7 @@
     }
     // END android-added
 
+    @Override
     public ShortBuffer slice() {
         byteBuffer.limit(limit << 1);
         byteBuffer.position(position << 1);
diff --git a/nio/src/main/java/java/nio/channels/AlreadyConnectedException.java b/nio/src/main/java/java/nio/channels/AlreadyConnectedException.java
index d558492..5e09b1c 100644
--- a/nio/src/main/java/java/nio/channels/AlreadyConnectedException.java
+++ b/nio/src/main/java/java/nio/channels/AlreadyConnectedException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * An {@code AlreadyConnectedException} is thrown when an attempt is made to
  * connect a SocketChannel that is already connected.
- * 
- * @since Android 1.0
  */
 public class AlreadyConnectedException extends IllegalStateException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs an {@code AlreadyConnectedException}.
-     * 
-     * @since Android 1.0
      */
     public AlreadyConnectedException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/AsynchronousCloseException.java b/nio/src/main/java/java/nio/channels/AsynchronousCloseException.java
index e34d8d0..c2d285a 100644
--- a/nio/src/main/java/java/nio/channels/AsynchronousCloseException.java
+++ b/nio/src/main/java/java/nio/channels/AsynchronousCloseException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * An {@code AsynchronousCloseException} is thrown when the underlying channel
  * for an I/O operation is closed by another thread.
- * 
- * @since Android 1.0
  */
 public class AsynchronousCloseException extends ClosedChannelException {
 
@@ -29,11 +26,8 @@
 
     /**
      * Constructs an {@code AsynchronousCloseException}.
-     * 
-     * @since Android 1.0
      */
     public AsynchronousCloseException() {
         super();
     }
-
 }
diff --git a/nio/src/main/java/java/nio/channels/ByteChannel.java b/nio/src/main/java/java/nio/channels/ByteChannel.java
index 97f5d23..383d350 100644
--- a/nio/src/main/java/java/nio/channels/ByteChannel.java
+++ b/nio/src/main/java/java/nio/channels/ByteChannel.java
@@ -16,17 +16,14 @@
 
 package java.nio.channels;
 
-
 /**
  * A ByteChannel is both readable and writable.
  * <p>
  * The methods for the byte channel are precisely those defined by readable and
  * writable byte channels.
- * </p>
- * 
+ *
  * @see ReadableByteChannel
  * @see WritableByteChannel
- * @since Android 1.0
  */
 public interface ByteChannel extends ReadableByteChannel, WritableByteChannel {
     // No methods defined.
diff --git a/nio/src/main/java/java/nio/channels/CancelledKeyException.java b/nio/src/main/java/java/nio/channels/CancelledKeyException.java
index ebb7c76..e955b3c 100644
--- a/nio/src/main/java/java/nio/channels/CancelledKeyException.java
+++ b/nio/src/main/java/java/nio/channels/CancelledKeyException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * A {@code CancelledKeyException} is thrown when an invalid selection key is
  * used.
- * 
- * @since Android 1.0
  */
 public class CancelledKeyException extends IllegalStateException {
 
@@ -32,8 +29,6 @@
 
     /**
      * Constructs a {@code CancelledKeyException}.
-     *
-     * @since Android 1.0
      */
     public CancelledKeyException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/Channel.java b/nio/src/main/java/java/nio/channels/Channel.java
index 585ce29..f31c565 100644
--- a/nio/src/main/java/java/nio/channels/Channel.java
+++ b/nio/src/main/java/java/nio/channels/Channel.java
@@ -16,7 +16,6 @@
 
 package java.nio.channels;
 
-
 import java.io.Closeable;
 import java.io.IOException;
 
@@ -27,13 +26,9 @@
  * Channels are open upon creation, and can be closed explicitly. Once a channel
  * is closed it cannot be re-opened, and any attempts to perform I/O operations
  * on the closed channel result in a <code>ClosedChannelException</code>.
- * </p>
  * <p>
  * Particular implementations or sub-interfaces of {@code Channel} dictate
  * whether they are thread-safe or not.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface Channel extends Closeable {
 
@@ -41,7 +36,6 @@
      * Returns whether this channel is open or not.
      * 
      * @return true if the channel is open, otherwise returns false.
-     * @since Android 1.0
      */
     public boolean isOpen();
 
@@ -53,16 +47,13 @@
      * <p>
      * If an attempt is made to perform an operation on a closed channel then a
      * {@link ClosedChannelException} will be thrown on that attempt.
-     * </p>
      * <p>
      * If multiple threads attempt to simultaneously close a channel, then only
      * one thread will run the closure code, and others will be blocked until
      * the first returns.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             if a problem occurs closing the channel.
-     * @since Android 1.0
      */
     public void close() throws IOException;
 }
diff --git a/nio/src/main/java/java/nio/channels/Channels.java b/nio/src/main/java/java/nio/channels/Channels.java
index fa70dc0..f29ca74 100644
--- a/nio/src/main/java/java/nio/channels/Channels.java
+++ b/nio/src/main/java/java/nio/channels/Channels.java
@@ -32,14 +32,9 @@
 
 /**
  * This class provides several utilities to get I/O streams from channels.
- * 
- * @since Android 1.0
  */
 public final class Channels {
 
-    // -------------------------------------------------------------------
-    // Constructor
-    // -------------------------------------------------------------------
     /*
      * Not intended to be instantiated.
      */
@@ -47,10 +42,6 @@
         super();
     }
 
-    // -------------------------------------------------------------------
-    // Public Methods
-    // -------------------------------------------------------------------
-
     /**
      * Returns an input stream on the given channel. The resulting stream has
      * the following properties:
@@ -67,7 +58,6 @@
      * @param channel
      *            the channel to be wrapped by an InputStream.
      * @return an InputStream that takes bytes from the given byte channel.
-     * @since Android 1.0
      */
     public static InputStream newInputStream(ReadableByteChannel channel) {
         return new ReadableByteChannelInputStream(channel);
@@ -88,7 +78,6 @@
      * @param channel
      *            the channel to be wrapped by an OutputStream.
      * @return an OutputStream that puts bytes onto the given byte channel.
-     * @since Android 1.0
      */
     public static OutputStream newOutputStream(WritableByteChannel channel) {
         return new WritableByteChannelOutputStream(channel);
@@ -106,7 +95,6 @@
      * @param inputStream
      *            the stream to be wrapped by a byte channel.
      * @return a byte channel that reads bytes from the input stream.
-     * @since Android 1.0
      */
     public static ReadableByteChannel newChannel(InputStream inputStream) {
         return new ReadableByteChannelImpl(inputStream);
@@ -121,11 +109,10 @@
      * well.</li>
      * <li>It is not buffered.</li>
      * </ul>
-     * 
+     *
      * @param outputStream
      *            the stream to be wrapped by a byte channel.
      * @return a byte channel that writes bytes to the output stream.
-     * @since Android 1.0
      */
     public static WritableByteChannel newChannel(OutputStream outputStream) {
         return new WritableByteChannelImpl(outputStream);
@@ -142,12 +129,10 @@
      *            The minimum size of the byte buffer, -1 means to use the
      *            default size.
      * @return the reader.
-     * @since Android 1.0
      */
     public static Reader newReader(ReadableByteChannel channel,
             CharsetDecoder decoder, int minBufferCapacity) {
-        return new ByteChannelReader(
-                new ReaderInputStream(channel), decoder,
+        return new ByteChannelReader(new ReaderInputStream(channel), decoder,
                 minBufferCapacity);
     }
 
@@ -162,7 +147,6 @@
      * @return the reader.
      * @throws java.nio.charset.UnsupportedCharsetException
      *             if the given charset name is not supported.
-     * @since Android 1.0
      */
     public static Reader newReader(ReadableByteChannel channel,
             String charsetName) {
@@ -181,7 +165,6 @@
      *            the minimum size of the byte buffer, -1 means to use the
      *            default size.
      * @return the writer.
-     * @since Android 1.0
      */
     public static Writer newWriter(WritableByteChannel channel,
             CharsetEncoder encoder, int minBufferCapacity) {
@@ -201,16 +184,12 @@
      * @return the writer.
      * @throws java.nio.charset.UnsupportedCharsetException
      *             if the given charset name is not supported.
-     * @since Android 1.0
      */
     public static Writer newWriter(WritableByteChannel channel,
             String charsetName) {
         return newWriter(channel, Charset.forName(charsetName).newEncoder(), -1);
     }
 
-    // -------------------------------------------------------------------
-    // share routine
-    // -------------------------------------------------------------------
     /*
      * wrap a byte array to a ByteBuffer
      */
@@ -223,10 +202,6 @@
         return buffer;
     }
 
-    // -------------------------------------------------------------------
-    // Wrapper classes
-    // -------------------------------------------------------------------
-
     private static class ChannelInputStream extends InputStream {
 
         protected ReadableByteChannel channel;
@@ -236,9 +211,6 @@
             channel = aChannel;
         }
 
-        /*
-         * @see java.io.InputStream#read()
-         */
         @Override
         public synchronized int read() throws IOException {
             byte[] oneByte = new byte[1];
@@ -250,9 +222,6 @@
             return -1;
         }
 
-        /*
-         * @see java.io.InputStream#close()
-         */
         @Override
         public synchronized void close() throws IOException {
             channel.close();
@@ -265,16 +234,10 @@
     private static class ReadableByteChannelInputStream extends
             ChannelInputStream {
 
-        /*
-         * @param someChannel
-         */
         public ReadableByteChannelInputStream(ReadableByteChannel aChannel) {
             super(aChannel);
         }
 
-        /*
-         * @see java.io.InputStream#read(byte[], int, int)
-         */
         @Override
         public synchronized int read(byte[] target, int offset, int length)
                 throws IOException {
@@ -301,16 +264,10 @@
      */
     private static class ReaderInputStream extends ChannelInputStream {
 
-        /*
-         * @param someChannel
-         */
         public ReaderInputStream(ReadableByteChannel aChannel) {
             super(aChannel);
         }
 
-        /*
-         * @see java.io.InputStream#read(byte[], int, int)
-         */
         @Override
         public synchronized int read(byte[] target, int offset, int length)
                 throws IOException {
@@ -333,26 +290,19 @@
 
         private WritableByteChannel channel;
 
-        /*
-         * @param someChannel
-         */
         public WritableByteChannelOutputStream(WritableByteChannel aChannel) {
             super();
             channel = aChannel;
         }
 
-        /*
-         * @see java.io.OutputStream#write(int)
-         */
+        @Override
         public synchronized void write(int oneByte) throws IOException {
             byte[] wrappedByte = new byte[1];
             wrappedByte[0] = (byte) oneByte;
             write(wrappedByte);
         }
 
-        /*
-         * @see java.io.OutputStream#write(byte[], int, int)
-         */
+        @Override
         public synchronized void write(byte[] source, int offset, int length)
                 throws IOException {
             // avoid int overflow, check null source
@@ -371,9 +321,7 @@
             channel.write(buffer);
         }
 
-        /*
-         * @see java.io.OutputStream#close()
-         */
+        @Override
         public synchronized void close() throws IOException {
             channel.close();
         }
@@ -391,9 +339,6 @@
             inputStream = aInputStream;
         }
 
-        /*
-         * @see java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer)
-         */
         public synchronized int read(ByteBuffer target) throws IOException {
             if (!isOpen()) {
                 throw new ClosedChannelException();
@@ -413,9 +358,7 @@
             return readCount;
         }
 
-        /*
-         * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel()
-         */
+        @Override
         protected void implCloseChannel() throws IOException {
             inputStream.close();
         }
@@ -433,9 +376,6 @@
             outputStream = aOutputStream;
         }
 
-        /*
-         * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
-         */
         public synchronized int write(ByteBuffer source) throws IOException {
             if (!isOpen()) {
                 throw new ClosedChannelException();
@@ -455,9 +395,7 @@
             return bytesRemain;
         }
 
-        /*
-         * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel()
-         */
+        @Override
         protected void implCloseChannel() throws IOException {
             outputStream.close();
         }
@@ -479,9 +417,6 @@
 
         CharBuffer chars;
 
-        /*
-         * @param inputStream @param dec @param minBufferCapacity
-         */
         public ByteChannelReader(InputStream aInputStream,
                 CharsetDecoder aDecoder, int minBufferCapacity) {
             super(aInputStream);
@@ -494,9 +429,7 @@
             chars.limit(0);
         }
 
-        /*
-         * @see java.io.Reader#close()
-         */
+        @Override
         public void close() throws IOException {
             synchronized (lock) {
                 decoder = null;
@@ -507,9 +440,7 @@
             }
         }
 
-        /*
-         * @see java.io.Reader#ready()
-         */
+        @Override
         public boolean ready() {
             synchronized (lock) {
                 if (null == inputStream) {
@@ -524,20 +455,16 @@
             }
         }
 
-        /*
-         * @see java.io.Reader#read()
-         */
+        @Override
         public int read() throws IOException {
-            return IOUtil.readInputStreamReader(inputStream,
-                    bytes, chars, decoder, lock);
+            return IOUtil.readInputStreamReader(inputStream, bytes, chars,
+                    decoder, lock);
         }
 
-        /*
-         * @see java.io.Reader#read(char[], int, int)
-         */
+        @Override
         public int read(char[] buf, int offset, int length) throws IOException {
-            return IOUtil.readInputStreamReader(buf, offset,
-                    length, inputStream, bytes, chars, decoder, lock);
+            return IOUtil.readInputStreamReader(buf, offset, length,
+                    inputStream, bytes, chars, decoder, lock);
         }
     }
 
@@ -555,9 +482,6 @@
 
         private ByteBuffer byteBuf;
 
-        /*
-         * @param outputStream @param enc @param minBufferCap
-         */
         public ByteChannelWriter(OutputStream aOutputStream,
                 CharsetEncoder aEncoder, int minBufferCap) {
             super(aOutputStream);
@@ -567,9 +491,7 @@
             encoder = aEncoder;
         }
 
-        /*
-         * @see java.io.Writer#close()
-         */
+        @Override
         public void close() throws IOException {
             synchronized (lock) {
                 if (encoder != null) {
@@ -582,37 +504,29 @@
             }
         }
 
-        /*
-         * @see java.io.Writer#flush()
-         */
+        @Override
         public void flush() throws IOException {
-            IOUtil.flushOutputStreamWriter(outputStream,
+            IOUtil
+                    .flushOutputStreamWriter(outputStream, byteBuf, encoder,
+                            lock);
+        }
+
+        @Override
+        public void write(char[] buf, int offset, int count) throws IOException {
+            IOUtil.writeOutputStreamWriter(buf, offset, count, outputStream,
                     byteBuf, encoder, lock);
         }
 
-        /*
-         * @see java.io.Writer#write(char[], int, int)
-         */
-        public void write(char[] buf, int offset, int count) throws IOException {
-            IOUtil.writeOutputStreamWriter(buf, offset, count,
-                    outputStream, byteBuf, encoder, lock);
-        }
-
-        /*
-         * @see java.io.Writer#write(int)
-         */
+        @Override
         public void write(int oneChar) throws IOException {
-            IOUtil.writeOutputStreamWriter(oneChar,
-                    outputStream, byteBuf, encoder, lock);
+            IOUtil.writeOutputStreamWriter(oneChar, outputStream, byteBuf,
+                    encoder, lock);
         }
 
-        /*
-         * @see java.io.Writer#write(java.lang.String, int, int)
-         */
+        @Override
         public void write(String str, int offset, int count) throws IOException {
-            IOUtil.writeOutputStreamWriter(str, offset, count,
-                    outputStream, byteBuf, encoder, lock);
+            IOUtil.writeOutputStreamWriter(str, offset, count, outputStream,
+                    byteBuf, encoder, lock);
         }
     }
-
 }
diff --git a/nio/src/main/java/java/nio/channels/ClosedByInterruptException.java b/nio/src/main/java/java/nio/channels/ClosedByInterruptException.java
index c7d5c6a..cc4c5eb 100644
--- a/nio/src/main/java/java/nio/channels/ClosedByInterruptException.java
+++ b/nio/src/main/java/java/nio/channels/ClosedByInterruptException.java
@@ -16,7 +16,6 @@
 
 package java.nio.channels;
 
-
 /**
  * A {@code ClosedByInterruptException} is thrown when a thread is interrupted
  * in a blocking I/O operation.
@@ -24,9 +23,6 @@
  * When the thread is interrupted by a call to {@code interrupt()}, it closes
  * the channel, sets the interrupt status of the thread to {@code true} and
  * throws a {@code ClosedByInterruptException}.
- * </p>
- * 
- * @since Android 1.0
  */
 public class ClosedByInterruptException extends AsynchronousCloseException {
 
@@ -34,8 +30,6 @@
 
     /**
      * Constructs a {@code ClosedByInterruptException}.
-     * 
-     * @since Android 1.0
      */
     public ClosedByInterruptException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/ClosedChannelException.java b/nio/src/main/java/java/nio/channels/ClosedChannelException.java
index 4cf4b38..2b77601 100644
--- a/nio/src/main/java/java/nio/channels/ClosedChannelException.java
+++ b/nio/src/main/java/java/nio/channels/ClosedChannelException.java
@@ -16,14 +16,11 @@
 
 package java.nio.channels;
 
-
 import java.io.IOException;
 
 /**
  * A {@code ClosedChannelException} is thrown when a channel is closed for the
  * type of operation attempted.
- * 
- * @since Android 1.0
  */
 public class ClosedChannelException extends IOException {
 
@@ -31,11 +28,8 @@
 
     /**
      * Constructs a {@code ClosedChannelException}.
-     * 
-     * @since Android 1.0
      */
     public ClosedChannelException() {
         super();
     }
-
 }
diff --git a/nio/src/main/java/java/nio/channels/ClosedSelectorException.java b/nio/src/main/java/java/nio/channels/ClosedSelectorException.java
index 0fb16d3..5acc878 100644
--- a/nio/src/main/java/java/nio/channels/ClosedSelectorException.java
+++ b/nio/src/main/java/java/nio/channels/ClosedSelectorException.java
@@ -16,25 +16,18 @@
 
 package java.nio.channels;
 
-
 /**
  * A {@code ClosedSelectorException} is thrown when a {@link Selector selector}
  * is closed and an I/O operation is attempted.
- * 
- * @since Android 1.0
  */
 public class ClosedSelectorException extends IllegalStateException {
 
     private static final long serialVersionUID = 6466297122317847835L;
-    
+
     /**
      * Constructs a {@code ClosedSelectorException}.
-     * 
-     * @since Android 1.0
      */
     public ClosedSelectorException() {
         super();
     }
 }
-
-
diff --git a/nio/src/main/java/java/nio/channels/ConnectionPendingException.java b/nio/src/main/java/java/nio/channels/ConnectionPendingException.java
index c535925..43ff65cd 100644
--- a/nio/src/main/java/java/nio/channels/ConnectionPendingException.java
+++ b/nio/src/main/java/java/nio/channels/ConnectionPendingException.java
@@ -16,13 +16,10 @@
 
 package java.nio.channels;
 
-
 /**
  * A {@code ConnectionPendingException} is thrown when an attempt is made to
  * connect a {@link SocketChannel} that has a non-blocking connection already
  * underway.
- * 
- * @since Android 1.0
  */
 public class ConnectionPendingException extends IllegalStateException {
 
@@ -30,11 +27,8 @@
 
     /**
      * Constructs a {@code ConnectionPendingException}.
-     * 
-     * @since Android 1.0
      */
     public ConnectionPendingException() {
         super();
     }
-
 }
diff --git a/nio/src/main/java/java/nio/channels/DatagramChannel.java b/nio/src/main/java/java/nio/channels/DatagramChannel.java
index 534155a..31b0825 100644
--- a/nio/src/main/java/java/nio/channels/DatagramChannel.java
+++ b/nio/src/main/java/java/nio/channels/DatagramChannel.java
@@ -37,13 +37,9 @@
  * status until it is disconnected or closed. The benefit of a connected channel
  * is the reduced effort of security checks during send and receive. When
  * invoking {@code read} or {@code write}, a connected channel is required.
- * </p>
  * <p>
  * Datagram channels are thread-safe; only one thread can read or write at the
  * same time.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class DatagramChannel extends AbstractSelectableChannel
         implements ByteChannel, ScatteringByteChannel, GatheringByteChannel {
@@ -51,13 +47,12 @@
     static {
         Platform.getNetworkSystem().oneTimeInitialization(true);
     }
-    
+
     /**
      * Constructs a new {@code DatagramChannel}.
      * 
      * @param selectorProvider
      *            an instance of SelectorProvider.
-     * @since Android 1.0
      */
     protected DatagramChannel(SelectorProvider selectorProvider) {
         super(selectorProvider);
@@ -68,12 +63,10 @@
      * <p>
      * This channel is created by calling the <code>openDatagramChannel</code>
      * method of the default {@link SelectorProvider} instance.
-     * </p>
-     * 
+     *
      * @return the new channel which is open but not connected.
      * @throws IOException
      *             if some I/O error occurs.
-     * @since Android 1.0
      */
     public static DatagramChannel open() throws IOException {
         return SelectorProvider.provider().openDatagramChannel();
@@ -86,8 +79,8 @@
      * 
      * @see java.nio.channels.SelectableChannel#validOps()
      * @return valid operations in bit-set.
-     * @since Android 1.0
      */
+    @Override
     public final int validOps() {
         return (SelectionKey.OP_READ | SelectionKey.OP_WRITE);
     }
@@ -98,7 +91,6 @@
      * {@link DatagramSocket}.
      * 
      * @return the related DatagramSocket instance.
-     * @since Android 1.0
      */
     public abstract DatagramSocket socket();
 
@@ -107,7 +99,6 @@
      * 
      * @return <code>true</code> if this channel's socket is connected;
      *         <code>false</code> otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isConnected();
 
@@ -120,12 +111,10 @@
      * write operations being processed at the time the method is called. The
      * connection status does not change until the channel is disconnected or
      * closed.
-     * </p>
      * <p>
      * This method executes the same security checks as the connect method of
      * the {@link DatagramSocket} class.
-     * </p>
-     * 
+     *
      * @param address
      *            the address to be connected to.
      * @return this channel.
@@ -143,7 +132,6 @@
      *             permitted to be accessed.
      * @throws IOException
      *             if some other I/O error occurrs.
-     * @since Android 1.0
      */
     public abstract DatagramChannel connect(SocketAddress address)
             throws IOException;
@@ -155,12 +143,10 @@
      * This method can be called at any time without affecting the read and
      * write operations being underway. It does not have any effect if the
      * socket is not connected or the channel is closed.
-     * </p>
-     * 
+     *
      * @return this channel.
      * @throws IOException
      *             some other I/O error occurs.
-     * @since Android 1.0
      */
     public abstract DatagramChannel disconnect() throws IOException;
 
@@ -174,16 +160,13 @@
      * immediately. The transfer starts at the current position of the buffer,
      * and if there is not enough space remaining in the buffer to store the
      * datagram then the part of the datagram that does not fit is discarded.
-     * </p>
      * <p>
      * This method can be called at any time and it will block if there is
      * another thread that has started a read operation on the channel.
-     * </p>
      * <p>
      * This method executes the same security checks as the receive method of
      * the {@link DatagramSocket} class.
-     * </p>
-     * 
+     *
      * @param target
      *            the byte buffer to store the received datagram.
      * @return the address of the datagram if the transfer is performed, or null
@@ -203,7 +186,6 @@
      *             permitted to be accessed.
      * @throws IOException
      *             some other I/O error occurs.
-     * @since Android 1.0
      */
     public abstract SocketAddress receive(ByteBuffer target) throws IOException;
 
@@ -216,16 +198,13 @@
      * in non-blocking mode then the datagram is only sent if there is enough
      * space in the underlying output buffer at that moment. The transfer action
      * is just like a regular write operation.
-     * </p>
      * <p>
      * This method can be called at any time and it will block if another thread
      * has started a send operation on this channel.
-     * </p>
      * <p>
      * This method executes the same security checks as the send method of the
      * {@link DatagramSocket} class.
-     * </p>
-     * 
+     *
      * @param source
      *            the byte buffer with the datagram to be sent.
      * @param address
@@ -248,7 +227,6 @@
      *             permitted to access.
      * @throws IOException
      *             some other I/O error occurs.
-     * @since Android 1.0
      */
     public abstract int send(ByteBuffer source, SocketAddress address)
             throws IOException;
@@ -262,8 +240,7 @@
      * not fit in the buffer is discarded. Otherwise, this method has the same
      * behavior as the {@code read} method in the {@link ReadableByteChannel}
      * interface.
-     * </p>
-     * 
+     *
      * @see java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer)
      * @param target
      *            the byte buffer to store the received datagram.
@@ -282,7 +259,6 @@
      *             interrupt state set and the channel will be closed.
      * @throws IOException
      *             some other I/O error occurs.
-     * @since Android 1.0
      */
     public abstract int read(ByteBuffer target) throws IOException;
 
@@ -295,8 +271,7 @@
      * datagram that does not fit in the buffers is discarded. Otherwise, this
      * method has the same behavior as the {@code read} method in the
      * {@link ScatteringByteChannel} interface.
-     * </p>
-     * 
+     *
      * @see java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[],
      *      int, int)
      * @param targets
@@ -324,7 +299,6 @@
      *             interrupt state set and the channel will be closed.
      * @throws IOException
      *             some other I/O error occurs.
-     * @since Android 1.0
      */
     public abstract long read(ByteBuffer[] targets, int offset, int length)
             throws IOException;
@@ -338,8 +312,7 @@
      * datagram that does not fit in the buffers is discarded. Otherwise, this
      * method has the same behavior as the {@code read} method in the
      * {@link ScatteringByteChannel} interface.
-     * </p>
-     * 
+     *
      * @see java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[])
      * @param targets
      *            the byte buffers to store the received datagram.
@@ -358,7 +331,6 @@
      *             interrupt state set and the channel will be closed.
      * @throws IOException
      *             some other I/O error occurs.
-     * @since Android 1.0
      */
     public synchronized final long read(ByteBuffer[] targets)
             throws IOException {
@@ -372,8 +344,7 @@
      * and the datagram is sent to the connected address. Otherwise, this method
      * has the same behavior as the {@code write} method in the
      * {@link WritableByteChannel} interface.
-     * </p>
-     * 
+     *
      * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
      * @param source
      *            the byte buffer as the source of the datagram.
@@ -391,7 +362,6 @@
      *             interrupt state set and the channel will be closed.
      * @throws IOException
      *             some other I/O error occurs.
-     * @since Android 1.0
      */
     public abstract int write(ByteBuffer source) throws IOException;
 
@@ -432,7 +402,6 @@
      *             interrupt state set and the channel will be closed.
      * @throws IOException
      *             some other I/O error occurs.
-     * @since Android 1.0
      */
     public abstract long write(ByteBuffer[] sources, int offset, int length)
             throws IOException;
@@ -465,7 +434,6 @@
      *             interrupt state set and the channel will be closed.
      * @throws IOException
      *             some other I/O error occurs.
-     * @since Android 1.0
      */
     public synchronized final long write(ByteBuffer[] sources)
             throws IOException {
diff --git a/nio/src/main/java/java/nio/channels/FileChannel.java b/nio/src/main/java/java/nio/channels/FileChannel.java
index 0518fd3..2c30bae 100644
--- a/nio/src/main/java/java/nio/channels/FileChannel.java
+++ b/nio/src/main/java/java/nio/channels/FileChannel.java
@@ -16,7 +16,6 @@
 
 package java.nio.channels;
 
-
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.MappedByteBuffer;
@@ -30,7 +29,6 @@
  * does not have a method for opening files, since this behavior has been
  * delegated to the {@link java.io.FileInputStream},
  * {@link java.io.FileOutputStream} and {@link java.io.RandomAccessFile} types.
- * </p>
  * <p>
  * FileChannels created from a {@code FileInputStream} or a
  * {@code RandomAccessFile} created in mode "r", are read-only. FileChannels
@@ -39,19 +37,16 @@
  * FileChannels created from a {@code RandomAccessFile} that was opened in
  * append-mode will also be in append-mode -- meaning that each write will be
  * proceeded by a seek to the end of file.
- * </p>
  * <p>
  * FileChannels have a virtual pointer into the file which is referred to as a
  * file <em>position</em>. The position can be manipulated by moving it
  * within the file, and the current position can be queried.
- * </p>
  * <p>
  * FileChannels also have an associated <em>size</em>. The size of the file
  * is the number of bytes that it currently contains. The size can be
  * manipulated by adding more bytes to the end of the file (which increases the
  * size) or truncating the file (which decreases the size). The current size can
  * also be queried.
- * </p>
  * <p>
  * FileChannels have operations beyond the simple read, write, and close. They
  * can also:
@@ -65,55 +60,41 @@
  * <li>read and write to the file at absolute byte offsets in a fashion that
  * does not modify the current position.</li>
  * </ul>
- * </p>
  * <p>
  * FileChannels are thread-safe. Only one operation involving manipulation of
  * the file position may be executed at the same time. Subsequent calls to such
  * operations will block, and one of those blocked will be freed to continue
  * when the first operation has completed. There is no ordered queue or fairness
  * applied to the blocked threads.
- * </p>
  * <p>
  * It is undefined whether operations that do not manipulate the file position
  * will also block when there are any other operations in-flight.
- * </p>
  * <p>
  * The logical view of the underlying file is consistent across all FileChannels
  * and I/O streams opened on the same file by the same virtual machine process.
  * Therefore, modifications performed via a channel will be visible to the
  * stream and vice versa; this includes modifications to the file position,
  * content, size, etc.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class FileChannel extends AbstractInterruptibleChannel
         implements GatheringByteChannel, ScatteringByteChannel, ByteChannel {
 
     /**
      * {@code MapMode} defines file mapping mode constants.
-     * 
-     * @since Android 1.0
      */
     public static class MapMode {
         /**
          * Private mapping mode (equivalent to copy on write).
-         * 
-         * @since Android 1.0
          */
         public static final MapMode PRIVATE = new MapMode("PRIVATE"); //$NON-NLS-1$
 
         /**
          * Read-only mapping mode.
-         * 
-         * @since Android 1.0
          */
         public static final MapMode READ_ONLY = new MapMode("READ_ONLY"); //$NON-NLS-1$
 
         /**
          * Read-write mapping mode.
-         * 
-         * @since Android 1.0
          */
         public static final MapMode READ_WRITE = new MapMode("READ_WRITE"); //$NON-NLS-1$
 
@@ -132,8 +113,8 @@
          * Returns a string version of the mapping mode.
          * 
          * @return this map mode as string.
-         * @since Android 1.0
          */
+        @Override
         public String toString() {
             return displayName;
         }
@@ -141,8 +122,6 @@
 
     /**
      * Protected default constructor.
-     * 
-     * @since Android 1.0
      */
     protected FileChannel() {
         super();
@@ -157,12 +136,10 @@
      * local storage device. If the file is not hosted locally, for example on a
      * networked file system, then applications cannot be certain that the
      * modifications have been committed.
-     * </p>
      * <p>
      * There are no assurances given that changes made to the file using methods
      * defined elsewhere will be committed. For example, changes made via a
      * mapped byte buffer may not be committed.
-     * </p>
      * <p>
      * The <code>metadata</code> parameter indicates whether the update should
      * include the file's metadata such as last modification time, last access
@@ -177,7 +154,6 @@
      *             if this channel is already closed.
      * @throws IOException
      *             if another I/O error occurs.
-     * @since Android 1.0
      */
     public abstract void force(boolean metadata) throws IOException;
 
@@ -187,7 +163,7 @@
      * This is a convenience method for acquiring a maximum length lock on a
      * file. It is equivalent to:
      * {@code fileChannel.lock(0L, Long.MAX_VALUE, false);}
-     * 
+     *
      * @return the lock object representing the locked file area.
      * @throws ClosedChannelException
      *             the file channel is closed.
@@ -206,7 +182,6 @@
      * @throws IOException
      *             if another I/O error occurs while obtaining the requested
      *             lock.
-     * @since Android 1.0
      */
     public final FileLock lock() throws IOException {
         return lock(0L, Long.MAX_VALUE, false);
@@ -217,41 +192,34 @@
      * <p>
      * This is the blocking version of lock acquisition, see also the
      * <code>tryLock()</code> methods.
-     * </p>
      * <p>
      * Attempts to acquire an overlapping lock region will fail. The attempt
      * will fail if the overlapping lock has already been obtained, or if
      * another thread is currently waiting to acquire the overlapping lock.
-     * </p>
      * <p>
      * If the request is not for an overlapping lock, the thread calling this
      * method will block until the lock is obtained (likely by no contention or
      * another process releasing a lock), or until this thread is interrupted or
      * the channel is closed.
-     * </p>
      * <p>
      * If the lock is obtained successfully then the {@link FileLock} object
      * returned represents the lock for subsequent operations on the locked
      * region.
-     * </p>
      * <p>
      * If the thread is interrupted while waiting for the lock, the thread is
      * set to the interrupted state and throws a
      * {@link FileLockInterruptionException}. If this channel is closed while
      * the thread is waiting to obtain the lock then the thread throws a
      * {@link AsynchronousCloseException}.
-     * </p>
      * <p>
      * There is no requirement for the position and size to be within the
      * current start and length of the file.
-     * </p>
      * <p>
      * Some platforms do not support shared locks, and if a request is made for
      * a shared lock on such a platform, this method will attempt to acquire an
      * exclusive lock instead. It is undefined whether the lock obtained is
      * advisory or mandatory.
-     * </p>
-     * 
+     *
      * @param position
      *            the starting position for the locked region.
      * @param size
@@ -280,7 +248,6 @@
      *             the desired file lock.
      * @throws IOException
      *             if another I/O error occurs.
-     * @since Android 1.0
      */
     public abstract FileLock lock(long position, long size, boolean shared)
             throws IOException;
@@ -291,8 +258,7 @@
      * channel do not affect the other storage place.
      * <p>
      * Note: mapping a file into memory is usually expensive.
-     * </p>
-     * 
+     *
      * @param mode
      *            one of the three mapping modes.
      * @param position
@@ -312,7 +278,6 @@
      *             bigger than max integer.
      * @throws IOException
      *             if any I/O error occurs.
-     * @since Android 1.0
      */
     public abstract MappedByteBuffer map(FileChannel.MapMode mode,
             long position, long size) throws IOException;
@@ -326,7 +291,6 @@
      *             if this channel is closed.
      * @throws IOException
      *             if another I/O error occurs.
-     * @since Android 1.0
      */
     public abstract long position() throws IOException;
 
@@ -349,7 +313,6 @@
      *             if this channel is closed.
      * @throws IOException
      *             if another I/O error occurs.
-     * @since Android 1.0
      */
     public abstract FileChannel position(long offset) throws IOException;
 
@@ -359,16 +322,13 @@
      * The maximum number of bytes that will be read is the remaining number of
      * bytes in the buffer when the method is invoked. The bytes will be copied
      * into the buffer starting at the buffer's current position.
-     * </p>
      * <p>
      * The call may block if other threads are also attempting to read from this
      * channel.
-     * </p>
      * <p>
      * Upon completion, the buffer's position is set to the end of the bytes
      * that have been read. The buffer's limit is not changed.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the byte buffer to receive the bytes.
      * @return the number of bytes actually read.
@@ -384,7 +344,6 @@
      * @throws NonReadableChannelException
      *             if the channel has not been opened in a mode that permits
      *             reading.
-     * @since Android 1.0
      */
     public abstract int read(ByteBuffer buffer) throws IOException;
 
@@ -395,15 +354,12 @@
      * The bytes are read starting at the given file position (up to the
      * remaining number of bytes in the buffer). The number of bytes actually
      * read is returned.
-     * </p>
      * <p>
      * If {@code position} is beyond the current end of file, then no bytes are
      * read.
-     * </p>
      * <p>
      * Note that the file position is unmodified by this method.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer to receive the bytes.
      * @param position
@@ -425,7 +381,6 @@
      * @throws NonReadableChannelException
      *             if the channel has not been opened in a mode that permits
      *             reading.
-     * @since Android 1.0
      */
     public abstract int read(ByteBuffer buffer, long position)
             throws IOException;
@@ -439,12 +394,10 @@
      * <p>
      * If a read operation is in progress, subsequent threads will block until
      * the read is completed and will then contend for the ability to read.
-     * </p>
      * <p>
      * Calling this method is equivalent to calling
      * {@code read(buffers, 0, buffers.length);}
-     * </p>
-     * 
+     *
      * @param buffers
      *            the array of byte buffers into which the bytes will be copied.
      * @return the number of bytes actually read.
@@ -461,24 +414,21 @@
      * @throws NonReadableChannelException
      *             if the channel has not been opened in a mode that permits
      *             reading.
-     * @since Android 1.0
      */
     public final long read(ByteBuffer[] buffers) throws IOException {
         return read(buffers, 0, buffers.length);
     }
 
     /**
-     * Reads bytes from this file channel and stores them in a subset of the
-     * specified array of buffers. The subset is defined by {@code start} and
-     * {@code number}, indicating the first buffer and the number of buffers to
-     * use. This method attempts to read as many bytes as can be stored in the
-     * buffer subset from this channel and returns the number of bytes actually
-     * read. It also increases the file position by the number of bytes read.
+     * Reads bytes from this file channel into a subset of the given buffers.
+     * This method attempts to read all {@code remaining()} bytes from {@code
+     * length} byte buffers, in order, starting at {@code targets[offset]}. It
+     * increases the file position by the number of bytes actually read. The
+     * number of bytes actually read is returned.
      * <p>
      * If a read operation is in progress, subsequent threads will block until
      * the read is completed and will then contend for the ability to read.
-     * </p>
-     * 
+     *
      * @param buffers
      *            the array of byte buffers into which the bytes will be copied.
      * @param start
@@ -503,7 +453,6 @@
      * @throws NonReadableChannelException
      *             if the channel has not been opened in a mode that permits
      *             reading.
-     * @since Android 1.0
      */
     public abstract long read(ByteBuffer[] buffers, int start, int number)
             throws IOException;
@@ -516,7 +465,6 @@
      *             if this channel is closed.
      * @throws IOException
      *             if an I/O error occurs while getting the size of the file.
-     * @since Android 1.0
      */
     public abstract long size() throws IOException;
 
@@ -530,8 +478,7 @@
      * buffer.
      * <p>
      * Note that this channel's position is not modified.
-     * </p>
-     * 
+     *
      * @param src
      *            the source channel to read bytes from.
      * @param position
@@ -554,7 +501,6 @@
      *             if the thread is interrupted during this operation.
      * @throws IOException
      *             if any I/O error occurs.
-     * @since Android 1.0
      */
     public abstract long transferFrom(ReadableByteChannel src, long position,
             long count) throws IOException;
@@ -569,8 +515,7 @@
      * buffer.
      * <p>
      * Note that this channel's position is not modified.
-     * </p>
-     * 
+     *
      * @param position
      *            the non-negative position to begin.
      * @param count
@@ -593,7 +538,6 @@
      *             if the thread is interrupted during this operation.
      * @throws IOException
      *             if any I/O error occurs.
-     * @since Android 1.0
      */
     public abstract long transferTo(long position, long count,
             WritableByteChannel target) throws IOException;
@@ -605,8 +549,7 @@
      * <p>
      * If the file position is currently greater than the given size, then it is
      * set to the new size.
-     * </p>
-     * 
+     *
      * @param size
      *            the maximum size of the underlying file.
      * @throws IllegalArgumentException
@@ -618,7 +561,6 @@
      * @throws IOException
      *             if another I/O error occurs.
      * @return this channel.
-     * @since Android 1.0
      */
     public abstract FileChannel truncate(long size) throws IOException;
 
@@ -628,12 +570,10 @@
      * This is a convenience method for attempting to acquire a maximum length
      * lock on the file. It is equivalent to:
      * {@code fileChannel.tryLock(0L, Long.MAX_VALUE, false);}
-     * </p>
      * <p>
      * The method returns {@code null} if the acquisition would result in an
      * overlapped lock with another OS process.
-     * </p>
-     * 
+     *
      * @return the file lock object, or {@code null} if the lock would overlap
      *         with an existing exclusive lock in another OS process.
      * @throws ClosedChannelException
@@ -644,7 +584,6 @@
      *             with this request.
      * @throws IOException
      *             if any I/O error occurs.
-     * @since Android 1.0
      */
     public final FileLock tryLock() throws IOException {
         return tryLock(0L, Long.MAX_VALUE, false);
@@ -659,8 +598,7 @@
      * outside of the file's size. The size of the lock is fixed. If the file
      * grows outside of the lock that region of the file won't be locked by this
      * lock.
-     * </p>
-     * 
+     *
      * @param position
      *            the starting position.
      * @param size
@@ -679,7 +617,6 @@
      *             with this request.
      * @throws IOException
      *             if any I/O error occurs.
-     * @since Android 1.0
      */
     public abstract FileLock tryLock(long position, long size, boolean shared)
             throws IOException;
@@ -703,11 +640,11 @@
      *             if another thread closes the channel during the write.
      * @throws ClosedByInterruptException
      *             if another thread interrupts the calling thread while this
-     *             operation is in progress. The interrupt state of the calling 
+     *             operation is in progress. The interrupt state of the calling
      *             thread is set and the channel is closed.
      * @throws IOException
      *             if another I/O error occurs, details are in the message.
-     * @since Android 1.0
+     * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
      */
     public abstract int write(ByteBuffer src) throws IOException;
 
@@ -718,16 +655,13 @@
      * The bytes are written starting at the given file position (up to the
      * remaining number of bytes in the buffer). The number of bytes actually
      * written is returned.
-     * </p>
      * <p>
      * If the position is beyond the current end of file, then the file is first
      * extended up to the given position by the required number of unspecified
      * byte values.
-     * </p>
      * <p>
      * Note that the file position is not modified by this method.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer containing the bytes to be written.
      * @param position
@@ -748,7 +682,6 @@
      *             thread is set and the channel is closed.
      * @throws IOException
      *             if another I/O error occurs.
-     * @since Android 1.0
      */
     public abstract int write(ByteBuffer buffer, long position)
             throws IOException;
@@ -763,8 +696,7 @@
      * <p>
      * Calling this method is equivalent to calling
      * {@code write(buffers, 0, buffers.length);}
-     * </p>
-     * 
+     *
      * @param buffers
      *            the buffers containing bytes to write.
      * @return the number of bytes actually written.
@@ -773,7 +705,7 @@
      *             operation.
      * @throws ClosedByInterruptException
      *             if another thread interrupts the calling thread while this
-     *             operation is in progress. The interrupt state of the calling 
+     *             operation is in progress. The interrupt state of the calling
      *             thread is set and the channel is closed.
      * @throws ClosedChannelException
      *             if this channel is closed.
@@ -781,21 +713,20 @@
      *             if another I/O error occurs; details are in the message.
      * @throws NonWritableChannelException
      *             if this channel was not opened for writing.
-     * @since Android 1.0
      */
     public final long write(ByteBuffer[] buffers) throws IOException {
         return write(buffers, 0, buffers.length);
     }
 
     /**
-     * Writes bytes from a subset of the specified array of buffers into this
-     * file channel. The subset is defined by {@code offset} and {@code length},
-     * indicating the first buffer and the number of buffers to use.
+     * Attempts to write a subset of the given bytes from the buffers to this
+     * file channel. This method attempts to write all {@code remaining()}
+     * bytes from {@code length} byte buffers, in order, starting at {@code
+     * sources[offset]}. The number of bytes actually written is returned.
      * <p>
      * If a write operation is in progress, subsequent threads will block until
      * the write is completed and then contend for the ability to write.
-     * </p>
-     * 
+     *
      * @param buffers
      *            the array of byte buffers that is the source for bytes written
      *            to this channel.
@@ -810,7 +741,7 @@
      *             operation.
      * @throws ClosedByInterruptException
      *             if another thread interrupts the calling thread while this
-     *             operation is in progress. The interrupt state of the calling 
+     *             operation is in progress. The interrupt state of the calling
      *             thread is set and the channel is closed.
      * @throws ClosedChannelException
      *             if this channel is closed.
@@ -822,9 +753,7 @@
      *             if another I/O error occurs; details are in the message.
      * @throws NonWritableChannelException
      *             if this channel was not opened for writing.
-     * @since Android 1.0
      */
     public abstract long write(ByteBuffer[] buffers, int offset, int length)
             throws IOException;
-
 }
diff --git a/nio/src/main/java/java/nio/channels/FileLock.java b/nio/src/main/java/java/nio/channels/FileLock.java
index e9aae1f..1bc71a8 100644
--- a/nio/src/main/java/java/nio/channels/FileLock.java
+++ b/nio/src/main/java/java/nio/channels/FileLock.java
@@ -30,7 +30,6 @@
  * simultaneously hold a shared lock overlapping the exclusive lock. An
  * application can determine whether a {@code FileLock} is shared or exclusive
  * via the {@code isShared()} method.
- * </p>
  * <p>
  * Locks held by a particular process cannot overlap one another. Applications
  * can determine whether a proposed lock will overlap by using the {@code
@@ -38,19 +37,16 @@
  * locks held in this process. Locks are shared amongst all threads in the
  * acquiring process, and are therefore unsuitable for intra-process
  * synchronization.
- * </p>
  * <p>
  * Once a lock is acquired, it is immutable in all its state except {@code
  * isValid()}. The lock will initially be valid, but may be rendered invalid by
  * explicit removal of the lock, using {@code release()}, or implicitly by
  * closing the channel or exiting the process (terminating the virtual machine).
- * </p>
  * <h3>Platform dependencies</h3>
  * <p>
  * Locks are intended to be true platform operating system file locks, and
  * therefore locks held by the virtual machine process will be visible to other
  * operating system processes.
- * </p>
  * <p>
  * The characteristics of the underlying operating system locks will show
  * through in the Java implementation. For example, some platforms' locks are
@@ -61,7 +57,6 @@
  * processes to not play well. To be on the safe side, it is best to assume that
  * the platform is adopting advisory locks and always acquire shared locks when
  * reading a region of a file.
- * </p>
  * <p>
  * On some platforms, the presence of a lock will prevent the file from being
  * memory-mapped. On some platforms, closing a channel on a given file handle
@@ -69,13 +64,9 @@
  * channels open on the same file; their locks will also be released. The safe
  * option here is to ensure that you only acquire locks on a single channel for
  * a particular file and that becomes the synchronization point.
- * </p>
  * <p>
  * Further care should be exercised when locking files maintained on network
  * file systems, since they often have further limitations.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class FileLock {
 
@@ -104,7 +95,6 @@
      * @param shared
      *            the lock's sharing mode of lock; {@code true} is shared,
      *            {@code false} is exclusive.
-     * @since Android 1.0
      */
     protected FileLock(FileChannel channel, long position, long size,
             boolean shared) {
@@ -122,7 +112,6 @@
      * Returns the lock's {@link FileChannel}.
      * 
      * @return the channel.
-     * @since Android 1.0
      */
     public final FileChannel channel() {
         return channel;
@@ -132,7 +121,6 @@
      * Returns the lock's starting position in the file.
      * 
      * @return the lock position.
-     * @since Android 1.0
      */
     public final long position() {
         return position;
@@ -142,7 +130,6 @@
      * Returns the length of the file lock in bytes.
      * 
      * @return the size of the file lock in bytes.
-     * @since Android 1.0
      */
     public final long size() {
         return size;
@@ -154,7 +141,6 @@
      * 
      * @return {@code true} if the lock is a shared lock, {@code false} if it is
      *         exclusive.
-     * @since Android 1.0
      */
     public final boolean isShared() {
         return shared;
@@ -169,7 +155,6 @@
      * @param length
      *            the length of the comparative lock.
      * @return {@code true} if there is an overlap, {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean overlaps(long start, long length) {
         final long end = position + size - 1;
@@ -186,7 +171,6 @@
      * explicitly released.
      * 
      * @return {@code true} if the lock is valid, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isValid();
 
@@ -199,7 +183,6 @@
      *             the lock is made.
      * @throws IOException
      *             if another I/O error occurs.
-     * @since Android 1.0
      */
     public abstract void release() throws IOException;
 
@@ -208,17 +191,18 @@
      * to an end user.
      * 
      * @return the display string.
-     * @since Android 1.0
      */
+    @Override
+    @SuppressWarnings("nls")
     public final String toString() {
-        StringBuffer buffer = new StringBuffer(64); // Guess length of string
-        buffer.append("FileLock: [position="); //$NON-NLS-1$
+        StringBuilder buffer = new StringBuilder(64); // Guess length of string
+        buffer.append("FileLock: [position=");
         buffer.append(position);
-        buffer.append(", size="); //$NON-NLS-1$
+        buffer.append(", size=");
         buffer.append(size);
-        buffer.append(", shared="); //$NON-NLS-1$
+        buffer.append(", shared=");
         buffer.append(Boolean.toString(shared));
-        buffer.append("]"); //$NON-NLS-1$
+        buffer.append("]");
         return buffer.toString();
     }
 }
diff --git a/nio/src/main/java/java/nio/channels/FileLockInterruptionException.java b/nio/src/main/java/java/nio/channels/FileLockInterruptionException.java
index 0920f52..71cc0c6 100644
--- a/nio/src/main/java/java/nio/channels/FileLockInterruptionException.java
+++ b/nio/src/main/java/java/nio/channels/FileLockInterruptionException.java
@@ -16,7 +16,6 @@
 
 package java.nio.channels;
 
-
 import java.io.IOException;
 
 /**
@@ -24,9 +23,6 @@
  * interrupted while waiting to acquire a file lock.
  * <p>
  * Note that the thread will also be in the 'interrupted' state.
- * </p>
- * 
- * @since Android 1.0
  */
 public class FileLockInterruptionException extends IOException {
 
@@ -34,8 +30,6 @@
 
     /**
      * Constructs a {@code FileLockInterruptionException}.
-     * 
-     * @since Android 1.0
      */
     public FileLockInterruptionException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/GatheringByteChannel.java b/nio/src/main/java/java/nio/channels/GatheringByteChannel.java
index e8a6c73..8e52075 100644
--- a/nio/src/main/java/java/nio/channels/GatheringByteChannel.java
+++ b/nio/src/main/java/java/nio/channels/GatheringByteChannel.java
@@ -16,7 +16,6 @@
 
 package java.nio.channels;
 
-
 import java.io.IOException;
 import java.nio.ByteBuffer;
 
@@ -24,8 +23,6 @@
  * The interface for channels that can write a set of buffers in a single
  * operation. The corresponding interface for read operations is
  * {@link ScatteringByteChannel}.
- * 
- * @since Android 1.0
  */
 public interface GatheringByteChannel extends WritableByteChannel {
 
@@ -33,8 +30,7 @@
      * Writes bytes from all the given buffers to a channel.
      * <p>
      * This method is equivalent to: {@code write(buffers, 0, buffers.length);}
-     * </p>
-     * 
+     *
      * @param buffers
      *            the buffers containing bytes to be written.
      * @return the number of bytes actually written.
@@ -43,7 +39,7 @@
      *             operation.
      * @throws ClosedByInterruptException
      *             if another thread interrupts the calling thread while the
-     *             operation is in progress. The interrupt state of the calling 
+     *             operation is in progress. The interrupt state of the calling
      *             thread is set and the channel is closed.
      * @throws ClosedChannelException
      *             if the channel is closed.
@@ -56,19 +52,17 @@
      * @throws NonWritableChannelException
      *             if the channel has not been opened in a mode that permits
      *             writing.
-     * @since Android 1.0
      */
     public long write(ByteBuffer[] buffers) throws IOException;
 
     /**
-     * Writes bytes from a subset of the specified array of buffers to a
-     * channel. The subset is defined by {@code offset} and {@code length},
-     * indicating the first buffer and the number of buffers to use.
+     * Attempts to write all <code>remaining()</code> bytes from {@code length}
+     * byte buffers, in order, starting at {@code buffers[offset]}. The number
+     * of bytes actually written is returned.
      * <p>
      * If a write operation is in progress, subsequent threads will block until
      * the write is completed and then contend for the ability to write.
-     * </p>
-     * 
+     *
      * @param buffers
      *            the array of byte buffers that is the source for bytes written
      *            to the channel.
@@ -83,7 +77,7 @@
      *             operation.
      * @throws ClosedByInterruptException
      *             if another thread interrupts the calling thread while the
-     *             operation is in progress. The interrupt state of the calling 
+     *             operation is in progress. The interrupt state of the calling
      *             thread is set and the channel is closed.
      * @throws ClosedChannelException
      *             if the channel is closed.
@@ -95,7 +89,6 @@
      *             if another I/O error occurs; details are in the message.
      * @throws NonWritableChannelException
      *             if the channel was not opened for writing.
-     * @since Android 1.0
      */
     public long write(ByteBuffer[] buffers, int offset, int length)
             throws IOException;
diff --git a/nio/src/main/java/java/nio/channels/IllegalBlockingModeException.java b/nio/src/main/java/java/nio/channels/IllegalBlockingModeException.java
index 3efd94a..5495321 100644
--- a/nio/src/main/java/java/nio/channels/IllegalBlockingModeException.java
+++ b/nio/src/main/java/java/nio/channels/IllegalBlockingModeException.java
@@ -16,13 +16,10 @@
 
 package java.nio.channels;
 
-
 /**
  * An {@code IllegalBlockingModeException} is thrown when an operation that
  * requires a specific blocking mode is invoked on a channel that is in a
  * different blocking mode.
- * 
- * @since Android 1.0
  */
 public class IllegalBlockingModeException extends IllegalStateException {
 
@@ -30,8 +27,6 @@
 
     /**
      * Constructs a {@code IllegalBlockingModeException}.
-     * 
-     * @since Android 1.0
      */
     public IllegalBlockingModeException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/IllegalSelectorException.java b/nio/src/main/java/java/nio/channels/IllegalSelectorException.java
index 0cffd22..a40e2cb 100644
--- a/nio/src/main/java/java/nio/channels/IllegalSelectorException.java
+++ b/nio/src/main/java/java/nio/channels/IllegalSelectorException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * An {@code IllegalSelectorException} is thrown when a call is made to register
  * a channel on a selector that has been created by a different provider.
- * 
- * @since Android 1.0
  */
 public class IllegalSelectorException extends IllegalArgumentException {
 
@@ -29,11 +26,8 @@
 
     /**
      * Constructs a {@code IllegalSelectorException}.
-     * 
-     * @since Android 1.0
      */
     public IllegalSelectorException() {
         super();
     }
-
 }
diff --git a/nio/src/main/java/java/nio/channels/InterruptibleChannel.java b/nio/src/main/java/java/nio/channels/InterruptibleChannel.java
index 0375618..b871c41 100644
--- a/nio/src/main/java/java/nio/channels/InterruptibleChannel.java
+++ b/nio/src/main/java/java/nio/channels/InterruptibleChannel.java
@@ -16,7 +16,6 @@
 
 package java.nio.channels;
 
-
 import java.io.IOException;
 
 /**
@@ -27,7 +26,6 @@
  * an I/O operation (the I/O thread) can be released by another thread calling
  * the channel's {@link #close()} method. The I/O thread will throw an
  * {@link AsynchronousCloseException} and the channel will be closed.
- * </p>
  * <p>
  * A channel that is interruptible permits a thread blocked on an I/O operation
  * (the I/O thread) to be interrupted by another thread (by invoking
@@ -36,8 +34,6 @@
  * its interrupted status set and the channel will be closed. If the I/O thread
  * attempts to make an I/O call with the interrupt status set the call will
  * immediately fail with a {@link ClosedByInterruptException}.
- * 
- * @since Android 1.0
  */
 public interface InterruptibleChannel extends Channel {
 
@@ -47,12 +43,9 @@
      * Any threads that are blocked on I/O operations on this channel will be
      * interrupted with an {@link AsynchronousCloseException}. Otherwise, this
      * method behaves the same as defined in the {@code Channel} interface.
-     * </p>
      * 
      * @throws IOException
      *             if an I/O error occurs while closing the channel.
-     * @since Android 1.0
      */
     public void close() throws IOException;
-
 }
diff --git a/nio/src/main/java/java/nio/channels/NoConnectionPendingException.java b/nio/src/main/java/java/nio/channels/NoConnectionPendingException.java
index 3434b87..34b3e5a 100644
--- a/nio/src/main/java/java/nio/channels/NoConnectionPendingException.java
+++ b/nio/src/main/java/java/nio/channels/NoConnectionPendingException.java
@@ -16,15 +16,12 @@
 
 package java.nio.channels;
 
-
 /**
  * A {@code NoConnectionPendingException} is thrown if {@code SocketChannel}'s
  * {@link SocketChannel#finishConnect() finishConnect} method is called before
- * the {@code SocketChannel}'s
- * {@link SocketChannel#connect(SocketAddress) connect} method completed without
- * error.
- * 
- * @since Android 1.0
+ * the {@code SocketChannel}'s {@link
+ * SocketChannel#connect(java.net.SocketAddress)} connect} method completed
+ * without error.
  */
 public class NoConnectionPendingException extends IllegalStateException {
 
@@ -32,8 +29,6 @@
 
     /**
      * Constructs a {@code NoConnectionPendingException}.
-     * 
-     * @since Android 1.0
      */
     public NoConnectionPendingException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/NonReadableChannelException.java b/nio/src/main/java/java/nio/channels/NonReadableChannelException.java
index c436682..51e3cd3 100644
--- a/nio/src/main/java/java/nio/channels/NonReadableChannelException.java
+++ b/nio/src/main/java/java/nio/channels/NonReadableChannelException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * A {@code NonReadableChannelException} is thrown when attempting to read from
  * a channel that is not open for reading.
- * 
- * @since Android 1.0
  */
 public class NonReadableChannelException extends IllegalStateException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs a {@code NonReadableChannelException}.
-     * 
-     * @since Android 1.0
      */
     public NonReadableChannelException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/NonWritableChannelException.java b/nio/src/main/java/java/nio/channels/NonWritableChannelException.java
index 81549cb..acc6305 100644
--- a/nio/src/main/java/java/nio/channels/NonWritableChannelException.java
+++ b/nio/src/main/java/java/nio/channels/NonWritableChannelException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * A {@code NonWritableChannelException} is thrown when attempting to write to a
  * channel that is not open for writing.
- * 
- * @since Android 1.0
  */
 public class NonWritableChannelException extends IllegalStateException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs a {@code NonWritableChannelException}.
-     * 
-     * @since Android 1.0
      */
     public NonWritableChannelException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/NotYetBoundException.java b/nio/src/main/java/java/nio/channels/NotYetBoundException.java
index 2210903..d2ffc55 100644
--- a/nio/src/main/java/java/nio/channels/NotYetBoundException.java
+++ b/nio/src/main/java/java/nio/channels/NotYetBoundException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * A {@code NotYetBoundException} is thrown if the server socket channel is not
  * bound before an I/O operation is made.
- * 
- * @since Android 1.0
  */
 public class NotYetBoundException extends IllegalStateException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs a {@code NotYetBoundException}.
-     * 
-     * @since Android 1.0
      */
     public NotYetBoundException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/NotYetConnectedException.java b/nio/src/main/java/java/nio/channels/NotYetConnectedException.java
index 393c77f..da3523a 100644
--- a/nio/src/main/java/java/nio/channels/NotYetConnectedException.java
+++ b/nio/src/main/java/java/nio/channels/NotYetConnectedException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * A {@code NotYetConnectedException} is thrown if the socket channel is not
  * connected before an I/O operation is invoked.
- * 
- * @since Android 1.0
  */
 public class NotYetConnectedException extends IllegalStateException {
 
@@ -29,11 +26,8 @@
 
     /**
      * Constructs a {@code NotYetConnectedException}.
-     * 
-     * @since Android 1.0
      */
     public NotYetConnectedException() {
         super();
     }
-
 }
diff --git a/nio/src/main/java/java/nio/channels/OverlappingFileLockException.java b/nio/src/main/java/java/nio/channels/OverlappingFileLockException.java
index 6a00a6b..98fab94 100644
--- a/nio/src/main/java/java/nio/channels/OverlappingFileLockException.java
+++ b/nio/src/main/java/java/nio/channels/OverlappingFileLockException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * An {@code OverlappingFileLockException} is thrown when attempting to acquire
  * a lock that overlaps an existing or pending lock held by this process.
- * 
- * @since Android 1.0
  */
 public class OverlappingFileLockException extends IllegalStateException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs a {@code OverlappingFileLockException}.
-     * 
-     * @since Android 1.0
      */
     public OverlappingFileLockException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/Pipe.java b/nio/src/main/java/java/nio/channels/Pipe.java
index e28812c..956e69b 100644
--- a/nio/src/main/java/java/nio/channels/Pipe.java
+++ b/nio/src/main/java/java/nio/channels/Pipe.java
@@ -25,13 +25,11 @@
  * is the readable source channel. When bytes are written into the writable
  * channel they can be read from the readable channel. The order of these bytes
  * remains unchanged.
- * @since Android 1.0
  */
 public abstract class Pipe {
 
     /**
      * Writable sink channel used to write to a pipe.
-     * @since Android 1.0
      */
     public static abstract class SinkChannel extends AbstractSelectableChannel
             implements WritableByteChannel, GatheringByteChannel {
@@ -41,7 +39,6 @@
          * 
          * @param provider
          *            the provider of the channel.
-         * @since Android 1.0
          */
         protected SinkChannel(SelectorProvider provider) {
             super(provider);
@@ -51,8 +48,8 @@
          * Indicates that this channel only supports writing.
          * 
          * @return a static value of OP_WRITE.
-         * @since Android 1.0
          */
+        @Override
         public final int validOps() {
             return SelectionKey.OP_WRITE;
         }
@@ -60,7 +57,6 @@
 
     /**
      * Readable source channel used to read from a pipe.
-     * @since Android 1.0
      */
     public static abstract class SourceChannel extends
             AbstractSelectableChannel implements ReadableByteChannel,
@@ -71,7 +67,6 @@
          * 
          * @param provider
          *            the provider of the channel.
-         * @since Android 1.0
          */
         protected SourceChannel(SelectorProvider provider) {
             super(provider);
@@ -81,8 +76,8 @@
          * Indicates that this channel only supports reading.
          * 
          * @return a static value of OP_READ.
-         * @since Android 1.0
          */
+        @Override
         public final int validOps() {
             return SelectionKey.OP_READ;
         }
@@ -96,7 +91,6 @@
      * 
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public static Pipe open() throws IOException {
         return SelectorProvider.provider().openPipe();
@@ -104,8 +98,6 @@
 
     /**
      * The protected default constructor.
-     * 
-     * @since Android 1.0
      */
     protected Pipe() {
         super();
@@ -115,7 +107,6 @@
      * Returns the sink channel of the pipe.
      * 
      * @return a writable sink channel of the pipe.
-     * @since Android 1.0
      */
     public abstract SinkChannel sink();
 
@@ -123,7 +114,6 @@
      * Returns the source channel of the pipe.
      * 
      * @return a readable source channel of the pipe.
-     * @since Android 1.0
      */
     public abstract SourceChannel source();
 
diff --git a/nio/src/main/java/java/nio/channels/ReadableByteChannel.java b/nio/src/main/java/java/nio/channels/ReadableByteChannel.java
index 9be1a72..649b64c 100644
--- a/nio/src/main/java/java/nio/channels/ReadableByteChannel.java
+++ b/nio/src/main/java/java/nio/channels/ReadableByteChannel.java
@@ -16,7 +16,6 @@
 
 package java.nio.channels;
 
-
 import java.io.IOException;
 import java.nio.ByteBuffer;
 
@@ -28,9 +27,6 @@
  * if a read is already in progress on the channel then subsequent reads will
  * block until the first read completes. It is undefined whether non-read
  * operations will block.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface ReadableByteChannel extends Channel {
 
@@ -42,17 +38,14 @@
      * buffer when the method is invoked. The bytes will be read into the buffer
      * starting at the buffer's current
      * {@link java.nio.Buffer#position() position}.
-     * </p>
      * <p>
      * The call may block if other threads are also attempting to read from the
      * same channel.
-     * </p>
      * <p>
      * Upon completion, the buffer's {@code position} is updated to the end of
      * the bytes that were read. The buffer's
      * {@link java.nio.Buffer#limit() limit} is not changed.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the byte buffer to receive the bytes.
      * @return the number of bytes actually read.
@@ -60,7 +53,7 @@
      *             if another thread closes the channel during the read.
      * @throws ClosedByInterruptException
      *             if another thread interrupts the calling thread while the
-     *             operation is in progress. The interrupt state of the calling 
+     *             operation is in progress. The interrupt state of the calling
      *             thread is set and the channel is closed.
      * @throws ClosedChannelException
      *             if the channel is closed.
@@ -68,7 +61,6 @@
      *             another I/O error occurs, details are in the message.
      * @throws NonReadableChannelException
      *             if the channel was not opened for reading.
-     * @since Android 1.0
      */
     public int read(ByteBuffer buffer) throws IOException;
 }
diff --git a/nio/src/main/java/java/nio/channels/ScatteringByteChannel.java b/nio/src/main/java/java/nio/channels/ScatteringByteChannel.java
index 2e654db..d25f69c 100644
--- a/nio/src/main/java/java/nio/channels/ScatteringByteChannel.java
+++ b/nio/src/main/java/java/nio/channels/ScatteringByteChannel.java
@@ -16,7 +16,6 @@
 
 package java.nio.channels;
 
-
 import java.io.IOException;
 import java.nio.ByteBuffer;
 
@@ -24,8 +23,6 @@
  * The interface for channels that can read data into a set of buffers in a
  * single operation. The corresponding interface for writes is
  * {@link GatheringByteChannel}.
- * 
- * @since Android 1.0
  */
 public interface ScatteringByteChannel extends ReadableByteChannel {
 
@@ -33,8 +30,7 @@
      * Reads bytes from this channel into the specified array of buffers.
      * <p>
      * This method is equivalent to {@code read(buffers, 0, buffers.length);}
-     * </p>
-     * 
+     *
      * @param buffers
      *            the array of byte buffers to store the bytes being read.
      * @return the number of bytes actually read.
@@ -43,7 +39,7 @@
      *             operation.
      * @throws ClosedByInterruptException
      *             if another thread interrupts the calling thread while the
-     *             operation is in progress. The interrupt state of the calling 
+     *             operation is in progress. The interrupt state of the calling
      *             thread is set and the channel is closed.
      * @throws ClosedChannelException
      *             if the channel is closed.
@@ -52,21 +48,16 @@
      * @throws NonWritableChannelException
      *             if the channel has not been opened in a mode that permits
      *             reading.
-     * @since Android 1.0
      */
     public long read(ByteBuffer[] buffers) throws IOException;
 
     /**
-     * Reads bytes from this channel and stores them in a subset of the
-     * specified array of buffers. The subset is defined by {@code offset} and
-     * {@code length}, indicating the first buffer and the number of buffers to
-     * use. This method attempts to read as many bytes as can be stored in the
-     * buffer subset from the channel and returns the number of bytes actually
-     * read.
+     * Attempts to read all {@code remaining()} bytes from {@code length} byte
+     * buffers, in order, starting at {@code buffers[offset]}. The number of
+     * bytes actually read is returned.
      * <p>
      * If a read operation is in progress, subsequent threads will block until
      * the read is completed and will then contend for the ability to read.
-     * </p>
      * 
      * @param buffers
      *            the array of byte buffers into which the bytes will be copied.
@@ -80,7 +71,7 @@
      *             operation.
      * @throws ClosedByInterruptException
      *             if another thread interrupts the calling thread while the
-     *             operation is in progress. The interrupt state of the calling 
+     *             operation is in progress. The interrupt state of the calling
      *             thread is set and the channel is closed.
      * @throws ClosedChannelException
      *             if the channel is closed.
@@ -93,9 +84,7 @@
      * @throws NonWritableChannelException
      *             if the channel has not been opened in a mode that permits
      *             reading.
-     * @since Android 1.0
      */
     public long read(ByteBuffer[] buffers, int offset, int length)
             throws IOException;
-
 }
diff --git a/nio/src/main/java/java/nio/channels/SelectableChannel.java b/nio/src/main/java/java/nio/channels/SelectableChannel.java
index ded66e6..6ac9a51 100644
--- a/nio/src/main/java/java/nio/channels/SelectableChannel.java
+++ b/nio/src/main/java/java/nio/channels/SelectableChannel.java
@@ -16,7 +16,6 @@
 
 package java.nio.channels;
 
-
 import java.io.IOException;
 import java.nio.channels.spi.AbstractInterruptibleChannel;
 import java.nio.channels.spi.SelectorProvider;
@@ -31,16 +30,12 @@
  * <p>
  * A channel may be registered with several selectors at the same time but only
  * once for any given selector.
- * </p>
- * @since Android 1.0
  */
 public abstract class SelectableChannel extends AbstractInterruptibleChannel
         implements Channel {
 
     /**
      * Constructs a new {@code SelectableChannel}.
-     * 
-     * @since Android 1.0
      */
     protected SelectableChannel() {
         super();
@@ -51,7 +46,6 @@
      * and {@code register} methods.
      * 
      * @return the blocking object as lock.
-     * @since Android 1.0
      */
     public abstract Object blockingLock();
 
@@ -74,7 +68,6 @@
      *             registered with at least one selector.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public abstract SelectableChannel configureBlocking(boolean block)
             throws IOException;
@@ -84,7 +77,6 @@
      * 
      * @return {@code true} if this channel is blocking, undefined if this
      *         channel is closed.
-     * @since Android 1.0
      */
     public abstract boolean isBlocking();
 
@@ -93,7 +85,6 @@
      * 
      * @return {@code true} if this channel is registered, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isRegistered();
 
@@ -104,7 +95,6 @@
      *            the selector with which this channel has been registered.
      * @return the selection key for the channel or {@code null} if this channel
      *         has not been registered with {@code sel}.
-     * @since Android 1.0
      */
     public abstract SelectionKey keyFor(Selector sel);
 
@@ -112,7 +102,6 @@
      * Gets the provider of this channel.
      * 
      * @return the provider of this channel.
-     * @since Android 1.0
      */
     public abstract SelectorProvider provider();
 
@@ -129,12 +118,10 @@
      * blocked until the other call finishes. After that, it will synchronize on
      * the key set of the selector and thus may again block if other threads
      * also hold locks on the key set of the same selector.
-     * </p>
      * <p>
      * Calling this method is equivalent to calling
      * {@code register(selector, operations, null)}.
-     * </p>
-     * 
+     *
      * @param selector
      *            the selector with which to register this channel.
      * @param operations
@@ -151,7 +138,6 @@
      *             if this channel is registered but its key has been canceled.
      * @throws IllegalArgumentException
      *             if the operation given is not supported by this channel.
-     * @since Android 1.0
      */
     public final SelectionKey register(Selector selector, int operations)
             throws ClosedChannelException {
@@ -171,8 +157,7 @@
      * blocked until the other call finishes. After that, it will synchronize on
      * the key set of the selector and thus may again block if other threads
      * also hold locks on the key set of the same selector.
-     * </p>
-     * 
+     *
      * @param sel
      *            the selector with which to register this channel.
      * @param ops
@@ -191,18 +176,15 @@
      *             selector.
      * @throws CancelledKeyException
      *             if this channel is registered but its key has been canceled.
-     * @since Android 1.0
      */
     public abstract SelectionKey register(Selector sel, int ops, Object att)
             throws ClosedChannelException;
 
     /**
      * Gets the set of valid {@link SelectionKey operations} of this channel.
-     * Instances of a concrete channel class always return the same value. 
-     * 
+     * Instances of a concrete channel class always return the same value.
+     *
      * @return the set of operations that this channel supports.
-     * @since Android 1.0
      */
     public abstract int validOps();
-
 }
diff --git a/nio/src/main/java/java/nio/channels/SelectionKey.java b/nio/src/main/java/java/nio/channels/SelectionKey.java
index b3773fa..d00627e 100644
--- a/nio/src/main/java/java/nio/channels/SelectionKey.java
+++ b/nio/src/main/java/java/nio/channels/SelectionKey.java
@@ -32,36 +32,26 @@
  * <h4>Ready set</h4>
  * The ready set is an operation set that shows the operations that a
  * {@code channel} is ready to execute.
- * 
- * @since Android 1.0
  */
 public abstract class SelectionKey {
 
     /**
      * Interest set mask bit for socket-accept operations.
-     * 
-     * @since Android 1.0
      */
     public static final int OP_ACCEPT = 16;
 
     /**
      * Interest set mask bit for socket-connect operations.
-     * 
-     * @since Android 1.0
      */
     public static final int OP_CONNECT = 8;
 
     /**
      * Interesting operation mask bit for read operations.
-     * 
-     * @since Android 1.0
      */
     public static final int OP_READ = 1;
 
     /**
      * Interest set mask bit for write operations.
-     * 
-     * @since Android 1.0
      */
     public static final int OP_WRITE = 4;
 
@@ -69,8 +59,6 @@
 
     /**
      * Constructs a new {@code SelectionKey}.
-     * 
-     * @since Android 1.0
      */
     protected SelectionKey() {
         super();
@@ -85,7 +73,6 @@
      *            attachment.
      * @return the last attached object or {@code null} if no object has been
      *         attached.
-     * @since Android 1.0
      */
     public final Object attach(Object anObject) {
         Object oldAttachment = attachment;
@@ -98,7 +85,6 @@
      * 
      * @return the attached object or {@code null} if no object has been
      *         attached.
-     * @since Android 1.0
      */
     public final Object attachment() {
         return attachment;
@@ -109,7 +95,6 @@
      * <p>
      * A key that has been canceled is no longer valid. Calling this method on
      * an already canceled key does nothing.
-     * </p>
      * <p>
      * Calling this method is safe at any time. The call might block until
      * another ongoing call to a method of this selector has finished. The
@@ -117,9 +102,6 @@
      * this call finishes, the key will have been added to the selectors
      * canceled-keys set and will not be included in any future selects of this
      * selector.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     public abstract void cancel();
 
@@ -127,7 +109,6 @@
      * Gets the channel of this key.
      * 
      * @return the channel of this key.
-     * @since Android 1.0
      */
     public abstract SelectableChannel channel();
 
@@ -138,7 +119,6 @@
      * @return the interest set of this key.
      * @throws CancelledKeyException
      *             if the key has already been canceled.
-     * @since Android 1.0
      */
     public abstract int interestOps();
 
@@ -154,7 +134,6 @@
      *             key's channel.
      * @throws CancelledKeyException
      *             if the key has already been canceled.
-     * @since Android 1.0
      */
     public abstract SelectionKey interestOps(int operations);
 
@@ -167,7 +146,6 @@
      *         and is ready to accept new connections, {@code false} otherwise.
      * @throws CancelledKeyException
      *             if the key has already been canceled.
-     * @since Android 1.0
      */
     public final boolean isAcceptable() {
         return (readyOps() & OP_ACCEPT) == OP_ACCEPT;
@@ -182,8 +160,7 @@
      *         operation and is ready to connect, {@code false} otherwise.
      * @throws CancelledKeyException
      *             if the key has already been canceled.
-     * @since Android 1.0
-     */    
+     */
     public final boolean isConnectable() {
         return (readyOps() & OP_CONNECT) == OP_CONNECT;
     }
@@ -197,7 +174,6 @@
      *         and is ready to read, {@code false} otherwise.
      * @throws CancelledKeyException
      *             if the key has already been canceled.
-     * @since Android 1.0
      */
     public final boolean isReadable() {
         return (readyOps() & OP_READ) == OP_READ;
@@ -209,7 +185,6 @@
      * 
      * @return {@code true} if this key has not been canceled, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isValid();
 
@@ -222,7 +197,6 @@
      *         and is ready to write, {@code false} otherwise.
      * @throws CancelledKeyException
      *             if the key has already been canceled.
-     * @since Android 1.0
      */
     public final boolean isWritable() {
         return (readyOps() & OP_WRITE) == OP_WRITE;
@@ -235,7 +209,6 @@
      * @return the operations for which this key's channel is ready.
      * @throws CancelledKeyException
      *             if the key has already been canceled.
-     * @since Android 1.0
      */
     public abstract int readyOps();
 
@@ -243,7 +216,6 @@
      * Gets the selector for which this key's channel is registered.
      * 
      * @return the related selector.
-     * @since Android 1.0
      */
     public abstract Selector selector();
 }
diff --git a/nio/src/main/java/java/nio/channels/Selector.java b/nio/src/main/java/java/nio/channels/Selector.java
index d417f51..8d43f4b 100644
--- a/nio/src/main/java/java/nio/channels/Selector.java
+++ b/nio/src/main/java/java/nio/channels/Selector.java
@@ -32,9 +32,6 @@
  * canceled keys. During the select operation, the channels registered with this
  * selector are checked to see whether they are ready for operation according to
  * their {@link SelectionKey interest set}.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class Selector {
 
@@ -46,7 +43,6 @@
      * @return a new selector.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public static Selector open() throws IOException {
         return SelectorProvider.provider().openSelector();
@@ -54,8 +50,6 @@
 
     /**
      * Constructs a new {@code Selector}.
-     * 
-     * @since Android 1.0
      */
     protected Selector() {
         super();
@@ -71,11 +65,9 @@
      * Any further attempt of using this selector after this method has been
      * called (except calling {@link #close()} or {@link #wakeup()}) results in
      * a {@link ClosedSelectorException} being thrown.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public abstract void close() throws IOException;
 
@@ -84,7 +76,6 @@
      * 
      * @return {@code true} if this selector is not closed, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isOpen();
 
@@ -93,7 +84,6 @@
      * safe.
      * 
      * @return the set of registered keys.
-     * @since Android 1.0
      */
     public abstract Set<SelectionKey> keys();
 
@@ -101,7 +91,6 @@
      * Gets the provider of this selector.
      * 
      * @return the provider of this selector.
-     * @since Android 1.0
      */
     public abstract SelectorProvider provider();
 
@@ -116,7 +105,6 @@
      *             if an I/O error occurs.
      * @throws ClosedSelectorException
      *             if the selector is closed.
-     * @since Android 1.0
      */
     public abstract int select() throws IOException;
 
@@ -137,7 +125,6 @@
      *             if the given timeout argument is less than zero.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public abstract int select(long timeout) throws IOException;
 
@@ -149,7 +136,6 @@
      * @return the selection keys whose channels are ready for operation.
      * @throws ClosedSelectorException
      *             if the selector is closed.
-     * @since Android 1.0
      */
     public abstract Set<SelectionKey> selectedKeys();
 
@@ -164,7 +150,6 @@
      *             if an I/O error occurrs.
      * @throws ClosedSelectorException
      *             if the selector is closed.
-     * @since Android 1.0
      */
     public abstract int selectNow() throws IOException;
 
@@ -176,12 +161,10 @@
      * be undone by a call to {@code selectNow()}; after calling
      * {@code selectNow()}, a subsequent call of {@code select} can block
      * again.
-     * </p>
-     * 
+     *
      * @return this selector.
      * @throws ClosedSelectorException
      *             if the selector is closed.
-     * @since Android 1.0
      */
     public abstract Selector wakeup();
 }
diff --git a/nio/src/main/java/java/nio/channels/ServerSocketChannel.java b/nio/src/main/java/java/nio/channels/ServerSocketChannel.java
index 8ecb183..b0508fa 100644
--- a/nio/src/main/java/java/nio/channels/ServerSocketChannel.java
+++ b/nio/src/main/java/java/nio/channels/ServerSocketChannel.java
@@ -33,9 +33,6 @@
  * open()} method. Calling {@code accept} before bound will cause a
  * {@link NotYetBoundException}. It can be bound by calling the bind method of a
  * related {@code ServerSocket} instance.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class ServerSocketChannel extends AbstractSelectableChannel {
 
@@ -44,7 +41,6 @@
      * 
      * @param selectorProvider
      *            an instance of SelectorProvider.
-     * @since Android 1.0
      */
     protected ServerSocketChannel(SelectorProvider selectorProvider) {
         super(selectorProvider);
@@ -55,12 +51,10 @@
      * <p>
      * This channel is created by calling {@code openServerSocketChannel} method
      * of the default {@code SelectorProvider} instance.
-     * </p>
-     * 
+     *
      * @return the new channel which is open but unbound.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public static ServerSocketChannel open() throws IOException {
         return SelectorProvider.provider().openServerSocketChannel();
@@ -73,8 +67,8 @@
      * 
      * @see java.nio.channels.SelectableChannel#validOps()
      * @return the operations supported by this channel.
-     * @since Android 1.0
      */
+    @Override
     public final int validOps() {
         return SelectionKey.OP_ACCEPT;
     }
@@ -84,7 +78,6 @@
      * any public methods that are not declared in {@code ServerSocket}.
      * 
      * @return the server-socket assigned to this channel.
-     * @since Android 1.0
      */
     public abstract ServerSocket socket();
 
@@ -95,11 +88,9 @@
      * connection is available, otherwise it blocks until a new connection is
      * available or an I/O error occurs. The socket channel returned by this
      * method will always be in blocking mode.
-     * </p>
      * <p>
      * This method just executes the same security checks as the {@code
      * accept()} method of the {@link ServerSocket} class.
-     * </p>
      * 
      * @return the accepted {@code SocketChannel} instance, or {@code null} if
      *         the channel is non-blocking and no connection is available.
@@ -119,8 +110,6 @@
      * @throws SecurityException
      *             if there is a security manager and it does not permit to
      *             access the new connection.
-     * @since Android 1.0
      */
     public abstract SocketChannel accept() throws IOException;
-
 }
diff --git a/nio/src/main/java/java/nio/channels/SocketChannel.java b/nio/src/main/java/java/nio/channels/SocketChannel.java
index a709dee..40003ea 100644
--- a/nio/src/main/java/java/nio/channels/SocketChannel.java
+++ b/nio/src/main/java/java/nio/channels/SocketChannel.java
@@ -39,7 +39,6 @@
  * connecting. {@code isConnectionPending()} indicates if the connection is
  * blocked or not; {@code isConnected()} indicates if the socket is finally
  * connected or not.
- * </p>
  * <p>
  * The input and output sides of a channel can be shut down independently and
  * asynchronously without closing the channel. The {@code shutdownInput} method
@@ -51,15 +50,11 @@
  * {@link ClosedChannelException}. If the output is shut down and another thread
  * is blocked in a write operation, an {@link AsynchronousCloseException} will
  * be thrown to the pending thread.
- * </p>
  * <p>
  * Socket channels are thread-safe, no more than one thread can read or write at
  * any given time. The {@code connect(SocketAddress)} and {@code
  * finishConnect()} methods are synchronized against each other; when they are
  * processing, calls to {@code read} and {@code write} will block.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class SocketChannel extends AbstractSelectableChannel implements
         ByteChannel, ScatteringByteChannel, GatheringByteChannel {
@@ -67,13 +62,12 @@
     static {
         Platform.getNetworkSystem().oneTimeInitialization(true);
     }
-    
+
     /**
      * Constructs a new {@code SocketChannel}.
      * 
      * @param selectorProvider
      *            an instance of SelectorProvider.
-     * @since Android 1.0
      */
     protected SocketChannel(SelectorProvider selectorProvider) {
         super(selectorProvider);
@@ -84,12 +78,10 @@
      * <p>
      * This channel is created by calling {@code openSocketChannel()} of the
      * default {@link SelectorProvider} instance.
-     * </p>
-     * 
+     *
      * @return the new channel which is open but unconnected.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public static SocketChannel open() throws IOException {
         return SelectorProvider.provider().openSocketChannel();
@@ -100,8 +92,7 @@
      * <p>
      * This method performs a call to {@code open()} followed by a call to
      * {@code connect(SocketAdress)}.
-     * </p>
-     * 
+     *
      * @param address
      *            the socket address to be connected to.
      * @return the new connected channel.
@@ -121,7 +112,6 @@
      *             if the address type is not supported.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public static SocketChannel open(SocketAddress address) throws IOException {
         SocketChannel socketChannel = open();
@@ -138,8 +128,8 @@
      * 
      * @return the operations supported by this channel.
      * @see java.nio.channels.SelectableChannel#validOps()
-     * @since Android 1.0
      */
+    @Override
     public final int validOps() {
         return (SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
     }
@@ -149,7 +139,6 @@
      * methods that are not declared in {@code Socket}.
      * 
      * @return the socket assigned to this channel.
-     * @since Android 1.0
      */
     public abstract Socket socket();
 
@@ -158,7 +147,6 @@
      * 
      * @return {@code true} if this channel's socket is connected, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isConnected();
 
@@ -167,7 +155,6 @@
      * 
      * @return {@code true} if the connection is initiated but not finished;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isConnectionPending();
 
@@ -179,13 +166,11 @@
      * this method will return {@code true} if the connection is finished at
      * once or return {@code false} when the connection must be finished later
      * by calling {@code finishConnect()}.
-     * </p>
      * <p>
      * This method can be called at any moment and can block other read and
      * write operations while connecting. It executes the same security checks
      * as the connect method of the {@code Socket} class.
-     * </p>
-     * 
+     *
      * @param address
      *            the address to connect with.
      * @return {@code true} if the connection is finished, {@code false}
@@ -213,7 +198,6 @@
      *             {@code address}.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public abstract boolean connect(SocketAddress address) throws IOException;
 
@@ -224,17 +208,14 @@
      * This method returns {@code true} if the connection is finished already
      * and returns {@code false} if the channel is non-blocking and the
      * connection is not finished yet.
-     * </p>
      * <p>
      * If this channel is in blocking mode, this method will suspend and return
      * {@code true} when the connection is finished. It closes this channel and
      * throws an exception if the connection fails.
-     * </p>
      * <p>
      * This method can be called at any moment and it can block other {@code
      * read} and {@code write} operations while connecting.
-     * </p>
-     * 
+     *
      * @return {@code true} if the connection is successfully finished, {@code
      *         false} otherwise.
      * @throws NoConnectionPendingException
@@ -251,7 +232,6 @@
      *             interrupt state set, and this channel is closed.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public abstract boolean finishConnect() throws IOException;
 
@@ -261,16 +241,13 @@
      * The maximum number of bytes that will be read is the remaining number of
      * bytes in the buffer when the method is invoked. The bytes will be copied
      * into the buffer starting at the buffer's current position.
-     * </p>
      * <p>
      * The call may block if other threads are also attempting to read from this
      * channel.
-     * </p>
      * <p>
      * Upon completion, the buffer's position is set to the end of the bytes
      * that have been read. The buffer's limit is not changed.
-     * </p>
-     * 
+     *
      * @param target
      *            the byte buffer to receive the bytes.
      * @return the number of bytes actually read.
@@ -286,22 +263,19 @@
      *             if this channel is closed.
      * @throws IOException
      *             if another I/O error occurs.
-     * @since Android 1.0
+     * @see java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer)
      */
     public abstract int read(ByteBuffer target) throws IOException;
 
     /**
-     * Reads bytes from this socket channel and stores them in a subset of the
-     * specified array of buffers. The subset is defined by {@code offset} and
-     * {@code length}, indicating the first buffer and the number of buffers to
-     * use. This method attempts to read as many bytes as can be stored in the
-     * buffer subset from this channel and returns the number of bytes actually
-     * read.
+     * Reads bytes from this socket channel into a subset of the given buffers.
+     * This method attempts to read all {@code remaining()} bytes from {@code
+     * length} byte buffers, in order, starting at {@code targets[offset]}. The
+     * number of bytes actually read is returned.
      * <p>
      * If a read operation is in progress, subsequent threads will block until
      * the read is completed and will then contend for the ability to read.
-     * </p>
-     * 
+     *
      * @param targets
      *            the array of byte buffers into which the bytes will be copied.
      * @param offset
@@ -325,7 +299,8 @@
      *             if another I/O error occurs.
      * @throws NotYetConnectedException
      *             if this channel is not yet connected.
-     * @since Android 1.0
+     * @see java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[],
+     *      int, int)
      */
     public abstract long read(ByteBuffer[] targets, int offset, int length)
             throws IOException;
@@ -338,12 +313,10 @@
      * <p>
      * If a read operation is in progress, subsequent threads will block until
      * the read is completed and will then contend for the ability to read.
-     * </p>
      * <p>
      * Calling this method is equivalent to calling {@code read(targets, 0,
      * targets.length);}
-     * </p>
-     * 
+     *
      * @param targets
      *            the array of byte buffers into which the bytes will be copied.
      * @return the number of bytes actually read.
@@ -360,7 +333,6 @@
      *             if another I/O error occurs.
      * @throws NotYetConnectedException
      *             if this channel is not yet connected.
-     * @since Android 1.0
      */
     public synchronized final long read(ByteBuffer[] targets)
             throws IOException {
@@ -375,12 +347,10 @@
      * <p>
      * The call may block if other threads are also attempting to write to the
      * same channel.
-     * </p>
      * <p>
      * Upon completion, the buffer's position is updated to the end of the bytes
      * that have been written. The buffer's limit is not changed.
-     * </p>
-     * 
+     *
      * @param source
      *            the byte buffer containing the bytes to be written.
      * @return the number of bytes actually written.
@@ -396,19 +366,19 @@
      *             if another I/O error occurs.
      * @throws NotYetConnectedException
      *             if this channel is not connected yet.
-     * @since Android 1.0
+     * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
      */
     public abstract int write(ByteBuffer source) throws IOException;
 
     /**
-     * Writes bytes from a subset of the specified array of buffers into this
-     * socket channel. The subset is defined by {@code offset} and {@code
-     * length}, indicating the first buffer and the number of buffers to use.
+     * Attempts to write a subset of the given bytes from the buffers to this
+     * socket channel. This method attempts to write all {@code remaining()}
+     * bytes from {@code length} byte buffers, in order, starting at {@code
+     * sources[offset]}. The number of bytes actually written is returned.
      * <p>
      * If a write operation is in progress, subsequent threads will block until
      * the write is completed and then contend for the ability to write.
-     * </p>
-     * 
+     *
      * @param sources
      *            the array of byte buffers that is the source for bytes written
      *            to this channel.
@@ -434,7 +404,8 @@
      *             if another I/O error occurs.
      * @throws NotYetConnectedException
      *             if this channel is not yet connected.
-     * @since Android 1.0
+     * @see java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[],
+     *      int, int)
      */
     public abstract long write(ByteBuffer[] sources, int offset, int length)
             throws IOException;
@@ -444,8 +415,7 @@
      * <p>
      * Calling this method is equivalent to calling {@code write(sources, 0,
      * sources.length);}
-     * </p>
-     * 
+     *
      * @param sources
      *            the buffers containing bytes to write.
      * @return the number of bytes actually written.
@@ -462,7 +432,7 @@
      *             if another I/O error occurs.
      * @throws NotYetConnectedException
      *             if this channel is not yet connected.
-     * @since Android 1.0
+     * @see java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[])
      */
     public synchronized final long write(ByteBuffer[] sources)
             throws IOException {
diff --git a/nio/src/main/java/java/nio/channels/UnresolvedAddressException.java b/nio/src/main/java/java/nio/channels/UnresolvedAddressException.java
index dfb475b..426e84c 100644
--- a/nio/src/main/java/java/nio/channels/UnresolvedAddressException.java
+++ b/nio/src/main/java/java/nio/channels/UnresolvedAddressException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * An {@code UnresolvedAddressException} is thrown when trying to use an
  * unresolved network address in a network operation.
- * 
- * @since Android 1.0
  */
 public class UnresolvedAddressException extends IllegalArgumentException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs an {@code UnresolvedAddressException}.
-     * 
-     * @since Android 1.0
      */
     public UnresolvedAddressException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/UnsupportedAddressTypeException.java b/nio/src/main/java/java/nio/channels/UnsupportedAddressTypeException.java
index ba613ac..62c1515 100644
--- a/nio/src/main/java/java/nio/channels/UnsupportedAddressTypeException.java
+++ b/nio/src/main/java/java/nio/channels/UnsupportedAddressTypeException.java
@@ -16,12 +16,9 @@
 
 package java.nio.channels;
 
-
 /**
  * An {@code UnsupportedAddressTypeException} is thrown when connecting or
  * binding to an unsupported address type.
- * 
- * @since Android 1.0
  */
 public class UnsupportedAddressTypeException extends IllegalArgumentException {
 
@@ -29,8 +26,6 @@
 
     /**
      * Constructs an {@code UnsupportedAddressTypeException}.
-     * 
-     * @since Android 1.0
      */
     public UnsupportedAddressTypeException() {
         super();
diff --git a/nio/src/main/java/java/nio/channels/WritableByteChannel.java b/nio/src/main/java/java/nio/channels/WritableByteChannel.java
index f8ea77f..4a9779a 100644
--- a/nio/src/main/java/java/nio/channels/WritableByteChannel.java
+++ b/nio/src/main/java/java/nio/channels/WritableByteChannel.java
@@ -16,7 +16,6 @@
 
 package java.nio.channels;
 
-
 import java.io.IOException;
 import java.nio.ByteBuffer;
 
@@ -28,8 +27,6 @@
  * if a write is already in progress on the channel then subsequent writes will
  * block until the first write completes. It is undefined whether non-write
  * operations will block.
- * 
- * @since Android 1.0
  */
 public interface WritableByteChannel extends Channel {
 
@@ -40,17 +37,14 @@
      * <code>remaining()</code> number of bytes in the buffer when the method
      * invoked. The bytes will be written from the buffer starting at the
      * buffer's <code>position</code>.
-     * </p>
      * <p>
      * The call may block if other threads are also attempting to write on the
      * same channel.
-     * </p>
      * <p>
      * Upon completion, the buffer's <code>position()</code> is updated to the
      * end of the bytes that were written. The buffer's <code>limit()</code>
      * is unmodified.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the byte buffer containing the bytes to be written.
      * @return the number of bytes actually written.
@@ -65,7 +59,6 @@
      *             write.
      * @throws IOException
      *             another IO exception occurs, details are in the message.
-     * @since Android 1.0
      */
     public int write(ByteBuffer buffer) throws IOException;
 }
diff --git a/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java b/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java
index 8f84e109..878f731 100644
--- a/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java
+++ b/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java
@@ -24,6 +24,7 @@
 import java.nio.channels.ClosedByInterruptException;
 import java.nio.channels.InterruptibleChannel;
 import java.security.AccessController;
+import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 
 /**
@@ -35,10 +36,7 @@
  * indefinitely, then {@code end(boolean)} after completing the operation. The
  * argument to the {@code end} method should indicate if the I/O operation has
  * actually completed so that any change may be visible to the invoker.
- * </p>
- * 
- * @since Android 1.0
- */
+*/
 public abstract class AbstractInterruptibleChannel implements Channel,
         InterruptibleChannel {
 
@@ -56,7 +54,7 @@
                         }
                     });
             setInterruptAction.setAccessible(true);
-        } catch (Exception e) {
+        } catch (PrivilegedActionException e) {
             // FIXME: be accommodate before VM actually provides
             // setInterruptAction method
             // throw new Error(e);
@@ -69,8 +67,6 @@
 
     /**
      * Default constructor.
-     * 
-     * @since Android 1.0
      */
     protected AbstractInterruptibleChannel() {
         super();
@@ -82,7 +78,6 @@
      * @return {@code true} if this channel is open, {@code false} if it is
      *         closed.
      * @see java.nio.channels.Channel#isOpen()
-     * @since Android 1.0
      */
     public synchronized final boolean isOpen() {
         return !closed;
@@ -95,16 +90,14 @@
      * <p>
      * If an attempt is made to perform an operation on a closed channel then a
      * {@link java.nio.channels.ClosedChannelException} is thrown.
-     * </p>
      * <p>
      * If multiple threads attempt to simultaneously close a channel, then only
      * one thread will run the closure code and the others will be blocked until
      * the first one completes.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             if a problem occurs while closing this channel.
-     * @since Android 1.0
+     * @see java.nio.channels.Channel#close()
      */
     public final void close() throws IOException {
         if (!closed) {
@@ -121,8 +114,6 @@
      * Indicates the beginning of a code section that includes an I/O operation
      * that is potentially blocking. After this operation, the application
      * should invoke the corresponding {@code end(boolean)} method.
-     * 
-     * @since Android 1.0
      */
     protected final void begin() {
         // FIXME: be accommodate before VM actually provides
@@ -159,7 +150,6 @@
      * @throws ClosedByInterruptException
      *             if another thread interrupts the calling thread while this
      *             method is executing.
-     * @since Android 1.0
      */
     protected final void end(boolean success) throws AsynchronousCloseException {
         // FIXME: be accommodate before VM actually provides
@@ -187,16 +177,13 @@
      * Closes the channel with a guarantee that the channel is not currently
      * closed through another invocation of {@code close()} and that the method
      * is thread-safe.
-     * </p>
      * <p>
      * Any outstanding threads blocked on I/O operations on this channel must be
      * released with either a normal return code, or by throwing an
      * {@code AsynchronousCloseException}.
-     * </p>
      * 
      * @throws IOException
      *             if a problem occurs while closing the channel.
-     * @since Android 1.0
      */
     protected abstract void implCloseChannel() throws IOException;
 }
diff --git a/nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java b/nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java
index a9bee52..54092ed 100644
--- a/nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java
+++ b/nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java
@@ -32,8 +32,6 @@
  * {@code AbstractSelectableChannel} is the base implementation class for
  * selectable channels. It declares methods for registering, unregistering and
  * closing selectable channels. It is thread-safe.
- * 
- * @since Android 1.0
  */
 public abstract class AbstractSelectableChannel extends SelectableChannel {
 
@@ -44,7 +42,8 @@
      */
     private List<SelectionKey> keyList = new ArrayList<SelectionKey>();
 
-    private class BlockingLock {
+    // Marker class so lock type shows up in profilers
+    static private class BlockingLock {
     }
 
     private final Object blockingLock = new BlockingLock();
@@ -56,7 +55,6 @@
      * 
      * @param selectorProvider
      *            the selector provider that creates this channel.
-     * @since Android 1.0
      */
     protected AbstractSelectableChannel(SelectorProvider selectorProvider) {
         super();
@@ -68,32 +66,32 @@
      * 
      * @see java.nio.channels.SelectableChannel#provider()
      * @return this channel's selector provider.
-     * @since Android 1.0
      */
+    @Override
     public final SelectorProvider provider() {
         return provider;
     }
 
     /**
      * Indicates whether this channel is registered with one or more selectors.
-     * 
+     *
      * @return {@code true} if this channel is registered with a selector,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
+    @Override
     synchronized public final boolean isRegistered() {
         return !keyList.isEmpty();
     }
 
     /**
      * Gets this channel's selection key for the specified selector.
-     * 
+     *
      * @param selector
      *            the selector with which this channel has been registered.
      * @return the selection key for the channel or {@code null} if this channel
      *         has not been registered with {@code selector}.
-     * @since Android 1.0
      */
+    @Override
     synchronized public final SelectionKey keyFor(Selector selector) {
         for (int i = 0; i < keyList.size(); i++) {
             SelectionKey key = keyList.get(i);
@@ -130,8 +128,8 @@
      * @throws IllegalSelectorException
      *             if this channel does not have the same provider as the given
      *             selector.
-     * @since Android 1.0
      */
+    @Override
     public final SelectionKey register(Selector selector, int interestSet,
             Object attachment) throws ClosedChannelException {
         if (!isOpen()) {
@@ -153,10 +151,6 @@
                 // throw NPE exactly to keep consistency
                 throw new NullPointerException();
             }
-            if (0 == interestSet) {
-                // throw ISE exactly to keep consistency
-                throw new IllegalSelectorException();
-            }
             SelectionKey key = keyFor(selector);
             if (null == key) {
                 key = ((AbstractSelector) selector).register(this, interestSet,
@@ -181,8 +175,8 @@
      * 
      * @throws IOException
      *             if a problem occurs while closing the channel.
-     * @since Android 1.0
      */
+    @Override
     synchronized protected final void implCloseChannel() throws IOException {
         implCloseSelectableChannel();
         for (int i = 0; i < keyList.size(); i++) {
@@ -199,17 +193,16 @@
      * 
      * @throws IOException
      *             if an I/O exception occurs.
-     * @since Android 1.0
      */
     protected abstract void implCloseSelectableChannel() throws IOException;
 
     /**
      * Indicates whether this channel is in blocking mode.
-     * 
+     *
      * @return {@code true} if this channel is blocking, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
+    @Override
     public final boolean isBlocking() {
         synchronized (blockingLock) {
             return isBlocking;
@@ -219,10 +212,10 @@
     /**
      * Gets the object used for the synchronization of {@code register} and
      * {@code configureBlocking}.
-     * 
+     *
      * @return the synchronization object.
-     * @since Android 1.0
      */
+    @Override
     public final Object blockingLock() {
         return blockingLock;
     }
@@ -233,6 +226,7 @@
      * actual setting of the mode is done by calling
      * {@code implConfigureBlocking(boolean)}.
      * 
+     * @see java.nio.channels.SelectableChannel#configureBlocking(boolean)
      * @param blockingMode
      *            {@code true} for setting this channel's mode to blocking,
      *            {@code false} to set it to non-blocking.
@@ -244,8 +238,8 @@
      *             registered with at least one selector.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
+    @Override
     public final SelectableChannel configureBlocking(boolean blockingMode)
             throws IOException {
         if (isOpen()) {
@@ -253,7 +247,7 @@
                 if (isBlocking == blockingMode) {
                     return this;
                 }
-                if (blockingMode && isRegistered()) {
+                if (blockingMode && containsValidKeys()) {
                     throw new IllegalBlockingModeException();
                 }
                 implConfigureBlocking(blockingMode);
@@ -262,7 +256,6 @@
             return this;
         }
         throw new ClosedChannelException();
-
     }
 
     /**
@@ -273,7 +266,6 @@
      *            {@code false} to set it to non-blocking.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     protected abstract void implConfigureBlocking(boolean blockingMode)
             throws IOException;
@@ -287,4 +279,17 @@
         }
     }
 
+    /**
+     * Returns true if the keyList contains at least 1 valid key and false
+     * otherwise.
+     */
+    private synchronized boolean containsValidKeys() {
+        for (int i = 0; i < keyList.size(); i++) {
+            SelectionKey key = keyList.get(i);
+            if (key != null && key.isValid()) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/nio/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java b/nio/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java
index e839126..4c46226 100644
--- a/nio/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java
+++ b/nio/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
 package java.nio.channels.spi;
 
 import java.nio.channels.SelectionKey;
@@ -21,8 +21,6 @@
 /**
  * {@code AbstractSelectionKey} is the base implementation class for selection keys.
  * It implements validation and cancellation methods.
- *
- * @since Android 1.0
  */
 public abstract class AbstractSelectionKey extends SelectionKey {
 
@@ -33,8 +31,6 @@
 
     /**
      * Constructs a new {@code AbstractSelectionKey}.
-     * 
-     * @since Android 1.0
      */
     protected AbstractSelectionKey() {
         super();
@@ -43,11 +39,11 @@
     /**
      * Indicates whether this key is valid. A key is valid as long as it has not
      * been canceled.
-     * 
+     *
      * @return {@code true} if this key has not been canceled, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
+    @Override
     public final boolean isValid() {
         return isValid;
     }
@@ -57,10 +53,8 @@
      * <p>
      * A key that has been canceled is no longer valid. Calling this method on
      * an already canceled key does nothing.
-     * </p>
-     * 
-     * @since Android 1.0
      */
+    @Override
     public final void cancel() {
         if (isValid) {
             isValid = false;
diff --git a/nio/src/main/java/java/nio/channels/spi/AbstractSelector.java b/nio/src/main/java/java/nio/channels/spi/AbstractSelector.java
index adef243..26bbb4f 100644
--- a/nio/src/main/java/java/nio/channels/spi/AbstractSelector.java
+++ b/nio/src/main/java/java/nio/channels/spi/AbstractSelector.java
@@ -22,17 +22,16 @@
 import java.nio.channels.Selector;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * {@code AbstractSelector} is the base implementation class for selectors.
  * It realizes the interruption of selection by {@code begin} and
  * {@code end}. It also holds the cancellation and the deletion of the key
  * set.
- * 
- * @since Android 1.0
  */
 public abstract class AbstractSelector extends Selector {
-    private volatile boolean isOpen = true;
+    private final AtomicBoolean isOpen = new AtomicBoolean(true);
 
     private SelectorProvider provider = null;
 
@@ -46,7 +45,6 @@
      * 
      * @param selectorProvider
      *            the selector provider that creates this selector.
-     * @since Android 1.0
      */
     protected AbstractSelector(SelectorProvider selectorProvider) {
         provider = selectorProvider;
@@ -59,11 +57,10 @@
      * 
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
-    public synchronized final void close() throws IOException {
-        if (isOpen) {
-            isOpen = false;
+    @Override
+    public final void close() throws IOException {
+        if (isOpen.getAndSet(false)) {
             implCloseSelector();
         }
     }
@@ -73,27 +70,26 @@
      * 
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     protected abstract void implCloseSelector() throws IOException;
 
     /**
      * Indicates whether this selector is open.
-     * 
+     *
      * @return {@code true} if this selector is not closed, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
+    @Override
     public final boolean isOpen() {
-        return isOpen;
+        return isOpen.get();
     }
 
     /**
      * Gets this selector's provider.
      * 
      * @return the provider of this selector.
-     * @since Android 1.0
      */
+    @Override
     public final SelectorProvider provider() {
         return provider;
     }
@@ -102,7 +98,6 @@
      * Returns this channel's set of canceled selection keys.
      * 
      * @return the set of canceled selection keys.
-     * @since Android 1.0
      */
     protected final Set<SelectionKey> cancelledKeys() {
         return cancelledKeysSet;
@@ -118,7 +113,6 @@
      * @param attachment
      *            the attachment for the selection key.
      * @return the key related to the channel and this selector.
-     * @since Android 1.0
      */
     protected abstract SelectionKey register(AbstractSelectableChannel channel,
             int operations, Object attachment);
@@ -128,7 +122,6 @@
      * 
      * @param key
      *            the key.
-     * @since Android 1.0
      */
     protected final void deregister(AbstractSelectionKey key) {
         ((AbstractSelectableChannel) key.channel()).deregister(key);
@@ -139,8 +132,6 @@
      * Indicates the beginning of a code section that includes an I/O operation
      * that is potentially blocking. After this operation, the application
      * should invoke the corresponding {@code end(boolean)} method.
-     * 
-     * @since Android 1.0
      */
     protected final void begin() {
         // FIXME: be accommodate before VM actually provides
@@ -162,8 +153,6 @@
     /**
      * Indicates the end of a code section that has been started with
      * {@code begin()} and that includes a potentially blocking I/O operation.
-     * 
-     * @since Android 1.0
      */
     protected final void end() {
         // FIXME: be accommodate before VM actually provides
diff --git a/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java b/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java
index b4b18e3..b474afa 100644
--- a/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java
+++ b/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java
@@ -42,9 +42,6 @@
  * A provider instance can be retrieved through a system property or the
  * configuration file in a jar file; if no provide is available that way then
  * the system default provider is returned.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class SelectorProvider extends Object {
 
@@ -55,8 +52,8 @@
     private static final String PROVIDER_IN_JAR_RESOURCE = "META-INF/services/java.nio.channels.spi.SelectorProvider"; //$NON-NLS-1$
 
     private static SelectorProvider provider = null;
-    
-    private static Channel inheritedChannel; 
+
+    private static Channel inheritedChannel;
 
     /**
      * Constructs a new {@code SelectorProvider}.
@@ -64,7 +61,6 @@
      * @throws SecurityException
      *             if there is a security manager installed that does not permit
      *             the runtime permission labeled "selectorProvider".
-     * @since Android 1.0
      */
     protected SelectorProvider() {
         super();
@@ -87,9 +83,8 @@
      * provider's class name; </li>
      * <li> otherwise, a system default provider will be returned.</li>
      * </ul>
-     * 
+     *
      * @return the provider.
-     * @since Android 1.0
      */
     synchronized public static SelectorProvider provider() {
         if (null == provider) {
@@ -115,8 +110,8 @@
     static SelectorProvider loadProviderByJar() {
         Enumeration<URL> enumeration = null;
 
-        ClassLoader classLoader = AccessController.doPrivileged(
-                new PrivilegedAction<ClassLoader>() {
+        ClassLoader classLoader = AccessController
+                .doPrivileged(new PrivilegedAction<ClassLoader>() {
                     public ClassLoader run() {
                         return ClassLoader.getSystemClassLoader();
                     }
@@ -153,40 +148,37 @@
                             .substring(0, siteComment);
                     if (0 < className.length()) {
                         return (SelectorProvider) classLoader.loadClass(
-                                className).newInstance();                  
+                                className).newInstance();
                     }
                 }
             } catch (Exception e) {
                 throw new Error(e);
-            // BEGIN android-added
-            // copied from a newer version of harmony
             } finally {
                 try {
                     br.close();
                 } catch (IOException ioe) {
                     // Ignore
                 }
-            // END android-added
             }
         }
         return null;
     }
 
     /*
-     * load by system property.
+     * Load by system property.
      */
     static SelectorProvider loadProviderByProperty() {
-        return AccessController.doPrivileged(
-                new PrivilegedAction<SelectorProvider>() {
+        return AccessController
+                .doPrivileged(new PrivilegedAction<SelectorProvider>() {
                     public SelectorProvider run() {
                         try {
-                            final String className =
-                                System.getProperty(PROVIDER_IN_SYSTEM_PROPERTY);
+                            final String className = System
+                                    .getProperty(PROVIDER_IN_SYSTEM_PROPERTY);
                             if (null != className) {
                                 Class<?> spClass = ClassLoader
                                         .getSystemClassLoader().loadClass(
                                                 className);
-                                return (SelectorProvider)spClass.newInstance();
+                                return (SelectorProvider) spClass.newInstance();
                             }
                             return null;
                         } catch (Exception e) {
@@ -202,7 +194,6 @@
      * @return the new channel.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public abstract DatagramChannel openDatagramChannel() throws IOException;
 
@@ -212,7 +203,6 @@
      * @return the new pipe.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public abstract Pipe openPipe() throws IOException;
 
@@ -222,7 +212,6 @@
      * @return the new selector.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public abstract AbstractSelector openSelector() throws IOException;
 
@@ -232,7 +221,6 @@
      * @return the new channel.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public abstract ServerSocketChannel openServerSocketChannel()
             throws IOException;
@@ -243,7 +231,6 @@
      * @return the new channel.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public abstract SocketChannel openSocketChannel() throws IOException;
 
@@ -257,7 +244,6 @@
      * @throws SecurityException
      *             if there is a security manager installed that does not permit
      *             the runtime permission labeled "selectorProvider".
-     * @since Android 1.0
      */
     public Channel inheritedChannel() throws IOException {
         // BEGIN android-added
diff --git a/nio/src/main/java/org/apache/harmony/nio/AddressUtil.java b/nio/src/main/java/org/apache/harmony/nio/AddressUtil.java
index 7c094e7..d39b1ea 100644
--- a/nio/src/main/java/org/apache/harmony/nio/AddressUtil.java
+++ b/nio/src/main/java/org/apache/harmony/nio/AddressUtil.java
@@ -1,5 +1,4 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one or more
+/* 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
@@ -16,7 +15,7 @@
  */
 
 /*
- * Android Notice 
+ * Android Notice
  * In this class the address length was changed from long to int.
  * This is due to performance optimizations for the device.
  */
@@ -26,6 +25,10 @@
 import java.io.FileDescriptor;
 import java.nio.Buffer;
 import java.nio.channels.Channel;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
 
 import org.apache.harmony.luni.platform.FileDescriptorHandler;
 import org.apache.harmony.nio.internal.DirectBuffer;
@@ -54,33 +57,9 @@
         }
         return ((DirectBuffer) buf).getEffectiveAddress().toInt();
     }
-    
-    /**
-     * Gets the address of native resource held by the given channel, if has
-     * any.
-     * 
-     * For network related channel, including SocketChannel, ServerSocketChannel
-     * and DatagramChannel, this method returns a int of Socket handler in Linux
-     * while returns a SOCKET (UINT_PTR) in windows.
-     * 
-     * For FileChannel, this method returns the native file descriptor.
-     * 
-     * For other channels, this method return 0, which means unsupported
-     * operation.
-     * 
-     * @param channel
-     *            the given channel which may holds a native resource address
-     * @return the address of native resource held by the given channel, if any,
-     *         otherwise return 0
-     */
-    public static int getChannelAddress(Channel channel){
-        if(channel instanceof FileDescriptorHandler){
-            return getFDAddress(((FileDescriptorHandler) channel).getFD());    
-        }else if(channel instanceof FileChannelImpl){
-            return ((FileChannelImpl) channel).getHandle();    
-        }
-        return 0;
-    }
 
-    private static native int getFDAddress(FileDescriptor fd);
-}
\ No newline at end of file
+    // BEGIN android-removed: dead code (the native side of which was scary!)
+    //public static int getChannelAddress(Channel channel);
+    //private static native int getFDAddress(FileDescriptor fd);
+    // END android-removed
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/FileChannelFactory.java b/nio/src/main/java/org/apache/harmony/nio/FileChannelFactory.java
index 5abe24a..e44422d 100644
--- a/nio/src/main/java/org/apache/harmony/nio/FileChannelFactory.java
+++ b/nio/src/main/java/org/apache/harmony/nio/FileChannelFactory.java
@@ -15,14 +15,13 @@
  */
 
 /*
- * Android Notice 
+ * Android Notice
  * In this class the address length was changed from long to int.
  * This is due to performance optimizations for the device.
  */
 
 package org.apache.harmony.nio;
 
-
 import java.nio.channels.FileChannel;
 
 import org.apache.harmony.nio.internal.ReadOnlyFileChannel;
@@ -37,20 +36,20 @@
  */
 public class FileChannelFactory {
     public static FileChannel getFileChannel(Object stream, int fd, int mode) {
-        switch(mode){
-        case IFileSystem.O_RDONLY:
-            return new ReadOnlyFileChannel(stream, fd);
-        case IFileSystem.O_WRONLY:
-            return new WriteOnlyFileChannel(stream, fd);
-        case IFileSystem.O_RDWR:
-            return new ReadWriteFileChannel(stream, fd);
-        case IFileSystem.O_RDWRSYNC:
-            return new ReadWriteFileChannel(stream, fd);
-        case IFileSystem.O_APPEND:
-            return new WriteOnlyFileChannel(stream, fd, true);
-        default:
-            // nio.09=Unknown file channel type: {0}
-            throw new RuntimeException(Messages.getString("nio.09", mode));  //$NON-NLS-1$
+        switch (mode) {
+            case IFileSystem.O_RDONLY:
+                return new ReadOnlyFileChannel(stream, fd);
+            case IFileSystem.O_WRONLY:
+                return new WriteOnlyFileChannel(stream, fd);
+            case IFileSystem.O_RDWR:
+                return new ReadWriteFileChannel(stream, fd);
+            case IFileSystem.O_RDWRSYNC:
+                return new ReadWriteFileChannel(stream, fd);
+            case IFileSystem.O_APPEND:
+                return new WriteOnlyFileChannel(stream, fd, true);
+            default:
+                // nio.09=Unknown file channel type: {0}
+                throw new RuntimeException(Messages.getString("nio.09", mode)); //$NON-NLS-1$
         }
     }
 }
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
index ac8f77b..109a819 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
@@ -18,7 +18,6 @@
 package org.apache.harmony.nio.internal;
 
 // BEGIN android-note
-// Copied from a newer version of Harmony.
 // In this class the address length was changed from long to int.
 // END android-note
 
@@ -46,7 +45,7 @@
 import org.apache.harmony.luni.platform.FileDescriptorHandler;
 import org.apache.harmony.luni.platform.INetworkSystem;
 import org.apache.harmony.luni.platform.Platform;
-import org.apache.harmony.luni.util.ErrorCodeException;
+//import org.apache.harmony.luni.util.ErrorCodeException; android-removed
 import org.apache.harmony.nio.AddressUtil;
 
 /*
@@ -62,8 +61,8 @@
     // default timeout used to nonblocking mode.
     private static final int DEFAULT_TIMEOUT = 1;
 
-    private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211;
-    
+    // android-removed: private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211;
+
     private static final byte[] stubArray = new byte[0];
 
     // The fd to interact with native code
@@ -245,7 +244,7 @@
         }
         return retAddr;
     }
-    
+
     private SocketAddress receiveImpl(ByteBuffer target, boolean loop)
             throws IOException {
         SocketAddress retAddr = null;
@@ -256,7 +255,7 @@
             receivePacket = new DatagramPacket(target.array(), target
                     .position()
                     + target.arrayOffset(), target.remaining());
-        } else {        
+        } else {
             receivePacket = new DatagramPacket(new byte[target.remaining()],
                     target.remaining());
         }
@@ -285,7 +284,7 @@
                 }
             }
             if (null != receivePacket && null != receivePacket.getAddress()) {
-                               
+
                 if (received > 0) {
                     if (target.hasArray()) {
                         target.position(oldposition + received);
@@ -300,7 +299,7 @@
         } while (loop);
         return retAddr;
     }
-    
+
     private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop)
             throws IOException {
         SocketAddress retAddr = null;
@@ -618,7 +617,7 @@
                 begin();
                 int length = buf.remaining();
                 int start = buf.position();
-    
+
                 if (buf.isDirect()) {
                     int address = AddressUtil.getDirectBufferAddress(buf);
                     result = networkSystem.sendConnectedDatagramDirect(fd,
@@ -630,14 +629,7 @@
                             .array(), start, length, isBound);
                 }
                 return result;
-            } catch (SocketException e) {
-                if (e.getCause() instanceof ErrorCodeException) {
-                    if (ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK == ((ErrorCodeException) e
-                            .getCause()).getErrorCode()) {
-                        return result;
-                    }
-                }
-                throw e;
+                // android-removed: bogus catch (SocketException e) and use of ErrorCodeException.
             } finally {
                 end(result > 0);
             }
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/DirectBuffer.java b/nio/src/main/java/org/apache/harmony/nio/internal/DirectBuffer.java
index 52a7b65..1af7c54 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/DirectBuffer.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/DirectBuffer.java
@@ -18,8 +18,7 @@
 import org.apache.harmony.luni.platform.PlatformAddress;
 
 public interface DirectBuffer {
-    // BEGIN android-changed
-    // Copied from a newer version of harmony
+    
     PlatformAddress getEffectiveAddress();
     
     PlatformAddress getBaseAddress();
@@ -31,5 +30,4 @@
     void free();
     
     int getByteCapacity();
-    // END android-changed
 }
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java
index 687b438..9e72082 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java
@@ -16,7 +16,7 @@
  */
 
 /*
- * Android Notice 
+ * Android Notice
  * In this class the address length was changed from long to int.
  * This is due to performance optimizations for the device.
  *
@@ -49,7 +49,6 @@
  * provided by the port layer.
  * 
  * This class is non-API, but implements the API of the FileChannel interface.
- * 
  */
 public abstract class FileChannelImpl extends FileChannel {
 
@@ -73,7 +72,7 @@
     // The object that will track all outstanding locks on this channel.
     private final LockManager lockManager = new LockManager();
 
-    private class RepositioningLock {}
+    private static class RepositioningLock {}
     private final Object repositioningLock = new RepositioningLock();
 
     private final Object stream;
@@ -115,8 +114,7 @@
             boolean wait) throws IOException {
         if ((position < 0) || (size < 0)) {
             // nio.0A=Lock position and size must be non-negative.
-            throw new IllegalArgumentException(
-                    Messages.getString("nio.0A"));  //$NON-NLS-1$
+            throw new IllegalArgumentException(Messages.getString("nio.0A")); //$NON-NLS-1$
         }
         int lockType = shared ? IFileSystem.SHARED_LOCK_TYPE
                 : IFileSystem.EXCLUSIVE_LOCK_TYPE;
@@ -198,8 +196,8 @@
         }
         long alignment = position - position % ALLOC_GRANULARITY;
         int offset = (int) (position - alignment);
-        PlatformAddress address = PlatformAddressFactory.allocMap(handle, alignment, size
-                + offset, mapMode);
+        PlatformAddress address = PlatformAddressFactory.allocMap(handle,
+                alignment, size + offset, mapMode);
         MappedByteBuffer buffer = null;
         try {
             buffer = MappedByteBufferFactory.getBuffer(address, mapMode, size,
@@ -225,9 +223,8 @@
         openCheck();
         if (newPosition < 0) {
             // nio.0B=New position must be non-negative.
-            throw new IllegalArgumentException(
-                    Messages.getString("nio.0B"));  //$NON-NLS-1$
-        }        
+            throw new IllegalArgumentException(Messages.getString("nio.0B")); //$NON-NLS-1$
+        }
 
         synchronized (repositioningLock) {
             fileSystem.seek(handle, newPosition, IFileSystem.SEEK_SET);
@@ -236,14 +233,14 @@
     }
 
     public int read(ByteBuffer buffer, long position) throws IOException {
-        if (null == buffer){
+        if (null == buffer) {
             throw new NullPointerException();
         }
-        if (position < 0){
+        if (position < 0) {
             throw new IllegalArgumentException();
         }
         openCheck();
-        if (!buffer.hasRemaining()){
+        if (!buffer.hasRemaining()) {
             return 0;
         }
         synchronized (repositioningLock) {
@@ -261,7 +258,7 @@
 
     public int read(ByteBuffer buffer) throws IOException {
         openCheck();
-        if (!buffer.hasRemaining()){
+        if (!buffer.hasRemaining()) {
             return 0;
         }
         boolean completed = false;
@@ -273,7 +270,7 @@
                 try {
                     begin();
                     /*
-                     * if (bytesRead <= EOF) delt by read completed = false;
+                     * if (bytesRead <= EOF) dealt by read completed = false;
                      */
                     bytesRead = (int) fileSystem.readDirect(handle, address,
                             buffer.position(), buffer.remaining());
@@ -285,7 +282,7 @@
                 try {
                     begin();
                     /*
-                     * if (bytesRead <= EOF) delt by read completed = false;
+                     * if (bytesRead <= EOF) dealt by read completed = false;
                      */
                     bytesRead = (int) fileSystem.read(handle, buffer.array(),
                             buffer.arrayOffset() + buffer.position(), buffer
@@ -346,7 +343,7 @@
                 }
                 completed = true;
                 /*
-                 * if (bytesRead < EOF) //delt by readv? completed = false;
+                 * if (bytesRead < EOF) //dealt by readv? completed = false;
                  */
             } finally {
                 end(completed);
@@ -367,16 +364,16 @@
                 }
             } else {
                 ByteBuffer buf = directBuffers[i - offset];
-                if (bytesRemaining < buf.remaining()){
-                    // this is the last step.                  
+                if (bytesRemaining < buf.remaining()) {
+                    // this is the last step.
                     int pos = buf.position();
                     buffers[i].put(buf);
-                    buffers[i].position(pos + (int)bytesRemaining);
+                    buffers[i].position(pos + (int) bytesRemaining);
                     bytesRemaining = 0;
                 } else {
                     bytesRemaining -= buf.remaining();
                     buffers[i].put(buf);
-                }                
+                }
             }
         }
         return bytesRead;
@@ -403,16 +400,15 @@
         if (!src.isOpen()) {
             throw new ClosedChannelException();
         }
-        if (position < 0 || count < 0 || position > Integer.MAX_VALUE
-                || count > Integer.MAX_VALUE) {
+        if (position < 0 || count < 0 || count > Integer.MAX_VALUE) {
             throw new IllegalArgumentException();
         }
-        if(position > size()) {
+        if (position > size()) {
             return 0;
         }
-        
+
         ByteBuffer buffer = null;
-        // BEGIN android-changed
+
         try {
             if (src instanceof FileChannel) {
                 FileChannel fileSrc = (FileChannel) src;
@@ -432,10 +428,9 @@
             if (buffer != null) {
                 // all children of FileChannelImpl currently returns
                 // an instance of DirectBuffer from map() method
-               ((DirectBuffer) buffer).free();
+                ((DirectBuffer) buffer).free();
             }
         }
-        // END android-changed
     }
 
     public long transferTo(long position, long count, WritableByteChannel target)
@@ -447,11 +442,10 @@
         if (target instanceof ReadOnlyFileChannel) {
             throw new NonWritableChannelException();
         }
-        if (position < 0 || count < 0 || position > Integer.MAX_VALUE
-                || count > Integer.MAX_VALUE) {
+        if (position < 0 || count < 0) {
             throw new IllegalArgumentException();
         }
-        
+
         if (count == 0 || position >= size()) {
             return 0;
         }
@@ -462,7 +456,7 @@
             return kernelTransfer(handle, ((SocketChannelImpl) target).getFD(),
                     position, count);
         }
-        // BEGIN android-changed
+
         try {
             buffer = map(MapMode.READ_ONLY, position, count);
             return target.write(buffer);
@@ -474,7 +468,6 @@
                 ((DirectBuffer) buffer).free();
             }
         }
-        // END android-changed
     }
 
     private long kernelTransfer(int l, FileDescriptor fd, long position,
@@ -518,14 +511,14 @@
      */
 
     public int write(ByteBuffer buffer, long position) throws IOException {
-        if (null == buffer){
+        if (null == buffer) {
             throw new NullPointerException();
         }
-        if (position < 0){
+        if (position < 0) {
             throw new IllegalArgumentException();
         }
         openCheck();
-        if (!buffer.hasRemaining()){
+        if (!buffer.hasRemaining()) {
             return 0;
         }
         int bytesWritten = 0;
@@ -653,8 +646,8 @@
         }
         return bytesWritten;
     }
-    
-    public int getHandle(){
+
+    public int getHandle() {
         return handle;
     }
 }
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/FileLockImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/FileLockImpl.java
index 4e0ddc9..bfe360b 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/FileLockImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/FileLockImpl.java
@@ -16,50 +16,54 @@
 
 package org.apache.harmony.nio.internal;
 
-
 import java.io.IOException;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileLock;
 
-/*
+/**
  * The concrete implementation of an NIO file lock object.
- * 
  */
 final class FileLockImpl extends FileLock {
 
     // Remembers if this lock has been released via the API.
     private boolean isReleased = false;
 
-    /*
-     * Returns a new file lock object with the given parameters.
+    /**
+     * Answers a new file lock object with the given parameters.
      * 
-     * @param channel the file channel hosting the lock. @param position the
-     * start position of the lock, in bytes @param size the length of the lock,
-     * in bytes @param shared whether this lock is shared (true) or exclusive
-     * (false)
+     * @param channel
+     *            the file channel hosting the lock.
+     * @param position
+     *            the start position of the lock, in bytes
+     * @param size
+     *            the length of the lock, in bytes
+     * @param shared
+     *            whether this lock is shared (true) or exclusive (false)
      */
     public FileLockImpl(FileChannel channel, long position, long size,
             boolean shared) {
         super(channel, position, size, shared);
     }
 
-    /*
+    /**
      * Tests to see if the lock is valid. A lock can be invalidated if the
      * channel it is acquired on is closed or if it is released. (non-Javadoc)
      * 
      * @see java.nio.channels.FileLock#isValid()
      */
+    @Override
     public boolean isValid() {
         return !isReleased && channel().isOpen();
     }
 
-    /*
+    /**
      * Releases the file lock on the channel that acquired it. Releasing an
      * invalid lock has no effect.
      * 
      * @see java.nio.channels.FileLock#release()
      */
+    @Override
     public void release() throws IOException {
         if (!channel().isOpen()) {
             throw new ClosedChannelException();
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java b/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java
index 6752732..816afcf 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java
@@ -29,34 +29,20 @@
 import org.apache.harmony.nio.Util;
 import org.apache.harmony.nio.internal.nls.Messages;
 
-
-/*
+/**
  * Static methods for I/O util. Used by io package and nio package.
- * 
  */
 public final class IOUtil {
 
-    // -------------------------------------------------------------------
-    // Class variables
-    // -------------------------------------------------------------------
-
     private static final int DEFAULT_BUFFER_SIZE = 8192;
 
-    // -------------------------------------------------------------------
-    // Constructor
-    // -------------------------------------------------------------------
-
     /*
-     * No instance.
+     * Not designed to be instantiated.
      */
     private IOUtil() {
         super();
     }
 
-    // -------------------------------------------------------------------
-    // Routine methods.
-    // -------------------------------------------------------------------
-
     /*
      * Read method for InputStreamReader and Channels.
      */
@@ -125,7 +111,7 @@
     }
 
     /*
-     * refill the buffer from wrapped InputStream
+     * Refill the buffer from wrapped InputStream.
      */
     private static void fillBuf(InputStream in, ByteBuffer bytes,
             CharBuffer chars, CharsetDecoder decoder) throws IOException {
@@ -211,7 +197,7 @@
     }
 
     /*
-     * convert function used in write.
+     * Convert function used in write.
      */
     private static void convert(Object lock, CharsetEncoder encoder,
             ByteBuffer bytes, CharBuffer chars, OutputStream out)
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/MappedByteBufferFactory.java b/nio/src/main/java/org/apache/harmony/nio/internal/MappedByteBufferFactory.java
index f3f5a35..b598c15 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/MappedByteBufferFactory.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/MappedByteBufferFactory.java
@@ -26,17 +26,17 @@
 
 class MappedByteBufferFactory {
 
-    static final Constructor constructor;
+    static final Constructor<?> constructor;
 
     static {
         constructor = AccessController
-                .doPrivileged(new PrivilegedAction<Constructor>() {
-                    public Constructor run() {
+                .doPrivileged(new PrivilegedAction<Constructor<?>>() {
+                    public Constructor<?> run() {
                         try {
-                            Class wrapperClazz = ClassLoader
+                            Class<?> wrapperClazz = ClassLoader
                                     .getSystemClassLoader().loadClass(
                                             "java.nio.MappedByteBufferAdapter"); //$NON-NLS-1$
-                            Constructor result = wrapperClazz
+                            Constructor<?> result = wrapperClazz
                                     .getConstructor(new Class[] {
                                             PlatformAddress.class, int.class,
                                             int.class, int.class });
@@ -51,8 +51,10 @@
 
     static MappedByteBuffer getBuffer(PlatformAddress addr, int mapmode,
             long size, int offset) throws Exception {
-        // Spec points out explicitly that the size of map should be no greater than
-        // Integer.MAX_VALUE, so long to int cast is safe here.
+        /*
+         * Spec points out explicitly that the size of map should be no greater
+         * than Integer.MAX_VALUE, so long to int cast is safe here.
+         */
         return (MappedByteBuffer) constructor.newInstance(new Object[] { addr,
                 new Integer((int) size), new Integer(offset),
                 new Integer(mapmode) });
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/PipeImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/PipeImpl.java
index beceac4..53e9ce6 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/PipeImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/PipeImpl.java
@@ -108,7 +108,7 @@
             super(provider);
             sourceServer = provider.openServerSocketChannel();
             sourceServer.socket().bind(
-                    new InetSocketAddress(InetAddress.getLocalHost(), 0));
+                new InetSocketAddress(InetAddress.getByName(null), 0));
             serverPort = sourceServer.socket().getLocalPort();
         }
 
@@ -161,8 +161,8 @@
         }
 
         public boolean finishConnect() throws IOException {
-            return sinkSocket.connect(new InetSocketAddress(InetAddress
-                    .getLocalHost(), serverPort));
+            return sinkSocket.connect(
+                new InetSocketAddress(InetAddress.getByName(null), serverPort));
         }
 
         protected void implCloseSelectableChannel() throws IOException {
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/ReadOnlyFileChannel.java b/nio/src/main/java/org/apache/harmony/nio/internal/ReadOnlyFileChannel.java
index 559fc89..359d108 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/ReadOnlyFileChannel.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/ReadOnlyFileChannel.java
@@ -16,7 +16,7 @@
  */
 
 /*
- * Android Notice 
+ * Android Notice
  * In this class the address length was changed from long to int.
  * This is due to performance optimizations for the device.
  */
@@ -40,10 +40,10 @@
     }
 
     public final int write(ByteBuffer buffer, long position) throws IOException {
-        if (null == buffer){
+        if (null == buffer) {
             throw new NullPointerException();
         }
-        if (position < 0){
+        if (position < 0) {
             throw new IllegalArgumentException();
         }
         throw new NonWritableChannelException();
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/SelectionKeyImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/SelectionKeyImpl.java
index f863928..c6e9930 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/SelectionKeyImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/SelectionKeyImpl.java
@@ -4,9 +4,9 @@
  * 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.
@@ -20,37 +20,41 @@
 import java.nio.channels.SelectableChannel;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
 import java.nio.channels.spi.AbstractSelectableChannel;
 import java.nio.channels.spi.AbstractSelectionKey;
 
-/*
+/**
  * Default implementation of SelectionKey
  */
 final class SelectionKeyImpl extends AbstractSelectionKey {
 
     private AbstractSelectableChannel channel;
 
-    int oldInterestOps;
-
     private int interestOps;
 
     private int readyOps;
 
     private SelectorImpl selector;
 
+    // BEGIN android-removed
+    // private int index;
+    // END android-removed
+
     public SelectionKeyImpl(AbstractSelectableChannel channel, int operations,
             Object attachment, SelectorImpl selector) {
-        super();
         this.channel = channel;
         interestOps = operations;
         this.selector = selector;
         attach(attachment);
     }
 
+    @Override
     public SelectableChannel channel() {
         return channel;
     }
 
+    @Override
     public int interestOps() {
         checkValid();
         synchronized (selector.keysLock) {
@@ -58,6 +62,13 @@
         }
     }
 
+    int interestOpsNoCheck() {
+        synchronized (selector.keysLock) {
+            return interestOps;
+        }
+    }
+
+    @Override
     public SelectionKey interestOps(int operations) {
         checkValid();
         if ((operations & ~(channel().validOps())) != 0) {
@@ -65,15 +76,20 @@
         }
         synchronized (selector.keysLock) {
             interestOps = operations;
+            // BEGIN android-removed
+            // selector.modKey(this);
+            // END android-removed
         }
         return this;
     }
 
+    @Override
     public int readyOps() {
         checkValid();
         return readyOps;
     }
 
+    @Override
     public Selector selector() {
         return selector;
     }
@@ -85,10 +101,28 @@
         this.readyOps = readyOps;
     }
 
+    // BEGIN android-removed
+    // int getIndex() {
+    //     return index;
+    // }
+
+    // void setIndex(int index) {
+    //     this.index = index;
+    // }
+    // END android-removed
+
     private void checkValid() {
         if (!isValid()) {
             throw new CancelledKeyException();
         }
     }
 
-}
\ No newline at end of file
+    /**
+     * Returns true if the channel for this key is connected. If the channel
+     * does not need connecting, this always return true.
+     */
+    boolean isConnected() {
+        return !(channel instanceof SocketChannel)
+                || ((SocketChannel) channel).isConnected();
+    }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java
index f8e7d80..9d96454 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java
@@ -4,9 +4,9 @@
  * 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.
@@ -15,37 +15,51 @@
  */
 package org.apache.harmony.nio.internal;
 
+// BEGIN android-note
+// This class differs significantly from Harmony. They have adopted indices to
+// track selection keys as-they-change; we avoid that cost by tracking keys on
+// calls to select().
+// END android-note
+
+import org.apache.harmony.luni.platform.FileDescriptorHandler;
+import org.apache.harmony.luni.platform.Platform;
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.channels.ClosedSelectorException;
 import java.nio.channels.IllegalSelectorException;
 import java.nio.channels.Pipe;
-import java.nio.channels.SelectableChannel;
 import java.nio.channels.SelectionKey;
+import static java.nio.channels.SelectionKey.*;
 import java.nio.channels.Selector;
-import java.nio.channels.SocketChannel;
 import java.nio.channels.spi.AbstractSelectableChannel;
 import java.nio.channels.spi.AbstractSelectionKey;
 import java.nio.channels.spi.AbstractSelector;
 import java.nio.channels.spi.SelectorProvider;
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Set;
 
-import org.apache.harmony.luni.platform.FileDescriptorHandler;
-import org.apache.harmony.luni.platform.Platform;
-
 /*
  * Default implementation of java.nio.channels.Selector
- * 
  */
 final class SelectorImpl extends AbstractSelector {
 
+    private static final int[] EMPTY_INT_ARRAY = new int[0];
+
+    private static final FileDescriptor[] EMPTY_FILE_DESCRIPTORS_ARRAY
+            = new FileDescriptor[0];
+    private static final SelectionKeyImpl[] EMPTY_SELECTION_KEY_IMPLS_ARRAY
+            = new SelectionKeyImpl[0];
+
+    private static final int CONNECT_OR_WRITE = OP_CONNECT | OP_WRITE;
+
+    private static final int ACCEPT_OR_READ = OP_ACCEPT | OP_READ;
+
     private static final int MOCK_WRITEBUF_SIZE = 1;
 
     private static final int MOCK_READBUF_SIZE = 8;
@@ -60,38 +74,66 @@
 
     private static final int SELECT_NOW = 0;
 
-    // keysLock is used to brief synchronization when get selectionKeys snapshot
-    // before selection
-    final Object keysLock = new Object();
+    /**
+     * Used to synchronize when a key's interest ops change.
+     */
+    private static class KeysLock {}
+    final Object keysLock = new KeysLock();
 
-    private final Set<SelectionKey> keys = new HashSet<SelectionKey>();
+    private final Set<SelectionKeyImpl> mutableKeys = new HashSet<SelectionKeyImpl>();
 
+    /**
+     * The unmodifiable set of keys as exposed to the user. This object is used
+     * for synchronization.
+     */
     private Set<SelectionKey> unmodifiableKeys = Collections
-            .unmodifiableSet(keys);
+            .<SelectionKey>unmodifiableSet(mutableKeys);
 
-    private final Set<SelectionKey> selectedKeys = new HashSet<SelectionKey>();
+    private final Set<SelectionKey> mutableSelectedKeys = new HashSet<SelectionKey>();
 
-    private Set<SelectionKey> unaddableSelectedKeys = new UnaddableSet<SelectionKey>(
-            selectedKeys);
+    /**
+     * The unmodifiable set of selectable keys as seen by the user. This object
+     * is used for synchronization.
+     */
+    private final Set<SelectionKey> selectedKeys
+            = new UnaddableSet<SelectionKey>(mutableSelectedKeys);
 
-    // sink and source are used by wakeup()
+    /**
+     * File descriptors we're interested in reading from. When actively
+     * selecting, the first element is always the mock channel's file
+     * descriptor, and the other elements are user-specified file descriptors.
+     * Otherwise, all elements are null.
+     */
+    private FileDescriptor[] readableFDs = EMPTY_FILE_DESCRIPTORS_ARRAY;
+
+    /**
+     * File descriptors we're interested in writing from. May be empty. When not
+     * actively selecting, all elements are null.
+     */
+    private FileDescriptor[] writableFDs = EMPTY_FILE_DESCRIPTORS_ARRAY;
+
+    /**
+     * Selection keys that correspond to the concatenation of readableFDs and
+     * writableFDs. This is used to interpret the results returned by select().
+     * When not actively selecting, all elements are null.
+     */
+    private SelectionKeyImpl[] readyKeys = EMPTY_SELECTION_KEY_IMPLS_ARRAY;
+
+    /**
+     * Selection flags that define the ready ops on the ready keys. When not
+     * actively selecting, all elements are 0. Corresponds to the ready keys
+     * set.
+     */
+    private int[] flags = EMPTY_INT_ARRAY;
+
+    /**
+     * A mock channel is used to signal wakeups. Whenever the selector should
+     * stop blocking on a select(), a byte is written to the sink and will be
+     * picked up in source by the selecting thread.
+     */
     private Pipe.SinkChannel sink;
-
     private Pipe.SourceChannel source;
-    
     private FileDescriptor sourcefd;
-    
-    private SelectionKey[] readableChannels;
-
-    private SelectionKey[] writableChannels;
-
-    private List<FileDescriptor> readableFDs = new ArrayList<FileDescriptor>();
-
-    private List<FileDescriptor> writableFDs = new ArrayList<FileDescriptor>();
-
-    private FileDescriptor[] readable;
-
-    private FileDescriptor[] writable;
 
     public SelectorImpl(SelectorProvider selectorProvider) {
         super(selectorProvider);
@@ -99,67 +141,82 @@
             Pipe mockSelector = selectorProvider.openPipe();
             sink = mockSelector.sink();
             source = mockSelector.source();
-            sourcefd = ((FileDescriptorHandler)source).getFD();
+            sourcefd = ((FileDescriptorHandler) source).getFD();
             source.configureBlocking(false);
         } catch (IOException e) {
-            // do nothing
+            // TODO: throw assertion error once IPv6+loopback is fixed
+            e.printStackTrace();
         }
     }
 
-    /*
+    /**
      * @see java.nio.channels.spi.AbstractSelector#implCloseSelector()
      */
+    @Override
     protected void implCloseSelector() throws IOException {
-        doCancel();
-        for (SelectionKey sk : keys) {
-            deregister((AbstractSelectionKey) sk);
-        }
         wakeup();
+        synchronized (this) {
+            synchronized (unmodifiableKeys) {
+                synchronized (selectedKeys) {
+                    doCancel();
+                    for (SelectionKey sk : mutableKeys) {
+                        deregister((AbstractSelectionKey) sk);
+                    }
+                }
+            }
+        }
     }
 
-    /*
+    /**
      * @see java.nio.channels.spi.AbstractSelector#register(java.nio.channels.spi.AbstractSelectableChannel,
      *      int, java.lang.Object)
      */
+    @Override
     protected SelectionKey register(AbstractSelectableChannel channel,
             int operations, Object attachment) {
         if (!provider().equals(channel.provider())) {
             throw new IllegalSelectorException();
         }
         synchronized (this) {
-            synchronized (keys) {
-                SelectionKey sk = new SelectionKeyImpl(channel, operations,
-                        attachment, this);
-                keys.add(sk);
-                return sk;
+            synchronized (unmodifiableKeys) {
+                SelectionKeyImpl selectionKey = new SelectionKeyImpl(
+                        channel, operations, attachment, this);
+                mutableKeys.add(selectionKey);
+                return selectionKey;
             }
         }
     }
 
-    /*
+    /**
      * @see java.nio.channels.Selector#keys()
      */
+    @Override
     public synchronized Set<SelectionKey> keys() {
         closeCheck();
         return unmodifiableKeys;
     }
 
+    /*
+     * Checks that the receiver is not closed. If it is throws an exception.
+     */
     private void closeCheck() {
         if (!isOpen()) {
             throw new ClosedSelectorException();
         }
     }
 
-    /*
+    /**
      * @see java.nio.channels.Selector#select()
      */
+    @Override
     public int select() throws IOException {
         return selectInternal(SELECT_BLOCK);
     }
 
-    /*
+    /**
      * @see java.nio.channels.Selector#select(long)
      */
+    @Override
     public int select(long timeout) throws IOException {
         if (timeout < 0) {
             throw new IllegalArgumentException();
@@ -167,9 +224,10 @@
         return selectInternal((0 == timeout) ? SELECT_BLOCK : timeout);
     }
 
-    /*
+    /**
      * @see java.nio.channels.Selector#selectNow()
      */
+    @Override
     public int selectNow() throws IOException {
         return selectInternal(SELECT_NOW);
     }
@@ -177,156 +235,184 @@
     private int selectInternal(long timeout) throws IOException {
         closeCheck();
         synchronized (this) {
-            synchronized (keys) {
+            synchronized (unmodifiableKeys) {
                 synchronized (selectedKeys) {
                     doCancel();
-                    int[] readyChannels = null;
                     boolean isBlock = (SELECT_NOW != timeout);
-                    // BEGIN android-removed
-                    // copied from newer version of harmony
-                    // if (keys.size() == 0) {
-                    //     return 0;
-                    // }
-                    // END android-removed
-                    prepareChannels();
+                    int readableKeysCount = 1; // first is always the mock channel
+                    int writableKeysCount = 0;
+                    synchronized (keysLock) {
+                        for (SelectionKeyImpl key : mutableKeys) {
+                            int ops = key.interestOpsNoCheck();
+                            if ((ACCEPT_OR_READ & ops) != 0) {
+                                readableKeysCount++;
+                            }
+                            if ((CONNECT_OR_WRITE & ops) != 0) {
+                                writableKeysCount++;
+                            }
+                        }
+                        prepareChannels(readableKeysCount, writableKeysCount);
+                    }
+                    boolean success;
                     try {
                         if (isBlock) {
                             begin();
                         }
-                        readyChannels = Platform.getNetworkSystem().select(readable, writable, timeout);
+                        success = Platform.getNetworkSystem().select(
+                                readableFDs, writableFDs, readableKeysCount, writableKeysCount, timeout, flags);
                     } finally {
-                        // clear results for next select
-                        readableFDs.clear();
-                        writableFDs.clear();                        
                         if (isBlock) {
                             end();
                         }
                     }
-                    return processSelectResult(readyChannels);                    
+
+                    int selected = success ? processSelectResult() : 0;
+
+                    Arrays.fill(readableFDs, null);
+                    Arrays.fill(writableFDs, null);
+                    Arrays.fill(readyKeys, null);
+                    Arrays.fill(flags, 0);
+
+                    selected -= doCancel();
+
+                    return selected;
                 }
             }
         }
     }
 
-    private boolean isConnected(SelectionKeyImpl key) {
-        SelectableChannel channel = key.channel();
-        if (channel instanceof SocketChannel) {
-            return ((SocketChannel) channel).isConnected();
+    /**
+     * Prepare the readableFDs, writableFDs, readyKeys and flags arrays in
+     * preparation for a call to {@code INetworkSystem#select()}. After they're
+     * used, the array elements must be cleared.
+     */
+    private void prepareChannels(int numReadable, int numWritable) {
+        // grow each array to sufficient capacity. Always grow to at least 1.5x
+        // to avoid growing too frequently
+        if (readableFDs.length < numReadable) {
+            int newSize = Math.max((int) (readableFDs.length * 1.5f), numReadable);
+            readableFDs = new FileDescriptor[newSize];
         }
-        return true;
-    }
+        if (writableFDs.length < numWritable) {
+            int newSize = Math.max((int) (writableFDs.length * 1.5f), numWritable);
+            writableFDs = new FileDescriptor[newSize];
+        }
+        int total = numReadable + numWritable;
+        if (readyKeys.length < total) {
+            int newSize = Math.max((int) (readyKeys.length * 1.5f), total);
+            readyKeys = new SelectionKeyImpl[newSize];
+            flags = new int[newSize];
+        }
 
-    // Prepares and adds channels to list for selection
-    private void prepareChannels() {
-        readableFDs.add(sourcefd);        
-        List<SelectionKey> readChannelList = new ArrayList<SelectionKey>();
-        readChannelList.add(source.keyFor(this));
-        List<SelectionKey> writeChannelList = new ArrayList<SelectionKey>();
-        synchronized (keysLock) {
-            for (Iterator<SelectionKey> i = keys.iterator(); i.hasNext();) {
-                SelectionKeyImpl key = (SelectionKeyImpl) i.next();
-                key.oldInterestOps = key.interestOps();
-                boolean isReadableChannel = ((SelectionKey.OP_ACCEPT | SelectionKey.OP_READ) & key.oldInterestOps) != 0;
-                boolean isWritableChannel = ((SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE) & key.oldInterestOps) != 0;
-                SelectableChannel channel = key.channel();                  
-                if (isReadableChannel) {
-                    readChannelList.add(channel.keyFor(this));
-                    readableFDs.add(((FileDescriptorHandler)channel).getFD());
-                }
-                if (isWritableChannel) {
-                    writeChannelList.add(channel.keyFor(this));
-                    writableFDs.add(((FileDescriptorHandler)channel).getFD());
-                }
+        // populate the FDs, including the mock channel
+        readableFDs[0] = sourcefd;
+        int r = 1;
+        int w = 0;
+        for (SelectionKeyImpl key : mutableKeys) {
+            int interestOps = key.interestOpsNoCheck();
+            if ((ACCEPT_OR_READ & interestOps) != 0) {
+                readableFDs[r] = ((FileDescriptorHandler) key.channel()).getFD();
+                readyKeys[r] = key;
+                r++;
+            }
+            if ((CONNECT_OR_WRITE & interestOps) != 0) {
+                writableFDs[w] = ((FileDescriptorHandler) key.channel()).getFD();
+                readyKeys[w + numReadable] = key;
+                w++;
             }
         }
-        readableChannels = readChannelList.toArray(new SelectionKey[0]);
-        writableChannels = writeChannelList.toArray(new SelectionKey[0]);
-        readable = readableFDs.toArray(new FileDescriptor[0]);
-        writable = writableFDs.toArray(new FileDescriptor[0]);
     }
 
-    // Analyses selected channels and adds keys of ready channels to
-    // selectedKeys list
-    private int processSelectResult(int[] readyChannels) throws IOException {
-        if (0 == readyChannels.length) {
-            return 0;
-        }
+    /**
+     * Updates the key ready ops and selected key set with data from the flags
+     * array.
+     */
+    private int processSelectResult() throws IOException {
         // if the mock channel is selected, read the content.
-        if (READABLE == readyChannels[0]) {
+        if (READABLE == flags[0]) {
             ByteBuffer readbuf = ByteBuffer.allocate(MOCK_READBUF_SIZE);
             while (source.read(readbuf) > 0) {
                 readbuf.flip();
             }
         }
         int selected = 0;
-        for (int i = 1; i < readyChannels.length; i++) {            
-            SelectionKeyImpl key = (SelectionKeyImpl) (i >= readable.length ? writableChannels[i
-                    - readable.length]
-                    : readableChannels[i]);
-            if (null == key) {
+
+        for (int i = 1; i < flags.length; i++) {
+            if (flags[i] == NA) {
                 continue;
             }
-            boolean isOldSelectedKey = selectedKeys.contains(key);
+
+            SelectionKeyImpl key = readyKeys[i];
+            int ops = key.interestOpsNoCheck();
             int selectedOp = 0;
-            // set ready ops
-            switch (readyChannels[i]) {
-            case NA:
-                selectedOp = 0;
-                break;
-            case READABLE:
-                selectedOp = (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)
-                        & key.oldInterestOps;
-                break;
-            case WRITEABLE:
-                if (isConnected(key)) {
-                    selectedOp = SelectionKey.OP_WRITE & key.oldInterestOps;
-                } else {
-                    selectedOp = SelectionKey.OP_CONNECT & key.oldInterestOps;
-                }
-                break;
+
+            switch (flags[i]) {
+                case READABLE:
+                    selectedOp = ACCEPT_OR_READ & ops;
+                    break;
+                case WRITEABLE:
+                    if (key.isConnected()) {
+                        selectedOp = OP_WRITE & ops;
+                    } else {
+                        selectedOp = OP_CONNECT & ops;
+                    }
+                    break;
             }
 
             if (0 != selectedOp) {
-                if (isOldSelectedKey && key.readyOps() != selectedOp) {
+                boolean wasSelected = mutableSelectedKeys.contains(key);
+                if (wasSelected && key.readyOps() != selectedOp) {
                     key.setReadyOps(key.readyOps() | selectedOp);
                     selected++;
-                } else if (!isOldSelectedKey) {
+                } else if (!wasSelected) {
                     key.setReadyOps(selectedOp);
-                    selectedKeys.add(key);
+                    mutableSelectedKeys.add(key);
                     selected++;
                 }
             }
         }
-        readableChannels = null;
-        writableChannels = null;
+
         return selected;
     }
 
-    /*
+    /**
      * @see java.nio.channels.Selector#selectedKeys()
      */
+    @Override
     public synchronized Set<SelectionKey> selectedKeys() {
         closeCheck();
-        return unaddableSelectedKeys;
+        return selectedKeys;
     }
 
-    private void doCancel() {
+    /**
+     * Removes cancelled keys from the key set and selected key set, and
+     * deregisters the corresponding channels. Returns the number of keys
+     * removed from the selected key set.
+     */
+    private int doCancel() {
+        int deselected = 0;
+
         Set<SelectionKey> cancelledKeys = cancelledKeys();
         synchronized (cancelledKeys) {
             if (cancelledKeys.size() > 0) {
                 for (SelectionKey currentkey : cancelledKeys) {
+                    mutableKeys.remove(currentkey);
                     deregister((AbstractSelectionKey) currentkey);
-                    keys.remove(currentkey);
-                    selectedKeys.remove(currentkey);
+                    if (mutableSelectedKeys.remove(currentkey)) {
+                        deselected++;
+                    }
                 }
+                cancelledKeys.clear();
             }
-            cancelledKeys.clear();
         }
+
+        return deselected;
     }
 
-    /*
+    /**
      * @see java.nio.channels.Selector#wakeup()
      */
+    @Override
     public Selector wakeup() {
         try {
             sink.write(ByteBuffer.allocate(MOCK_WRITEBUF_SIZE));
@@ -338,16 +424,18 @@
 
     private static class UnaddableSet<E> implements Set<E> {
 
-        private Set<E> set;
+        private final Set<E> set;
 
         UnaddableSet(Set<E> set) {
             this.set = set;
         }
 
+        @Override
         public boolean equals(Object object) {
             return set.equals(object);
         }
 
+        @Override
         public int hashCode() {
             return set.hashCode();
         }
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java
index d774b3a..0c75808 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java
@@ -25,10 +25,8 @@
 import java.nio.channels.spi.AbstractSelector;
 import java.nio.channels.spi.SelectorProvider;
 
-
 /*
  * Internal implementation of SelectorProvider.
- * 
  */
 public class SelectorProviderImpl extends SelectorProvider {
 
@@ -39,44 +37,38 @@
         super();
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.spi.SelectorProvider#openDatagramChannel()
      */
     public DatagramChannel openDatagramChannel() throws IOException {
         return new DatagramChannelImpl(this);
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.spi.SelectorProvider#openPipe()
      */
     public Pipe openPipe() throws IOException {
         return new PipeImpl();
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.spi.SelectorProvider#openSelector()
      */
     public AbstractSelector openSelector() throws IOException {
         return new SelectorImpl(this);
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.spi.SelectorProvider#openServerSocketChannel()
      */
     public ServerSocketChannel openServerSocketChannel() throws IOException {
         return new ServerSocketChannelImpl(this);
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.spi.SelectorProvider#openSocketChannel()
      */
     public SocketChannel openSocketChannel() throws IOException {
         return new SocketChannelImpl(this);
     }
-
 }
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
index dbef656..22d1b4a 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
@@ -126,15 +126,17 @@
                 synchronized (blockingLock()) {
                     boolean isBlocking = isBlocking();
                     if (!isBlocking) {
-                        // for non blocking mode, use select to see whether
-                        // there are any pending connections.
-                        int[] tryResult = Platform.getNetworkSystem().select(
+                        // BEGIN android-changed
+                        //     copied from a newer version of Harmony
+                        int[] tryResult = new int[1];
+                        boolean success = Platform.getNetworkSystem().select(
                                 new FileDescriptor[] { this.fd },
-                                new FileDescriptor[0], 0);
-                        if (0 == tryResult.length || 0 == tryResult[0]) {
+                                new FileDescriptor[0], 1, 0, 0, tryResult);
+                        if (!success || 0 == tryResult[0]) {
                             // no pending connections, returns immediately.
                             return null;
                         }
+                        // END android-changed
                     }
                     // do accept.
                     do {
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
index 1affb21..cf6d839 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
@@ -18,7 +18,6 @@
 package org.apache.harmony.nio.internal;
 
 // BEGIN android-note
-// Copied from a newer version of Harmony.
 // In this class the address length was changed from long to int.
 // END android-note
 
@@ -51,7 +50,7 @@
 import org.apache.harmony.luni.platform.FileDescriptorHandler;
 import org.apache.harmony.luni.platform.INetworkSystem;
 import org.apache.harmony.luni.platform.Platform;
-import org.apache.harmony.luni.util.ErrorCodeException;
+//import org.apache.harmony.luni.util.ErrorCodeException; android-removed
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.nio.AddressUtil;
 import org.apache.harmony.nio.internal.nls.Messages;
@@ -63,7 +62,7 @@
 
     private static final int EOF = -1;
 
-    private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211;
+    // android-removed: private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211;
 
     // The singleton to do the native network operation.
     static final INetworkSystem networkSystem = Platform.getNetworkSystem();
@@ -270,7 +269,8 @@
         try {
             if (isBlocking()) {
                 begin();
-                result = networkSystem.connect(fd, trafficClass, normalAddr, port);
+                networkSystem.connect(fd, trafficClass, normalAddr, port);
+                result = CONNECT_SUCCESS; // Or we'd have thrown an exception.
             } else {
                 result = networkSystem.connectWithTimeout(fd, 0, trafficClass,
                         normalAddr, port, HY_SOCK_STEP_START, connectContext);
@@ -376,7 +376,7 @@
         if (!target.hasRemaining()) {
             return 0;
         }
-        
+
         int readCount;
         if (target.isDirect() || target.hasArray()) {
             readCount = readImpl(target);
@@ -454,9 +454,9 @@
                 int length = target.remaining();
                 if (target.isDirect()) {
                     // BEGIN android-changed
-                    // changed address from long to int; split address and offset paramters
+                    // changed address from long to int
                     int address = AddressUtil.getDirectBufferAddress(target);
-                    readCount = networkSystem.readDirect(fd, address, offset,
+                    readCount = networkSystem.readDirect(fd, address + offset,
                             length, (isBlocking() ? TIMEOUT_BLOCK
                                     : TIMEOUT_NONBLOCK));
                     // END android-changed
@@ -569,14 +569,7 @@
                     writeCount = networkSystem.write(fd, array, 0, length);
                 }
                 source.position(pos + writeCount);
-            } catch (SocketException e) {
-                if (e.getCause() instanceof ErrorCodeException) {
-                    if (ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK == ((ErrorCodeException) e
-                            .getCause()).getErrorCode()) {
-                        return writeCount;
-                    }
-                }
-                throw e;
+                // android-removed: bogus catch (SocketException e) and use of ErrorCodeException.
             } finally {
                 if (isBlocking()) {
                     end(writeCount >= 0);
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/WriteOnlyFileChannel.java b/nio/src/main/java/org/apache/harmony/nio/internal/WriteOnlyFileChannel.java
index ffcdd14..eb46043 100644
--- a/nio/src/main/java/org/apache/harmony/nio/internal/WriteOnlyFileChannel.java
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/WriteOnlyFileChannel.java
@@ -16,7 +16,7 @@
  */
 
 /*
- * Android Notice 
+ * Android Notice
  * In this class the address length was changed from long to int.
  * This is due to performance optimizations for the device.
  */
@@ -43,9 +43,10 @@
         super(stream, handle);
         append = isAppend;
     }
-    
+
     /*
      * (non-Javadoc)
+     * 
      * @see org.apache.harmony.nio.internal.FileChannelImpl#position()
      */
     public long position() throws IOException {
@@ -62,7 +63,7 @@
     }
 
     public long read(ByteBuffer[] buffers, int offset, int length)
-            throws IOException {        
+            throws IOException {
         if (offset < 0 || length < 0 || offset + length > buffers.length) {
             throw new IndexOutOfBoundsException();
         }
@@ -75,11 +76,11 @@
         throw new NonReadableChannelException();
     }
 
-    public int read(ByteBuffer buffer, long position) throws IOException {        
+    public int read(ByteBuffer buffer, long position) throws IOException {
         if (null == buffer) {
             throw new NullPointerException();
         }
-        if (position < 0){
+        if (position < 0) {
             throw new IllegalArgumentException();
         }
         throw new NonReadableChannelException();
@@ -111,5 +112,4 @@
         }
         return super.basicLock(position, size, shared, wait);
     }
-
 }
diff --git a/nio/src/main/native/org_apache_harmony_nio_AddressUtil.cpp b/nio/src/main/native/org_apache_harmony_nio_AddressUtil.cpp
deleted file mode 100644
index cb665de..0000000
--- a/nio/src/main/native/org_apache_harmony_nio_AddressUtil.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 "AndroidSystemNatives.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#define SOCKET_CAST(x) ((struct hysocket_struct*)  x)->sock
-
-typedef jint OSSOCKET; 
-
-typedef struct hysocket_struct
-{
-    OSSOCKET sock;
-    unsigned short family;
-} hysocket_struct;
-
-typedef struct hysocket_struct *hysocket_t;
-
-/*
- * Internal helper function.
- *
- * Get the file descriptor.
- */
-static jint getFd(JNIEnv* env, jclass clazz, jobject fd)
-{
-    jclass descriptorCLS;
-    jfieldID descriptorFID;
-    hysocket_t* hysocketP;
-
-    descriptorCLS = env->FindClass("java/io/FileDescriptor");
-    if (NULL == descriptorCLS){
-        return 0;
-    }
-    descriptorFID = env->GetFieldID(descriptorCLS, "descriptor", "I");
-    if (NULL == descriptorFID){
-        return 0;
-    }
-    jint result = env->GetIntField(fd, descriptorFID);
-    hysocketP = (hysocket_t*) (result);
-    return SOCKET_CAST(hysocketP);
-}
-
-/*
- * JNI registration
- */
-static JNINativeMethod gMethods[] = {
-    /* name, signature, funcPtr */
-    { "getFDAddress", "(Ljava/io/FileDescriptor;)I", (void*) getFd }
-};
-
-int register_org_apache_harmony_nio_AddressUtil(JNIEnv* env)
-{
-    return jniRegisterNativeMethods(env, "org/apache/harmony/nio/AddressUtil",
-        gMethods, NELEM(gMethods));
-}
diff --git a/nio/src/main/native/sub.mk b/nio/src/main/native/sub.mk
deleted file mode 100644
index 750d216..0000000
--- a/nio/src/main/native/sub.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-# This file is included by the top-level libcore Android.mk.
-# It's not a normal makefile, so we don't include CLEAR_VARS
-# or BUILD_*_LIBRARY.
-
-LOCAL_SRC_FILES := \
-	org_apache_harmony_nio_AddressUtil.cpp
-
-LOCAL_C_INCLUDES +=
-
-# Any shared/static libs that are listed here must also
-# be listed in libs/nativehelper/Android.mk.
-# TODO: fix this requirement
-
-LOCAL_SHARED_LIBRARIES +=
-
-LOCAL_STATIC_LIBRARIES +=
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java
index d7dd36e..049c48b 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java
@@ -74,8 +74,6 @@
         SerializationTest.verifyGolden(this, new BufferOverflowException());
     }
 
-    // BEGIN android-added
-    // copied from newer version of harmony
     /**
      *@tests {@link java.nio.BufferOverflowException#BufferOverflowException()}
      */
@@ -91,5 +89,4 @@
         assertNull(exception.getLocalizedMessage());
         assertNull(exception.getCause());
     }
-    // END android-added
 }
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java
index 2c8d09e..d584994 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java
@@ -77,8 +77,6 @@
         SerializationTest.verifyGolden(this, new BufferUnderflowException());
     }
 
-    // BEGIN android-added
-    // copied from newer version of harmony
     /**
      *@tests {@link java.nio.BufferUnderflowException#BufferUnderflowException()}
      */
@@ -94,5 +92,4 @@
         assertNull(exception.getLocalizedMessage());
         assertNull(exception.getCause());
     }
-    // END android-added
 }
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java
index b232050..576fec5 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java
@@ -1342,6 +1342,30 @@
         }
     }
 
+    public void testRead_scenario1() throws Exception {
+        char[] charArray = new char[] { 'a', 'b' };
+        CharBuffer charBuffer = CharBuffer.wrap(charArray);
+        try {
+            charBuffer.read(charBuffer);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        charBuffer.put(charArray);
+        assertEquals(-1, charBuffer.read(charBuffer));
+    }
+
+    public void testRead_scenario2() throws Exception {
+        CharBuffer charBufferA = CharBuffer.allocate(0);
+        CharBuffer allocateBuffer = CharBuffer.allocate(1);
+        CharBuffer charBufferB = CharBuffer.wrap(allocateBuffer);
+        assertEquals(-1, charBufferA.read(charBufferB));
+
+        allocateBuffer.append(allocateBuffer);
+        charBufferB = CharBuffer.wrap(allocateBuffer);
+        assertEquals(-1, charBufferA.read(charBufferB));
+    }
+
     @TestTargetNew(
         level = TestLevel.PARTIAL_COMPLETE,
         notes = "Abstract method.",
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java
index 6256c16..cf2eb48 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java
@@ -293,6 +293,17 @@
         other.limit(5);
         assertTrue(buf.compareTo(other) > 0);
         assertTrue(other.compareTo(buf) < 0);
+
+        DoubleBuffer dbuffer1 = DoubleBuffer.wrap(new double[] { Double.NaN });
+        DoubleBuffer dbuffer2 = DoubleBuffer.wrap(new double[] { Double.NaN });
+        DoubleBuffer dbuffer3 = DoubleBuffer.wrap(new double[] { 42d });
+
+        assertEquals("Failed equal comparison with NaN entry", 0, dbuffer1
+                .compareTo(dbuffer2));
+        assertEquals("Failed greater than comparison with NaN entry", 1, dbuffer3
+                .compareTo(dbuffer1));
+        assertEquals("Failed greater than comparison with NaN entry", 1, dbuffer1
+                .compareTo(dbuffer3));
     }
 
     @TestTargetNew(
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java
index 4d5558c..8edd799 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java
@@ -290,8 +290,6 @@
         assertTrue(buf.compareTo(other) > 0);
         assertTrue(other.compareTo(buf) < 0);
 
-        // BEGIN android-added
-        // copied from a newer version of Harmony
         FloatBuffer fbuffer1 = FloatBuffer.wrap(new float[] { Float.NaN });
         FloatBuffer fbuffer2 = FloatBuffer.wrap(new float[] { Float.NaN });
         FloatBuffer fbuffer3 = FloatBuffer.wrap(new float[] { 42f });
@@ -302,7 +300,6 @@
                 .compareTo(fbuffer1));
         assertEquals("Failed greater than comparison with NaN entry", 1, fbuffer1
                 .compareTo(fbuffer3));
-        // END android-added
     }
 
     @TestTargetNew(
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java
index 3fd32f55..3278e6b 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java
@@ -56,8 +56,6 @@
         SerializationTest.verifyGolden(this, new InvalidMarkException());
     }
 
-    // BEGIN android-added
-    // copied from newer version of harmony
     /**
      *@tests {@link java.nio.InvalidMarkException#InvalidMarkException()}
      */
@@ -73,5 +71,4 @@
         assertNull(exception.getLocalizedMessage());
         assertNull(exception.getCause());
     }
-    // END android-added
 }
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java
index 8c97ae0..f01ed75 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java
@@ -73,8 +73,6 @@
         SerializationTest.verifyGolden(this, new ReadOnlyBufferException());
     }
 
-    // BEGIN android-added
-    // copied from newer version of harmony
     /**
      *@tests {@link java.nio.ReadOnlyBufferException#ReadOnlyBufferException()}
      */
@@ -90,5 +88,4 @@
         assertNull(exception.getLocalizedMessage());
         assertNull(exception.getCause());
     }
-    // END android-added
 }
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java
index 6767713..1f31121 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java
@@ -31,6 +31,16 @@
  * Tests for AlreadyConnectedException
  */
 public class AlreadyConnectedExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.AlreadyConnectedException#AlreadyConnectedException()}
+     */
+    public void test_Constructor() {
+        AlreadyConnectedException e = new AlreadyConnectedException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java
index b9f392d..9752ddc 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java
@@ -33,6 +33,16 @@
 public class AsynchronousCloseExceptionTest extends TestCase {
 
     /**
+     * @tests {@link java.nio.channels.AsynchronousCloseException#AsynchronousCloseException()}
+     */
+    public void test_Constructor() {
+        AsynchronousCloseException e = new AsynchronousCloseException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+    
+    /**
      * @tests serialization/deserialization compatibility.
      */
     @TestTargets({
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java
index a8edce4..91786d4 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(CancelledKeyException.class)
 public class CancelledKeyExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.CancelledKeyException#CancelledKeyException()}
+     */
+    public void test_Constructor() {
+        CancelledKeyException e = new CancelledKeyException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java
index 8b5dcc7..913598e 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java
@@ -31,7 +31,16 @@
  */
 @TestTargetClass(ClosedByInterruptException.class)
 public class ClosedByInterruptExceptionTest extends TestCase {
-
+    
+    /**
+     * @tests {@link java.nio.channels.ClosedByInterruptException#ClosedByInterruptException()}
+     */
+    public void test_Constructor() {
+        ClosedByInterruptException e = new ClosedByInterruptException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
     /**
      * @tests serialization/deserialization compatibility.
      */
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java
index 088b7b5..cc302ed 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(ClosedChannelException.class)
 public class ClosedChannelExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.ClosedChannelException#ClosedChannelException()}
+     */
+    public void test_Constructor() {
+        ClosedChannelException e = new ClosedChannelException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java
index 145dd22..232340f 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(ClosedSelectorException.class)
 public class ClosedSelectorExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.ClosedSelectorException#ClosedSelectorException()}
+     */
+    public void test_Constructor() {
+        ClosedSelectorException e = new ClosedSelectorException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java
index e0d6489..6726ca0 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(ConnectionPendingException.class)
 public class ConnectionPendingExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.ConnectionPendingException#ConnectionPendingException()}
+     */
+    public void test_Constructor() {
+        ConnectionPendingException e = new ConnectionPendingException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
index 36e0082..49c5faa 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
+++ b/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/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
index 91d6d06..2d96289 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
+++ b/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
     }
 
     /**
@@ -4562,6 +4581,52 @@
         }
     }
 
+    /**
+     * Regression test for Harmony-3324
+     * Make sure we could delete the file after we called transferTo() method.
+     */
+    public void test_transferTo_couldDelete() throws Exception {
+        // init data in files
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        // call transferTo() method
+        readOnlyFileChannel.transferTo(0 , 2, writeOnlyFileChannel);
+
+        // delete both files
+        readOnlyFileChannel.close();
+        writeOnlyFileChannel.close();
+        boolean rDel = fileOfReadOnlyFileChannel.delete();
+        boolean wDel = fileOfWriteOnlyFileChannel.delete();
+
+        // make sure both files were deleted
+        assertTrue("File " + readOnlyFileChannel + " exists", rDel);
+        assertTrue("File " + writeOnlyFileChannel + " exists", wDel);
+    }
+
+    /**
+     * Regression test for Harmony-3324
+     * Make sure we could delete the file after we called transferFrom() method.
+     */
+    public void test_transferFrom_couldDelete() throws Exception {
+        // init data in files
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        // call transferTo() method
+        writeOnlyFileChannel.transferFrom(readOnlyFileChannel, 0 , 2);
+
+        // delete both files
+        readOnlyFileChannel.close();
+        writeOnlyFileChannel.close();
+        boolean rDel = fileOfReadOnlyFileChannel.delete();
+        boolean wDel = fileOfWriteOnlyFileChannel.delete();
+
+        // make sure both files were deleted
+        assertTrue("File " + readOnlyFileChannel + " exists", rDel);
+        assertTrue("File " + writeOnlyFileChannel + " exists", wDel);
+    }
+
     private class MockFileChannel extends FileChannel {
 
         private boolean isLockCalled = false;
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java
index f1ccc96..3b30229 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(FileLockInterruptionException.class)
 public class FileLockInterruptionExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.FileLockInterruptionException#FileLockInterruptionException()}
+     */
+    public void test_Constructor() {
+        FileLockInterruptionException e = new FileLockInterruptionException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java
index 6148b6f..13e6b2d 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java
@@ -66,6 +66,12 @@
         mockLock = new MockFileLock(readWriteChannel, 10, 100, false);
     }
 
+	protected void tearDown() throws IOException {
+	    if (readWriteChannel != null) {
+	        readWriteChannel.close();
+	    }
+	}
+
     /**
      * @tests java.nio.channels.FileLock#FileLock(FileChannel, long, long,
      *        boolean)
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java
index 4b1a840..85e995f 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(IllegalBlockingModeException.class)
 public class IllegalBlockingModeExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.IllegalBlockingModeException#IllegalBlockingModeException()}
+     */
+    public void test_Constructor() {
+        IllegalBlockingModeException e = new IllegalBlockingModeException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java
index e8efc31..69066b8 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(IllegalSelectorException.class)
 public class IllegalSelectorExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.IllegalSelectorException#IllegalSelectorException()}
+     */
+    public void test_Constructor() {
+        IllegalSelectorException e = new IllegalSelectorException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java
index 8efe2ae..e2deb04 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(NoConnectionPendingException.class)
 public class NoConnectionPendingExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.NoConnectionPendingException#NoConnectionPendingException()}
+     */
+    public void test_Constructor() {
+        NoConnectionPendingException e = new NoConnectionPendingException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java
index d255e4b..76002ea 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(NonReadableChannelException.class)
 public class NonReadableChannelExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.NonReadableChannelException#NonReadableChannelException()}
+     */
+    public void test_Constructor() {
+        NonReadableChannelException e = new NonReadableChannelException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java
index fc23223..60e0cd5 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(NonWritableChannelException.class)
 public class NonWritableChannelExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.NonWritableChannelException#NonWritableChannelException()}
+     */
+    public void test_Constructor() {
+        NonWritableChannelException e = new NonWritableChannelException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java
index d76d84a..d0d8df7 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(NotYetBoundException.class)
 public class NotYetBoundExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.NotYetBoundException#NotYetBoundException()}
+     */
+    public void test_Constructor() {
+        NotYetBoundException e = new NotYetBoundException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java
index e1a8945..4d81c62e 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(NotYetConnectedException.class)
 public class NotYetConnectedExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.NotYetConnectedException#NotYetConnectedException()}
+     */
+    public void test_Constructor() {
+        NotYetConnectedException e = new NotYetConnectedException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java
index 0c1cc8b..7907369 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(OverlappingFileLockException.class)
 public class OverlappingFileLockExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.OverlappingFileLockException#OverlappingFileLockException()}
+     */
+    public void test_Constructor() {
+        OverlappingFileLockException e = new OverlappingFileLockException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java
index de69f9f..ee4b02b 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java
@@ -23,6 +23,8 @@
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.ClosedSelectorException;
@@ -30,8 +32,12 @@
 import java.nio.channels.Selector;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
+import java.nio.channels.Pipe;
 import java.nio.channels.spi.SelectorProvider;
 import java.util.Set;
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import junit.framework.TestCase;
 import tests.support.Support_PortManager;
@@ -331,29 +337,6 @@
     }
 
     /**
-     * @test java.nio.channels.Selector#select(long)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "Verifies select(long) method for empty selection keys.",
-        method = "select",
-        args = {long.class}
-    )
-    public void test_selectJ_Empty_Keys() throws IOException {
-        // regression test, see HARMONY-3888.
-        // make sure select(long) does wait for specified amount of
-        // time if keys.size() == 0 (initial state of selector).
-
-        final long SELECT_TIMEOUT = 1000;
-
-        long time1 = System.currentTimeMillis();
-        selector.select(SELECT_TIMEOUT);
-        long time2 = System.currentTimeMillis();
-        assertEquals("elapsed time", SELECT_TIMEOUT, (time2 - time1),
-                     SELECT_TIMEOUT * 0.05); // 5% accuracy
-    }
-
-    /**
      * @tests java.nio.channel.Selector#select(long)
      */
     @TestTargetNew(
@@ -400,6 +383,29 @@
     }
 
     /**
+     * @test java.nio.channels.Selector#select(long)
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "Verifies select(long) method for empty selection keys.",
+            method = "select",
+            args = {long.class}
+    )
+    public void test_selectJ_Empty_Keys() throws IOException {
+        // regression test, see HARMONY-3888.
+        // make sure select(long) does wait for specified amount of
+        // time if keys.size() == 0 (initial state of selector).
+
+        final long SELECT_TIMEOUT = 2000;
+
+        long time1 = System.currentTimeMillis();
+        selector.select(SELECT_TIMEOUT);
+        long time2 = System.currentTimeMillis();
+        assertEquals("elapsed time", SELECT_TIMEOUT, (time2 - time1),
+                SELECT_TIMEOUT * 0.05); // 5% accuracy
+    }
+
+    /**
      * @tests java.nio.channels.Selector#wakeup()
      */
     @TestTargetNew(
@@ -448,6 +454,69 @@
         selectOnce(SelectType.TIMEOUT, 0);
     }
 
+    public void test_keySetViewsModifications() throws IOException {
+        Set<SelectionKey> keys = selector.keys();
+
+        SelectionKey key1 = ssc.register(selector, SelectionKey.OP_ACCEPT);
+
+        assertTrue(keys.contains(key1));
+
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        SelectionKey key2 = sc.register(selector, SelectionKey.OP_READ);
+
+        assertTrue(keys.contains(key1));
+        assertTrue(keys.contains(key2));
+
+        key1.cancel();
+        assertTrue(keys.contains(key1));
+
+        selector.selectNow();
+        assertFalse(keys.contains(key1));
+        assertTrue(keys.contains(key2));
+     }
+
+    /**
+     * This test cancels a key while selecting to verify that the cancelled
+     * key set is processed both before and after the call to the underlying
+     * operating system.
+     */
+    public void test_cancelledKeys() throws Exception {
+        final AtomicReference<Throwable> failure = new AtomicReference<Throwable>();
+        final AtomicBoolean complete = new AtomicBoolean();
+
+        final Pipe pipe = Pipe.open();
+        pipe.source().configureBlocking(false);
+        final SelectionKey key = pipe.source().register(selector, SelectionKey.OP_READ);
+
+        Thread thread = new Thread() {
+            public void run() {
+                try {
+                    // make sure to call key.cancel() while the main thread is selecting
+                    Thread.sleep(500);
+                    key.cancel();
+                    assertFalse(key.isValid());
+                    pipe.sink().write(ByteBuffer.allocate(4)); // unblock select()
+                } catch (Throwable e) {
+                    failure.set(e);
+                } finally {
+                    complete.set(true);
+                }
+            }
+        };
+        assertTrue(key.isValid());
+
+        thread.start();
+        do {
+            assertEquals(0, selector.select(5000)); // blocks
+            assertEquals(0, selector.selectedKeys().size());
+        } while (!complete.get()); // avoid spurious interrupts
+        assertFalse(key.isValid());
+
+        thread.join();
+        assertNull(failure.get());
+    }
+
     private void assert_select_SelectorClosed(SelectType type, int timeout)
             throws IOException {
         // selector is closed
@@ -669,4 +738,4 @@
         return ret;
     }
 
-}
\ No newline at end of file
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
old mode 100755
new mode 100644
index ce34dba..54ef9db
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
@@ -2796,6 +2796,42 @@
         }
     }
 
+    public void testReadByteBuffer_Direct2() throws IOException {
+        byte[] request = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+        ByteBuffer buffer = ByteBuffer.allocateDirect(128);
+
+        ServerSocketChannel server = ServerSocketChannel.open();
+        server.socket().bind(
+                new InetSocketAddress(InetAddress.getLocalHost(), 0), 5);
+        Socket client = new Socket(InetAddress.getLocalHost(), server.socket()
+                .getLocalPort());
+        client.setTcpNoDelay(false);
+        Socket worker = server.socket().accept();
+        SocketChannel workerChannel = worker.getChannel();
+
+        OutputStream out = client.getOutputStream();
+        out.write(request);
+        out.close();
+
+        buffer.limit(5);
+        int bytesRead = workerChannel.read(buffer);
+        assertEquals(5, bytesRead);
+        assertEquals(5, buffer.position());
+
+        buffer.limit(request.length);
+        bytesRead = workerChannel.read(buffer);
+        assertEquals(6, bytesRead);
+
+        buffer.flip();
+        assertEquals(request.length, buffer.limit());
+
+        assertEquals(ByteBuffer.wrap(request), buffer);
+
+        client.close();
+        worker.close();
+        server.close();
+    }
+
     @TestTargetNew(
         level = TestLevel.PARTIAL_COMPLETE,
         notes = "",
@@ -3279,6 +3315,20 @@
      * ==========================================================================
      */
 
+
+    /**
+     * @tests java.nio.channels.SocketChannel#read(ByteBuffer[])
+     */
+    public void test_read$LByteBuffer() throws IOException {
+        MockSocketChannel sc = new MockSocketChannel(null);
+        ByteBuffer [] byteBufferArray = { ByteBuffer.allocate(1), ByteBuffer.allocate(1)};
+        // Verify that calling read(ByteBuffer[]) leads to the method
+        // read(ByteBuffer[], int, int) being called with a 0 for the
+        // second parameter and targets.length as the third parameter.
+        sc.read(byteBufferArray);
+        assertTrue(sc.isReadCalled);
+    }
+
     /**
      * @tests java.nio.channels.SocketChannel#read(ByteBuffer[],int,int)
      */
@@ -3524,6 +3574,19 @@
     }
 
     /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+     */
+    public void test_write$LByteBuffer() throws IOException {
+        MockSocketChannel sc = new MockSocketChannel(null);
+        ByteBuffer [] byteBufferArray = { ByteBuffer.allocate(1), ByteBuffer.allocate(1)};
+        // Verify that calling write(ByteBuffer[]) leads to the method
+        // write(ByteBuffer[], int, int) being called with a 0 for the
+        // second parameter and sources.length as the third parameter.
+        sc.write(byteBufferArray);
+        assertTrue(sc.isWriteCalled);
+    }
+
+    /**
      * @tests java.nio.channels.SocketChannel#write(ByteBuffer[],int,int)
      */
     @TestTargetNew(
@@ -4116,6 +4179,39 @@
         }
     }
 
+    public void testSocket_setOptions() throws IOException {
+        channel1.connect(localAddr1);
+        Socket socket = channel1.socket();
+
+        ByteBuffer buffer = ByteBuffer.wrap(new byte[] {1, 2, 3});
+        socket.setKeepAlive(true);
+        channel1.write(buffer);
+
+        socket.setOOBInline(true);
+        channel1.write(buffer);
+
+        socket.setReceiveBufferSize(100);
+        channel1.write(buffer);
+
+        socket.setReuseAddress(true);
+        channel1.write(buffer);
+
+        socket.setSendBufferSize(100);
+        channel1.write(buffer);
+
+        socket.setSoLinger(true, 100);
+        channel1.write(buffer);
+
+        socket.setSoTimeout(1000);
+        channel1.write(buffer);
+
+        socket.setTcpNoDelay(true);
+        channel1.write(buffer);
+
+        socket.setTrafficClass(10);
+        channel1.write(buffer);
+    }
+
     /**
      * @throws IOException 
      * @tests java.nio.channels.SocketChannel#read(ByteBuffer)
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java
index fe3417f..1838902 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(UnresolvedAddressException.class)
 public class UnresolvedAddressExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.UnresolvedAddressException#UnresolvedAddressException()}
+     */
+    public void test_Constructor() {
+        UnresolvedAddressException e = new UnresolvedAddressException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java
index 442fc1e..97e3eda 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java
@@ -31,6 +31,16 @@
  */
 @TestTargetClass(UnsupportedAddressTypeException.class)
 public class UnsupportedAddressTypeExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.UnsupportedAddressTypeException#UnsupportedAddressTypeException()}
+     */
+    public void test_Constructor() {
+        UnsupportedAddressTypeException e = new UnsupportedAddressTypeException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
 
     /**
      * @tests serialization/deserialization compatibility.
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
index c81efa2..4a2fa73 100644
--- a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
@@ -178,8 +178,17 @@
         assertSame(sc, acceptKey.channel());
 
         //test that sc.register invokes Selector.register()
-        sc.register(acceptSelector2, SelectionKey.OP_READ, null);
+        acceptKey = sc.register(acceptSelector2, SelectionKey.OP_READ, null);
         assertTrue(((MockAbstractSelector)acceptSelector2).isRegisterCalled);
+
+        // Regression test to ensure acceptance of a selector with empty
+        // interest set.
+        SocketChannel channel = SocketChannel.open();
+        channel.configureBlocking(false);
+        Selector selector = Selector.open();
+        channel.register(selector, 0);
+        selector.close();
+        channel.close();
     }
 
     /**
diff --git a/nio_char/src/main/java/java/nio/charset/CharacterCodingException.java b/nio_char/src/main/java/java/nio/charset/CharacterCodingException.java
index a6c04bc..eee01f7 100644
--- a/nio_char/src/main/java/java/nio/charset/CharacterCodingException.java
+++ b/nio_char/src/main/java/java/nio/charset/CharacterCodingException.java
@@ -22,8 +22,6 @@
 /**
  * A {@code CharacterCodingException} is thrown when an encoding or decoding
  * error occurs.
- * 
- * @since Android 1.0
  */
 public class CharacterCodingException extends IOException {
 
@@ -35,8 +33,6 @@
 
     /**
      * Constructs a new {@code CharacterCodingException}.
-     *
-     * @since Android 1.0
      */
     public CharacterCodingException() {
         super();
diff --git a/nio_char/src/main/java/java/nio/charset/Charset.java b/nio_char/src/main/java/java/nio/charset/Charset.java
index 045f71f..724699f 100644
--- a/nio_char/src/main/java/java/nio/charset/Charset.java
+++ b/nio_char/src/main/java/java/nio/charset/Charset.java
@@ -37,8 +37,11 @@
 import java.util.Set;
 import java.util.SortedMap;
 import java.util.TreeMap;
+import java.util.Vector;
 
+// BEGIN android-changed
 import com.ibm.icu4jni.charset.CharsetProviderICU;
+// END android-changed
 
 /**
  * A charset defines a mapping between a Unicode character sequence and a byte
@@ -50,11 +53,9 @@
  * also has one or more aliases. The name string can only consist of the
  * following characters: '0' - '9', 'A' - 'Z', 'a' - 'z', '.', ':'. '-' and '_'.
  * The first character of the name must be a digit or a letter.
- * </p>
  * <p>
  * The following charsets should be supported by any java platform: US-ASCII,
  * ISO-8859-1, UTF-8, UTF-16BE, UTF-16LE, UTF-16.
- * </p>
  * <p>
  * Additional charsets can be made available by configuring one or more charset
  * providers through provider configuration files. Such files are always named
@@ -68,96 +69,62 @@
  * comments, are both ignored. Duplicates of names already found are also
  * ignored. Both the configuration files and the provider classes will be loaded
  * using the thread context class loader.
- * </p>
  * <p>
  * This class is thread-safe.
- * </p>
- * 
+ *
  * @see java.nio.charset.spi.CharsetProvider
- * @since Android 1.0
  */
 public abstract class Charset implements Comparable<Charset> {
 
     /*
-     * --------------------------------------------------------------------
-     * Constants
-     * --------------------------------------------------------------------
-     */
-
-    /*
-     * the name of configuration files where charset provider class names can be
+     * The name of configuration files where charset provider class names can be
      * specified.
      */
     private static final String PROVIDER_CONFIGURATION_FILE_NAME = "META-INF/services/java.nio.charset.spi.CharsetProvider"; //$NON-NLS-1$
 
     /*
-     * the encoding of configuration files
+     * The encoding of configuration files
      */
     private static final String PROVIDER_CONFIGURATION_FILE_ENCODING = "UTF-8"; //$NON-NLS-1$
 
     /*
-     * the comment string used in configuration files
+     * The comment string used in configuration files
      */
     private static final String PROVIDER_CONFIGURATION_FILE_COMMENT = "#"; //$NON-NLS-1$
 
     private static ClassLoader systemClassLoader;
 
-    /*
-     * --------------------------------------------------------------------
-     * Class variables
-     * --------------------------------------------------------------------
-     */
-
     // built in provider instance, assuming thread-safe
-    private static CharsetProviderICU _builtInProvider = null;
+    // BEGIN android-changed
+    private static final CharsetProviderICU _builtInProvider;
+    // END android-changed
 
     // cached built in charsets
     private static TreeMap<String, Charset> _builtInCharsets = null;
 
-    /*
-     * --------------------------------------------------------------------
-     * Instance variables
-     * --------------------------------------------------------------------
-     */
-
     private final String canonicalName;
 
     // the aliases set
     private final HashSet<String> aliasesSet;
 
     // cached Charset table
-    private static HashMap<String, Charset> cachedCharsetTable = new HashMap<String, Charset>();
+    private final static HashMap<String, Charset> cachedCharsetTable = new HashMap<String, Charset>();
 
-    // cached CharsetDecoder table
-    private static HashMap<String, CharsetDecoder> cachedCharsetDecoderTable = new HashMap<String, CharsetDecoder>();
+    private static boolean inForNameInternal = false;
 
-    // cached CharsetEncoder table
-    private static HashMap<String, CharsetEncoder> cachedCharsetEncoderTable = new HashMap<String, CharsetEncoder>();
-
-    /*
-     * -------------------------------------------------------------------
-     * Global initialization
-     * -------------------------------------------------------------------
-     */
     static {
         /*
-         * create built-in charset provider even if no privilege to access
+         * Create built-in charset provider even if no privilege to access
          * charset provider.
          */
         _builtInProvider = AccessController
                 .doPrivileged(new PrivilegedAction<CharsetProviderICU>() {
                     public CharsetProviderICU run() {
-                        return new CharsetProviderICU();
-                    }
+                         return new CharsetProviderICU();
+                   }
                 });
     }
 
-    /*
-     * -------------------------------------------------------------------
-     * Constructors
-     * -------------------------------------------------------------------
-     */
-
     /**
      * Constructs a <code>Charset</code> object. Duplicated aliases are
      * ignored.
@@ -170,11 +137,8 @@
      *             on an illegal value being supplied for either
      *             <code>canonicalName</code> or for any element of
      *             <code>aliases</code>.
-     * @since Android 1.0
      */
-    protected Charset(String canonicalName, String[] aliases)
-            throws IllegalCharsetNameException {
-        // throw IllegalArgumentException if name is null
+    protected Charset(String canonicalName, String[] aliases) {
         if (null == canonicalName) {
             throw new NullPointerException();
         }
@@ -192,12 +156,6 @@
     }
 
     /*
-     * -------------------------------------------------------------------
-     * Methods
-     * -------------------------------------------------------------------
-     */
-
-    /*
      * Checks whether a character is a special character that can be used in
      * charset names, other than letters and digits.
      */
@@ -361,16 +319,22 @@
      * Gets a map of all available charsets supported by the runtime.
      * <p>
      * The returned map contains mappings from canonical names to corresponding
-     * instances of <code>Charset</code>. The canonical names can be
-     * considered as case-insensitive.
-     * </p>
-     * 
+     * instances of <code>Charset</code>. The canonical names can be considered
+     * as case-insensitive.
+     *
      * @return an unmodifiable map of all available charsets supported by the
-     *         runtime.
-     * @since Android 1.0
+     *         runtime
      */
     @SuppressWarnings("unchecked")
     public static SortedMap<String, Charset> availableCharsets() {
+        // BEGIN android-removed
+        // // workaround: conflicted Charsets with icu4j 4.0
+        // Charset.forName("TIS-620");
+        // Charset.forName("windows-1258");
+        // Charset.forName("cp856");
+        // Charset.forName("cp922");
+        // END android-removed
+
         // Initialize the built-in charsets map cache if necessary
         if (null == _builtInCharsets) {
             synchronized (Charset.class) {
@@ -480,53 +444,66 @@
     }
 
     /*
-     * Gets a <code> Charset </code> instance for the specified charset name. If
+     * Gets a <code>Charset</code> instance for the specified charset name. If
      * the charset is not supported, returns null instead of throwing an
      * exception.
      */
-    private static Charset forNameInternal(String charsetName)
+    private synchronized static Charset forNameInternal(String charsetName)
             throws IllegalCharsetNameException {
+        Charset cs = cachedCharsetTable.get(charsetName);
+        if (null != cs) {
+            return cs;
+        }
+
         if (null == charsetName) {
             throw new IllegalArgumentException();
         }
         checkCharsetName(charsetName);
-        synchronized (Charset.class) {
-            // Try to get Charset from cachedCharsetTable
-            Charset cs = getCachedCharset(charsetName);
-            if (null != cs) {
-                return cs;
-            }
-            // Try built-in charsets
-            cs = _builtInProvider.charsetForName(charsetName);
-            if (null != cs) {
-                cacheCharset(cs);
-                return cs;
-            }
+        // try built-in charsets
+        // BEGIN android-removed
+        // if (_builtInProvider == null) {
+        //     _builtInProvider = new CharsetProviderICU();
+        // }
+        // END android-removed
+        cs = _builtInProvider.charsetForName(charsetName);
+        if (null != cs) {
+            cacheCharset(cs);
+            return cs;
+        }
 
-            // Collect all charsets provided by charset providers
-            ClassLoader contextClassLoader = getContextClassLoader();
-            Enumeration<URL> e = null;
-            try {
-                if (null != contextClassLoader) {
-                    e = contextClassLoader
-                            .getResources(PROVIDER_CONFIGURATION_FILE_NAME);
+        // collect all charsets provided by charset providers
+        ClassLoader contextClassLoader = getContextClassLoader();
+        Enumeration<URL> e = null;
+        try {
+            if (null != contextClassLoader) {
+                e = contextClassLoader
+                        .getResources(PROVIDER_CONFIGURATION_FILE_NAME);
+            } else {
+                getSystemClassLoader();
+                if (systemClassLoader == null) {
+                    // Non available during class library start-up phase
+                    e = new Vector<URL>().elements();
                 } else {
-                    getSystemClassLoader();
                     e = systemClassLoader
                             .getResources(PROVIDER_CONFIGURATION_FILE_NAME);
                 }
-                // Examine each configuration file
-                while (e.hasMoreElements()) {
-                    cs = searchConfiguredCharsets(charsetName,
-                            contextClassLoader, e.nextElement());
-                    if (null != cs) {
-                        cacheCharset(cs);
-                        return cs;
-                    }
-                }
-            } catch (IOException ex) {
-                // Unexpected ClassLoader exception, ignore
             }
+
+            // examine each configuration file
+            while (e.hasMoreElements()) {
+			     inForNameInternal = true;
+			     cs = searchConfiguredCharsets(charsetName, contextClassLoader,
+                        e.nextElement());
+				 inForNameInternal = false;
+                if (null != cs) {
+                    cacheCharset(cs);
+                    return cs;
+                }
+            }
+        } catch (IOException ex) {
+            // Unexpected ClassLoader exception, ignore
+        } finally {
+		    inForNameInternal = false;
         }
         return null;
     }
@@ -535,24 +512,21 @@
      * save charset into cachedCharsetTable
      */
     private static void cacheCharset(Charset cs) {
-        cachedCharsetTable.put(cs.name(), cs);
+        if (!cachedCharsetTable.containsKey(cs.name())){
+            cachedCharsetTable.put(cs.name(), cs);  
+        }
         Set<String> aliasesSet = cs.aliases();
         if (null != aliasesSet) {
             Iterator<String> iter = aliasesSet.iterator();
             while (iter.hasNext()) {
                 String alias = iter.next();
-                cachedCharsetTable.put(alias, cs);
+                if (!cachedCharsetTable.containsKey(alias)) {
+                    cachedCharsetTable.put(alias, cs); 
+                }
             }
         }
     }
 
-    /*
-     * get cached charset reference by name
-     */
-    private static Charset getCachedCharset(String name) {
-        return cachedCharsetTable.get(name);
-    }
-
     /**
      * Gets a <code>Charset</code> instance for the specified charset name.
      * 
@@ -563,10 +537,8 @@
      *             if the specified charset name is illegal.
      * @throws UnsupportedCharsetException
      *             if the desired charset is not supported by this runtime.
-     * @since Android 1.0
      */
-    public static Charset forName(String charsetName)
-            throws IllegalCharsetNameException, UnsupportedCharsetException {
+    public static Charset forName(String charsetName) {
         Charset c = forNameInternal(charsetName);
         if (null == c) {
             throw new UnsupportedCharsetException(charsetName);
@@ -582,12 +554,36 @@
      * @return true if the specified charset is supported, otherwise false.
      * @throws IllegalCharsetNameException
      *             if the specified charset name is illegal.
-     * @since Android 1.0
      */
-    public static boolean isSupported(String charsetName)
-            throws IllegalCharsetNameException {
-        Charset cs = forNameInternal(charsetName);
-        return (null != cs);
+    public static synchronized boolean isSupported(String charsetName) {
+        if (inForNameInternal) {
+            Charset cs = cachedCharsetTable.get(charsetName);
+            if (null != cs) {
+                return true;
+            }
+
+            if (null == charsetName) {
+                throw new IllegalArgumentException();
+            }
+            checkCharsetName(charsetName);
+
+            // Try built-in charsets
+            // BEGIN android-removed
+            // if (_builtInProvider == null) {
+            //     _builtInProvider = new CharsetProviderICU();
+            // }
+            // END android-removed
+            cs = _builtInProvider.charsetForName(charsetName);
+            if (null != cs) {
+                cacheCharset(cs);
+                return true;
+            }
+            return false;
+        } else {
+            Charset cs = forNameInternal(charsetName);
+            return (null != cs);
+        }
+
     }
 
     /**
@@ -598,7 +594,6 @@
      * @return true if this charset is a super set of the given charset,
      *         false if it's unknown or this charset is not a superset of
      *         the given charset.
-     * @since Android 1.0
      */
     public abstract boolean contains(Charset charset);
 
@@ -606,7 +601,6 @@
      * Gets a new instance of an encoder for this charset.
      * 
      * @return a new instance of an encoder for this charset.
-     * @since Android 1.0
      */
     public abstract CharsetEncoder newEncoder();
 
@@ -614,7 +608,6 @@
      * Gets a new instance of a decoder for this charset.
      * 
      * @return a new instance of a decoder for this charset.
-     * @since Android 1.0
      */
     public abstract CharsetDecoder newDecoder();
 
@@ -622,7 +615,6 @@
      * Gets the canonical name of this charset.
      * 
      * @return this charset's name in canonical form.
-     * @since Android 1.0
      */
     public final String name() {
         return this.canonicalName;
@@ -632,7 +624,6 @@
      * Gets the set of this charset's aliases.
      * 
      * @return an unmodifiable set of this charset's aliases.
-     * @since Android 1.0
      */
     public final Set<String> aliases() {
         return Collections.unmodifiableSet(this.aliasesSet);
@@ -641,12 +632,10 @@
     /**
      * Gets the name of this charset for the default locale.
      * 
-     * This is the default implementation of this method which always returns
-     * the canonical name of this charset. Subclasses overriding this Method
-     * may return a display name that was localized.
-     * 
+     * <p>The default implementation returns the canonical name of this charset.
+     * Subclasses may return a localized display name.
+     *
      * @return the name of this charset for the default locale.
-     * @since Android 1.0
      */
     public String displayName() {
         return this.canonicalName;
@@ -654,15 +643,13 @@
 
     /**
      * Gets the name of this charset for the specified locale.
-     * 
-     * This is the default implementation of this method which always returns
-     * the canonical name of this charset. Subclasses overriding this Method
-     * may return a display name that was localized.
-     * 
+     *
+     * <p>The default implementation returns the canonical name of this charset.
+     * Subclasses may return a localized display name.
+     *
      * @param l
      *            a certain locale
-     * @return the name of this charset for the specified locale.
-     * @since Android 1.0
+     * @return the name of this charset for the specified locale
      */
     public String displayName(Locale l) {
         return this.canonicalName;
@@ -674,7 +661,6 @@
      * 
      * @return true if the charset is known to be registered, otherwise returns
      *         false.
-     * @since Android 1.0
      */
     public final boolean isRegistered() {
         return !canonicalName.startsWith("x-") //$NON-NLS-1$
@@ -685,7 +671,6 @@
      * Returns true if this charset supports encoding, false otherwise.
      * 
      * @return true if this charset supports encoding, false otherwise.
-     * @since Android 1.0
      */
     public boolean canEncode() {
         return true;
@@ -697,52 +682,32 @@
      * <p>
      * The default action in case of encoding errors is
      * <code>CodingErrorAction.REPLACE</code>.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the character buffer containing the content to be encoded.
      * @return the result of the encoding.
-     * @since Android 1.0
      */
-    synchronized public final ByteBuffer encode(CharBuffer buffer) {
-        CharsetEncoder e = getCachedCharsetEncoder(canonicalName);
+    public final ByteBuffer encode(CharBuffer buffer) {
         try {
-            synchronized (e) {
-                return e.encode(buffer);
-            }
+            return this.newEncoder()
+                    .onMalformedInput(CodingErrorAction.REPLACE)
+                    .onUnmappableCharacter(CodingErrorAction.REPLACE).encode(
+                            buffer);
+
         } catch (CharacterCodingException ex) {
             throw new Error(ex.getMessage(), ex);
         }
     }
 
-    /*
-     * get cached CharsetEncoder by canonical name
-     */
-    private CharsetEncoder getCachedCharsetEncoder(String name) {
-        synchronized (cachedCharsetEncoderTable) {
-            CharsetEncoder e = cachedCharsetEncoderTable
-                    .get(name);
-            if (null == e) {
-                e = this.newEncoder();
-                e.onMalformedInput(CodingErrorAction.REPLACE);
-                e.onUnmappableCharacter(CodingErrorAction.REPLACE);
-                cachedCharsetEncoderTable.put(name, e);
-            }
-            return e;
-        }
-    }
-
     /**
      * Encodes a string and outputs to a byte buffer that is to be returned.
      * <p>
      * The default action in case of encoding errors is
      * <code>CodingErrorAction.REPLACE</code>.
-     * </p>
-     * 
+     *
      * @param s
      *            the string to be encoded.
      * @return the result of the encoding.
-     * @since Android 1.0
      */
     public final ByteBuffer encode(String s) {
         return encode(CharBuffer.wrap(s));
@@ -754,42 +719,25 @@
      * <p>
      * The default action in case of decoding errors is
      * <code>CodingErrorAction.REPLACE</code>.
-     * </p>
      * 
      * @param buffer
      *            the byte buffer containing the content to be decoded.
      * @return a character buffer containing the output of the decoding.
-     * @since Android 1.0
      */
     public final CharBuffer decode(ByteBuffer buffer) {
-        CharsetDecoder d = getCachedCharsetDecoder(canonicalName);
+
         try {
-            synchronized (d) {
-                return d.decode(buffer);
-            }
+            return this.newDecoder()
+                    .onMalformedInput(CodingErrorAction.REPLACE)
+                    .onUnmappableCharacter(CodingErrorAction.REPLACE).decode(
+                            buffer);
+
         } catch (CharacterCodingException ex) {
             throw new Error(ex.getMessage(), ex);
         }
     }
 
     /*
-     * get cached CharsetDecoder by canonical name
-     */
-    private CharsetDecoder getCachedCharsetDecoder(String name) {
-        synchronized (cachedCharsetDecoderTable) {
-            CharsetDecoder d = cachedCharsetDecoderTable
-                    .get(name);
-            if (null == d) {
-                d = this.newDecoder();
-                d.onMalformedInput(CodingErrorAction.REPLACE);
-                d.onUnmappableCharacter(CodingErrorAction.REPLACE);
-                cachedCharsetDecoderTable.put(name, d);
-            }
-            return d;
-        }
-    }
-
-    /*
      * -------------------------------------------------------------------
      * Methods implementing parent interface Comparable
      * -------------------------------------------------------------------
@@ -803,7 +751,6 @@
      *            the given object to be compared with.
      * @return a negative integer if less than the given object, a positive
      *         integer if larger than it, or 0 if equal to it.
-     * @since Android 1.0
      */
     public final int compareTo(Charset charset) {
         return this.canonicalName.compareToIgnoreCase(charset.canonicalName);
@@ -822,7 +769,6 @@
      * @param obj
      *            the given object to be compared with.
      * @return true if they have the same canonical name, otherwise false.
-     * @since Android 1.0
      */
     @Override
     public final boolean equals(Object obj) {
@@ -837,7 +783,6 @@
      * Gets the hash code of this charset.
      * 
      * @return the hash code of this charset.
-     * @since Android 1.0
      */
     @Override
     public final int hashCode() {
@@ -849,7 +794,6 @@
      * canonical name of the charset.
      * 
      * @return a string representation of this charset.
-     * @since Android 1.0
      */
     @Override
     public final String toString() {
@@ -860,7 +804,6 @@
      * Gets the system default charset from the virtual machine.
      * 
      * @return the default charset.
-     * @since Android 1.0
      */
     public static Charset defaultCharset() {
         Charset defaultCharset = null;
diff --git a/nio_char/src/main/java/java/nio/charset/CharsetDecoder.java b/nio_char/src/main/java/java/nio/charset/CharsetDecoder.java
index 38fb9b2..dc243cc 100644
--- a/nio_char/src/main/java/java/nio/charset/CharsetDecoder.java
+++ b/nio_char/src/main/java/java/nio/charset/CharsetDecoder.java
@@ -44,7 +44,6 @@
  * <li>invoking the {@link #flush(CharBuffer) flush} method to flush the
  * output.</li>
  * </ol>
- * </p>
  * <p>
  * The {@link #decode(ByteBuffer, CharBuffer, boolean) decode} method will
  * convert as many bytes as possible, and the process won't stop until the input
@@ -53,14 +52,12 @@
  * indicate the stop reason, and the invoker can identify the result and choose
  * further action, which includes filling the input buffer, flushing the output
  * buffer or recovering from an error and trying again.
- * </p>
  * <p>
  * There are two common decoding errors. One is named malformed and it is
  * returned when the input byte sequence is illegal for the current specific
  * charset, the other is named unmappable character and it is returned when a
  * problem occurs mapping a legal input byte sequence to its Unicode character
  * equivalent.
- * </p>
  * <p>
  * Both errors can be handled in three ways, the default one is to report the
  * error to the invoker by a {@link CoderResult CoderResult} instance, and the
@@ -72,7 +69,6 @@
  * {@link #onMalformedInput(CodingErrorAction) onMalformedInput} method and
  * {@link #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter}
  * method.
- * </p>
  * <p>
  * This is an abstract class and encapsulates many common operations of the
  * decoding process for all charsets. Decoders for a specific charset should
@@ -81,20 +77,14 @@
  * decoding. If a subclass maintains an internal state, it should override the
  * {@link #implFlush(CharBuffer) implFlush} method and the
  * {@link #implReset() implReset} method in addition.
- * </p>
  * <p>
  * This class is not thread-safe.
- * </p>
- * 
+ *
  * @see java.nio.charset.Charset
  * @see java.nio.charset.CharsetEncoder
- * @since Android 1.0
  */
 public abstract class CharsetDecoder {
-    /*
-     * --------------------------------------- Consts
-     * ---------------------------------------
-     */
+
     /*
      * internal status consts
      */
@@ -106,10 +96,6 @@
 
     private static final int FLUSH = 3;
 
-    /*
-     * --------------------------------------- Instance variables
-     * ---------------------------------------
-     */
     // average number of chars for one byte
     private float averChars;
 
@@ -131,10 +117,6 @@
     // the current status
     private int status;
 
-    /*
-     * --------------------------------------- Constructor
-     * ---------------------------------------
-     */
     /**
      * Constructs a new <code>CharsetDecoder</code> using the given
      * <code>Charset</code>, average number and maximum number of characters
@@ -152,7 +134,6 @@
      * @throws IllegalArgumentException
      *             if <code>averageCharsPerByte</code> or
      *             <code>maxCharsPerByte</code> is negative.
-     * @since Android 1.0
      */
     protected CharsetDecoder(Charset charset, float averageCharsPerByte,
             float maxCharsPerByte) {
@@ -173,17 +154,12 @@
         replace = "\ufffd"; //$NON-NLS-1$
     }
 
-    /*
-     * --------------------------------------- Methods
-     * ---------------------------------------
-     */
     /**
      * Gets the average number of characters created by this decoder for a
      * single input byte.
      * 
      * @return the average number of characters created by this decoder for a
      *         single input byte.
-     * @since Android 1.0
      */
     public final float averageCharsPerByte() {
         return averChars;
@@ -193,7 +169,6 @@
      * Gets the <code>Charset</code> which this decoder uses.
      * 
      * @return the <code>Charset</code> which this decoder uses.
-     * @since Android 1.0
      */
     public final Charset charset() {
         return cs;
@@ -205,12 +180,10 @@
      * This method decodes the remaining byte sequence of the given byte buffer
      * into a new character buffer. This method performs a complete decoding
      * operation, resets at first, then decodes, and flushes at last.
-     * </p>
      * <p>
      * This method should not be invoked while another {@code decode} operation
      * is ongoing.
-     * </p>
-     * 
+     *
      * @param in
      *            the input buffer.
      * @return a new <code>CharBuffer</code> containing the the characters
@@ -233,7 +206,6 @@
      *             sequence.
      * @throws CharacterCodingException
      *             if another exception happened during the decode operation.
-     * @since Android 1.0
      */
     public final CharBuffer decode(ByteBuffer in)
             throws CharacterCodingException {
@@ -303,7 +275,6 @@
      * <p>
      * The buffers' position will be changed with the reading and writing
      * operation, but their limits and marks will be kept intact.
-     * </p>
      * <p>
      * A <code>CoderResult</code> instance will be returned according to
      * following rules:
@@ -332,7 +303,6 @@
      * only if the unmappable character action is
      * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. </li>
      * </ul>
-     * </p>
      * <p>
      * The <code>endOfInput</code> parameter indicates that the invoker cannot
      * provide further input. This parameter is true if and only if the bytes in
@@ -341,13 +311,11 @@
      * then can't provide more input, while it may cause an error if the invoker
      * always sets true in several consecutive invocations. This would make the
      * remaining input to be treated as malformed input.
-     * </p>
      * <p>
      * This method invokes the
      * {@link #decodeLoop(ByteBuffer, CharBuffer) decodeLoop} method to
      * implement the basic decode logic for a specific charset.
-     * </p>
-     * 
+     *
      * @param in
      *            the input buffer.
      * @param out
@@ -363,7 +331,6 @@
      *             if the {@link #decodeLoop(ByteBuffer, CharBuffer) decodeLoop}
      *             method threw an <code>BufferUnderflowException</code> or
      *             <code>BufferOverflowException</code>.
-     * @since Android 1.0
      */
     public final CoderResult decode(ByteBuffer in, CharBuffer out,
             boolean endOfInput) {
@@ -397,7 +364,10 @@
                 status = endOfInput ? END : ONGOING;
                 if (endOfInput && remaining > 0) {
                     result = CoderResult.malformedForLength(remaining);
+                    // BEGIN android-added
+                    // needed to adjust for the changed call to position() below
                     in.position(in.position() + result.length());
+                    // END android-added
                 } else {
                     return result;
                 }
@@ -420,12 +390,14 @@
                 if (action != CodingErrorAction.IGNORE)
                     return result;
             }
+            // BEGIN android-changed
+            // the condition is removed in Harmony revision 518047. However,
+            // making the conditional statement unconditional leads to
+            // misbehavior when using REPLACE on malformedInput.
             if (!result.isMalformed()) {
-                // Note: the following condition is removed in Harmony revision 518047
-                // However, making the conditional statement unconditional
-                // leads to misbehavior when using REPLACE on malformedInput.
                 in.position(in.position() + result.length());
             }
+            // END android-changed
         }
     }
 
@@ -445,25 +417,21 @@
      * {@link #decode(ByteBuffer, CharBuffer, boolean) decode} method, and some
      * performance optimized implementation may handle the exception and
      * implement the error action itself.
-     * </p>
      * <p>
      * The buffers are scanned from their current positions, and their positions
      * will be modified accordingly, while their marks and limits will be
      * intact. At most {@link ByteBuffer#remaining() in.remaining()} characters
      * will be read, and {@link CharBuffer#remaining() out.remaining()} bytes
      * will be written.
-     * </p>
      * <p>
      * Note that some implementations may pre-scan the input buffer and return a
      * <code>CoderResult.UNDERFLOW</code> until it receives sufficient input.
-     * </p>
      * 
      * @param in
      *            the input buffer.
      * @param out
      *            the output buffer.
      * @return a <code>CoderResult</code> instance indicating the result.
-     * @since Android 1.0
      */
     protected abstract CoderResult decodeLoop(ByteBuffer in, CharBuffer out);
 
@@ -473,17 +441,14 @@
      * If implementing an auto-detecting charset, then this decoder returns the
      * detected charset from this method when it is available. The returned
      * charset will be the same for the rest of the decode operation.
-     * </p>
      * <p>
      * If insufficient bytes have been read to determine the charset, an
      * <code>IllegalStateException</code> will be thrown.
-     * </p>
      * <p>
      * The default implementation always throws
      * <code>UnsupportedOperationException</code>, so it should be overridden
      * by a subclass if needed.
-     * </p>
-     * 
+     *
      * @return the charset detected by this decoder, or null if it is not yet
      *         determined.
      * @throws UnsupportedOperationException
@@ -491,7 +456,6 @@
      * @throws IllegalStateException
      *             if insufficient bytes have been read to determine the
      *             charset.
-     * @since Android 1.0
      */
     public Charset detectedCharset() {
         throw new UnsupportedOperationException();
@@ -513,11 +477,10 @@
      * space. Otherwise this method will return
      * <code>CoderResult.UNDERFLOW</code>, which means one decoding process
      * has been completed successfully.
-     * </p>
      * <p>
      * During the flush, the output buffer's position will be changed
      * accordingly, while its mark and limit will be intact.
-     * </p>
+     *
      * @param out
      *            the given output buffer.
      * @return <code>CoderResult.UNDERFLOW</code> or
@@ -529,7 +492,6 @@
      *             calling {@link #decode(ByteBuffer, CharBuffer, boolean)
      *             decode(ByteBuffer, CharBuffer, boolean)} with true as value
      *             for the last boolean parameter.
-     * @since Android 1.0
      */
     public final CoderResult flush(CharBuffer out) {
         if (status != END && status != INIT) {
@@ -551,7 +513,6 @@
      *            the output buffer.
      * @return <code>CoderResult.UNDERFLOW</code> or
      *         <code>CoderResult.OVERFLOW</code>.
-     * @since Android 1.0
      */
     protected CoderResult implFlush(CharBuffer out) {
         return CoderResult.UNDERFLOW;
@@ -564,7 +525,6 @@
      * 
      * @param newAction
      *            the new action.
-     * @since Android 1.0
      */
     protected void implOnMalformedInput(CodingErrorAction newAction) {
         // default implementation is empty
@@ -577,7 +537,6 @@
      * 
      * @param newAction
      *            the new action.
-     * @since Android 1.0
      */
     protected void implOnUnmappableCharacter(CodingErrorAction newAction) {
         // default implementation is empty
@@ -589,7 +548,6 @@
      * 
      * @param newReplacement
      *            the new replacement string.
-     * @since Android 1.0
      */
     protected void implReplaceWith(String newReplacement) {
         // default implementation is empty
@@ -598,8 +556,6 @@
     /**
      * Reset this decoder's charset related state. The default implementation
      * does nothing; this method can be overridden if needed.
-     * 
-     * @since Android 1.0
      */
     protected void implReset() {
         // default implementation is empty
@@ -610,7 +566,6 @@
      * 
      * @return <code>true</code> if this decoder implements an auto-detecting
      *         charset.
-     * @since Android 1.0
      */
     public boolean isAutoDetecting() {
         return false;
@@ -625,24 +580,20 @@
      * charset has been detected in the input bytes and that the charset can be
      * retrieved by invoking the {@link #detectedCharset() detectedCharset}
      * method.
-     * </p>
      * <p>
      * Note that a decoder that implements an auto-detecting charset may still
      * succeed in decoding a portion of the given input even when it is unable
      * to detect the charset. For this reason users should be aware that a
      * <code>false</code> return value does not indicate that no decoding took
      * place.
-     * </p>
      * <p>
      * The default implementation always throws an
      * <code>UnsupportedOperationException</code>; it should be overridden by
      * a subclass if needed.
-     * </p>
      * 
      * @return <code>true</code> if this decoder has detected a charset.
      * @throws UnsupportedOperationException
      *             if this decoder doesn't implement an auto-detecting charset.
-     * @since Android 1.0
      */
     public boolean isCharsetDetected() {
         throw new UnsupportedOperationException();
@@ -654,7 +605,6 @@
      * 
      * @return this decoder's <code>CodingErrorAction</code> when malformed
      *         input occurred during the decoding process.
-     * @since Android 1.0
      */
     public CodingErrorAction malformedInputAction() {
         return malformAction;
@@ -666,7 +616,6 @@
      * 
      * @return the maximum number of characters which can be created by this
      *         decoder for one input byte, must be positive.
-     * @since Android 1.0
      */
     public final float maxCharsPerByte() {
         return maxChars;
@@ -684,7 +633,6 @@
      * @return this decoder.
      * @throws IllegalArgumentException
      *             if {@code newAction} is {@code null}.
-     * @since Android 1.0
      */
     public final CharsetDecoder onMalformedInput(CodingErrorAction newAction) {
         if (null == newAction) {
@@ -707,7 +655,6 @@
      * @return this decoder.
      * @throws IllegalArgumentException
      *             if {@code newAction} is {@code null}.
-     * @since Android 1.0
      */
     public final CharsetDecoder onUnmappableCharacter(
             CodingErrorAction newAction) {
@@ -723,7 +670,6 @@
      * Gets the replacement string, which is never null or empty.
      * 
      * @return the replacement string, cannot be null or empty.
-     * @since Android 1.0
      */
     public final String replacement() {
         return replace;
@@ -744,7 +690,6 @@
      * @throws IllegalArgumentException
      *             if the given replacement cannot satisfy the requirement
      *             mentioned above.
-     * @since Android 1.0
      */
     public final CharsetDecoder replaceWith(String newReplacement) {
         if (null == newReplacement || newReplacement.length() == 0) {
@@ -767,7 +712,6 @@
      * specific charset.
      * 
      * @return this decoder.
-     * @since Android 1.0
      */
     public final CharsetDecoder reset() {
         status = INIT;
@@ -781,7 +725,6 @@
      * 
      * @return this decoder's <code>CodingErrorAction</code> when an
      *         unmappable character error occurred during the decoding process.
-     * @since Android 1.0
      */
     public CodingErrorAction unmappableCharacterAction() {
         return unmapAction;
diff --git a/nio_char/src/main/java/java/nio/charset/CharsetEncoder.java b/nio_char/src/main/java/java/nio/charset/CharsetEncoder.java
index 24b8b3f..f24be92 100644
--- a/nio_char/src/main/java/java/nio/charset/CharsetEncoder.java
+++ b/nio_char/src/main/java/java/nio/charset/CharsetEncoder.java
@@ -44,7 +44,6 @@
  * <li>invoking the {@link #flush(ByteBuffer) flush} method to flush the
  * output.</li>
  * </ol>
- * </p>
  * <p>
  * The {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method will
  * convert as many characters as possible, and the process won't stop until the
@@ -53,13 +52,11 @@
  * returned to indicate the stop reason, and the invoker can identify the result
  * and choose further action, which includes filling the input buffer, flushing
  * the output buffer or recovering from an error and trying again.
- * </p>
  * <p>
  * There are two common encoding errors. One is named malformed and it is
  * returned when the input content is an illegal 16-bit Unicode character
  * sequence, the other is named unmappable character and occurs when there is a
  * problem mapping the input to a valid byte sequence in the specified charset.
- * </p>
  * <p>
  * Both errors can be handled in three ways, the default one is to report the
  * error to the invoker by a {@link CoderResult CoderResult} instance, and the
@@ -72,7 +69,6 @@
  * the {@link #onMalformedInput(CodingErrorAction) onMalformedInput} method and
  * the {@link #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter}
  * method.
- * </p>
  * <p>
  * This class is abstract and encapsulates many common operations of the
  * encoding process for all charsets. Encoders for a specific charset should
@@ -81,20 +77,14 @@
  * encoding. If a subclass maintains an internal state, it should override the
  * {@link #implFlush(ByteBuffer) implFlush} method and the
  * {@link #implReset() implReset} method in addition.
- * </p>
  * <p>
  * This class is not thread-safe.
- * </p>
- * 
+ *
  * @see java.nio.charset.Charset
  * @see java.nio.charset.CharsetDecoder
- * @since Android 1.0
  */
 public abstract class CharsetEncoder {
-    /*
-     * --------------------------------------- Consts
-     * ---------------------------------------
-     */
+
     /*
      * internal status consts
      */
@@ -106,10 +96,6 @@
 
     private static final int FLUSH = 3;
 
-    /*
-     * --------------------------------------- Instance variables
-     * ---------------------------------------
-     */
     // the Charset which creates this encoder
     private Charset cs;
 
@@ -135,11 +121,6 @@
     // checking
     private CharsetDecoder decoder;
 
-    /*
-     * --------------------------------------- Constructors
-     * ---------------------------------------
-     */
-
     /**
      * Constructs a new <code>CharsetEncoder</code> using the given
      * <code>Charset</code>, average number and maximum number of bytes
@@ -156,7 +137,6 @@
      * @throws IllegalArgumentException
      *             if <code>maxBytesPerChar</code> or
      *             <code>averageBytesPerChar</code> is negative.
-     * @since Android 1.0
      */
     protected CharsetEncoder(Charset cs, float averageBytesPerChar,
             float maxBytesPerChar) {
@@ -184,7 +164,6 @@
      *            {@link #isLegalReplacement(byte[]) isLegalReplacement}.
      * @throws IllegalArgumentException
      *             if any parameters are invalid.
-     * @since Android 1.0
      */
     protected CharsetEncoder(Charset cs, float averageBytesPerChar,
             float maxBytesPerChar, byte[] replacement) {
@@ -205,17 +184,12 @@
         replaceWith(replacement);
     }
 
-    /*
-     * --------------------------------------- Methods
-     * ---------------------------------------
-     */
     /**
      * Gets the average number of bytes created by this encoder for a single
      * input character.
      * 
      * @return the average number of bytes created by this encoder for a single
      *         input character.
-     * @since Android 1.0
      */
     public final float averageBytesPerChar() {
         return averBytes;
@@ -227,18 +201,15 @@
      * Note that this method can change the internal status of this encoder, so
      * it should not be called when another encoding process is ongoing,
      * otherwise it will throw an <code>IllegalStateException</code>.
-     * </p>
      * <p>
      * This method can be overridden for performance improvement.
-     * </p>
-     * 
+     *
      * @param c
      *            the given encoder.
      * @return true if given character can be encoded by this encoder.
      * @throws IllegalStateException
      *             if another encode process is ongoing so that the current
      *             internal status is neither RESET or FLUSH.
-     * @since Android 1.0
      */
     public boolean canEncode(char c) {
         return implCanEncode(CharBuffer.wrap(new char[] { c }));
@@ -285,7 +256,6 @@
      *         this encoder.
      * @throws IllegalStateException
      *             if current internal status is neither RESET or FLUSH.
-     * @since Android 1.0
      */
     public boolean canEncode(CharSequence sequence) {
         CharBuffer cb;
@@ -301,7 +271,6 @@
      * Gets the <code>Charset</code> which this encoder uses.
      * 
      * @return the <code>Charset</code> which this encoder uses.
-     * @since Android 1.0
      */
     public final Charset charset() {
         return cs;
@@ -313,11 +282,9 @@
      * This method encodes the remaining character sequence of the given
      * character buffer into a new byte buffer. This method performs a complete
      * encoding operation, resets at first, then encodes, and flushes at last.
-     * </p>
      * <p>
      * This method should not be invoked if another encode operation is ongoing.
-     * </p>
-     * 
+     *
      * @param in
      *            the input buffer.
      * @return a new <code>ByteBuffer</code> containing the bytes produced by
@@ -339,7 +306,6 @@
      *             byte sequence.
      * @throws CharacterCodingException
      *             if other exception happened during the encode operation.
-     * @since Android 1.0
      */
     public final ByteBuffer encode(CharBuffer in)
             throws CharacterCodingException {
@@ -352,31 +318,34 @@
         CoderResult result = null;
         while (true) {
             result = encode(in, output, false);
-            checkCoderResult(result);
-            if (result.isUnderflow()) {
+            if (result==CoderResult.UNDERFLOW) {
                 break;
-            } else if (result.isOverflow()) {
+            } else if (result==CoderResult.OVERFLOW) {
                 output = allocateMore(output);
+                continue;
             }
+            checkCoderResult(result);
         }
         result = encode(in, output, true);
         checkCoderResult(result);
 
         while (true) {
             result = flush(output);
-            checkCoderResult(result);
-            if (result.isOverflow()) {
-                output = allocateMore(output);
-            } else {
+            if (result==CoderResult.UNDERFLOW) {
+                output.flip();
                 break;
+            } else if (result==CoderResult.OVERFLOW) {
+                output = allocateMore(output);
+                continue;
             }
-        }
-
-        output.flip();
-        if (result.isMalformed()) {
-            throw new MalformedInputException(result.length());
-        } else if (result.isUnmappable()) {
-            throw new UnmappableCharacterException(result.length());
+            checkCoderResult(result);
+            output.flip();
+            if (result.isMalformed()) {
+                throw new MalformedInputException(result.length());
+            } else if (result.isUnmappable()) {
+                throw new UnmappableCharacterException(result.length());
+            }
+            break;
         }
         status = FLUSH;
         return output;
@@ -387,10 +356,9 @@
      */
     private void checkCoderResult(CoderResult result)
             throws CharacterCodingException {
-        if (result.isMalformed() && malformAction == CodingErrorAction.REPORT) {
+        if (malformAction == CodingErrorAction.REPORT && result.isMalformed() ) {
             throw new MalformedInputException(result.length());
-        } else if (result.isUnmappable()
-                && unmapAction == CodingErrorAction.REPORT) {
+        } else if (unmapAction == CodingErrorAction.REPORT && result.isUnmappable()) {
             throw new UnmappableCharacterException(result.length());
         }
     }
@@ -413,7 +381,6 @@
      * <p>
      * The buffers' position will be changed with the reading and writing
      * operation, but their limits and marks will be kept intact.
-     * </p>
      * <p>
      * A <code>CoderResult</code> instance will be returned according to
      * following rules:
@@ -440,7 +407,6 @@
      * This kind of result can be returned only on
      * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.</li>
      * </ul>
-     * </p>
      * <p>
      * The <code>endOfInput</code> parameter indicates if the invoker can
      * provider further input. This parameter is true if and only if the
@@ -450,13 +416,11 @@
      * error if the invoker always sets true in several consecutive invocations.
      * This would make the remaining input to be treated as malformed input.
      * input.
-     * </p>
      * <p>
      * This method invokes the
      * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method to
      * implement the basic encode logic for a specific charset.
-     * </p>
-     * 
+     *
      * @param in
      *            the input buffer.
      * @param out
@@ -471,7 +435,6 @@
      *             If the {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop}
      *             method threw an <code>BufferUnderflowException</code> or
      *             <code>BufferUnderflowException</code>.
-     * @since Android 1.0
      */
     public final CoderResult encode(CharBuffer in, ByteBuffer out,
             boolean endOfInput) {
@@ -488,16 +451,19 @@
             } catch (BufferUnderflowException e) {
                 throw new CoderMalfunctionError(e);
             }
-            if (result.isUnderflow()) {
-                int remaining = in.remaining();
+            if (result==CoderResult.UNDERFLOW) {
                 status = endOfInput ? END : ONGOING;
-                if (endOfInput && remaining > 0) {
-                    result = CoderResult.malformedForLength(remaining);
+                if (endOfInput) {
+                    int remaining = in.remaining();
+                    if (remaining > 0) {
+                        result = CoderResult.malformedForLength(remaining);
+                    } else {
+                        return result;
+                    }
                 } else {
                     return result;
                 }
-            }
-            if (result.isOverflow()) {
+            } else if (result==CoderResult.OVERFLOW) {
                 status = endOfInput ? END : ONGOING;
                 return result;
             }
@@ -537,13 +503,13 @@
      * {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method, and some
      * performance optimized implementation may handle the exception and
      * implement the error action itself.
-     * </p><p>
+     * <p>
      * The buffers are scanned from their current positions, and their positions
      * will be modified accordingly, while their marks and limits will be
      * intact. At most {@link CharBuffer#remaining() in.remaining()} characters
      * will be read, and {@link ByteBuffer#remaining() out.remaining()} bytes
      * will be written.
-     * </p><p>
+     * <p>
      * Note that some implementations may pre-scan the input buffer and return
      * <code>CoderResult.UNDERFLOW</code> until it receives sufficient input.
      * <p>
@@ -552,7 +518,6 @@
      * @param out
      *            the output buffer.
      * @return a <code>CoderResult</code> instance indicating the result.
-     * @since Android 1.0
      */
     protected abstract CoderResult encodeLoop(CharBuffer in, ByteBuffer out);
 
@@ -563,7 +528,6 @@
      * encoders may need to write some bytes to the output buffer when they have
      * read all input characters, subclasses can overridden
      * {@link #implFlush(ByteBuffer) implFlush} to perform writing action.
-     * </p>
      * <p>
      * The maximum number of written bytes won't larger than
      * {@link ByteBuffer#remaining() out.remaining()}. If some encoder wants to
@@ -572,11 +536,9 @@
      * must be called again with a byte buffer that has free space. Otherwise
      * this method will return <code>CoderResult.UNDERFLOW</code>, which
      * means one encoding process has been completed successfully.
-     * </p>
      * <p>
      * During the flush, the output buffer's position will be changed
      * accordingly, while its mark and limit will be intact.
-     * </p>
      * 
      * @param out
      *            the given output buffer.
@@ -589,7 +551,6 @@
      *             calling {@link #encode(CharBuffer, ByteBuffer, boolean) 
      *             encode(CharBuffer, ByteBuffer, boolean)} with {@code true}
      *             for the last boolean parameter.
-     * @since Android 1.0
      */
     public final CoderResult flush(ByteBuffer out) {
         if (status != END && status != INIT) {
@@ -611,7 +572,6 @@
      *            the output buffer.
      * @return <code>CoderResult.UNDERFLOW</code> or
      *         <code>CoderResult.OVERFLOW</code>.
-     * @since Android 1.0
      */
     protected CoderResult implFlush(ByteBuffer out) {
         return CoderResult.UNDERFLOW;
@@ -624,7 +584,6 @@
      * 
      * @param newAction
      *            the new action.
-     * @since Android 1.0
      */
     protected void implOnMalformedInput(CodingErrorAction newAction) {
         // default implementation is empty
@@ -637,7 +596,6 @@
      * 
      * @param newAction
      *            the new action.
-     * @since Android 1.0
      */
     protected void implOnUnmappableCharacter(CodingErrorAction newAction) {
         // default implementation is empty
@@ -649,7 +607,6 @@
      * 
      * @param newReplacement
      *            the new replacement string.
-     * @since Android 1.0
      */
     protected void implReplaceWith(byte[] newReplacement) {
         // default implementation is empty
@@ -658,8 +615,6 @@
     /**
      * Resets this encoder's charset related state. The default implementation
      * does nothing; this method can be overridden if needed.
-     * 
-     * @since Android 1.0
      */
     protected void implReset() {
         // default implementation is empty
@@ -678,7 +633,6 @@
      *            the given byte array to be checked.
      * @return true if the the given argument is legal as this encoder's
      *         replacement byte array.
-     * @since Android 1.0
      */
     public boolean isLegalReplacement(byte[] repl) {
         if (decoder == null) {
@@ -704,7 +658,6 @@
      * 
      * @return this encoder's <code>CodingErrorAction</code> when a malformed
      *         input error occurred during the encoding process.
-     * @since Android 1.0
      */
     public CodingErrorAction malformedInputAction() {
         return malformAction;
@@ -716,7 +669,6 @@
      * 
      * @return the maximum number of bytes which can be created by this encoder
      *         for one input character, must be positive.
-     * @since Android 1.0
      */
     public final float maxBytesPerChar() {
         return maxBytes;
@@ -734,7 +686,6 @@
      * @return this encoder.
      * @throws IllegalArgumentException
      *             if the given newAction is null.
-     * @since Android 1.0
      */
     public final CharsetEncoder onMalformedInput(CodingErrorAction newAction) {
         if (null == newAction) {
@@ -758,7 +709,6 @@
      * @return this encoder.
      * @throws IllegalArgumentException
      *             if the given newAction is null.
-     * @since Android 1.0
      */
     public final CharsetEncoder onUnmappableCharacter(
             CodingErrorAction newAction) {
@@ -775,7 +725,6 @@
      * Gets the replacement byte array, which is never null or empty.
      * 
      * @return the replacement byte array, cannot be null or empty.
-     * @since Android 1.0
      */
     public final byte[] replacement() {
         return replace;
@@ -798,7 +747,6 @@
      * @throws IllegalArgumentException
      *             if the given replacement cannot satisfy the requirement
      *             mentioned above.
-     * @since Android 1.0
      */
     public final CharsetEncoder replaceWith(byte[] replacement) {
         if (null == replacement || 0 == replacement.length
@@ -818,7 +766,6 @@
      * specific charset.
      * 
      * @return this encoder.
-     * @since Android 1.0
      */
     public final CharsetEncoder reset() {
         status = INIT;
@@ -832,7 +779,6 @@
      * 
      * @return this encoder's <code>CodingErrorAction</code> when unmappable
      *         character occurred during encoding process.
-     * @since Android 1.0
      */
     public CodingErrorAction unmappableCharacterAction() {
         return unmapAction;
diff --git a/nio_char/src/main/java/java/nio/charset/CoderMalfunctionError.java b/nio_char/src/main/java/java/nio/charset/CoderMalfunctionError.java
index 2fc2ae8..b7262a1 100644
--- a/nio_char/src/main/java/java/nio/charset/CoderMalfunctionError.java
+++ b/nio_char/src/main/java/java/nio/charset/CoderMalfunctionError.java
@@ -20,8 +20,6 @@
 /**
  * A {@code CoderMalfunctionError} is thrown when the encoder/decoder is
  * malfunctioning.
- * 
- * @since Android 1.0
  */
 public class CoderMalfunctionError extends Error {
 
@@ -36,7 +34,6 @@
      * 
      * @param ex
      *            the original exception thrown by the encoder/decoder.
-     * @since Android 1.0
      */
     public CoderMalfunctionError(Exception ex) {
         super(ex);
diff --git a/nio_char/src/main/java/java/nio/charset/CoderResult.java b/nio_char/src/main/java/java/nio/charset/CoderResult.java
index 9d47c9f..47df0dd 100644
--- a/nio_char/src/main/java/java/nio/charset/CoderResult.java
+++ b/nio_char/src/main/java/java/nio/charset/CoderResult.java
@@ -40,8 +40,6 @@
  * result by calling <code>CoderResult.unmappableForLength(int)</code> with
  * the input sequence size indicating the identity of the unmappable character.
  * </ol>
- * 
- * @since Android 1.0
  */
 public class CoderResult {
 
@@ -60,8 +58,6 @@
     /**
      * Result object indicating that there is insufficient data in the
      * encoding/decoding buffer or that additional data is required.
-     * 
-     * @since Android 1.0
      */
     public static final CoderResult UNDERFLOW = new CoderResult(TYPE_UNDERFLOW,
             0);
@@ -69,8 +65,6 @@
     /**
      * Result object used to indicate that the output buffer does not have
      * enough space available to store the result of the encoding/decoding.
-     * 
-     * @since Android 1.0
      */
     public static final CoderResult OVERFLOW = new CoderResult(TYPE_OVERFLOW, 0);
 
@@ -116,7 +110,6 @@
      *         error.
      * @throws IllegalArgumentException
      *             if <code>length</code> is non-positive.
-     * @since Android 1.0
      */
     public static synchronized CoderResult malformedForLength(int length)
             throws IllegalArgumentException {
@@ -147,7 +140,6 @@
      *         character error.
      * @throws IllegalArgumentException
      *             if <code>length</code> is non-positive.
-     * @since Android 1.0
      */
     public static synchronized CoderResult unmappableForLength(int length)
             throws IllegalArgumentException {
@@ -171,7 +163,6 @@
      * Returns true if this result is an underflow condition.
      * 
      * @return true if an underflow, otherwise false.
-     * @since Android 1.0
      */
     public boolean isUnderflow() {
         return this.type == TYPE_UNDERFLOW;
@@ -181,9 +172,8 @@
      * Returns true if this result represents a malformed-input error or an
      * unmappable-character error.
      * 
-     * @return true if this is a malformed-input error or an 
+     * @return true if this is a malformed-input error or an
      *         unmappable-character error, otherwise false.
-     * @since Android 1.0
      */
     public boolean isError() {
         return this.type == TYPE_MALFORMED_INPUT
@@ -194,7 +184,6 @@
      * Returns true if this result represents a malformed-input error.
      * 
      * @return true if this is a malformed-input error, otherwise false.
-     * @since Android 1.0
      */
     public boolean isMalformed() {
         return this.type == TYPE_MALFORMED_INPUT;
@@ -204,7 +193,6 @@
      * Returns true if this result is an overflow condition.
      * 
      * @return true if this is an overflow, otherwise false.
-     * @since Android 1.0
      */
     public boolean isOverflow() {
         return this.type == TYPE_OVERFLOW;
@@ -214,7 +202,6 @@
      * Returns true if this result represents an unmappable-character error.
      * 
      * @return true if this is an unmappable-character error, otherwise false.
-     * @since Android 1.0
      */
     public boolean isUnmappable() {
         return this.type == TYPE_UNMAPPABLE_CHAR;
@@ -227,7 +214,6 @@
      * @return the length, as an integer, of this object's erroneous input.
      * @throws UnsupportedOperationException
      *             if this result is an overflow or underflow.
-     * @since Android 1.0
      */
     public int length() throws UnsupportedOperationException {
         if (this.type == TYPE_MALFORMED_INPUT
@@ -253,7 +239,6 @@
      *             in case this is a malformed-input error.
      * @throws CharacterCodingException
      *             the default exception.
-     * @since Android 1.0
      */
     public void throwException() throws BufferUnderflowException,
             BufferOverflowException, UnmappableCharacterException,
@@ -272,18 +257,12 @@
         }
     }
 
-    /*
-     * -------------------------------------------------------------------
-     * Methods overriding parent class Object
-     * -------------------------------------------------------------------
-     */
-
     /**
      * Returns a text description of this result.
      * 
      * @return a text description of this result.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         String dsc = null;
         switch (this.type) {
diff --git a/nio_char/src/main/java/java/nio/charset/CodingErrorAction.java b/nio_char/src/main/java/java/nio/charset/CodingErrorAction.java
index d949c81..030623b 100644
--- a/nio_char/src/main/java/java/nio/charset/CodingErrorAction.java
+++ b/nio_char/src/main/java/java/nio/charset/CodingErrorAction.java
@@ -20,15 +20,11 @@
  * Used to indicate what kind of actions to take in case of encoding/decoding
  * errors. Currently three actions are defined: {@code IGNORE}, {@code REPLACE}
  * and {@code REPORT}.
- * 
- * @since Android 1.0
  */
 public class CodingErrorAction {
 
     /**
      * Denotes the action to ignore any errors.
-     * 
-     * @since Android 1.0
      */
     public static final CodingErrorAction IGNORE = new CodingErrorAction(
             "IGNORE"); //$NON-NLS-1$
@@ -36,8 +32,6 @@
     /**
      * Denotes the action to fill in the output with a replacement character
      * when malformed input or an unmappable character is encountered.
-     * 
-     * @since Android 1.0
      */
     public static final CodingErrorAction REPLACE = new CodingErrorAction(
             "REPLACE"); //$NON-NLS-1$
@@ -46,8 +40,6 @@
      * Denotes the action to report the encountered error in an appropriate
      * manner, for example to throw an exception or return an informative
      * result.
-     * 
-     * @since Android 1.0
      */
     public static final CodingErrorAction REPORT = new CodingErrorAction(
             "REPORT"); //$NON-NLS-1$
@@ -66,8 +58,8 @@
      * Returns a text description of this action indication.
      * 
      * @return a text description of this action indication.
-     * @since Android 1.0
      */
+    @Override
     public String toString() {
         return "Action: " + this.action; //$NON-NLS-1$
     }
diff --git a/nio_char/src/main/java/java/nio/charset/IllegalCharsetNameException.java b/nio_char/src/main/java/java/nio/charset/IllegalCharsetNameException.java
index 36ff3ad..fad9fa6 100644
--- a/nio_char/src/main/java/java/nio/charset/IllegalCharsetNameException.java
+++ b/nio_char/src/main/java/java/nio/charset/IllegalCharsetNameException.java
@@ -22,8 +22,6 @@
 /**
  * An {@code IllegalCharsetNameException} is thrown when an illegal charset name
  * is encountered.
- * 
- * @since Android 1.0
  */
 public class IllegalCharsetNameException extends IllegalArgumentException {
 
@@ -42,7 +40,6 @@
      * 
      * @param charset
      *            the encountered illegal charset name.
-     * @since Android 1.0
      */
     public IllegalCharsetNameException(String charset) {
         // niochar.0F=The illegal charset name is "{0}".
@@ -54,7 +51,6 @@
      * Gets the encountered illegal charset name.
      * 
      * @return the encountered illegal charset name.
-     * @since Android 1.0
      */
     public String getCharsetName() {
         return this.charsetName;
diff --git a/nio_char/src/main/java/java/nio/charset/MalformedInputException.java b/nio_char/src/main/java/java/nio/charset/MalformedInputException.java
index 9fa0aa2..0a93728 100644
--- a/nio_char/src/main/java/java/nio/charset/MalformedInputException.java
+++ b/nio_char/src/main/java/java/nio/charset/MalformedInputException.java
@@ -22,8 +22,6 @@
 /**
  * A {@code MalformedInputException} is thrown when a malformed input is
  * encountered, for example if a byte sequence is illegal for the given charset.
- * 
- * @since Android 1.0
  */
 public class MalformedInputException extends CharacterCodingException {
 
@@ -41,7 +39,6 @@
      * 
      * @param length
      *            the length of the malformed input.
-     * @since Android 1.0
      */
     public MalformedInputException(int length) {
         this.inputLength = length;
@@ -51,7 +48,6 @@
      * Gets the length of the malformed input.
      * 
      * @return the length of the malformed input.
-     * @since Android 1.0
      */
     public int getInputLength() {
         return this.inputLength;
@@ -61,8 +57,8 @@
      * Gets a message describing this exception.
      * 
      * @return a message describing this exception.
-     * @since Android 1.0
      */
+    @Override
     public String getMessage() {
         // niochar.05=Malformed input length is {0}.
         return Messages.getString("niochar.05", this.inputLength); //$NON-NLS-1$
diff --git a/nio_char/src/main/java/java/nio/charset/UnmappableCharacterException.java b/nio_char/src/main/java/java/nio/charset/UnmappableCharacterException.java
index 7cc56e2..db23a6f 100644
--- a/nio_char/src/main/java/java/nio/charset/UnmappableCharacterException.java
+++ b/nio_char/src/main/java/java/nio/charset/UnmappableCharacterException.java
@@ -22,8 +22,6 @@
 /**
  * An {@code UnmappableCharacterException} is thrown when an unmappable
  * character for the given charset is encountered.
- * 
- * @since Android 1.0
  */
 public class UnmappableCharacterException extends CharacterCodingException {
 
@@ -41,7 +39,6 @@
      * 
      * @param length
      *            the length of the unmappable character.
-     * @since Android 1.0
      */
     public UnmappableCharacterException(int length) {
         this.inputLength = length;
@@ -51,7 +48,6 @@
      * Gets the length of the unmappable character.
      * 
      * @return the length of the unmappable character.
-     * @since Android 1.0
      */
     public int getInputLength() {
         return this.inputLength;
@@ -61,8 +57,8 @@
      * Gets a message describing this exception.
      * 
      * @return a message describing this exception.
-     * @since Android 1.0
      */
+    @Override
     public String getMessage() {
         // niochar.0A=The unmappable character length is {0}.
         return Messages.getString("niochar.0A", this.inputLength); //$NON-NLS-1$
diff --git a/nio_char/src/main/java/java/nio/charset/UnsupportedCharsetException.java b/nio_char/src/main/java/java/nio/charset/UnsupportedCharsetException.java
index 45dbf3d..b5985b4 100644
--- a/nio_char/src/main/java/java/nio/charset/UnsupportedCharsetException.java
+++ b/nio_char/src/main/java/java/nio/charset/UnsupportedCharsetException.java
@@ -22,8 +22,6 @@
 /**
  * An {@code UnsupportedCharsetException} is thrown when an unsupported charset
  * name is encountered.
- * 
- * @since Android 1.0
  */
 public class UnsupportedCharsetException extends IllegalArgumentException {
 
@@ -37,11 +35,11 @@
     private String charsetName;
 
     /**
-     * Constructs a new {@code UnsupportedCharsetException} with the supplied charset name.
+     * Constructs a new {@code UnsupportedCharsetException} with the supplied
+     * charset name.
      * 
      * @param charset
      *            the encountered unsupported charset name.
-     * @since Android 1.0
      */
     public UnsupportedCharsetException(String charset) {
         // niochar.04=The unsupported charset name is "{0}".
@@ -53,7 +51,6 @@
      * Gets the encountered unsupported charset name.
      * 
      * @return the encountered unsupported charset name.
-     * @since Android 1.0
      */
     public String getCharsetName() {
         return this.charsetName;
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
index 5908b14..70c6c8f 100644
--- a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
@@ -21,6 +21,7 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestLevel;
 
+import java.io.IOException;
 import java.nio.BufferOverflowException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
@@ -32,6 +33,7 @@
 import java.nio.charset.CoderResult;
 import java.nio.charset.CodingErrorAction;
 import java.nio.charset.MalformedInputException;
+import java.util.Arrays;
 
 import junit.framework.TestCase;
 @TestTargetClass(CharsetDecoder.class)
@@ -271,4 +273,51 @@
             return CoderResult.UNDERFLOW;
         }
     }
+
+
+    public void testInvalidDecoding() throws IOException {
+
+        byte[][] invalidSequences = new byte[][] {
+                // overlong NULL
+                { (byte) 0xC0, (byte) 0x80 },
+                // overlong ascii 'A'
+                { (byte) 0xC0, (byte) 0xC1 },
+                // overlong "/../"
+                { (byte) 0x2F, (byte) 0xC0, (byte) 0xAE, (byte) 0x2E, (byte) 0x2F },
+                // Invalid encoding 2r11111000 (sequence too long)
+                { (byte) 0xF8 },
+                // Invalid encoding 2r10000000 (sequence too short)
+                { (byte) 0x80 }
+        };
+
+        CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
+        decoder.onMalformedInput(CodingErrorAction.REPORT);
+
+        /*
+         * When bytebuffer has a backing array...
+         */
+        for (byte[] bytes : invalidSequences) {
+            try {
+                decoder.decode(ByteBuffer.wrap(bytes));
+                fail("No exception thrown on " + Arrays.toString(bytes));
+            } catch (MalformedInputException e) {
+                // expected
+            }
+        }
+
+        /*
+         * When bytebuffer has _not_ got a backing array...
+         */
+        for (byte[] bytes : invalidSequences) {
+            try {
+                ByteBuffer bb = ByteBuffer.allocateDirect(8);
+                bb.put(bytes).flip();
+                decoder.decode(bb);
+                fail("No exception thrown on " + Arrays.toString(bytes));
+            } catch (MalformedInputException e) {
+                // expected
+            }
+        }
+    }
+
 }
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
index 1f33a05..c3e2256 100644
--- a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
@@ -21,6 +21,7 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestLevel;
 
+import java.io.IOException;
 import java.nio.BufferOverflowException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
@@ -203,4 +204,22 @@
         assertEquals(4, out.remaining());
         assertTrue(result.isMalformed());
     }
+
+    /**
+     * @tests {@link java.nio.charset.Charset#encode(java.nio.CharBuffer)
+     */
+    public void testUtf8Encoding() throws IOException {
+        byte[] orig = new byte[] { (byte) 0xed, (byte) 0xa0,
+                (byte) 0x80 };
+        String s = new String(orig, "UTF-8");
+        assertEquals(1, s.length());
+        assertEquals(55296, s.charAt(0));
+        Charset.forName("UTF-8").encode(CharBuffer.wrap(s));
+//        ByteBuffer buf = <result>
+//        for (byte o : orig) {
+//            byte b = 0;
+//            buf.get(b);
+//            assertEquals(o, b);
+//        }
+    }
 }
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java
index f8b0b7e..e7c5f5c 100644
--- a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java
@@ -16,24 +16,18 @@
 
 package org.apache.harmony.nio_char.tests.java.nio.charset;
 
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import junit.framework.TestCase;
+import tests.util.TestEnvironment;
 
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
 import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
 import java.nio.charset.IllegalCharsetNameException;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Properties;
 import java.util.Set;
-
-import junit.framework.TestCase;
 @TestTargetClass(Charset.class)
 public class CharsetTest extends TestCase {
 
@@ -47,6 +41,8 @@
      * JUnit set-up method
      */
     public void setUp() {
+        TestEnvironment.reset();
+
         // Populate the known charset vars
         Set names = Charset.availableCharsets().keySet();
         for (Iterator nameItr = names.iterator(); nameItr.hasNext();) {
@@ -181,153 +177,4 @@
         Charset cs4 = Charset.forName("US-ASCII");
         assertSame(cs3, cs4);
     }
-    
-    /*
-     * test cached decoder
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "This test is quite useless for the rest it does, though.",
-        method = "Charset",
-        args = {java.lang.String.class, java.lang.String[].class}
-    )
-    public void test_DecodeLjava_nio_ByteBuffer() throws Exception{
-            MockCharsetForDecoder cs1 = new MockCharsetForDecoder("CachedCharset",null);
-            MockCharsetForDecoder cs2 = new MockCharsetForDecoder("CachedCharset",null);
-            ByteBuffer in = ByteBuffer.wrap(new byte[]{0x00});
-            cs1.decode(in);
-            in.flip();
-            cs2.decode(in);
-            in.flip();
-    }
-    /*
-     * Mock Charset for cached decoder test
-     */
-    static class MockCharsetForDecoder extends Charset{
-
-            public MockCharsetForDecoder(String canonicalName, String[] aliases){
-                    super(canonicalName, aliases);
-            }
-
-            public boolean contains(Charset charset) {
-                    return false;
-            }
-
-            public CharsetEncoder newEncoder() {
-                    return null;
-            }
-
-            public CharsetDecoder newDecoder() {
-                    return new MockCachedDecoder(this);
-            }
-
-
-    }
-    /*
-     * Mock decoder. Only one caller is permitted.
-     */
-    static class MockCachedDecoder extends CharsetDecoder {
-            static MockCachedDecoder caller = null;
-
-            public MockCachedDecoder(Charset cs) {
-                    super(cs, 1, 10);
-            }
-
-            /*
-             * Only one caller is permitted.
-             * If there's another caller, throw RuntimeException.
-             */
-            protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
-                    if(null == caller){
-                            caller = this;
-                    }else{
-                            if(caller != this){
-                                // Another instance
-                                fail("should use the same instance");
-                            }
-                    }
-                    return CoderResult.UNDERFLOW;
-            }
-    }
-
-    /*
-     * test cached encoder
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Functional test.",
-        method = "encode",
-        args = {java.nio.CharBuffer.class}
-    )
-    public void test_EncodeLjava_nio_CharBuffer() throws Exception {
-            MockCharsetForEncoder cs1 = new MockCharsetForEncoder("CachedCharset", null);
-            MockCharsetForEncoder cs2 = new MockCharsetForEncoder("CachedCharset", null);
-            CharBuffer in = CharBuffer.wrap("A");
-            cs1.encode(in);
-            in.flip();
-            cs2.encode(in);
-    }
-
-    /*
-     * Mock Charset for cached encoder test
-     */
-    static class MockCharsetForEncoder extends Charset {
-
-            public MockCharsetForEncoder(String canonicalName, String[] aliases) {
-                    super(canonicalName, aliases);
-            }
-
-            public boolean contains(Charset charset) {
-                    return false;
-            }
-
-            public CharsetDecoder newDecoder() {
-                    return new MockDecoderForEncoder(this);
-            }
-
-            public CharsetEncoder newEncoder() {
-                    return new MockCachedEncoder(this);
-            }
-    }
-
-    /*
-     * Mock encoder. Only one caller is permitted.
-     */
-    static class MockCachedEncoder extends CharsetEncoder {
-            static MockCachedEncoder caller = null;
-
-            public MockCachedEncoder(Charset cs) {
-                    super(cs, 1, 10);
-            }
-
-            /*
-             * Only one caller is permitted.
-             */
-            protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
-                    if (null == caller) {
-                            caller = this;
-                    } else {
-                            if (caller != this) {
-                                    // Another instance
-                                    fail("should use the same instance");
-                            }
-                    }
-                    return CoderResult.UNDERFLOW;
-            }
-    }
-
-    /*
-     * Mock decoder for MockCachedEncoder.
-     */
-    static class MockDecoderForEncoder extends CharsetDecoder {
-            public MockDecoderForEncoder(Charset cs) {
-                    super(cs, 1, 10);
-            }
-
-            protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
-                    in.position(in.limit());
-                    return CoderResult.UNDERFLOW;
-            }
-    }
-
 }
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java b/nio_char/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java
index 88cbbdb..ff6fe42 100644
--- a/nio_char/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java
@@ -1,3 +1,20 @@
+/*
+ *  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 tests.api.java.nio.charset;
 
 import java.nio.ByteBuffer;
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
index 927a96f..06d7da2 100644
--- a/nio_char/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
@@ -20,13 +20,18 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
 
+import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CoderResult;
 import java.nio.charset.CodingErrorAction;
 import java.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
 @TestTargetClass(CharsetDecoder.class)
 /**
  * API unit test for java.nio.charset.CharsetDecoder
@@ -37,14 +42,35 @@
 
     protected static final double AVER_BYTES = 0.5;
 
-
     protected void setUp() throws Exception {
         cs = new CharsetEncoderTest.MockCharset("mock", new String[0]);
         unibytes = new byte[] { 32, 98, 117, 102, 102, 101, 114 };
+        decoder = cs.newDecoder();
+
+        // for this test's weird superclass, super.setUp() needs to be run last
         super.setUp();
     }
 
 
+    public void testDefaultValues() {
+        assertSame(cs, decoder.charset());
+        try {
+            decoder.detectedCharset();
+            fail("should unsupported");
+        } catch (UnsupportedOperationException e) {
+        }
+        try {
+            assertTrue(decoder.isCharsetDetected());
+            fail("should unsupported");
+        } catch (UnsupportedOperationException e) {
+        }
+        assertFalse(decoder.isAutoDetecting());
+        assertSame(CodingErrorAction.REPORT, decoder.malformedInputAction());
+        assertSame(CodingErrorAction.REPORT, decoder
+                .unmappableCharacterAction());
+        assertEquals(decoder.replacement(), "\ufffd");
+    }
+
     /*
      * test constructor
      */
@@ -127,6 +153,615 @@
         }
     }
 
+    /*
+     * test onMalformedInput
+     */
+    public void testOnMalformedInput() {
+        assertSame(CodingErrorAction.REPORT, decoder.malformedInputAction());
+        try {
+            decoder.onMalformedInput(null);
+            fail("should throw null pointer exception");
+        } catch (IllegalArgumentException e) {
+        }
+        decoder.onMalformedInput(CodingErrorAction.IGNORE);
+        assertSame(CodingErrorAction.IGNORE, decoder.malformedInputAction());
+    }
+
+    /*
+     * test unmappableCharacter
+     */
+    public void testOnUnmappableCharacter() {
+        assertSame(CodingErrorAction.REPORT, decoder
+                .unmappableCharacterAction());
+        try {
+            decoder.onUnmappableCharacter(null);
+            fail("should throw null pointer exception");
+        } catch (IllegalArgumentException e) {
+        }
+        decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+        assertSame(CodingErrorAction.IGNORE, decoder
+                .unmappableCharacterAction());
+    }
+
+    /*
+     * test replaceWith
+     */
+    public void testReplaceWith() {
+        try {
+            decoder.replaceWith(null);
+            fail("should throw null pointer exception");
+        } catch (IllegalArgumentException e) {
+        }
+        try {
+            decoder.replaceWith("");
+            fail("should throw null pointer exception");
+        } catch (IllegalArgumentException e) {
+        }
+        try {
+            decoder.replaceWith("testReplaceWith");
+            fail("should throw illegal argument exception");
+        } catch (IllegalArgumentException e) {
+        }
+
+        decoder.replaceWith("a");
+        assertSame("a", decoder.replacement());
+    }
+
+    /*
+     * Class under test for CharBuffer decode(ByteBuffer)
+     */
+    public void testDecodeByteBuffer() throws CharacterCodingException {
+        implTestDecodeByteBuffer();
+    }
+
+    void implTestDecodeByteBuffer() throws CharacterCodingException {
+        // Null pointer
+        try {
+            decoder.decode(null);
+            fail("should throw null pointer exception");
+        } catch (NullPointerException e) {
+        }
+
+        // empty input buffer
+        CharBuffer out = decoder.decode(ByteBuffer.allocate(0));
+        assertCharBufferValue("", out);
+
+        // normal case
+        ByteBuffer in = getByteBuffer();
+        out = decoder.decode(in);
+        assertEquals(0, out.position());
+        assertEquals(getString().length(), out.limit());
+        assertEquals(getString().length(), out.remaining());
+        assertCharBufferValue(getString(), out);
+
+        // normal read only case
+        in = getByteBuffer().asReadOnlyBuffer();
+        out = decoder.decode(in);
+        assertEquals(out.position(), 0);
+        assertEquals(out.limit(), getString().length());
+        assertEquals(out.remaining(), getString().length());
+        assertCharBufferValue(getString(), out);
+    }
+
+    public void testDecodeByteBufferException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        CharBuffer out;
+        ByteBuffer in;
+        String replaceStr = decoder.replacement() + getString();
+
+        // MalformedException:
+        decoder.onMalformedInput(CodingErrorAction.REPORT);
+        decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        in = getMalformedByteBuffer();
+        if (in != null) {
+            try {
+                CharBuffer buffer = decoder.decode(in);
+                assertTrue(buffer.remaining() > 0);
+                fail("should throw MalformedInputException");
+            } catch (MalformedInputException e) {
+            }
+
+            decoder.reset();
+            in.rewind();
+            decoder.onMalformedInput(CodingErrorAction.IGNORE);
+            out = decoder.decode(in);
+            assertCharBufferValue(getString(), out);
+
+            decoder.reset();
+            in.rewind();
+            decoder.onMalformedInput(CodingErrorAction.REPLACE);
+            out = decoder.decode(in);
+            assertCharBufferValue(replaceStr, out);
+        }
+
+        // Unmapped Exception:
+        decoder.onMalformedInput(CodingErrorAction.REPORT);
+        decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        in = getUnmappedByteBuffer();
+        if (in != null) {
+            try {
+                decoder.decode(in);
+                fail("should throw UnmappableCharacterException");
+            } catch (UnmappableCharacterException e) {
+            }
+
+            decoder.reset();
+            in.rewind();
+            decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+            out = decoder.decode(in);
+            assertCharBufferValue(getString(), out);
+
+            decoder.reset();
+            in.rewind();
+            decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+            out = decoder.decode(in);
+            assertCharBufferValue(replaceStr, out);
+        }
+
+        // RuntimeException
+        try {
+            decoder.decode(getExceptionByteArray());
+            fail("should throw runtime exception");
+        } catch (RuntimeException e) {
+        }
+    }
+
+    /*
+     * Class under test for CoderResult decode(ByteBuffer, CharBuffer, boolean)
+     */
+    public void testDecodeByteBufferCharBuffer() {
+        implTestDecodeByteBufferCharBuffer(getByteBuffer());
+    }
+
+    public void testDecodeByteBufferCharBufferReadOnly() {
+        implTestDecodeByteBufferCharBuffer(getByteBuffer());
+    }
+
+    void implTestDecodeByteBufferCharBuffer(ByteBuffer in) {
+        CharBuffer out = CharBuffer.allocate(100);
+
+        // Null pointer
+        decoder.reset();
+        try {
+            decoder.decode(null, out, true);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+        }
+        try {
+            decoder.decode(in, null, true);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+        }
+
+        // normal case, one complete operation
+        decoder.reset();
+        in.rewind();
+        out.rewind();
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+        assertEquals(out.limit(), 100);
+        assertEquals(out.position(), getString().length());
+        assertEquals(out.remaining(), 100 - getString().length());
+        assertEquals(out.capacity(), 100);
+        assertCharBufferValue(getString(), out);
+        decoder.flush(out);
+
+        // normal case, one complete operation, but call twice, first time set
+        // endOfInput to false
+        decoder.reset();
+        in.rewind();
+        out.clear();
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+        assertEquals(out.limit(), 100);
+        assertEquals(out.position(), getString().length());
+        assertEquals(out.remaining(), 100 - getString().length());
+        assertEquals(out.capacity(), 100);
+        assertCharBufferValue(getString(), out);
+
+        decoder.reset();
+        in.rewind();
+        out.clear();
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+        in = getHeadlessByteBuffer();
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+        in.rewind();
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+        assertEquals(out.limit(), 100);
+        assertTrue(out.position() > 0);
+        assertEquals(out.remaining(), out.capacity() - out.position());
+        assertEquals(out.capacity(), 100);
+        assertCharBufferValue(getString() + getString() + getString(), out);
+
+        // overflow
+        out = CharBuffer.allocate(4);
+        decoder.reset();
+        in = getByteBuffer();
+        out.rewind();
+        assertSame(CoderResult.OVERFLOW, decoder.decode(in, out, false));
+
+        assertCharBufferValue(getString().substring(0, 4), out);
+        out = CharBuffer.allocate(100);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+        assertCharBufferValue(getString().substring(4), out);
+        in.rewind();
+        out = CharBuffer.allocate(100);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+        assertCharBufferValue(bom + getString(), out);
+    }
+
+    public void testDecodeCharBufferByteBufferUnmappedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferUnmappedException(
+                getUnmappedByteBuffer(), true);
+    }
+
+    public void testDecodeCharBufferByteIncompleteBufferUnmappedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferUnmappedException(
+                getUnmappedByteBuffer(), false);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyBufferUnmappedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferUnmappedException(
+                readOnly(getUnmappedByteBuffer()), true);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyIncompleteBufferUnmappedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferUnmappedException(
+                readOnly(getUnmappedByteBuffer()), false);
+    }
+
+    void implTestDecodeCharBufferByteBufferUnmappedException(ByteBuffer in,
+            boolean endOfInput) throws CharacterCodingException,
+            UnsupportedEncodingException {
+        if (null == in) {
+            return;
+        }
+        CharBuffer out = CharBuffer.allocate(50);
+
+        decoder.onMalformedInput(CodingErrorAction.REPORT);
+        decoder.reset();
+        decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        CoderResult result = decoder.decode(in, out, endOfInput);
+        assertTrue(result.isUnmappable());
+
+        decoder.reset();
+        out.clear();
+        in.rewind();
+        decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+        assertCharBufferValue(getString(), out);
+
+        decoder.reset();
+        out.clear();
+        in.rewind();
+        decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+        assertCharBufferValue(decoder.replacement() + getString(), out);
+    }
+
+    public void testDecodeCharBufferByteBufferMalformedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferMalformedException(
+                getMalformedByteBuffer(), true);
+    }
+
+    public void testDecodeCharBufferByteIncompleteBufferMalformedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+
+        implTestDecodeCharBufferByteBufferMalformedException(
+                getMalformedByteBuffer(), false);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyBufferMalformedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferMalformedException(
+                readOnly(getMalformedByteBuffer()), true);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyIncompleteBufferMalformedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferMalformedException(
+                readOnly(getMalformedByteBuffer()), false);
+    }
+
+    void implTestDecodeCharBufferByteBufferMalformedException(ByteBuffer in,
+            boolean endOfInput) throws CharacterCodingException,
+            UnsupportedEncodingException {
+        if (null == in) {
+            return;
+        }
+        CharBuffer out = CharBuffer.allocate(getString().length() * 3);
+        decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        decoder.reset();
+        decoder.onMalformedInput(CodingErrorAction.REPORT);
+        CoderResult result = decoder.decode(in, out, endOfInput);
+        assertTrue(result.isMalformed());
+
+        decoder.reset();
+        out.clear();
+        in.rewind();
+        decoder.onMalformedInput(CodingErrorAction.IGNORE);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+        assertCharBufferValue(getString(), out);
+
+        decoder.reset();
+        out.clear();
+        in.rewind();
+        decoder.onMalformedInput(CodingErrorAction.REPLACE);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+        assertCharBufferValue(decoder.replacement() + getString(), out);
+    }
+
+    public void testDecodeCharBufferByteBufferException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferException(getExceptionByteArray(),
+                true);
+    }
+
+    public void testDecodeCharBufferByteIncompleteBufferException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferException(getExceptionByteArray(),
+                false);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyBufferException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferException(
+                readOnly(getExceptionByteArray()), true);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyIncompleteBufferException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferException(
+                readOnly(getExceptionByteArray()), false);
+    }
+
+    void implTestDecodeCharBufferByteBufferException(ByteBuffer in,
+            boolean endOfInput) throws CharacterCodingException,
+            UnsupportedEncodingException {
+        CharBuffer out = CharBuffer.allocate(50);
+        decoder.reset();
+        try {
+            decoder.decode(in, out, endOfInput);
+            fail("should throw runtime exception");
+        } catch (RuntimeException e) {
+        }
+    }
+
+    private ByteBuffer readOnly(ByteBuffer b) {
+        if (null == b) {
+            return null;
+        }
+        return b.asReadOnlyBuffer();
+    }
+
+    protected String getString() {
+        return " buffer";
+    }
+
+    protected ByteBuffer getByteBuffer() {
+        return ByteBuffer.wrap(new byte[] { 32, 98, 117, 102, 102, 101, 114 });
+    }
+
+    protected ByteBuffer getHeadlessByteBuffer() {
+        return getByteBuffer();
+    }
+
+    ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+        // "runtime"
+        return ByteBuffer
+                .wrap(new byte[] { 114, 117, 110, 116, 105, 109, 101 });
+    }
+
+    ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+        // "unmap buffer"
+        byte[] ba = new byte[] { 117, 110, 109, 97, 112, 32, 98, 117, 102, 102,
+                101, 114 };
+        return ByteBuffer.wrap(ba);
+    }
+
+    ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+        // "malform buffer"
+        byte[] ba = new byte[] { 109, 97, 108, 102, 111, 114, 109, 32, 98, 117,
+                102, 102, 101, 114 };
+        return ByteBuffer.wrap(ba);
+    }
+
+    private void assertCharBufferValue(String expected, CharBuffer out) {
+        if (out.position() != 0) {
+            out.flip();
+        }
+        assertEquals(expected, new String(out.array(), out.arrayOffset(), out
+                .arrayOffset() + out.limit()));
+    }
+
+    /*
+     * test flush
+     */
+    public void testFlush() throws CharacterCodingException {
+        CharBuffer out = CharBuffer.allocate(10);
+        ByteBuffer in = ByteBuffer.wrap(new byte[] { 12, 12 });
+        decoder.decode(in, out, true);
+        assertSame(CoderResult.UNDERFLOW, decoder.flush(out));
+
+        decoder.reset();
+        decoder.decode((ByteBuffer) in.rewind(), (CharBuffer) out.rewind(),
+                true);
+        assertSame(CoderResult.UNDERFLOW, decoder
+                .flush(CharBuffer.allocate(10)));
+    }
+
+    /*
+     * ---------------------------------- methods to test illegal state
+     * -----------------------------------
+     */
+    // Normal case: just after reset, and it also means reset can be done
+    // anywhere
+    public void testResetIllegalState() throws CharacterCodingException {
+        decoder.reset();
+        decoder.decode(getByteBuffer());
+        decoder.reset();
+        decoder.decode(getByteBuffer(), CharBuffer.allocate(3), false);
+        decoder.reset();
+        decoder.decode(getByteBuffer(), CharBuffer.allocate(3), true);
+        decoder.reset();
+    }
+
+    public void testFlushIllegalState() throws CharacterCodingException {
+        ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+        CharBuffer out = CharBuffer.allocate(5);
+        // Normal case: after decode with endOfInput is true
+        decoder.reset();
+        decoder.decode(in, out, true);
+        out.rewind();
+        CoderResult result = decoder.flush(out);
+        assertSame(result, CoderResult.UNDERFLOW);
+
+        // Illegal state: flush twice
+        try {
+            decoder.flush(out);
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+        }
+
+        // Illegal state: flush after decode with endOfInput is false
+        decoder.reset();
+        decoder.decode(in, out, false);
+        try {
+            decoder.flush(out);
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+        }
+    }
+
+    // test illegal states for decode facade
+    public void testDecodeFacadeIllegalState() throws CharacterCodingException {
+        // decode facade can be execute in anywhere
+        ByteBuffer in = getByteBuffer();
+
+        // Normal case: just created
+        decoder.decode(in);
+        in.rewind();
+
+        // Normal case: just after decode facade
+        decoder.decode(in);
+        in.rewind();
+
+        // Normal case: just after decode with that endOfInput is true
+        decoder.reset();
+        decoder.decode(getByteBuffer(), CharBuffer.allocate(30), true);
+        decoder.decode(in);
+        in.rewind();
+
+        // Normal case:just after decode with that endOfInput is false
+        decoder.reset();
+        decoder.decode(getByteBuffer(), CharBuffer.allocate(30), false);
+        decoder.decode(in);
+        in.rewind();
+
+        // Normal case: just after flush
+        decoder.reset();
+        decoder.decode(getByteBuffer(), CharBuffer.allocate(30), true);
+        decoder.flush(CharBuffer.allocate(10));
+        decoder.decode(in);
+        in.rewind();
+    }
+
+    // test illegal states for two decode method with endOfInput is true
+    public void testDecodeTrueIllegalState() throws CharacterCodingException {
+        ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+        CharBuffer out = CharBuffer.allocate(100);
+        // Normal case: just created
+        decoder.decode(in, out, true);
+        in.rewind();
+        out.rewind();
+
+        // Normal case: just after decode with that endOfInput is true
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), true);
+        in.rewind();
+        decoder.decode(in, out, true);
+        in.rewind();
+        out.rewind();
+
+        // Normal case:just after decode with that endOfInput is false
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), false);
+        in.rewind();
+        decoder.decode(in, out, true);
+        in.rewind();
+        out.rewind();
+
+        // Illegal state: just after flush
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), true);
+        decoder.flush(CharBuffer.allocate(10));
+        in.rewind();
+        try {
+            decoder.decode(in, out, true);
+            fail("should illegal state");
+        } catch (IllegalStateException e) {
+        }
+        in.rewind();
+        out.rewind();
+
+    }
+
+    // test illegal states for two decode method with endOfInput is false
+    public void testDecodeFalseIllegalState() throws CharacterCodingException {
+        ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+        CharBuffer out = CharBuffer.allocate(5);
+        // Normal case: just created
+        decoder.decode(in, out, false);
+        in.rewind();
+        out.rewind();
+
+        // Illegal state: just after decode facade
+        decoder.reset();
+        decoder.decode(in);
+        in.rewind();
+        try {
+            decoder.decode(in, out, false);
+            fail("should illegal state");
+        } catch (IllegalStateException e) {
+        }
+        in.rewind();
+        out.rewind();
+
+        // Illegal state: just after decode with that endOfInput is true
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), true);
+        in.rewind();
+        try {
+            decoder.decode(in, out, false);
+            fail("should illegal state");
+        } catch (IllegalStateException e) {
+        }
+        in.rewind();
+        out.rewind();
+
+        // Normal case:just after decode with that endOfInput is false
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), false);
+        in.rewind();
+        decoder.decode(in, out, false);
+        in.rewind();
+        out.rewind();
+
+        // Illegal state: just after flush
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), true);
+        in.rewind();
+        decoder.flush(CharBuffer.allocate(10));
+        try {
+            decoder.decode(in, out, false);
+            fail("should illegal state");
+        } catch (IllegalStateException e) {
+        }
+    }
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/Charset_TestGenerator_Res.java b/nio_char/src/test/java/tests/api/java/nio/charset/Charset_TestGenerator_Res.java
index dfdffa6..a8c89ef 100644
--- a/nio_char/src/test/java/tests/api/java/nio/charset/Charset_TestGenerator_Res.java
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/Charset_TestGenerator_Res.java
@@ -15,20 +15,9 @@
  */
 package tests.api.java.nio.charset;
 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-
-import junit.framework.TestCase;
-
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CodingErrorAction;
-import java.util.Arrays;
 
 /**
  * Super class for concrete charset test suites.
diff --git a/openssl/src/main/java/org/openssl/NativeBN.java b/openssl/src/main/java/org/openssl/NativeBN.java
index 44464e0..fd796f8 100644
--- a/openssl/src/main/java/org/openssl/NativeBN.java
+++ b/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)
@@ -89,9 +86,6 @@
     public static native void BN_set_negative(int b, int n);
     // void BN_set_negative(BIGNUM *b, int n);
 
-
-    public static native boolean twosCompFitsIntoBytes(int a, int byteCnt);
-
     public static native int bitLength(int a);
 
     public static native boolean BN_is_bit_set(int a, int n);
diff --git a/openssl/src/main/native/BNInterface.c b/openssl/src/main/native/BNInterface.c
index 4132e4f..79f0680 100644
--- a/openssl/src/main/native/BNInterface.c
+++ b/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)
@@ -496,60 +469,6 @@
     BN_set_negative(b, n);
 }
 
-
-/**
- * public static native int twosCompFitsIntoBytes(int, int)
- */
-static jboolean NativeBN_twosCompFitsIntoBytes(JNIEnv* env, jclass cls, BIGNUM* a, int byteCnt) {
-// byteCnt IN {1, 2, 4, 8, 12, 16, ... (k * 4)}
-// We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
-//
-// LOGD("NativeBN_twosCompFitsIntoBytes");
-    if (!oneValidHandle(env, a)) return FALSE;
-    bn_check_top(a);
-    int intLen = a->top;
-    BN_ULONG* d = a->d;
-    BN_ULONG msd; // most significant digit
-    switch (byteCnt) {
-    case 1:
-        if (intLen > 1) return FALSE;
-        else if (intLen == 0) return TRUE;
-        msd = d[0];
-        if (a->neg) msd--;
-        return ((msd & 0XFFFFFF80) == 0);
-    case 2:
-        if (intLen > 1) return FALSE;
-        else if (intLen == 0) return TRUE;
-        msd = d[0];
-        if (a->neg) msd--;
-        return ((msd & 0XFFFF8000) == 0);
-    case 4:
-        if (intLen > 1) return FALSE;
-        else if (intLen == 0) return TRUE;
-        msd = d[0];
-        if (a->neg) msd--;
-        return ((msd & 0X80000000) == 0);
-    case 8:
-        if (intLen > 2) return FALSE;
-        else if (intLen == 0) return TRUE;
-        msd = d[1];
-        if ((a->neg) && (d[0]) == 0) msd--;
-        return ((msd & 0X80000000) == 0);
-    default:
-        if (intLen > byteCnt / 4) return FALSE;
-        else if (intLen == 0) return TRUE;
-        int i = intLen - 1;
-        msd = d[i];
-        if (a->neg) {
-            // Handle negative values correctly:
-            // i.e. decrement the msd if all other digits are 0:
-            do { i--; } while (!((i < 0) || (d[i] != 0)));
-            if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
-        }
-        return ((msd & 0X80000000) == 0);
-    }
-}
-
 /**
  * public static native int bitLength(int)
  */
@@ -574,15 +493,6 @@
 }
 
 /**
- * public static native int BN_num_bits(int)
- */
-// static int NativeBN_BN_num_bits(JNIEnv* env, jclass cls, BIGNUM* a) {
-// LOGD("NativeBN_BN_num_bits");
-//     if (!oneValidHandle(env, a)) return FALSE;
-//     return BN_num_bits(a);
-// }
-
-/**
  * public static native boolean BN_is_bit_set(int, int)
  */
 static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass cls, BIGNUM* a, int n) {
@@ -833,12 +743,9 @@
    { "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 },
    { "bitLength", "(I)I", (void*)NativeBN_bitLength },
-//   { "BN_num_bits", "(I)I", (void*)NativeBN_BN_num_bits },
    { "BN_is_bit_set", "(II)Z", (void*)NativeBN_BN_is_bit_set },
    { "modifyBit", "(III)Z", (void*)NativeBN_modifyBit },
    { "BN_lshift", "(III)Z", (void*)NativeBN_BN_lshift },
@@ -860,19 +767,6 @@
    { "BN_is_prime_ex", "(IIII)Z", (void*)NativeBN_BN_is_prime_ex }
 };
 
-/*
- * Peforms the actual registration of the native methods.
- * Also looks up the fields that belong to the class (if
- * any) and stores the field IDs.
- */
 int register_org_openssl_NativeBN(JNIEnv* env) {
-/*
-   jclass clazz;
-
-   clazz = (*env)->FindClass(env, "org/openssl/NativeBN");
-   if (clazz == NULL) {
-       return -1;
-   }
-*/
    return jniRegisterNativeMethods(env, "org/openssl/NativeBN", METHODS, NELEM(METHODS));
 }
diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/AbstractPreferencesTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/AbstractPreferencesTest.java
index 76ef4e7..b45a75a 100644
--- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/AbstractPreferencesTest.java
+++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/AbstractPreferencesTest.java
@@ -16,12 +16,12 @@
 
 package org.apache.harmony.prefs.tests.java.util.prefs;
 
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
-
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
 import junit.framework.TestCase;
+import tests.util.TestEnvironment;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -35,13 +35,9 @@
 import java.util.prefs.PreferenceChangeListener;
 import java.util.prefs.Preferences;
 
-import tests.util.PrefsTester;
-
 @TestTargetClass(AbstractPreferences.class)
 public class AbstractPreferencesTest extends TestCase {
 
-    private final PrefsTester prefsTester = new PrefsTester();
-
     AbstractPreferences pref;
 
     static AbstractPreferences root;
@@ -55,7 +51,7 @@
     
     protected void setUp() throws Exception {
         super.setUp();
-        prefsTester.setUp();
+        TestEnvironment.reset();
 
         root = (AbstractPreferences) Preferences.userRoot();
         parent = (AbstractPreferences) Preferences.userNodeForPackage(this.getClass());
@@ -64,7 +60,6 @@
     }
 
     protected void tearDown() throws Exception {
-        prefsTester.tearDown();
         super.tearDown();
     }
 
diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java
index 0cb1975..4535a59 100644
--- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java
+++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java
@@ -17,33 +17,29 @@
 package org.apache.harmony.prefs.tests.java.util.prefs;
 
 import dalvik.annotation.AndroidOnly;
-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 tests.util.TestEnvironment;
 
 import java.io.FilePermission;
 import java.security.Permission;
 import java.util.prefs.BackingStoreException;
 import java.util.prefs.Preferences;
 
-import junit.framework.TestCase;
-import tests.util.PrefsTester;
-
 @TestTargetClass(java.util.prefs.Preferences.class)
 public class FilePreferencesImplTest extends TestCase {
 
-    private final PrefsTester prefsTester = new PrefsTester();
-
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        prefsTester.setUp();
+        TestEnvironment.reset();
     }
 
     @Override
     protected void tearDown() throws Exception {
-        prefsTester.tearDown();
         super.tearDown();
     }
 
diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java
index 1afd755..e24026c 100644
--- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java
+++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java
@@ -16,10 +16,12 @@
 
 package org.apache.harmony.prefs.tests.java.util.prefs;
 
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
+import junit.framework.TestCase;
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import tests.util.TestEnvironment;
 
 import java.io.NotSerializableException;
 import java.util.prefs.AbstractPreferences;
@@ -27,28 +29,20 @@
 import java.util.prefs.NodeChangeEvent;
 import java.util.prefs.Preferences;
 
-import junit.framework.TestCase;
-
-import org.apache.harmony.testframework.serialization.SerializationTest;
-import tests.util.PrefsTester;
-
 /**
  * 
  */
 @TestTargetClass(NodeChangeEvent.class)
 public class NodeChangeEventTest extends TestCase {
 
-    private final PrefsTester prefsTester = new PrefsTester();
-
     NodeChangeEvent event;
 
     protected void setUp() throws Exception {
         super.setUp();
-        prefsTester.setUp();
+        TestEnvironment.reset();
     }
 
     protected void tearDown() throws Exception {
-        prefsTester.tearDown();
         super.tearDown();
     }
 
diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeListenerTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeListenerTest.java
index 3cdb4d9..8e01589 100644
--- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeListenerTest.java
+++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeListenerTest.java
@@ -16,26 +16,22 @@
 
 package org.apache.harmony.prefs.tests.java.util.prefs;
 
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
+import junit.framework.TestCase;
+import tests.util.TestEnvironment;
 
 import java.util.prefs.NodeChangeEvent;
 import java.util.prefs.NodeChangeListener;
 import java.util.prefs.Preferences;
 
-import junit.framework.TestCase;
-import tests.util.PrefsTester;
-
 /**
  * 
  */
 @TestTargetClass(NodeChangeListener.class)
 public class NodeChangeListenerTest extends TestCase {
 
-    private final PrefsTester prefsTester = new PrefsTester();
-
     NodeChangeListener l;
 
     /*
@@ -44,7 +40,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        prefsTester.setUp();
+        TestEnvironment.reset();
         l = new NodeChangeListenerImpl();
     }
 
@@ -53,7 +49,6 @@
      */
     @Override
     protected void tearDown() throws Exception {
-        prefsTester.tearDown();
         super.tearDown();
     }
 
diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeEventTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeEventTest.java
index dda1f6c..47e621e 100644
--- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeEventTest.java
+++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeEventTest.java
@@ -16,20 +16,18 @@
 
 package org.apache.harmony.prefs.tests.java.util.prefs;
 
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
+import junit.framework.TestCase;
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import tests.util.TestEnvironment;
 
 import java.io.NotSerializableException;
 import java.util.prefs.AbstractPreferences;
 import java.util.prefs.PreferenceChangeEvent;
 import java.util.prefs.Preferences;
 
-import junit.framework.TestCase;
-
-import org.apache.harmony.testframework.serialization.SerializationTest;
-
 /**
  * 
  */
@@ -38,6 +36,15 @@
 
     PreferenceChangeEvent event;
 
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+    }
+
+    @Override protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
     @TestTargetNew(
         level = TestLevel.PARTIAL,
         notes = "Checks exception.",
diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java
index c9c74fd..122dacd 100644
--- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java
+++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java
@@ -21,11 +21,10 @@
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
-
 import junit.framework.TestCase;
+import tests.util.TestEnvironment;
 
 import java.io.ByteArrayInputStream;
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -39,16 +38,12 @@
 import java.util.prefs.PreferenceChangeListener;
 import java.util.prefs.Preferences;
 
-import tests.util.PrefsTester;
-
 /**
  * 
  */
 @TestTargetClass(Preferences.class)
 public class PreferencesTest extends TestCase {
 
-    private final PrefsTester prefsTester = new PrefsTester();
-
     MockSecurityManager manager = new MockSecurityManager();
 
     MockInputStream stream = null;
@@ -82,7 +77,7 @@
                 "<!DOCTYPE preferences SYSTEM \"http://java.sun.com/dtd/preferences.dtd\"><preferences><root type=\"user\"><map></map></root></preferences>"
                         .getBytes("UTF-8"));
         stream = new MockInputStream(in);
-        prefsTester.setUp();
+        TestEnvironment.reset();
     }
 
     /*
@@ -91,7 +86,6 @@
     @Override
     protected void tearDown() throws Exception {
         stream.close();
-        prefsTester.tearDown();
         super.tearDown();
     }
 
diff --git a/regex/src/main/java/java/util/regex/MatchResult.java b/regex/src/main/java/java/util/regex/MatchResult.java
index fa67ba6..76c17a8 100644
--- a/regex/src/main/java/java/util/regex/MatchResult.java
+++ b/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/regex/src/main/java/java/util/regex/Matcher.java b/regex/src/main/java/java/util/regex/Matcher.java
index e3e4874..be5c782 100644
--- a/regex/src/main/java/java/util/regex/Matcher.java
+++ b/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/regex/src/main/java/java/util/regex/Pattern.java b/regex/src/main/java/java/util/regex/Pattern.java
index 2c71de1..db3bc21 100644
--- a/regex/src/main/java/java/util/regex/Pattern.java
+++ b/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/regex/src/main/java/java/util/regex/PatternSyntaxException.java b/regex/src/main/java/java/util/regex/PatternSyntaxException.java
index e4d5abd..d59bdd4 100644
--- a/regex/src/main/java/java/util/regex/PatternSyntaxException.java
+++ b/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/run-core-tests b/run-core-tests
index 70ab320..723d36f 100755
--- a/run-core-tests
+++ b/run-core-tests
@@ -25,6 +25,11 @@
 mkdir $tmp
 chmod 777 $tmp
   
-exec dalvikvm -Duser.language=en -Duser.region=US -Djava.io.tmpdir=$tmp \
+exec dalvikvm \
+     -Duser.name=root \
+     -Duser.language=en \
+     -Duser.region=US \
+     -Djava.io.tmpdir=$tmp \
+     -Djavax.net.ssl.trustStore=/system/etc/security/cacerts.bks \
      -classpath /system/framework/core-tests.jar \
      -Xmx64M com.google.coretests.Main "$@"
diff --git a/security/src/main/files/cacerts.bks b/security/src/main/files/cacerts.bks
index 36f4919..583c6fa 100644
--- a/security/src/main/files/cacerts.bks
+++ b/security/src/main/files/cacerts.bks
Binary files differ
diff --git a/security/src/main/files/cacerts/97b4211c.0 b/security/src/main/files/cacerts/97b4211c.0
deleted file mode 100644
index 9417aed..0000000
--- a/security/src/main/files/cacerts/97b4211c.0
+++ /dev/null
@@ -1,47 +0,0 @@
-Certificate:
-    Data:
-        Version: 1 (0x0)
-        Serial Number: 419 (0x1a3)
-        Signature Algorithm: md5WithRSAEncryption
-        Issuer: C=US, O=GTE Corporation, CN=GTE CyberTrust Root
-        Validity
-            Not Before: Feb 23 23:01:00 1996 GMT
-            Not After : Feb 23 23:59:00 2006 GMT
-        Subject: C=US, O=GTE Corporation, CN=GTE CyberTrust Root
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-            RSA Public Key: (1024 bit)
-                Modulus (1024 bit):
-                    00:b8:e6:4f:ba:db:98:7c:71:7c:af:44:b7:d3:0f:
-                    46:d9:64:e5:93:c1:42:8e:c7:ba:49:8d:35:2d:7a:
-                    e7:8b:bd:e5:05:31:59:c6:b1:2f:0a:0c:fb:9f:a7:
-                    3f:a2:09:66:84:56:1e:37:29:1b:87:e9:7e:0c:ca:
-                    9a:9f:a5:7f:f5:15:94:a3:d5:a2:46:82:d8:68:4c:
-                    d1:37:15:06:68:af:bd:f8:b0:b3:f0:29:f5:95:5a:
-                    09:16:61:77:0a:22:25:d4:4f:45:aa:c7:bd:e5:96:
-                    df:f9:d4:a8:8e:42:cc:24:c0:1e:91:27:4a:b5:6d:
-                    06:80:63:39:c4:a2:5e:38:03
-                Exponent: 65537 (0x10001)
-    Signature Algorithm: md5WithRSAEncryption
-        12:b3:75:c6:5f:1d:e1:61:55:80:00:d4:81:4b:7b:31:0f:23:
-        63:e7:3d:f3:03:f9:f4:36:a8:bb:d9:e3:a5:97:4d:ea:2b:29:
-        e0:d6:6a:73:81:e6:c0:89:a3:d3:f1:e0:a5:a5:22:37:9a:63:
-        c2:48:20:b4:db:72:e3:c8:f6:d9:7c:be:b1:af:53:da:14:b4:
-        21:b8:d6:d5:96:e3:fe:4e:0c:59:62:b6:9a:4a:f9:42:dd:8c:
-        6f:81:a9:71:ff:f4:0a:72:6d:6d:44:0e:9d:f3:74:74:a8:d5:
-        34:49:e9:5e:9e:e9:b4:7a:e1:e5:5a:1f:84:30:9c:d3:9f:a5:
-        25:d8
-SHA1 Fingerprint=90:DE:DE:9E:4C:4E:9F:6F:D8:86:17:57:9D:D3:91:BC:65:A6:89:64
------BEGIN CERTIFICATE-----
-MIIB+jCCAWMCAgGjMA0GCSqGSIb3DQEBBAUAMEUxCzAJBgNVBAYTAlVTMRgwFgYD
-VQQKEw9HVEUgQ29ycG9yYXRpb24xHDAaBgNVBAMTE0dURSBDeWJlclRydXN0IFJv
-b3QwHhcNOTYwMjIzMjMwMTAwWhcNMDYwMjIzMjM1OTAwWjBFMQswCQYDVQQGEwJV
-UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMRwwGgYDVQQDExNHVEUgQ3liZXJU
-cnVzdCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyv
-RLfTD0bZZOWTwUKOx7pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4M
-ypqfpX/1FZSj1aJGgthoTNE3FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/5
-1KiOQswkwB6RJ0q1bQaAYznEol44AwIDAQABMA0GCSqGSIb3DQEBBAUAA4GBABKz
-dcZfHeFhVYAA1IFLezEPI2PnPfMD+fQ2qLvZ46WXTeorKeDWanOB5sCJo9Px4KWl
-IjeaY8JIILTbcuPI9tl8vrGvU9oUtCG41tWW4/5ODFlitppK+ULdjG+BqXH/9Apy
-bW1EDp3zdHSo1TRJ6V6e6bR64eVaH4QwnNOfpSXY
------END CERTIFICATE-----
diff --git a/security/src/main/java/java/security/AccessControlException.java b/security/src/main/java/java/security/AccessControlException.java
index 1710e77..ae23ab1 100644
--- a/security/src/main/java/java/security/AccessControlException.java
+++ b/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/security/src/main/java/java/security/AlgorithmParameterGenerator.java b/security/src/main/java/java/security/AlgorithmParameterGenerator.java
index 199efa1..6814813 100644
--- a/security/src/main/java/java/security/AlgorithmParameterGenerator.java
+++ b/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/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java b/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java
index 9ddff23..44b3def 100644
--- a/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java
+++ b/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/security/src/main/java/java/security/AlgorithmParameters.java b/security/src/main/java/java/security/AlgorithmParameters.java
index aaefe1b..d659200 100644
--- a/security/src/main/java/java/security/AlgorithmParameters.java
+++ b/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/security/src/main/java/java/security/AlgorithmParametersSpi.java b/security/src/main/java/java/security/AlgorithmParametersSpi.java
index 3bc8891..41b30bc 100644
--- a/security/src/main/java/java/security/AlgorithmParametersSpi.java
+++ b/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/security/src/main/java/java/security/AllPermission.java b/security/src/main/java/java/security/AllPermission.java
index f4b8aad..c12bb27 100644
--- a/security/src/main/java/java/security/AllPermission.java
+++ b/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/security/src/main/java/java/security/AllPermissionCollection.java b/security/src/main/java/java/security/AllPermissionCollection.java
index 000365d..5b28420 100644
--- a/security/src/main/java/java/security/AllPermissionCollection.java
+++ b/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/security/src/main/java/java/security/AuthProvider.java b/security/src/main/java/java/security/AuthProvider.java
index 5a3be77..15324b3 100644
--- a/security/src/main/java/java/security/AuthProvider.java
+++ b/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/security/src/main/java/java/security/BasicPermission.java b/security/src/main/java/java/security/BasicPermission.java
index 1d566ec..aa49cba 100644
--- a/security/src/main/java/java/security/BasicPermission.java
+++ b/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/security/src/main/java/java/security/BasicPermissionCollection.java b/security/src/main/java/java/security/BasicPermissionCollection.java
index eb80503..820ae7f 100644
--- a/security/src/main/java/java/security/BasicPermissionCollection.java
+++ b/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/security/src/main/java/java/security/Certificate.java b/security/src/main/java/java/security/Certificate.java
index bf9a1ae..b30352d 100644
--- a/security/src/main/java/java/security/Certificate.java
+++ b/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/security/src/main/java/java/security/CodeSigner.java b/security/src/main/java/java/security/CodeSigner.java
index 0719e8f..24d2b55 100644
--- a/security/src/main/java/java/security/CodeSigner.java
+++ b/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/security/src/main/java/java/security/CodeSource.java b/security/src/main/java/java/security/CodeSource.java
index f4da89c..96a4b8c5 100644
--- a/security/src/main/java/java/security/CodeSource.java
+++ b/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/security/src/main/java/java/security/DigestException.java b/security/src/main/java/java/security/DigestException.java
index d579885..0d0a1ee 100644
--- a/security/src/main/java/java/security/DigestException.java
+++ b/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/security/src/main/java/java/security/DigestInputStream.java b/security/src/main/java/java/security/DigestInputStream.java
index 0db7613..26433fa 100644
--- a/security/src/main/java/java/security/DigestInputStream.java
+++ b/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/security/src/main/java/java/security/DigestOutputStream.java b/security/src/main/java/java/security/DigestOutputStream.java
index 858f8dd..f4cd659 100644
--- a/security/src/main/java/java/security/DigestOutputStream.java
+++ b/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/security/src/main/java/java/security/DomainCombiner.java b/security/src/main/java/java/security/DomainCombiner.java
index 501c419..36433b3 100644
--- a/security/src/main/java/java/security/DomainCombiner.java
+++ b/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/security/src/main/java/java/security/GeneralSecurityException.java b/security/src/main/java/java/security/GeneralSecurityException.java
index 2a1cacb..78fca29 100644
--- a/security/src/main/java/java/security/GeneralSecurityException.java
+++ b/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/security/src/main/java/java/security/Guard.java b/security/src/main/java/java/security/Guard.java
index 1e4d270..b652054 100644
--- a/security/src/main/java/java/security/Guard.java
+++ b/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/security/src/main/java/java/security/GuardedObject.java b/security/src/main/java/java/security/GuardedObject.java
index a64d634..34a5113 100644
--- a/security/src/main/java/java/security/GuardedObject.java
+++ b/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/security/src/main/java/java/security/Identity.java b/security/src/main/java/java/security/Identity.java
index 7111029..d55cd3a 100644
--- a/security/src/main/java/java/security/Identity.java
+++ b/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/security/src/main/java/java/security/IdentityScope.java b/security/src/main/java/java/security/IdentityScope.java
index 93729dc..60ab3e8 100644
--- a/security/src/main/java/java/security/IdentityScope.java
+++ b/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/security/src/main/java/java/security/InvalidAlgorithmParameterException.java b/security/src/main/java/java/security/InvalidAlgorithmParameterException.java
index 0d8a607..26d9f97 100644
--- a/security/src/main/java/java/security/InvalidAlgorithmParameterException.java
+++ b/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/security/src/main/java/java/security/InvalidKeyException.java b/security/src/main/java/java/security/InvalidKeyException.java
index 95d864e..f08fc51 100644
--- a/security/src/main/java/java/security/InvalidKeyException.java
+++ b/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/security/src/main/java/java/security/InvalidParameterException.java b/security/src/main/java/java/security/InvalidParameterException.java
index ac10448..6ad4645 100644
--- a/security/src/main/java/java/security/InvalidParameterException.java
+++ b/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/security/src/main/java/java/security/Key.java b/security/src/main/java/java/security/Key.java
index 1359ab2..28d24ff 100644
--- a/security/src/main/java/java/security/Key.java
+++ b/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/security/src/main/java/java/security/KeyException.java b/security/src/main/java/java/security/KeyException.java
index b01f75b..721c896 100644
--- a/security/src/main/java/java/security/KeyException.java
+++ b/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/security/src/main/java/java/security/KeyFactory.java b/security/src/main/java/java/security/KeyFactory.java
index 7c4966f..7484a31 100644
--- a/security/src/main/java/java/security/KeyFactory.java
+++ b/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/security/src/main/java/java/security/KeyFactorySpi.java b/security/src/main/java/java/security/KeyFactorySpi.java
index 7d3154e..0de00b2 100644
--- a/security/src/main/java/java/security/KeyFactorySpi.java
+++ b/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/security/src/main/java/java/security/KeyManagementException.java b/security/src/main/java/java/security/KeyManagementException.java
index 295ec03..00a5b3c 100644
--- a/security/src/main/java/java/security/KeyManagementException.java
+++ b/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/security/src/main/java/java/security/KeyPair.java b/security/src/main/java/java/security/KeyPair.java
index 6399427..b86593b 100644
--- a/security/src/main/java/java/security/KeyPair.java
+++ b/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/security/src/main/java/java/security/KeyPairGenerator.java b/security/src/main/java/java/security/KeyPairGenerator.java
index 5682aa2..2a17e98 100644
--- a/security/src/main/java/java/security/KeyPairGenerator.java
+++ b/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/security/src/main/java/java/security/KeyPairGeneratorSpi.java b/security/src/main/java/java/security/KeyPairGeneratorSpi.java
index 272c305..e2e22c1 100644
--- a/security/src/main/java/java/security/KeyPairGeneratorSpi.java
+++ b/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/security/src/main/java/java/security/KeyRep.java b/security/src/main/java/java/security/KeyRep.java
index ec1d364..29ccd22 100644
--- a/security/src/main/java/java/security/KeyRep.java
+++ b/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/security/src/main/java/java/security/KeyStore.java b/security/src/main/java/java/security/KeyStore.java
index 699a9df..02ac01d 100644
--- a/security/src/main/java/java/security/KeyStore.java
+++ b/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/security/src/main/java/java/security/KeyStoreException.java b/security/src/main/java/java/security/KeyStoreException.java
index 7c697f7..4327f7f 100644
--- a/security/src/main/java/java/security/KeyStoreException.java
+++ b/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/security/src/main/java/java/security/KeyStoreSpi.java b/security/src/main/java/java/security/KeyStoreSpi.java
index b02f264..e884123 100644
--- a/security/src/main/java/java/security/KeyStoreSpi.java
+++ b/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/security/src/main/java/java/security/MessageDigest.java b/security/src/main/java/java/security/MessageDigest.java
index 97cbdcc..cb8fc08 100644
--- a/security/src/main/java/java/security/MessageDigest.java
+++ b/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/security/src/main/java/java/security/MessageDigestSpi.java b/security/src/main/java/java/security/MessageDigestSpi.java
index ae5ed32..52ad3cd 100644
--- a/security/src/main/java/java/security/MessageDigestSpi.java
+++ b/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/security/src/main/java/java/security/NoSuchAlgorithmException.java b/security/src/main/java/java/security/NoSuchAlgorithmException.java
index 3324076..8ef2e3f 100644
--- a/security/src/main/java/java/security/NoSuchAlgorithmException.java
+++ b/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/security/src/main/java/java/security/NoSuchProviderException.java b/security/src/main/java/java/security/NoSuchProviderException.java
index f016ce6..57cda40 100644
--- a/security/src/main/java/java/security/NoSuchProviderException.java
+++ b/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/security/src/main/java/java/security/Permission.java b/security/src/main/java/java/security/Permission.java
index 93e769c..26bdfcd 100644
--- a/security/src/main/java/java/security/Permission.java
+++ b/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/security/src/main/java/java/security/PermissionCollection.java b/security/src/main/java/java/security/PermissionCollection.java
index 2502123..56b6cd0 100644
--- a/security/src/main/java/java/security/PermissionCollection.java
+++ b/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/security/src/main/java/java/security/Permissions.java b/security/src/main/java/java/security/Permissions.java
index b9b13c6..e8d3375 100644
--- a/security/src/main/java/java/security/Permissions.java
+++ b/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/security/src/main/java/java/security/PermissionsHash.java b/security/src/main/java/java/security/PermissionsHash.java
index 69d2b07..4c9e0c9 100644
--- a/security/src/main/java/java/security/PermissionsHash.java
+++ b/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/security/src/main/java/java/security/Policy.java b/security/src/main/java/java/security/Policy.java
index 21b13b0..d5719a3 100644
--- a/security/src/main/java/java/security/Policy.java
+++ b/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/security/src/main/java/java/security/Principal.java b/security/src/main/java/java/security/Principal.java
index 0716681..f86bc87 100644
--- a/security/src/main/java/java/security/Principal.java
+++ b/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/security/src/main/java/java/security/PrivateKey.java b/security/src/main/java/java/security/PrivateKey.java
index 8513b75..246f286 100644
--- a/security/src/main/java/java/security/PrivateKey.java
+++ b/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/security/src/main/java/java/security/PrivilegedAction.java b/security/src/main/java/java/security/PrivilegedAction.java
index 5912cdc..1dbbe65 100644
--- a/security/src/main/java/java/security/PrivilegedAction.java
+++ b/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/security/src/main/java/java/security/PrivilegedActionException.java b/security/src/main/java/java/security/PrivilegedActionException.java
index eaca2b2..a1f5b15 100644
--- a/security/src/main/java/java/security/PrivilegedActionException.java
+++ b/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/security/src/main/java/java/security/PrivilegedExceptionAction.java b/security/src/main/java/java/security/PrivilegedExceptionAction.java
index dd3ae8d..bc072d5 100644
--- a/security/src/main/java/java/security/PrivilegedExceptionAction.java
+++ b/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/security/src/main/java/java/security/ProtectionDomain.java b/security/src/main/java/java/security/ProtectionDomain.java
index d41f4a8..1e85c4a 100644
--- a/security/src/main/java/java/security/ProtectionDomain.java
+++ b/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/security/src/main/java/java/security/Provider.java b/security/src/main/java/java/security/Provider.java
index 491470f..cf9c94d 100644
--- a/security/src/main/java/java/security/Provider.java
+++ b/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/security/src/main/java/java/security/ProviderException.java b/security/src/main/java/java/security/ProviderException.java
index d4def5b..22950f5 100644
--- a/security/src/main/java/java/security/ProviderException.java
+++ b/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/security/src/main/java/java/security/PublicKey.java b/security/src/main/java/java/security/PublicKey.java
index 4888a64..c197840 100644
--- a/security/src/main/java/java/security/PublicKey.java
+++ b/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/security/src/main/java/java/security/SecureClassLoader.java b/security/src/main/java/java/security/SecureClassLoader.java
index 7d08fc8..07bebc9 100644
--- a/security/src/main/java/java/security/SecureClassLoader.java
+++ b/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/security/src/main/java/java/security/SecureRandom.java b/security/src/main/java/java/security/SecureRandom.java
index e1d99e9..c697504 100644
--- a/security/src/main/java/java/security/SecureRandom.java
+++ b/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/security/src/main/java/java/security/SecureRandomSpi.java b/security/src/main/java/java/security/SecureRandomSpi.java
index 7ce880c..829464f 100644
--- a/security/src/main/java/java/security/SecureRandomSpi.java
+++ b/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/security/src/main/java/java/security/Security.java b/security/src/main/java/java/security/Security.java
index 505a557..6ff38ad 100644
--- a/security/src/main/java/java/security/Security.java
+++ b/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/security/src/main/java/java/security/SecurityPermission.java b/security/src/main/java/java/security/SecurityPermission.java
index 87f3aaa..599ec6f 100644
--- a/security/src/main/java/java/security/SecurityPermission.java
+++ b/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/security/src/main/java/java/security/Signature.java b/security/src/main/java/java/security/Signature.java
index e5d488e..4e3fe14 100644
--- a/security/src/main/java/java/security/Signature.java
+++ b/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/security/src/main/java/java/security/SignatureException.java b/security/src/main/java/java/security/SignatureException.java
index f07c34b..f8909d1 100644
--- a/security/src/main/java/java/security/SignatureException.java
+++ b/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/security/src/main/java/java/security/SignatureSpi.java b/security/src/main/java/java/security/SignatureSpi.java
index 738d489..93c9e8c 100644
--- a/security/src/main/java/java/security/SignatureSpi.java
+++ b/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/security/src/main/java/java/security/SignedObject.java b/security/src/main/java/java/security/SignedObject.java
index d2022c8..3347cf3 100644
--- a/security/src/main/java/java/security/SignedObject.java
+++ b/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/security/src/main/java/java/security/Signer.java b/security/src/main/java/java/security/Signer.java
index 9e48226..64996bf 100644
--- a/security/src/main/java/java/security/Signer.java
+++ b/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/security/src/main/java/java/security/Timestamp.java b/security/src/main/java/java/security/Timestamp.java
index 1d31e6f..5a2930a 100644
--- a/security/src/main/java/java/security/Timestamp.java
+++ b/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/security/src/main/java/java/security/UnrecoverableEntryException.java b/security/src/main/java/java/security/UnrecoverableEntryException.java
index dc2981a..24ff54b 100644
--- a/security/src/main/java/java/security/UnrecoverableEntryException.java
+++ b/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/security/src/main/java/java/security/UnrecoverableKeyException.java b/security/src/main/java/java/security/UnrecoverableKeyException.java
index e4b399b..3840e6b 100644
--- a/security/src/main/java/java/security/UnrecoverableKeyException.java
+++ b/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/security/src/main/java/java/security/UnresolvedPermission.java b/security/src/main/java/java/security/UnresolvedPermission.java
index 6570de4..bf99a40 100644
--- a/security/src/main/java/java/security/UnresolvedPermission.java
+++ b/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/security/src/main/java/java/security/UnresolvedPermissionCollection.java b/security/src/main/java/java/security/UnresolvedPermissionCollection.java
index a43a54f..3a6ba92 100644
--- a/security/src/main/java/java/security/UnresolvedPermissionCollection.java
+++ b/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/security/src/main/java/java/security/acl/Acl.java b/security/src/main/java/java/security/acl/Acl.java
index 35c92fc..88dd9f0 100644
--- a/security/src/main/java/java/security/acl/Acl.java
+++ b/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/security/src/main/java/java/security/acl/AclEntry.java b/security/src/main/java/java/security/acl/AclEntry.java
index 7a5b722..fe2fb3a 100644
--- a/security/src/main/java/java/security/acl/AclEntry.java
+++ b/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/security/src/main/java/java/security/acl/AclNotFoundException.java b/security/src/main/java/java/security/acl/AclNotFoundException.java
index c8d4208..59b9045 100644
--- a/security/src/main/java/java/security/acl/AclNotFoundException.java
+++ b/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/security/src/main/java/java/security/acl/Group.java b/security/src/main/java/java/security/acl/Group.java
index 16898e6..7452181 100644
--- a/security/src/main/java/java/security/acl/Group.java
+++ b/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/security/src/main/java/java/security/acl/LastOwnerException.java b/security/src/main/java/java/security/acl/LastOwnerException.java
index 11c235f..f947f22 100644
--- a/security/src/main/java/java/security/acl/LastOwnerException.java
+++ b/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/security/src/main/java/java/security/acl/NotOwnerException.java b/security/src/main/java/java/security/acl/NotOwnerException.java
index 081bdea..c7de8c9 100644
--- a/security/src/main/java/java/security/acl/NotOwnerException.java
+++ b/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/security/src/main/java/java/security/acl/Owner.java b/security/src/main/java/java/security/acl/Owner.java
index 335dc84..c392e2f 100644
--- a/security/src/main/java/java/security/acl/Owner.java
+++ b/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/security/src/main/java/java/security/acl/Permission.java b/security/src/main/java/java/security/acl/Permission.java
index 0d6e22c..f2ee251 100644
--- a/security/src/main/java/java/security/acl/Permission.java
+++ b/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/security/src/main/java/java/security/cert/CRL.java b/security/src/main/java/java/security/cert/CRL.java
index b0f3e30..8153853 100644
--- a/security/src/main/java/java/security/cert/CRL.java
+++ b/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/security/src/main/java/java/security/cert/CRLException.java b/security/src/main/java/java/security/cert/CRLException.java
index 625d7d3..01e2071 100644
--- a/security/src/main/java/java/security/cert/CRLException.java
+++ b/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/security/src/main/java/java/security/cert/CRLSelector.java b/security/src/main/java/java/security/cert/CRLSelector.java
index ee2d39e..5b14446 100644
--- a/security/src/main/java/java/security/cert/CRLSelector.java
+++ b/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/security/src/main/java/java/security/cert/CertPath.java b/security/src/main/java/java/security/cert/CertPath.java
index 2874a4d..e9d049b 100644
--- a/security/src/main/java/java/security/cert/CertPath.java
+++ b/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/security/src/main/java/java/security/cert/CertPathBuilder.java b/security/src/main/java/java/security/cert/CertPathBuilder.java
index 47eac13..8daa741 100644
--- a/security/src/main/java/java/security/cert/CertPathBuilder.java
+++ b/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/security/src/main/java/java/security/cert/CertPathBuilderException.java b/security/src/main/java/java/security/cert/CertPathBuilderException.java
index b957291..58a4a60 100644
--- a/security/src/main/java/java/security/cert/CertPathBuilderException.java
+++ b/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/security/src/main/java/java/security/cert/CertPathBuilderResult.java b/security/src/main/java/java/security/cert/CertPathBuilderResult.java
index e56c4a0..36d99a1 100644
--- a/security/src/main/java/java/security/cert/CertPathBuilderResult.java
+++ b/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/security/src/main/java/java/security/cert/CertPathBuilderSpi.java b/security/src/main/java/java/security/cert/CertPathBuilderSpi.java
index 952f387..80ee0ef 100644
--- a/security/src/main/java/java/security/cert/CertPathBuilderSpi.java
+++ b/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/security/src/main/java/java/security/cert/CertPathParameters.java b/security/src/main/java/java/security/cert/CertPathParameters.java
index c99826f..e2cee18 100644
--- a/security/src/main/java/java/security/cert/CertPathParameters.java
+++ b/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/security/src/main/java/java/security/cert/CertPathValidator.java b/security/src/main/java/java/security/cert/CertPathValidator.java
index f95bd03..0d73280 100644
--- a/security/src/main/java/java/security/cert/CertPathValidator.java
+++ b/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/security/src/main/java/java/security/cert/CertPathValidatorException.java b/security/src/main/java/java/security/cert/CertPathValidatorException.java
index 072785c..4d2b69f 100644
--- a/security/src/main/java/java/security/cert/CertPathValidatorException.java
+++ b/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/security/src/main/java/java/security/cert/CertPathValidatorResult.java b/security/src/main/java/java/security/cert/CertPathValidatorResult.java
index 42540e4..7fab21a 100644
--- a/security/src/main/java/java/security/cert/CertPathValidatorResult.java
+++ b/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/security/src/main/java/java/security/cert/CertPathValidatorSpi.java b/security/src/main/java/java/security/cert/CertPathValidatorSpi.java
index 5573679..e14e8dd 100644
--- a/security/src/main/java/java/security/cert/CertPathValidatorSpi.java
+++ b/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/security/src/main/java/java/security/cert/CertSelector.java b/security/src/main/java/java/security/cert/CertSelector.java
index 0316ad3..c490b22 100644
--- a/security/src/main/java/java/security/cert/CertSelector.java
+++ b/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/security/src/main/java/java/security/cert/CertStore.java b/security/src/main/java/java/security/cert/CertStore.java
index a5c8260..d0b7600 100644
--- a/security/src/main/java/java/security/cert/CertStore.java
+++ b/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/security/src/main/java/java/security/cert/CertStoreException.java b/security/src/main/java/java/security/cert/CertStoreException.java
index 8351605..7f356b2 100644
--- a/security/src/main/java/java/security/cert/CertStoreException.java
+++ b/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/security/src/main/java/java/security/cert/CertStoreParameters.java b/security/src/main/java/java/security/cert/CertStoreParameters.java
index 566b2e2..06a1976 100644
--- a/security/src/main/java/java/security/cert/CertStoreParameters.java
+++ b/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/security/src/main/java/java/security/cert/CertStoreSpi.java b/security/src/main/java/java/security/cert/CertStoreSpi.java
index be680a7..cb38a31 100644
--- a/security/src/main/java/java/security/cert/CertStoreSpi.java
+++ b/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/security/src/main/java/java/security/cert/Certificate.java b/security/src/main/java/java/security/cert/Certificate.java
index 0543329..22cbe9c 100644
--- a/security/src/main/java/java/security/cert/Certificate.java
+++ b/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/security/src/main/java/java/security/cert/CertificateEncodingException.java b/security/src/main/java/java/security/cert/CertificateEncodingException.java
index 188d084..c5532b9 100644
--- a/security/src/main/java/java/security/cert/CertificateEncodingException.java
+++ b/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/security/src/main/java/java/security/cert/CertificateException.java b/security/src/main/java/java/security/cert/CertificateException.java
index 674d617..8b1c4d3 100644
--- a/security/src/main/java/java/security/cert/CertificateException.java
+++ b/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/security/src/main/java/java/security/cert/CertificateExpiredException.java b/security/src/main/java/java/security/cert/CertificateExpiredException.java
index fe3fc1f..e15bf98 100644
--- a/security/src/main/java/java/security/cert/CertificateExpiredException.java
+++ b/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/security/src/main/java/java/security/cert/CertificateFactory.java b/security/src/main/java/java/security/cert/CertificateFactory.java
index b4213d4..cb2636a 100644
--- a/security/src/main/java/java/security/cert/CertificateFactory.java
+++ b/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/security/src/main/java/java/security/cert/CertificateFactorySpi.java b/security/src/main/java/java/security/cert/CertificateFactorySpi.java
index ed6ffed..d9f2044 100644
--- a/security/src/main/java/java/security/cert/CertificateFactorySpi.java
+++ b/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/security/src/main/java/java/security/cert/CertificateNotYetValidException.java b/security/src/main/java/java/security/cert/CertificateNotYetValidException.java
index 221b22a..dd26bf8 100644
--- a/security/src/main/java/java/security/cert/CertificateNotYetValidException.java
+++ b/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/security/src/main/java/java/security/cert/CertificateParsingException.java b/security/src/main/java/java/security/cert/CertificateParsingException.java
index 2c75d20..4efd159 100644
--- a/security/src/main/java/java/security/cert/CertificateParsingException.java
+++ b/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/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java b/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java
index 23d8884..3c2fe1c 100644
--- a/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java
+++ b/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/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java b/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java
index 9145848..1d6542f 100644
--- a/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java
+++ b/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/security/src/main/java/java/security/cert/PKIXBuilderParameters.java b/security/src/main/java/java/security/cert/PKIXBuilderParameters.java
index a047a80..1a75063 100644
--- a/security/src/main/java/java/security/cert/PKIXBuilderParameters.java
+++ b/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/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java b/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
index 6064194..5a9fb2d 100644
--- a/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
+++ b/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/security/src/main/java/java/security/cert/PKIXCertPathChecker.java b/security/src/main/java/java/security/cert/PKIXCertPathChecker.java
index 5614878..5eaac74 100644
--- a/security/src/main/java/java/security/cert/PKIXCertPathChecker.java
+++ b/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,13 +50,12 @@
      * Clones this {@code PKIXCertPathChecker} instance.
      * 
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone() {
         try {
             return super.clone();
         } catch (CloneNotSupportedException e) {
-            throw new Error(e);
+            throw new AssertionError(e); // android-changed
         }
     }
 
@@ -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/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java b/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
index 21f90c9..d82c699 100644
--- a/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
+++ b/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,14 +94,12 @@
      * Clones this {@code PKIXCertPathValidatorResult} instance.
      * 
      * @return the cloned instance.
-     * @since Android 1.0
      */
     public Object clone() {
         try {
             return super.clone();
         } catch (CloneNotSupportedException e) {
-            // Actually, the exception will not be thrown out.
-            throw new Error(e);
+            throw new AssertionError(e); // android-changed
         }
     }
 
@@ -116,10 +109,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/security/src/main/java/java/security/cert/PKIXParameters.java b/security/src/main/java/java/security/cert/PKIXParameters.java
index 16b0686..79d3d5e 100644
--- a/security/src/main/java/java/security/cert/PKIXParameters.java
+++ b/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 {
@@ -587,7 +554,7 @@
             }
             return ret;
         } catch (CloneNotSupportedException e) {
-            throw new Error(e);
+            throw new AssertionError(e); // android-changed
         }
     }
 
@@ -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/security/src/main/java/java/security/cert/PolicyNode.java b/security/src/main/java/java/security/cert/PolicyNode.java
index c112a8a..c485b69 100644
--- a/security/src/main/java/java/security/cert/PolicyNode.java
+++ b/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/security/src/main/java/java/security/cert/PolicyQualifierInfo.java b/security/src/main/java/java/security/cert/PolicyQualifierInfo.java
index 5a63d51..903a6e9 100644
--- a/security/src/main/java/java/security/cert/PolicyQualifierInfo.java
+++ b/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/security/src/main/java/java/security/cert/TrustAnchor.java b/security/src/main/java/java/security/cert/TrustAnchor.java
index 9dc2025..eae38d6 100644
--- a/security/src/main/java/java/security/cert/TrustAnchor.java
+++ b/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/security/src/main/java/java/security/cert/X509CRL.java b/security/src/main/java/java/security/cert/X509CRL.java
index eabdb68..cb99843 100644
--- a/security/src/main/java/java/security/cert/X509CRL.java
+++ b/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/security/src/main/java/java/security/cert/X509CRLEntry.java b/security/src/main/java/java/security/cert/X509CRLEntry.java
index 35fb78b..ccdaf2f 100644
--- a/security/src/main/java/java/security/cert/X509CRLEntry.java
+++ b/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/security/src/main/java/java/security/cert/X509CRLSelector.java b/security/src/main/java/java/security/cert/X509CRLSelector.java
index c1b5f45..0edddf4 100644
--- a/security/src/main/java/java/security/cert/X509CRLSelector.java
+++ b/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/security/src/main/java/java/security/cert/X509CertSelector.java b/security/src/main/java/java/security/cert/X509CertSelector.java
index c6d2e98..e2de95b 100644
--- a/security/src/main/java/java/security/cert/X509CertSelector.java
+++ b/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/security/src/main/java/java/security/cert/X509Certificate.java b/security/src/main/java/java/security/cert/X509Certificate.java
index 9e10077..e49901c 100644
--- a/security/src/main/java/java/security/cert/X509Certificate.java
+++ b/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/security/src/main/java/java/security/cert/X509Extension.java b/security/src/main/java/java/security/cert/X509Extension.java
index cc8648b..1543f3d 100644
--- a/security/src/main/java/java/security/cert/X509Extension.java
+++ b/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/security/src/main/java/java/security/interfaces/DSAKey.java b/security/src/main/java/java/security/interfaces/DSAKey.java
index 1362bff..ac9aade 100644
--- a/security/src/main/java/java/security/interfaces/DSAKey.java
+++ b/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/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java b/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
index 4b89c6a..b7b5480 100644
--- a/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
+++ b/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/security/src/main/java/java/security/interfaces/DSAParams.java b/security/src/main/java/java/security/interfaces/DSAParams.java
index 0483da2..62f2d00 100644
--- a/security/src/main/java/java/security/interfaces/DSAParams.java
+++ b/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/security/src/main/java/java/security/interfaces/DSAPrivateKey.java b/security/src/main/java/java/security/interfaces/DSAPrivateKey.java
index e2592ca..6419440 100644
--- a/security/src/main/java/java/security/interfaces/DSAPrivateKey.java
+++ b/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/security/src/main/java/java/security/interfaces/DSAPublicKey.java b/security/src/main/java/java/security/interfaces/DSAPublicKey.java
index ccb985e..9642bf1 100644
--- a/security/src/main/java/java/security/interfaces/DSAPublicKey.java
+++ b/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/security/src/main/java/java/security/interfaces/ECKey.java b/security/src/main/java/java/security/interfaces/ECKey.java
index 9f5d254..5469392 100644
--- a/security/src/main/java/java/security/interfaces/ECKey.java
+++ b/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/security/src/main/java/java/security/interfaces/ECPrivateKey.java b/security/src/main/java/java/security/interfaces/ECPrivateKey.java
index 74ef4c2..254d2a6 100644
--- a/security/src/main/java/java/security/interfaces/ECPrivateKey.java
+++ b/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/security/src/main/java/java/security/interfaces/ECPublicKey.java b/security/src/main/java/java/security/interfaces/ECPublicKey.java
index 063dfe9..8ad97fc 100644
--- a/security/src/main/java/java/security/interfaces/ECPublicKey.java
+++ b/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/security/src/main/java/java/security/interfaces/RSAKey.java b/security/src/main/java/java/security/interfaces/RSAKey.java
index bc0877e..2c9e6c1 100644
--- a/security/src/main/java/java/security/interfaces/RSAKey.java
+++ b/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/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java b/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
index c5e86c3..d8aa1bf 100644
--- a/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
+++ b/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/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java b/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
index 48d70ce..a670491 100644
--- a/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
+++ b/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/security/src/main/java/java/security/interfaces/RSAPrivateKey.java b/security/src/main/java/java/security/interfaces/RSAPrivateKey.java
index 041a1e3..0da15e9 100644
--- a/security/src/main/java/java/security/interfaces/RSAPrivateKey.java
+++ b/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/security/src/main/java/java/security/interfaces/RSAPublicKey.java b/security/src/main/java/java/security/interfaces/RSAPublicKey.java
index b13b1aa..379351f 100644
--- a/security/src/main/java/java/security/interfaces/RSAPublicKey.java
+++ b/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/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java b/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java
index 32c7a3a..0cbba76 100644
--- a/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java
+++ b/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/security/src/main/java/java/security/spec/DSAParameterSpec.java b/security/src/main/java/java/security/spec/DSAParameterSpec.java
index 5465b5b..e23a682 100644
--- a/security/src/main/java/java/security/spec/DSAParameterSpec.java
+++ b/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/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java b/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java
index 3b692c8..6dc12c8 100644
--- a/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java
+++ b/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/security/src/main/java/java/security/spec/DSAPublicKeySpec.java b/security/src/main/java/java/security/spec/DSAPublicKeySpec.java
index 95d1141..af90919 100644
--- a/security/src/main/java/java/security/spec/DSAPublicKeySpec.java
+++ b/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/security/src/main/java/java/security/spec/ECField.java b/security/src/main/java/java/security/spec/ECField.java
index 74a5eb8..b4c6be2 100644
--- a/security/src/main/java/java/security/spec/ECField.java
+++ b/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/security/src/main/java/java/security/spec/ECFieldF2m.java b/security/src/main/java/java/security/spec/ECFieldF2m.java
index d68378b..e5a636a 100644
--- a/security/src/main/java/java/security/spec/ECFieldF2m.java
+++ b/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/security/src/main/java/java/security/spec/ECFieldFp.java b/security/src/main/java/java/security/spec/ECFieldFp.java
index d3f4ee6..b68238d 100644
--- a/security/src/main/java/java/security/spec/ECFieldFp.java
+++ b/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/security/src/main/java/java/security/spec/ECGenParameterSpec.java b/security/src/main/java/java/security/spec/ECGenParameterSpec.java
index 210b315..de4cd04 100644
--- a/security/src/main/java/java/security/spec/ECGenParameterSpec.java
+++ b/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/security/src/main/java/java/security/spec/ECParameterSpec.java b/security/src/main/java/java/security/spec/ECParameterSpec.java
index e10757b..a1985db 100644
--- a/security/src/main/java/java/security/spec/ECParameterSpec.java
+++ b/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/security/src/main/java/java/security/spec/ECPoint.java b/security/src/main/java/java/security/spec/ECPoint.java
index 3aba6c7..0751757 100644
--- a/security/src/main/java/java/security/spec/ECPoint.java
+++ b/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/security/src/main/java/java/security/spec/ECPrivateKeySpec.java b/security/src/main/java/java/security/spec/ECPrivateKeySpec.java
index de778fd..1ddfec3 100644
--- a/security/src/main/java/java/security/spec/ECPrivateKeySpec.java
+++ b/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/security/src/main/java/java/security/spec/ECPublicKeySpec.java b/security/src/main/java/java/security/spec/ECPublicKeySpec.java
index da182b5..0c88590 100644
--- a/security/src/main/java/java/security/spec/ECPublicKeySpec.java
+++ b/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/security/src/main/java/java/security/spec/EllipticCurve.java b/security/src/main/java/java/security/spec/EllipticCurve.java
index 3ab2921..45ff042 100644
--- a/security/src/main/java/java/security/spec/EllipticCurve.java
+++ b/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/security/src/main/java/java/security/spec/EncodedKeySpec.java b/security/src/main/java/java/security/spec/EncodedKeySpec.java
index f199bca..d34794c 100644
--- a/security/src/main/java/java/security/spec/EncodedKeySpec.java
+++ b/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/security/src/main/java/java/security/spec/InvalidKeySpecException.java b/security/src/main/java/java/security/spec/InvalidKeySpecException.java
index a83e984..4ae5877 100644
--- a/security/src/main/java/java/security/spec/InvalidKeySpecException.java
+++ b/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/security/src/main/java/java/security/spec/InvalidParameterSpecException.java b/security/src/main/java/java/security/spec/InvalidParameterSpecException.java
index 668fda5..e308dd8 100644
--- a/security/src/main/java/java/security/spec/InvalidParameterSpecException.java
+++ b/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/security/src/main/java/java/security/spec/KeySpec.java b/security/src/main/java/java/security/spec/KeySpec.java
index 350a7eb..fe8df1d 100644
--- a/security/src/main/java/java/security/spec/KeySpec.java
+++ b/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/security/src/main/java/java/security/spec/MGF1ParameterSpec.java b/security/src/main/java/java/security/spec/MGF1ParameterSpec.java
index a40f0b3..6475d90 100644
--- a/security/src/main/java/java/security/spec/MGF1ParameterSpec.java
+++ b/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/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java b/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java
index 5cb67b8..6910789 100644
--- a/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java
+++ b/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/security/src/main/java/java/security/spec/PSSParameterSpec.java b/security/src/main/java/java/security/spec/PSSParameterSpec.java
index c6a5bc5..06c1d05 100644
--- a/security/src/main/java/java/security/spec/PSSParameterSpec.java
+++ b/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/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java b/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java
index 06f3498..2377c75 100644
--- a/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java
+++ b/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/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java b/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
index 93e3193..28469d7 100644
--- a/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
+++ b/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/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java b/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java
index 9b4828e..177ddf5 100644
--- a/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java
+++ b/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/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java b/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java
index 1157099..e786e9e 100644
--- a/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java
+++ b/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/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java b/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java
index bd7d4e8..c94420e 100644
--- a/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java
+++ b/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/security/src/main/java/java/security/spec/RSAPublicKeySpec.java b/security/src/main/java/java/security/spec/RSAPublicKeySpec.java
index bd4c5b5..fe6de07 100644
--- a/security/src/main/java/java/security/spec/RSAPublicKeySpec.java
+++ b/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/security/src/main/java/java/security/spec/X509EncodedKeySpec.java b/security/src/main/java/java/security/spec/X509EncodedKeySpec.java
index 6cc6104..61f3475 100644
--- a/security/src/main/java/java/security/spec/X509EncodedKeySpec.java
+++ b/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/security/src/main/java/javax/security/cert/Certificate.java b/security/src/main/java/javax/security/cert/Certificate.java
index fb00789..ef513a3 100644
--- a/security/src/main/java/javax/security/cert/Certificate.java
+++ b/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/security/src/main/java/javax/security/cert/CertificateEncodingException.java b/security/src/main/java/javax/security/cert/CertificateEncodingException.java
index 4091695..780e43f 100644
--- a/security/src/main/java/javax/security/cert/CertificateEncodingException.java
+++ b/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/security/src/main/java/javax/security/cert/CertificateException.java b/security/src/main/java/javax/security/cert/CertificateException.java
index f186e51..fd2a614 100644
--- a/security/src/main/java/javax/security/cert/CertificateException.java
+++ b/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/security/src/main/java/javax/security/cert/CertificateExpiredException.java b/security/src/main/java/javax/security/cert/CertificateExpiredException.java
index 62870a6..94e6558 100644
--- a/security/src/main/java/javax/security/cert/CertificateExpiredException.java
+++ b/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/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java b/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java
index 6f32945..8fe0a33 100644
--- a/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java
+++ b/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/security/src/main/java/javax/security/cert/CertificateParsingException.java b/security/src/main/java/javax/security/cert/CertificateParsingException.java
index 9b208e6..48986c0 100644
--- a/security/src/main/java/javax/security/cert/CertificateParsingException.java
+++ b/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/security/src/main/java/javax/security/cert/X509Certificate.java b/security/src/main/java/javax/security/cert/X509Certificate.java
index 77bffae..8877386 100644
--- a/security/src/main/java/javax/security/cert/X509Certificate.java
+++ b/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/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java b/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java
index ba3229b..afab96e 100644
--- a/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java
+++ b/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/security/src/main/java/org/apache/harmony/security/PolicyEntry.java b/security/src/main/java/org/apache/harmony/security/PolicyEntry.java
index 4c7aa5b..0037ad6 100644
--- a/security/src/main/java/org/apache/harmony/security/PolicyEntry.java
+++ b/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/security/src/main/java/org/apache/harmony/security/Util.java b/security/src/main/java/org/apache/harmony/security/Util.java
new file mode 100644
index 0000000..e6e764f
--- /dev/null
+++ b/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/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java b/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java
index 1f5534d..e8db789 100644
--- a/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java
+++ b/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/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java b/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
index 4ec103b..4908afb 100644
--- a/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
+++ b/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/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java b/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java
index 6292870..960dc0f 100644
--- a/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java
+++ b/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/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java b/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
index 55f48fa..0bc4b8a 100644
--- a/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
+++ b/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/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java b/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
index 0dd7ae4..3d2cb3e 100644
--- a/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
+++ b/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/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java b/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java
index 68819b8..531d760 100644
--- a/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java
+++ b/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/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java b/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java
index 2a267e5..06ada53 100644
--- a/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java
+++ b/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/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java b/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java
index 0e7269a..0d3a77a 100644
--- a/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java
+++ b/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/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java b/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java
index 2aa474e..df425a4 100644
--- a/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java
+++ b/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/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java b/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java
index fafa66c..c809fe4 100644
--- a/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java
+++ b/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/security/src/main/java/org/apache/harmony/security/fortress/Engine.java b/security/src/main/java/org/apache/harmony/security/fortress/Engine.java
index 3b6f5d5..19fed41 100644
--- a/security/src/main/java/org/apache/harmony/security/fortress/Engine.java
+++ b/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/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java b/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java
index eda7327..b4e0e6a 100644
--- a/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java
+++ b/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/security/src/main/java/org/apache/harmony/security/fortress/Services.java b/security/src/main/java/org/apache/harmony/security/fortress/Services.java
index 300854a..60d9edd 100644
--- a/security/src/main/java/org/apache/harmony/security/fortress/Services.java
+++ b/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/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java b/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java
index 7c57e93..2f31131 100644
--- a/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java
+++ b/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/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java b/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java
index 0249055..2c129e2 100644
--- a/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java
+++ b/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/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java b/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java
index 718d3d3..2f9e99d 100644
--- a/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java
+++ b/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/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java b/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
index 05a0c7a..9235577 100644
--- a/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
+++ b/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/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java b/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java
index d53eb8a..7414e75 100644
--- a/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java
+++ b/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/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java b/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
index 17fd6f7..f0e47d9 100644
--- a/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
+++ b/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/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java b/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java
index 2234ce4..83b9944 100644
--- a/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java
+++ b/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/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java b/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java
index af314ef..42d3043 100644
--- a/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java
+++ b/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/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java b/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java
index 17af038..291d69e 100644
--- a/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java
+++ b/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/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java b/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java
index bd1efdd..f4bb13d 100644
--- a/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java
+++ b/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/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java b/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
index 14db652..e3fde7f 100644
--- a/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
+++ b/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/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java b/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
index 6e9ecb8..7294361 100644
--- a/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
+++ b/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/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java b/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java
index 576ac76..b7b9c98 100644
--- a/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java
+++ b/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/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java b/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
index f1f5bce..bc84c01 100644
--- a/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
+++ b/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/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java b/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java
index 517e096..2a19656 100644
--- a/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java b/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
index 34337eb..63434893 100644
--- a/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java b/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java
index 8844035..30d71e7 100644
--- a/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java b/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
index 51f9725..0844c5e 100644
--- a/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x501/Name.java b/security/src/main/java/org/apache/harmony/security/x501/Name.java
index 836342e..ae08671 100644
--- a/security/src/main/java/org/apache/harmony/security/x501/Name.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java b/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java
index bc8fd28..69b9258 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java b/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java
index 70dba99..728fd6a 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java b/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java
index 1cf9c3e..3de59fb 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java b/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java
index 10b3156..edbf13e 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java b/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java
index 85cbea0..db2480e 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java b/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java
index 3a31734..d6ab760 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/DNParser.java b/security/src/main/java/org/apache/harmony/security/x509/DNParser.java
index 730f7df..5870bcd 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/DNParser.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java b/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java
index 69e9cee..4eacbd5 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/Extension.java b/security/src/main/java/org/apache/harmony/security/x509/Extension.java
index 833f2fe..86e7a45 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/Extension.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/Extensions.java b/security/src/main/java/org/apache/harmony/security/x509/Extensions.java
index e98a116..1fee6c0 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/Extensions.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java b/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java
index db4daaa..3b291a1 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java b/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java
index 7323124..ce5404e 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java b/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java
index bc04caf..b01fa45 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java b/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java
index aec57c3..102fe05 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java b/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java
index 26b4acc..de3505d 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java b/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java
index 6f72dc7..842784f 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java b/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java
index 597ca59..6b04d55 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java b/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java
index 336a60d..b0b75a6 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java b/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java
index 4c9454e..f2aa0ee 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java b/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java
index 117ae27..5e4e6ff 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java
+++ b/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/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java b/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java
index ea50a2d44..af03ea5 100644
--- a/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java
index bbbe861..13ac904 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java
index 2803251..089a7db 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java
index c70bc57..fa94fbf 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestException2Test.java
deleted file mode 100644
index 544e618..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java
index 69a73a3..93ffe77 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
index 8309c87..ca80f19 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/GeneralSecurityException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/GeneralSecurityException2Test.java
deleted file mode 100644
index 3647115..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
index 55e2fd2..865bbea 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidAlgorithmParameterException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidAlgorithmParameterException2Test.java
deleted file mode 100644
index dafdb38..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidKeyException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidKeyException2Test.java
deleted file mode 100644
index bbe9e08..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidParameterException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidParameterException2Test.java
deleted file mode 100644
index 4830731..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyException2Test.java
deleted file mode 100644
index 1c7b71f..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyManagementException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyManagementException2Test.java
deleted file mode 100644
index c30370a..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java
index 817de35..059cef4 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreException2Test.java
deleted file mode 100644
index b3c9583..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStorePrivateKeyEntryTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStorePrivateKeyEntryTest.java
new file mode 100644
index 0000000..42feeec
--- /dev/null
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java
index d7ae43f..210116e 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
index c26708d..9eca936 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java
index b7c11e5..8bcb392 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchAlgorithmException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchAlgorithmException2Test.java
deleted file mode 100644
index 289047b..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchProviderException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchProviderException2Test.java
deleted file mode 100644
index 256ed66..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java
index af33804..a60adbf 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java
index 78038b5..ce57328 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java
+++ b/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java
@@ -31,6 +31,7 @@
 
 import org.apache.harmony.security.tests.support.SecurityChecker;
 import org.apache.harmony.security.tests.support.TestUtils;
+import tests.util.TestEnvironment;
 
 import java.io.File;
 import java.io.FilePermission;
@@ -60,6 +61,11 @@
         junit.textui.TestRunner.run(PolicyTest.class);
     }
 
+    @Override protected void tearDown() throws Exception {
+        TestEnvironment.reset();
+        super.tearDown();
+    }
+
     /**
      * @tests constructor Policy()
      */
@@ -395,7 +401,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 +410,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/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java
index 48e8f32..a8ec69a 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderException2Test.java
deleted file mode 100644
index 4b0f2ec..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java
index c93011c..730e329 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java
index a3b3077..3cc447f 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java
index 49a0365..a59ada5 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java
index c03afc5..aa4c71b 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
index 20bc4b1..a657f60 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/SignatureException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/SignatureException2Test.java
deleted file mode 100644
index 9a6209a..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java
index 77f341b..89d872e 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java
index c3414f4..1015521 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java
+++ b/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/security/src/test/java/org/apache/harmony/security/tests/java/security/UnrecoverableKeyException2Test.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/UnrecoverableKeyException2Test.java
deleted file mode 100644
index ce97d60..0000000
--- a/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/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java b/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java
index ce02e9d..d03b43d 100644
--- a/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java
+++ b/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/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java b/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java
index f36f119..267923a 100644
--- a/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java
+++ b/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/security/src/test/java/tests/security/permissions/JavaLangSystemTest.java b/security/src/test/java/tests/security/permissions/JavaLangSystemTest.java
index d1bf7c2..b9217a1 100644
--- a/security/src/test/java/tests/security/permissions/JavaLangSystemTest.java
+++ b/security/src/test/java/tests/security/permissions/JavaLangSystemTest.java
@@ -22,6 +22,7 @@
 import dalvik.annotation.TestTargetClass;
 
 import junit.framework.TestCase;
+import tests.util.TestEnvironment;
 
 import java.io.InputStream;
 import java.io.PrintStream;
@@ -46,6 +47,7 @@
 
     @Override
     protected void tearDown() throws Exception {
+        TestEnvironment.reset();
         System.setSecurityManager(old);
         super.tearDown();
     }
diff --git a/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser b/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
index 2937f2f..931ee3f 100755
--- a/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
+++ b/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
Binary files differ
diff --git a/sql/src/main/native/sqlite_jni.c b/sql/src/main/native/sqlite_jni.c
index 4923869..341ef2e 100644
--- a/sql/src/main/native/sqlite_jni.c
+++ b/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,14 @@
     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);
+        if (!dest->tofree) {
+            throwoom(env, "string translation failed");
+            return dest->result;
+        }
+        (*env)->GetStringUTFRegion(env, src, 0, utfLength, dest->result);
+        return dest->result;
     }
     if (enc) {
 	bytes = (*env)->CallObjectMethod(env, src,
@@ -418,6 +403,7 @@
 					    "(Ljava/lang/String;I)Z");
 
 	if (mid == 0) {
+	    (*env)->DeleteLocalRef(env, cls);
 	    return ret;
 	}
 	trans2utf(env, h->haveutf, h->enc, table, &tabstr);
@@ -425,6 +411,7 @@
 					(jint) count)
 	      != JNI_FALSE;
 	(*env)->DeleteLocalRef(env, tabstr.jstr);
+	(*env)->DeleteLocalRef(env, cls);
     }
     return ret;
 }
@@ -444,10 +431,12 @@
 					    "(Ljava/lang/String;I)Z");
 
 	if (mid == 0) {
+	    (*env)->DeleteLocalRef(env, cls);
 	    return ret;
 	}
 	ret = (*env)->CallBooleanMethod(env, h->bh, mid, 0, (jint) count)
 	    != JNI_FALSE;
+	(*env)->DeleteLocalRef(env, cls);
     }
     return ret;
 }
@@ -465,9 +454,11 @@
 	jmethodID mid = (*env)->GetMethodID(env, cls, "progress", "()Z");
 
 	if (mid == 0) {
+	    (*env)->DeleteLocalRef(env, cls);
 	    return ret;
 	}
 	ret = (*env)->CallBooleanMethod(env, h->ph, mid) != JNI_TRUE;
+	(*env)->DeleteLocalRef(env, cls);
     }
     return ret;
 }
@@ -1331,11 +1322,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;
@@ -1611,6 +1601,7 @@
 	int i;
 
 	if (mid == 0) {
+	    (*env)->DeleteLocalRef(env, cls);
 	    return;
 	}
 	arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0);
@@ -1659,6 +1650,7 @@
 	jmethodID mid = (*env)->GetMethodID(env, cls, "last_step",
 					    "(LSQLite/FunctionContext;)V");
 	if (mid == 0) {
+	    (*env)->DeleteLocalRef(env, cls);
 	    return;
 	}
 	f->sf = sf;
@@ -1685,6 +1677,7 @@
 	int i;
 
 	if (mid == 0) {
+	    (*env)->DeleteLocalRef(env, cls);
 	    return;
 	}
 	arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0);
@@ -1734,6 +1727,7 @@
 	jmethodID mid = (*env)->GetMethodID(env, cls, "last_step",
 					    "(LSQLite/FunctionContext;)V");
 	if (mid == 0) {
+	    (*env)->DeleteLocalRef(env, cls);
 	    return;
 	}
 	f->sf = sf;
@@ -3009,10 +3003,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 +3394,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 +3667,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/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
index 68ac6c5..d53f078 100644
--- a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
+++ b/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,12 @@
 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;
+import tests.util.TestEnvironment;
+
 @TestTargetClass(DriverManager.class)
 /**
  * JUnit Testcase for the java.sql.DriverManager class
@@ -77,6 +78,7 @@
     // test methods as needed.
     @Override
     public void setUp() {
+        TestEnvironment.reset();
         numberLoaded = loadDrivers();
     } // end setUp()
 
@@ -715,10 +717,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/sql/src/test/java/tests/java/sql/StressTest.java b/sql/src/test/java/tests/java/sql/StressTest.java
index 555ad03..b6d13c1 100755
--- a/sql/src/test/java/tests/java/sql/StressTest.java
+++ b/sql/src/test/java/tests/java/sql/StressTest.java
@@ -16,8 +16,8 @@
 
 package tests.java.sql;
 
+import dalvik.annotation.BrokenTest;
 import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetNew;
 
@@ -30,7 +30,6 @@
 import java.sql.Statement;
 import java.util.Properties;
 import java.util.Vector;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import tests.support.DatabaseCreator;
diff --git a/support/src/test/java/org/apache/harmony/security/tests/support/cert/MyCertStoreParameters.java b/support/src/test/java/org/apache/harmony/security/tests/support/cert/MyCertStoreParameters.java
index 6518c6f..1166b41 100644
--- a/support/src/test/java/org/apache/harmony/security/tests/support/cert/MyCertStoreParameters.java
+++ b/support/src/test/java/org/apache/harmony/security/tests/support/cert/MyCertStoreParameters.java
@@ -37,7 +37,7 @@
         try {
             return super.clone();
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 }
diff --git a/support/src/test/java/tests/support/Support_Exec.java b/support/src/test/java/tests/support/Support_Exec.java
index c3a5ccc..2e709a5 100644
--- a/support/src/test/java/tests/support/Support_Exec.java
+++ b/support/src/test/java/tests/support/Support_Exec.java
@@ -17,204 +17,136 @@
 
 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();
-                    }
+    /**
+     * Starts the process described by 'builder', and asserts that it sees
+     * 'expectedOut' on stdout and 'expectedErr' on stderr. Times out after
+     * 10s.
+     */
+    public static void execAndCheckOutput(ProcessBuilder builder,
+            String expectedOut, String expectedErr) throws Exception {
+        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()));
+            assertEquals(expectedOut, outFuture.get(10, TimeUnit.SECONDS));
+            assertEquals(expectedErr, errFuture.get(10, TimeUnit.SECONDS));
+        } finally {
+            executorService.shutdown();
+            process.waitFor();
+        }
+    }
 
-                    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/support/src/test/java/tests/support/Support_TestWebServer.java b/support/src/test/java/tests/support/Support_TestWebServer.java
index 609e993..8c88cc0 100644
--- a/support/src/test/java/tests/support/Support_TestWebServer.java
+++ b/support/src/test/java/tests/support/Support_TestWebServer.java
@@ -39,22 +39,13 @@
     /* The ANDROID_LOG_TAG */
     private final static String LOGTAG = "httpsv";
 
-    /* Where worker threads stand idle */
-    Vector threads = new Vector();
-
     /** maps the recently requested URLs to the full request snapshot */
     private final Map<String, Request> pathToRequest
             = new ConcurrentHashMap<String, Request>();
 
-    /* List of all active worker threads */
-    Vector activeThreads = new Vector();
-
     /* timeout on client connections */
     int timeout = 0;
 
-    /* max # worker threads */
-    int workers = 5;
-
     /* Default port for this server to listen on */
     final static int DEFAULT_PORT = 8080;
 
@@ -283,19 +274,7 @@
                         running = false;
                     }
 
-                    Worker w = null;
-                    synchronized (threads) {
-                        if (threads.isEmpty()) {
-                            Worker ws = new Worker();
-                            ws.setSocket(s);
-                            activeThreads.addElement(ws);
-                            (new Thread(ws, "additional worker")).start();
-                        } else {
-                            w = (Worker) threads.elementAt(0);
-                            threads.removeElementAt(0);
-                            w.setSocket(s);
-                        }
-                    }
+                    new Thread(new Worker(s), "additional worker").start();
                 }
             } catch (SocketException e) {
                 log("SocketException in AcceptThread: probably closed during accept");
@@ -316,14 +295,6 @@
                    therefore the acceptLimit functionality has been added
                    to circumvent this limitation */
                 ss.close();
-
-                // Stop worker threads from continuing
-                for (Enumeration e = activeThreads.elements(); e.hasMoreElements();) {
-                    Worker w = (Worker)e.nextElement();
-                    w.close();
-                }
-                activeThreads.clear();
-
             } catch (IOException e) {
                 /* We are shutting down the server, so we expect
                  * things to die. Don't propagate.
@@ -393,75 +364,20 @@
         /* Indicates whether current request has any data content */
         private boolean hasContent = false;
 
-        boolean running = false;
-
         /* Request headers are stored here */
         private Map<String, String> headers = new LinkedHashMap<String, String>();
 
         /* Create a new worker thread */
-        Worker() {
-            buf = new byte[BUF_SIZE];
-            s = null;
-        }
-
-        /**
-         * Called by the AcceptThread to unblock this Worker to process
-         * a request.
-         * @param s The socket on which the connection has been made
-         */
-        synchronized void setSocket(Socket s) {
+        Worker(Socket s) {
+            this.buf = new byte[BUF_SIZE];
             this.s = s;
-            notify();
         }
 
-        /**
-         * Called by the accept thread when it's closing. Potentially unblocks
-         * the worker thread to terminate properly
-         */
-        synchronized void close() {
-            running = false;
-            notify();
-        }
-
-        /**
-         * Main worker thread. This will wait until a request has
-         * been identified by the accept thread upon which it will
-         * service the thread.
-         */
         public synchronized void run() {
-            running = true;
-            while(running) {
-                if (s == null) {
-                    /* nothing to do */
-                    try {
-                        log(this+" Moving to wait state");
-                        wait();
-                    } catch (InterruptedException e) {
-                        /* should not happen */
-                        continue;
-                    }
-                    if (!running) break;
-                }
-                try {
-                    handleClient();
-                } catch (Exception e) {
-                    log("Exception during handleClient in the TestWebServer: "
-                            + e.getMessage());
-                }
-                /* go back in wait queue if there's fewer
-                 * than numHandler connections.
-                 */
-                s = null;
-                Vector pool = threads;
-                synchronized (pool) {
-                    if (pool.size() >= workers) {
-                        /* too many threads, exit this one */
-                        activeThreads.remove(this);
-                        return;
-                    } else {
-                        pool.addElement(this);
-                    }
-                }
+            try {
+                handleClient();
+            } catch (Exception e) {
+                log("Exception during handleClient in the TestWebServer: " + e.getMessage());
             }
             log(this+" terminated");
         }
diff --git a/support/src/test/java/tests/support/ThrowingReader.java b/support/src/test/java/tests/support/ThrowingReader.java
new file mode 100644
index 0000000..fbefeb1
--- /dev/null
+++ b/support/src/test/java/tests/support/ThrowingReader.java
@@ -0,0 +1,64 @@
+/*
+ *  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 tests.support;
+
+import java.io.FilterReader;
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * A reader that always throws after a predetermined number of bytes have been
+ * read.
+ */
+public class ThrowingReader extends FilterReader {
+
+    private int total = 0;
+    private int throwAt;
+
+    public ThrowingReader(Reader in, int throwAt) {
+        super(in);
+        this.throwAt = throwAt;
+    }
+
+    @Override public int read() throws IOException {
+        explodeIfNecessary();
+        int result = super.read();
+        total++;
+        return result;
+    }
+
+    @Override public int read(char[] buf, int offset, int count)
+            throws IOException {
+        explodeIfNecessary();
+
+        if (total < throwAt) {
+            count = Math.min(count, (throwAt - total));
+        }
+
+        int returned = super.read(buf, offset, count);
+        total += returned;
+        return returned;
+    }
+
+    private void explodeIfNecessary() throws IOException {
+        if (total == throwAt) {
+            throwAt = Integer.MAX_VALUE;
+            throw new IOException();
+        }
+    }
+}
diff --git a/support/src/test/java/tests/util/PrefsTester.java b/support/src/test/java/tests/util/PrefsTester.java
deleted file mode 100644
index 047b357..0000000
--- a/support/src/test/java/tests/util/PrefsTester.java
+++ /dev/null
@@ -1,73 +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 tests.util;
-
-import java.util.prefs.BackingStoreException;
-import java.util.prefs.Preferences;
-import java.util.Arrays;
-
-/**
- * Prepares the shared preferences store for a test by wiping preference data
- * before and after the test. Sample usage:
- * <pre>
- * public void MyPreferencesTest extends TestCase {
- *     private final PrefsTester prefsTester = new PrefsTester();
- *
- *     public void setUp() throws BackingStoreException {
- *         super.setUp();
- *         prefsTester.setUp();
- *     }
- *
- *     public void tearDown() throws BackingStoreException {
- *         prefsTester.tearDown();
- *         super.tearDown();
- *     }
- *
- *     ...
- * }</pre>
- *
- * <p>Once the preferences classes have been initialized, the path where their
- * data is stored is fixed. For that reason, every test that reads or writes
- * preferences must first prepare preferences for testing by using this class.
- */
-public final class PrefsTester {
-
-    static {
-        String tmp = System.getProperty("java.io.tmpdir");
-        System.setProperty("user.home", tmp);
-        System.setProperty("java.home", tmp);
-    }
-
-    public void setUp() throws BackingStoreException {
-        clear();
-    }
-
-    public void tearDown() throws BackingStoreException {
-        clear();
-    }
-
-    private void clear() throws BackingStoreException {
-        for (Preferences root : Arrays .asList(
-                Preferences.systemRoot(), Preferences.userRoot())) {
-            for (String child : root.childrenNames()) {
-                root.node(child).removeNode();
-            }
-            root.clear();
-            root.flush();
-        }
-    }
-}
diff --git a/support/src/test/java/tests/util/TestEnvironment.java b/support/src/test/java/tests/util/TestEnvironment.java
new file mode 100644
index 0000000..92facda
--- /dev/null
+++ b/support/src/test/java/tests/util/TestEnvironment.java
@@ -0,0 +1,159 @@
+/*
+ * 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.util;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Properties;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+
+/**
+ * Prepares system properties and preferences to hygienic values for testing:
+ * <ul>
+ *   <li>System properties are set to reasonable defaults. Referenced
+ *       directories such as the user and Java home directories will be
+ *       writable.
+ *   <li>System and user preferences are cleared. Once the preferences classes
+ *       have been initialized, the path where their data is stored is fixed.
+ *       For this reason, every test that reads or writes preferences should
+ *       first reset the system configuration with this API.
+ * </ul>
+ *
+ * <p>Use this class to clean up before and/or after your test. Sample usage:
+ * <pre>
+ * public void MyTest extends TestCase {
+ *
+ *     protected void setUp() throws Exception {
+ *         super.setUp();
+ *         TestEnvironment().reset();
+ *     }
+ *
+ *     protected void tearDown() throws Exception {
+ *         TestEnvironment().reset();
+ *         super.tearDown();
+ *     }
+ *
+ *     ...
+ * }</pre>
+ */
+public final class TestEnvironment {
+    private TestEnvironment() {}
+
+    public static synchronized void reset() {
+        resetSystemProperties();
+        resetPreferences();
+
+        // TODO: TimeZone?, SecurityManager?
+    }
+
+    private static void resetSystemProperties() {
+        String tmpDir = System.getProperty("java.io.tmpdir");
+        if (tmpDir == null) {
+            throw new IllegalStateException("Test execution requires the"
+                    + " system property java.io.tmpdir to be set.");
+        }
+
+        Properties p = new Properties();
+
+        // runtime properties that we never want to clobber
+        copyProperty(p, "android.vm.dexfile");
+        copyProperty(p, "java.boot.class.path");
+        copyProperty(p, "java.class.path");
+        copyProperty(p, "java.io.tmpdir");
+        copyProperty(p, "java.library.path");
+        copyProperty(p, "os.arch");
+        copyProperty(p, "os.name");
+        copyProperty(p, "os.version");
+
+        // paths with writable values for testing
+        String userHome = tmpDir + "/user.home";
+        String javaHome = tmpDir + "/java.home";
+        String userDir = tmpDir + "/user.dir";
+        makeDirectory(new File(userHome));
+        makeDirectory(new File(javaHome));
+        makeDirectory(new File(userDir));
+        p.put("java.home", javaHome);
+        p.put("user.dir", userDir);
+        p.put("user.home", userHome);
+
+        // hardcoded properties
+        p.put("file.encoding", "UTF-8");
+        p.put("file.separator", "/");
+        p.put("java.class.version", "46.0");
+        p.put("java.compiler", "");
+        p.put("java.ext.dirs", "");
+        p.put("java.net.preferIPv6Addresses", "true");
+        p.put("java.runtime.name", "Android Runtime");
+        p.put("java.runtime.version", "0.9");
+        p.put("java.specification.name", "Dalvik Core Library");
+        p.put("java.specification.vendor", "The Android Project");
+        p.put("java.specification.version", "0.9");
+        p.put("java.vendor", "The Android Project");
+        p.put("java.vendor.url", "http://www.android.com/");
+        p.put("java.version", "0");
+        p.put("java.vm.name", "Dalvik");
+        p.put("java.vm.specification.name", "Dalvik Virtual Machine Specification");
+        p.put("java.vm.specification.vendor", "The Android Project");
+        p.put("java.vm.specification.version", "0.9");
+        p.put("java.vm.vendor", "The Android Project");
+        p.put("java.vm.vendor.url", "http://www.android.com/");
+        p.put("java.vm.version", "1.2.0");
+        p.put("javax.net.ssl.trustStore", "/etc/security/cacerts.bks");
+        p.put("line.separator", "\n");
+        p.put("path.separator", ":");
+        p.put("user.language", "en");
+        p.put("user.name", "");
+        p.put("user.region", "US");
+
+        System.setProperties(p);
+    }
+
+    private static void copyProperty(Properties p, String key) {
+        p.put(key, System.getProperty(key));
+    }
+
+    private static void makeDirectory(File path) {
+        boolean success;
+        if (!path.exists()) {
+            success = path.mkdirs();
+        } else if (!path.isDirectory()) {
+            success = path.delete() && path.mkdirs();
+        } else {
+            success = true;
+        }
+
+        if (!success) {
+            throw new RuntimeException("Failed to make directory " + path);
+        }
+    }
+
+    private static void resetPreferences() {
+        try {
+            for (Preferences root : Arrays.asList(
+                    Preferences.systemRoot(), Preferences.userRoot())) {
+                for (String child : root.childrenNames()) {
+                    root.node(child).removeNode();
+                }
+                root.clear();
+                root.flush();
+            }
+        } catch (BackingStoreException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/text/src/main/java/java/text/AttributedString.java b/text/src/main/java/java/text/AttributedString.java
index 77bbf78..fe7aa0c 100644
--- a/text/src/main/java/java/text/AttributedString.java
+++ b/text/src/main/java/java/text/AttributedString.java
@@ -107,7 +107,7 @@
                 }
                 return clone;
             } catch (CloneNotSupportedException e) {
-                return null;
+                throw new AssertionError(e); // android-changed
             }
         }
 
diff --git a/text/src/main/java/java/text/BreakIterator.java b/text/src/main/java/java/text/BreakIterator.java
index 7d19179..78870f0 100644
--- a/text/src/main/java/java/text/BreakIterator.java
+++ b/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.
@@ -522,7 +524,7 @@
             cloned.wrapped = (com.ibm.icu4jni.text.BreakIterator) wrapped.clone();
             return cloned;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError(e.getMessage());
+            throw new AssertionError(e); // android-changed
         }
     }
 
@@ -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/text/src/main/java/java/text/Collator.java b/text/src/main/java/java/text/Collator.java
index aaa3e12..e954b8b 100644
--- a/text/src/main/java/java/text/Collator.java
+++ b/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);
@@ -208,7 +211,7 @@
             clone.icuColl = (com.ibm.icu4jni.text.Collator) this.icuColl.clone();
             return clone;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/text/src/main/java/java/text/DateFormat.java b/text/src/main/java/java/text/DateFormat.java
index f39965a..531bed8 100644
--- a/text/src/main/java/java/text/DateFormat.java
+++ b/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/text/src/main/java/java/text/DecimalFormatSymbols.java b/text/src/main/java/java/text/DecimalFormatSymbols.java
index a71a4c6..46849ef 100644
--- a/text/src/main/java/java/text/DecimalFormatSymbols.java
+++ b/text/src/main/java/java/text/DecimalFormatSymbols.java
@@ -115,7 +115,7 @@
             symbols.patternChars = patternChars.clone();
             return symbols;
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/text/src/main/java/java/text/Format.java b/text/src/main/java/java/text/Format.java
index 6ee1ba2..8abe605 100644
--- a/text/src/main/java/java/text/Format.java
+++ b/text/src/main/java/java/text/Format.java
@@ -84,7 +84,7 @@
         try {
             return super.clone();
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
@@ -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/text/src/main/java/java/text/MessageFormat.java b/text/src/main/java/java/text/MessageFormat.java
index 4ab1ade..f6074b2 100644
--- a/text/src/main/java/java/text/MessageFormat.java
+++ b/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/text/src/main/java/java/text/NumberFormat.java b/text/src/main/java/java/text/NumberFormat.java
index 5b8d883..87f17c1 100644
--- a/text/src/main/java/java/text/NumberFormat.java
+++ b/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/text/src/main/java/java/text/StringCharacterIterator.java b/text/src/main/java/java/text/StringCharacterIterator.java
index 8ef0341..ea60180 100644
--- a/text/src/main/java/java/text/StringCharacterIterator.java
+++ b/text/src/main/java/java/text/StringCharacterIterator.java
@@ -105,7 +105,7 @@
         try {
             return super.clone();
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e); // android-changed
         }
     }
 
diff --git a/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties b/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties
index 22221a9..b80cde2 100644
--- a/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties
+++ b/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/text/src/test/java/org/apache/harmony/text/tests/java/text/CollationKeyTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/CollationKeyTest.java
index d1a7c42..c2135c3 100644
--- a/text/src/test/java/org/apache/harmony/text/tests/java/text/CollationKeyTest.java
+++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/CollationKeyTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.harmony.text.tests.java.text;
 
-import dalvik.annotation.KnownFailure;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
@@ -127,7 +126,6 @@
         method = "toByteArray",
         args = {}
     )
-    @KnownFailure("This test fails on Harmony ClassLibrary.")
     public void test_toByteArray() {
         // Test for method byte [] java.text.CollationKey.toByteArray()
         Collator collator = Collator.getInstance();
@@ -142,7 +140,6 @@
             fail("ParseException");
             return;
         }
-        bytes = collator.getCollationKey("1234567").toByteArray();
         /*
          * CollationElementIterator it =
          * ((RuleBasedCollator)collator).getCollationElementIterator("1234567");
@@ -152,8 +149,51 @@
          * i+=2) { System.out.print(Integer.toHexString(bytes[i]) +
          * Integer.toHexString(bytes[i+1]) + " "); } System.out.println();
          */
-        byte[] result = new byte[] { 0, 2, 0, 2, 0, 2, 0, 0, 0, 3, 0, 3, 0, 1,
-                0, 2, 0, 2, 0, 0, 0, 4, 0, 4, 0, 1, 0, 1, 0, 2 };
-        assertTrue("Wrong bytes", Arrays.equals(bytes, result));
+
+        // The RI has a different algorithm to generate the collation keys.
+        // bytes = collator.getCollationKey("1234567").toByteArray();
+        // byte[] result = new byte[] { 0, 2, 0, 2, 0, 2, 0, 0, 0, 3, 0, 3, 0, 1,
+        //         0, 2, 0, 2, 0, 0, 0, 4, 0, 4, 0, 1, 0, 1, 0, 2 };
+        byte[] bytes1 = collator.getCollationKey("12").toByteArray();
+        byte[] bytes2 = collator.getCollationKey("123").toByteArray();
+        byte[] bytes3 = collator.getCollationKey("124").toByteArray();
+        byte[] bytes4 = collator.getCollationKey("1245").toByteArray();
+        byte[] bytes5 = collator.getCollationKey("1245").toByteArray();
+
+        assertTrue("returned collation key does not sort correctly",
+                compareUnsignedByteArrays(bytes1, bytes2) < 0);
+
+        assertTrue("returned collation key does not sort correctly",
+                compareUnsignedByteArrays(bytes2, bytes3) < 0);
+
+        assertTrue("returned collation key does not sort correctly",
+                compareUnsignedByteArrays(bytes3, bytes4) < 0);
+
+        assertTrue("returned collation key does not sort correctly",
+                compareUnsignedByteArrays(bytes4, bytes5) == 0);
+
+    }
+
+    private int compareUnsignedByteArrays(byte[] bytes1, byte[] bytes2) {
+        int commonLength = Math.min(bytes1.length, bytes2.length);
+
+        for (int i = 0; i < commonLength; i++) {
+            int keyA = bytes1[i] & 0xFF;
+            int keyB = bytes2[i] & 0xFF;
+            if (keyA < keyB) {
+                return -1;
+            }
+            if (keyA > keyB) {
+                return 1;
+            }
+        }
+
+        if (bytes1.length < bytes2.length) {
+            return -1;
+        } else if (bytes1.length > bytes2.length) {
+            return 1;
+        } else {
+            return 0;
+        }
     }
 }
diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java
index e7609a8..e636a07 100644
--- a/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java
+++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java
@@ -182,7 +182,6 @@
         method = "getAvailableLocales",
         args = {}
     )
-    @KnownFailure("German locales were removed last minute in cupcake")
     public void test_getAvailableLocales() {
         Locale[] locales = DateFormat.getAvailableLocales();
         assertTrue("No locales", locales.length > 0);
diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java
index 47107cd..542ad7f 100644
--- a/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java
+++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java
@@ -146,7 +146,6 @@
         method = "getCurrency",
         args = {}
     )
-    @KnownFailure("some locales were removed last minute in cupcake")
     public void test_getCurrency() {
         Currency currency = Currency.getInstance("USD");
         assertEquals("Returned incorrect currency",
diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java
index aa36abc..edab40b 100644
--- a/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java
+++ b/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};
@@ -1807,7 +1830,6 @@
         method = "formatToCharacterIterator",
         args = {java.lang.Object.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_formatToCharacterIteratorLjava_lang_Object() {
 
         try {
@@ -2438,7 +2460,6 @@
         method = "!SerializationGolden",
         args = {}
     )
-    @KnownFailure("a regression. This didn't fail before")
     public void test_serializationHarmonyRICompatible() throws Exception {
         NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
 
@@ -2547,4 +2568,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/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java
index 0480704..d1246d3 100644
--- a/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java
+++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java
@@ -143,7 +143,6 @@
         method = "getIntegerInstance",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getIntegerInstanceLjava_util_Locale()
             throws ParseException {
         // Test for method java.text.NumberFormat
@@ -319,7 +318,6 @@
         method = "parseObject",
         args = {java.lang.String.class, java.text.ParsePosition.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_parseObjectLjava_lang_StringLjava_text_ParsePosition() {
         // regression test for HARMONY-1003
         assertNull(NumberFormat.getInstance().parseObject("0",
@@ -452,7 +450,6 @@
         method = "format",
         args = {double.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_formatLdouble() {
         // BEGIN android-changed
         NumberFormat nf1 = NumberFormat.getInstance(Locale.US);
@@ -492,7 +489,6 @@
         method = "format",
         args = {long.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_formatLlong() {
         // BEGIN android-changed
         NumberFormat nf1 = NumberFormat.getInstance(Locale.US);
@@ -591,7 +587,6 @@
         method = "getCurrencyInstance",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getCurrencyInstanceLjava_util_Locale() {
         // BEGIN android-changed
         Locale usLocale = Locale.US;
@@ -693,7 +688,6 @@
         method = "getInstance",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getInstanceLjava_util_Locale() {
         // BEGIN android-changed
         Locale.setDefault(Locale.US);
@@ -770,7 +764,6 @@
         method = "getNumberInstance",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getNumberInstanceLjava_util_Locale() {
         // BEGIN android-changed
         Locale.setDefault(Locale.US);
@@ -849,7 +842,6 @@
         method = "getPercentInstance",
         args = {java.util.Locale.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_getPercentInstanceLjava_util_Locale() {
         Locale.setDefault(Locale.US);
         NumberFormat format = NumberFormat.getPercentInstance(new Locale("cs",
@@ -1061,7 +1053,6 @@
         method = "setGroupingUsed",
         args = {boolean.class}
     )
-    @KnownFailure("Some locales were removed last minute in cupcake")
     public void test_setGroupingUsed() {
         NumberFormat nf1 = NumberFormat.getInstance(Locale.US);
         nf1.setGroupingUsed(false);
diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java
index 1c2da6a..3bcc38c 100644
--- a/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java
+++ b/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/tools/dalvik_jtreg/Android.mk b/tools/dalvik_jtreg/Android.mk
new file mode 100644
index 0000000..7da7212
--- /dev/null
+++ b/tools/dalvik_jtreg/Android.mk
@@ -0,0 +1,41 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+        java/dalvik/jtreg/Adb.java \
+        java/dalvik/jtreg/Command.java \
+        java/dalvik/jtreg/CommandFailedException.java \
+        java/dalvik/jtreg/Dx.java \
+        java/dalvik/jtreg/ExpectedResult.java \
+        java/dalvik/jtreg/Javac.java \
+        java/dalvik/jtreg/JtregRunner.java \
+        java/dalvik/jtreg/Result.java \
+        java/dalvik/jtreg/Strings.java \
+        java/dalvik/jtreg/TestRun.java \
+        java/dalvik/jtreg/TestDescriptions.java \
+        java/dalvik/jtreg/TestRunner.java \
+        java/dalvik/jtreg/TestToDex.java \
+        java/dalvik/jtreg/XmlReportPrinter.java \
+
+LOCAL_MODULE:= dalvik_jtreg
+LOCAL_STATIC_JAVA_LIBRARIES := javatest jh jtreg kxml2-2.3.0
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-subdir-makefiles)
+
+# prebuilt javatest.jar
+include $(CLEAR_VARS)
+LOCAL_PREBUILT_JAVA_LIBRARIES := javatest:lib/javatest.jar
+include $(BUILD_HOST_PREBUILT)
+
+# prebuilt jh.jar
+include $(CLEAR_VARS)
+LOCAL_PREBUILT_JAVA_LIBRARIES := jh:lib/jh.jar
+include $(BUILD_HOST_PREBUILT)
+
+# prebuilt jtreg.jar
+include $(CLEAR_VARS)
+LOCAL_PREBUILT_JAVA_LIBRARIES := jtreg:lib/jtreg.jar
+include $(BUILD_HOST_PREBUILT)
diff --git a/tools/dalvik_jtreg/expectations/java.util.Arrays.Big.expected b/tools/dalvik_jtreg/expectations/java.util.Arrays.Big.expected
new file mode 100644
index 0000000..4d1156b
--- /dev/null
+++ b/tools/dalvik_jtreg/expectations/java.util.Arrays.Big.expected
@@ -0,0 +1,2 @@
+result=COMPILE_FAILED
+pattern=.*cannot find symbol.*
\ No newline at end of file
diff --git a/tools/dalvik_jtreg/expectations/java.util.Arrays.CopyMethods.expected b/tools/dalvik_jtreg/expectations/java.util.Arrays.CopyMethods.expected
new file mode 100644
index 0000000..4d1156b
--- /dev/null
+++ b/tools/dalvik_jtreg/expectations/java.util.Arrays.CopyMethods.expected
@@ -0,0 +1,2 @@
+result=COMPILE_FAILED
+pattern=.*cannot find symbol.*
\ No newline at end of file
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/Adb.java b/tools/dalvik_jtreg/java/dalvik/jtreg/Adb.java
new file mode 100644
index 0000000..ef8508e
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/Adb.java
@@ -0,0 +1,43 @@
+/*
+ * 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 dalvik.jtreg;
+
+import java.io.File;
+
+/**
+ * An adb command.
+ */
+final class Adb {
+
+    public void mkdir(File name) {
+        new Command("adb", "shell", "mkdir", name.toString()).execute();
+    }
+
+    public void rm(File name) {
+        new Command("adb", "shell", "rm", "-r", name.toString()).execute();
+    }
+
+    public void push(File local, File remote) {
+        new Command("adb", "push", local.toString(), remote.toString())
+                .execute();
+    }
+
+    public void forwardTcp(int localPort, int devicePort) {
+        new Command("adb", "forward", "tcp:" + localPort, "tcp:" + devicePort)
+                .execute();
+    }
+}
\ No newline at end of file
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/Command.java b/tools/dalvik_jtreg/java/dalvik/jtreg/Command.java
new file mode 100644
index 0000000..9682a18
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/Command.java
@@ -0,0 +1,140 @@
+/*
+ * 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 dalvik.jtreg;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * An out of process executable.
+ */
+final class Command {
+
+    private final List<String> args;
+    private final boolean permitNonZeroExitStatus;
+    private Process process;
+
+    Command(String... args) {
+        this(Arrays.asList(args));
+    }
+
+    Command(List<String> args) {
+        this.args = new ArrayList<String>(args);
+        this.permitNonZeroExitStatus = false;
+    }
+
+    private Command(Builder builder) {
+        this.args = new ArrayList<String>(builder.args);
+        this.permitNonZeroExitStatus = builder.permitNonZeroExitStatus;
+    }
+
+    static String path(Object... objects) {
+        return Strings.join(objects, ":");
+    }
+
+    public synchronized void start() throws IOException {
+        if (isStarted()) {
+            throw new IllegalStateException("Already started!");
+        }
+
+        process = new ProcessBuilder()
+                .command(args)
+                .redirectErrorStream(true)
+                .start();
+    }
+
+    public boolean isStarted() {
+        return process != null;
+    }
+
+    public Process getProcess() {
+        if (!isStarted()) {
+            throw new IllegalStateException("Not started!");
+        }
+
+        return process;
+    }
+
+    public synchronized List<String> gatherOutput()
+            throws IOException, InterruptedException {
+        if (!isStarted()) {
+            throw new IllegalStateException("Not started!");
+        }
+
+        BufferedReader in = new BufferedReader(
+                new InputStreamReader(process.getInputStream()));
+        List<String> outputLines = new ArrayList<String>();
+        String outputLine;
+        while ((outputLine = in.readLine()) != null) {
+            outputLines.add(outputLine);
+        }
+
+        if (process.waitFor() != 0 && !permitNonZeroExitStatus) {
+            StringBuilder message = new StringBuilder();
+            for (String line : outputLines) {
+                message.append("\n").append(line);
+            }
+            throw new CommandFailedException(args, outputLines);
+        }
+
+        return outputLines;
+    }
+
+    public synchronized List<String> execute() {
+        try {
+            start();
+            return gatherOutput();
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to execute process: " + args, e);
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted while executing process: " + args, e);
+        }
+    }
+
+    static class Builder {
+        private final List<String> args = new ArrayList<String>();
+        private boolean permitNonZeroExitStatus = false;
+
+        public Builder args(String... args) {
+            return args(Arrays.asList(args));
+        }
+
+        public Builder args(Collection<String> args) {
+            this.args.addAll(args);
+            return this;
+        }
+
+        public Builder permitNonZeroExitStatus() {
+            permitNonZeroExitStatus = true;
+            return this;
+        }
+
+        public Command build() {
+            return new Command(this);
+        }
+
+        public List<String> execute() {
+            return build().execute();
+        }
+    }
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/CommandFailedException.java b/tools/dalvik_jtreg/java/dalvik/jtreg/CommandFailedException.java
new file mode 100644
index 0000000..ebbb42e
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/CommandFailedException.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.
+ */
+
+package dalvik.jtreg;
+
+import java.util.List;
+
+/**
+ * Thrown when an out of process executable does not return normally.
+ */
+class CommandFailedException extends RuntimeException {
+
+    private final List<String> args;
+    private final List<String> outputLines;
+
+    public CommandFailedException(List<String> args, List<String> outputLines) {
+        super("Command failed: " + args);
+        this.args = args;
+        this.outputLines = outputLines;
+    }
+
+    public List<String> getArgs() {
+        return args;
+    }
+
+    public List<String> getOutputLines() {
+        return outputLines;
+    }
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/Dx.java b/tools/dalvik_jtreg/java/dalvik/jtreg/Dx.java
new file mode 100644
index 0000000..21bcbbe
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/Dx.java
@@ -0,0 +1,34 @@
+/*
+ * 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 dalvik.jtreg;
+
+import java.io.File;
+
+/**
+ * A dx command.
+ */
+final class Dx {
+
+    public void dex(String output, File... inputs) {
+        new Command.Builder()
+                .args("dx")
+                .args("--dex")
+                .args("--output=" + output)
+                .args(Strings.objectsToStrings(inputs))
+                .execute();
+    }
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/ExpectedResult.java b/tools/dalvik_jtreg/java/dalvik/jtreg/ExpectedResult.java
new file mode 100644
index 0000000..79ee36c
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/ExpectedResult.java
@@ -0,0 +1,87 @@
+/*
+ * 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 dalvik.jtreg;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * The expected outcome of a test execution. This is typically encoded in a
+ * properties file named by the test name and the {@code .expected} suffix; for
+ * example, {@code java.util.Arrays.CopyMethods.expected}.
+ */
+class ExpectedResult {
+
+    /**
+     * Property identifier for the test's expected result, such as {@code
+     * EXEC_FAILED}. This property is required.
+     */
+    static final String RESULT = "result";
+
+    /**
+     * Property identifier for a regular expression that is the expected output
+     * will match. This property is optional.
+     */
+    static final String PATTERN = "pattern";
+
+    /**
+     * The expectation of a general successful test run.
+     */
+    static final ExpectedResult SUCCESS = new ExpectedResult(
+            Result.SUCCESS, ".*");
+
+    private final Result result;
+    private final String pattern;
+
+    private ExpectedResult(File expectationFile) throws IOException {
+        Properties properties = new Properties();
+        FileInputStream in = new FileInputStream(expectationFile);
+        properties.load(in);
+        in.close();
+
+        result = Result.valueOf(properties.getProperty(RESULT));
+        pattern = properties.getProperty(PATTERN);
+    }
+
+    private ExpectedResult(Result result, String pattern) {
+        this.result = result;
+        this.pattern = pattern;
+    }
+
+    public Result getResult() {
+        return result;
+    }
+
+    public String getPattern() {
+        return pattern;
+    }
+
+    public static ExpectedResult forRun(Set<File> searchDirectories,
+            String qualifiedName) throws IOException {
+        for (File expectationDir : searchDirectories) {
+            File expectationFile = new File(expectationDir, qualifiedName + ".expected");
+            if (expectationFile.exists()) {
+                return new ExpectedResult(expectationFile);
+            }
+        }
+
+        return SUCCESS;
+    }
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/Javac.java b/tools/dalvik_jtreg/java/dalvik/jtreg/Javac.java
new file mode 100644
index 0000000..0808200
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/Javac.java
@@ -0,0 +1,57 @@
+/*
+ * 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 dalvik.jtreg;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * A javac command.
+ */
+final class Javac {
+
+    private final Command.Builder builder = new Command.Builder();
+
+    Javac() {
+        builder.args("javac", "-Xmaxerrs", "1");
+    }
+
+    public Javac bootClasspath(File... path) {
+        builder.args("-bootclasspath", Command.path((Object[]) path));
+        return this;
+    }
+
+    public Javac classpath(File... path) {
+        builder.args("-classpath", Command.path((Object[]) path));
+        return this;
+    }
+
+    public Javac sourcepath(File... path) {
+        builder.args("-sourcepath", Command.path((Object[]) path));
+        return this;
+    }
+
+    public Javac destination(File directory) {
+        builder.args("-d", directory.toString());
+        return this;
+    }
+
+    public List<String> compile(File... files) {
+        return builder.args(Strings.objectsToStrings(files))
+                .execute();
+    }
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/JtregRunner.java b/tools/dalvik_jtreg/java/dalvik/jtreg/JtregRunner.java
new file mode 100644
index 0000000..bfe2908
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/JtregRunner.java
@@ -0,0 +1,361 @@
+/*
+ * 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 dalvik.jtreg;
+
+import com.sun.javatest.TestDescription;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Formatter;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+/**
+ * Runs a directory's worth of jtreg tests on a device.
+ */
+public final class JtregRunner {
+
+    private static final Logger logger = Logger.getLogger(JtregRunner.class.getName());
+
+    private final File localTemp = new File("/tmp/" + UUID.randomUUID());
+    private final File deviceTemp = new File("/data/jtreg" + UUID.randomUUID());
+
+    private final Adb adb = new Adb();
+    private final File directoryToScan;
+    private final TestToDex testToDex;
+    private final ExecutorService outputReaders = Executors.newFixedThreadPool(1);
+
+    private Integer debugPort;
+    private Set<File> expectationDirs = new LinkedHashSet<File>();
+    private long timeoutSeconds = 10 * 60; // default is ten minutes
+    private File xmlReportsDirectory;
+
+    private File deviceTestRunner;
+
+    public JtregRunner(File sdkJar, File directoryToScan) {
+        this.directoryToScan = directoryToScan;
+        this.testToDex = new TestToDex(sdkJar, localTemp);
+    }
+
+    /**
+     * Builds and executes all tests in the test directory.
+     */
+    public void buildAndRunAllTests() throws Exception {
+        localTemp.mkdirs();
+
+        List<TestDescription> tests = testToDex.findTests(directoryToScan);
+        final BlockingQueue<TestRun> readyToRun = new ArrayBlockingQueue<TestRun>(4);
+
+        // build and install tests in a background thread. Using lots of
+        // threads helps for packages that contain many unsupported tests
+        ExecutorService builders = Executors.newFixedThreadPool(8);
+        for (final TestDescription testDescription : tests) {
+            builders.submit(new Callable<Void>() {
+                public Void call() throws Exception {
+                    String qualifiedName = TestDescriptions.qualifiedName(testDescription);
+                    ExpectedResult expectedResult = ExpectedResult.forRun(expectationDirs, qualifiedName);
+                    TestRun testRun = new TestRun(qualifiedName, testDescription, expectedResult);
+                    buildAndInstall(testRun);
+                    readyToRun.put(testRun);
+                    return null;
+                }
+            });
+        }
+        builders.shutdown();
+
+        prepareDevice();
+
+        int unsupportedTests = 0;
+
+        List<TestRun> runs = new ArrayList<TestRun>(tests.size());
+        while (!builders.isTerminated() || !readyToRun.isEmpty()) {
+            TestRun testRun = readyToRun.take();
+            runs.add(testRun);
+
+            if (testRun.getResult() == Result.UNSUPPORTED) {
+                logger.fine("skipping " + testRun.getQualifiedName());
+                unsupportedTests++;
+                continue;
+            }
+
+            if (testRun.isRunnable()) {
+                runTest(testRun);
+            }
+
+            printResult(testRun);
+        }
+
+        if (unsupportedTests > 0) {
+            logger.info("Skipped " + unsupportedTests + " unsupported tests.");
+        }
+
+        if (xmlReportsDirectory != null) {
+            logger.info("Printing XML Reports... ");
+            int numFiles = new XmlReportPrinter().generateReports(xmlReportsDirectory, runs);
+            logger.info(numFiles + " XML files written.");
+        }
+    }
+
+    /**
+     * Initializes the temporary directories and test harness necessary to run
+     * tests on a device.
+     */
+    private void prepareDevice() {
+        adb.mkdir(deviceTemp);
+        File testRunnerJar = testToDex.writeTestRunnerJar();
+        adb.push(testRunnerJar, deviceTemp);
+        deviceTestRunner = new File(deviceTemp, testRunnerJar.getName());
+        if (debugPort != null) {
+            adb.forwardTcp(debugPort, debugPort);
+        }
+        logger.info("Prepared device.");
+    }
+
+    /**
+     * Creates a dex file for the given test and push it out to the device.
+     *
+     * @return true if building and installing completed successfully.
+     */
+    private void buildAndInstall(TestRun testRun) {
+        TestDescription testDescription = testRun.getTestDescription();
+        String qualifiedName = testRun.getQualifiedName();
+        logger.fine("building " + testRun.getQualifiedName());
+
+        File base = new File(deviceTemp, qualifiedName);
+        adb.mkdir(base);
+
+        File dex;
+        try {
+            dex = testToDex.dexify(testDescription);
+            if (dex == null) {
+                testRun.setResult(Result.UNSUPPORTED, Collections.<String>emptyList());
+                return;
+            }
+        } catch (CommandFailedException e) {
+            testRun.setResult(Result.COMPILE_FAILED, e.getOutputLines());
+            return;
+        } catch (IOException e) {
+            testRun.setResult(Result.ERROR, e);
+            return;
+        }
+
+        logger.fine("installing " + testRun.getQualifiedName());
+        adb.push(testDescription.getDir(), base);
+        adb.push(dex, deviceTemp);
+        testRun.setInstalledFiles(base, new File(deviceTemp, dex.getName()));
+    }
+
+    /**
+     * Runs the specified test on the device.
+     */
+    private void runTest(TestRun testRun) {
+        if (!testRun.isRunnable()) {
+            throw new IllegalArgumentException();
+        }
+
+        Command.Builder builder = new Command.Builder();
+        builder.args("adb", "shell", "dalvikvm");
+        builder.args("-classpath", Command.path(testRun.getDeviceDex(), deviceTestRunner));
+        builder.args("-Duser.dir=" + testRun.getBase());
+        if (debugPort != null) {
+            builder.args("-Xrunjdwp:transport=dt_socket,address="
+                    + debugPort + ",server=y,suspend=y");
+        }
+        builder.args("dalvik.jtreg.TestRunner");
+        final Command command = builder.build();
+
+        try {
+            command.start();
+
+            // run on a different thread to allow a timeout
+            List<String> output = outputReaders.submit(new Callable<List<String>>() {
+                public List<String> call() throws Exception {
+                    return command.gatherOutput();
+                }
+            }).get(timeoutSeconds, TimeUnit.SECONDS);
+
+            if (output.isEmpty()) {
+                testRun.setResult(Result.ERROR,
+                        Collections.singletonList("No output returned!"));
+                return;
+            }
+
+            Result result = "SUCCESS".equals(output.get(output.size() - 1))
+                    ? Result.SUCCESS
+                    : Result.EXEC_FAILED;
+            testRun.setResult(result, output.subList(0, output.size() - 1));
+        } catch (TimeoutException e) {
+            testRun.setResult(Result.EXEC_TIMEOUT, e);
+        } catch (Exception e) {
+            testRun.setResult(Result.ERROR,
+                    Collections.singletonList("Exceeded timeout! (" + timeoutSeconds + "s)"));
+        } finally {
+            if (command.isStarted()) {
+                command.getProcess().destroy(); // to release the output reader
+            }
+        }
+    }
+
+    private void printResult(TestRun testRun) {
+        ExpectedResult expected = testRun.getExpectedResult();
+        boolean patternSuccess;
+
+        if (expected.getPattern() != null) {
+            Pattern pattern = Pattern.compile(expected.getPattern(),
+                    Pattern.MULTILINE | Pattern.DOTALL);
+            patternSuccess = pattern.matcher(Strings.join(testRun.getOutputLines(), "\n")).matches();
+        } else {
+            patternSuccess = true;
+        }
+
+        if (expected.getResult() == testRun.getResult() && patternSuccess) {
+            logger.info("OK " + testRun.getQualifiedName() + " (" + testRun.getResult() + ")");
+            return;
+        }
+
+        logger.info("FAIL " + testRun.getQualifiedName() + " (" + testRun.getResult() + ")");
+        logger.info("  \"" + testRun.getTestDescription().getTitle() + "\"");
+
+        if (expected.getResult() != Result.SUCCESS
+                && expected.getResult() != testRun.getResult()) {
+            logger.info("  Expected result: " + expected.getResult());
+        }
+
+        if (!patternSuccess) {
+            logger.info("  Expected output to match \"" + expected.getPattern() + "\"");
+        }
+
+        for (String output : testRun.getOutputLines()) {
+            logger.info("  " + output);
+        }
+    }
+
+    private void shutdown() {
+        adb.rm(deviceTemp);
+        outputReaders.shutdown();
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (args.length < 2) {
+            System.out.println("Usage: JTRegRunner [options]... <android jar> <tests directory>");
+            System.out.println();
+            System.out.println("  <android jar>: the API jar file to compile against. Usually");
+            System.out.println("      this is <SDK>/platforms/android-<X.X>/android.jar where");
+            System.out.println("      <SDK> is the path to an Android SDK path and <X.X> is a");
+            System.out.println("      release version like 1.5.");
+            System.out.println();
+            System.out.println("  <tests directory>: a directory to scan for test cases;");
+            System.out.println("      typically this is 'platform_v6/jdk/test' if 'platform_v6'");
+            System.out.println("      contains the sources of a platform implementation.");
+            System.out.println();
+            System.out.println("OPTIONS");
+            System.out.println();
+            System.out.println("  --debug <port>: enable Java debugging on the specified port.");
+            System.out.println("      This port must be free both on the device and on the local");
+            System.out.println("      system.");
+            System.out.println();
+            System.out.println("  --expectations <directory>: use the specified directory when");
+            System.out.println("      looking for test expectations. The directory should include");
+            System.out.println("      <test>.expected files describing expected results.");
+            System.out.println();
+            System.out.println("  --timeout-seconds <seconds>: maximum execution time of each");
+            System.out.println("      test before the runner aborts it.");
+            System.out.println();
+            System.out.println("  --xml-reports-directory <path>: directory to emit JUnit-style");
+            System.out.println("      XML test results.");
+            System.out.println();
+            System.out.println("  --verbose: turn on verbose output");
+            System.out.println();
+            return;
+        }
+
+        prepareLogging();
+
+        File sdkJar = new File(args[args.length - 2]);
+        if (!sdkJar.exists()) {
+            throw new RuntimeException("Could not find SDK jar: " + sdkJar);
+        }
+
+        File directoryToScan = new File(args[args.length - 1]);
+        if (!directoryToScan.isDirectory()) {
+            throw new RuntimeException("Invalid test directory: " + directoryToScan);
+        }
+
+        JtregRunner jtregRunner = new JtregRunner(sdkJar, directoryToScan);
+
+        for (int i = 0; i < args.length - 2; i++) {
+            if ("--debug".equals(args[i])) {
+                jtregRunner.debugPort = Integer.valueOf(args[++i]);
+
+            } else if ("--expectations".equals(args[i])) {
+                File expectationDir = new File(args[++i]);
+                if (!expectationDir.isDirectory()) {
+                    throw new RuntimeException("Invalid expectation directory: " + directoryToScan);
+                }
+                jtregRunner.expectationDirs.add(expectationDir);
+
+            } else if ("--timeout-seconds".equals(args[i])) {
+                jtregRunner.timeoutSeconds = Long.valueOf(args[++i]);
+
+            } else if ("--verbose".equals(args[i])) {
+                Logger.getLogger("dalvik.jtreg").setLevel(Level.FINE);
+
+            } else if ("--xml-reports-directory".equals(args[i])) {
+                jtregRunner.xmlReportsDirectory = new File(args[++i]);
+                if (!jtregRunner.xmlReportsDirectory.isDirectory()) {
+                    throw new RuntimeException("Invalid XML reports directory: "
+                            + jtregRunner.xmlReportsDirectory);
+                }
+
+            } else {
+                throw new RuntimeException("Unrecognized option: " + args[i]);
+            }
+        }
+
+        jtregRunner.buildAndRunAllTests();
+        jtregRunner.shutdown();
+    }
+
+    private static void prepareLogging() {
+        ConsoleHandler handler = new ConsoleHandler();
+        handler.setLevel(Level.ALL);
+        handler.setFormatter(new Formatter() {
+            @Override public String format(LogRecord r) {
+                return r.getMessage() + "\n";
+            }
+        });
+        Logger logger = Logger.getLogger("dalvik.jtreg");
+        logger.addHandler(handler);
+        logger.setUseParentHandlers(false);
+    }
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/Result.java b/tools/dalvik_jtreg/java/dalvik/jtreg/Result.java
new file mode 100644
index 0000000..b612407
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/Result.java
@@ -0,0 +1,34 @@
+/*
+ * 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 dalvik.jtreg;
+
+/**
+ * A test run result.
+ */
+public enum Result {
+
+    /**
+     * A test that cannot be run by this harness, such as a shell script.
+     */
+    UNSUPPORTED,
+
+    COMPILE_FAILED,
+    EXEC_FAILED,
+    EXEC_TIMEOUT,
+    ERROR,
+    SUCCESS
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/Strings.java b/tools/dalvik_jtreg/java/dalvik/jtreg/Strings.java
new file mode 100644
index 0000000..c06c98a
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/Strings.java
@@ -0,0 +1,54 @@
+/*
+ * 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 dalvik.jtreg;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * Utility methods for strings.
+ */
+public class Strings {
+
+    static String join(Object[] objects, String delimiter) {
+        return join(Arrays.asList(objects), delimiter);
+    }
+
+    static String join(Iterable<?> objects, String delimiter) {
+        Iterator<?> i = objects.iterator();
+        if (!i.hasNext()) {
+            return "";
+        }
+
+        StringBuilder result = new StringBuilder();
+        result.append(i.next());
+        while(i.hasNext()) {
+            result.append(delimiter).append(i.next());
+        }
+        return result.toString();
+    }
+
+    static String[] objectsToStrings(Object[] objects) {
+        String[] result = new String[objects.length];
+        int i = 0;
+        for (Object o : objects) {
+            result[i++] = o.toString();
+        }
+        return result;
+    }
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/TestDescriptions.java b/tools/dalvik_jtreg/java/dalvik/jtreg/TestDescriptions.java
new file mode 100644
index 0000000..c7ffe7f
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/TestDescriptions.java
@@ -0,0 +1,74 @@
+/*
+ * 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 dalvik.jtreg;
+
+import com.sun.javatest.TestDescription;
+
+import java.util.Properties;
+
+/**
+ * Utility methods for manipulating {@link TestDescription} instances.
+ */
+class TestDescriptions {
+
+    /**
+     * The subpath of a platform implementation under which tests live. Used to
+     * derive relative test paths like {@code /java/io/Reader} from an absolute
+     * path like {@code /home/jessewilson/platform_v6/test/java/io/Reader}.
+     */
+    static final String TEST_ROOT = "/test/";
+
+    /**
+     * Returns a properties object for the given test description.
+     */
+    static Properties toProperties(TestDescription testDescription) {
+        Properties result = new Properties();
+        result.setProperty(TestRunner.CLASS_NAME, testDescription.getName());
+        result.setProperty(TestRunner.QUALIFIED_NAME, qualifiedName(testDescription));
+        return result;
+    }
+
+    /**
+     * Returns a fully qualified name of the form {@code
+     * java.lang.Math.PowTests} from the given test description. The returned
+     * name is appropriate for use in a filename.
+     */
+    static String qualifiedName(TestDescription testDescription) {
+        return className(testDescription) + "." + escape(testDescription.getName());
+    }
+
+    /**
+     * Returns the name of the class under test, such as {@code java.lang.Math}.
+     */
+    static String className(TestDescription testDescription) {
+        String dir = testDescription.getDir().toString();
+        int separatorIndex = dir.indexOf(TEST_ROOT);
+        return separatorIndex != -1
+                ? escape(dir.substring(separatorIndex + TEST_ROOT.length()))
+                : escape(dir);
+    }
+
+    /**
+     * Returns a similar string with filename-unsafe characters replaced by
+     * filename-safe ones.
+     */
+    private static String escape(String s) {
+        return s.replace('/', '.');
+    }
+
+    private TestDescriptions() {}
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/TestRun.java b/tools/dalvik_jtreg/java/dalvik/jtreg/TestRun.java
new file mode 100644
index 0000000..feb919a
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/TestRun.java
@@ -0,0 +1,125 @@
+/*
+ * 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 dalvik.jtreg;
+
+import com.sun.javatest.TestDescription;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A test run and its outcome.
+ */
+public final class TestRun {
+
+    private final TestDescription testDescription;
+    private final String qualifiedName;
+    private final ExpectedResult expectedResult;
+
+    private File base;
+    private File deviceDex;
+
+    private Result result;
+    private List<String> outputLines;
+
+
+    public TestRun(String qualifiedName, TestDescription testDescription,
+            ExpectedResult expectedResult) {
+        this.qualifiedName = qualifiedName;
+        this.testDescription = testDescription;
+        this.expectedResult = expectedResult;
+    }
+
+    public TestDescription getTestDescription() {
+        return testDescription;
+    }
+
+    public String getQualifiedName() {
+        return qualifiedName;
+    }
+
+    /**
+     * Initializes the on-device base directory from which the test program
+     * shall be executed, and the dex file containing that program.
+     */
+    public void setInstalledFiles(File base, File deviceDex) {
+        if (this.base != null) {
+            throw new IllegalStateException();
+        }
+
+        this.base = base;
+        this.deviceDex = deviceDex;
+    }
+
+    /**
+     * Returns true if this test is ready for execution on a device.
+     */
+    public boolean isRunnable() {
+        return base != null && deviceDex != null;
+    }
+
+    /**
+     * Returns the test's base directory, from which local files can be read by
+     * the test.
+     */
+    public File getBase() {
+        return base;
+    }
+
+    /**
+     * Returns the jar file containing the test code.
+     */
+    public File getDeviceDex() {
+        return deviceDex;
+    }
+
+    public void setResult(Result result, Throwable e) {
+        setResult(result, throwableToLines(e));
+    }
+
+    public void setResult(Result result, List<String> outputLines) {
+        if (this.result != null) {
+            throw new IllegalStateException();
+        }
+
+        this.result = result;
+        this.outputLines = outputLines;
+    }
+
+    private static List<String> throwableToLines(Throwable t) {
+        StringWriter writer = new StringWriter();
+        PrintWriter out = new PrintWriter(writer);
+        t.printStackTrace(out);
+        return Arrays.asList(writer.toString().split("\\n"));
+    }
+
+    public Result getResult() {
+        return result;
+    }
+
+    public List<String> getOutputLines() {
+        return outputLines;
+    }
+
+    public ExpectedResult getExpectedResult() {
+        return expectedResult;
+    }
+
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/TestRunner.java b/tools/dalvik_jtreg/java/dalvik/jtreg/TestRunner.java
new file mode 100644
index 0000000..f1b5577
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/TestRunner.java
@@ -0,0 +1,103 @@
+/*
+ * 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 dalvik.jtreg;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Properties;
+
+/**
+ * Runs a jtreg test that was prepared with {@link TestToDex}.
+ */
+public final class TestRunner {
+
+    /**
+     * The name of the test properties file within the {@code .jar} file.
+     */
+    static final String TEST_PROPERTIES_FILE = "test.properties";
+
+    /**
+     * Property identifier for the test's main class name. This class should
+     * have a {@code public static void main(String[] args)} method.
+     */
+    static final String CLASS_NAME = "className";
+
+    /**
+     * Property identifier for the test's name, such as {@code
+     * java.math.BigDecimal.PowTests}.
+     */
+    static final String QUALIFIED_NAME = "qualifiedName";
+
+    private String className;
+    private String qualifiedName;
+
+    private Method main;
+
+    public void test(String[] args)
+            throws InvocationTargetException, IllegalAccessException {
+        System.out.println("Executing " + qualifiedName);
+        try {
+            main.invoke(null, new Object[] { args });
+            System.out.println("SUCCESS");
+        } catch (Throwable failure) {
+            failure.printStackTrace();
+            System.out.println("FAILURE");
+        }
+    }
+
+    private void loadProperties() {
+        Properties properties = new Properties();
+        try {
+            InputStream propertiesStream = TestRunner.class.getResourceAsStream(
+                    "/" + TEST_PROPERTIES_FILE);
+            if (propertiesStream == null) {
+                throw new RuntimeException(TEST_PROPERTIES_FILE + " missing!");
+            }
+
+            properties.load(propertiesStream);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        className = properties.getProperty(CLASS_NAME);
+        qualifiedName = properties.getProperty(QUALIFIED_NAME);
+
+        if (className == null || qualifiedName == null) {
+            throw new RuntimeException(TEST_PROPERTIES_FILE + " missing required values!");
+        }
+    }
+
+    private void prepareTest() {
+        try {
+            Class<?> testClass = Class.forName(className);
+            main = testClass.getMethod("main", String[].class);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        // Usage: TestRunner [optional test args]...
+
+        TestRunner testRunner = new TestRunner();
+        testRunner.loadProperties();
+        testRunner.prepareTest();
+        testRunner.test(args);
+    }
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/TestToDex.java b/tools/dalvik_jtreg/java/dalvik/jtreg/TestToDex.java
new file mode 100644
index 0000000..6badf34
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/TestToDex.java
@@ -0,0 +1,143 @@
+/*
+ * 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 dalvik.jtreg;
+
+import com.sun.javatest.TestDescription;
+import com.sun.javatest.TestResult;
+import com.sun.javatest.TestResultTable;
+import com.sun.javatest.TestSuite;
+import com.sun.javatest.WorkDirectory;
+import com.sun.javatest.regtest.RegressionTestSuite;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+/**
+ * Scans a directory of jtreg tests and creates Dalvik-friendly {@code .jar}
+ * files for them. These tests can be executed by {@link TestRunner}. Because of
+ * the heavy use of the default package by jtreg tests, it is not generally
+ * possible to run multiple tests in the same dalvik VM.
+ */
+final class TestToDex {
+
+    private static final String DALVIK_JTREG_HOME
+            = "dalvik/libcore/tools/dalvik_jtreg";
+    private static final File JTREG_JAR
+            = new File(DALVIK_JTREG_HOME + "/lib/jtreg.jar");
+    private static final File TEST_RUNNER_JAVA
+            = new File(DALVIK_JTREG_HOME + "/java/dalvik/jtreg/TestRunner.java");
+
+    private static final Logger logger = Logger.getLogger(TestToDex.class.getName());
+
+    private final Pattern JAVA_TEST_PATTERN = Pattern.compile("\\/(\\w)+\\.java$");
+
+    private final File sdkJar;
+    private final File temp;
+
+    TestToDex(File sdkJar, File temp) {
+        this.sdkJar = sdkJar;
+        this.temp = temp;
+    }
+
+    /**
+     * Creates a testrunner jar that can execute the packaged tests.
+     */
+    File writeTestRunnerJar() {
+        File base = new File(temp, "testrunner");
+        base.mkdirs();
+
+        new Javac()
+                .destination(base)
+                .compile(TEST_RUNNER_JAVA);
+
+        File output = new File(temp, "testrunner.jar");
+        new Dx().dex(output.toString(), base);
+        return output;
+    }
+
+    /**
+     * Writes a Dalvik-friendly {@code .jar} for the described test.
+     *
+     * @return the path of the constructed {@code .jar}, or {@code null} if the
+     *      test cannot be converted to Dex (presumably because it is not of
+     *      the right type).
+     * @throws CommandFailedException if javac fails
+     */
+    File dexify(TestDescription testDescription) throws IOException {
+        String qualifiedName = TestDescriptions.qualifiedName(testDescription);
+
+        if (!JAVA_TEST_PATTERN.matcher(testDescription.getFile().toString()).find()) {
+            return null;
+        }
+
+        File jarContents = new File(temp, qualifiedName);
+        jarContents.mkdirs();
+
+        // write a test descriptor
+        Properties properties = TestDescriptions.toProperties(testDescription);
+        FileOutputStream propertiesOut = new FileOutputStream(
+                new File(jarContents, TestRunner.TEST_PROPERTIES_FILE));
+        properties.store(propertiesOut, "generated by " + getClass().getName());
+        propertiesOut.close();
+
+        new Javac()
+                .bootClasspath(sdkJar)
+                .classpath(testDescription.getDir(), JTREG_JAR)
+                .sourcepath(testDescription.getDir())
+                .destination(jarContents)
+                .compile(testDescription.getFile());
+
+        File output = new File(temp, qualifiedName + ".jar");
+        new Dx().dex(output.toString(), jarContents);
+        return output;
+    }
+
+    /**
+     * Scans {@code directoryToScan} for test cases, using JTHarness + jtreg
+     * behind the scenes.
+     */
+    List<TestDescription> findTests(File directoryToScan) throws Exception {
+        logger.info("Scanning " + directoryToScan + " for tests.");
+        File workDirectory = new File(temp, "JTwork");
+        workDirectory.mkdirs();
+
+        /*
+         * This code is capable of extracting test descriptions using jtreg 4.0
+         * and its bundled copy of jtharness. As a command line tool, jtreg's
+         * API wasn't intended for this style of use. As a consequence, this
+         * code is fragile and may be incompatible with newer versions of jtreg.
+         */
+        TestSuite testSuite = new RegressionTestSuite(directoryToScan);
+        WorkDirectory wd = WorkDirectory.convert(workDirectory, testSuite);
+        TestResultTable resultTable = wd.getTestResultTable();
+
+        List<TestDescription> result = new ArrayList<TestDescription>();
+        for (Iterator i = resultTable.getIterator(); i.hasNext(); ) {
+            TestResult testResult = (TestResult) i.next();
+            result.add(testResult.getDescription());
+        }
+        logger.info("Found " + result.size() + " tests.");
+        return result;
+    }
+}
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/XmlReportPrinter.java b/tools/dalvik_jtreg/java/dalvik/jtreg/XmlReportPrinter.java
new file mode 100644
index 0000000..bfea0bc
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/XmlReportPrinter.java
@@ -0,0 +1,205 @@
+/*
+ * 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 dalvik.jtreg;
+
+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.Collection;
+import java.util.Date;
+import java.util.EnumSet;
+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.
+ *
+ * TODO: unify this and com.google.coretests.XmlReportPrinter
+ */
+public class XmlReportPrinter {
+
+    /**
+     * Test results of these types are omitted from the report, as if the tests
+     * never existed. Equivalent to the core test runner's @BrokenTest.
+     */
+    private static final EnumSet<Result> IGNORED_RESULTS
+            = EnumSet.of(Result.COMPILE_FAILED);
+
+    private static final EnumSet<Result> FAILED_RESULTS
+            = EnumSet.of(Result.EXEC_FAILED);
+    private static final EnumSet<Result> ERROR_RESULTS
+            = EnumSet.complementOf(EnumSet.of(Result.EXEC_FAILED, Result.SUCCESS));
+
+    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;
+
+    /**
+     * Populates the directory with the report data from the completed tests.
+     */
+    public int generateReports(File directory, Collection<TestRun> results) {
+        Map<String, Suite> suites = testsToSuites(results);
+
+        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(directory, "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();
+    }
+
+    private Map<String, Suite> testsToSuites(Collection<TestRun> testRuns) {
+        Map<String, Suite> result = new LinkedHashMap<String, Suite>();
+        for (TestRun testRun : testRuns) {
+            if (IGNORED_RESULTS.contains(testRun.getResult())) {
+                continue;
+            }
+
+            String suiteName = suiteName(testRun);
+            Suite suite = result.get(suiteName);
+            if (suite == null) {
+                suite = new Suite(suiteName);
+                result.put(suiteName, suite);
+            }
+
+            suite.tests.add(testRun);
+            if (FAILED_RESULTS.contains(testRun.getResult())) {
+                suite.failuresCount++;
+            } else if (ERROR_RESULTS.contains(testRun.getResult())) {
+                suite.errorsCount++;
+            }
+        }
+        return result;
+    }
+
+    private static String suiteName(TestRun testRun) {
+        return TestDescriptions.className(testRun.getTestDescription());
+    }
+
+    static class Suite {
+        private final String name;
+        private final List<TestRun> tests = new ArrayList<TestRun>();
+        private int failuresCount;
+        private int errorsCount;
+
+        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(failuresCount));
+            serializer.attribute(ns, ATTR_ERRORS, Integer.toString(errorsCount));
+            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 (TestRun testRun : tests) {
+                print(serializer, testRun);
+            }
+
+            serializer.endTag(ns, TESTSUITE);
+        }
+
+        void print(KXmlSerializer serializer, TestRun testRun) throws IOException {
+            serializer.startTag(ns, TESTCASE);
+            serializer.attribute(ns, ATTR_NAME, testRun.getTestDescription().getName());
+            serializer.attribute(ns, ATTR_CLASSNAME, suiteName(testRun));
+            serializer.attribute(ns, ATTR_TIME, "0");
+
+            String result = ERROR_RESULTS.contains(testRun.getResult()) ? ERROR
+                    : FAILED_RESULTS.contains(testRun.getResult()) ? FAILURE
+                    : null;
+
+            if (result != null) {
+                serializer.startTag(ns, result);
+                String title = testRun.getTestDescription().getTitle();
+                if (title != null && title.length() > 0) {
+                    serializer.attribute(ns, ATTR_MESSAGE, title);
+                }
+                serializer.attribute(ns, ATTR_TYPE, testRun.getResult().toString());
+                String text = sanitize(Strings.join(testRun.getOutputLines(), "\n"));
+                serializer.text(text);
+                serializer.endTag(ns, result);
+            }
+
+            serializer.endTag(ns, TESTCASE);
+        }
+
+        /**
+         * Returns the text in a format that is safe for use in an XML document.
+         */
+        private String sanitize(String text) {
+            return text.replace("\0", "<\\0>");
+        }
+    }
+}
\ No newline at end of file
diff --git a/tools/dalvik_jtreg/lib/javatest.jar b/tools/dalvik_jtreg/lib/javatest.jar
new file mode 100644
index 0000000..f550f44
--- /dev/null
+++ b/tools/dalvik_jtreg/lib/javatest.jar
Binary files differ
diff --git a/tools/dalvik_jtreg/lib/jh.jar b/tools/dalvik_jtreg/lib/jh.jar
new file mode 100644
index 0000000..e5748fb
--- /dev/null
+++ b/tools/dalvik_jtreg/lib/jh.jar
Binary files differ
diff --git a/tools/dalvik_jtreg/lib/jtreg.jar b/tools/dalvik_jtreg/lib/jtreg.jar
new file mode 100644
index 0000000..452453a
--- /dev/null
+++ b/tools/dalvik_jtreg/lib/jtreg.jar
Binary files differ
diff --git a/tools/integrate/Android.mk b/tools/integrate/Android.mk
index 629a5fd..f0f25b3 100644
--- a/tools/integrate/Android.mk
+++ b/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/tools/integrate/Filesystem.java b/tools/integrate/Filesystem.java
index a9c1789..4b296a0 100644
--- a/tools/integrate/Filesystem.java
+++ b/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/tools/integrate/Module.java b/tools/integrate/Module.java
index 5cb7035..02cdb6a 100644
--- a/tools/integrate/Module.java
+++ b/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,49 @@
  */
 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("logging", new Module.Builder(svnRoot, "logging").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/tools/integrate/Modules.java b/tools/integrate/Modules.java
deleted file mode 100644
index 2475852..0000000
--- a/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/tools/integrate/PullHarmonyCode.java b/tools/integrate/PullHarmonyCode.java
index 6710801..ce019d4 100644
--- a/tools/integrate/PullHarmonyCode.java
+++ b/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/tools/integrate/PushAndroidCode.java b/tools/integrate/PushAndroidCode.java
new file mode 100644
index 0000000..c0002f5
--- /dev/null
+++ b/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/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java b/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
index 36282e1..d52f08f 100644
--- a/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
+++ b/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
@@ -196,28 +196,9 @@
         return nativegetsupportedciphersuites();
     }
 
-    /**
-     * Calls native OpenSSL functions to get the enabled ciphers.
-     */
-    private native String[] nativegetenabledciphersuites();
-
     @Override
     public String[] getEnabledCipherSuites() {
-        return nativegetenabledciphersuites();
-    }
-
-    /**
-     * Calls the SSL_CTX_set_cipher_list(...) OpenSSL function with the passed
-     * char array.
-     */
-    private native void nativesetenabledciphersuites(String controlString);
-
-    private boolean findSuite(String suite) {
-        String[] supportedCipherSuites = nativegetsupportedciphersuites();
-        for(int i = 0; i < supportedCipherSuites.length; i++)
-            if (supportedCipherSuites[i].equals(suite)) return true;
-        throw new IllegalArgumentException("Protocol " + suite +
-        " is not supported.");
+        return OpenSSLSocketImpl.nativeGetEnabledCipherSuites(ssl_ctx);
     }
 
     /**
@@ -230,16 +211,7 @@
      */
     @Override
     public void setEnabledCipherSuites(String[] suites) {
-        if (suites == null) {
-            throw new IllegalArgumentException("Provided parameter is null");
-        }
-        String controlString = "";
-        for (int i = 0; i < suites.length; i++) {
-            findSuite(suites[i]);
-            if (i == 0) controlString = suites[i];
-            else controlString += ":" + suites[i];
-        }
-        nativesetenabledciphersuites(controlString);
+        OpenSSLSocketImpl.setEnabledCipherSuites(ssl_ctx, suites);
     }
 
     /**
diff --git a/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java b/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
index fcc1a77..d287bbd 100644
--- a/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
+++ b/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
@@ -662,7 +662,7 @@
         return nativegetsupportedciphersuites();
     }
 
-    private native String[] nativegetenabledciphersuites();
+    static native String[] nativeGetEnabledCipherSuites(int ssl_ctx);
 
     /**
      * The names of the cipher suites that are in use in the actual the SSL
@@ -671,21 +671,23 @@
      * @return an array of cipher suite names
      */
     public String[] getEnabledCipherSuites() {
-        return nativegetenabledciphersuites();
+        return nativeGetEnabledCipherSuites(ssl_ctx);
     }
 
     /**
      * Calls the SSL_CTX_set_cipher_list(...) OpenSSL function with the passed
      * char array.
      */
-    private native void nativesetenabledciphersuites(String controlString);
+    static native void nativeSetEnabledCipherSuites(int ssl_ctx, String controlString);
 
-    private boolean findSuite(String suite) {
+    private static boolean findSuite(String suite) {
         String[] supportedCipherSuites = nativegetsupportedciphersuites();
-        for(int i = 0; i < supportedCipherSuites.length; i++)
-            if (supportedCipherSuites[i].equals(suite)) return true;
-        throw new IllegalArgumentException("Protocol " + suite +
-        " is not supported.");
+        for(int i = 0; i < supportedCipherSuites.length; i++) {
+            if (supportedCipherSuites[i].equals(suite)) {
+                return true;
+            }
+        }
+        throw new IllegalArgumentException("Protocol " + suite + " is not supported.");
     }
 
     /**
@@ -699,16 +701,20 @@
      *             is null.
      */
     public void setEnabledCipherSuites(String[] suites) {
+        setEnabledCipherSuites(ssl_ctx, suites);
+    }
+    
+    static void setEnabledCipherSuites(int ssl_ctx, String[] suites) {
         if (suites == null) {
             throw new IllegalArgumentException("Provided parameter is null");
         }
         String controlString = "";
-        for(int i = 0; i < suites.length; i++) {
+        for (int i = 0; i < suites.length; i++) {
             findSuite(suites[i]);
             if (i == 0) controlString = suites[i];
             else controlString += ":" + suites[i];
         }
-        nativesetenabledciphersuites(controlString);
+        nativeSetEnabledCipherSuites(ssl_ctx, controlString);
     }
 
     /**
diff --git a/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java b/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
index 6c23a91..507e14f 100644
--- a/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
+++ b/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/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp b/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
index 13a1e61..1e73041 100644
--- a/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
+++ b/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,93 +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;
-}
-
-/**
- * Loads the ciphers suites that are enabled in the OpenSSL server
- * and returns them in a string array.
- */
-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;
-}
-
-/**
- * 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)
-{
-    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.");
-    }    
+    jobjectArray result = makeCipherList(env, ssl_ctx);
+    SSL_CTX_free(ssl_ctx);
+    return result;
 }
 
 /**
@@ -285,8 +195,6 @@
     {"nativeinit", "(Ljava/lang/String;Ljava/lang/String;[B)V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_init},
     {"nativesetenabledprotocols", "(J)V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_setenabledprotocols},
     {"nativegetsupportedciphersuites", "()[Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_getsupportedciphersuites},
-    {"nativegetenabledciphersuites", "()[Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_getenabledciphersuites},
-    {"nativesetenabledciphersuites", "(Ljava/lang/String;)V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_setenabledciphersuites},
     {"nativesetclientauth", "(I)V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_nativesetclientauth},
     {"nativefree", "()V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_nativefree}
 };
@@ -296,20 +204,15 @@
  */
 extern "C" int register_org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl(JNIEnv* env)
 {
-    int ret;
-    jclass clazz;
-
-    clazz = env->FindClass("org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl");
-
+    jclass clazz = env->FindClass("org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl");
     if (clazz == NULL) {
         LOGE("Can't find org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl");
         return -1;
     }
 
-    ret = jniRegisterNativeMethods(env, "org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl",
+    int rc = jniRegisterNativeMethods(env, "org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl",
             sMethods, NELEM(sMethods));
-
-    if (ret >= 0) {
+    if (rc >= 0) {
         // Note: do these after the registration of native methods, because 
         // there is a static method "initstatic" that's called when the
         // OpenSSLServerSocketImpl class is first loaded, and that required
@@ -320,5 +223,5 @@
             return -1;
         }
     }
-    return ret;
+    return rc;
 }
diff --git a/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp b/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
index feae690..324dacf 100644
--- a/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
+++ b/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/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp b/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
index 87f2af3..538b7f3 100644
--- a/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
+++ b/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,23 @@
      */
     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;
+    mode |= SSL_MODE_SMALL_BUFFERS;  /* lazily allocate record buffers; usually saves
+                                      * 44k over the default */
+    mode |= SSL_MODE_HANDSHAKE_CUTTHROUGH;  /* enable sending of client data as soon as
+                                             * ClientCCS and ClientFinished are sent */
+    SSL_CTX_set_mode(ssl_ctx, mode);
+
     if (privatekey != NULL) {
         BIO* privatekeybio = stringToMemBuf(env, (jstring) privatekey);
         EVP_PKEY* privatekeyevp =
@@ -1114,17 +1131,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,105 +1410,82 @@
 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;
 }
 
 /**
  * Loads the ciphers suites that are enabled in the OpenSSL client
  * and returns them in a string array.
  */
-static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_getenabledciphersuites(JNIEnv* env,
-        jobject object)
+static jobjectArray OpenSSLSocketImpl_nativeGetEnabledCipherSuites(JNIEnv* env,
+        jclass, jint ssl_ctx_address)
 {
-    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*>(static_cast<uintptr_t>(ssl_ctx_address));
+    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)
+static void OpenSSLSocketImpl_nativeSetEnabledCipherSuites(JNIEnv* env, jclass,
+        jint ssl_ctx_address, jstring controlString)
 {
-    SSL_CTX* ctx;
-    const char *str;
-    int ret;
+    SSL_CTX* ssl_ctx =
+            reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
+    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
@@ -1848,8 +1831,8 @@
     {"nativeaccept", "(Ljava/net/Socket;IZ)V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_accept},
     {"nativesetenabledprotocols", "(J)V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_setenabledprotocols},
     {"nativegetsupportedciphersuites", "()[Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_getsupportedciphersuites},
-    {"nativegetenabledciphersuites", "()[Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_getenabledciphersuites},
-    {"nativesetenabledciphersuites", "(Ljava/lang/String;)V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_setenabledciphersuites},
+    {"nativeGetEnabledCipherSuites", "(I)[Ljava/lang/String;", (void*) OpenSSLSocketImpl_nativeGetEnabledCipherSuites},
+    {"nativeSetEnabledCipherSuites", "(ILjava/lang/String;)V", (void*) OpenSSLSocketImpl_nativeSetEnabledCipherSuites},
     {"nativecipherauthenticationmethod", "()Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_cipherauthenticationmethod},
     {"nativeinterrupt", "()V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_interrupt},
     {"nativeclose", "()V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_close},
@@ -1862,63 +1845,51 @@
  */
 extern "C" int register_org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl(JNIEnv* env)
 {
-    int ret;
-    jclass clazz;
-
-    clazz = env->FindClass("org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl");
-
+    jclass clazz = env->FindClass("org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl");
     if (clazz == NULL) {
         LOGE("Can't find org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl");
         return -1;
     }
 
     jclass socketClass = env->FindClass("java/net/Socket");
-
     if (socketClass == NULL) {
         LOGE("Can't find class java.net.Socket");
         return -1;
     }
 
     field_mImpl = env->GetFieldID(socketClass, "impl", "Ljava/net/SocketImpl;");
-
     if (field_mImpl == NULL) {
         LOGE("Can't find field impl in class java.net.Socket");
         return -1;
     }
 
     jclass socketImplClass = env->FindClass("java/net/SocketImpl");
-
-    if(socketImplClass == NULL) {
+    if (socketImplClass == NULL) {
         LOGE("Can't find class java.net.SocketImpl");
         return -1;
     }
 
     field_mFD = env->GetFieldID(socketImplClass, "fd", "Ljava/io/FileDescriptor;");
-
     if (field_mFD == NULL) {
         LOGE("Can't find field fd in java.net.SocketImpl");
         return -1;
     }
 
     jclass fdclazz = env->FindClass("java/io/FileDescriptor");
-
-    if (fdclazz == NULL)
-    {
+    if (fdclazz == NULL) {
         LOGE("Can't find java/io/FileDescriptor");
         return -1;
     }
 
     field_descriptor = env->GetFieldID(fdclazz, "descriptor", "I");
-
     if (field_descriptor == NULL) {
         LOGE("Can't find FileDescriptor.descriptor");
         return -1;
     }
 
-    ret = jniRegisterNativeMethods(env, "org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl",
+    int rc = jniRegisterNativeMethods(env, "org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl",
             sMethods, NELEM(sMethods));
-
-    if (ret >= 0) {
+    if (rc >= 0) {
         // Note: do these after the registration of native methods, because 
         // there is a static method "initstatic" that's called when the
         // OpenSSLSocketImpl class is first loaded, and that required
@@ -1941,5 +1912,5 @@
             return -1;
         }
     }
-    return ret;
+    return rc;
 }
diff --git a/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h b/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
index 9ed75be..e78cdd8 100644
--- a/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
+++ b/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/x-net/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java b/x-net/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java
index 0e3fee3..f659919 100644
--- a/x-net/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java
+++ b/x-net/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java
@@ -49,6 +49,7 @@
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
+import tests.util.TestEnvironment;
 
 
 /**
@@ -65,6 +66,11 @@
         junit.textui.TestRunner.run(SSLEngineTest.class);
     }
 
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+        TestEnvironment.reset();
+    }
+
     /**
      * Test for <code>SSLEngine()</code> constructor Assertion: creates
      * SSLEngine object with null host and -1 port
diff --git a/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java b/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
index 3c1fb2e..c4bae0a 100644
--- a/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
+++ b/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/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java b/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
index 46ec1d2..6eca114 100644
--- a/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
+++ b/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
@@ -34,6 +34,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.security.KeyStore;
@@ -699,14 +700,15 @@
     boolean notFinished = true;
     SSLSession clientSession = null;
     SSLContext clientSslContext = null;
+    String testData = "PING";
     
     private String PASSWORD = "android";
 
     String cipherSuite = (useBKS ? cipherSuiteBKS : cipherSuiteJKS);
 
     /** 
-     * Implements a test SSL socket server. It wait for a connection on a given
-     * port, requests client authentication (if specified), and read 256 bytes
+     * Implements a test SSL socket server. It waits for a connection on a given
+     * port, requests client authentication (if specified), and reads
      * from the socket. 
      */
     class TestServer implements Runnable {
@@ -789,7 +791,7 @@
 
     /** 
      * Implements a test SSL socket client. It open a connection to localhost on
-     * a given port and writes 256 bytes to the socket. 
+     * a given port and writes to the socket. 
      */
     class TestClient implements Runnable {
         
@@ -822,6 +824,9 @@
                 SSLSocket socket = (SSLSocket)clientSslContext.getSocketFactory().createSocket();
 
                 socket.connect(new InetSocketAddress(port));
+                OutputStream ostream = socket.getOutputStream();
+                ostream.write(testData.getBytes());
+                ostream.flush();
 
                 clientSession = socket.getSession();
                 while (notFinished) {
diff --git a/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java b/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
index 5e39cb1..13a0e59 100644
--- a/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
+++ b/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/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
index f71d289..2fd16d0 100644
--- a/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
+++ b/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/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java b/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java
index 7b786f6..7814651 100644
--- a/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java
+++ b/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java
@@ -252,6 +252,7 @@
     public static XmlPullParserFactory newInstance (String classNames, Class context)
         throws XmlPullParserException {
 
+        /*
         if (context == null) {
             //NOTE: make sure context uses the same class loader as API classes
             //      this is the best we can do without having access to context classloader in J2ME
@@ -259,7 +260,6 @@
             context = referenceContextClass;
         }
 
-        /*
         String  classNamesLocation = null;
 
         if (classNames == null || classNames.length() == 0 || "DEFAULT".equals(classNames)) {
@@ -345,5 +345,3 @@
         return factory;
     }
 }
-
-
diff --git a/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index 40a4116..9192b1a 100644
--- a/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/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/xml/src/test/java/org/apache/harmony/xml/AllTests.java b/xml/src/test/java/org/apache/harmony/xml/AllTests.java
new file mode 100644
index 0000000..f7fac7c
--- /dev/null
+++ b/xml/src/test/java/org/apache/harmony/xml/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 org.apache.harmony.xml;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+        suite.addTestSuite(ExpatParserTest.class);
+        return suite;
+    }
+
+}
diff --git a/xml/src/test/java/org/kxml2/io/AllTests.java b/xml/src/test/java/org/kxml2/io/AllTests.java
new file mode 100644
index 0000000..f996d25
--- /dev/null
+++ b/xml/src/test/java/org/kxml2/io/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 org.kxml2.io;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+        suite.addTestSuite(KXmlSerializerTest.class);
+        return suite;
+    }
+
+}
diff --git a/xml/src/test/java/org/kxml2/io/KXmlSerializerTest.java b/xml/src/test/java/org/kxml2/io/KXmlSerializerTest.java
new file mode 100644
index 0000000..2d5ddf7
--- /dev/null
+++ b/xml/src/test/java/org/kxml2/io/KXmlSerializerTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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 org.kxml2.io;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public class KXmlSerializerTest extends TestCase {
+
+    /** the namespace */
+    final String ns = null;
+
+    public void testEmittingNullCharacterThrows() throws IOException {
+        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+        KXmlSerializer serializer = new KXmlSerializer();
+        serializer.setOutput(bytesOut, "UTF-8");
+        serializer.startDocument("UTF-8", null);
+
+        serializer.startTag(ns, "foo");
+        try {
+            serializer.text("bar\0baz");
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        serializer.startTag(ns, "bar");
+        try {
+            serializer.attribute(ns, "baz", "qu\0ux");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderFactoryTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderFactoryTest.java
index 1e1ffdd..b6c400f 100644
--- a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderFactoryTest.java
+++ b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderFactoryTest.java
@@ -31,6 +31,7 @@
 import org.xml.sax.SAXParseException;
 
 import tests.api.javax.xml.parsers.SAXParserFactoryTest.MyHandler;
+import tests.util.TestEnvironment;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -57,6 +58,7 @@
 
     protected void setUp() throws Exception {
         super.setUp();
+        TestEnvironment.reset();
         dbf = DocumentBuilderFactory.newInstance();
 
         cdataElements = new ArrayList<String>();
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserFactoryTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserFactoryTest.java
index 5d41356..a918ac2 100644
--- a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserFactoryTest.java
+++ b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserFactoryTest.java
@@ -41,6 +41,7 @@
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(SAXParserFactory.class) 
 public class SAXParserFactoryTest extends TestCase {
@@ -66,7 +67,9 @@
     }
 
     public void tearDown() throws Exception {
+        TestEnvironment.reset();
         is1.close();
+        super.tearDown();
     }
 
     @TestTargetNew(
@@ -175,13 +178,10 @@
         args = {}
     )
     public void test_newInstance() {
-        String className = null;
         try {
             SAXParserFactory dtf = SAXParserFactory.newInstance();
             assertNotNull("New Instance of DatatypeFactory is null", dtf);
 
-            className = System.getProperty("javax.xml.parsers.SAXParserFactory");
-
             System.setProperty("javax.xml.parsers.SAXParserFactory",
             "org.apache.harmony.xml.parsers.SAXParserFactoryImpl");
 
@@ -205,13 +205,6 @@
             }
         } catch (IOException ioe) {
             fail("Unexpected exception " + ioe.toString());
-        } finally {
-            if (className == null) {
-                System.clearProperty("javax.xml.parsers.SAXParserFactory");
-            } else {
-                System.setProperty("javax.xml.parsers.SAXParserFactory",
-                        className);
-            }
         }
     }
 
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java
index bc5e6a1..a1627ba 100644
--- a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java
+++ b/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/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserAdapterTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserAdapterTest.java
index 27a7e78..608d52c 100644
--- a/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserAdapterTest.java
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserAdapterTest.java
@@ -44,6 +44,7 @@
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
+import tests.util.TestEnvironment;
 
 @SuppressWarnings("deprecation")
 @TestTargetClass(ParserAdapter.class)
@@ -79,11 +80,17 @@
 
     @Override
     public void setUp() {
+        TestEnvironment.reset();
         adapter.setContentHandler(handler);
         adapter.setDTDHandler(handler);
         adapter.setErrorHandler(handler);
     }
-    
+
+    @Override protected void tearDown() throws Exception {
+        TestEnvironment.reset();
+        super.tearDown();
+    }
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         method = "ParserAdapter",
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserFactoryTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserFactoryTest.java
index dd4b1c3..113a569 100644
--- a/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserFactoryTest.java
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserFactoryTest.java
@@ -23,6 +23,7 @@
 import junit.framework.TestCase;
 
 import org.xml.sax.helpers.ParserFactory;
+import tests.util.TestEnvironment;
 
 import java.util.Iterator;
 import java.util.Properties;
@@ -32,6 +33,11 @@
 @TestTargetClass(ParserFactory.class)
 public class ParserFactoryTest extends TestCase {
 
+    @Override protected void tearDown() throws Exception {
+        TestEnvironment.reset();
+        super.tearDown();
+    }
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         method = "makeParser",
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderAdapterTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderAdapterTest.java
index 20488c5..0fe6f52 100644
--- a/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderAdapterTest.java
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderAdapterTest.java
@@ -42,6 +42,7 @@
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
+import tests.util.TestEnvironment;
 
 @SuppressWarnings("deprecation")
 @TestTargetClass(XMLReaderAdapter.class)
@@ -68,11 +69,17 @@
 
     @Override
     public void setUp() {
+        TestEnvironment.reset();
         adapter.setDocumentHandler(handler);
         adapter.setDTDHandler(handler);
         adapter.setErrorHandler(handler);
     }
-    
+
+    @Override protected void tearDown() throws Exception {
+        TestEnvironment.reset();
+        super.tearDown();
+    }
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         method = "XMLReaderAdapter",
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderFactoryTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderFactoryTest.java
index bfb1bd1..2edb918 100644
--- a/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderFactoryTest.java
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderFactoryTest.java
@@ -24,10 +24,21 @@
 
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.XMLReaderFactory;
+import tests.util.TestEnvironment;
 
 @TestTargetClass(XMLReaderFactory.class)
 public class XMLReaderFactoryTest extends TestCase {
 
+    @Override protected void setUp() throws Exception {
+        TestEnvironment.reset();
+        super.setUp();
+    }
+
+    @Override protected void tearDown() throws Exception {
+        TestEnvironment.reset();
+        super.tearDown();
+    }
+
     @TestTargetNew(
         level = TestLevel.SUFFICIENT,
         method = "createXMLReader",
diff --git a/xml/src/test/java/tests/xml/AllTests.java b/xml/src/test/java/tests/xml/AllTests.java
index eefae50..45ca18e 100644
--- a/xml/src/test/java/tests/xml/AllTests.java
+++ b/xml/src/test/java/tests/xml/AllTests.java
@@ -26,12 +26,17 @@
 
         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());
 
         suite.addTest(tests.api.org.xml.sax.AllTests.suite());
-        
+        suite.addTest(tests.api.org.w3c.dom.AllTests.suite());
+        suite.addTest(tests.org.w3c.dom.AllTests.suite());
+        suite.addTest(org.apache.harmony.xml.AllTests.suite());
+        suite.addTest(org.kxml2.io.AllTests.suite());
+
         return suite;
     }
 
diff --git a/xml/src/test/java/tests/xml/NodeTests.java b/xml/src/test/java/tests/xml/NodeTests.java
new file mode 100644
index 0000000..e46e216
--- /dev/null
+++ b/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());
+    }
+}