Fix AppCompat action bar theming.

Use themed context to inflate the action bar when AppCompat is used.
Also fix minor issues exposed as a result.

 - Set project callback when LayoutInflater is created by
   LayoutInflater.from(context).
 - Remove duplication of code to get base context from context wrapper.

Bug: http://b.android.com/159711
Change-Id: I379ba2ba71c0ef547460987c3aa5db521c7de967
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index 7e4ff69..7ca4c47 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -35,6 +35,8 @@
 
 import java.io.File;
 
+import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext;
+
 /**
  * Custom implementation of {@link LayoutInflater} to handle custom views.
  */
@@ -56,7 +58,12 @@
 
     protected BridgeInflater(LayoutInflater original, Context newContext) {
         super(original, newContext);
-        mProjectCallback = null;
+        newContext = getBaseContext(newContext);
+        if (newContext instanceof BridgeContext) {
+            mProjectCallback = ((BridgeContext) newContext).getProjectCallback();
+        } else {
+            mProjectCallback = null;
+        }
     }
 
     /**
@@ -151,9 +158,7 @@
     @Override
     public View inflate(int resource, ViewGroup root) {
         Context context = getContext();
-        while (context instanceof ContextThemeWrapper) {
-            context = ((ContextThemeWrapper) context).getBaseContext();
-        }
+        context = getBaseContext(context);
         if (context instanceof BridgeContext) {
             BridgeContext bridgeContext = (BridgeContext)context;
 
@@ -217,9 +222,7 @@
 
     private void setupViewInContext(View view, AttributeSet attrs) {
         Context context = getContext();
-        while (context instanceof ContextThemeWrapper) {
-            context = ((ContextThemeWrapper) context).getBaseContext();
-        }
+        context = getBaseContext(context);
         if (context instanceof BridgeContext) {
             BridgeContext bc = (BridgeContext) context;
             // get the view key
diff --git a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java
index dafc96b..08a97d6 100644
--- a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java
@@ -48,9 +48,7 @@
             AttributeSet attrs) {
         if (menuItem instanceof BridgeMenuItemImpl) {
             Context context = thisInflater.getContext();
-            while (context instanceof ContextThemeWrapper) {
-                context = ((ContextThemeWrapper) context).getBaseContext();
-            }
+            context = BridgeContext.getBaseContext(context);
             if (context instanceof BridgeContext) {
                 Object viewKey = BridgeInflater.getViewKeyFromParser(
                         attrs, ((BridgeContext) context), null, false);
diff --git a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
index 3915046..82ae1df 100644
--- a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
@@ -122,9 +122,7 @@
     @NonNull
     private static DisplayMetrics getMetrics(View view) {
         Context context = view.getContext();
-        while (context instanceof ContextThemeWrapper) {
-            context = ((ContextThemeWrapper) context).getBaseContext();
-        }
+        context = BridgeContext.getBaseContext(context);
         if (context instanceof BridgeContext) {
             return ((BridgeContext) context).getMetrics();
         }
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
index 8d1d0c1..bb95c4e 100644
--- a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
@@ -19,7 +19,6 @@
 import com.android.layoutlib.bridge.android.BridgeContext;
 
 import android.content.Context;
-import android.view.ContextThemeWrapper;
 import android.view.View;
 
 /**
@@ -42,9 +41,7 @@
             CharSequence title, int showAsAction) {
         super(menu, group, id, categoryOrder, ordering, title, showAsAction);
         Context context = menu.getContext();
-        while (context instanceof ContextThemeWrapper) {
-            context = ((ContextThemeWrapper) context).getBaseContext();
-        }
+        context = BridgeContext.getBaseContext(context);
         if (context instanceof BridgeContext) {
             mContext = ((BridgeContext) context);
         }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 7c86f75..ef7b85b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -40,6 +40,7 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
@@ -924,6 +925,13 @@
         return defValue;
     }
 
+    public static Context getBaseContext(Context context) {
+        while (context instanceof ContextWrapper) {
+            context = ((ContextWrapper) context).getBaseContext();
+        }
+        return context;
+    }
+
     //------------ NOT OVERRIDEN --------------------
 
     @Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
index f54815e..ee57067 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
@@ -21,11 +21,15 @@
 import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.ide.common.rendering.api.SessionParams;
+import com.android.ide.common.rendering.api.StyleResourceValue;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.impl.ResourceHelper;
 import com.android.resources.ResourceType;
 
+import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -85,6 +89,27 @@
     }
 
     @Override
+    protected LayoutInflater getInflater(BridgeContext context) {
+        // Other than the resource resolution part, the code has been taken from the support
+        // library. see code from line 269 onwards in
+        // https://android.googlesource.com/platform/frameworks/support/+/android-5.1.0_r1/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java
+        Context themedContext = context;
+        RenderResources resources = context.getRenderResources();
+        ResourceValue actionBarTheme = resources.findItemInTheme("actionBarTheme", false);
+        if (actionBarTheme != null) {
+            // resolve it, if needed.
+            actionBarTheme = resources.resolveResValue(actionBarTheme);
+        }
+        if (actionBarTheme instanceof StyleResourceValue) {
+            int styleId = context.getDynamicIdByStyle(((StyleResourceValue) actionBarTheme));
+            if (styleId != 0) {
+                themedContext = new ContextThemeWrapper(context, styleId);
+            }
+        }
+        return LayoutInflater.from(themedContext);
+    }
+
+    @Override
     protected void setTitle(CharSequence title) {
         if (title != null && mWindowDecorActionBar != null) {
             Method setTitle = getMethod(mWindowActionBarClass, "setTitle", CharSequence.class);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java
index c25db35..2a83ea1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java
@@ -81,7 +81,7 @@
         }
 
         // Inflate action bar layout.
-        mDecorContent = LayoutInflater.from(context).inflate(layoutId, mEnclosingLayout, true);
+        mDecorContent = getInflater(context).inflate(layoutId, mEnclosingLayout, true);
 
     }
 
@@ -92,6 +92,10 @@
      */
     protected abstract ResourceValue getLayoutResource(BridgeContext context);
 
+    protected LayoutInflater getInflater(BridgeContext context) {
+        return LayoutInflater.from(context);
+    }
+
     protected void setContentRoot(@NonNull FrameLayout contentRoot) {
         mContentRoot = contentRoot;
     }