Fix bug #5199577 TextView with android:password="true" is showing the "dots" on the left even if the password chars are RTL

- force TextView to LOCALE text heuristic when in "password" mode
- remove TEXT_LAYOUT_DIRECTION_UNKNOWN_DO_NOT_USE
- LocaleUtils.getLayoutDirectionFromLocale() returns "LTR" is locale is NULL or ROOT

Change-Id: I182c46aaf2d73c8b18967fffa230bfabec91ed06
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index a00f790..5c3a17a 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -345,7 +345,6 @@
             sb.append(" (no locale)");
         }
         switch (textLayoutDirection) {
-            case LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE: sb.append(" ?layoutdir"); break;
             case LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE: sb.append(" rtl"); break;
             default: sb.append(" layoutdir="); sb.append(textLayoutDirection); break;
         }
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index 6debc6b..18b4040 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -17,6 +17,10 @@
 package android.text;
 
 
+import java.util.Locale;
+
+import android.util.LocaleUtil;
+
 /**
  * Some objects that implement TextDirectionHeuristic.
  * @hide
@@ -75,6 +79,11 @@
     public static final TextDirectionHeuristic CHARCOUNT_RTL =
         new TextDirectionHeuristicInternal(CharCount.INSTANCE_DEFAULT, true);
 
+    /**
+     * Force the paragraph direction to the Locale direction. Falls back to left to right.
+     */
+    public static final TextDirectionHeuristic LOCALE = TextDirectionHeuristicLocale.INSTANCE;
+
     private static enum TriState {
         TRUE, FALSE, UNKNOWN;
     }
@@ -300,4 +309,23 @@
         public static final float DEFAULT_THRESHOLD = 0.6f;
         public static final CharCount INSTANCE_DEFAULT = new CharCount(DEFAULT_THRESHOLD);
     }
+
+    /**
+     * Algorithm that uses the Locale direction to force the direction of a paragraph.
+     */
+    public static class TextDirectionHeuristicLocale extends TextDirectionHeuristicImpl {
+
+        public TextDirectionHeuristicLocale() {
+            super(null);
+        }
+
+        @Override
+        protected boolean defaultIsRtl() {
+            final int dir = LocaleUtil.getLayoutDirectionFromLocale(java.util.Locale.getDefault());
+            return (dir == LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE);
+        }
+
+        public static final TextDirectionHeuristicLocale INSTANCE =
+                new TextDirectionHeuristicLocale();
+    }
 }
diff --git a/core/java/android/util/LocaleUtil.java b/core/java/android/util/LocaleUtil.java
index 74a930f..763af73 100644
--- a/core/java/android/util/LocaleUtil.java
+++ b/core/java/android/util/LocaleUtil.java
@@ -32,11 +32,6 @@
     /**
      * @hide Do not use. Implementation not finished.
      */
-    public static final int TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE = -1;
-
-    /**
-     * @hide Do not use. Implementation not finished.
-     */
     public static final int TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE = 0;
 
     /**
@@ -54,7 +49,6 @@
      *
      * @param locale the Locale for which we want the layout direction. Can be null.
      * @return the layout direction. This may be one of:
-     * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
      *
@@ -63,17 +57,16 @@
      * @hide
      */
     public static int getLayoutDirectionFromLocale(Locale locale) {
-        if (locale == null || locale.equals(Locale.ROOT)) {
-            return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
+        if (locale != null && !locale.equals(Locale.ROOT)) {
+            final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
+            if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
+
+            if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
+                    scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
+                return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
+            }
         }
 
-        final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
-        if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
-
-        if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
-                scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
-            return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
-        }
         return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
     }
 
@@ -84,7 +77,6 @@
      *
      * @param locale
      * @return the layout direction. This may be one of:
-     * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
      *
@@ -94,13 +86,13 @@
      */
     private static int getLayoutDirectionFromFirstChar(Locale locale) {
         switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) {
-            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
-                return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
                 return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
+
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
             default:
-                return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
+                return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
         }
     }
 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a3e67cc..d830f20 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10701,6 +10701,11 @@
 
     @Override
     protected void resolveTextDirection() {
+        if (hasPasswordTransformationMethod()) {
+            mTextDir = TextDirectionHeuristics.LOCALE;
+            return;
+        }
+
         // Always need to resolve layout direction first
         final boolean defaultIsRtl = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
 
diff --git a/core/tests/coretests/src/android/util/LocaleUtilTest.java b/core/tests/coretests/src/android/util/LocaleUtilTest.java
index 203781f..ff3d539 100644
--- a/core/tests/coretests/src/android/util/LocaleUtilTest.java
+++ b/core/tests/coretests/src/android/util/LocaleUtilTest.java
@@ -23,7 +23,6 @@
 import dalvik.annotation.TestTargetNew;
 
 import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
-import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
 
 public class LocaleUtilTest extends AndroidTestCase {
 
@@ -33,7 +32,7 @@
         args = {Locale.class}
     )
     public void testGetLayoutDirectionFromLocale() {
-        assertEquals(TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
+        assertEquals(TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
                 LocaleUtil.getLayoutDirectionFromLocale(null));
 
         assertEquals(TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
@@ -59,7 +58,7 @@
         assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             LocaleUtil.getLayoutDirectionFromLocale(Locale.US));
 
-        assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
+        assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             LocaleUtil.getLayoutDirectionFromLocale(Locale.ROOT));
 
         assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
diff --git a/tests/BiDiTests/res/layout/basic.xml b/tests/BiDiTests/res/layout/basic.xml
index 8a27213..f503658 100644
--- a/tests/BiDiTests/res/layout/basic.xml
+++ b/tests/BiDiTests/res/layout/basic.xml
@@ -27,11 +27,18 @@
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content">
 
-            <Button android:id="@+id/button"
+            <TextView android:id="@+id/textview_password_default"
                     android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button_text"
                     android:textSize="32dip"
+                    android:text="@string/textview_password_default_text"
+            />
+
+            <EditText android:id="@+id/edittext_password_default"
+                      android:layout_height="wrap_content"
+                      android:layout_width="match_parent"
+                      android:textSize="32dip"
+                      android:password="true"
                     />
 
             <TextView android:id="@+id/textview_default"
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index b0809da..b1f5e50e 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -28,6 +28,7 @@
     <string name="textview_ltr_text">This is a text for a LTR TextView</string>
     <string name="textview_rtl_text">This is a text for a RTL TextView</string>
     <string name="textview_default_text">This is a text for a default TextView</string>
+    <string name="textview_password_default_text">This is a text for a password TextView</string>
     <string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
     <string name="normal_text">Normal String</string>
     <string name="normal_long_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>