LayoutLib: render system/title/action bars.

Also a few generic fixes in the layoutlib itself to support
this.

Change-Id: Ie3f24c9056bd3cc72f39f8a4f2c0861be15bff55
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index 3d4c76a..ca7db8c 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -17,6 +17,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_JAVA_RESOURCE_DIRS := resources
+
 
 LOCAL_JAVA_LIBRARIES := \
 	kxml2-2.3.0 \
diff --git a/tools/layoutlib/bridge/resources/bars/action_bar.xml b/tools/layoutlib/bridge/resources/bars/action_bar.xml
new file mode 100644
index 0000000..cd99a09
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/action_bar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+	<ImageView
+			android:layout_height="wrap_content"
+			android:layout_width="wrap_content"
+			android:layout_gravity="center"/>
+	<TextView
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
new file mode 100644
index 0000000..4bcd2be
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
new file mode 100644
index 0000000..cfeba3e
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
new file mode 100644
index 0000000..1d97e05
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..c629387
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
new file mode 100644
index 0000000..29df909
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+	<TextView
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:layout_weight="1"
+			android:text=" "/>
+	<ImageView
+			android:layout_height="wrap_content"
+			android:layout_width="wrap_content"
+			android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
new file mode 100644
index 0000000..8a3b87a
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+	<ImageView
+			android:layout_height="wrap_content"
+			android:layout_width="wrap_content"/>
+	<ImageView
+			android:layout_height="wrap_content"
+			android:layout_width="wrap_content"/>
+	<ImageView
+			android:layout_height="wrap_content"
+			android:layout_width="wrap_content"/>
+	<TextView
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:layout_weight="1"/>
+	<ImageView
+			android:layout_height="wrap_content"
+			android:layout_width="wrap_content"
+			android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/title_bar.xml b/tools/layoutlib/bridge/resources/bars/title_bar.xml
new file mode 100644
index 0000000..29fcc4b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/title_bar.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+	<TextView
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
index 993c305..ee60eb4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
@@ -18,6 +18,9 @@
 
 import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeResources.NinePatchInputStream;
+import com.android.ninepatch.NinePatch;
+import com.android.ninepatch.NinePatchChunk;
 import com.android.resources.Density;
 
 import android.content.res.AssetManager;
@@ -438,6 +441,8 @@
             return null;
         }
 
+        boolean isNinePatch = is instanceof NinePatchInputStream;
+
         // we need mark/reset to work properly
 
         if (!is.markSupported()) {
@@ -466,7 +471,29 @@
                 if (opts != null) {
                     density = Density.getEnum(opts.inDensity);
                 }
-                bm = Bitmap_Delegate.createBitmap(is, true, density);
+
+                if (isNinePatch) {
+                    // load the bitmap as a nine patch
+                    NinePatch ninePatch = NinePatch.load(is, true /*is9Patch*/, false /*convert*/);
+
+                    // get the bitmap and chunk objects.
+                    bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/,
+                            density);
+                    NinePatchChunk chunk = ninePatch.getChunk();
+
+                    // put the chunk in the bitmap
+                    bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk));
+
+                    // read the padding
+                    int[] padding = chunk.getPadding();
+                    outPadding.left = padding[0];
+                    outPadding.top = padding[1];
+                    outPadding.right = padding[2];
+                    outPadding.bottom = padding[3];
+                } else {
+                    // load the bitmap directly.
+                    bm = Bitmap_Delegate.createBitmap(is, true, density);
+                }
             } catch (IOException e) {
                 return null;
             }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 93c81d1..65f6bed 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -21,7 +21,7 @@
 
 import com.android.ide.common.rendering.api.Capability;
 import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderParams;
 import com.android.ide.common.rendering.api.RenderSession;
 import com.android.ide.common.rendering.api.Result;
 import com.android.layoutlib.bridge.android.BridgeAssetManager;
@@ -293,15 +293,15 @@
 
     /**
      * Starts a layout session by inflating and rendering it. The method returns a
-     * {@link ILayoutScene} on which further actions can be taken.
+     * {@link RenderSession} on which further actions can be taken.
      *
-     * @param params the {@link SceneParams} object with all the information necessary to create
+     * @param params the {@link RenderParams} object with all the information necessary to create
      *           the scene.
-     * @return a new {@link ILayoutScene} object that contains the result of the layout.
+     * @return a new {@link RenderSession} object that contains the result of the layout.
      * @since 5
      */
     @Override
