Serialize minusSign/percentSign as strings in DecimalFormatSymbols.

This allows us to Parcel DFS objects (not sure why anybody would
do that, but..) without crashes.

bug: https://code.google.com/p/android/issues/detail?id=170718
bug: 21455225

(cherry picked from commit 4fd2c14ce54447f13cd115e105d7b000adf24c2e)

Change-Id: I8f860b3fc764932291000ac6651bc95a8e457a99
diff --git a/luni/src/main/java/java/text/DecimalFormatSymbols.java b/luni/src/main/java/java/text/DecimalFormatSymbols.java
index 2f1d4f4..69c4935 100644
--- a/luni/src/main/java/java/text/DecimalFormatSymbols.java
+++ b/luni/src/main/java/java/text/DecimalFormatSymbols.java
@@ -601,6 +601,8 @@
         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 {
@@ -613,15 +615,21 @@
         fields.put("groupingSeparator", getGroupingSeparator());
         fields.put("infinity", infinity);
         fields.put("intlCurrencySymbol", intlCurrencySymbol);
-        fields.put("minusSign", getMinusSign());
         fields.put("monetarySeparator", getMonetaryDecimalSeparator());
         fields.put("NaN", NaN);
         fields.put("patternSeparator", getPatternSeparator());
-        fields.put("percent", getPercent());
         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.length() == 1 ? minusSign.charAt(0) : '-');
+        fields.put("percent", percent.length() == 1 ? percent.charAt(0) : '%');
+
+        fields.put("minusSignStr", getMinusSignString());
+        fields.put("percentStr", getPercentString());
         stream.writeFields();
     }
 
@@ -634,10 +642,26 @@
         setGroupingSeparator(fields.get("groupingSeparator", ','));
         infinity = (String) fields.get("infinity", "");
         intlCurrencySymbol = (String) fields.get("intlCurrencySymbol", "");
-        setMinusSign(fields.get("minusSign", '-'));
         NaN = (String) fields.get("NaN", "");
         setPatternSeparator(fields.get("patternSeparator", ';'));
-        setPercent(fields.get("percent", '%'));
+
+        // 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;
+        } else {
+            setMinusSign(fields.get("minusSign", '-'));
+        }
+        final String percentStr = (String) fields.get("percentStr", null);
+        if (percentStr != null) {
+            percent = percentStr;
+        } else {
+            setPercent(fields.get("percent", '%'));
+        }
+
         setPerMill(fields.get("perMill", '\u2030'));
         setZeroDigit(fields.get("zeroDigit", '0'));
         locale = (Locale) fields.get("locale", null);
diff --git a/luni/src/test/java/libcore/java/text/DecimalFormatSymbolsTest.java b/luni/src/test/java/libcore/java/text/DecimalFormatSymbolsTest.java
index 3e0aeba..564001a 100644
--- a/luni/src/test/java/libcore/java/text/DecimalFormatSymbolsTest.java
+++ b/luni/src/test/java/libcore/java/text/DecimalFormatSymbolsTest.java
@@ -86,4 +86,24 @@
         assertEquals("$", dfs.getCurrencySymbol());
         assertEquals(null, dfs.getInternationalCurrencySymbol());
     }
+
+    // https://code.google.com/p/android/issues/detail?id=170718
+    public void testSerializationOfMultiCharNegativeAndPercentage() throws Exception {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.forLanguageTag("ar-AR"));
+        assertTrue(dfs.getMinusSignString().length() > 1);
+        assertTrue(dfs.getPercentString().length() > 1);
+
+        // Serialize...
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        new ObjectOutputStream(out).writeObject(dfs);
+        byte[] bytes = out.toByteArray();
+
+        // Deserialize...
+        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
+        DecimalFormatSymbols deserializedDfs = (DecimalFormatSymbols) in.readObject();
+        assertEquals(-1, in.read());
+
+        assertEquals(dfs.getMinusSignString(), deserializedDfs.getMinusSignString());
+        assertEquals(dfs.getPercentString(), deserializedDfs.getPercentString());
+    }
 }