Removing private system ui flags from status bar flags logic. am: ab216609f1 am: b7a673ed95
am: dccfd4394e

Change-Id: Ie8bbbfb5c24957f64036e8de23d6a29e6669ea18
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 3681f2a..74fa549 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -11,7 +11,6 @@
       <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
       <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
     </inspection_tool>
-    <inspection_tool class="ToArrayCallWithZeroLengthArrayArgument" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="WeakerAccess" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="false" />
       <option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="false" />
diff --git a/bridge/src/android/content/res/AssetManager_Delegate.java b/bridge/src/android/content/res/AssetManager_Delegate.java
index e0d3b8c..b4d5288 100644
--- a/bridge/src/android/content/res/AssetManager_Delegate.java
+++ b/bridge/src/android/content/res/AssetManager_Delegate.java
@@ -18,6 +18,8 @@
 
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
+import android.util.SparseArray;
+
 /**
  * Delegate used to provide implementation of a select few native methods of {@link AssetManager}
  * <p/>
@@ -38,4 +40,8 @@
         Resources_Theme_Delegate.getDelegateManager().removeJavaReferenceFor(theme);
     }
 
+    @LayoutlibDelegate
+    /*package*/ static SparseArray<String> getAssignedPackageIdentifiers(AssetManager manager) {
+        return new SparseArray<>();
+    }
 }
diff --git a/bridge/src/android/content/res/BridgeTypedArray.java b/bridge/src/android/content/res/BridgeTypedArray.java
index d0e431a..9da65a6 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().
@@ -632,7 +638,15 @@
             }
         }
 
