Merge "Avoid calling deepCopyNodes on null array"
diff --git a/bridge/src/android/content/res/BridgeTypedArray.java b/bridge/src/android/content/res/BridgeTypedArray.java
index d0e431a..1d5ac0c 100644
--- a/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/bridge/src/android/content/res/BridgeTypedArray.java
@@ -584,6 +584,7 @@
         if (value == null) {
             return defValue;
         }
+        value = value.trim();
 
         // if the value is just an integer, return it.
         try {
@@ -595,6 +596,11 @@
             // pass
         }
 
+        if (value.startsWith("#")) {
+            // this looks like a color, do not try to parse it
+            return defValue;
+        }
+
         // Handle the @id/<name>, @+id/<name> and @android:id/<name>
         // We need to return the exact value that was compiled (from the various R classes),
         // as these values can be reused internally with calls to findViewById().
diff --git a/bridge/src/android/graphics/Path_Delegate.java b/bridge/src/android/graphics/Path_Delegate.java
index 265ebd1..219c487 100644
--- a/bridge/src/android/graphics/Path_Delegate.java
+++ b/bridge/src/android/graphics/Path_Delegate.java
@@ -86,6 +86,8 @@
 
     public void reset() {
         mPath.reset();
+        mLastX = 0;
+        mLastY = 0;
     }
 
     public void setPathIterator(PathIterator iterator) {
@@ -124,7 +126,7 @@
             return;
         }
 
-        pathDelegate.mPath.reset();
+        pathDelegate.reset();
     }
 
     @LayoutlibDelegate
diff --git a/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
index 680259b..1dfd305 100644
--- a/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
+++ b/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -96,6 +96,14 @@
     }
 
     @LayoutlibDelegate
+    static long nCreateTreeFromCopy(long rendererToCopyPtr, long rootGroupPtr) {
+        VGroup_Delegate rootGroup = VNativeObject.getDelegate(rootGroupPtr);
+        VPathRenderer_Delegate rendererToCopy = VNativeObject.getDelegate(rendererToCopyPtr);
+        return sPathManager.addNewDelegate(new VPathRenderer_Delegate(rendererToCopy,
+                rootGroup));
+    }
+
+    @LayoutlibDelegate
     static void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
             float viewportHeight) {
         VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
@@ -1035,6 +1043,14 @@
             mRenderPath = new Path();
         }
 
+        private VPathRenderer_Delegate(VPathRenderer_Delegate rendererToCopy,
+                VGroup_Delegate rootGroup) {
+            this(rootGroup);
+            mViewportWidth = rendererToCopy.mViewportWidth;
+            mViewportHeight = rendererToCopy.mViewportHeight;
+            mRootAlpha = rendererToCopy.mRootAlpha;
+        }
+
         private float getRootAlpha() {
             return mRootAlpha;
         }
@@ -1133,7 +1149,8 @@
                     }
 
                     final Paint fillPaint = mFillPaint;
-                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
+                    fillPaint.setColor(applyAlpha(applyAlpha(fullPath.mFillColor, fullPath
+                      .mFillAlpha), getRootAlpha()));
                     Paint_Delegate fillPaintDelegate = Paint_Delegate.getDelegate(fillPaint
                             .getNativeInstance());
                     // mFillPaint can not be null at this point so we will have a delegate
@@ -1162,7 +1179,8 @@
                     }
 
                     strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
-                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
+                    strokePaint.setColor(applyAlpha(applyAlpha(fullPath.mStrokeColor, fullPath
+                      .mStrokeAlpha), getRootAlpha()));
                     Paint_Delegate strokePaintDelegate = Paint_Delegate.getDelegate(strokePaint
                             .getNativeInstance());
                     // mStrokePaint can not be null at this point so we will have a delegate
