Merge "Revert "reflection: Add new AnnotatedElement 1.8 methods.""
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java
index e9a73de..fdf6056 100644
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ b/dalvik/src/main/java/dalvik/system/DexPathList.java
@@ -245,12 +245,12 @@
     }
 
     /*
-     * TODO (dimitry): Revert after GMS core stops relying on the existence of this
-     * method (see b/21957414 for details)
+     * TODO (dimitry): Revert after apps stops relying on the existence of this
+     * method (see http://b/21957414 and http://b/26317852 for details)
      */
     private static Element[] makePathElements(List<File> files, File optimizedDirectory,
                                               List<IOException> suppressedExceptions) {
-        return makeElements(files, null, suppressedExceptions, true, null);
+        return makeElements(files, optimizedDirectory, suppressedExceptions, false, null);
     }
 
     private static Element[] makeElements(List<File> files, File optimizedDirectory,
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index db08a10..cf6c852 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -29,11 +29,6 @@
   bug: 2541757
 },
 {
-  description: "NaN character not found when deserializing DecimalFormatSymbols",
-  name: "libcore.java.text.OldDecimalFormatSymbolsTest#test_RIHarmony_compatible",
-  bug: 3056792
-},
-{
   description: "DecimalFormat is limited to 127 digits",
   name: "libcore.java.text.DecimalFormatTest#test_setMaximumIntegerDigits",
   bug: 2400429
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 13f693a..df0b6df 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -2171,8 +2171,8 @@
         testUrlToRequestMapping(")", ")", ")");
         testUrlToUriMapping("*", "*", "*", "*", "*");
         testUrlToRequestMapping("*", "*", "*");
-        testUrlToUriMapping("+", "+", "+", "%20", "+");
-        testUrlToRequestMapping("+", "+", "%20");
+        testUrlToUriMapping("+", "+", "+", "+", "+");
+        testUrlToRequestMapping("+", "+", "+");
         testUrlToUriMapping(",", ",", ",", ",", ",");
         testUrlToRequestMapping(",", ",", ",");
         testUrlToUriMapping("-", "-", "-", "-", "-");
diff --git a/luni/src/test/java/libcore/java/text/OldDecimalFormatSymbolsTest.java b/luni/src/test/java/libcore/java/text/OldDecimalFormatSymbolsTest.java
index c078684..fa98bf9 100644
--- a/luni/src/test/java/libcore/java/text/OldDecimalFormatSymbolsTest.java
+++ b/luni/src/test/java/libcore/java/text/OldDecimalFormatSymbolsTest.java
@@ -38,7 +38,7 @@
                     getClass()
                             .getClassLoader()
                             .getResourceAsStream(
-                    "serialization/java/text/DecimalFormatSymbols.ser"));
+                    "serialization/org/apache/harmony/tests/java/text/DecimalFormatSymbols.ser"));
             DecimalFormatSymbols riSymbols = (DecimalFormatSymbols) i.readObject();
             // RI's default NaN is U+FFFD, Harmony's is based on ICU
             // This suggests an RI bug, assuming that non-UTF8 bytes are UTF8 and
diff --git a/ojluni/src/main/java/java/text/DecimalFormat.java b/ojluni/src/main/java/java/text/DecimalFormat.java
index 49299a8..b8eade3 100755
--- a/ojluni/src/main/java/java/text/DecimalFormat.java
+++ b/ojluni/src/main/java/java/text/DecimalFormat.java
@@ -39,16 +39,15 @@
 
 package java.text;
 
-import java.io.InvalidObjectException;
 import java.io.IOException;
 import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.math.RoundingMode;
-import java.util.ArrayList;
 import java.util.Currency;
 import java.util.Locale;
