am cd5f3bab: Merge "Use the right layout for inflating Action Bar." into lmp-dev automerge: 84a89ed

* commit 'cd5f3bab37ef1dc041489f53f565416d295916d9':
  Use the right layout for inflating Action Bar.
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index d4d186c..f90d64a 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -1752,6 +1752,17 @@
     }
 
     /**
+     * Accessor to enable LayoutLib to get ActionMenuPresenter directly.
+     */
+    ActionMenuPresenter getOuterActionMenuPresenter() {
+        return mOuterActionMenuPresenter;
+    }
+
+    Context getPopupContext() {
+        return mPopupContext;
+    }
+
+    /**
      * Interface responsible for receiving menu item click events if the items themselves
      * do not have individual item click listeners.
      */
diff --git a/tools/layoutlib/bridge/src/android/view/WindowCallback.java b/tools/layoutlib/bridge/src/android/view/WindowCallback.java
new file mode 100644
index 0000000..78242a8
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/WindowCallback.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2014 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 android.view;
+
+import android.view.ActionMode.Callback;
+import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * An empty implementation of {@link Window.Callback} that always returns null/false.
+ */
+public class WindowCallback implements Window.Callback {
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean dispatchTrackballEvent(MotionEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean dispatchGenericMotionEvent(MotionEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        return false;
+    }
+
+    @Override
+    public View onCreatePanelView(int featureId) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreatePanelMenu(int featureId, Menu menu) {
+        return false;
+    }
+
+    @Override
+    public boolean onPreparePanel(int featureId, View view, Menu menu) {
+        return false;
+    }
+
+    @Override
+    public boolean onMenuOpened(int featureId, Menu menu) {
+        return false;
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        return false;
+    }
+
+    @Override
+    public void onWindowAttributesChanged(LayoutParams attrs) {
+
+    }
+
+    @Override
+    public void onContentChanged() {
+
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+
+    }
+
+    @Override
+    public void onPanelClosed(int featureId, Menu menu) {
+
+    }
+
+    @Override
+    public boolean onSearchRequested() {
+        return false;
+    }
+
+    @Override
+    public ActionMode onWindowStartingActionMode(Callback callback) {
+        return null;
+    }
+
+    @Override
+    public void onActionModeStarted(ActionMode mode) {
+
+    }
+
+    @Override
+    public void onActionModeFinished(ActionMode mode) {
+
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java b/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java
new file mode 100644
index 0000000..fdd1779
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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 android.widget;
+
+import android.content.Context;
+
+/**
+ * To access non public members of classes in {@link Toolbar}
+ */
+public class Toolbar_Accessor {
+    public static ActionMenuPresenter getActionMenuPresenter(Toolbar toolbar) {
+        return toolbar.getOuterActionMenuPresenter();
+    }
+
+    public static Context getPopupContext(Toolbar toolbar) {
+        return toolbar.getPopupContext();
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
index d95c815..57fd68e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
@@ -18,36 +18,24 @@
 
 import com.android.annotations.NonNull;
 import com.android.annotations.Nullable;
-import com.android.ide.common.rendering.api.ActionBarCallback;
-import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
-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.internal.R;
-import com.android.internal.app.WindowDecorActionBar;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuItemImpl;
-import com.android.internal.widget.ActionBarAccessor;
-import com.android.internal.widget.ActionBarContainer;
-import com.android.internal.widget.ActionBarView;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.impl.ResourceHelper;
-import com.android.resources.ResourceType;
 
-import android.app.ActionBar;
-import android.app.ActionBar.Tab;
-import android.app.ActionBar.TabListener;
-import android.app.FragmentTransaction;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
-import android.view.Gravity;
 import android.view.LayoutInflater;
-import android.view.MenuInflater;
 import android.view.View;
+import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.ActionMenuPresenter;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.ListAdapter;
@@ -56,172 +44,72 @@
 
 import java.util.ArrayList;
 
-/**
- * A layout representing the action bar.
- */
-public class ActionBarLayout extends LinearLayout {
+public class ActionBarLayout {
+
+    private static final String LAYOUT_ATTR_NAME = "windowActionBarFullscreenDecorLayout";
+
+    // The Action Bar
+    @NonNull private CustomActionBarWrapper mActionBar;
 
     // Store another reference to the context so that we don't have to cast it repeatedly.
     @NonNull private final BridgeContext mBridgeContext;
-    @NonNull private final Context mThemedContext;
 
-    @NonNull private final ActionBar mActionBar;
-
-    // Data for Action Bar.
-    @Nullable private final String mIcon;
-    @Nullable private final String mTitle;
-    @Nullable private final String mSubTitle;
-    private final boolean mSplit;
-    private final boolean mShowHomeAsUp;
-    private final int mNavMode;
-
-    // Helper fields.
-    @NonNull private final MenuBuilder mMenuBuilder;
-    private final int mPopupMaxWidth;
-    @NonNull private final RenderResources res;
-    @Nullable private final ActionBarView mActionBarView;
-    @Nullable private FrameLayout mContentRoot;
-    @NonNull private final ActionBarCallback mCallback;
+    @NonNull private FrameLayout mContentRoot;
 
     // A fake parent for measuring views.
     @Nullable private ViewGroup mMeasureParent;
 
-    public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params) {
+    /**
+     * Inflate the action bar and attach it to {@code parentView}
+     */
+    public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params,
+            @NonNull ViewGroup parentView) {
 
-        super(context);
-        setOrientation(LinearLayout.HORIZONTAL);
-        setGravity(Gravity.CENTER_VERTICAL);
-
-        // Inflate action bar layout.
-        LayoutInflater.from(context).inflate(R.layout.screen_action_bar, this,
-                true /*attachToRoot*/);
-        mActionBar = new WindowDecorActionBar(this);
-
-        // Set contexts.
         mBridgeContext = context;
-        mThemedContext = mActionBar.getThemedContext();
 
-        // Set data for action bar.
-        mCallback = params.getProjectCallback().getActionBarCallback();
-        mIcon = params.getAppIcon();
-        mTitle = params.getAppLabel();
-        // Split Action Bar when the screen size is narrow and the application requests split action
-        // bar when narrow.
-        mSplit = context.getResources().getBoolean(R.bool.split_action_bar_is_narrow) &&
-                mCallback.getSplitActionBarWhenNarrow();
-        mNavMode = mCallback.getNavigationMode();
-        // TODO: Support Navigation Drawer Indicator.
-        mShowHomeAsUp = mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP;
-        mSubTitle = mCallback.getSubTitle();
-
-
-        // Set helper fields.
-        mMenuBuilder = new MenuBuilder(mThemedContext);
-        res = mBridgeContext.getRenderResources();
-        mPopupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
-                mThemedContext.getResources().getDimensionPixelSize(
-                        R.dimen.config_prefDialogWidth));
-        mActionBarView = (ActionBarView) findViewById(R.id.action_bar);
-        mContentRoot = (FrameLayout) findViewById(android.R.id.content);
-
-        setupActionBar();
-    }
-
-    /**
-     * Sets up the action bar by filling the appropriate data.
-     */
-    private void setupActionBar() {
-        // Add title and sub title.
-        ResourceValue titleValue = res.findResValue(mTitle, false /*isFramework*/);
-        if (titleValue != null && titleValue.getValue() != null) {
-            mActionBar.setTitle(titleValue.getValue());
+        ResourceValue layoutName = context.getRenderResources()
+                .findItemInTheme(LAYOUT_ATTR_NAME, true);
+        if (layoutName != null) {
+            // We may need to resolve the reference obtained.
+            layoutName = context.getRenderResources().findResValue(layoutName.getValue(),
+                    layoutName.isFramework());
+        }
+        int layoutId = 0;
+        String error = null;
+        if (layoutName == null) {
+            error = "Unable to find action bar layout (" + LAYOUT_ATTR_NAME
+                    + ") in the current theme.";
         } else {
-            mActionBar.setTitle(mTitle);
-        }
-        if (mSubTitle != null) {
-            mActionBar.setSubtitle(mSubTitle);
-        }
-
-        // Add show home as up icon.
-        if (mShowHomeAsUp) {
-            mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
-        }
-
-        // Set the navigation mode.
-        mActionBar.setNavigationMode(mNavMode);
-        if (mNavMode == ActionBar.NAVIGATION_MODE_TABS) {
-            setupTabs(3);
-        }
-
-        if (mActionBarView != null) {
-            // If the action bar style doesn't specify an icon, set the icon obtained from the session
-            // params.
-            if (!mActionBarView.hasIcon() && mIcon != null) {
-                Drawable iconDrawable = getDrawable(mIcon, false /*isFramework*/);
-                if (iconDrawable != null) {
-                    mActionBar.setIcon(iconDrawable);
-                }
-            }
-
-            // Set action bar to be split, if needed.
-            ActionBarContainer splitView = (ActionBarContainer) findViewById(R.id.split_action_bar);
-            mActionBarView.setSplitView(splitView);
-            mActionBarView.setSplitToolbar(mSplit);
-
-            inflateMenus();
-        }
-    }
-
-    /**
-     * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
-     * adds them to the action bar.
-     */
-    private void inflateMenus() {
-        if (mActionBarView == null) {
-            return;
-        }
-        final MenuInflater inflater = new MenuInflater(mThemedContext);
-        for (String name : mCallback.getMenuIdNames()) {
-            if (mBridgeContext.getRenderResources().getProjectResource(ResourceType.MENU, name)
-                    != null) {
-                int id = mBridgeContext.getProjectResourceValue(ResourceType.MENU, name, -1);
-                if (id > -1) {
-                    inflater.inflate(id, mMenuBuilder);
-                }
+            layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(),
+                    layoutName.getName(), 0);
+            if (layoutId == 0) {
+                error = String.format("Unable to resolve attribute \"%s\" of type \"%s\"",
+                        layoutName.getName(), layoutName.getResourceType());
             }
         }
-        mActionBarView.setMenu(mMenuBuilder, null /*callback*/);
-    }
-
-    // TODO: Use an adapter, like List View to set up tabs.
-    private void setupTabs(int num) {
-        for (int i = 1; i <= num; i++) {
-            Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
-                @Override
-                public void onTabUnselected(Tab t, FragmentTransaction ft) {
-                    // pass
-                }
-                @Override
-                public void onTabSelected(Tab t, FragmentTransaction ft) {
-                    // pass
-                }
-                @Override
-                public void onTabReselected(Tab t, FragmentTransaction ft) {
-                    // pass
-                }
-            });
-            mActionBar.addTab(tab);
+        if (layoutId == 0) {
+            throw new RuntimeException(error);
         }
-    }
+        // Inflate action bar layout.
+        View decorContent = LayoutInflater.from(context).inflate(layoutId, parentView, true);
 
-    @Nullable
-    private Drawable getDrawable(@NonNull String name, boolean isFramework) {
-        ResourceValue value = res.findResValue(name, isFramework);
-        value = res.resolveResValue(value);
-        if (value != null) {
-            return ResourceHelper.getDrawable(value, mBridgeContext);
+        mActionBar = CustomActionBarWrapper.getActionBarWrapper(context, params, decorContent);
+
+        FrameLayout contentRoot = (FrameLayout) parentView.findViewById(android.R.id.content);
+
+        // If something went wrong and we were not able to initialize the content root,
+        // just add a frame layout inside this and return.
+        if (contentRoot == null) {
+            contentRoot = new FrameLayout(context);
+            contentRoot.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+                    LayoutParams.MATCH_PARENT));
+            parentView.addView(contentRoot);
+            mContentRoot = contentRoot;
+        } else {
+            mContentRoot = contentRoot;
+            mActionBar.setupActionBar();
+            mActionBar.inflateMenus();
         }
-        return null;
     }
 
     /**
@@ -229,7 +117,7 @@
      * the content frame which shall serve as the new content root.
      */
     public void createMenuPopup() {
-        assert mContentRoot != null && findViewById(android.R.id.content) == mContentRoot
+        assert mContentRoot.getId() == android.R.id.content
                 : "Action Bar Menus have already been created.";
 
         if (!isOverflowPopupNeeded()) {
@@ -237,7 +125,7 @@
         }
 
         // Create a layout to hold the menus and the user's content.
-        RelativeLayout layout = new RelativeLayout(mThemedContext);
+        RelativeLayout layout = new RelativeLayout(mActionBar.getPopupContext());
         layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                 LayoutParams.MATCH_PARENT));
         mContentRoot.addView(layout);
@@ -259,13 +147,14 @@
     @NonNull
     private View createMenuView() {
         DisplayMetrics metrics = mBridgeContext.getMetrics();
-        OverflowMenuAdapter adapter = new OverflowMenuAdapter(mMenuBuilder, mThemedContext);
+        MenuBuilder menu = mActionBar.getMenuBuilder();
+        OverflowMenuAdapter adapter = new OverflowMenuAdapter(menu, mActionBar.getPopupContext());
 
-        LinearLayout layout = new LinearLayout(mThemedContext);
+        LinearLayout layout = new LinearLayout(mActionBar.getPopupContext());
         RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                 measureContentWidth(adapter), LayoutParams.WRAP_CONTENT);
         layoutParams.addRule(RelativeLayout.ALIGN_PARENT_END);
-        if (mSplit) {
+        if (mActionBar.isSplit()) {
             layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
             // TODO: Find correct value instead of hardcoded 10dp.
             layoutParams.bottomMargin = getPixelValue("-10dp", metrics);
@@ -273,7 +162,7 @@
             layoutParams.topMargin = getPixelValue("-10dp", metrics);
         }
         layout.setLayoutParams(layoutParams);
-        final TypedArray a = mThemedContext.obtainStyledAttributes(null,
+        final TypedArray a = mActionBar.getPopupContext().obtainStyledAttributes(null,
                 R.styleable.PopupWindow, R.attr.popupMenuStyle, 0);
         layout.setBackground(a.getDrawable(R.styleable.PopupWindow_popupBackground));
         layout.setDividerDrawable(a.getDrawable(R.attr.actionBarDivider));
@@ -282,20 +171,25 @@
         layout.setDividerPadding(getPixelValue("12dp", metrics));
         layout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
 
-        ListView listView = new ListView(mThemedContext, null, R.attr.dropDownListViewStyle);
+        ListView listView = new ListView(mActionBar.getPopupContext(), null,
+                R.attr.dropDownListViewStyle);
         listView.setAdapter(adapter);
         layout.addView(listView);
         return layout;
     }
 
     private boolean isOverflowPopupNeeded() {
-        boolean needed = mCallback.isOverflowPopupNeeded();
+        boolean needed = mActionBar.isOverflowPopupNeeded();
         if (!needed) {
             return false;
         }
         // Copied from android.widget.ActionMenuPresenter.updateMenuView()
-        ArrayList<MenuItemImpl> menus = mMenuBuilder.getNonActionItems();
-        if (ActionBarAccessor.getActionMenuPresenter(mActionBarView).isOverflowReserved() &&
+        ArrayList<MenuItemImpl> menus = mActionBar.getMenuBuilder().getNonActionItems();
+        ActionMenuPresenter presenter = mActionBar.getActionMenuPresenter();
+        if (presenter == null) {
+            throw new RuntimeException("Failed to create a Presenter for Action Bar Menus.");
+        }
+        if (presenter.isOverflowReserved() &&
                 menus != null) {
             final int count = menus.size();
             if (count == 1) {
@@ -307,7 +201,7 @@
         return needed;
     }
 
-    @Nullable
+    @NonNull
     public FrameLayout getContentRoot() {
         return mContentRoot;
     }
@@ -319,6 +213,7 @@
         View itemView = null;
         int itemType = 0;
 
+        Context context = mActionBar.getPopupContext();
         final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         final int count = adapter.getCount();
@@ -330,15 +225,17 @@
             }
 
             if (mMeasureParent == null) {
-                mMeasureParent = new FrameLayout(mThemedContext);
+                mMeasureParent = new FrameLayout(context);
             }
 
             itemView = adapter.getView(i, itemView, mMeasureParent);
             itemView.measure(widthMeasureSpec, heightMeasureSpec);
 
             final int itemWidth = itemView.getMeasuredWidth();
-            if (itemWidth >= mPopupMaxWidth) {
-                return mPopupMaxWidth;
+            int popupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
+                    context.getResources().getDimensionPixelSize(R.dimen.config_prefDialogWidth));
+            if (itemWidth >= popupMaxWidth) {
+                return popupMaxWidth;
             } else if (itemWidth > maxWidth) {
                 maxWidth = itemWidth;
             }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java
new file mode 100644
index 0000000..f3fc397
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2014 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.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.ActionBarCallback;
+import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
+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.internal.R;
+import com.android.internal.app.ToolbarActionBar;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.widget.ActionBarAccessor;
+import com.android.internal.widget.ActionBarView;
+import com.android.internal.widget.DecorToolbar;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.resources.ResourceType;
+
+import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowCallback;
+import android.widget.ActionMenuPresenter;
+import android.widget.Toolbar;
+import android.widget.Toolbar_Accessor;
+
+/**
+ * A common API to access {@link ToolbarActionBar} and {@link WindowDecorActionBar}.
+ */
+public abstract class CustomActionBarWrapper {
+
+    @NonNull protected ActionBar mActionBar;
+    @NonNull protected SessionParams mParams;
+    @NonNull protected ActionBarCallback mCallback;
+    @NonNull protected BridgeContext mContext;
+
+    /**
+     * Returns a wrapper around different implementations of the Action Bar to provide a common API.
+     *
+     * @param decorContent the top level view returned by inflating
+                     * ?attr/windowActionBarFullscreenDecorLayout
+     */
+    @NonNull
+    public static CustomActionBarWrapper getActionBarWrapper(@NonNull BridgeContext context,
+            @NonNull SessionParams params, @NonNull View decorContent) {
+        View view = decorContent.findViewById(R.id.action_bar);
+        if (view instanceof Toolbar) {
+            return new ToolbarWrapper(context, params, ((Toolbar) view)
+            );
+        } else if (view instanceof ActionBarView) {
+            return new WindowActionBarWrapper(context, params, decorContent, ((ActionBarView) view)
+            );
+        } else {
+            throw new IllegalStateException("Can't make an action bar out of " +
+                    view.getClass().getSimpleName());
+        }
+    }
+
+    CustomActionBarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+            @NonNull ActionBar actionBar) {
+        mActionBar = actionBar;
+        mParams = params;
+        mCallback = params.getProjectCallback().getActionBarCallback();
+        mContext = context;
+    }
+
+    protected void setupActionBar() {
+        // Do the things that are common to all implementations.
+        RenderResources res = mContext.getRenderResources();
+
+        String title = mParams.getAppLabel();
+        ResourceValue titleValue = res.findResValue(title, false);
+        if (titleValue != null && titleValue.getValue() != null) {
+            mActionBar.setTitle(titleValue.getValue());
+        } else {
+            mActionBar.setTitle(title);
+        }
+
+        String subTitle = mCallback.getSubTitle();
+        if (subTitle != null) {
+            mActionBar.setSubtitle(subTitle);
+        }
+
+        // Add show home as up icon.
+        if (mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP) {
+            mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
+        }
+    }
+
+    protected boolean isSplit() {
+        return getDecorToolbar().isSplit();
+    }
+
+    protected boolean isOverflowPopupNeeded() {
+        return mCallback.isOverflowPopupNeeded();
+    }
+
+    /**
+     * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
+     * adds them to the action bar.
+     */
+    protected void inflateMenus() {
+        MenuInflater inflater = new MenuInflater(getActionMenuContext());
+        MenuBuilder menuBuilder = getMenuBuilder();
+        for (String name : mCallback.getMenuIdNames()) {
+            if (mContext.getRenderResources().getProjectResource(ResourceType.MENU, name)
+                    != null) {
+                int id = mContext.getProjectResourceValue(ResourceType.MENU, name, -1);
+                if (id > -1) {
+                    inflater.inflate(id, menuBuilder);
+                }
+            }
+        }
+    }
+
+    /**
+     * The context used for the ActionBar and the menus in the ActionBarView.
+     */
+    @NonNull
+    protected Context getActionMenuContext() {
+        return mActionBar.getThemedContext();
+    }
+
+    /**
+     * The context used to inflate the popup menu.
+     */
+    @NonNull
+    abstract Context getPopupContext();
+
+    /**
+     * The Menu in which to inflate the user's menus.
+     */
+    @NonNull
+    abstract MenuBuilder getMenuBuilder();
+
+    @Nullable
+    abstract ActionMenuPresenter getActionMenuPresenter();
+
+    /**
+     * Framework's wrapper over two ActionBar implementations.
+     */
+    @NonNull
+    abstract DecorToolbar getDecorToolbar();
+
+    // ---- The implementations ----
+
+    /**
+     * Material theme uses {@link Toolbar} as the action bar. This wrapper provides access to
+     * Toolbar using a common API.
+     */
+    private static class ToolbarWrapper extends CustomActionBarWrapper {
+
+        @NonNull
+        private final Toolbar mToolbar;  // This is the view.
+
+        ToolbarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+                @NonNull Toolbar toolbar) {
+            super(context, params, new ToolbarActionBar(toolbar, "", new WindowCallback())
+            );
+            mToolbar = toolbar;
+        }
+
+        @Override
+        protected void inflateMenus() {
+            super.inflateMenus();
+            // Inflating the menus doesn't initialize the ActionMenuPresenter. Setting a fake menu
+            // and then setting it back does the trick.
+            MenuBuilder menu = getMenuBuilder();
+            DecorToolbar decorToolbar = getDecorToolbar();
+            decorToolbar.setMenu(new MenuBuilder(getActionMenuContext()), null);
+            decorToolbar.setMenu(menu, null);
+        }
+
+        @NonNull
+        @Override
+        Context getPopupContext() {
+            return Toolbar_Accessor.getPopupContext(mToolbar);
+        }
+
+        @NonNull
+        @Override
+        MenuBuilder getMenuBuilder() {
+            return (MenuBuilder) mToolbar.getMenu();
+        }
+
+        @Nullable
+        @Override
+        ActionMenuPresenter getActionMenuPresenter() {
+            return Toolbar_Accessor.getActionMenuPresenter(mToolbar);
+        }
+
+        @NonNull
+        @Override
+        DecorToolbar getDecorToolbar() {
+            return mToolbar.getWrapper();
+        }
+    }
+
+    /**
+     * Holo theme uses {@link WindowDecorActionBar} as the action bar. This wrapper provides
+     * access to it using a common API.
+     */
+    private static class WindowActionBarWrapper extends CustomActionBarWrapper{
+
+        @NonNull
+        private final WindowDecorActionBar mActionBar;
+        private final ActionBarView mActionBarView;
+        private MenuBuilder mMenuBuilder;
+
+        public WindowActionBarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+                @NonNull View decorContentRoot, @NonNull ActionBarView actionBarView) {
+            super(context, params, new WindowDecorActionBar(decorContentRoot)
+            );
+            mActionBarView = actionBarView;
+            mActionBar = ((WindowDecorActionBar) super.mActionBar);
+        }
+
+        @Override
+        protected void setupActionBar() {
+            super.setupActionBar();
+
+            // Set the navigation mode.
+            int navMode = mCallback.getNavigationMode();
+            mActionBar.setNavigationMode(navMode);
+            //noinspection deprecation
+            if (navMode == ActionBar.NAVIGATION_MODE_TABS) {
+                setupTabs(3);
+            }
+
+            String icon = mParams.getAppIcon();
+            // If the action bar style doesn't specify an icon, set the icon obtained from the
+            // session params.
+            if (!mActionBar.hasIcon() && icon != null) {
+                Drawable iconDrawable = getDrawable(icon, false);
+                if (iconDrawable != null) {
+                    mActionBar.setIcon(iconDrawable);
+                }
+            }
+
+            // Set action bar to be split, if needed.
+            ViewGroup splitView = (ViewGroup) mActionBarView.findViewById(R.id.split_action_bar);
+            if (splitView != null) {
+                mActionBarView.setSplitView(splitView);
+                Resources res = mContext.getResources();
+                boolean split = res.getBoolean(R.bool.split_action_bar_is_narrow)
+                        && mCallback.getSplitActionBarWhenNarrow();
+                mActionBarView.setSplitToolbar(split);
+            }
+        }
+
+        @Override
+        protected void inflateMenus() {
+            super.inflateMenus();
+            // The super implementation doesn't set the menu on the view. Set it here.
+            mActionBarView.setMenu(getMenuBuilder(), null);
+        }
+
+        @NonNull
+        @Override
+        Context getPopupContext() {
+            return getActionMenuContext();
+        }
+
+        @NonNull
+        @Override
+        MenuBuilder getMenuBuilder() {
+            if (mMenuBuilder == null) {
+                mMenuBuilder = new MenuBuilder(getActionMenuContext());
+            }
+            return mMenuBuilder;
+        }
+
+        @Nullable
+        @Override
+        ActionMenuPresenter getActionMenuPresenter() {
+            return ActionBarAccessor.getActionMenuPresenter(mActionBarView);
+        }
+
+        @NonNull
+        @Override
+        ActionBarView getDecorToolbar() {
+            return mActionBarView;
+        }
+
+        // TODO: Use an adapter, like List View to set up tabs.
+        @SuppressWarnings("deprecation")  // For Tab
+        private void setupTabs(int num) {
+            for (int i = 1; i <= num; i++) {
+                Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
+                    @Override
+                    public void onTabUnselected(Tab t, FragmentTransaction ft) {
+                        // pass
+                    }
+                    @Override
+                    public void onTabSelected(Tab t, FragmentTransaction ft) {
+                        // pass
+                    }
+                    @Override
+                    public void onTabReselected(Tab t, FragmentTransaction ft) {
+                        // pass
+                    }
+                });
+                mActionBar.addTab(tab);
+            }
+        }
+
+        @Nullable
+        private Drawable getDrawable(@NonNull String name, boolean isFramework) {
+            RenderResources res = mContext.getRenderResources();
+            ResourceValue value = res.findResValue(name, isFramework);
+            value = res.resolveResValue(value);
+            if (value != null) {
+                return ResourceHelper.getDrawable(value, mContext);
+            }
+            return null;
+        }
+
+    }
+}
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 b8dce70..a2eed9a 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
@@ -353,8 +353,7 @@
 
                 // if the theme says no title/action bar, then the size will be 0
                 if (mActionBarSize > 0) {
-                    ActionBarLayout actionBar = createActionBar(context, params);
-                    backgroundLayout.addView(actionBar);
+                    ActionBarLayout actionBar = createActionBar(context, params, backgroundLayout);
                     actionBar.createMenuPopup();
                     mContentRoot = actionBar.getContentRoot();
                 } else if (mTitleBarSize > 0) {
@@ -1624,11 +1623,9 @@
     /**
      * Creates the action bar. Also queries the project callback for missing information.
      */
-    private ActionBarLayout createActionBar(BridgeContext context, SessionParams params) {
-        ActionBarLayout actionBar = new ActionBarLayout(context, params);
-        actionBar.setLayoutParams(new LinearLayout.LayoutParams(
-                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
-        return actionBar;
+    private ActionBarLayout createActionBar(BridgeContext context, SessionParams params,
+            ViewGroup parentView) {
+        return new ActionBarLayout(context, params, parentView);
     }
 
     public BufferedImage getImage() {