diff --git a/bridge/src/android/view/BridgeInflater.java b/bridge/src/android/view/BridgeInflater.java
index bdddfd8..3667f58 100644
--- a/bridge/src/android/view/BridgeInflater.java
+++ b/bridge/src/android/view/BridgeInflater.java
@@ -39,11 +39,27 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.widget.NumberPicker;
 
 import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
+import static com.android.SdkConstants.AUTO_COMPLETE_TEXT_VIEW;
+import static com.android.SdkConstants.BUTTON;
+import static com.android.SdkConstants.CHECKED_TEXT_VIEW;
+import static com.android.SdkConstants.CHECK_BOX;
+import static com.android.SdkConstants.EDIT_TEXT;
+import static com.android.SdkConstants.IMAGE_BUTTON;
+import static com.android.SdkConstants.MULTI_AUTO_COMPLETE_TEXT_VIEW;
+import static com.android.SdkConstants.RADIO_BUTTON;
+import static com.android.SdkConstants.SEEK_BAR;
+import static com.android.SdkConstants.SPINNER;
+import static com.android.SdkConstants.TEXT_VIEW;
 import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext;
 
 /**
@@ -52,6 +68,13 @@
 public final class BridgeInflater extends LayoutInflater {
 
     private final LayoutlibCallback mLayoutlibCallback;
+    /**
+     * If true, the inflater will try to replace the framework widgets with the AppCompat versions.
+     * Ideally, this should be based on the activity being an AppCompat activity but since that is
+     * not trivial to check from layoutlib, we currently base the decision on the current theme
+     * being an AppCompat theme.
+     */
+    private boolean mLoadAppCompatViews;
     private boolean mIsInMerge = false;
     private ResourceReference mResourceReference;
     private Map<View, String> mOpenDrawerLayouts;
@@ -59,6 +82,15 @@
     // Keep in sync with the same value in LayoutInflater.
     private static final int[] ATTRS_THEME = new int[] {com.android.internal.R.attr.theme };
 
+    private static final String APPCOMPAT_WIDGET_PREFIX = "android.support.v7.widget.AppCompat";
+    /** List of platform widgets that have an AppCompat version */
+    private static final Set<String> APPCOMPAT_VIEWS = Collections.unmodifiableSet(
+            new HashSet<>(
+                    Arrays.asList(TEXT_VIEW, "ImageSwitcher", BUTTON, EDIT_TEXT, SPINNER,
+                            IMAGE_BUTTON, CHECK_BOX, RADIO_BUTTON, CHECKED_TEXT_VIEW,
+                            AUTO_COMPLETE_TEXT_VIEW, MULTI_AUTO_COMPLETE_TEXT_VIEW, "RatingBar",
+                            SEEK_BAR)));
+
     /**
      * List of class prefixes which are tried first by default.
      * <p/>
@@ -74,13 +106,15 @@
         return sClassPrefixList;
     }
 
-    protected BridgeInflater(LayoutInflater original, Context newContext) {
+    private BridgeInflater(LayoutInflater original, Context newContext) {
         super(original, newContext);
         newContext = getBaseContext(newContext);
         if (newContext instanceof BridgeContext) {
             mLayoutlibCallback = ((BridgeContext) newContext).getLayoutlibCallback();
+            mLoadAppCompatViews = ((BridgeContext) newContext).isAppCompatTheme();
         } else {
             mLayoutlibCallback = null;
+            mLoadAppCompatViews = false;
         }
     }
 
@@ -90,10 +124,11 @@
      * @param context The Android application context.
      * @param layoutlibCallback the {@link LayoutlibCallback} object.
      */
