Merge "Change theme application order" into oc-mr1-jetpack-dev
diff --git a/v7/mediarouter/res/values/themes.xml b/v7/mediarouter/res/values/themes.xml
index 586db92..8c6e97a 100644
--- a/v7/mediarouter/res/values/themes.xml
+++ b/v7/mediarouter/res/values/themes.xml
@@ -17,7 +17,6 @@
 <resources>
 
     <style name="Theme.MediaRouter" parent="ThemeOverlay.AppCompat.Dark">
-        <item name="android:backgroundDimEnabled">true</item>
         <item name="windowNoTitle">true</item>
         <item name="mediaRouteButtonStyle">@style/Widget.MediaRouter.MediaRouteButton</item>
 
@@ -39,7 +38,6 @@
     </style>
 
     <style name="Theme.MediaRouter.Light" parent="ThemeOverlay.AppCompat.Light">
-        <item name="android:backgroundDimEnabled">true</item>
         <item name="windowNoTitle">true</item>
         <item name="mediaRouteButtonStyle">@style/Widget.MediaRouter.Light.MediaRouteButton</item>
 
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
index d3f7020..fdbcf9a 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
@@ -121,8 +121,7 @@
     }
 
     public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(MediaRouterThemeHelper.createThemedContext(context, defStyleAttr), attrs,
-                defStyleAttr);
+        super(MediaRouterThemeHelper.createThemedButtonContext(context), attrs, defStyleAttr);
         context = getContext();
 
         mRouter = MediaRouter.getInstance(context);
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java
index 0ab2eb1..17364ef 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java
@@ -92,10 +92,8 @@
     }
 
     public MediaRouteChooserDialog(Context context, int theme) {
-        // If we pass theme ID of 0 to AppCompatDialog, it will apply dialogTheme on the context,
-        // which may override our style settings. Passes our uppermost theme ID to prevent this.
-        super(MediaRouterThemeHelper.createThemedContext(context, theme),
-                theme == 0 ? MediaRouterThemeHelper.createThemeForDialog(context, theme) : theme);
+        super(context = MediaRouterThemeHelper.createThemedDialogContext(context, theme, false),
+                MediaRouterThemeHelper.createThemedDialogStyle(context));
         context = getContext();
 
         mRouter = MediaRouter.getInstance(context);
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
index 4b9a17a..d89bf21 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
@@ -201,12 +201,8 @@
     }
 
     public MediaRouteControllerDialog(Context context, int theme) {
-        // If we pass theme ID of 0 to AppCompatDialog, it will apply dialogTheme on the context,
-        // which may override our style settings. Passes our uppermost theme ID to prevent this.
-        super(MediaRouterThemeHelper.createThemedContext(context,
-                MediaRouterThemeHelper.getAlertDialogResolvedTheme(context, theme)), theme == 0
-                ? MediaRouterThemeHelper.createThemeForDialog(context, MediaRouterThemeHelper
-                        .getAlertDialogResolvedTheme(context, theme)) : theme);
+        super(context = MediaRouterThemeHelper.createThemedDialogContext(context, theme, true),
+                MediaRouterThemeHelper.createThemedDialogStyle(context));
         mContext = getContext();
 
         mControllerCallback = new MediaControllerCallback();
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouterThemeHelper.java b/v7/mediarouter/src/android/support/v7/app/MediaRouterThemeHelper.java
index 9ef218e..69e40ac 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouterThemeHelper.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouterThemeHelper.java
@@ -42,47 +42,76 @@
     private MediaRouterThemeHelper() {
     }
 
-    /**
-     * Creates a themed context based on the explicit style resource or the parent context's default
-     * theme.
-     * <p>
-     * The theme which will be applied on top of the parent {@code context}'s theme is determined
-     * by the primary color defined in the given {@code style}, or in the parent {@code context}.
+    static Context createThemedButtonContext(Context context) {
+        // Apply base Media Router theme.
+        context = new ContextThemeWrapper(context, getRouterThemeId(context));
+
+        // Apply custom Media Router theme.
+        int style = getThemeResource(context, R.attr.mediaRouteTheme);
+        if (style != 0) {
+            context = new ContextThemeWrapper(context, style);
+        }
+
+        return context;
+    }
+
+    /*
+     * The following two methods are to be used in conjunction. They should be used to prepare
+     * the context and theme for a super class constructor (the latter method relies on the
+     * former method to properly prepare the context):
+     *   super(context = createThemedDialogContext(context, theme),
+     *           createThemedDialogStyle(context));
      *
-     * @param context the parent context
-     * @param style the resource ID of the style against which to inflate this context, or
-     *              {@code 0} to use the parent {@code context}'s default theme.
-     * @return The themed context.
+     * It will apply theme in the following order (style lookups will be done in reverse):
+     *   1) Current theme
+     *   2) Supplied theme
+     *   3) Base Media Router theme
+     *   4) Custom Media Router theme, if provided
      */
-    static Context createThemedContext(Context context, int style) {
-        // First, apply dialog property overlay.
-        Context themedContext =
-                new ContextThemeWrapper(context, getStyledRouterThemeId(context, style));
-        int customizedThemeId = getThemeResource(context, R.attr.mediaRouteTheme);
-        return customizedThemeId == 0 ? themedContext
-                : new ContextThemeWrapper(themedContext, customizedThemeId);
-    }
+    static Context createThemedDialogContext(Context context, int theme, boolean alertDialog) {
+        // 1) Current theme is already applied to the context
 
-    /**
-     * Creates the theme resource ID intended to be used by dialogs.
-     */
-    static int createThemeForDialog(Context context, int style) {
-        int customizedThemeId = getThemeResource(context, R.attr.mediaRouteTheme);
-        return customizedThemeId != 0 ? customizedThemeId : getStyledRouterThemeId(context, style);
-    }
+        // 2) If no theme is supplied, look it up from the context (dialogTheme/alertDialogTheme)
+        if (theme == 0) {
+            theme = getThemeResource(context, !alertDialog
+                    ? android.support.v7.appcompat.R.attr.dialogTheme
+                    : android.support.v7.appcompat.R.attr.alertDialogTheme);
+        }
+        //    Apply it
+        context = new ContextThemeWrapper(context, theme);
 
-    public static int getThemeResource(Context context, int attr) {
+        // 3) If a custom Media Router theme is provided then apply the base theme
+        if (getThemeResource(context, R.attr.mediaRouteTheme) != 0) {
+            context = new ContextThemeWrapper(context, getRouterThemeId(context));
+        }
+
+        return context;
+    }
+    // This method should be used in conjunction with the previous method.
+    static int createThemedDialogStyle(Context context) {
+        // 4) Apply the custom Media Router theme
+        int theme = getThemeResource(context, R.attr.mediaRouteTheme);
+        if (theme == 0) {
+            // 3) No custom MediaRouther theme was provided so apply the base theme instead
+            theme = getRouterThemeId(context);
+        }
+
+        return theme;
+    }
+    // END. Previous two methods should be used in conjunction.
+
+    static int getThemeResource(Context context, int attr) {
         TypedValue value = new TypedValue();
         return context.getTheme().resolveAttribute(attr, value, true) ? value.resourceId : 0;
     }
 
-    public static float getDisabledAlpha(Context context) {
+    static float getDisabledAlpha(Context context) {
         TypedValue value = new TypedValue();
         return context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true)
                 ? value.getFloat() : 0.5f;
     }
 
-    public static @ControllerColorType int getControllerColor(Context context, int style) {
+    static @ControllerColorType int getControllerColor(Context context, int style) {
         int primaryColor = getThemeColor(context, style,
                 android.support.v7.appcompat.R.attr.colorPrimary);
         if (ColorUtils.calculateContrast(COLOR_WHITE_ON_DARK_BACKGROUND, primaryColor)
@@ -92,7 +121,7 @@
         return COLOR_DARK_ON_LIGHT_BACKGROUND;
     }
 
-    public static int getButtonTextColor(Context context) {
+    static int getButtonTextColor(Context context) {
         int primaryColor = getThemeColor(context, 0,
                 android.support.v7.appcompat.R.attr.colorPrimary);
         int backgroundColor = getThemeColor(context, 0, android.R.attr.colorBackground);
@@ -104,7 +133,7 @@
         return primaryColor;
     }
 
-    public static void setMediaControlsBackgroundColor(
+    static void setMediaControlsBackgroundColor(
             Context context, View mainControls, View groupControls, boolean hasGroup) {
         int primaryColor = getThemeColor(context, 0,
                 android.support.v7.appcompat.R.attr.colorPrimary);
@@ -124,7 +153,7 @@
         groupControls.setTag(primaryDarkColor);
     }
 
-    public static void setVolumeSliderColor(
+    static void setVolumeSliderColor(
             Context context, MediaRouteVolumeSlider volumeSlider, View backgroundView) {
         int controllerColor = getControllerColor(context, 0);
         if (Color.alpha(controllerColor) != 0xFF) {
@@ -136,23 +165,10 @@
         volumeSlider.setColor(controllerColor);
     }
 
-    // This is copied from {@link AlertDialog#resolveDialogTheme} to pre-evaluate theme in advance.
-    public static int getAlertDialogResolvedTheme(Context context, int themeResId) {
-        if (themeResId >= 0x01000000) {   // start of real resource IDs.
-            return themeResId;
-        } else {
-            TypedValue outValue = new TypedValue();
-            context.getTheme().resolveAttribute(
-                    android.support.v7.appcompat.R.attr.alertDialogTheme, outValue, true);
-            return outValue.resourceId;
-        }
-    }
-
     private static boolean isLightTheme(Context context) {
         TypedValue value = new TypedValue();
-        return context.getTheme().resolveAttribute(
-                android.support.v7.appcompat.R.attr.isLightTheme, value, true)
-                && value.data != 0;
+        return context.getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.isLightTheme,
+                value, true) && value.data != 0;
     }
 
     private static int getThemeColor(Context context, int style, int attr) {
@@ -173,16 +189,16 @@
         return value.data;
     }
 
-    private static int getStyledRouterThemeId(Context context, int style) {
+    private static int getRouterThemeId(Context context) {
         int themeId;
         if (isLightTheme(context)) {
-            if (getControllerColor(context, style) == COLOR_DARK_ON_LIGHT_BACKGROUND) {
+            if (getControllerColor(context, 0) == COLOR_DARK_ON_LIGHT_BACKGROUND) {
                 themeId = R.style.Theme_MediaRouter_Light;
             } else {
                 themeId = R.style.Theme_MediaRouter_Light_DarkControlPanel;
             }
         } else {
-            if (getControllerColor(context, style) == COLOR_DARK_ON_LIGHT_BACKGROUND) {
+            if (getControllerColor(context, 0) == COLOR_DARK_ON_LIGHT_BACKGROUND) {
                 themeId = R.style.Theme_MediaRouter_LightControlPanel;
             } else {
                 themeId = R.style.Theme_MediaRouter;
diff --git a/v7/mediarouter/tests/src/android/support/v7/app/MediaRouteChooserDialogTest.java b/v7/mediarouter/tests/src/android/support/v7/app/MediaRouteChooserDialogTest.java
index 415ec1f..7288968 100644
--- a/v7/mediarouter/tests/src/android/support/v7/app/MediaRouteChooserDialogTest.java
+++ b/v7/mediarouter/tests/src/android/support/v7/app/MediaRouteChooserDialogTest.java
@@ -16,7 +16,6 @@
 
 package android.support.v7.app;
 
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
@@ -66,7 +65,7 @@
         // No base theme, with a customized theme (has window title)
         dialog = new MediaRouteChooserDialog(context, R.style.HasWindowTitle);
         typedArray = dialog.getContext().obtainStyledAttributes(R.styleable.AppCompatTheme);
-        assertFalse(typedArray.getBoolean(R.styleable.AppCompatTheme_windowNoTitle, false));
+        assertTrue(typedArray.getBoolean(R.styleable.AppCompatTheme_windowNoTitle, false));
         typedArray.recycle();
 
         // With base theme (has window title), no customized theme
@@ -79,7 +78,7 @@
         // With base theme and a customized theme (both has window title)
         dialog = new MediaRouteChooserDialog(context, R.style.HasWindowTitle);
         typedArray = dialog.getContext().obtainStyledAttributes(R.styleable.AppCompatTheme);
-        assertFalse(typedArray.getBoolean(R.styleable.AppCompatTheme_windowNoTitle, false));
+        assertTrue(typedArray.getBoolean(R.styleable.AppCompatTheme_windowNoTitle, false));
         typedArray.recycle();
 
         context.setTheme(0);