Merge "Fix bug #6140391 Make RTL awareness as an opt-in into the AndroidManifest"
diff --git a/api/current.txt b/api/current.txt
index 3a63d78..05fca90 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -596,7 +596,7 @@
     field public static final int layerType = 16843604; // 0x1010354
     field public static final int layout = 16842994; // 0x10100f2
     field public static final int layoutAnimation = 16842988; // 0x10100ec
-    field public static final int layoutDirection = 16843689; // 0x10103a9
+    field public static final int layoutDirection = 16843690; // 0x10103aa
     field public static final int layout_above = 16843140; // 0x1010184
     field public static final int layout_alignBaseline = 16843142; // 0x1010186
     field public static final int layout_alignBottom = 16843146; // 0x101018a
@@ -618,10 +618,10 @@
     field public static final int layout_height = 16842997; // 0x10100f5
     field public static final int layout_margin = 16842998; // 0x10100f6
     field public static final int layout_marginBottom = 16843002; // 0x10100fa
-    field public static final int layout_marginEnd = 16843693; // 0x10103ad
+    field public static final int layout_marginEnd = 16843694; // 0x10103ae
     field public static final int layout_marginLeft = 16842999; // 0x10100f7
     field public static final int layout_marginRight = 16843001; // 0x10100f9
-    field public static final int layout_marginStart = 16843692; // 0x10103ac
+    field public static final int layout_marginStart = 16843693; // 0x10103ad
     field public static final int layout_marginTop = 16843000; // 0x10100f8
     field public static final int layout_row = 16843643; // 0x101037b
     field public static final int layout_rowSpan = 16843644; // 0x101037c
@@ -717,10 +717,10 @@
     field public static final int packageNames = 16843649; // 0x1010381
     field public static final int padding = 16842965; // 0x10100d5
     field public static final int paddingBottom = 16842969; // 0x10100d9
-    field public static final int paddingEnd = 16843691; // 0x10103ab
+    field public static final int paddingEnd = 16843692; // 0x10103ac
     field public static final int paddingLeft = 16842966; // 0x10100d6
     field public static final int paddingRight = 16842968; // 0x10100d8
-    field public static final int paddingStart = 16843690; // 0x10103aa
+    field public static final int paddingStart = 16843691; // 0x10103ab
     field public static final int paddingTop = 16842967; // 0x10100d7
     field public static final int panelBackground = 16842846; // 0x101005e
     field public static final int panelColorBackground = 16842849; // 0x1010061
@@ -931,6 +931,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
+    field public static final int supportsRtl = 16843688; // 0x10103a8
     field public static final int supportsUploading = 16843419; // 0x101029b
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
@@ -1000,7 +1001,7 @@
     field public static final int textColorTertiary = 16843282; // 0x1010212
     field public static final int textColorTertiaryInverse = 16843283; // 0x1010213
     field public static final int textCursorDrawable = 16843618; // 0x1010362
-    field public static final int textDirection = 16843688; // 0x10103a8
+    field public static final int textDirection = 16843689; // 0x10103a9
     field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
     field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
     field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
@@ -6131,6 +6132,7 @@
     field public static final int FLAG_STOPPED = 2097152; // 0x200000
     field public static final int FLAG_SUPPORTS_LARGE_SCREENS = 2048; // 0x800
     field public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1024; // 0x400