-    public BridgeInflater(Context context, LayoutlibCallback layoutlibCallback) {
+    public BridgeInflater(BridgeContext context, LayoutlibCallback layoutlibCallback) {
         super(context);
         mLayoutlibCallback = layoutlibCallback;
         mConstructorArgs[0] = context;
+        mLoadAppCompatViews = context.isAppCompatTheme();
     }
 
     @Override
@@ -101,28 +136,38 @@
         View view = null;
 
         try {
-            // First try to find a class using the default Android prefixes
-            for (String prefix : sClassPrefixList) {
+            if (mLoadAppCompatViews && APPCOMPAT_VIEWS.contains(name)) {
+                // We are using an AppCompat theme so try to load the appcompat views
+                view = loadCustomView(APPCOMPAT_WIDGET_PREFIX + name, attrs);
+
+                if (view == null) {
+                    mLoadAppCompatViews = false; // Do not try anymore
+                }
+            } else {
+
+                // First try to find a class using the default Android prefixes
+                for (String prefix : sClassPrefixList) {
+                    try {
+                        view = createView(name, prefix, attrs);
+                        if (view != null) {
+                            break;
+                        }
+                    } catch (ClassNotFoundException e) {
+                        // Ignore. We'll try again using the base class below.
+                    }
+                }
+
+                // Next try using the parent loader. This will most likely only work for
+                // fully-qualified class names.
                 try {
-                    view = createView(name, prefix, attrs);
-                    if (view != null) {
-                        break;
+                    if (view == null) {
+                        view = super.onCreateView(name, attrs);
                     }
                 } catch (ClassNotFoundException e) {
-                    // Ignore. We'll try again using the base class below.
+                    // Ignore. We'll try again using the custom view loader below.
                 }
             }
 
-            // Next try using the parent loader. This will most likely only work for
-            // fully-qualified class names.
-            try {
-                if (view == null) {
-                    view = super.onCreateView(name, attrs);
-                }
-            } catch (ClassNotFoundException e) {
-                // Ignore. We'll try again using the custom view loader below.
-            }
-
             // Finally try again using the custom view loader
             if (view == null) {
                 view = loadCustomView(name, attrs);
@@ -144,9 +189,26 @@
     @Override
     public View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
             boolean ignoreThemeAttr) {
-        View view;
+        View view = null;
+        if (name.equals("view")) {
+            // This is usually done by the superclass but this allows us catching the error and
+            // reporting something useful.
+            name = attrs.getAttributeValue(null, "class");
+
+            if (name == null) {
+                Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to inflate view tag without " +
+                  "class attribute", null);
+                // We weren't able to resolve the view so we just pass a mock View to be able to
+                // continue rendering.
+                view = new MockView(context, attrs);
+                ((MockView) view).setText("view");
+            }
+        }
+
         try {
-            view = super.createViewFromTag(parent, name, context, attrs, ignoreThemeAttr);
+            if (view == null) {
+                view = super.createViewFromTag(parent, name, context, attrs, ignoreThemeAttr);
+            }
         } catch (InflateException e) {
             // Creation of ContextThemeWrapper code is same as in the super method.
             // Apply a theme wrapper, if allowed and one is specified.
@@ -240,6 +302,9 @@
             // first get the classname in case it's not the node name
             if (name.equals("view")) {
                 name = attrs.getAttributeValue(null, "class");
+                if (name == null) {
+                    return null;
+                }
             }
 
             mConstructorArgs[1] = attrs;
@@ -300,6 +365,17 @@
                     getDrawerLayoutMap().put(view, attrVal);
                 }
             }
+            else if (view instanceof NumberPicker) {
+                NumberPicker numberPicker = (NumberPicker) view;
+                String minValue = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI, "minValue");
+                if (minValue != null) {
+                    numberPicker.setMinValue(Integer.parseInt(minValue));
+                }
+                String maxValue = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI, "maxValue");
+                if (maxValue != null) {
+                    numberPicker.setMaxValue(Integer.parseInt(maxValue));
+                }
+            }
 
         }
     }
diff --git a/bridge/src/android/view/RectShadowPainter.java b/bridge/src/android/view/RectShadowPainter.java
index ea9a255..d15cb48 100644
--- a/bridge/src/android/view/RectShadowPainter.java
+++ b/bridge/src/android/view/RectShadowPainter.java
@@ -54,12 +54,18 @@
         if (saved == -1) {
             return;
         }