-    public RenderSession createSession(Params params) {
+    public RenderSession createSession(RenderParams params) {
         try {
             Result lastResult = SUCCESS.createResult();
             RenderSessionImpl scene = new RenderSessionImpl(params);
@@ -331,10 +331,6 @@
         }
     }
 
-    /*
-     * (non-Javadoc)
-     * @see com.android.layoutlib.api.ILayoutLibBridge#clearCaches(java.lang.Object)
-     */
     @Override
     public void clearCaches(Object projectKey) {
         if (projectKey != null) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
index 0c6fa20..765fd99 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -18,7 +18,7 @@
 
 import com.android.ide.common.rendering.api.IAnimationListener;
 import com.android.ide.common.rendering.api.ILayoutPullParser;
-import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderParams;
 import com.android.ide.common.rendering.api.RenderSession;
 import com.android.ide.common.rendering.api.Result;
 import com.android.ide.common.rendering.api.ViewInfo;
@@ -128,7 +128,7 @@
             boolean isFrameworkAnimation, IAnimationListener listener) {
         try {
             Bridge.prepareThread();
-            mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+            mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
             if (mLastResult.isSuccess()) {
                 mLastResult = mSession.animate(targetObject, animationName, isFrameworkAnimation,
                         listener);
@@ -150,7 +150,7 @@
 
         try {
             Bridge.prepareThread();
-            mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+            mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
             if (mLastResult.isSuccess()) {
                 mLastResult = mSession.insertChild((ViewGroup) parentView, childXml, index,
                         listener);
@@ -176,7 +176,7 @@
 
         try {
             Bridge.prepareThread();
-            mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+            mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
             if (mLastResult.isSuccess()) {
                 mLastResult = mSession.moveChild((ViewGroup) parentView, (View) childView, index,
                         layoutParams, listener);
@@ -197,7 +197,7 @@
 
         try {
             Bridge.prepareThread();
-            mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+            mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
             if (mLastResult.isSuccess()) {
                 mLastResult = mSession.removeChild((View) childView, listener);
             }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index 5ea0a8d..d31fcc8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -22,6 +22,7 @@
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.BridgeConstants;
 import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.ninepatch.NinePatch;
 import com.android.resources.ResourceType;
 import com.android.util.Pair;
 
@@ -58,6 +59,18 @@
     private boolean[] mPlatformResourceFlag = new boolean[1];
 
     /**
+     * Simpler wrapper around FileInputStream. This is used when the input stream represent
+     * not a normal bitmap but a nine patch.
+     * This is useful when the InputStream is created in a method but used in another that needs
+     * to know whether this is 9-patch or not, such as BitmapFactory.
+     */
+    public class NinePatchInputStream extends FileInputStream {
+        public NinePatchInputStream(File file) throws FileNotFoundException {
+            super(file);
+        }
+    }
+
+    /**
      * This initializes the static field {@link Resources#mSystem} which is used
      * by methods who get global resources using {@link Resources#getSystem()}.
      * <p/>
@@ -129,7 +142,7 @@
         ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
 
         if (value != null) {
-            return ResourceHelper.getDrawable(value, mContext, value.isFramework());
+            return ResourceHelper.getDrawable(value, mContext);
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
@@ -165,44 +178,9 @@
         ResourceValue resValue = getResourceValue(id, mPlatformResourceFlag);
 
         if (resValue != null) {
-            String value = resValue.getValue();
-            if (value != null) {
-                // first check if the value is a file (xml most likely)
-                File f = new File(value);
-                if (f.isFile()) {
-                    try {
-                        // let the framework inflate the ColorStateList from the XML file, by
-                        // providing an XmlPullParser
-                        KXmlParser parser = new KXmlParser();
-                        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
-                        parser.setInput(new FileReader(f));
-
-                        return ColorStateList.createFromXml(this,
-                                new BridgeXmlBlockParser(parser, mContext, resValue.isFramework()));
-                    } catch (XmlPullParserException e) {
-                        Bridge.getLog().error(LayoutLog.TAG_BROKEN,
-                                "Failed to configure parser for " + value, e, null /*data*/);
-                        // we'll return null below.
-                    } catch (Exception e) {
-                        // this is an error and not warning since the file existence is
-                        // checked before attempting to parse it.
-                        Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
-                                "Failed to parse file " + value, e, null /*data*/);
-
-                        return null;
-                    }
-                } else {
-                    // try to load the color state list from an int
-                    try {
-                        int color = ResourceHelper.getColor(value);
-                        return ColorStateList.valueOf(color);
-                    } catch (NumberFormatException e) {
-                        Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
-                                "Failed to convert " + value + " into a ColorStateList", e,
-                                null /*data*/);
-                        return null;
-                    }
-                }
+            ColorStateList stateList = ResourceHelper.getColorStateList(resValue, mContext);
+            if (stateList != null) {
+                return stateList;
             }
         }
 
@@ -562,13 +540,19 @@
         ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
 
         if (value != null) {
-            String v = value.getValue();
+            String path = value.getValue();
 
-            if (v != null) {
+            if (path != null) {
                 // check this is a file
-                File f = new File(value.getValue());
+                File f = new File(path);
                 if (f.isFile()) {
                     try {
+                        // if it's a nine-patch return a custom input stream so that
+                        // other methods (mainly bitmap factory) can detect it's a 9-patch
+                        // and actually load it as a 9-patch instead of a normal bitmap
+                        if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
+                            return new NinePatchInputStream(f);
+                        }
                         return new FileInputStream(f);
                     } catch (FileNotFoundException e) {
                         NotFoundException newE = new NotFoundException();
@@ -590,9 +574,17 @@
     public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
         getValue(id, value, true);
 
-        File f = new File(value.string.toString());
+        String path = value.string.toString();
+
+        File f = new File(path);
         if (f.isFile()) {
             try {
+                // if it's a nine-patch return a custom input stream so that
+                // other methods (mainly bitmap factory) can detect it's a 9-patch
+                // and actually load it as a 9-patch instead of a normal bitmap
+                if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
+                    return new NinePatchInputStream(f);
+                }
                 return new FileInputStream(f);
             } catch (FileNotFoundException e) {
                 NotFoundException exception = new NotFoundException();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index cf2c0ff..c226b8b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -690,7 +690,7 @@
             return null;
         }
 
-        return ResourceHelper.getDrawable(value, mContext, mResourceData[index].isFramework());
+        return ResourceHelper.getDrawable(value, mContext);
     }
 
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
new file mode 100644
index 0000000..f039994
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2011 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.bars;
+
+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.Bridge;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.resources.Density;
+
+import org.kxml2.io.KXmlParser;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap_Delegate;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Base "bar" class for the window decor around the the edited layout.
+ * This is basically an horizontal layout that loads a given layout on creation (it is read
+ * through {@link Class#getResourceAsStream(String)}).
+ *
+ * The given layout should be a merge layout so that all the children belong to this class directly.
+ *
+ * It also provides a few utility methods to configure the content of the layout.
+ */
+abstract class CustomBar extends LinearLayout {
+
+    protected abstract TextView getStyleableTextView();
+
+    protected CustomBar(Context context, Density density, String layoutPath)
+            throws XmlPullParserException {
+        super(context);
+        setOrientation(LinearLayout.HORIZONTAL);
+        setBackgroundColor(0xFF000000);
+
+        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+
+        KXmlParser parser = new KXmlParser();
+        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+        parser.setInput(
+                getClass().getResourceAsStream(layoutPath),
+                "UTF8");
+
+        BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
+                parser, (BridgeContext) context, false);
+
+        inflater.inflate(bridgeParser, this, true);
+    }
+
+    protected void loadIcon(int index, String iconName, Density density) {
+        View child = getChildAt(index);
+        if (child instanceof ImageView) {
+            ImageView imageView = (ImageView) child;
+
+            // bitmap url relative to this class
+            String path = "/bars/" + density.getResourceValue() + "/" + iconName;
+
+            // create a bitmap
+            Bitmap bitmap = Bridge.getCachedBitmap(path, true /*isFramework*/);
+
+            if (bitmap == null) {
+                InputStream stream = getClass().getResourceAsStream(path);
+
+                if (stream != null) {
+                    try {
+                        bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density);
+                        Bridge.setCachedBitmap(path, bitmap, true /*isFramework*/);
+                    } catch (IOException e) {
+                        return;
+                    }
+                }
+            }
+
+            if (bitmap != null) {
+                BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), bitmap);
+                imageView.setBackgroundDrawable(drawable);
+            }
+        }
+    }
+
+    protected void loadIcon(int index, String iconReference) {
+        ResourceValue value = getResourceValue(iconReference);
+        if (value != null) {
+            View child = getChildAt(index);
+            if (child instanceof ImageView) {
+                ImageView imageView = (ImageView) child;
+
+                Drawable drawable = ResourceHelper.getDrawable(
+                        value, (BridgeContext) mContext);
+                if (drawable != null) {
+                    imageView.setBackgroundDrawable(drawable);
+                }
+            }
+        }
+    }
+
+    protected TextView setText(int index, String stringReference) {
+        View child = getChildAt(index);
+        if (child instanceof TextView) {
+            TextView textView = (TextView) child;
+            ResourceValue value = getResourceValue(stringReference);
+            if (value != null) {
+                textView.setText(value.getValue());
+            } else {
+                textView.setText(stringReference);
+            }
+            return textView;
+        }
+
+        return null;
+    }
+
+    protected void setStyle(String themeEntryName) {
+
+        BridgeContext bridgeContext = (BridgeContext) mContext;
+        RenderResources res = bridgeContext.getRenderResources();
+
+        ResourceValue value = res.findItemInTheme(themeEntryName);
+        value = res.resolveResValue(value);
+
+        if (value instanceof StyleResourceValue == false) {
+            return;
+        }
+
+        StyleResourceValue style = (StyleResourceValue) value;
+
+        // get the background
+        ResourceValue backgroundValue = res.findItemInStyle(style, "background");
+        backgroundValue = res.resolveResValue(backgroundValue);
+        if (backgroundValue != null) {
+            Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
+            if (d != null) {
+                setBackgroundDrawable(d);
+            }
+        }
+
+        TextView textView = getStyleableTextView();
+        if (textView != null) {
+            // get the text style
+            ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle");
+            textStyleValue = res.resolveResValue(textStyleValue);
+            if (textStyleValue instanceof StyleResourceValue) {
+                StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
+
+                ResourceValue textSize = res.findItemInStyle(textStyle, "textSize");
+                textSize = res.resolveResValue(textSize);
+
+                if (textSize != null) {
+                    TypedValue out = new TypedValue();
+                    if (ResourceHelper.stringToFloat(textSize.getValue(), out)) {
+                        textView.setTextSize(
+                                out.getDimension(bridgeContext.getResources().mMetrics));
+                    }
+                }
+
+
+                ResourceValue textColor = res.findItemInStyle(textStyle, "textColor");
+                textColor = res.resolveResValue(textColor);
+                if (textColor != null) {
+                    ColorStateList stateList = ResourceHelper.getColorStateList(
+                            textColor, bridgeContext);
+                    if (stateList != null) {
+                        textView.setTextColor(stateList);
+                    }
+                }
+            }
+        }
+    }
+
+    private ResourceValue getResourceValue(String reference) {
+        BridgeContext bridgeContext = (BridgeContext) mContext;
+        RenderResources res = bridgeContext.getRenderResources();
+
+        // find the resource
+        ResourceValue value = res.findResValue(reference, false /*isFramework*/);
+
+        // resolve it if needed
+        return res.resolveResValue(value);
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
new file mode 100644
index 0000000..3af4e3a
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 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.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class FakeActionBar extends CustomBar {
+
+    private TextView mTextView;
+
+    public FakeActionBar(Context context, Density density, String label, String icon)
+            throws XmlPullParserException {
+        super(context, density, "/bars/action_bar.xml");
+
+        // Cannot access the inside items through id because no R.id values have been
+        // created for them.
+        // We do know the order though.
+        loadIcon(0, icon);
+        mTextView = setText(1, label);
+
+        setStyle("actionBarStyle");
+    }
+
+    @Override
+    protected TextView getStyleableTextView() {
+        return mTextView;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
new file mode 100644
index 0000000..92615dc
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 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.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class PhoneSystemBar extends CustomBar {
+
+    public PhoneSystemBar(Context context, Density density) throws XmlPullParserException {
+        super(context, density, "/bars/tablet_system_bar.xml");
+
+        // Cannot access the inside items through id because no R.id values have been
+        // created for them.
+        // We do know the order though.
+        // 0 is the spacer
+        loadIcon(1, "stat_sys_wifi_signal_4_fully.png", density);
+    }
+
+    @Override
+    protected TextView getStyleableTextView() {
+        return null;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
new file mode 100644
index 0000000..bc61799
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 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.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class TabletSystemBar extends CustomBar {
+
+    public TabletSystemBar(Context context, Density density) throws XmlPullParserException {
+        super(context, density, "/bars/tablet_system_bar.xml");
+
+        // Cannot access the inside items through id because no R.id values have been
+        // created for them.
+        // We do know the order though.
+        loadIcon(0, "ic_sysbar_back_default.png", density);
+        loadIcon(1, "ic_sysbar_home_default.png", density);
+        loadIcon(2, "ic_sysbar_recent_default.png", density);
+        // 3 is the spacer
+        loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density);
+    }
+
+    @Override
+    protected TextView getStyleableTextView() {
+        return null;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
new file mode 100644
index 0000000..d7401d9
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 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.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class TitleBar extends CustomBar {
+
+    private TextView mTextView;
+
+    public TitleBar(Context context, Density density, String label)
+            throws XmlPullParserException {
+        super(context, density, "/bars/title_bar.xml");
+
+        // Cannot access the inside items through id because no R.id values have been
+        // created for them.
+        // We do know the order though.
+        mTextView = setText(0, label);
+
+        setStyle("windowTitleBackgroundStyle");
+    }
+
+    @Override
+    protected TextView getStyleableTextView() {
+        return mTextView;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index c8ad1d6..0aa2e6d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -29,14 +29,13 @@
 import com.android.ide.common.rendering.api.ILayoutPullParser;
 import com.android.ide.common.rendering.api.IProjectCallback;
 import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderParams;
 import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.RenderSession;
 import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.StyleResourceValue;
 import com.android.ide.common.rendering.api.ViewInfo;
-import com.android.ide.common.rendering.api.Params.RenderingMode;
+import com.android.ide.common.rendering.api.RenderParams.RenderingMode;
 import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider;
 import com.android.ide.common.rendering.api.Result.Status;
 import com.android.internal.util.XmlUtils;
@@ -47,11 +46,16 @@
 import com.android.layoutlib.bridge.android.BridgeWindow;
 import com.android.layoutlib.bridge.android.BridgeWindowSession;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.resources.Density;
+import com.android.layoutlib.bridge.bars.FakeActionBar;
+import com.android.layoutlib.bridge.bars.PhoneSystemBar;
+import com.android.layoutlib.bridge.bars.TabletSystemBar;
+import com.android.layoutlib.bridge.bars.TitleBar;
 import com.android.resources.ResourceType;
 import com.android.resources.ScreenSize;
 import com.android.util.Pair;
 
+import org.xmlpull.v1.XmlPullParserException;
+
 import android.animation.Animator;
 import android.animation.AnimatorInflater;
 import android.animation.LayoutTransition;
@@ -105,7 +109,7 @@
      */
     private static BridgeContext sCurrentContext = null;
 
-    private final Params mParams;
+    private final RenderParams mParams;
 
     // scene state
     private RenderSession mScene;
@@ -113,17 +117,18 @@
     private BridgeXmlBlockParser mBlockParser;
     private BridgeInflater mInflater;
     private ResourceValue mWindowBackground;
-    private FrameLayout mViewRoot;
+    private ViewGroup mViewRoot;
+    private FrameLayout mContentRoot;
     private Canvas mCanvas;
     private int mMeasuredScreenWidth = -1;
     private int mMeasuredScreenHeight = -1;
-    private boolean mIsAlphaChannelImage = true;
+    private boolean mIsAlphaChannelImage;
+    private boolean mWindowIsFloating;
 
     private int mStatusBarSize;
-    private int mTopBarSize;
     private int mSystemBarSize;
-    private int mTopOffset;
-    private int mTotalBarSize;
+    private int mTitleBarSize;
+    private int mActionBarSize;
 
 
     // information being returned through the API
@@ -146,9 +151,9 @@
      *
      * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
      */
-    public RenderSessionImpl(Params params) {
+    public RenderSessionImpl(RenderParams params) {
         // copy the params.
-        mParams = new Params(params);
+        mParams = new RenderParams(params);
     }
 
     /**
@@ -172,8 +177,8 @@
 
         // setup the display Metrics.
         DisplayMetrics metrics = new DisplayMetrics();
-        metrics.densityDpi = mParams.getDensity();
-        metrics.density = mParams.getDensity() / (float) DisplayMetrics.DENSITY_DEFAULT;
+        metrics.densityDpi = mParams.getDensity().getDpiValue();
+        metrics.density = metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
         metrics.scaledDensity = metrics.density;
         metrics.widthPixels = mParams.getScreenWidth();
         metrics.heightPixels = mParams.getScreenHeight();
@@ -190,17 +195,16 @@
         mIsAlphaChannelImage  = getBooleanThemeValue(resources,
                 "windowIsFloating", true /*defaultValue*/);
 
+        mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating",
+                true /*defaultValue*/);
 
         setUp();
 
         findBackground(resources);
         findStatusBar(resources, metrics);
-        findTopBar(resources, metrics);
+        findActionBar(resources, metrics);
         findSystemBar(resources, metrics);
 
-        mTopOffset = mStatusBarSize + mTopBarSize;
-        mTotalBarSize = mTopOffset + mSystemBarSize;
-
         // build the inflater and parser.
         mInflater = new BridgeInflater(mContext, mParams.getProjectCallback());
         mContext.setBridgeInflater(mInflater);
@@ -353,13 +357,100 @@
 
         try {
 
-            mViewRoot = new FrameLayout(mContext);
+            if (mWindowIsFloating || mParams.isForceNoDecor()) {
+                mViewRoot = mContentRoot = new FrameLayout(mContext);
+            } else {
+                /*
+                 * we're creating the following layout
+                 *
+                   +-------------------------------------------------+
+                   | System bar (only in phone UI)                   |
+                   +-------------------------------------------------+
+                   | Title/Action bar (optional)                     |
+                   +-------------------------------------------------+
+                   | Content, vertical extending                     |
+                   |                                                 |
+                   +-------------------------------------------------+
+                   | System bar (only in tablet UI)                  |
+                   +-------------------------------------------------+
+
+                 */
+
+                LinearLayout topLayout = new LinearLayout(mContext);
+                mViewRoot = topLayout;
+                topLayout.setOrientation(LinearLayout.VERTICAL);
+
+                if (mStatusBarSize > 0) {
+                    // system bar
+                    try {
+                        PhoneSystemBar systemBar = new PhoneSystemBar(mContext,
+                                mParams.getDensity());
+                        systemBar.setLayoutParams(
+                                new LinearLayout.LayoutParams(
+                                        LayoutParams.MATCH_PARENT, mStatusBarSize));
+                        topLayout.addView(systemBar);
+                    } catch (XmlPullParserException e) {
+
+                    }
+                }
+
+                // if the theme says no title/action bar, then the size will be 0
+                if (mActionBarSize > 0) {
+                    try {
+                        FakeActionBar actionBar = new FakeActionBar(mContext,
+                                mParams.getDensity(),
+                                mParams.getAppLabel(), mParams.getAppIcon());
+                        actionBar.setLayoutParams(
+                                new LinearLayout.LayoutParams(
+                                        LayoutParams.MATCH_PARENT, mActionBarSize));
+                        topLayout.addView(actionBar);
+                    } catch (XmlPullParserException e) {
+
+                    }
+                } else if (mTitleBarSize > 0) {
+                    try {
+                        TitleBar titleBar = new TitleBar(mContext,
+                                mParams.getDensity(), mParams.getAppLabel());
+                        titleBar.setLayoutParams(
+                                new LinearLayout.LayoutParams(
+                                        LayoutParams.MATCH_PARENT, mTitleBarSize));
+                        topLayout.addView(titleBar);
+                    } catch (XmlPullParserException e) {
+
+                    }
+                }
+
+
+                // content frame
+                mContentRoot = new FrameLayout(mContext);
+                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+                        LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+                params.weight = 1;
+                mContentRoot.setLayoutParams(params);
+                topLayout.addView(mContentRoot);
+
+                if (mSystemBarSize > 0) {
+                    // system bar
+                    try {
+                        TabletSystemBar systemBar = new TabletSystemBar(mContext,
+                                mParams.getDensity());
+                        systemBar.setLayoutParams(
+                                new LinearLayout.LayoutParams(
+                                        LayoutParams.MATCH_PARENT, mSystemBarSize));
+                        topLayout.addView(systemBar);
+                    } catch (XmlPullParserException e) {
+
+                    }
+                }
+
+            }
+
 
             // Sets the project callback (custom view loader) to the fragment delegate so that
             // it can instantiate the custom Fragment.
             Fragment_Delegate.setProjectCallback(mParams.getProjectCallback());
 
-            View view = mInflater.inflate(mBlockParser, mViewRoot);
+            View view = mInflater.inflate(mBlockParser, mContentRoot);
 
             Fragment_Delegate.setProjectCallback(null);
 
@@ -377,9 +468,8 @@
 
             // get the background drawable
             if (mWindowBackground != null) {
-                Drawable d = ResourceHelper.getDrawable(mWindowBackground,
-                        mContext, true /* isFramework */);
-                mViewRoot.setBackgroundDrawable(d);
+                Drawable d = ResourceHelper.getDrawable(mWindowBackground, mContext);
+                mContentRoot.setBackgroundDrawable(d);
             }
 
             return SUCCESS.createResult();
@@ -408,8 +498,8 @@
      * @throws IllegalStateException if the current context is different than the one owned by
      *      the scene, or if {@link #acquire(long)} was not called.
      *
-     * @see SceneParams#getRenderingMode()
-     * @see LayoutScene#render(long)
+     * @see RenderParams#getRenderingMode()
+     * @see RenderSession#render(long)
      */
     public Result render(boolean freshRender) {
         checkLock();
@@ -428,7 +518,7 @@
             if (mMeasuredScreenWidth == -1) {
                 newRenderSize = true;
                 mMeasuredScreenWidth = mParams.getScreenWidth();
-                mMeasuredScreenHeight = mParams.getScreenHeight() - mTotalBarSize;
+                mMeasuredScreenHeight = mParams.getScreenHeight();
 
                 if (renderingMode != RenderingMode.NORMAL) {
                     // measure the full size needed by the layout.
@@ -476,11 +566,11 @@
                 if (mParams.getImageFactory() != null) {
                     mImage = mParams.getImageFactory().getImage(
                             mMeasuredScreenWidth,
-                            mMeasuredScreenHeight + mTotalBarSize);
+                            mMeasuredScreenHeight);
                 } else {
                     mImage = new BufferedImage(
                             mMeasuredScreenWidth,
-                            mMeasuredScreenHeight + mTotalBarSize,
+                            mMeasuredScreenHeight,
                             BufferedImage.TYPE_INT_ARGB);
                     newImage = true;
                 }
@@ -491,46 +581,26 @@
                     Graphics2D gc = mImage.createGraphics();
                     gc.setColor(new Color(mParams.getOverrideBgColor(), true));
                     gc.setComposite(AlphaComposite.Src);
-                    gc.fillRect(0, 0, mMeasuredScreenWidth,
-                            mMeasuredScreenHeight + mTotalBarSize);
+                    gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
                     gc.dispose();
                 }
 
                 // create an Android bitmap around the BufferedImage
                 Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
-                        true /*isMutable*/,
-                        Density.getEnum(mParams.getDensity()));
+                        true /*isMutable*/, mParams.getDensity());
 
                 // create a Canvas around the Android bitmap
                 mCanvas = new Canvas(bitmap);
-                mCanvas.setDensity(mParams.getDensity());
-                mCanvas.translate(0, mTopOffset);
+                mCanvas.setDensity(mParams.getDensity().getDpiValue());
             }
 
             if (freshRender && newImage == false) {
                 Graphics2D gc = mImage.createGraphics();
                 gc.setComposite(AlphaComposite.Src);
 
-                if (mStatusBarSize > 0) {
-                    gc.setColor(new Color(0xFF3C3C3C, true));
-                    gc.fillRect(0, 0, mMeasuredScreenWidth, mStatusBarSize);
-                }
-
-                if (mTopBarSize > 0) {
-                    gc.setColor(new Color(0xFF7F7F7F, true));
-                    gc.fillRect(0, mStatusBarSize, mMeasuredScreenWidth, mTopOffset);
-                }
-
-                // erase the rest
                 gc.setColor(new Color(0x00000000, true));
-                gc.fillRect(0, mTopOffset,
-                        mMeasuredScreenWidth, mMeasuredScreenHeight + mTopOffset);
-
-                if (mSystemBarSize > 0) {
-                    gc.setColor(new Color(0xFF3C3C3C, true));
-                    gc.fillRect(0, mMeasuredScreenHeight + mTopOffset,
-                            mMeasuredScreenWidth, mMeasuredScreenHeight + mTotalBarSize);
-                }
+                gc.fillRect(0, 0,
+                        mMeasuredScreenWidth, mMeasuredScreenHeight);
 
                 // done
                 gc.dispose();
@@ -538,7 +608,7 @@
 
             mViewRoot.draw(mCanvas);
 
-            mViewInfoList = visitAllChildren((ViewGroup)mViewRoot, mContext, mTopOffset);
+            mViewInfoList = startVisitingViews(mViewRoot, 0);
 
             // success!
             return SUCCESS.createResult();
@@ -561,7 +631,7 @@
      * @throws IllegalStateException if the current context is different than the one owned by
      *      the scene, or if {@link #acquire(long)} was not called.
      *
-     * @see LayoutScene#animate(Object, String, boolean, IAnimationListener)
+     * @see RenderSession#animate(Object, String, boolean, IAnimationListener)
      */
     public Result animate(Object targetObject, String animationName,
             boolean isFrameworkAnimation, IAnimationListener listener) {
@@ -617,7 +687,7 @@
      * @throws IllegalStateException if the current context is different than the one owned by
      *      the scene, or if {@link #acquire(long)} was not called.
      *
-     * @see LayoutScene#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
+     * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
      */
     public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
             final int index, IAnimationListener listener) {
@@ -696,7 +766,7 @@
      * @throws IllegalStateException if the current context is different than the one owned by
      *      the scene, or if {@link #acquire(long)} was not called.
      *
-     * @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener)
+     * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
      */
     public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
             Map<String, String> layoutParamsMap, final IAnimationListener listener) {
@@ -892,7 +962,7 @@
      * @throws IllegalStateException if the current context is different than the one owned by
      *      the scene, or if {@link #acquire(long)} was not called.
      *
-     * @see LayoutScene#removeChild(Object, IAnimationListener)
+     * @see RenderSession#removeChild(Object, IAnimationListener)
      */
     public Result removeChild(final View childView, IAnimationListener listener) {
         checkLock();
@@ -989,40 +1059,12 @@
         return mParams.getConfigScreenSize() == ScreenSize.XLARGE;
     }
 
-    private boolean isHCApp() {
-        RenderResources resources = mContext.getRenderResources();
-
-        // the app must say it targets 11+ and the theme name must extend Theme.Holo or
-        // Theme.Holo.Light (which does not extend Theme.Holo, but Theme.Light)
-        if (mParams.getTargetSdkVersion() < 11) {
-            return false;
-        }
-
-        StyleResourceValue currentTheme = resources.getCurrentTheme();
-        StyleResourceValue holoTheme = resources.getTheme("Theme.Holo", true /*frameworkTheme*/);
-
-        if (currentTheme == holoTheme ||
-                resources.themeIsParentOf(holoTheme, currentTheme)) {
-            return true;
-        }
-
-        StyleResourceValue holoLightTheme = resources.getTheme("Theme.Holo.Light",
-                true /*frameworkTheme*/);
-
-        if (currentTheme == holoLightTheme ||
-                resources.themeIsParentOf(holoLightTheme, currentTheme)) {
-            return true;
-        }
-
-        return false;
-    }
-
     private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
         if (isTabletUi() == false) {
             boolean windowFullscreen = getBooleanThemeValue(resources,
                     "windowFullscreen", false /*defaultValue*/);
 
-            if (windowFullscreen == false) {
+            if (windowFullscreen == false && mWindowIsFloating == false) {
                 // default value
                 mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
 
@@ -1041,20 +1083,11 @@
         }
     }
 
-    private void findTopBar(RenderResources resources, DisplayMetrics metrics) {
-        boolean windowIsFloating = getBooleanThemeValue(resources,
-                "windowIsFloating", true /*defaultValue*/);
-
-        if (windowIsFloating == false) {
-            if (isHCApp()) {
-                findActionBar(resources, metrics);
-            } else {
-                findTitleBar(resources, metrics);
-            }
-        }
-    }
-
     private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
+        if (mWindowIsFloating) {
+            return;
+        }
+
         boolean windowActionBar = getBooleanThemeValue(resources,
                 "windowActionBar", true /*defaultValue*/);
 
@@ -1062,7 +1095,7 @@
         if (windowActionBar) {
 
             // default size of the window title bar
-            mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT;
+            mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
 
             // get value from the theme.
             ResourceValue value = resources.findItemInTheme("actionBarSize");
@@ -1075,44 +1108,43 @@
                 TypedValue typedValue = ResourceHelper.getValue(value.getValue());
                 if (typedValue != null) {
                     // compute the pixel value based on the display metrics
-                    mTopBarSize = (int)typedValue.getDimension(metrics);
+                    mActionBarSize = (int)typedValue.getDimension(metrics);
                 }
             }
-        }
-    }
+        } else {
+            // action bar overrides title bar so only look for this one if action bar is hidden
+            boolean windowNoTitle = getBooleanThemeValue(resources,
+                    "windowNoTitle", false /*defaultValue*/);
 
-    private void findTitleBar(RenderResources resources, DisplayMetrics metrics) {
-        boolean windowNoTitle = getBooleanThemeValue(resources,
-                "windowNoTitle", false /*defaultValue*/);
+            if (windowNoTitle == false) {
 
-        if (windowNoTitle == false) {
+                // default size of the window title bar
+                mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
 
-            // default size of the window title bar
-            mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT;
+                // get value from the theme.
+                ResourceValue value = resources.findItemInTheme("windowTitleSize");
 
-            // get value from the theme.
-            ResourceValue value = resources.findItemInTheme("windowTitleSize");
+                // resolve it
+                value = resources.resolveResValue(value);
 
-            // resolve it
-            value = resources.resolveResValue(value);
-
-            if (value != null) {
-                // get the numerical value, if available
-                TypedValue typedValue = ResourceHelper.getValue(value.getValue());
-                if (typedValue != null) {
-                    // compute the pixel value based on the display metrics
-                    mTopBarSize = (int)typedValue.getDimension(metrics);
+                if (value != null) {
+                    // get the numerical value, if available
+                    TypedValue typedValue = ResourceHelper.getValue(value.getValue());
+                    if (typedValue != null) {
+                        // compute the pixel value based on the display metrics
+                        mTitleBarSize = (int)typedValue.getDimension(metrics);
+                    }
                 }
             }
+
         }
     }
 
     private void findSystemBar(RenderResources resources, DisplayMetrics metrics) {
-        if (isTabletUi() && getBooleanThemeValue(
-                resources, "windowIsFloating", true /*defaultValue*/) == false) {
+        if (isTabletUi() && mWindowIsFloating == false) {
 
             // default value
-            mSystemBarSize = 56; // ??
+            mSystemBarSize = 48; // ??
 
             // get the real value
             ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
@@ -1244,40 +1276,71 @@
         }
     }
 
+    private List<ViewInfo> startVisitingViews(View view, int offset) {
+        if (view == null) {
+            return null;
+        }
+
+        // adjust the offset to this view.
+        offset += view.getTop();
+
+        if (view == mContentRoot) {
+            return visitAllChildren(mContentRoot, offset);
+        }
+
+        // otherwise, look for mContentRoot in the children
+        if (view instanceof ViewGroup) {
+            ViewGroup group = ((ViewGroup) view);
+
+            for (int i = 0; i < group.getChildCount(); i++) {
+                List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset);
+                if (list != null) {
+                    return list;
+                }
+            }
+        }
+
+        return null;
+    }
 
     /**
      * Visits a View and its children and generate a {@link ViewInfo} containing the
      * bounds of all the views.
      * @param view the root View
-     * @param context the context.
+     * @param offset an offset for the view bounds.
      */
-    private ViewInfo visit(View view, BridgeContext context, int offset) {
+    private ViewInfo visit(View view, int offset) {
         if (view == null) {
             return null;
         }
 
         ViewInfo result = new ViewInfo(view.getClass().getName(),
-                context.getViewKey(view),
+                mContext.getViewKey(view),
                 view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset,
                 view, view.getLayoutParams());
 
         if (view instanceof ViewGroup) {
             ViewGroup group = ((ViewGroup) view);
-            result.setChildren(visitAllChildren(group, context, 0 /*offset*/));
+            result.setChildren(visitAllChildren(group, 0 /*offset*/));
         }
 
         return result;
     }
 
-    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, BridgeContext context,
-            int offset) {
+    /**
+     * Visits all the children of a given ViewGroup generate a list of {@link ViewInfo}
+     * containing the bounds of all the views.
+     * @param view the root View
+     * @param offset an offset for the view bounds.
+     */
+    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset) {
         if (viewGroup == null) {
             return null;
         }
 
         List<ViewInfo> children = new ArrayList<ViewInfo>();
         for (int i = 0; i < viewGroup.getChildCount(); i++) {
-            children.add(visit(viewGroup.getChildAt(i), context, offset));
+            children.add(visit(viewGroup.getChildAt(i), offset));
         }
         return children;
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 25bb81c..cea7cf3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -18,6 +18,7 @@
 
 import com.android.ide.common.rendering.api.DensityBasedResourceValue;
 import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
@@ -28,7 +29,9 @@
 
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
+import android.content.res.ColorStateList;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
 import android.graphics.NinePatch_Delegate;
@@ -108,19 +111,63 @@
         throw new NumberFormatException();
     }
 
+    public static ColorStateList getColorStateList(ResourceValue resValue, BridgeContext context) {
+        String value = resValue.getValue();
+        if (value != null) {
+            // first check if the value is a file (xml most likely)
+            File f = new File(value);
+            if (f.isFile()) {
+                try {
+                    // let the framework inflate the ColorStateList from the XML file, by
+                    // providing an XmlPullParser
+                    KXmlParser parser = new KXmlParser();
+                    parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+                    parser.setInput(new FileReader(f));
+
+                    return ColorStateList.createFromXml(context.getResources(),
+                            new BridgeXmlBlockParser(parser, context, resValue.isFramework()));
+                } catch (XmlPullParserException e) {
+                    Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                            "Failed to configure parser for " + value, e, null /*data*/);
+                    // we'll return null below.
+                } catch (Exception e) {
+                    // this is an error and not warning since the file existence is
+                    // checked before attempting to parse it.
+                    Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+                            "Failed to parse file " + value, e, null /*data*/);
+
+                    return null;
+                }
+            } else {
+                // try to load the color state list from an int
+                try {
+                    int color = ResourceHelper.getColor(value);
+                    return ColorStateList.valueOf(color);
+                } catch (NumberFormatException e) {
+                    Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
+                            "Failed to convert " + value + " into a ColorStateList", e,
+                            null /*data*/);
+                    return null;
+                }
+            }
+        }
+
+        return null;
+    }
+
     /**
      * Returns a drawable from the given value.
      * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable,
      * or an hexadecimal color
-     * @param context
-     * @param isFramework indicates whether the resource is a framework resources.
-     * Framework resources are cached, and loaded only once.
+     * @param context the current context
      */
-    public static Drawable getDrawable(ResourceValue value, BridgeContext context,
-            boolean isFramework) {
+    public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
         Drawable d = null;
 
         String stringValue = value.getValue();
+        if (RenderResources.REFERENCE_NULL.equals(stringValue)) {
+            return null;
+        }
 
         String lowerCaseValue = stringValue.toLowerCase();
 
@@ -129,9 +176,9 @@
             if (file.isFile()) {
                 // see if we still have both the chunk and the bitmap in the caches
                 NinePatchChunk chunk = Bridge.getCached9Patch(stringValue,
-                        isFramework ? null : context.getProjectKey());
+                        value.isFramework() ? null : context.getProjectKey());
                 Bitmap bitmap = Bridge.getCachedBitmap(stringValue,
-                        isFramework ? null : context.getProjectKey());
+                        value.isFramework() ? null : context.getProjectKey());
 
                 // if either chunk or bitmap is null, then we reload the 9-patch file.
                 if (chunk == null || bitmap == null) {
@@ -143,7 +190,7 @@
                                 chunk = ninePatch.getChunk();
 
                                 Bridge.setCached9Patch(stringValue, chunk,
-                                        isFramework ? null : context.getProjectKey());
+                                        value.isFramework() ? null : context.getProjectKey());
                             }
 
                             if (bitmap == null) {
@@ -158,7 +205,7 @@
                                         density);
 
                                 Bridge.setCachedBitmap(stringValue, bitmap,
-                                        isFramework ? null : context.getProjectKey());
+                                        value.isFramework() ? null : context.getProjectKey());
                             }
                         }
                     } catch (MalformedURLException e) {
@@ -192,7 +239,7 @@
                     parser.setInput(new FileReader(f));
 
                     d = Drawable.createFromXml(context.getResources(),
-                            new BridgeXmlBlockParser(parser, context, isFramework));
+                            new BridgeXmlBlockParser(parser, context, value.isFramework()));
                     return d;
                 } catch (Exception e) {
                     // this is an error and not warning since the file existence is checked before
@@ -212,7 +259,7 @@
             if (bmpFile.isFile()) {
                 try {
                     Bitmap bitmap = Bridge.getCachedBitmap(stringValue,
-                            isFramework ? null : context.getProjectKey());
+                            value.isFramework() ? null : context.getProjectKey());
 
                     if (bitmap == null) {
                         Density density = Density.MEDIUM;
@@ -223,7 +270,7 @@
                         bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/,
                                 density);
                         Bridge.setCachedBitmap(stringValue, bitmap,
-                                isFramework ? null : context.getProjectKey());
+                                value.isFramework() ? null : context.getProjectKey());
                     }
 
                     return new BitmapDrawable(context.getResources(), bitmap);