am 68411471: Merge "Fix layout rendering for RTL locales" into jb-mr2-dev

* commit '68411471083abd7a7713483b5cd40f394387b7b3':
  Fix layout rendering for RTL locales
diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath
index 3c124d9..2e4274d 100644
--- a/tools/layoutlib/bridge/.classpath
+++ b/tools/layoutlib/bridge/.classpath
@@ -7,5 +7,6 @@
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/icu4j/icu4j.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index 687a91f..e3d48fc 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -22,6 +22,7 @@
 
 LOCAL_JAVA_LIBRARIES := \
 	kxml2-2.3.0 \
+	icu4j \
 	layoutlib_api-prebuilt \
 	tools-common-prebuilt
 
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..782ebfe
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..677b471
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..a1b8062
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..fcdbefe
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..633d864
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..4665e2a
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 42257c5..ab4be71 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -35,6 +35,7 @@
 import com.android.tools.layoutlib.create.MethodAdapter;
 import com.android.tools.layoutlib.create.OverrideMethod;
 import com.android.util.Pair;
+import com.ibm.icu.util.ULocale;
 
 import android.content.res.BridgeAssetManager;
 import android.graphics.Bitmap;
@@ -64,6 +65,8 @@
  */
 public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
 
+    private static final String ICU_LOCALE_DIRECTION_RTL = "right-to-left";
+
     public static class StaticMethodNotImplementedException extends RuntimeException {
         private static final long serialVersionUID = 1L;
 
@@ -211,7 +214,8 @@
                 Capability.ANIMATED_VIEW_MANIPULATION,
                 Capability.ADAPTER_BINDING,
                 Capability.EXTENDED_VIEWINFO,
-                Capability.FIXED_SCALABLE_NINE_PATCH);
+                Capability.FIXED_SCALABLE_NINE_PATCH,
+                Capability.RTL);
 
 
         BridgeAssetManager.initSystem();
@@ -411,6 +415,20 @@
         throw new IllegalArgumentException("viewObject is not a View");
     }
 
+    @Override
+    public boolean isRtl(String locale) {
+        return isLocaleRtl(locale);
+    }
+
+    public static boolean isLocaleRtl(String locale) {
+        if (locale == null) {
+            locale = "";
+        }
+        ULocale uLocale = new ULocale(locale);
+        return uLocale.getCharacterOrientation().equals(ICU_LOCALE_DIRECTION_RTL) ?
+                true : false;
+    }
+
     /**
      * Returns the lock for the bridge
      */
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 21bef1c..99aa228 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -132,7 +132,8 @@
             RenderResources renderResources,
             IProjectCallback projectCallback,
             Configuration config,
-            int targetSdkVersion) {
+            int targetSdkVersion,
+            boolean hasRtlSupport) {
         mProjectKey = projectKey;
         mMetrics = metrics;
         mProjectCallback = projectCallback;
@@ -142,6 +143,9 @@
 
         mApplicationInfo = new ApplicationInfo();
         mApplicationInfo.targetSdkVersion = targetSdkVersion;
+        if (hasRtlSupport) {
+            mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL;
+        }
 
         mWindowManager = new WindowManagerImpl(mMetrics);
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index ea9d8d9..17b0eb6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -25,6 +25,7 @@
 import com.android.layoutlib.bridge.impl.ParserFactory;
 import com.android.layoutlib.bridge.impl.ResourceHelper;
 import com.android.resources.Density;
+import com.android.resources.LayoutDirection;
 import com.android.resources.ResourceType;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -86,38 +87,53 @@
         }
     }
 
