Fix deadlock between java.util and ICU TimeZone.

There was a deadlock between java.util.TimeZone.setDefault() and
android.icu.util.TimeZone.getDefault():

- the former would lock on j.u.TimeZone.class and the call
  the synchronized a.i.u.TimeZone.clearCachedDefault()
- the latter would synchronize on a.i.u.TimeZone and then call
  the synchronized j.u.TimeZone.getDefault

To ensure every path synchronizes on objects in the same order, this
change adds an explicit synchronize block on j.u.TimeZone in
a.i.u.TimeZone.getDefault().

TimeZoneTest.testSetDefaultDeadlock() is a probabilistic test that was
able to reproduce the problem roughly 8 times out of 10.

Bug: 30937209
Test: libcore/run-libcore-tests libcore.java.util
  org.apache.harmony.tests.java.util

(cherry picked from commit 15c4b7460a92a69ca40db46baf17e205421fa8a1)

Change-Id: Ic3f2db31195f12c27fb9b4f30a54d2bf19b4e52c
diff --git a/android_icu4j/src/main/java/android/icu/util/TimeZone.java b/android_icu4j/src/main/java/android/icu/util/TimeZone.java
index 27f2eec0..7b64afe 100644
--- a/android_icu4j/src/main/java/android/icu/util/TimeZone.java
+++ b/android_icu4j/src/main/java/android/icu/util/TimeZone.java
@@ -845,16 +845,26 @@
      */
     public static TimeZone getDefault() {
         if (defaultZone == null) {
-            synchronized(TimeZone.class) {
-                if (defaultZone == null) {
-                    if (TZ_IMPL == TIMEZONE_JDK) {
-                        defaultZone = new JavaTimeZone();
-                    } else {
-                        java.util.TimeZone temp = java.util.TimeZone.getDefault();
-                        defaultZone = getFrozenTimeZone(temp.getID());
+            // Android patch (http://b/30937209) start.
+            // Avoid a deadlock by always acquiring monitors in order (1) java.util.TimeZone.class
+            // then (2) icu.util.TimeZone.class and not (2) then (1).
+            // Without the synchronized here there is a possible deadlock between threads calling
+            // this method and other threads calling methods on java.util.TimeZone. e.g.
+            // java.util.TimeZone.setDefault() calls back into
+            // icu.util.TimeZone.clearCachedDefault() so always acquires them in order (1) then (2).
+            synchronized (java.util.TimeZone.class) {
+                synchronized (TimeZone.class) {
+                    if (defaultZone == null) {
+                        if (TZ_IMPL == TIMEZONE_JDK) {
+                            defaultZone = new JavaTimeZone();
+                        } else {
+                            java.util.TimeZone temp = java.util.TimeZone.getDefault();
+                            defaultZone = getFrozenTimeZone(temp.getID());
+                        }
                     }
                 }
             }
+            // Android patch (http://b/30937209) end.
         }
         return defaultZone.cloneAsThawed();
     }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java b/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java
index dc9b7d3..6a37b36 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java
@@ -922,16 +922,26 @@
      */
     public static TimeZone getDefault() {
         if (defaultZone == null) {
-            synchronized(TimeZone.class) {
-                if (defaultZone == null) {
-                    if (TZ_IMPL == TIMEZONE_JDK) {
-                        defaultZone = new JavaTimeZone();
-                    } else {
-                        java.util.TimeZone temp = java.util.TimeZone.getDefault();
-                        defaultZone = getFrozenTimeZone(temp.getID());
+            // Android patch (http://b/30937209) start.
+            // Avoid a deadlock by always acquiring monitors in order (1) java.util.TimeZone.class
+            // then (2) icu.util.TimeZone.class and not (2) then (1).
+            // Without the synchronized here there is a possible deadlock between threads calling
+            // this method and other threads calling methods on java.util.TimeZone. e.g.
+            // java.util.TimeZone.setDefault() calls back into
+            // icu.util.TimeZone.clearCachedDefault() so always acquires them in order (1) then (2).
+            synchronized (java.util.TimeZone.class) {
+                synchronized (TimeZone.class) {
+                    if (defaultZone == null) {
+                        if (TZ_IMPL == TIMEZONE_JDK) {
+                            defaultZone = new JavaTimeZone();
+                        } else {
+                            java.util.TimeZone temp = java.util.TimeZone.getDefault();
+                            defaultZone = getFrozenTimeZone(temp.getID());
+                        }
                     }
                 }
             }
+            // Android patch (http://b/30937209) end.
         }
         return defaultZone.cloneAsThawed();
     }