-import java.util.ResourceBundle;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -380,6 +379,8 @@
  */
 public class DecimalFormat extends NumberFormat {
 
+    private transient android.icu.text.DecimalFormat icuDecimalFormat;
+
     /**
      * Creates a DecimalFormat using the default pattern and symbols
      * for the default locale. This is a convenient way to obtain a
@@ -395,9 +396,6 @@
      * @see java.text.NumberFormat#getCurrencyInstance
      * @see java.text.NumberFormat#getPercentInstance
      */
-
-    private android.icu.text.DecimalFormat icuDecimalFormat;
-
     public DecimalFormat() {
         Locale def = Locale.getDefault(Locale.Category.FORMAT);
         // try to get the pattern from the cache
@@ -409,12 +407,7 @@
             cachedLocaleData.putIfAbsent(def, pattern);
         }
         this.symbols = new DecimalFormatSymbols(def);
-        this.icuDecimalFormat =  new android.icu.text.DecimalFormat(pattern,
-                                                                    symbols.getIcuDecimalFormatSymbols());
-        maximumIntegerDigits = icuDecimalFormat.getMaximumIntegerDigits();
-        minimumIntegerDigits = icuDecimalFormat.getMinimumIntegerDigits();
-        maximumFractionDigits = icuDecimalFormat.getMaximumFractionDigits();
-        minimumFractionDigits = icuDecimalFormat.getMinimumFractionDigits();
+        init(pattern);
     }
 
 
@@ -438,12 +431,7 @@
      */
     public DecimalFormat(String pattern) {
         this.symbols = new DecimalFormatSymbols(Locale.getDefault(Locale.Category.FORMAT));
-        this.icuDecimalFormat =  new android.icu.text.DecimalFormat(pattern,
-                                                                    symbols.getIcuDecimalFormatSymbols());
-        maximumIntegerDigits = icuDecimalFormat.getMaximumIntegerDigits();
-        minimumIntegerDigits = icuDecimalFormat.getMinimumIntegerDigits();
-        maximumFractionDigits = icuDecimalFormat.getMaximumFractionDigits();
-        minimumFractionDigits = icuDecimalFormat.getMinimumFractionDigits();
+        init(pattern);
     }
 
 
@@ -471,8 +459,12 @@
     public DecimalFormat (String pattern, DecimalFormatSymbols symbols) {
         // Always applyPattern after the symbols are set
         this.symbols = (DecimalFormatSymbols)symbols.clone();
+        init(pattern);
+    }
+
+    private void init(String pattern) {
         this.icuDecimalFormat =  new android.icu.text.DecimalFormat(pattern,
-                                                                    symbols.getIcuDecimalFormatSymbols());
+                symbols.getIcuDecimalFormatSymbols());
         maximumIntegerDigits = icuDecimalFormat.getMaximumIntegerDigits();
         minimumIntegerDigits = icuDecimalFormat.getMinimumIntegerDigits();
         maximumFractionDigits = icuDecimalFormat.getMaximumFractionDigits();
@@ -1428,6 +1420,61 @@
         }
     }
 
