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());
+ }
}