Add Java 6 additions to Double, Enum, Float, and String.

I rewrote the documentation for Double, Enum, and Float, but the "code" is the
same as harmony's. I rewrote the String code and wrote some tests to ensure
that a malicious Charset can't subvert String immutability.

I've also extracted the Android-specific bits of StringTest (which weren't
testing String at all) and brought back the latest harmony StringTest.java.

(The Class and Package changes are just to placate our API comparison tools.)

Bug: 2497395
Change-Id: Id57bda806891c3c85adfcb3b85eea8a8fad2c7b4
diff --git a/libcore/luni-kernel/src/main/java/java/lang/Class.java b/libcore/luni-kernel/src/main/java/java/lang/Class.java
index 571f5b1..e999c92 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/Class.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/Class.java
@@ -1425,8 +1425,7 @@
      *             if a security manager exists and it does not allow creating
      *             new instances.
      */
-    public T newInstance() throws IllegalAccessException,
-            InstantiationException {
+    public T newInstance() throws InstantiationException, IllegalAccessException {
         checkPublicMemberAccess();        
         return newInstanceImpl();
     }
diff --git a/libcore/luni-kernel/src/main/java/java/lang/Package.java b/libcore/luni-kernel/src/main/java/java/lang/Package.java
index 4d98959..58cee36 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/Package.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/Package.java
@@ -79,11 +79,11 @@
      * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
-    public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
+    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
         Annotation[] list = getAnnotations();
         for (int i = 0; i < list.length; i++) {
             if (annotationType.isInstance(list[i])) {
-                return (T)list[i];
+                return (A) list[i];
             }
         }
         
diff --git a/libcore/luni/src/main/java/java/lang/Double.java b/libcore/luni/src/main/java/java/lang/Double.java
index 95c7b81..a4a9dc2 100644
--- a/libcore/luni/src/main/java/java/lang/Double.java
+++ b/libcore/luni/src/main/java/java/lang/Double.java
@@ -51,16 +51,42 @@
     public static final double NaN = 0.0 / 0.0;
 
     /**
-     * Constant for the Positive Infinity value of the {@code double} type.
+     * Constant for the positive infinity value of the {@code double} type.
      */
     public static final double POSITIVE_INFINITY = 1.0 / 0.0;
 
     /**
-     * Constant for the Negative Infinity value of the {@code double} type.
+     * Constant for the negative infinity value of the {@code double} type.
      */
     public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
 
     /**
+     * Constant for the smallest positive normal value of the {@code double} type.
+     * 
+     * @since 1.6
+     * @hide
+     */
+    public static final double MIN_NORMAL = 2.2250738585072014E-308;
+
+    /**
+     * Maximum exponent that a finite value of the {@code double} type may have.
+     * Equal to {@code Math.getExponent(Double.MAX_VALUE)}.
+     * 
+     * @since 1.6
+     * @hide
+     */
+    public static final int MAX_EXPONENT = 1023;
+
+    /**
+     * Minimum exponent that a normal value of the {@code double} type may have.
+     * Equal to {@code Math.getExponent(Double.MIN_NORMAL)}.
+     * 
+     * @since 1.6
+     * @hide
+     */
+    public static final int MIN_EXPONENT = -1022;
+
+    /**
      * The {@link Class} object that represents the primitive type {@code
      * double}.
      *
diff --git a/libcore/luni/src/main/java/java/lang/Enum.java b/libcore/luni/src/main/java/java/lang/Enum.java
index e2ee32a..a59010c 100644
--- a/libcore/luni/src/main/java/java/lang/Enum.java
+++ b/libcore/luni/src/main/java/java/lang/Enum.java
@@ -191,6 +191,16 @@
         // END android-changed
     }
 
+    /**
+     * Enum types may not have finalizers.
+     * 
+     * @since 1.6
+     * @hide
+     */
+    @Override
+    protected final void finalize() {
+    }
+
     /*
      * Helper to invoke the values() static method on T and answer the result.
      * Returns null if there is a problem.
diff --git a/libcore/luni/src/main/java/java/lang/Float.java b/libcore/luni/src/main/java/java/lang/Float.java
index 54cc246..2d2140d 100644
--- a/libcore/luni/src/main/java/java/lang/Float.java
+++ b/libcore/luni/src/main/java/java/lang/Float.java
@@ -48,16 +48,42 @@
     public static final float NaN = 0.0f / 0.0f;
 
     /**
-     * Constant for the Positive Infinity value of the {@code float} type.
+     * Constant for the positive infinity value of the {@code float} type.
      */
     public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
 
     /**
-     * Constant for the Negative Infinity value of the {@code float} type.
+     * Constant for the negative infinity value of the {@code float} type.
      */
     public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
 
     /**
+     * Constant for the smallest positive normal value of the {@code float} type.
+     * 
+     * @since 1.6
+     * @hide
+     */
+    public static final float MIN_NORMAL = 1.1754943508222875E-38f;
+
+    /**
+     * Maximum exponent that a finite value of the {@code float} type may have.
+     * Equal to {@code Math.getExponent(Float.MAX_VALUE)}.
+     * 
+     * @since 1.6
+     * @hide
+     */
+    public static final int MAX_EXPONENT = 127;
+
+    /**
+     * Minimum exponent that a normal value of the {@code float} type may have.
+     * Equal to {@code Math.getExponent(Float.MIN_NORMAL)}.
+     * 
+     * @since 1.6
+     * @hide
+     */
+    public static final int MIN_EXPONENT = -126;
+
+    /**
      * The {@link Class} object that represents the primitive type {@code
      * float}.
      *
diff --git a/libcore/luni/src/main/java/java/lang/String.java b/libcore/luni/src/main/java/java/lang/String.java
index 2dda14b..4fe31f2 100644
--- a/libcore/luni/src/main/java/java/lang/String.java
+++ b/libcore/luni/src/main/java/java/lang/String.java
@@ -430,6 +430,84 @@
     }
 
     /**
+     * Converts the byte array to a String using the specified encoding.
+     * 
+     * @param data
+     *            the byte array to convert to a String
+     * @param start
+     *            the starting offset in the byte array
+     * @param length
+     *            the number of bytes to convert
+     * @param encoding
+     *            the encoding
+     * 
+     * @throws IndexOutOfBoundsException
+     *             when <code>length &lt; 0, start &lt; 0</code> or
+     *             <code>start + length &gt; data.length</code>
+     * @throws NullPointerException
+     *             when data is null
+     * 
+     * @see #getBytes()
+     * @see #getBytes(int, int, byte[], int)
+     * @see #getBytes(String)
+     * @see #valueOf(boolean)
+     * @see #valueOf(char)
+     * @see #valueOf(char[])
+     * @see #valueOf(char[], int, int)
+     * @see #valueOf(double)
+     * @see #valueOf(float)
+     * @see #valueOf(int)
+     * @see #valueOf(long)
+     * @see #valueOf(Object)
+     * @since 1.6
+     * @hide
+     */
+    public String(byte[] data, int start, int length, final Charset encoding) {
+        if (encoding == null) {
+            throw new NullPointerException();
+        }
+        if (start < 0 || length < 0 || length > data.length - start) {
+            throw new StringIndexOutOfBoundsException();
+        }
+        CharBuffer cb = encoding.decode(ByteBuffer.wrap(data, start, length));
+        this.lastCharset = encoding;
+        this.offset = 0;
+        this.count = cb.length();
+        this.value = new char[count];
+        System.arraycopy(cb.array(), 0, value, 0, count);
+    }
+
+    /**
+     * Converts the byte array to a String using the specified encoding.
+     * 
+     * @param data
+     *            the byte array to convert to a String
+     * @param encoding
+     *            the encoding
+     * 
+     * @throws NullPointerException
+     *             when data is null
+     * 
+     * @see #getBytes()
+     * @see #getBytes(int, int, byte[], int)
+     * @see #getBytes(String)
+     * @see #valueOf(boolean)
+     * @see #valueOf(char)
+     * @see #valueOf(char[])
+     * @see #valueOf(char[], int, int)
+     * @see #valueOf(double)
+     * @see #valueOf(float)
+     * @see #valueOf(int)
+     * @see #valueOf(long)
+     * @see #valueOf(Object)
+     * @since 1.6
+     * @hide
+     */
+    public String(byte[] data, Charset encoding) {
+        this(data, 0, data.length, encoding);
+    }
+    
+    /**
      * Initializes this string to contain the characters in the specified
      * character array. Modifying the character array after creating the string
      * has no effect on the string.
@@ -900,11 +978,7 @@
      * @return the byte array encoding of this string.
      */
     public byte[] getBytes() {
-        ByteBuffer buffer = defaultCharset().encode(
-                CharBuffer.wrap(this.value, this.offset, this.count));
-        byte[] bytes = new byte[buffer.limit()];
-        buffer.get(bytes);
-        return bytes;
+        return getBytes(defaultCharset());
     }
 
     /**
@@ -952,11 +1026,7 @@
      *             if the encoding is not supported.
      */
     public byte[] getBytes(String encoding) throws UnsupportedEncodingException {
-        ByteBuffer buffer = getCharset(encoding).encode(
-                CharBuffer.wrap(this.value, this.offset, this.count));
-        byte[] bytes = new byte[buffer.limit()];
-        buffer.get(bytes);
-        return bytes;
+        return getBytes(getCharset(encoding));
     }
 
     private Charset getCharset(final String encoding)
@@ -978,6 +1048,23 @@
     }
 
     /**
+     * Returns a new byte array containing the characters of this string encoded in the
+     * given charset.
+     * 
+     * @param encoding the encoding
+     * 
+     * @since 1.6
+     * @hide
+     */
+    public byte[] getBytes(Charset encoding) {
+        CharBuffer chars = CharBuffer.wrap(this.value, this.offset, this.count);
+        ByteBuffer buffer = encoding.encode(chars.asReadOnlyBuffer());
+        byte[] bytes = new byte[buffer.limit()];
+        buffer.get(bytes);
+        return bytes;
+    }
+
+    /**
      * Copies the specified characters in this string to the character array
      * starting at the specified offset in the character array.
      * 
diff --git a/libcore/luni/src/test/java/java/lang/AllTests.java b/libcore/luni/src/test/java/java/lang/AllTests.java
index d8b7ade..f1c1c72 100644
--- a/libcore/luni/src/test/java/java/lang/AllTests.java
+++ b/libcore/luni/src/test/java/java/lang/AllTests.java
@@ -24,6 +24,7 @@
         TestSuite suite = new TestSuite();
         suite.addTestSuite(java.lang.FloatTest.class);
         suite.addTestSuite(java.lang.ProcessBuilderTest.class);
+        suite.addTestSuite(StringTest.class);
         suite.addTestSuite(SystemTest.class);
         return suite;
     }
diff --git a/libcore/luni/src/test/java/java/lang/StringTest.java b/libcore/luni/src/test/java/java/lang/StringTest.java
new file mode 100644
index 0000000..4b204bb
--- /dev/null
+++ b/libcore/luni/src/test/java/java/lang/StringTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.util.Arrays;
+import junit.framework.TestCase;
+
+public class StringTest extends TestCase {
+    // The evil decoder keeps hold of the CharBuffer it wrote to.
+    private static final class EvilCharsetDecoder extends CharsetDecoder {
+        private static char[] chars;
+        public EvilCharsetDecoder(Charset cs) {
+            super(cs, 1.0f, 1.0f);
+        }
+        protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+            chars = out.array();
+            int inLength = in.remaining();
+            for (int i = 0; i < inLength; ++i) {
+                in.put((byte) 'X');
+                out.put('Y');
+            }
+            return CoderResult.UNDERFLOW;
+        }
+        public static void corrupt() {
+            for (int i = 0; i < chars.length; ++i) {
+                chars[i] = '$';
+            }
+        }
+    }
+
+    // The evil encoder tries to write to the CharBuffer it was given to
+    // read from.
+    private static final class EvilCharsetEncoder extends CharsetEncoder {
+        public EvilCharsetEncoder(Charset cs) {
+            super(cs, 1.0f, 1.0f);
+        }
+        protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+            int inLength = in.remaining();
+            for (int i = 0; i < inLength; ++i) {
+                in.put('x');
+                out.put((byte) 'y');
+            }
+            return CoderResult.UNDERFLOW;
+        }
+    }
+
+    private static final Charset EVIL_CHARSET = new Charset("evil", null) {
+        public boolean contains(Charset charset) { return false; }
+        public CharsetEncoder newEncoder() { return new EvilCharsetEncoder(this); }
+        public CharsetDecoder newDecoder() { return new EvilCharsetDecoder(this); }
+    };
+
+    public void testGetBytes() {
+        Charset cs = Charset.forName("UTF-8");
+        byte[] expected = new byte[] {(byte) 'h', (byte) 'i'};
+        assertTrue(Arrays.equals(expected, "hi".getBytes(cs)));
+    }
+
+    public void testGetBytes_MaliciousCharset() {
+        try {
+            String s = "hi";
+            // Check that our encoder can't write to the input CharBuffer
+            // it was given.
+            s.getBytes(EVIL_CHARSET);
+            fail(); // We shouldn't have got here!
+        } catch (ReadOnlyBufferException expected) {
+            // We caught you trying to be naughty!
+        }
+    }
+
+    public void testStringFromCharset() {
+        Charset cs = Charset.forName("UTF-8");
+        byte[] bytes = new byte[] {(byte) 'h', (byte) 'i'};
+        assertEquals("hi", new String(bytes, cs));
+    }
+
+    public void testStringFromCharset_MaliciousCharset() {
+        Charset cs = EVIL_CHARSET;
+        byte[] bytes = new byte[] {(byte) 'h', (byte) 'i'};
+        final String result = new String(bytes, cs);
+        assertEquals("YY", result); // (Our decoder always outputs 'Y's.)
+        // Check that even if the decoder messes with the output CharBuffer
+        // after we've created a string from it, it doesn't affect the string.
+        EvilCharsetDecoder.corrupt();
+        assertEquals("YY", result);
+    }
+}
diff --git a/libcore/luni/src/test/java/java/util/FormatterTest.java b/libcore/luni/src/test/java/java/util/FormatterTest.java
index 1722e67..c57c131 100644
--- a/libcore/luni/src/test/java/java/util/FormatterTest.java
+++ b/libcore/luni/src/test/java/java/util/FormatterTest.java
@@ -42,4 +42,32 @@
         // ...without screwing up conversions that don't take an argument.
         assertEquals("%", String.format(Locale.US, "%%"));
     }
+    
+    // Alleged regression tests for historical bugs. (It's unclear whether the bugs were in
+    // BigDecimal or Formatter.)
+    public void test_BigDecimalFormatting() throws Exception {
+        BigDecimal[] input = new BigDecimal[] {
+            new BigDecimal("20.00000"),
+            new BigDecimal("20.000000"),
+            new BigDecimal(".2"),
+            new BigDecimal("2"),
+            new BigDecimal("-2"),
+            new BigDecimal("200000000000000000000000"),
+            new BigDecimal("20000000000000000000000000000000000000000000000000")
+        };
+        String[] output = new String[] {
+            "20.00",
+            "20.00",
+            "0.20",
+            "2.00",
+            "-2.00",
+            "200000000000000000000000.00",
+            "20000000000000000000000000000000000000000000000000.00"
+        };
+        for (int i = 0; i < input.length; ++i) {
+            String result = String.format("%.2f", input[i]);
+            assertEquals("input=\"" + input[i] + "\", " + ",expected=" + output[i] + ",actual=" + result,
+                    output[i], result);
+        }
+    }
 }
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringTest.java
index 4ad0c52..efbb198 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringTest.java
@@ -17,31 +17,40 @@
 
 package org.apache.harmony.luni.tests.java.lang;
 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Constructor;
+import java.nio.charset.Charset;
+import java.util.SortedMap;
 
 import junit.framework.TestCase;
 
-import java.io.UnsupportedEncodingException;
-import java.math.BigDecimal;
-
-@TestTargetClass(String.class) 
 public class StringTest extends TestCase {
 
-    private static String newString(int start, int len, char[] data) {
-        return new String(data, start,len);
+    private static final Constructor<String> UNSAFE_CONSTRUCTOR;
+    static {
+        Constructor<String> uc;
+        try {
+            uc = String.class.getDeclaredConstructor(new Class[] { int.class,
+                    int.class, char[].class });
+            uc.setAccessible(true);
+        } catch (Exception e) {
+            uc = null;
+        }
+        UNSAFE_CONSTRUCTOR = uc;
+    }
+
+    private static String newString(int start, int len, char[] data) throws Exception {
+        if (UNSAFE_CONSTRUCTOR == null) {
+            return new String(data, start, len);
+        }
+
+        return UNSAFE_CONSTRUCTOR.newInstance(Integer.valueOf(start), Integer.valueOf(len),
+                    data);
     }
     
     /**
      * @tests java.lang.String#String()
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {}
-    )
     public void test_Constructor() {
         assertEquals("Created incorrect string", "", new String());
     }
@@ -49,12 +58,6 @@
     /**
      * @tests java.lang.String#String(byte[])
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {byte[].class}
-    )
     public void test_Constructor$B() {
         assertEquals("Failed to create string", "HelloWorld", new String(
                 "HelloWorld".getBytes()));
@@ -63,12 +66,6 @@
     /**
      * @tests java.lang.String#String(byte[], int)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {byte[].class, int.class}
-    )
     @SuppressWarnings("deprecation")
     public void test_Constructor$BI() {
         String s = new String(new byte[] { 65, 66, 67, 68, 69 }, 0);
@@ -80,12 +77,6 @@
     /**
      * @tests java.lang.String#String(byte[], int, int)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {byte[].class, int.class, int.class}
-    )
     public void test_Constructor$BII() {
         byte[] hwba = "HelloWorld".getBytes();
         assertEquals("Failed to create string", "HelloWorld", new String(hwba,
@@ -101,12 +92,6 @@
     /**
      * @tests java.lang.String#String(byte[], int, int, int)
      */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "IndexOutOfBoundsException is not verified.",