+    private static final int currentSerialVersion = 4;
+
+    // the fields list to be serialized
+    private static final ObjectStreamField[] serialPersistentFields = {
+            new ObjectStreamField("positivePrefix", String.class),
+            new ObjectStreamField("positiveSuffix", String.class),
+            new ObjectStreamField("negativePrefix", String.class),
+            new ObjectStreamField("negativeSuffix", String.class),
+            new ObjectStreamField("posPrefixPattern", String.class),
+            new ObjectStreamField("posSuffixPattern", String.class),
+            new ObjectStreamField("negPrefixPattern", String.class),
+            new ObjectStreamField("negSuffixPattern", String.class),
+            new ObjectStreamField("multiplier", int.class),
+            new ObjectStreamField("groupingSize", byte.class),
+            new ObjectStreamField("groupingUsed", boolean.class),
+            new ObjectStreamField("decimalSeparatorAlwaysShown", boolean.class),
+            new ObjectStreamField("parseBigDecimal", boolean.class),
+            new ObjectStreamField("roundingMode", RoundingMode.class),
+            new ObjectStreamField("symbols", DecimalFormatSymbols.class),
+            new ObjectStreamField("useExponentialNotation", boolean.class),
+            new ObjectStreamField("minExponentDigits", byte.class),
+            new ObjectStreamField("maximumIntegerDigits", int.class),
+            new ObjectStreamField("minimumIntegerDigits", int.class),
+            new ObjectStreamField("maximumFractionDigits", int.class),
+            new ObjectStreamField("minimumFractionDigits", int.class),
+            new ObjectStreamField("serialVersionOnStream", int.class),
+    };
+
+    private void writeObject(ObjectOutputStream stream) throws IOException, ClassNotFoundException {
+        ObjectOutputStream.PutField fields = stream.putFields();
+        fields.put("positivePrefix", icuDecimalFormat.getPositivePrefix());
+        fields.put("positiveSuffix", icuDecimalFormat.getPositiveSuffix());
+        fields.put("negativePrefix", icuDecimalFormat.getNegativePrefix());
+        fields.put("negativeSuffix", icuDecimalFormat.getNegativeSuffix());
+        fields.put("posPrefixPattern", (String) null);
+        fields.put("posSuffixPattern", (String) null);
+        fields.put("negPrefixPattern", (String) null);
+        fields.put("negSuffixPattern", (String) null);
+        fields.put("multiplier", icuDecimalFormat.getMultiplier());
+        fields.put("groupingSize", (byte) icuDecimalFormat.getGroupingSize());
+        fields.put("groupingUsed", icuDecimalFormat.isGroupingUsed());
+        fields.put("decimalSeparatorAlwaysShown", icuDecimalFormat.isDecimalSeparatorAlwaysShown());
+        fields.put("parseBigDecimal", icuDecimalFormat.isParseBigDecimal());
+        fields.put("roundingMode", roundingMode);
+        fields.put("symbols", symbols);
+        fields.put("useExponentialNotation", false);
+        fields.put("minExponentDigits", (byte) 0);
+        fields.put("maximumIntegerDigits", icuDecimalFormat.getMaximumIntegerDigits());
+        fields.put("minimumIntegerDigits", icuDecimalFormat.getMinimumIntegerDigits());
+        fields.put("maximumFractionDigits", icuDecimalFormat.getMaximumFractionDigits());
+        fields.put("minimumFractionDigits", icuDecimalFormat.getMinimumFractionDigits());
+        fields.put("serialVersionOnStream", currentSerialVersion);
+        stream.writeFields();
+    }
+
     /**
      * Reads the default serializable fields from the stream and performs
      * validations and adjustments for older serialized versions. The
@@ -1472,49 +1519,47 @@
      * the pre-version-2 behavior.
      */
     private void readObject(ObjectInputStream stream)