-        // not a direct id valid reference? resolve it
+        // not a direct id valid reference. First check if it's an enum (this is a corner case
+        // for attributes that have a reference|enum type), then fallback to resolve
+        // as an ID without prefix.
+        Integer enumValue = resolveEnumAttribute(index);
+        if (enumValue != null) {
+            return enumValue;
+        }
+
+        // Ok, not an enum, resolve as an ID
         Integer idValue;
 
         if (resValue.isFramework()) {
diff --git a/bridge/src/android/content/res/Resources_Delegate.java b/bridge/src/android/content/res/Resources_Delegate.java
index ea320c7..c3d4cef 100644
--- a/bridge/src/android/content/res/Resources_Delegate.java
+++ b/bridge/src/android/content/res/Resources_Delegate.java
@@ -45,6 +45,7 @@
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
+import android.util.LruCache;
 import android.util.TypedValue;
 import android.view.ViewGroup.LayoutParams;
 
@@ -58,6 +59,9 @@
 public class Resources_Delegate {
 
     private static boolean[] mPlatformResourceFlag = new boolean[1];
+    // TODO: This cache is cleared every time a render session is disposed. Look into making this
+    // more long lived.
+    private static LruCache<String, Drawable.ConstantState> sDrawableCache = new LruCache<>(50);
 
     public static Resources initSystem(BridgeContext context,
             AssetManager assets,
@@ -75,6 +79,7 @@
      * would prevent us from unloading the library.
      */
     public static void disposeSystem() {
+        sDrawableCache.evictAll();
         Resources.mSystem.mContext = null;
         Resources.mSystem.mLayoutlibCallback = null;
         Resources.mSystem = null;
@@ -137,9 +142,23 @@
     @LayoutlibDelegate
     static Drawable getDrawable(Resources resources, int id, Theme theme) {
         Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
         if (value != null) {
-            return ResourceHelper.getDrawable(value.getSecond(), resources.mContext, theme);
+            String key = value.getSecond().getValue();
+
+            Drawable.ConstantState constantState = key != null ? sDrawableCache.get(key) : null;
+            Drawable drawable;
+            if (constantState != null) {
+                drawable = constantState.newDrawable(resources, theme);
+            } else {
+                drawable =
+                        ResourceHelper.getDrawable(value.getSecond(), resources.mContext, theme);
+
+                if (key != null) {
+                    sDrawableCache.put(key, drawable.getConstantState());
+                }
+            }
+
+            return drawable;
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
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 49f8691..3e81e83 100644
--- a/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
+++ b/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -70,6 +70,13 @@
     private static final DelegateManager<VNativeObject> sPathManager =
             new DelegateManager<>(VNativeObject.class);
 
+    private static long addNativeObject(VNativeObject object) {
+        long ptr = sPathManager.addNewDelegate(object);
+        object.setNativePtr(ptr);
+
+        return ptr;
+    }
+
     /**
      * Obtains styled attributes from the theme, if available, or unstyled resources if the theme is
      * null.
@@ -91,8 +98,14 @@
 
     @LayoutlibDelegate
     static long nCreateTree(long rootGroupPtr) {
-        VGroup_Delegate rootGroup = VNativeObject.getDelegate(rootGroupPtr);
-        return sPathManager.addNewDelegate(new VPathRenderer_Delegate(rootGroup));
+        return addNativeObject(new VPathRenderer_Delegate(rootGroupPtr));
+    }
+
+    @LayoutlibDelegate
+    static long nCreateTreeFromCopy(long rendererToCopyPtr, long rootGroupPtr) {
+        VPathRenderer_Delegate rendererToCopy = VNativeObject.getDelegate(rendererToCopyPtr);
+        return addNativeObject(new VPathRenderer_Delegate(rendererToCopy,
+                rootGroupPtr));
     }
 
     @LayoutlibDelegate
@@ -149,14 +162,13 @@
 
     @LayoutlibDelegate
     static long nCreateFullPath() {
-        return sPathManager.addNewDelegate(new VFullPath_Delegate());
+        return addNativeObject(new VFullPath_Delegate());
     }
 
     @LayoutlibDelegate
     static long nCreateFullPath(long nativeFullPathPtr) {
         VFullPath_Delegate original = VNativeObject.getDelegate(nativeFullPathPtr);
-
-        return sPathManager.addNewDelegate(new VFullPath_Delegate(original));
+        return addNativeObject(new VFullPath_Delegate(original));
     }
 
     @LayoutlibDelegate
@@ -222,25 +234,24 @@
 
     @LayoutlibDelegate
     static long nCreateClipPath() {
-        return sPathManager.addNewDelegate(new VClipPath_Delegate());
+        return addNativeObject(new VClipPath_Delegate());
     }
 
     @LayoutlibDelegate
     static long nCreateClipPath(long clipPathPtr) {
         VClipPath_Delegate original = VNativeObject.getDelegate(clipPathPtr);
-        return sPathManager.addNewDelegate(new VClipPath_Delegate(original));
+        return addNativeObject(new VClipPath_Delegate(original));
     }
 
     @LayoutlibDelegate
     static long nCreateGroup() {
-        return sPathManager.addNewDelegate(new VGroup_Delegate());
+        return addNativeObject(new VGroup_Delegate());
     }
 
     @LayoutlibDelegate
     static long nCreateGroup(long groupPtr) {
         VGroup_Delegate original = VNativeObject.getDelegate(groupPtr);
-        return sPathManager.addNewDelegate(
-                new VGroup_Delegate(original, new ArrayMap<String, Object>()));
+        return addNativeObject(new VGroup_Delegate(original, new ArrayMap<>()));
     }
 
     @LayoutlibDelegate
@@ -493,7 +504,9 @@
      *     not need it
      * </ol>
      */
-    interface VNativeObject {
+    abstract static class VNativeObject {
+        long mNativePtr = 0;
+
         @NonNull
         static <T> T getDelegate(long nativePtr) {
             //noinspection unchecked
@@ -503,7 +516,17 @@
             return vNativeObject;
         }
 
-        void setName(String name);
+        abstract void setName(String name);
+
+        void setNativePtr(long nativePtr) {
+            mNativePtr = nativePtr;
+        }
+
+        /**
+         * Method to explicitly dispose native objects
+         */
+        void dispose() {
+        }
     }
 
     private static class VClipPath_Delegate extends VPath_Delegate {
@@ -773,7 +796,7 @@
         }
     }
 
-    static class VGroup_Delegate implements VNativeObject {
+    static class VGroup_Delegate extends VNativeObject {
         // This constants need to be kept in sync with their definitions in VectorDrawable.Group
         private static final int ROTATE_INDEX = 0;
         private static final int PIVOT_X_INDEX = 1;
@@ -959,9 +982,28 @@
         public void setName(String name) {
             mGroupName = name;
         }
+
+        @Override
+        protected void dispose() {
+            mChildren.stream().filter(child -> child instanceof VNativeObject).forEach(child
+                    -> {
+                VNativeObject nativeObject = (VNativeObject) child;
+                if (nativeObject.mNativePtr != 0) {
+                    sPathManager.removeJavaReferenceFor(nativeObject.mNativePtr);
+                    nativeObject.mNativePtr = 0;
+                }
+                nativeObject.dispose();
+            });
+            mChildren.clear();
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            super.finalize();
+        }
     }
 
-    public static class VPath_Delegate implements VNativeObject {
+    public static class VPath_Delegate extends VNativeObject {
         protected PathParser_Delegate.PathDataNode[] mNodes = null;
         String mPathName;
         int mChangingConfigurations;
@@ -973,7 +1015,7 @@
         public VPath_Delegate(VPath_Delegate copy) {
             mPathName = copy.mPathName;
             mChangingConfigurations = copy.mChangingConfigurations;
-            mNodes = PathParser_Delegate.deepCopyNodes(copy.mNodes);
+            mNodes = copy.mNodes != null ? PathParser_Delegate.deepCopyNodes(copy.mNodes) : null;
         }
 
         public void toPath(Path path) {
@@ -1001,9 +1043,14 @@
                 PathParser_Delegate.updateNodes(mNodes, nodes);
             }
         }
+
+        @Override
+        void dispose() {
+            mNodes = null;
+        }
     }
 
-    static class VPathRenderer_Delegate implements VNativeObject {
+    static class VPathRenderer_Delegate extends VNativeObject {
         /* Right now the internal data structure is organized as a tree.
          * Each node can be a group node, or a path.
          * A group node can have groups or paths as children, but a path node has
@@ -1021,7 +1068,7 @@
         private final Path mPath;
         private final Path mRenderPath;
         private final Matrix mFinalPathMatrix = new Matrix();
-        private final VGroup_Delegate mRootGroup;
+        private final long mRootGroupPtr;
         private float mViewportWidth = 0;
         private float mViewportHeight = 0;
         private float mRootAlpha = 1.0f;
@@ -1029,12 +1076,20 @@
         private Paint mFillPaint;
         private PathMeasure mPathMeasure;
 
-        private VPathRenderer_Delegate(VGroup_Delegate rootGroup) {
-            mRootGroup = rootGroup;
+        private VPathRenderer_Delegate(long rootGroupPtr) {
+            mRootGroupPtr = rootGroupPtr;
             mPath = new Path();
             mRenderPath = new Path();
         }
 
+        private VPathRenderer_Delegate(VPathRenderer_Delegate rendererToCopy,
+                long rootGroupPtr) {
+            this(rootGroupPtr);
+            mViewportWidth = rendererToCopy.mViewportWidth;
+            mViewportHeight = rendererToCopy.mViewportHeight;
+            mRootAlpha = rendererToCopy.mRootAlpha;
+        }
+
         private float getRootAlpha() {
             return mRootAlpha;
         }
@@ -1071,7 +1126,7 @@
 
         public void draw(long canvasPtr, long filterPtr, int w, int h) {
             // Traverse the tree in pre-order to draw.
-            drawGroupTree(mRootGroup, Matrix.IDENTITY_MATRIX, canvasPtr, w, h, filterPtr);
+            drawGroupTree(VNativeObject.getDelegate(mRootGroupPtr), Matrix.IDENTITY_MATRIX, canvasPtr, w, h, filterPtr);
         }
 
         private void drawPath(VGroup_Delegate VGroup, VPath_Delegate VPath, long canvasPtr,
@@ -1133,7 +1188,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 +1218,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
@@ -1209,5 +1266,17 @@
         @Override
         public void setName(String name) {
         }
+
+        @Override
+        protected void finalize() throws Throwable {
+            // The mRootGroupPtr is not explicitly freed by anything in the VectorDrawable so we
+            // need to free it here.
+            VNativeObject nativeObject = sPathManager.getDelegate(mRootGroupPtr);
+            sPathManager.removeJavaReferenceFor(mRootGroupPtr);
+            assert nativeObject != null;
+            nativeObject.dispose();
+
+            super.finalize();
+        }
     }
 }
diff --git a/bridge/src/android/preference/BridgePreferenceInflater.java b/bridge/src/android/preference/BridgePreferenceInflater.java
index 4f00b5d..aa393a9 100644
--- a/bridge/src/android/preference/BridgePreferenceInflater.java
+++ b/bridge/src/android/preference/BridgePreferenceInflater.java
@@ -21,6 +21,7 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.InflateException;
 
 public class BridgePreferenceInflater extends PreferenceInflater {
 
@@ -42,7 +43,15 @@
             viewKey = ((BridgeXmlBlockParser) attrs).getViewCookie();
         }
 
-        Preference preference = super.onCreateItem(name, attrs);
+        Preference preference = null;
+        try {
+            preference = super.onCreateItem(name, attrs);
+        } catch (ClassNotFoundException | InflateException exception) {
+            // name is probably not a valid preference type
+            if ("SwitchPreferenceCompat".equals(name)) {
+                preference = super.onCreateItem("SwitchPreference", attrs);
+            }
+        }
 
         if (viewKey != null && bc != null) {
             bc.addCookie(preference, viewKey);
diff --git a/bridge/src/android/view/AttachInfo_Accessor.java b/bridge/src/android/view/AttachInfo_Accessor.java
index 94f3f54..85584d3 100644
--- a/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/bridge/src/android/view/AttachInfo_Accessor.java
@@ -34,7 +34,7 @@
         Display display = wm.getDefaultDisplay();
         ViewRootImpl root = new ViewRootImpl(context, display);
         AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
-                display, root, new Handler(), null);
+                display, root, new Handler(), null, context);
         info.mHasWindowFocus = true;
         info.mWindowVisibility = View.VISIBLE;
         info.mInTouchMode = false; // this is so that we can display selections.
diff --git a/bridge/src/android/view/BridgeInflater.java b/bridge/src/android/view/BridgeInflater.java
index bdddfd8..b19cb58 100644
--- a/bridge/src/android/view/BridgeInflater.java
+++ b/bridge/src/android/view/BridgeInflater.java
@@ -39,11 +39,28 @@
 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.IMAGE_VIEW;
+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 +69,21 @@
 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;
+    /**
+     * This set contains the framework views that have an AppCompat version but failed to load.
+     * This might happen because not all widgets are contained in all versions of the support
+     * library.
+     * This will help us to avoid trying to load the AppCompat version multiple times if it
+     * doesn't exist.
+     */
+    private Set<String> mFailedAppCompatViews = new HashSet<>();
     private boolean mIsInMerge = false;
     private ResourceReference mResourceReference;
     private Map<View, String> mOpenDrawerLayouts;
@@ -59,6 +91,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, IMAGE_VIEW, 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 +115,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 +133,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,26 +145,39 @@
         View view = null;
 
         try {
-            // 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.
+            if (mLoadAppCompatViews
+                    && APPCOMPAT_VIEWS.contains(name)
+                    && !mFailedAppCompatViews.contains(name)) {
+                // We are using an AppCompat theme so try to load the appcompat views
+                view = loadCustomView(APPCOMPAT_WIDGET_PREFIX + name, attrs, true);
+
+                if (view == null) {
+                    mFailedAppCompatViews.add(name); // Do not try this one anymore
                 }
             }
 
-            // 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);
+            if (view == null) {
+                // 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.
+                    }
                 }
-            } catch (ClassNotFoundException e) {
-                // 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
@@ -144,9 +201,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.
@@ -235,17 +309,29 @@
         return null;
     }
 
-    private View loadCustomView(String name, AttributeSet attrs) throws Exception {
+    /**
+     * Instantiates the given view name and returns the instance. If the view doesn't exist, a
+     * MockView or null might be returned.
+     * @param name the custom view name
+     * @param attrs the {@link AttributeSet} to be passed to the view constructor
+     * @param silent if true, errors while loading the view won't be reported and, if the view
+     * doesn't exist, null will be returned.
+     */
+    private View loadCustomView(String name, AttributeSet attrs, boolean silent) throws Exception {
         if (mLayoutlibCallback != null) {
             // 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;
 
-            Object customView = mLayoutlibCallback.loadView(name, mConstructorSignature,
-                    mConstructorArgs);
+            Object customView = silent ?
+                    mLayoutlibCallback.loadClass(name, mConstructorSignature, mConstructorArgs)
+                    : mLayoutlibCallback.loadView(name, mConstructorSignature, mConstructorArgs);
 
             if (customView instanceof View) {
                 return (View)customView;
@@ -255,6 +341,10 @@
         return null;
     }
 
+    private View loadCustomView(String name, AttributeSet attrs) throws Exception {
+        return loadCustomView(name, attrs, false);
+    }
+
     private void setupViewInContext(View view, AttributeSet attrs) {
         Context context = getContext();
         context = getBaseContext(context);
@@ -300,6 +390,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/IWindowManagerImpl.java b/bridge/src/android/view/IWindowManagerImpl.java
index 0c3231b..f4f92ec 100644
--- a/bridge/src/android/view/IWindowManagerImpl.java
+++ b/bridge/src/android/view/IWindowManagerImpl.java
@@ -30,6 +30,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
 import android.view.AppTransitionAnimationSpec;
@@ -79,7 +80,7 @@
     public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, int arg4,
             boolean arg5, boolean arg6, int arg7, int arg8, boolean arg9, boolean arg10,
             Rect arg11, Configuration arg12, int arg13, boolean arg14, boolean arg15, int arg16,
-            int arg17)
+            int arg17, boolean arg18)
             throws RemoteException {
         // TODO Auto-generated method stub
     }
@@ -326,7 +327,7 @@
 
     @Override
     public void setAppTask(IBinder arg0, int arg1, int arg2, Rect arg3, Configuration arg4,
-            int arg5, boolean arg6)
+            int arg5, boolean arg6, boolean arg7)
             throws RemoteException {
         // TODO Auto-generated method stub
     }
@@ -522,6 +523,14 @@
     }
 
     @Override
+    public void setKeyguardAnimatingIn(boolean animating) throws RemoteException {
+    }
+
+    @Override
+    public void setSwitchingUser(boolean switching) throws RemoteException {
+    }
+
+    @Override
     public void lockNow(Bundle options) {
         // TODO Auto-generated method stub
     }
@@ -612,4 +621,12 @@
     public Bitmap screenshotWallpaper() throws RemoteException {
         return null;
     }
+
+    @Override
+    public void enableSurfaceTrace(ParcelFileDescriptor fd) throws RemoteException {
+    }
+
+    @Override
+    public void disableSurfaceTrace() throws RemoteException {
+    }
 }
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 616cb57..8d93b7f 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.
@@ -1615,6 +1657,12 @@
         // pass
     }
 
+    @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission, Bundle options) {
+        // pass
+    }
+
     public void sendBroadcastAsUser(Intent intent, UserHandle user,
             String receiverPermission, int appOp) {
         // pass
diff --git a/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java b/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java
index d432120..ab27819 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java
@@ -21,6 +21,7 @@
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.RenderParamsFlags;
+import com.android.layoutlib.bridge.util.ReflectionUtils;
 import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
 
 import android.annotation.NonNull;
@@ -116,7 +117,7 @@
     private static void setProperty(@NonNull Object object, @NonNull String propertyClassName,
       @NonNull Object propertyValue, @NonNull String propertySetter)
             throws ReflectionException {
-        Class<?> propertyClass = getClassInstance(propertyValue, propertyClassName);
+        Class<?> propertyClass = ReflectionUtils.getClassInstance(propertyValue, propertyClassName);
         setProperty(object, propertyClass, propertyValue, propertySetter);
     }
 
@@ -126,22 +127,4 @@
         invoke(getMethod(object.getClass(), propertySetter, propertyClass), object, propertyValue);
     }
 
-    /**
-     * Looks through the class hierarchy of {@code object} at runtime and returns the class matching
-     * the name {@code className}.
-     * <p/>
-     * This is used when we cannot use Class.forName() since the class we want was loaded from a
-     * different ClassLoader.
-     */
-    @NonNull
-    private static Class<?> getClassInstance(@NonNull Object object, @NonNull String className) {
-        Class<?> superClass = object.getClass();
-        while (superClass != null) {
-            if (className.equals(superClass.getName())) {
-                return superClass;
-            }
-            superClass = superClass.getSuperclass();
-        }
-        throw new RuntimeException("invalid object/classname combination.");
-    }
 }
diff --git a/bridge/src/com/android/layoutlib/bridge/android/support/SupportPreferencesUtil.java b/bridge/src/com/android/layoutlib/bridge/android/support/SupportPreferencesUtil.java
new file mode 100644
index 0000000..6ad9efc
--- /dev/null
+++ b/bridge/src/com/android/layoutlib/bridge/android/support/SupportPreferencesUtil.java
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ */
+
+package com.android.layoutlib.bridge.android.support;
+
+import com.android.ide.common.rendering.api.LayoutlibCallback;
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.StyleResourceValue;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.view.ContextThemeWrapper;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+import android.widget.ScrollView;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+import static com.android.layoutlib.bridge.util.ReflectionUtils.getAccessibleMethod;
+import static com.android.layoutlib.bridge.util.ReflectionUtils.getClassInstance;
+import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod;
+import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;
+
+/**
+ * Class with utility methods to instantiate Preferences provided by the support library.
+ * This class uses reflection to access the support preference objects so it heavily depends on
+ * the API being stable.
+ */
+public class SupportPreferencesUtil {
+    private static final String PREFERENCE_PKG = "android.support.v7.preference";
+    private static final String PREFERENCE_MANAGER = PREFERENCE_PKG + ".PreferenceManager";
+    private static final String PREFERENCE_GROUP = PREFERENCE_PKG + ".PreferenceGroup";
+    private static final String PREFERENCE_GROUP_ADAPTER =
+      PREFERENCE_PKG + ".PreferenceGroupAdapter";
+    private static final String PREFERENCE_INFLATER = PREFERENCE_PKG + ".PreferenceInflater";
+
+    private SupportPreferencesUtil() {
+    }
+
+    @NonNull
+    private static Object instantiateClass(@NonNull LayoutlibCallback callback,
+            @NonNull String className, @Nullable Class[] constructorSignature,
+            @Nullable Object[] constructorArgs) throws ReflectionException {
+        try {
+            Object instance = callback.loadClass(className, constructorSignature, constructorArgs);
+            if (instance == null) {
+                throw new ClassNotFoundException(className + " class not found");
+            }
+            return instance;
+        } catch (ClassNotFoundException e) {
+            throw new ReflectionException(e);
+        }
+    }
+
+    @NonNull
+    private static Object createPreferenceGroupAdapter(@NonNull LayoutlibCallback callback,
+            @NonNull Object preferenceScreen) throws ReflectionException {
+        Class<?> preferenceGroupClass = getClassInstance(preferenceScreen, PREFERENCE_GROUP);
+
+        return instantiateClass(callback, PREFERENCE_GROUP_ADAPTER,
+                new Class[]{preferenceGroupClass}, new Object[]{preferenceScreen});
+    }
+
+    @NonNull
+    private static Object createInflatedPreference(@NonNull LayoutlibCallback callback,
+      @NonNull Context context, @NonNull XmlPullParser parser, @NonNull Object preferenceScreen,
+      @NonNull Object preferenceManager) throws ReflectionException {
+        Class<?> preferenceGroupClass = getClassInstance(preferenceScreen, PREFERENCE_GROUP);
+        Object preferenceInflater = instantiateClass(callback, PREFERENCE_INFLATER,
+          new Class[]{Context.class, preferenceManager.getClass()},
+          new Object[]{context, preferenceManager});
+        Object inflatedPreference =
+                invoke(getAccessibleMethod(preferenceInflater.getClass(), "inflate",
+                        XmlPullParser.class, preferenceGroupClass), preferenceInflater, parser,
+                        null);
+
+        if (inflatedPreference == null) {
+            throw new ReflectionException("inflate method returned null");
+        }
+
+        return inflatedPreference;
+    }
+
+    /**
+     * Returns a themed wrapper context of {@link BridgeContext} with the theme specified in
+     * ?attr/preferenceTheme applied to it.
+     */
+    @Nullable
+    private static Context getThemedContext(@NonNull BridgeContext bridgeContext) {
+        RenderResources resources = bridgeContext.getRenderResources();
+        ResourceValue preferenceTheme = resources.findItemInTheme("preferenceTheme", false);
+
+        if (preferenceTheme != null) {
+            // resolve it, if needed.
+            preferenceTheme = resources.resolveResValue(preferenceTheme);
+        }
+        if (preferenceTheme instanceof StyleResourceValue) {
+            int styleId = bridgeContext.getDynamicIdByStyle(((StyleResourceValue) preferenceTheme));
+            if (styleId != 0) {
+                return new ContextThemeWrapper(bridgeContext, styleId);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns a {@link LinearLayout} containing all the UI widgets representing the preferences
+     * passed in the group adapter.
+     */
+    @Nullable
+    private static LinearLayout setUpPreferencesListView(@NonNull BridgeContext bridgeContext,
+            @NonNull Context themedContext, @NonNull ArrayList<Object> viewCookie,
+            @NonNull Object preferenceGroupAdapter) throws ReflectionException {
+        // Setup the LinearLayout that will contain the preferences
+        LinearLayout listView = new LinearLayout(themedContext);
+        listView.setOrientation(LinearLayout.VERTICAL);
+        listView.setLayoutParams(
+                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+        if (!viewCookie.isEmpty()) {
+            bridgeContext.addViewKey(listView, viewCookie.get(0));
+        }
+
+        // Get all the preferences and add them to the LinearLayout
+        Integer preferencesCount =
+                (Integer) invoke(getMethod(preferenceGroupAdapter.getClass(), "getItemCount"),
+                        preferenceGroupAdapter);
+        if (preferencesCount == null) {
+            return listView;
+        }
+
+        Method getItemId = getMethod(preferenceGroupAdapter.getClass(), "getItemId", int.class);
+        Method getItemViewType =
+                getMethod(preferenceGroupAdapter.getClass(), "getItemViewType", int.class);
+        Method onCreateViewHolder =
+                getMethod(preferenceGroupAdapter.getClass(), "onCreateViewHolder", ViewGroup.class,
+                        int.class);
+        for (int i = 0; i < preferencesCount; i++) {
+            Long id = (Long) invoke(getItemId, preferenceGroupAdapter, i);
+            if (id == null) {
+                continue;
+            }
+
+            // Get the type of the preference layout and bind it to a newly created view holder
+            Integer type = (Integer) invoke(getItemViewType, preferenceGroupAdapter, i);
+            Object viewHolder =
+                    invoke(onCreateViewHolder, preferenceGroupAdapter, listView, type);
+            if (viewHolder == null) {
+                continue;
+            }
+            invoke(getMethod(preferenceGroupAdapter.getClass(), "onBindViewHolder",
+                    viewHolder.getClass(), int.class), preferenceGroupAdapter, viewHolder, i);
+
+            try {
+                // Get the view from the view holder and add it to our layout
+                View itemView =
+                        (View) viewHolder.getClass().getField("itemView").get(viewHolder);
+
+                int arrayPosition = id.intValue() - 1; // IDs are 1 based
+                if (arrayPosition >= 0 && arrayPosition < viewCookie.size()) {
+                    bridgeContext.addViewKey(itemView, viewCookie.get(arrayPosition));
+                }
+                listView.addView(itemView);
+            } catch (IllegalAccessException | NoSuchFieldException ignored) {
+            }
+        }
+
+        return listView;
+    }
+
+    /**
+     * Inflates a preferences layout using the support library. If the support library is not
+     * available, this method will return null without advancing the parsers.
+     */
+    @Nullable
+    public static View inflatePreference(@NonNull BridgeContext bridgeContext,
+            @NonNull XmlPullParser parser, @Nullable ViewGroup root) {
+        try {
+            LayoutlibCallback callback = bridgeContext.getLayoutlibCallback();
+
+            Context context = getThemedContext(bridgeContext);
+            if (context == null) {
+                // Probably we couldn't find the "preferenceTheme" in the theme
+                return null;
+            }
+
+            // Create PreferenceManager
+            Object preferenceManager =
+                    instantiateClass(callback, PREFERENCE_MANAGER, new Class[]{Context.class},
+                            new Object[]{context});
+
+            // From this moment on, we can assume that we found the support library and that
+            // nothing should fail
+
+            // Create PreferenceScreen
+            Object preferenceScreen =
+                    invoke(getMethod(preferenceManager.getClass(), "createPreferenceScreen",
+                            Context.class), preferenceManager, context);
+            if (preferenceScreen == null) {
+                return null;
+            }
+
+            // Setup a parser that stores the list of cookies in the same order as the preferences
+            // are inflated. That way we can later reconstruct the list using the preference id
+            // since they are sequential and start in 1.
+            ArrayList<Object> viewCookie = new ArrayList<>();
+            if (parser instanceof BridgeXmlBlockParser) {
+                // Setup a parser that stores the XmlTag
+                parser = new BridgeXmlBlockParser(parser, null, false) {
+                    @Override
+                    public Object getViewCookie() {
+                        return ((BridgeXmlBlockParser) getParser()).getViewCookie();
+                    }
+
+                    @Override
+                    public int next() throws XmlPullParserException, IOException {
+                        int ev = super.next();
+                        if (ev == XmlPullParser.START_TAG) {
+                            viewCookie.add(this.getViewCookie());
+                        }
+
+                        return ev;
+                    }
+                };
+            }
+
+            // Create the PreferenceInflater
+            Object inflatedPreference =
+              createInflatedPreference(callback, context, parser, preferenceScreen,
+                preferenceManager);
+
+            // Setup the RecyclerView (set adapter and layout manager)
+            Object preferenceGroupAdapter =
+                    createPreferenceGroupAdapter(callback, inflatedPreference);
+
+            // Instead of just setting the group adapter as adapter for a RecyclerView, we manually
+            // get all the items and add them to a LinearLayout. This allows us to set the view
+            // cookies so the preferences are correctly linked to their XML.
+            LinearLayout listView = setUpPreferencesListView(bridgeContext, context, viewCookie,
+                    preferenceGroupAdapter);
+
+            ScrollView scrollView = new ScrollView(context);
+            scrollView.setLayoutParams(
+              new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+            scrollView.addView(listView);
+
+            if (root != null) {
+                root.addView(scrollView);
+            }
+
+            return scrollView;
+        } catch (ReflectionException e) {
+            return null;
+        }
+    }
+}
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
index c59b1a6..11da445 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
@@ -24,8 +24,8 @@
 
 import java.io.PrintStream;
 import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
@@ -33,7 +33,7 @@
  *
  * This is used in conjunction with layoublib_create: certain Android java classes are mere
  * wrappers around a heavily native based implementation, and we need a way to run these classes
- * in our Eclipse rendering framework without bringing all the native code from the Android
+ * in our Android Studio rendering framework without bringing all the native code from the Android
  * platform.
  *
  * Thus we instruct layoutlib_create to modify the bytecode of these classes to replace their
@@ -61,7 +61,7 @@
  * following mechanism:
  *
  * - {@link #addNewDelegate(Object)} and {@link #removeJavaReferenceFor(long)} adds and removes
- *   the delegate to/from a list. This list hold the reference and prevents the GC from reclaiming
+ *   the delegate to/from a set. This set holds the reference and prevents the GC from reclaiming
  *   the delegate.
  *
  * - {@link #addNewDelegate(Object)} also adds the delegate to a {@link SparseArray} that holds a
@@ -76,12 +76,12 @@
     @SuppressWarnings("FieldCanBeLocal")
     private final Class<T> mClass;
     private static final SparseWeakArray<Object> sDelegates = new SparseWeakArray<>();
-    /** list used to store delegates when their main object holds a reference to them.
+    /** Set used to store delegates when their main object holds a reference to them.
      * This is to ensure that the WeakReference in the SparseWeakArray doesn't get GC'ed
      * @see #addNewDelegate(Object)
      * @see #removeJavaReferenceFor(long)
      */
-    private static final List<Object> sJavaReferences = new ArrayList<>();
+    private static final Set<Object> sJavaReferences = new HashSet<>();
     private static final AtomicLong sDelegateCounter = new AtomicLong(1);
 
     public DelegateManager(Class<T> theClass) {
@@ -129,7 +129,7 @@
         long native_object = sDelegateCounter.getAndIncrement();
         synchronized (DelegateManager.class) {
             sDelegates.put(native_object, newDelegate);
-            assert !sJavaReferences.contains(newDelegate);
+            // Only for development: assert !sJavaReferences.contains(newDelegate);
             sJavaReferences.add(newDelegate);
         }
 
@@ -165,5 +165,6 @@
             int idx = sDelegates.indexOfValue(reference);
             out.printf("[%d] %s\n", sDelegates.keyAt(idx), reference.getClass().getSimpleName());
         }
+        out.printf("\nTotal number of objects: %d\n", sJavaReferences.size());
     }
 }
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
index a39eb4d..769ee33 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
@@ -620,7 +620,8 @@
             int y = 0;
             int width;
             int height;
-            Rectangle clipBounds = originalGraphics.getClipBounds();
+            Rectangle clipBounds = originalGraphics.getClip() != null ? originalGraphics
+                    .getClipBounds() : null;
             if (clipBounds != null) {
                 if (clipBounds.width == 0 || clipBounds.height == 0) {
                     // Clip is 0 so no need to paint anything.
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index 1afd90d..97698df 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;
@@ -364,8 +360,10 @@
                 return;
             }
             // Check if an actionbar is needed
-            boolean windowActionBar = getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR,
-                    !isThemeAppCompat(), true);
+            boolean isMenu = "menu".equals(mParams.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG));
+            boolean windowActionBar = isMenu ||
+                    getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR,
+                            !mContext.isAppCompatTheme(), true);
             if (windowActionBar) {
                 mActionBarSize = getDimension(ATTR_ACTION_BAR_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT);
             } else {
@@ -420,33 +418,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..feed045 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;
@@ -44,6 +45,7 @@
 import com.android.layoutlib.bridge.android.RenderParamsFlags;
 import com.android.layoutlib.bridge.android.graphics.NopCanvas;
 import com.android.layoutlib.bridge.android.support.DesignLibUtil;
+import com.android.layoutlib.bridge.android.support.SupportPreferencesUtil;
 import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
 import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
 import com.android.resources.ResourceType;
@@ -303,6 +305,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());
@@ -311,8 +327,14 @@
             boolean isPreference = "PreferenceScreen".equals(rootTag);
             View view;
             if (isPreference) {
-                view = Preference_Delegate.inflatePreference(getContext(), mBlockParser,
+                // First try to use the support library inflater. If something fails, fallback
+                // to the system preference inflater.
+                view = SupportPreferencesUtil.inflatePreference(getContext(), mBlockParser,
                         mContentRoot);
+                if (view == null) {
+                    view = Preference_Delegate.inflatePreference(getContext(), mBlockParser,
+                            mContentRoot);
+                }
             } else {
                 view = mInflater.inflate(mBlockParser, mContentRoot);
             }
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/src/com/android/layoutlib/bridge/util/ReflectionUtils.java b/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java
index 7ce27b6..040191e 100644
--- a/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java
+++ b/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java
@@ -37,6 +37,15 @@
         }
     }
 
+    @NonNull
+    public static Method getAccessibleMethod(@NonNull Class<?> clazz, @NonNull String name,
+      @Nullable Class<?>... params) throws ReflectionException {
+        Method method = getMethod(clazz, name, params);
+        method.setAccessible(true);
+
+        return method;
+    }
+
     @Nullable
     public static Object invoke(@NonNull Method method, @Nullable Object object,
             @Nullable Object... args) throws ReflectionException {
@@ -74,6 +83,25 @@
     }
 
     /**
+     * Looks through the class hierarchy of {@code object} at runtime and returns the class matching
+     * the name {@code className}.
+     * <p>
+     * This is used when we cannot use Class.forName() since the class we want was loaded from a
+     * different ClassLoader.
+     */
+    @NonNull
+    public static Class<?> getClassInstance(@NonNull Object object, @NonNull String className) {
+        Class<?> superClass = object.getClass();
+        while (superClass != null) {
+            if (className.equals(superClass.getName())) {
+                return superClass;
+            }
+            superClass = superClass.getSuperclass();
+        }
+        throw new RuntimeException("invalid object/classname combination.");
+    }
+
+    /**
      * Wraps all reflection related exceptions. Created since ReflectiveOperationException was
      * introduced in 1.7 and we are still on 1.6
      */
diff --git a/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
index bad296b..6eeb82c 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png b/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png
index 9f26627..26aed6a 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png b/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png
index 89009be..aaf1514 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png b/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png
new file mode 100644
index 0000000..4e448c8
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png b/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png
new file mode 100644
index 0000000..290018b
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png
Binary files differ
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/simple_activity.xml b/bridge/tests/res/testApp/MyApplication/src/main/res/layout/simple_activity.xml
new file mode 100644
index 0000000..14b93f3
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/src/main/res/layout/simple_activity.xml
@@ -0,0 +1,32 @@
+<!--
+  ~ 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.
+  -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:paddingLeft="@dimen/activity_horizontal_margin"
+                android:paddingRight="@dimen/activity_horizontal_margin"
+                android:paddingTop="@dimen/activity_vertical_margin"
+                android:paddingBottom="@dimen/activity_vertical_margin">
+
+    <TextView
+        android:text="@string/hello_world"
+        android:layout_width="wrap_content"
+        android:layout_height="200dp"
+        android:background="#FF0000"
+        android:id="@+id/text1"/>
+
+</RelativeLayout>
\ No newline at end of file
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..e7c6cc9 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.
@@ -309,7 +309,44 @@
     /** Test activity.xml */
     @Test
     public void testActivity() throws ClassNotFoundException {
-        renderAndVerify("activity.xml", "activity.png");
+        try {
+            renderAndVerify("activity.xml", "activity.png");
+        } catch (AssertionError e) {
+            // This is a KI in CalendarWidget and DatePicker rendering.
+            // Tracker bug: http://b.android.com/214370
+            if (!e.getLocalizedMessage().startsWith("Images differ (by 6.5%)")) {
+                throw e;
+            }
+        }
+    }
+
+    @Test
+    public void testActivityActionBar() throws ClassNotFoundException {
+        LayoutPullParser parser = createLayoutPullParser("simple_activity.xml");
+        LayoutLibTestCallback layoutLibCallback = new LayoutLibTestCallback(getLogger());
+        layoutLibCallback.initResources();
+
+        SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
+                layoutLibCallback, "Theme.Material.Light.NoActionBar", false,
+                RenderingMode.V_SCROLL, 22);
+
+        renderAndVerify(params, "simple_activity_noactionbar.png");
+
+        parser = createLayoutPullParser("simple_activity.xml");
+        params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
+                layoutLibCallback, "Theme.Material.Light", false,
+                RenderingMode.V_SCROLL, 22);
+
+        renderAndVerify(params, "simple_activity.png");
+
+        // This also tests that a theme with "NoActionBar" DOES HAVE an action bar when we are
+        // displaying menus.
+        parser = createLayoutPullParser("simple_activity.xml");
+        params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
+                layoutLibCallback, "Theme.Material.Light.NoActionBar", false,
+                RenderingMode.V_SCROLL, 22);
+        params.setFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG, "menu");
+        renderAndVerify(params, "simple_activity.png");
     }
 
     /** Test allwidgets.xml */
@@ -341,7 +378,11 @@
         obj = null;
         while(ref.get() != null) {
             System.gc();
+            System.runFinalization();
         }
+
+        System.gc();
+        System.runFinalization();
     }
 
     @AfterClass
@@ -433,6 +474,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 +528,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);
diff --git a/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index 3b37612..a2f8372 100644
--- a/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -26,6 +26,7 @@
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.ListIterator;
@@ -48,8 +49,6 @@
     private final String mOsDestJar;
     /** List of classes to inject in the final JAR from _this_ archive. */
     private final Class<?>[] mInjectClasses;