+
+        float radius = viewOutline.getRadius();
+        if (radius <= 0) {
+            // We can not paint a shadow with radius 0
+            return;
+        }
+
         try {
             Paint cornerPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
             cornerPaint.setStyle(Style.FILL);
             Paint edgePaint = new Paint(cornerPaint);
             edgePaint.setAntiAlias(false);
-            float radius = viewOutline.getRadius();
             float outerArcRadius = radius + shadowSize;
             int[] colors = {START_COLOR, START_COLOR, END_COLOR};
             cornerPaint.setShader(new RadialGradient(0, 0, outerArcRadius, colors,
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index f87269b..72ac4c3 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -110,6 +110,7 @@
  */
 @SuppressWarnings("deprecation")  // For use of Pair.
 public final class BridgeContext extends Context {
+    private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat";
 
     /** The map adds cookies to each view so that IDE can link xml tags to views. */
     private final HashMap<View, Object> mViewKeyMap = new HashMap<>();
@@ -153,6 +154,7 @@
     private ClassLoader mClassLoader;
     private IBinder mBinder;
     private PackageManager mPackageManager;
+    private Boolean mIsThemeAppCompat;
 
     /**
      * Some applications that target both pre API 17 and post API 17, set the newer attrs to
@@ -479,6 +481,36 @@
         return Pair.of(null, Boolean.FALSE);
     }
 
+    /**
+     * Returns whether the current selected theme is based on AppCompat
+     */
+    public boolean isAppCompatTheme() {
+        // If a cached value exists, return it.
+        if (mIsThemeAppCompat != null) {
+            return mIsThemeAppCompat;
+        }
+        // Ideally, we should check if the corresponding activity extends
+        // android.support.v7.app.ActionBarActivity, and not care about the theme name at all.
+        StyleResourceValue defaultTheme = mRenderResources.getDefaultTheme();
+        // We can't simply check for parent using resources.themeIsParentOf() since the
+        // inheritance structure isn't really what one would expect. The first common parent
+        // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21).
+        boolean isThemeAppCompat = false;
+        for (int i = 0; i < 50; i++) {
+            if (defaultTheme == null) {
+                break;
+            }
+            // for loop ensures that we don't run into cyclic theme inheritance.
+            if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) {
+                isThemeAppCompat = true;
+                break;
+            }
+            defaultTheme = mRenderResources.getParent(defaultTheme);
+        }
+        mIsThemeAppCompat = isThemeAppCompat;
+        return isThemeAppCompat;
+    }
+
     @SuppressWarnings("deprecation")
     private ILayoutPullParser getParser(ResourceReference resource) {
         ILayoutPullParser parser;
@@ -831,45 +863,55 @@
                     }
                 }
 
-                // if there's no direct value for this attribute in the XML, we look for default
-                // values in the widget defStyle, and then in the theme.
-                if (value == null) {
-                    ResourceValue resValue = null;
-
+                // Calculate the default value from the Theme in two cases:
+                //   - If defaultPropMap is not null, get the default value to add it to the list
+                //   of default values of properties.
+                //   - If value is null, it means that the attribute is not directly set as an
+                //   attribute in the XML so try to get the default value.
+                ResourceValue defaultValue = null;
+                if (defaultPropMap != null || value == null) {
                     // look for the value in the custom style first (and its parent if needed)
                     if (customStyleValues != null) {
-                        resValue = mRenderResources.findItemInStyle(customStyleValues,
-                                attrName, frameworkAttr);
+                        defaultValue = mRenderResources.findItemInStyle(customStyleValues, attrName,
+                                frameworkAttr);
                     }
 
                     // then look for the value in the default Style (and its parent if needed)
-                    if (resValue == null && defStyleValues != null) {
-                        resValue = mRenderResources.findItemInStyle(defStyleValues,
-                                attrName, frameworkAttr);
+                    if (defaultValue == null && defStyleValues != null) {
+                        defaultValue = mRenderResources.findItemInStyle(defStyleValues, attrName,
+                                frameworkAttr);
                     }
 
                     // if the item is not present in the defStyle, we look in the main theme (and
                     // its parent themes)
-                    if (resValue == null) {
-                        resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
+                    if (defaultValue == null) {
+                        defaultValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
                     }
 
                     // if we found a value, we make sure this doesn't reference another value.
                     // So we resolve it.
-                    if (resValue != null) {
-                        String preResolve = resValue.getValue();
-                        resValue = mRenderResources.resolveResValue(resValue);
+                    if (defaultValue != null) {
+                        String preResolve = defaultValue.getValue();
+                        defaultValue = mRenderResources.resolveResValue(defaultValue);
 
                         if (defaultPropMap != null) {
                             defaultPropMap.put(
                                     frameworkAttr ? SdkConstants.PREFIX_ANDROID + attrName :
-                                            attrName,
-                                    new Property(preResolve, resValue.getValue()));
+                                            attrName, new Property(preResolve, defaultValue.getValue()));
                         }
+                    }
+                }
+                // Done calculating the defaultValue
 
+                // if there's no direct value for this attribute in the XML, we look for default
+                // values in the widget defStyle, and then in the theme.
+                if (value == null) {
+                    // if we found a value, we make sure this doesn't reference another value.
+                    // So we resolve it.
+                    if (defaultValue != null) {
                         // If the value is a reference to another theme attribute that doesn't
                         // exist, we should log a warning and omit it.
-                        String val = resValue.getValue();
+                        String val = defaultValue.getValue();
                         if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) {
                             if (!attrName.equals(RTL_ATTRS.get(val)) ||
                                     getApplicationInfo().targetSdkVersion <
@@ -880,11 +922,11 @@
                                         String.format("Failed to find '%s' in current theme.", val),
                                         val);
                             }
-                            resValue = null;
+                            defaultValue = null;
                         }
                     }
 
-                    ta.bridgeSetValue(index, attrName, frameworkAttr, resValue);
+                    ta.bridgeSetValue(index, attrName, frameworkAttr, defaultValue);
                 } else {
                     // there is a value in the XML, but we need to resolve it in case it's
                     // referencing another resource or a theme value.
@@ -1799,6 +1841,12 @@
     }
 
     @Override
+    public Display getDisplay() {
+        // pass
+        return null;
+    }
+
+    @Override
     public int getUserId() {
         return 0; // not used
     }
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index 3f276c9..ab73a8b 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -16,11 +16,13 @@
 
 package com.android.layoutlib.bridge.android;
 
+import com.android.internal.inputmethod.IInputContentUriToken;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
 import com.android.internal.view.IInputMethodManager;
 import com.android.internal.view.InputBindResult;
 
+import android.net.Uri;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -239,4 +241,11 @@
         // TODO Auto-generated method stub
         return null;
     }
+
+    @Override
+    public IInputContentUriToken createInputContentUriToken(IBinder token, Uri contentUri,
+            String packageName) {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index 1afd90d..537fa77 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
@@ -20,7 +20,6 @@
 import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.ide.common.rendering.api.SessionParams;
-import com.android.ide.common.rendering.api.StyleResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.RenderParamsFlags;
@@ -94,7 +93,6 @@
     private static final String ATTR_WINDOW_TITLE_SIZE = "windowTitleSize";
     private static final String ATTR_WINDOW_TRANSLUCENT_STATUS = StatusBar.ATTR_TRANSLUCENT;
     private static final String ATTR_WINDOW_TRANSLUCENT_NAV = NavigationBar.ATTR_TRANSLUCENT;
-    private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat";
 
     // Default sizes
     private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
@@ -236,7 +234,7 @@
         boolean isMenu = "menu".equals(params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG));
 
         BridgeActionBar actionBar;
-        if (mBuilder.isThemeAppCompat() && !isMenu) {
+        if (context.isAppCompatTheme() && !isMenu) {
             actionBar = new AppCompatActionBar(context, params);
         } else {
             actionBar = new FrameworkActionBar(context, params);
@@ -324,8 +322,6 @@
         private boolean mTranslucentStatus;
         private boolean mTranslucentNav;
 
-        private Boolean mIsThemeAppCompat;
-
         public Builder(@NonNull SessionParams params, @NonNull BridgeContext context) {
             mParams = params;
             mContext = context;
@@ -365,7 +361,7 @@
             }
             // Check if an actionbar is needed
             boolean windowActionBar = getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR,
-                    !isThemeAppCompat(), true);
+                    !mContext.isAppCompatTheme(), true);
             if (windowActionBar) {
                 mActionBarSize = getDimension(ATTR_ACTION_BAR_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT);
             } else {
@@ -420,33 +416,6 @@
             return mParams.getHardwareConfig().hasSoftwareButtons();
         }
 
-        private boolean isThemeAppCompat() {
-            // If a cached value exists, return it.
-            if (mIsThemeAppCompat != null) {
-                return mIsThemeAppCompat;
-            }
-            // Ideally, we should check if the corresponding activity extends
-            // android.support.v7.app.ActionBarActivity, and not care about the theme name at all.
-            StyleResourceValue defaultTheme = mResources.getDefaultTheme();
-            // We can't simply check for parent using resources.themeIsParentOf() since the
-            // inheritance structure isn't really what one would expect. The first common parent
-            // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21).
-            boolean isThemeAppCompat = false;
-            for (int i = 0; i < 50; i++) {
-                if (defaultTheme == null) {
-                    break;
-                }
-                // for loop ensures that we don't run into cyclic theme inheritance.
-                if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) {
-                    isThemeAppCompat = true;
-                    break;
-                }
-                defaultTheme = mResources.getParent(defaultTheme);
-            }
-            mIsThemeAppCompat = isThemeAppCompat;
-            return isThemeAppCompat;
-        }
-
         /**
          * Return true if the status bar or nav bar are present, they are not translucent (i.e
          * content doesn't overlap with them).
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java b/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java
index e273b2c..1ae9cb6 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java
@@ -39,8 +39,6 @@
 
     public final static boolean LOG_PARSER = false;
 
-    private final static String ENCODING = "UTF-8"; //$NON-NLS-1$
-
     // Used to get a new XmlPullParser from the client.
     @Nullable
     private static com.android.ide.common.rendering.api.ParserFactory sParserFactory;
@@ -74,7 +72,7 @@
 
         stream = readAndClose(stream, name, size);
 
-        parser.setInput(stream, ENCODING);
+        parser.setInput(stream, null);
         if (isLayout) {
             try {
                 return new LayoutParserWrapper(parser).peekTillLayoutStart();
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index a8077cc..c890793 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -20,6 +20,7 @@
 import com.android.ide.common.rendering.api.HardwareConfig;
 import com.android.ide.common.rendering.api.IAnimationListener;
 import com.android.ide.common.rendering.api.ILayoutPullParser;
+import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.ide.common.rendering.api.LayoutlibCallback;
 import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.RenderSession;
@@ -303,6 +304,20 @@
             SessionParams params = getParams();
             BridgeContext context = getContext();
 
+            if (Bridge.isLocaleRtl(params.getLocale())) {
+                if (!params.isRtlSupported()) {
+                    Bridge.getLog().warning(LayoutLog.TAG_RTL_NOT_ENABLED,
+                            "You are using a right-to-left " +
+                                    "(RTL) locale but RTL is not enabled", null);
+                } else if (params.getSimulatedPlatformVersion() < 17) {
+                    // This will render ok because we are using the latest layoutlib but at least
+                    // warn the user that this might fail in a real device.
+                    Bridge.getLog().warning(LayoutLog.TAG_RTL_NOT_SUPPORTED, "You are using a " +
+                            "right-to-left " +
+                            "(RTL) locale but RTL is not supported for API level < 17", null);
+                }
+            }
+
             // Sets the project callback (custom view loader) to the fragment delegate so that
             // it can instantiate the custom Fragment.
             Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback());
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index a21de56..c197e40 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -77,6 +77,7 @@
      */
     public static int getColor(String value) {
         if (value != null) {
+            value = value.trim();
             if (!value.startsWith("#")) {
                 if (value.startsWith(SdkConstants.PREFIX_THEME_REF)) {
                     throw new NumberFormatException(String.format(
diff --git a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
index 55d6a20..466eca8 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png
new file mode 100644
index 0000000..940fe5b
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/android.xml b/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/android.xml
new file mode 100644
index 0000000..42e3beb
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/android.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:viewportWidth="1102"
+        android:viewportHeight="642"
+        android:width="1102px"
+        android:height="642px">
+
+    <group
+        android:translateX="-126.347"
+        android:translateY="6.7928655e-4">
+
+
+        <path
+            android:fillColor="#94c147"
+            android:pathData="
+            m 552.777,147.57
+            c -14.147,0 -25.622,11.652 -25.622,26.02
+            v 101.68
+            c 0,14.372 11.475,26.019 25.622,26.019 14.147,0 25.61,-11.646 25.61,-26.019
+            V 173.59
+            c 0.001,-14.368 -11.462,-26.02 -25.61,-26.02
+            z
+
+            m -309.011,0
+            c -14.155,0 -25.618,11.652 -25.618,26.02
+            v 101.68
+            c 0,14.372 11.462,26.019 25.618,26.019 14.153,0 25.623,-11.646 25.623,-26.019
+            V 173.59
+            c -0.008,-14.368 -11.475,-26.02 -25.623,-26.02
+            z" />
+
+
+        <path
+        android:fillColor="#94c147"
+        android:pathData="m 284.799,148.364 v 185.768 c 0,11.035 8.948,19.98 19.983,19.98 h 22.815 v 56.567 c 0,14.37 11.47,26.016 25.623,26.016 14.148,0 25.623,-11.646 25.623,-26.016 v -56.567 h 39.878 v 56.567 c 0,14.37 11.463,26.016 25.61,26.016 14.147,0 25.622,-11.646 25.622,-26.016 v -56.567 h 22.828 c 11.022,0 19.971,-8.953 19.971,-19.98 V 148.364 H 284.799 l 0,0 z" />
+
+        <group
+        android:name="head"
+        android:pivotX="400"
+        android:pivotY="131.105">
+
+        <path
+        android:fillColor="#94c147"
+        android:pathData="m 452.302,52.105 21.057,-30.572 c 1.245,-1.819 0.939,-4.199 -0.695,-5.329 -1.637,-1.123 -3.968,-0.568 -5.225,1.251 l -21.875,31.75 c -14.404,-5.682 -30.418,-8.844 -47.293,-8.844 -16.87,0 -32.893,3.162 -47.297,8.844 l -21.875,-31.75 c -1.257,-1.819 -3.589,-2.375 -5.225,-1.251 -1.636,1.124 -1.946,3.509 -0.696,5.329 l 21.057,30.572 c -33.464,15.57 -56.951,45.166 -59.941,79.706 H 512.25 C 509.259,97.271 485.772,67.676 452.302,52.105 z M 350.187,100.28 c -6.965,0 -12.617,-5.646 -12.617,-12.616 0,-6.958 5.647,-12.61 12.617,-12.61 6.97,0 12.603,5.652 12.603,12.61 0,6.965 -5.64,12.616 -12.603,12.616 z m 97.744,0 c -6.97,0 -12.609,-5.646 -12.609,-12.616 0,-6.958 5.64,-12.61 12.609,-12.61 6.971,0 12.61,5.652 12.61,12.61 0,6.965 -5.64,12.616 -12.61,12.616 z" />
+        </group>
+
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/headset.xml b/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/headset.xml
new file mode 100644
index 0000000..897c411
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/headset.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="150dp"
+        android:height="150dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="m12,1c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,-3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h4v1h-7v2h6c1.66,0 3,-1.34 3,-3V10c0,-4.97 -4.03,-9 -9,-9z"/>
+</vector>
\ No newline at end of file
diff --git a/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml b/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
index 32e6e73..0998b25 100644
--- a/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
+++ b/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
@@ -4,7 +4,8 @@
         android:height="76dp"
         android:width="76dp"
         android:viewportHeight="48"
-        android:viewportWidth="48">
+        android:viewportWidth="48"
+        android:alpha="0.6">
 
     <group
         android:name="root"
@@ -79,7 +80,7 @@
             android:fillType="nonZero"
             android:strokeWidth="1"
             android:strokeColor="#AABBCC"
-            android:fillColor="#AAEFCC"
+            android:fillColor="#40AAEFCC"
             android:pathData="M0,-40 l0, 10 l10, 0 l0, -10 l-10,0 m5,0 l0, 10 l10, 0 l0, -10 l-10,0"
         />
     </group>
diff --git a/bridge/tests/res/testApp/MyApplication/src/main/res/layout/empty.xml b/bridge/tests/res/testApp/MyApplication/src/main/res/layout/empty.xml
new file mode 100644
index 0000000..5322411
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/src/main/res/layout/empty.xml
@@ -0,0 +1,16 @@
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
diff --git a/bridge/tests/res/testApp/MyApplication/src/main/res/layout/vector_drawable_android.xml b/bridge/tests/res/testApp/MyApplication/src/main/res/layout/vector_drawable_android.xml
new file mode 100644
index 0000000..3b01ea0
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/src/main/res/layout/vector_drawable_android.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:padding="16dp"
+              android:orientation="vertical"
+              android:layout_width="fill_parent"
+              android:layout_height="fill_parent">
+    <ImageView
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:src="@drawable/android"/>
+    <ImageView
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:src="@drawable/headset"/>
+
+</LinearLayout>
+
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index 8f570ae..88ac72d 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -116,7 +116,7 @@
     private static ArrayList<String> sRenderMessages = Lists.newArrayList();
 
     @Rule
-    public static TestWatcher sRenderMessageWatcher = new TestWatcher() {
+    public TestWatcher sRenderMessageWatcher = new TestWatcher() {
         @Override
         protected void succeeded(Description description) {
             // We only check error messages if the rest of the test case was successful.
@@ -433,6 +433,24 @@
         renderAndVerify(params, "vector_drawable.png", TimeUnit.SECONDS.toNanos(2));
     }
 
+    /**
+     * Regression test for http://b.android.com/91383 and http://b.android.com/203797
+     */
+    @Test
+    public void testVectorDrawable91383() throws ClassNotFoundException {
+        // Create the layout pull parser.
+        LayoutPullParser parser = createLayoutPullParser("vector_drawable_android.xml");
+        // Create LayoutLibCallback.
+        LayoutLibTestCallback layoutLibCallback = new LayoutLibTestCallback(getLogger());
+        layoutLibCallback.initResources();
+
+        SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
+                layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+                RenderingMode.V_SCROLL, 22);
+
+        renderAndVerify(params, "vector_drawable_91383.png", TimeUnit.SECONDS.toNanos(2));
+    }
+
     /** Test activity.xml */
     @Test
     public void testScrolling() throws ClassNotFoundException {
@@ -469,7 +487,7 @@
     @Test
     public void testGetResourceNameVariants() throws Exception {
         // Setup
-        SessionParams params = createSessionParams("", ConfigGenerator.NEXUS_4);
+        SessionParams params = createSessionParams("empty.xml", ConfigGenerator.NEXUS_4);
         AssetManager assetManager = AssetManager.getSystem();
         DisplayMetrics metrics = new DisplayMetrics();
         Configuration configuration = RenderAction.getConfiguration(params);