-         throws IOException, ClassNotFoundException
-    {
-        stream.defaultReadObject();
+            throws IOException, ClassNotFoundException {
+        ObjectInputStream.GetField fields = stream.readFields();
+        this.symbols = (DecimalFormatSymbols) fields.get("symbols", null);
 
-        if (serialVersionOnStream < 4) {
-            setRoundingMode(RoundingMode.HALF_EVEN);
-        }
-        // We only need to check the maximum counts because NumberFormat
-        // .readObject has already ensured that the maximum is greater than the
-        // minimum count.
-        if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
-            super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
-            throw new InvalidObjectException("Digit count out of range");
-        }
+        init("");
 
-        // ICU has its own logic about what these values can be set to. We set the desired value
-        // on icuDecimalFormat and then update NumberFormat's idea of the limits to what ICU has
-        // allowed to be set. This isn't RI-compatible, but then very little of our
+        icuDecimalFormat.setPositivePrefix((String) fields.get("positivePrefix", ""));
+        icuDecimalFormat.setPositiveSuffix((String) fields.get("positiveSuffix", ""));
+        icuDecimalFormat.setNegativePrefix((String) fields.get("negativePrefix", "-"));
+        icuDecimalFormat.setNegativeSuffix((String) fields.get("negativeSuffix", ""));
+        icuDecimalFormat.setMultiplier(fields.get("multiplier", 1));
+        icuDecimalFormat.setGroupingSize(fields.get("groupingSize", (byte) 3));
+        icuDecimalFormat.setGroupingUsed(fields.get("groupingUsed", true));
+        icuDecimalFormat.setDecimalSeparatorAlwaysShown(fields.get("decimalSeparatorAlwaysShown",
+                false));
+
+        setRoundingMode((RoundingMode) fields.get("roundingMode", RoundingMode.HALF_EVEN));
+
+        final int maximumIntegerDigits = fields.get("maximumIntegerDigits", 309);
+        final int minimumIntegerDigits = fields.get("minimumIntegerDigits", 309);
+        final int maximumFractionDigits = fields.get("maximumFractionDigits", 340);
+        final int minimumFractionDigits = fields.get("minimumFractionDigits", 340);
+        // Tell ICU what we want, then ask it what we can have, and then
+        // set that in our Java object. This isn't RI-compatible, but then very little of our
         // behavior in this area is, and it's not obvious how we can second-guess ICU (or tell
-        // it to just do exactly what we ask).
+        // it to just do exactly what we ask). We only need to do this with maximumIntegerDigits
+        // because ICU doesn't seem to have its own ideas about the other options.
         icuDecimalFormat.setMaximumIntegerDigits(maximumIntegerDigits);
-        setMaximumIntegerDigits(icuDecimalFormat.getMaximumIntegerDigits());
+        super.setMaximumIntegerDigits(icuDecimalFormat.getMaximumIntegerDigits());
 
-        icuDecimalFormat.setMinimumIntegerDigits(minimumIntegerDigits);
-        setMinimumIntegerDigits(icuDecimalFormat.getMinimumIntegerDigits());
-
-        icuDecimalFormat.setMaximumFractionDigits(maximumFractionDigits);
-        setMaximumFractionDigits(icuDecimalFormat.getMaximumFractionDigits());
-
-        icuDecimalFormat.setMinimumFractionDigits(minimumFractionDigits);
+        setMinimumIntegerDigits(minimumIntegerDigits);
         setMinimumFractionDigits(minimumFractionDigits);
+        setMaximumFractionDigits(maximumFractionDigits);
+        setParseBigDecimal(fields.get("parseBigDecimal", false));
 
-        if (serialVersionOnStream < 3) {
+        if (fields.get("serialVersionOnStream", 0) < 3) {
             setMaximumIntegerDigits(super.getMaximumIntegerDigits());
             setMinimumIntegerDigits(super.getMinimumIntegerDigits());
             setMaximumFractionDigits(super.getMaximumFractionDigits());
             setMinimumFractionDigits(super.getMinimumFractionDigits());
         }
-        if (serialVersionOnStream < 1) {
-            // Didn't have exponential fields
-            useExponentialNotation = false;
-        }
-        serialVersionOnStream = currentSerialVersion;
     }
 
     //----------------------------------------------------------------------
@@ -1530,16 +1575,7 @@
      * @see #setDecimalFormatSymbols
      * @see java.text.DecimalFormatSymbols
      */
-    private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
-
-    /**
-     * True to force the use of exponential (i.e. scientific) notation when formatting
-     * numbers.
-     *
-     * @serial
-     * @since 1.2
-     */
-    private boolean useExponentialNotation;  // Newly persistent in the Java 2 platform v.1.2
+    private DecimalFormatSymbols symbols;
 
     /**
      * The maximum number of digits allowed in the integer portion of a
@@ -1597,34 +1633,7 @@
      */
     private RoundingMode roundingMode = RoundingMode.HALF_EVEN;
 
-    //----------------------------------------------------------------------
 
-    static final int currentSerialVersion = 4;
-
-    /**
-     * The internal serial version which says which version was written.
-     * Possible values are:
-     * <ul>
-     * <li><b>0</b> (default): versions before the Java 2 platform v1.2
-     * <li><b>1</b>: version for 1.2, which includes the two new fields
-     *      <code>useExponentialNotation</code> and
-     *      <code>minExponentDigits</code>.
-     * <li><b>2</b>: version for 1.3 and later, which adds four new fields:
-     *      <code>posPrefixPattern</code>, <code>posSuffixPattern</code>,
-     *      <code>negPrefixPattern</code>, and <code>negSuffixPattern</code>.
-     * <li><b>3</b>: version for 1.5 and later, which adds five new fields:
-     *      <code>maximumIntegerDigits</code>,
-     *      <code>minimumIntegerDigits</code>,
-     *      <code>maximumFractionDigits</code>,
-     *      <code>minimumFractionDigits</code>, and
-     *      <code>parseBigDecimal</code>.
-     * <li><b>4</b>: version for 1.6 and later, which adds one new field:
-     *      <code>roundingMode</code>.
-     * </ul>
-     * @since 1.2
-     * @serial
-     */
-    private int serialVersionOnStream = currentSerialVersion;
 
     //----------------------------------------------------------------------
     // CONSTANTS
diff --git a/ojluni/src/main/java/java/text/DecimalFormatSymbols.java b/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
index 4263f68..4ae3097 100755
--- a/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
+++ b/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
@@ -41,6 +41,8 @@
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
 import java.io.Serializable;
 import java.text.spi.DecimalFormatSymbolsProvider;
 import java.util.Currency;
@@ -741,6 +743,56 @@
     }
 
 