-        method = "String",
-        args = {byte[].class, int.class, int.class, int.class}
-    )
     @SuppressWarnings("deprecation")
     public void test_Constructor$BIII() {
         String s = new String(new byte[] { 65, 66, 67, 68, 69 }, 0, 1, 3);
@@ -118,33 +103,21 @@
     /**
      * @tests java.lang.String#String(byte[], int, int, java.lang.String)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {byte[].class, int.class, int.class, java.lang.String.class}
-    )
     public void test_Constructor$BIILjava_lang_String() throws Exception {
         String s = new String(new byte[] { 65, 66, 67, 68, 69 }, 0, 5, "8859_1");
         assertEquals("Incorrect string returned: " + s, "ABCDE", s);
         
         try {
-            new String(new byte[] { 65, 66, 67, 68, 69 }, 0, 5, "");
-            fail("Should throw UnsupportedEncodingException");
+        	new String(new byte[] { 65, 66, 67, 68, 69 }, 0, 5, "");
+        	fail("Should throw UnsupportedEncodingException");
         } catch (UnsupportedEncodingException e) {
-            //expected
+        	//expected
         }
     }
 
     /**
      * @tests java.lang.String#String(byte[], java.lang.String)
      */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "UnsupportedEncodingException is not verified.",
-        method = "String",
-        args = {byte[].class, java.lang.String.class}
-    )
     public void test_Constructor$BLjava_lang_String() throws Exception {
         String s = new String(new byte[] { 65, 66, 67, 68, 69 }, "8859_1");
         assertEquals("Incorrect string returned: " + s, "ABCDE", s);
@@ -153,12 +126,6 @@
     /**
      * @tests java.lang.String#String(char[])
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {char[].class}
-    )
     public void test_Constructor$C() {
         assertEquals("Failed Constructor test", "World", new String(new char[] {
                 'W', 'o', 'r', 'l', 'd' }));
@@ -167,12 +134,6 @@
     /**
      * @tests java.lang.String#String(char[], int, int)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {char[].class, int.class, int.class}
-    )
     public void test_Constructor$CII() throws Exception {
         char[] buf = { 'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd' };
         String s = new String(buf, 0, buf.length);
@@ -188,12 +149,6 @@
     /**
      * @tests java.lang.String#String(java.lang.String)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {java.lang.String.class}
-    )
     public void test_ConstructorLjava_lang_String() {
         String s = new String("Hello World");
         assertEquals("Failed to construct correct string", "Hello World", s);
@@ -202,12 +157,6 @@
     /**
      * @tests java.lang.String#String(java.lang.StringBuffer)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {java.lang.StringBuffer.class}
-    )
     public void test_ConstructorLjava_lang_StringBuffer() {
         StringBuffer sb = new StringBuffer();
         sb.append("HelloWorld");
@@ -217,12 +166,6 @@
     /**
      * @tests java.lang.String#String(java.lang.StringBuilder)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {java.lang.StringBuilder.class}
-    )
     public void test_ConstructorLjava_lang_StringBuilder() {
         StringBuilder sb = new StringBuilder(32);
         sb.append("HelloWorld");
@@ -238,12 +181,6 @@
     /**
      * @tests java.lang.String#String(int[],int,int)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "String",
-        args = {int[].class, int.class, int.class}
-    )
     public void test_Constructor$III() {
         assertEquals("HelloWorld", new String(new int[] { 'H', 'e', 'l', 'l',
                 'o', 'W', 'o', 'r', 'l', 'd' }, 0, 10));
@@ -292,13 +229,7 @@
     /**
      * @tests java.lang.String#contentEquals(CharSequence)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "contentEquals",
-        args = {java.lang.CharSequence.class}
-    )
-    public void test_contentEqualsLjava_lang_CharSequence() {
+    public void test_contentEqualsLjava_lang_CharSequence() throws Exception {
         String s = "abc";
         assertTrue(s.contentEquals((CharSequence) new StringBuffer("abc")));
         assertFalse(s.contentEquals((CharSequence) new StringBuffer("def")));
@@ -319,14 +250,8 @@
     /**
      * @tests java.lang.String#contentEquals(StringBuffer)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "contentEquals",
-        args = {java.lang.StringBuffer.class}
-    )
     @SuppressWarnings("nls")
-    public void test_boolean_contentEquals_StringBuffer() {
+    public void test_boolean_contentEquals_StringBuffer() throws Exception {
         String s = "abc";
         assertTrue(s.contentEquals(new StringBuffer("abc")));
         assertFalse(s.contentEquals(new StringBuffer("def")));
@@ -348,14 +273,8 @@
     /**
      * @tests java.lang.String#contains(CharSequence)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "contains",
-        args = {java.lang.CharSequence.class}
-    )
     @SuppressWarnings("cast")
-    public void test_containsLjava_lang_CharSequence() {
+    public void test_containsLjava_lang_CharSequence() throws Exception {
         String s = "abcdefghijklmnopqrstuvwxyz";
         assertTrue(s.contains((CharSequence) new StringBuffer("abc")));
         assertTrue(s.contains((CharSequence) new StringBuffer("def")));
@@ -376,13 +295,7 @@
     /**
      * @tests java.lang.String.offsetByCodePoints(int, int)'
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "offsetByCodePoints",
-        args = {int.class, int.class}
-    )
-    public void test_offsetByCodePointsII() {
+    public void test_offsetByCodePoints_II() throws Exception {
         int result = new String("a\uD800\uDC00b").offsetByCodePoints(0, 2);
         assertEquals(3, result);
 
@@ -505,13 +418,7 @@
     /**
      * @tests java.lang.StringBuilder.codePointAt(int)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "codePointAt",
-        args = {int.class}
-    )
-    public void test_codePointAtI() {
+    public void test_codePointAtI() throws Exception {
         String s = "abc";
         assertEquals('a', s.codePointAt(0));
         assertEquals('b', s.codePointAt(1));
@@ -572,13 +479,7 @@
     /**
      * @tests java.lang.StringBuilder.codePointBefore(int)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "codePointBefore",
-        args = {int.class}
-    )
-    public void test_codePointBeforeI() {
+    public void test_codePointBeforeI() throws Exception {
         String s = "abc";
         assertEquals('a', s.codePointBefore(1));
         assertEquals('b', s.codePointBefore(2));
@@ -639,13 +540,7 @@
     /**
      * @tests java.lang.StringBuilder.codePointCount(int, int)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "codePointCount",
-        args = {int.class, int.class}
-    )
-    public void test_codePointCountII() {
+    public void test_codePointCountII() throws Exception {
         assertEquals(1, "\uD800\uDC00".codePointCount(0, 2));
         assertEquals(1, "\uD800\uDC01".codePointCount(0, 2));
         assertEquals(1, "\uD801\uDC01".codePointCount(0, 2));
@@ -700,40 +595,165 @@
         } catch (IndexOutOfBoundsException e) {
         }
     }
-
-    @TestTargetNew(
-        level = TestLevel.ADDITIONAL,
-        notes = "Regression test for some existing bugs and crashes",
-        method = "format",
-        args = { String.class, Object[].class }
-    )
-    public void testProblemCases() {
-        BigDecimal[] input = new BigDecimal[] {
-            new BigDecimal("20.00000"),
-            new BigDecimal("20.000000"),
-            new BigDecimal(".2"),
-            new BigDecimal("2"),
-            new BigDecimal("-2"),
-            new BigDecimal("200000000000000000000000"),
-            new BigDecimal("20000000000000000000000000000000000000000000000000")
-        };
-
-        String[] output = new String[] {
-                "20.00",
-                "20.00",
-                "0.20",
-                "2.00",
-                "-2.00",
-                "200000000000000000000000.00",
-                "20000000000000000000000000000000000000000000000000.00"
-        };
-        
-        for (int i = 0; i < input.length; i++) {
-            String result = String.format("%.2f", input[i]);
-            assertEquals("Format test for \"" + input[i] + "\" failed, " +
-                    "expected=" + output[i] + ", " +
-                    "actual=" + result, output[i], result);
+    
+    /**
+     * @tests {@link java.lang.String#String(byte[], int, int, Charset)} 
+     * 
+     * @since 1.6
+     */
+    public void test_ConstructorBIIL() throws Exception {
+        // can construct normally
+        new String(new byte[8], 0, 4, Charset.defaultCharset());
+        new String(new byte[8], 8, 0, Charset.defaultCharset());
+        new String(new byte[0], 0, 0, Charset.defaultCharset());
+        // throws exceptions
+        try {
+            new String(new byte[8], 0, 9, Charset.defaultCharset());
+            fail("should throw StringIndexOutOfBoundsException");
+        } catch (StringIndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            new String(new byte[8], 9, 0, Charset.defaultCharset());
+            fail("should throw StringIndexOutOfBoundsException");
+        } catch (StringIndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            new String(new byte[8], -1, 0, Charset.defaultCharset());
+            fail("should throw StringIndexOutOfBoundsException");
+        } catch (StringIndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            new String(new byte[8], 9, -1, Charset.defaultCharset());
+            fail("should throw StringIndexOutOfBoundsException");
+        } catch (StringIndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            new String(null, -1, 0, Charset.defaultCharset());
+            fail("should throw StringIndexOutOfBoundsException");
+        } catch (StringIndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            new String(null, 0, -1, Charset.defaultCharset());
+            fail("should throw StringIndexOutOfBoundsException");
+        } catch (StringIndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            new String(null, 0, 9, Charset.defaultCharset());
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            new String(null, 0, 0, Charset.defaultCharset());
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            new String(null, -1, 0, (Charset)null);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            new String(new byte[8], -1, 0, (Charset)null);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            new String(new byte[8], 0, 9, (Charset)null);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            new String(new byte[8], 0, 4, (Charset)null);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
         }
     }
     
+    /**
+     * @tests {@link java.lang.String#String(byte[], Charset)}
+     * 
+     *  @since 1.6
+     */
+    public void test_ConstructorBL() throws Exception {
+        new String(new byte[8], Charset.defaultCharset());
+        try {
+            new String(new byte[8],(Charset)null);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            new String(new byte[0],(Charset)null);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            new String(null,Charset.defaultCharset());
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        new String(new byte[0], Charset.defaultCharset());
+    }
+    
+    /**
+     * @tests {@link java.lang.String#isEmpty()}
+     * 
+     * @since 1.6
+     */
+    public void test_isEmpty() throws Exception {
+        assertTrue(new String(new byte[0], Charset.defaultCharset()).isEmpty());
+        assertTrue(new String(new byte[8], Charset.defaultCharset()).substring(0, 0).isEmpty());
+    }
+    
+    /**
+     * @tests {@link java.lang.String#getBytes(Charset)}
+     * 
+     * @since 1.6
+     */
+    public void test_getBytesLCharset() throws Exception {
+        byte[] emptyBytes = new byte[0];
+        byte[] someBytes = new byte[]{'T','h','i','s',' ',' ','i','s',' ','t','e','s','t',' ','b','y','t','e','s'};
+        assertEquals(0, new String(emptyBytes, Charset.defaultCharset()).getBytes(Charset.defaultCharset()).length);
+        try{
+            new String(emptyBytes, Charset.defaultCharset()).getBytes((Charset)null);
+            fail("should throw NPE");
+        } catch (NullPointerException e){
+            // correct
+        }
+        assertTrue(bytesEquals(someBytes,new String(someBytes, Charset.defaultCharset()).getBytes(Charset.defaultCharset())));
+        SortedMap<String, Charset> charsets = Charset.availableCharsets();
+
+        Charset ascii = charsets.get("US-ASCII");
+        Charset utf8 = charsets.get("UTF-8");
+        if (charsets.size() >= 2){
+            // assertTrue(bytesEquals(someBytes,new String(someBytes, charsets.get(charsets.firstKey())).getBytes(charsets.get(charsets.lastKey()))));  android-changed: invalid test
+            assertFalse(bytesEquals("\u4f60\u597d".getBytes(ascii), "\u4f60\u597d".getBytes(utf8)));
+        }
+    }
+    
+    boolean bytesEquals(byte[] bytes1, byte[] bytes2){
+        if (bytes1.length == bytes2.length){
+            for (int i = 0; i < bytes1.length; i++){
+                if (bytes1[i] != bytes2[i]){
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
 }