-    /** The set of methods to stub out. */
-    private final Set<String> mStubMethods;
     /** All classes to output as-is, except if they have native methods. */
     private Map<String, ClassReader> mKeep;
     /** All dependencies that must be completely stubbed. */
@@ -107,7 +106,6 @@
             }
         }
         mInjectClasses = injectedClasses.toArray(new Class<?>[0]);
-        mStubMethods = new HashSet<>(Arrays.asList(createInfo.getOverriddenMethods()));
 
         // Create the map/set of methods to change to delegates
         mDelegateMethods = new HashMap<>();
@@ -384,7 +382,7 @@
         if (mInjectedMethodsMap.keySet().contains(binaryNewName)) {
             cv = new InjectMethodsAdapter(cv, mInjectedMethodsMap.get(binaryNewName));
         }
-        cv = new TransformClassAdapter(mLog, mStubMethods, mDeleteReturns.get(className),
+        cv = new TransformClassAdapter(mLog, Collections.emptySet(), mDeleteReturns.get(className),
                 newName, cv, stubNativesOnly);
 
         Set<String> delegateMethods = mDelegateMethods.get(className);
diff --git a/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 061bed7..bf61f7e 100644
--- a/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -64,18 +64,6 @@
     }
 
     /**
-     * Returns The list of methods to stub out. Each entry must be in the form
-     * "package.package.OuterClass$InnerClass#MethodName".
-     * The list can be empty but must not be null.
-     * <p/>
-     * This usage is deprecated. Please use method 'delegates' instead.
-     */
-    @Override
-    public String[] getOverriddenMethods() {
-        return OVERRIDDEN_METHODS;
-    }
-
-    /**
      * Returns the list of classes to rename, must be an even list: the binary FQCN
      * of class to replace followed by the new FQCN.
      * The list can be empty but must not be null.
@@ -186,6 +174,7 @@
         "android.content.res.Resources$Theme#resolveAttributes",
         "android.content.res.AssetManager#newTheme",
         "android.content.res.AssetManager#deleteTheme",
+        "android.content.res.AssetManager#getAssignedPackageIdentifiers",
         "android.content.res.TypedArray#getValueAt",
         "android.content.res.TypedArray#obtain",
         "android.graphics.BitmapFactory#finishDecode",
@@ -309,14 +298,6 @@
     };
 
     /**
-     * The list of methods to stub out. Each entry must be in the form
-     *  "package.package.OuterClass$InnerClass#MethodName".
-     *  This usage is deprecated. Please use method 'delegates' instead.
-     */
-    private final static String[] OVERRIDDEN_METHODS = new String[] {
-    };
-
-    /**
      *  The list of classes to rename, must be an even list: the binary FQCN
      *  of class to replace followed by the new FQCN.
      */