+    field public static final int FLAG_SUPPORTS_RTL = 1073741824; // 0x40000000
     field public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 8192; // 0x2000
     field public static final int FLAG_SUPPORTS_SMALL_SCREENS = 512; // 0x200
     field public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 524288; // 0x80000
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 65a8750..cbabc7c 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -291,6 +291,17 @@
     public static final int FLAG_STOPPED = 1<<21;
 
     /**
+     * Value for {@link #flags}: true  when the application is willing to support
+     * RTL (right to left). All activities will inherit this value.
+     *
+     * Set from the {@link android.R.attr#supportsRtl} attribute in the
+     * activity's manifest.
+     *
+     * Default value is false (no support for RTL).
+     */
+    public static final int FLAG_SUPPORTS_RTL = 1<<22;
+
+    /**
      * Value for {@link #flags}: Set to true if the application has been
      * installed using the forward lock option.
      *
@@ -466,8 +477,17 @@
         if (uiOptions != 0) {
             pw.println(prefix + "uiOptions=0x" + Integer.toHexString(uiOptions));
         }
+        pw.println(prefix + "supportsRtl=" + (hasRtlSupport() ? "true" : "false"));
         super.dumpBack(pw, prefix);
     }
+
+    /**
+     * @return true if "supportsRtl" has been set to true in the AndroidManifest
+     * @hide
+     */
+    public boolean hasRtlSupport() {
+        return (flags & FLAG_SUPPORTS_RTL) == FLAG_SUPPORTS_RTL;
+    }
     
     public static class DisplayNameComparator
             implements Comparator<ApplicationInfo> {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index eb8536f..a79b86a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1761,6 +1761,12 @@
             ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
         }
 
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
+                false /* default is no RTL support*/)) {
+            ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
+        }
+
         String str;
         str = sa.getNonConfigurationString(
                 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 69d7655..a9421f0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9998,6 +9998,13 @@
     }
 
     /**
+     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
+     */
+    private boolean hasRtlSupport() {
+        return mContext.getApplicationInfo().hasRtlSupport();
+    }
+
+    /**
      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
      * that the parent directionality can and will be resolved before its children.
      * Will call {@link View#onResolvedLayoutDirectionChanged} when resolution is done.
@@ -10006,30 +10013,32 @@
         // Clear any previous layout direction resolution
         mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
 
-        // Set resolved depending on layout direction
-        switch (getLayoutDirection()) {
-            case LAYOUT_DIRECTION_INHERIT:
-                // If this is root view, no need to look at parent's layout dir.
-                if (canResolveLayoutDirection()) {
-                    ViewGroup viewGroup = ((ViewGroup) mParent);
+        if (hasRtlSupport()) {
+            // Set resolved depending on layout direction
+            switch (getLayoutDirection()) {
+                case LAYOUT_DIRECTION_INHERIT:
+                    // If this is root view, no need to look at parent's layout dir.
+                    if (canResolveLayoutDirection()) {
+                        ViewGroup viewGroup = ((ViewGroup) mParent);
 
-                    if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                            mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                        }
+                    } else {
+                        // Nothing to do, LTR by default
+                    }
+                    break;
+                case LAYOUT_DIRECTION_RTL:
+                    mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                    break;
+                case LAYOUT_DIRECTION_LOCALE:
+                    if(isLayoutDirectionRtl(Locale.getDefault())) {
                         mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
                     }
-                } else {
+                    break;
+                default:
                     // Nothing to do, LTR by default
-                }
-                break;
-            case LAYOUT_DIRECTION_RTL:
-                mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
-                break;
-            case LAYOUT_DIRECTION_LOCALE:
-                if(isLayoutDirectionRtl(Locale.getDefault())) {
-                    mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
-                }
-                break;
-            default:
-                // Nothing to do, LTR by default
+            }
         }
 
         // Set to resolved
@@ -14809,44 +14818,49 @@
         // Reset any previous text direction resolution
         mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
 
-        // Set resolved text direction flag depending on text direction flag
-        final int textDirection = getTextDirection();
-        switch(textDirection) {
-            case TEXT_DIRECTION_INHERIT:
-                if (canResolveTextDirection()) {
-                    ViewGroup viewGroup = ((ViewGroup) mParent);
+        if (hasRtlSupport()) {
+            // Set resolved text direction flag depending on text direction flag
+            final int textDirection = getTextDirection();
+            switch(textDirection) {
+                case TEXT_DIRECTION_INHERIT:
+                    if (canResolveTextDirection()) {
+                        ViewGroup viewGroup = ((ViewGroup) mParent);
 
-                    // Set current resolved direction to the same value as the parent's one
-                    final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
-                    switch (parentResolvedDirection) {
-                        case TEXT_DIRECTION_FIRST_STRONG:
-                        case TEXT_DIRECTION_ANY_RTL:
-                        case TEXT_DIRECTION_LTR:
-                        case TEXT_DIRECTION_RTL:
-                        case TEXT_DIRECTION_LOCALE:
-                            mPrivateFlags2 |=
-                                    (parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
-                            break;
-                        default:
-                            // Default resolved direction is "first strong" heuristic
-                            mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                        // Set current resolved direction to the same value as the parent's one
+                        final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
+                        switch (parentResolvedDirection) {
+                            case TEXT_DIRECTION_FIRST_STRONG:
+                            case TEXT_DIRECTION_ANY_RTL:
+                            case TEXT_DIRECTION_LTR:
+                            case TEXT_DIRECTION_RTL:
+                            case TEXT_DIRECTION_LOCALE:
+                                mPrivateFlags2 |=
+                                        (parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                                break;
+                            default:
+                                // Default resolved direction is "first strong" heuristic
+                                mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                        }
+                    } else {
+                        // We cannot do the resolution if there is no parent, so use the default one
+                        mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
                     }
-                } else {
-                    // We cannot do the resolution if there is no parent, so use the default one
+                    break;
+                case TEXT_DIRECTION_FIRST_STRONG:
+                case TEXT_DIRECTION_ANY_RTL:
+                case TEXT_DIRECTION_LTR:
+                case TEXT_DIRECTION_RTL:
+                case TEXT_DIRECTION_LOCALE:
+                    // Resolved direction is the same as text direction
+                    mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                    break;
+                default:
+                    // Default resolved direction is "first strong" heuristic
                     mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
-                }
-                break;
-            case TEXT_DIRECTION_FIRST_STRONG:
-            case TEXT_DIRECTION_ANY_RTL:
-            case TEXT_DIRECTION_LTR:
-            case TEXT_DIRECTION_RTL:
-            case TEXT_DIRECTION_LOCALE:
-                // Resolved direction is the same as text direction
-                mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
-                break;
-            default:
-                // Default resolved direction is "first strong" heuristic
-                mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+            }
+        } else {
+            // Default resolved direction is "first strong" heuristic
+            mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
         }
 
         // Set to resolved
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 4aa7dde..1649c48 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -843,6 +843,9 @@
              @hide -->
         <attr name="cantSaveState" format="boolean" />
         <attr name="uiOptions" />
+        <!-- Declare that your application will be able to deal with RTL (right to left) layouts.
+             If set to  false (default value), your application will not care about RTL layouts. -->
+        <attr name="supportsRtl" format="boolean" />
     </declare-styleable>
     
     <!-- The <code>permission</code> tag declares a security permission that can be
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9f29630..e5f049d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3551,6 +3551,8 @@
      =============================================================== -->
   <public type="attr" name="isolatedProcess" id="0x010103a7" />
 
+  <public type="attr" name="supportsRtl" id="0x010103a8" />
+
   <public type="attr" name="textDirection"/>
 
   <public type="attr" name="layoutDirection" />
diff --git a/tests/BiDiTests/AndroidManifest.xml b/tests/BiDiTests/AndroidManifest.xml
index c60edd8..4aead814 100644
--- a/tests/BiDiTests/AndroidManifest.xml
+++ b/tests/BiDiTests/AndroidManifest.xml
@@ -19,7 +19,9 @@
     android:versionCode="1"
     android:versionName="1.0">
 
-    <application android:label="BiDiTests" android:hardwareAccelerated="true">
+    <application android:label="BiDiTests"
+                 android:hardwareAccelerated="true"
+                 android:supportsRtl="true" >
 
         <activity android:name=".BiDiTestActivity"
             android:windowSoftInputMode="stateAlwaysHidden">