Support all RTL scripts in getLayoutDirectionFromLocale().

Previously, only the languages written in Arabic and Hebrew were
considered right-to-left. Now, ICU is used to return the direction
of the language, which not only support other right-to-left scripts
(such as Thaana), but also has better logic to determine the
direction of the locale and uses caching to improve the speed.

Bug: 22559274
Change-Id: I760be7984a9b35ea77d59ca84a220798e205af36
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index d8f7158..8132dee 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.content.res.Resources;
+import android.icu.util.ULocale;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemProperties;
@@ -1754,45 +1755,12 @@
      * Be careful: this code will need to be updated when vertical scripts will be supported
      */
     public static int getLayoutDirectionFromLocale(Locale locale) {
-        if (locale != null && !locale.equals(Locale.ROOT)) {
-            final String scriptSubtag = ICU.addLikelySubtags(locale).getScript();
-            if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
-
-            if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
-                    scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
-                return View.LAYOUT_DIRECTION_RTL;
-            }
-        }
-        // If forcing into RTL layout mode, return RTL as default, else LTR
-        return SystemProperties.getBoolean(Settings.Global.DEVELOPMENT_FORCE_RTL, false)
-                ? View.LAYOUT_DIRECTION_RTL
-                : View.LAYOUT_DIRECTION_LTR;
-    }
-
-    /**
-     * Fallback algorithm to detect the locale direction. Rely on the fist char of the
-     * localized locale name. This will not work if the localized locale name is in English
-     * (this is the case for ICU 4.4 and "Urdu" script)
-     *
-     * @param locale
-     * @return the layout direction. This may be one of:
-     * {@link View#LAYOUT_DIRECTION_LTR} or
-     * {@link View#LAYOUT_DIRECTION_RTL}.
-     *
-     * Be careful: this code will need to be updated when vertical scripts will be supported
-     *
-     * @hide
-     */
-    private static int getLayoutDirectionFromFirstChar(Locale locale) {
-        switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) {
-            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
-            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
-                return View.LAYOUT_DIRECTION_RTL;
-
-            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
-            default:
-                return View.LAYOUT_DIRECTION_LTR;
-        }
+        return ((locale != null && !locale.equals(Locale.ROOT)
+                        && ULocale.forLocale(locale).isRightToLeft())
+                // If forcing into RTL layout mode, return RTL as default
+                || SystemProperties.getBoolean(Settings.Global.DEVELOPMENT_FORCE_RTL, false))
+            ? View.LAYOUT_DIRECTION_RTL
+            : View.LAYOUT_DIRECTION_LTR;
     }
 
     /**
@@ -1811,7 +1779,4 @@
     private static String[] EMPTY_STRING_ARRAY = new String[]{};
 
     private static final char ZWNBS_CHAR = '\uFEFF';
-
-    private static String ARAB_SCRIPT_SUBTAG = "Arab";
-    private static String HEBR_SCRIPT_SUBTAG = "Hebr";
 }
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index 5a6ef30..121f02a 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -25,9 +25,11 @@
 import android.text.style.StyleSpan;
 import android.text.util.Rfc822Token;
 import android.text.util.Rfc822Tokenizer;
+import android.view.View;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import junit.framework.TestCase;
 
@@ -519,4 +521,46 @@
             return 0;
         }
     }
+
+    @SmallTest
+    public void testGetLayoutDirectionFromLocale() {
+        assertEquals(View.LAYOUT_DIRECTION_LTR, TextUtils.getLayoutDirectionFromLocale(null));
+        assertEquals(View.LAYOUT_DIRECTION_LTR,
+                TextUtils.getLayoutDirectionFromLocale(Locale.ROOT));
+        assertEquals(View.LAYOUT_DIRECTION_LTR,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("en")));
+        assertEquals(View.LAYOUT_DIRECTION_LTR,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("en-US")));
+        assertEquals(View.LAYOUT_DIRECTION_LTR,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("az")));
+        assertEquals(View.LAYOUT_DIRECTION_LTR,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("az-AZ")));
+        assertEquals(View.LAYOUT_DIRECTION_LTR,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("az-Latn")));
+        assertEquals(View.LAYOUT_DIRECTION_LTR,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("en-EG")));
+        assertEquals(View.LAYOUT_DIRECTION_LTR,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("ar-Latn")));
+
+        assertEquals(View.LAYOUT_DIRECTION_RTL,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("ar")));
+        assertEquals(View.LAYOUT_DIRECTION_RTL,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("fa")));
+        assertEquals(View.LAYOUT_DIRECTION_RTL,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("he")));
+        assertEquals(View.LAYOUT_DIRECTION_RTL,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("iw")));
+        assertEquals(View.LAYOUT_DIRECTION_RTL,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("ur")));
+        assertEquals(View.LAYOUT_DIRECTION_RTL,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("dv")));
+        assertEquals(View.LAYOUT_DIRECTION_RTL,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("az-Arab")));
+        assertEquals(View.LAYOUT_DIRECTION_RTL,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("az-IR")));
+        assertEquals(View.LAYOUT_DIRECTION_RTL,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("fa-US")));
+        assertEquals(View.LAYOUT_DIRECTION_RTL,
+                TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("tr-Arab")));
+    }
 }