diff --git a/create/src/com/android/tools/layoutlib/create/ICreateInfo.java b/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
index 6c62423..535a9a8 100644
--- a/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
+++ b/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
@@ -45,13 +45,6 @@
     String[] getDelegateClassNatives();
 
     /**
-     * Returns The list of methods to stub out. Each entry must be in the form
-     * "package.package.OuterClass$InnerClass#MethodName".
-     * The list can be empty but must not be null.
-     */
-    String[] getOverriddenMethods();
-
-    /**
      * Returns the list of classes to rename, must be an even list: the binary FQCN
      * of class to replace followed by the new FQCN.
      * The list can be empty but must not be null.
diff --git a/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java b/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
index c4dd7ee..0560d8a 100644
--- a/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
+++ b/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
@@ -107,12 +107,6 @@
             }
 
             @Override
-            public String[] getOverriddenMethods() {
-                // methods to force override
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
             public String[] getRenamedClasses() {
                 // classes to rename (so that we can replace them)
                 return new String[] {
@@ -187,12 +181,6 @@
             }
 
             @Override
-            public String[] getOverriddenMethods() {
-                // methods to force override
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
             public String[] getRenamedClasses() {
                 // classes to rename (so that we can replace them)
                 return EMPTY_STRING_ARRAY;
@@ -274,12 +262,6 @@
             }
 
             @Override
-            public String[] getOverriddenMethods() {
-                // methods to force override
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
             public String[] getRenamedClasses() {
                 // classes to rename (so that we can replace them)
                 return EMPTY_STRING_ARRAY;
@@ -360,12 +342,6 @@
             }
 
             @Override
-            public String[] getOverriddenMethods() {
-                // methods to force override
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
             public String[] getRenamedClasses() {
                 // classes to rename (so that we can replace them)
                 return EMPTY_STRING_ARRAY;