-    private InputStream getIcon(String iconName, Density[] densityInOut, String[] pathOut,
-            boolean tryOtherDensities) {
+    private InputStream getIcon(String iconName, Density[] densityInOut, LayoutDirection direction, 
+            String[] pathOut, boolean tryOtherDensities) {
         // current density
         Density density = densityInOut[0];
 
         // bitmap url relative to this class
-        pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName;
+        if (direction != null) {
+            pathOut[0] = "/bars/" + direction.getResourceValue() + "-" + density.getResourceValue()
+                    + "/" + iconName;
+        } else {
+            pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName;
+        }
 
         InputStream stream = getClass().getResourceAsStream(pathOut[0]);
         if (stream == null && tryOtherDensities) {
             for (Density d : Density.values()) {
                 if (d != density) {
                     densityInOut[0] = d;
-                    stream = getIcon(iconName, densityInOut, pathOut, false /*tryOtherDensities*/);
+                    stream = getIcon(iconName, densityInOut, direction, pathOut,
+                            false /*tryOtherDensities*/);
                     if (stream != null) {
                         return stream;
                     }
                 }
             }
+            // couldn't find resource with direction qualifier. try without.
+            if (direction != null) {
+                return getIcon(iconName, densityInOut, null, pathOut, true);
+            }
         }
 
         return stream;
     }
 
     protected void loadIcon(int index, String iconName, Density density) {
+        loadIcon(index, iconName, density, false);
+    }
+
+    protected void loadIcon(int index, String iconName, Density density, boolean isRtl) {
         View child = getChildAt(index);
         if (child instanceof ImageView) {
             ImageView imageView = (ImageView) child;
 
             String[] pathOut = new String[1];
             Density[] densityInOut = new Density[] { density };
-            InputStream stream = getIcon(iconName, densityInOut, pathOut,
+            LayoutDirection dir = isRtl ? LayoutDirection.RTL : LayoutDirection.LTR;
+            InputStream stream = getIcon(iconName, densityInOut, dir, pathOut,
                     true /*tryOtherDensities*/);
             density = densityInOut[0];
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
index cc90d6b..84e676e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -17,6 +17,7 @@
 package com.android.layoutlib.bridge.bars;
 
 import com.android.resources.Density;
+import com.android.layoutlib.bridge.Bridge;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -26,7 +27,8 @@
 
 public class NavigationBar extends CustomBar {
 
-    public NavigationBar(Context context, Density density, int orientation) throws XmlPullParserException {
+    public NavigationBar(Context context, Density density, int orientation, boolean isRtl,
+            boolean rtlEnabled) throws XmlPullParserException {
         super(context, density, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml");
 
         setBackgroundColor(0xFF000000);
@@ -37,14 +39,15 @@
         // 0 is a spacer.
         int back = 1;
         int recent = 3;
-        if (orientation == LinearLayout.VERTICAL) {
+        if (orientation == LinearLayout.VERTICAL || (isRtl && !rtlEnabled)) {
+            // If RTL is enabled, then layoutlib mirrors the layout for us.
             back = 3;
             recent = 1;
         }
 
-        loadIcon(back,   "ic_sysbar_back.png", density);
-        loadIcon(2,      "ic_sysbar_home.png", density);
-        loadIcon(recent, "ic_sysbar_recent.png", density);
+        loadIcon(back,   "ic_sysbar_back.png",   density, isRtl);
+        loadIcon(2,      "ic_sysbar_home.png",   density, isRtl);
+        loadIcon(recent, "ic_sysbar_recent.png", density, isRtl);
     }
 
     @Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 5c08412..baa956d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -30,7 +30,10 @@
 
 public class StatusBar extends CustomBar {
 
-    public StatusBar(Context context, Density density) throws XmlPullParserException {
+    public StatusBar(Context context, Density density, int direction, boolean RtlEnabled)
+            throws XmlPullParserException {
+        // FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar.
+
         super(context, density, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml");
 
         // FIXME: use FILL_H?
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index b909bec..87047b3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -121,7 +121,8 @@
 
         // build the context
         mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
-                mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion());
+                mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion(),
+                mParams.isRtlSupported());
 
         setUp();
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index c14af4a..9ddbbf1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -225,13 +225,15 @@
             SessionParams params = getParams();
             HardwareConfig hardwareConfig = params.getHardwareConfig();
             BridgeContext context = getContext();
-
+            boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
+            int direction = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
 
             // the view group that receives the window background.
             ViewGroup backgroundView = null;
 
             if (mWindowIsFloating || params.isForceNoDecor()) {
                 backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
+                mViewRoot.setLayoutDirection(direction);
             } else {
                 if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
                     /*
@@ -253,12 +255,14 @@
                        the bottom
                      */
                     LinearLayout topLayout = new LinearLayout(context);
+                    topLayout.setLayoutDirection(direction);
                     mViewRoot = topLayout;
                     topLayout.setOrientation(LinearLayout.HORIZONTAL);
 
                     try {
                         NavigationBar navigationBar = new NavigationBar(context,
-                                hardwareConfig.getDensity(), LinearLayout.VERTICAL);
+                                hardwareConfig.getDensity(), LinearLayout.VERTICAL, isRtl,
+                                params.isRtlSupported());
                         navigationBar.setLayoutParams(
                                 new LinearLayout.LayoutParams(
                                         mNavigationBarSize,
@@ -290,6 +294,7 @@
 
                 LinearLayout topLayout = new LinearLayout(context);
                 topLayout.setOrientation(LinearLayout.VERTICAL);
+                topLayout.setLayoutDirection(direction);
                 // if we don't already have a view root this is it
                 if (mViewRoot == null) {
                     mViewRoot = topLayout;
@@ -301,13 +306,22 @@
 
                     // this is the case of soft buttons + vertical bar.
                     // this top layout is the first layout in the horizontal layout. see above)
-                    mViewRoot.addView(topLayout, 0);
+                    if (isRtl && params.isRtlSupported()) {
+                        // If RTL is enabled, layoutlib will mirror the layouts. So, add the
+                        // topLayout to the right of Navigation Bar and layoutlib will draw it
+                        // to the left.
+                        mViewRoot.addView(topLayout);
+                    } else {
+                        // Add the top layout to the left of the Navigation Bar.
+                        mViewRoot.addView(topLayout, 0);
+                    }
                 }
 
                 if (mStatusBarSize > 0) {
                     // system bar
                     try {
-                        StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity());
+                        StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity(),
+                                direction, params.isRtlSupported());
                         systemBar.setLayoutParams(
                                 new LinearLayout.LayoutParams(
                                         LayoutParams.MATCH_PARENT, mStatusBarSize));
@@ -366,7 +380,8 @@
                     // system bar
                     try {
                         NavigationBar navigationBar = new NavigationBar(context,
-                                hardwareConfig.getDensity(), LinearLayout.HORIZONTAL);
+                                hardwareConfig.getDensity(), LinearLayout.HORIZONTAL, isRtl,
+                                params.isRtlSupported());
                         navigationBar.setLayoutParams(
                                 new LinearLayout.LayoutParams(
                                         LayoutParams.MATCH_PARENT, mNavigationBarSize));