+    private static final ObjectStreamField[] serialPersistentFields = {
+            new ObjectStreamField("currencySymbol", String.class),
+            new ObjectStreamField("decimalSeparator", char.class),
+            new ObjectStreamField("digit", char.class),
+            new ObjectStreamField("exponential", char.class),
+            new ObjectStreamField("exponentialSeparator", String.class),
+            new ObjectStreamField("groupingSeparator", char.class),
+            new ObjectStreamField("infinity", String.class),
+            new ObjectStreamField("intlCurrencySymbol", String.class),
+            new ObjectStreamField("minusSign", char.class),
+            new ObjectStreamField("monetarySeparator", char.class),
+            new ObjectStreamField("NaN", String.class),
+            new ObjectStreamField("patternSeparator", char.class),
+            new ObjectStreamField("percent", char.class),
+            new ObjectStreamField("perMill", char.class),
+            new ObjectStreamField("serialVersionOnStream", int.class),
+            new ObjectStreamField("zeroDigit", char.class),
+            new ObjectStreamField("locale", Locale.class),
+            new ObjectStreamField("minusSignStr", String.class),
+            new ObjectStreamField("percentStr", String.class),
+    };
+
+    private void writeObject(ObjectOutputStream stream) throws IOException {
+        ObjectOutputStream.PutField fields = stream.putFields();
+        fields.put("currencySymbol", currencySymbol);
+        fields.put("decimalSeparator", getDecimalSeparator());
+        fields.put("digit", getDigit());
+        fields.put("exponential", exponentialSeparator.charAt(0));
+        fields.put("exponentialSeparator", exponentialSeparator);
+        fields.put("groupingSeparator", getGroupingSeparator());
+        fields.put("infinity", infinity);
+        fields.put("intlCurrencySymbol", intlCurrencySymbol);
+        fields.put("monetarySeparator", getMonetaryDecimalSeparator());
+        fields.put("NaN", NaN);
+        fields.put("patternSeparator", getPatternSeparator());
+        fields.put("perMill", getPerMill());
+        fields.put("serialVersionOnStream", 3);
+        fields.put("zeroDigit", getZeroDigit());
+        fields.put("locale", locale);
+
+        // Hardcode values here for backwards compatibility. These values will only be used
+        // if we're de-serializing this object on an earlier version of android.
+        fields.put("minusSign", minusSign);
+        fields.put("percent", percent);
+
+        fields.put("minusSignStr", getMinusSignString());
+        fields.put("percentStr", getPercentString());
+        stream.writeFields();
+    }
+
     /**
      * Reads the default serializable fields, provides default values for objects
      * in older serial versions, and initializes non-serializable fields.
@@ -758,30 +810,59 @@
      *
      * @since JDK 1.1.6
      */
