Remove DateFormat time pattern caching

This change removes pattern string caching from
the SimpleDateFormat constructor only used by
DateFormat.getInstance().

Before this change, the LocaleData.getTimeFormat(int) method
that is used to populate the cached data can return different
information for SHORT and MEDIUM times based on the
DateFormat.is24Hour setting and so the results are not safe
to cache: if the user modifies their "use 24-hour format"
setting and the data is already cached the old pattern was
persisted forever.

This was also causing various CTS tests to fail if the device
had the "use 24-hour format" setting on. For example:

libcore.java.text.OldDateFormatTest
org.apache.harmony.tests.java.text.MessageFormatTest
org.apache.harmony.tests.java.util.DateTest

Callers of java.text.DateFormat.get(int, int, int, Locale)
are affected. In practice that means DateFormat.getTimeInstance()
/ getTimeInstance(int) and getTimeInstance(int, Locale).

Indirect callers in the Android framework include:
android.text.format.DateUtils
android.text.format.DateFormat
android.widget.DigitalClock
java.text.MessageFormat

This change has a small negative affect on performance, but
not a significant one: obtaining a DateFormat via
DateFormat.getTimeInstance() goes from ~28us to
~33us on an Angler device.

Full results for the benchmarks included:

Before:

benchmarkMethod=timeGetDateTimeInstance
runtime(ns): min=27518.68, 1st qu.=28461.12, median=28775.87,
mean=28732.44, 3rd qu.=29235.59, max=29320.80
runtime(ns): min=28599.17, 1st qu.=28769.57, median=29277.13,
mean=29682.69, 3rd qu.=29824.08, max=33419.06

benchmarkMethod=timeGetDateTimeInstance_multiple
runtime(ns): min=108667.38, 1st qu.=110223.70, median=111547.98,
mean=112173.89, 3rd qu.=113748.88, max=118091.12
runtime(ns): min=102995.66, 1st qu.=105045.16, median=108558.77,
mean=108817.18, 3rd qu.=111677.65, max=115886.11

After:

benchmarkMethod=timeGetDateTimeInstance
runtime(ns): min=31365.39, 1st qu.=32904.01, median=33303.47,
mean=33244.55, 3rd qu.=33983.32, max=34052.99
runtime(ns): min=31785.28, 1st qu.=32921.68, median=33364.01,
mean=33531.03, 3rd qu.=34301.06, max=35031.33

benchmarkMethod=timeGetDateTimeInstance_multiple
runtime(ns): min=126834.48, 1st qu.=128605.17, median=130069.44,
mean=131157.63, 3rd qu.=134095.26, max=138164.92
runtime(ns): min=124618.08, 1st qu.=126097.91, median=130190.93,
mean=130027.17, 3rd qu.=131991.56, max=140283.06

Bug: 31762542
Test: Ran CtsLibcoreTestCases with the "use 24-hour format" on
      and off
Change-Id: I02798e8fcd2ed5f7625a32261112560b5d9b18f3
diff --git a/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java b/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java
new file mode 100644
index 0000000..bd5bf1a
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * 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 benchmarks.regression;
+
+import com.google.caliper.BeforeExperiment;
+
+import java.text.DateFormat;
+import java.util.Locale;
+
+public final class DateFormatBenchmark {
+
+    private Locale locale1;
+    private Locale locale2;
+    private Locale locale3;
+    private Locale locale4;
+
+    @BeforeExperiment
+    protected void setUp() throws Exception {
+        locale1 = Locale.TAIWAN;
+        locale2 = Locale.GERMANY;
+        locale3 = Locale.FRANCE;
+        locale4 = Locale.ITALY;
+    }
+
+    public void timeGetDateTimeInstance(int reps) throws Exception {
+        for (int i = 0; i < reps; ++i) {
+            DateFormat.getDateTimeInstance();
+        }
+    }
+
+    public void timeGetDateTimeInstance_multiple(int reps) throws Exception {
+        for (int i = 0; i < reps; ++i) {
+            DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale1);
+            DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale2);
+            DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale3);
+            DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale4);
+        }
+    }
+}
diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index 72ff142..62cbd00 100755
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -502,12 +502,6 @@
     private static final String GMT = "GMT";
 
     /**
-     * Cache to hold the DateTimePatterns of a Locale.
-     */
-    private static final ConcurrentMap<Locale, String[]> cachedLocaleData
-        = new ConcurrentHashMap<Locale, String[]>(3);
-
-    /**
      * Cache NumberFormat instances with Locale key.
      */
     private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
@@ -618,33 +612,20 @@
         // initialize calendar and related fields
         initializeCalendar(loc);
 
-        /* try the cache first */
-        String[] dateTimePatterns = cachedLocaleData.get(loc);
-        if (dateTimePatterns == null) { /* cache miss */
-            LocaleData localeData = LocaleData.get(loc);
-            dateTimePatterns = new String[9];
-            dateTimePatterns[DateFormat.SHORT + 4] = localeData.getDateFormat(DateFormat.SHORT);
-            dateTimePatterns[DateFormat.MEDIUM + 4] = localeData.getDateFormat(DateFormat.MEDIUM);
-            dateTimePatterns[DateFormat.LONG + 4] = localeData.getDateFormat(DateFormat.LONG);
-            dateTimePatterns[DateFormat.FULL + 4] = localeData.getDateFormat(DateFormat.FULL);
-            dateTimePatterns[DateFormat.SHORT] = localeData.getTimeFormat(DateFormat.SHORT);
-            dateTimePatterns[DateFormat.MEDIUM] = localeData.getTimeFormat(DateFormat.MEDIUM);
-            dateTimePatterns[DateFormat.LONG] = localeData.getTimeFormat(DateFormat.LONG);
-            dateTimePatterns[DateFormat.FULL] = localeData.getTimeFormat(DateFormat.FULL);
-            dateTimePatterns[8] = "{0} {1}";
-            /* update cache */
-            cachedLocaleData.putIfAbsent(loc, dateTimePatterns);
-        }
         formatData = DateFormatSymbols.getInstanceRef(loc);
+        LocaleData localeData = LocaleData.get(loc);
         if ((timeStyle >= 0) && (dateStyle >= 0)) {
-            Object[] dateTimeArgs = {dateTimePatterns[dateStyle + 4], dateTimePatterns[timeStyle]};
-            pattern = MessageFormat.format(dateTimePatterns[8], dateTimeArgs);
+            Object[] dateTimeArgs = {
+                localeData.getDateFormat(dateStyle),
+                localeData.getTimeFormat(timeStyle),
+            };
+            pattern = MessageFormat.format("{0} {1}", dateTimeArgs);
         }
         else if (timeStyle >= 0) {
-            pattern = dateTimePatterns[timeStyle];
+            pattern = localeData.getTimeFormat(timeStyle);
         }
         else if (dateStyle >= 0) {
-            pattern = dateTimePatterns[dateStyle + 4];
+            pattern = localeData.getDateFormat(dateStyle);
         }
         else {
             throw new IllegalArgumentException("No date or time style specified");