-    private void readObject(ObjectInputStream stream)
-            throws IOException, ClassNotFoundException {
-        stream.defaultReadObject();
-        if (serialVersionOnStream < 1) {
-            // Didn't have monetarySeparator or exponential field;
-            // use defaults.
-            monetarySeparator = decimalSeparator;
-            exponential       = 'E';
-        }
-        if (serialVersionOnStream < 2) {
-            // didn't have locale; use root locale
-            locale = Locale.ROOT;
-        }
-        if (serialVersionOnStream < 3) {
-            // didn't have exponentialSeparator. Create one using exponential
-            exponentialSeparator = Character.toString(exponential);
-        }
-        serialVersionOnStream = currentSerialVersion;
+    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
+        ObjectInputStream.GetField fields = stream.readFields();
+        final int serialVersionOnStream = fields.get("serialVersionOnStream", 0);
+        currencySymbol = (String) fields.get("currencySymbol", "");
+        setDecimalSeparator(fields.get("decimalSeparator", '.'));
+        setDigit(fields.get("digit", '#'));
+        setGroupingSeparator(fields.get("groupingSeparator", ','));
+        infinity = (String) fields.get("infinity", "");
+        intlCurrencySymbol = (String) fields.get("intlCurrencySymbol", "");
+        NaN = (String) fields.get("NaN", "");
+        setPatternSeparator(fields.get("patternSeparator", ';'));
 
-        if (intlCurrencySymbol != null) {
-            try {
-                 currency = Currency.getInstance(intlCurrencySymbol);
-            } catch (IllegalArgumentException e) {
-            }
+        // Special handling for minusSign and percent. If we've serialized the string versions of
+        // these fields, use them. If not, fall back to the single character versions. This can
+        // only happen if we're de-serializing an object that was written by an older version of
+        // android (something that's strongly discouraged anyway).
+        final String minusSignStr = (String) fields.get("minusSignStr", null);
+        if (minusSignStr != null) {
+            minusSign = minusSignStr.charAt(0);
+        } else {
+            setMinusSign(fields.get("minusSign", '-'));
+        }
+        final String percentStr = (String) fields.get("percentStr", null);
+        if (percentStr != null) {
+            percent = percentStr.charAt(0);
+        } else {
+            setPercent(fields.get("percent", '%'));
+        }
+
+        setPerMill(fields.get("perMill", '\u2030'));
+        setZeroDigit(fields.get("zeroDigit", '0'));
+        locale = (Locale) fields.get("locale", null);
+        if (serialVersionOnStream == 0) {
+            setMonetaryDecimalSeparator(getDecimalSeparator());
+        } else {
+            setMonetaryDecimalSeparator(fields.get("monetarySeparator", '.'));
+        }
+
+        if (serialVersionOnStream == 0) {
+            // Prior to Java 1.1.6, the exponent separator wasn't configurable.
+            exponentialSeparator = "E";
+        } else if (serialVersionOnStream < 3) {
+            // In Javas 1.1.6 and 1.4, there was a character field "exponential".
+            setExponentSeparator(String.valueOf(fields.get("exponential", 'E')));
+        } else {
+            // In Java 6, there's a new "exponentialSeparator" field.
+            setExponentSeparator((String) fields.get("exponentialSeparator", "E"));
+        }
+
+        try {
+            currency = Currency.getInstance(intlCurrencySymbol);
+        } catch (IllegalArgumentException e) {
+            currency = null;
         }
     }