Merge "Annotate more Transition APIs" into oc-support-26.0-dev
diff --git a/api/25.4.0-SNAPSHOT.ignore b/api/25.4.0.ignore
similarity index 100%
rename from api/25.4.0-SNAPSHOT.ignore
rename to api/25.4.0.ignore
diff --git a/api/25.4.0-SNAPSHOT.txt b/api/25.4.0.txt
similarity index 100%
rename from api/25.4.0-SNAPSHOT.txt
rename to api/25.4.0.txt
diff --git a/api/26.0.0-SNAPSHOT.txt b/api/26.0.0-SNAPSHOT.txt
index 0311835..a38526f 100644
--- a/api/26.0.0-SNAPSHOT.txt
+++ b/api/26.0.0-SNAPSHOT.txt
@@ -2206,6 +2206,7 @@
     ctor public TransitionManager();
     method public static void beginDelayedTransition(android.view.ViewGroup);
     method public static void beginDelayedTransition(android.view.ViewGroup, android.support.transition.Transition);
+    method public static void endTransitions(android.view.ViewGroup);
     method public static void go(android.support.transition.Scene);
     method public static void go(android.support.transition.Scene, android.support.transition.Transition);
     method public void setTransition(android.support.transition.Scene, android.support.transition.Transition);
@@ -10311,7 +10312,6 @@
   public abstract class AppCompatDelegate {
     method public abstract void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public abstract boolean applyDayNight();
-    method public abstract boolean checkActionBarFocusKey(android.view.KeyEvent);
     method public static android.support.v7.app.AppCompatDelegate create(android.app.Activity, android.support.v7.app.AppCompatCallback);
     method public static android.support.v7.app.AppCompatDelegate create(android.app.Dialog, android.support.v7.app.AppCompatCallback);
     method public abstract android.view.View createView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
diff --git a/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy b/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy
index 77a58f8..0ffd3d7 100644
--- a/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy
+++ b/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy
@@ -190,6 +190,7 @@
 
                             // Enforce the following checks.
                             '-Xep:MissingOverride:ERROR',
+                            '-Xep:ClassNewInstance:ERROR',
                     ]
                 }
             }
diff --git a/compat/res-public/values/public_attrs.xml b/compat/res-public/values/public_attrs.xml
index eb60607..e45f8c2 100644
--- a/compat/res-public/values/public_attrs.xml
+++ b/compat/res-public/values/public_attrs.xml
@@ -21,8 +21,8 @@
      <public type="attr" name="fontProviderPackage"/>
      <public type="attr" name="fontProviderQuery"/>
      <public type="attr" name="fontProviderCerts"/>
-     <public type="attr" name="fontProviderStrategy"/>
-     <public type="attr" name="fontProviderTimeout"/>
+     <public type="attr" name="fontProviderFetchStrategy"/>
+     <public type="attr" name="fontProviderFetchTimeout"/>
      <public type="attr" name="fontStyle"/>
      <public type="attr" name="font"/>
      <public type="attr" name="fontWeight"/>
diff --git a/design/src/android/support/design/widget/CoordinatorLayout.java b/design/src/android/support/design/widget/CoordinatorLayout.java
index e5c52b3..2f87edf 100644
--- a/design/src/android/support/design/widget/CoordinatorLayout.java
+++ b/design/src/android/support/design/widget/CoordinatorLayout.java
@@ -627,7 +627,8 @@
             }
             if (defaultBehavior != null) {
                 try {
-                    result.setBehavior(defaultBehavior.value().newInstance());
+                    result.setBehavior(
+                            defaultBehavior.value().getDeclaredConstructor().newInstance());
                 } catch (Exception e) {
                     Log.e(TAG, "Default behavior class " + defaultBehavior.value().getName() +
                             " could not be instantiated. Did you forget a default constructor?", e);
diff --git a/transition/src/android/support/transition/Transition.java b/transition/src/android/support/transition/Transition.java
index c6eeb9c..d5c757c 100644
--- a/transition/src/android/support/transition/Transition.java
+++ b/transition/src/android/support/transition/Transition.java
@@ -1963,6 +1963,27 @@
     }
 
     /**
+     * Force the transition to move to its end state, ending all the animators.
+     *
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    void forceToEnd(ViewGroup sceneRoot) {
+        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
+        int numOldAnims = runningAnimators.size();
+        if (sceneRoot != null) {
+            WindowIdImpl windowId = ViewUtils.getWindowId(sceneRoot);
+            for (int i = numOldAnims - 1; i >= 0; i--) {
+                AnimationInfo info = runningAnimators.valueAt(i);
+                if (info.mView != null && windowId != null && windowId.equals(info.mWindowId)) {
+                    Animator anim = runningAnimators.keyAt(i);
+                    anim.end();
+                }
+            }
+        }
+    }
+
+    /**
      * This method cancels a transition that is currently running.
      *
      * @hide
diff --git a/transition/src/android/support/transition/TransitionManager.java b/transition/src/android/support/transition/TransitionManager.java
index 105aca4..f65a464 100644
--- a/transition/src/android/support/transition/TransitionManager.java
+++ b/transition/src/android/support/transition/TransitionManager.java
@@ -409,4 +409,22 @@
         }
     }
 
+    /**
+     * Ends all pending and ongoing transitions on the specified scene root.
+     *
+     * @param sceneRoot The root of the View hierarchy to end transitions on.
+     */
+    public static void endTransitions(final ViewGroup sceneRoot) {
+        sPendingTransitions.remove(sceneRoot);
+        final ArrayList<Transition> runningTransitions = getRunningTransitions().get(sceneRoot);
+        if (runningTransitions != null && !runningTransitions.isEmpty()) {
+            // Make a copy in case this is called by an onTransitionEnd listener
+            ArrayList<Transition> copy = new ArrayList<>(runningTransitions);
+            for (int i = copy.size() - 1; i >= 0; i--) {
+                final Transition transition = copy.get(i);
+                transition.forceToEnd(sceneRoot);
+            }
+        }
+    }
+
 }
diff --git a/transition/src/android/support/transition/TransitionSet.java b/transition/src/android/support/transition/TransitionSet.java
index df63414..404245a 100644
--- a/transition/src/android/support/transition/TransitionSet.java
+++ b/transition/src/android/support/transition/TransitionSet.java
@@ -530,6 +530,17 @@
         }
     }
 
+    /** @hide */
+    @RestrictTo(LIBRARY_GROUP)
+    @Override
+    void forceToEnd(ViewGroup sceneRoot) {
+        super.forceToEnd(sceneRoot);
+        int numTransitions = mTransitions.size();
+        for (int i = 0; i < numTransitions; ++i) {
+            mTransitions.get(i).forceToEnd(sceneRoot);
+        }
+    }
+
     @Override
     TransitionSet setSceneRoot(ViewGroup sceneRoot) {
         super.setSceneRoot(sceneRoot);
diff --git a/transition/tests/src/android/support/transition/TransitionManagerTest.java b/transition/tests/src/android/support/transition/TransitionManagerTest.java
index 7f49982..dc4f983 100644
--- a/transition/tests/src/android/support/transition/TransitionManagerTest.java
+++ b/transition/tests/src/android/support/transition/TransitionManagerTest.java
@@ -20,6 +20,11 @@
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.sameInstance;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
 
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.MediumTest;
@@ -132,4 +137,47 @@
         });
     }
 
+    @Test
+    public void testEndTransitions() throws Throwable {
+        final ViewGroup root = rule.getActivity().getRoot();
+        final Transition transition = new AutoTransition();
+        // This transition is very long, but will be forced to end as soon as it starts
+        transition.setDuration(30000);
+        final Transition.TransitionListener listener = mock(Transition.TransitionListener.class);
+        transition.addListener(listener);
+        rule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.go(mScenes[0], transition);
+            }
+        });
+        verify(listener, timeout(3000)).onTransitionStart(any(Transition.class));
+        rule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.endTransitions(root);
+            }
+        });
+        verify(listener, timeout(3000)).onTransitionEnd(any(Transition.class));
+    }
+
+    @Test
+    public void testEndTransitionsBeforeStarted() throws Throwable {
+        final ViewGroup root = rule.getActivity().getRoot();
+        final Transition transition = new AutoTransition();
+        transition.setDuration(0);
+        final Transition.TransitionListener listener = mock(Transition.TransitionListener.class);
+        transition.addListener(listener);
+        rule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.go(mScenes[0], transition);
+                // This terminates the transition before it starts
+                TransitionManager.endTransitions(root);
+            }
+        });
+        verify(listener, never()).onTransitionStart(any(Transition.class));
+        verify(listener, never()).onTransitionEnd(any(Transition.class));
+    }
+
 }
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java b/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
index 3d9647a..78136e2 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
@@ -524,9 +524,6 @@
 
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
-        if (getDelegate().checkActionBarFocusKey(event)) {
-            return true;
-        }
         // Let support action bars open menus in response to the menu key prioritized over
         // the window handling it
         final int keyCode = event.getKeyCode();
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java
index a2fac6f..5d0bf6b 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java
@@ -31,13 +31,11 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.support.v4.app.FragmentActivity;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.view.WindowCompat;
 import android.support.v7.view.ActionMode;
 import android.support.v7.widget.Toolbar;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.KeyEvent;
 import android.view.MenuInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -196,9 +194,7 @@
 
     private static AppCompatDelegate create(Context context, Window window,
             AppCompatCallback callback) {
-        if (BuildCompat.isAtLeastO()) {
-            return new AppCompatDelegateImplO(context, window, callback);
-        } else if (Build.VERSION.SDK_INT >= 24) {
+        if (Build.VERSION.SDK_INT >= 24) {
             return new AppCompatDelegateImplN(context, window, callback);
         } else if (Build.VERSION.SDK_INT >= 23) {
             return new AppCompatDelegateImplV23(context, window, callback);
@@ -425,13 +421,6 @@
     public abstract void onSaveInstanceState(Bundle outState);
 
     /**
-     * Gives AppCompat an opportunity to send focus to the ActionBar.
-     *
-     * @return false if ActionBar was not focused.
-     */
-    public abstract boolean checkActionBarFocusKey(KeyEvent event);
-
-    /**
      * Allow AppCompat to apply the {@code night} and {@code notnight} resource qualifiers.
      *
      * <p>Doing this enables the
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
index 08271d0..5bb5ca6 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
@@ -294,26 +294,6 @@
         // no-op
     }
 
-    @Override
-    public boolean checkActionBarFocusKey(KeyEvent event) {
-        if (event.isCtrlPressed()
-                && event.getUnicodeChar(event.getMetaState() & ~KeyEvent.META_CTRL_MASK) == '<') {
-            // Capture the Control-< and send focus to the ActionBar
-            final int action = event.getAction();
-            if (action == KeyEvent.ACTION_DOWN) {
-                final ActionBar actionBar = getSupportActionBar();
-                if (actionBar != null && actionBar.isShowing() && actionBar.requestFocus()) {
-                    mEatKeyUpEvent = true;
-                    return true;
-                }
-            } else if (action == KeyEvent.ACTION_UP && mEatKeyUpEvent) {
-                mEatKeyUpEvent = false;
-                return true;
-            }
-        }
-        return false;
-    }
-
     abstract void onTitleChanged(CharSequence title);
 
     final CharSequence getTitle() {
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplO.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplO.java
deleted file mode 100644
index 9a60612..0000000
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplO.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2017 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.support.v7.app;
-
-import android.content.Context;
-import android.support.annotation.RequiresApi;
-import android.view.KeyEvent;
-import android.view.Window;
-
-@RequiresApi(26)
-class AppCompatDelegateImplO extends AppCompatDelegateImplN {
-
-    AppCompatDelegateImplO(Context context, Window window, AppCompatCallback callback) {
-        super(context, window, callback);
-    }
-
-    @Override
-    public boolean checkActionBarFocusKey(KeyEvent event) {
-        // In O+, ActionBar's make use of cluster navigation instead of a specific hotkey
-        return false;
-    }
-}
diff --git a/v7/appcompat/tests/src/android/support/v7/app/KeyboardShortcutsTestCaseWithToolbar.java b/v7/appcompat/tests/src/android/support/v7/app/KeyboardShortcutsTestCaseWithToolbar.java
index c22207c..fc2b2ae 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/KeyboardShortcutsTestCaseWithToolbar.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/KeyboardShortcutsTestCaseWithToolbar.java
@@ -20,12 +20,11 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.os.Build;
 import android.os.SystemClock;
 import android.support.test.filters.SmallTest;
-import android.support.v4.os.BuildCompat;
 import android.support.v7.testutils.BaseTestActivity;
 import android.support.v7.widget.Toolbar;
-import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MenuItem;
 import android.view.View;
@@ -42,6 +41,10 @@
     @Test
     @SmallTest
     public void testAccessActionBar() throws Throwable {
+        // Since O, we rely on keyboard navigation clusters for jumping to actionbar
+        if (Build.VERSION.SDK_INT <= 25) {
+            return;
+        }
         final BaseTestActivity activity = getActivity();
 
         final View editText = activity.findViewById(android.support.v7.appcompat.test.R.id.editText);
@@ -53,15 +56,9 @@
         });
 
         getInstrumentation().waitForIdleSync();
-        if (BuildCompat.isAtLeastO()) {
-            // Since O, we rely on keyboard navigation clusters for jumping to actionbar
-            sendMetaKey(KeyEvent.KEYCODE_TAB);
-        } else {
-            sendControlChar('<');
-        }
+        sendMetaKey(KeyEvent.KEYCODE_TAB);
         getInstrumentation().waitForIdleSync();
 
-        // Should jump to the action bar after control-<
         mActivityTestRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -70,13 +67,10 @@
                 assertTrue(toolbar.hasFocus());
             }
         });
-        if (BuildCompat.isAtLeastO()) {
-            // Since O, we rely on keyboard navigation clusters for jumping out of actionbar since
-            // normal navigation no-longer leaves it.
-            sendMetaKey(KeyEvent.KEYCODE_TAB);
-        } else {
-            getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
-        }
+        // We rely on keyboard navigation clusters for jumping out of actionbar since normal
+        // navigation won't leaves it.
+        sendMetaKey(KeyEvent.KEYCODE_TAB);
+
         getInstrumentation().waitForIdleSync();
 
         // Should jump to the first view again.
@@ -147,19 +141,6 @@
         assertEquals(0, activity.mCreateMenuCount);
     }
 
-    private void sendControlChar(char key) throws Throwable {
-        KeyEvent tempEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A);
-        KeyCharacterMap map = tempEvent.getKeyCharacterMap();
-        KeyEvent[] events = map.getEvents(new char[] {key});
-        for (int i = 0; i < events.length; i++) {
-            long time = SystemClock.uptimeMillis();
-            KeyEvent event = events[i];
-            KeyEvent controlKey = new KeyEvent(time, time, event.getAction(), event.getKeyCode(),
-                    event.getRepeatCount(), event.getMetaState() | KeyEvent.META_CTRL_ON);
-            getInstrumentation().sendKeySync(controlKey);
-        }
-    }
-
     private void sendMetaKey(int keyCode) throws Throwable {
         long time = SystemClock.uptimeMillis();
         KeyEvent keyDown = new KeyEvent(time, time, KeyEvent.ACTION_DOWN, keyCode,
diff --git a/v7/mediarouter/res/drawable/mr_button_dark_static.xml b/v7/mediarouter/res/drawable/mr_button_dark_static.xml
new file mode 100644
index 0000000..20cb447
--- /dev/null
+++ b/v7/mediarouter/res/drawable/mr_button_dark_static.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"
+        android:drawable="@drawable/ic_mr_button_disconnected_dark" />
+    <item android:drawable="@drawable/ic_mr_button_disabled_dark" />
+</selector>
diff --git a/v7/mediarouter/res/drawable/mr_button_light_static.xml b/v7/mediarouter/res/drawable/mr_button_light_static.xml
new file mode 100644
index 0000000..9d805d1
--- /dev/null
+++ b/v7/mediarouter/res/drawable/mr_button_light_static.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"
+        android:drawable="@drawable/ic_mr_button_disconnected_light" />
+    <item android:drawable="@drawable/ic_mr_button_disabled_light" />
+</selector>
diff --git a/v7/mediarouter/res/values/attrs.xml b/v7/mediarouter/res/values/attrs.xml
index e9f20a5..abd5815 100644
--- a/v7/mediarouter/res/values/attrs.xml
+++ b/v7/mediarouter/res/values/attrs.xml
@@ -21,6 +21,10 @@
              and non-checked / non-checkable indicates
              that media is playing to the local device only. -->
         <attr name="externalRouteEnabledDrawable" format="reference" />
+        <!-- This drawable is a static version of the above animation drawable.
+             In order to speed up inflation, the static drawable is loaded first and
+             the animation drawable will be loaded in a worker thread separately. -->
+        <attr name="externalRouteEnabledDrawableStatic" format="reference" />
         <!-- Tint to apply to the media route button -->
         <attr name="mediaRouteButtonTint" format="color" />
 
diff --git a/v7/mediarouter/res/values/styles.xml b/v7/mediarouter/res/values/styles.xml
index e8e00e7..2611804 100644
--- a/v7/mediarouter/res/values/styles.xml
+++ b/v7/mediarouter/res/values/styles.xml
@@ -17,11 +17,13 @@
 <resources>
     <style name="Widget.MediaRouter.MediaRouteButton"
             parent="Widget.AppCompat.ActionButton">
+        <item name="externalRouteEnabledDrawableStatic">@drawable/mr_button_dark_static</item>
         <item name="externalRouteEnabledDrawable">@drawable/mr_button_dark</item>
     </style>
 
     <style name="Widget.MediaRouter.Light.MediaRouteButton"
             parent="Widget.AppCompat.Light.ActionButton">
+        <item name="externalRouteEnabledDrawableStatic">@drawable/mr_button_light_static</item>
         <item name="externalRouteEnabledDrawable">@drawable/mr_button_light</item>
     </style>
 
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
index 22ab925..a7e8cb5 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
@@ -24,6 +24,7 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
 import android.support.annotation.NonNull;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentManager;
@@ -34,6 +35,7 @@
 import android.support.v7.widget.TooltipCompat;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.SoundEffectConstants;
 import android.view.View;
 
@@ -127,7 +129,22 @@
                 R.styleable.MediaRouteButton, defStyleAttr, 0);
         mButtonTint = a.getColorStateList(R.styleable.MediaRouteButton_mediaRouteButtonTint);
         setRemoteIndicatorDrawable(a.getDrawable(
-                R.styleable.MediaRouteButton_externalRouteEnabledDrawable));
+                R.styleable.MediaRouteButton_externalRouteEnabledDrawableStatic));
+        final TypedValue value = new TypedValue();
+        a.getValue(R.styleable.MediaRouteButton_externalRouteEnabledDrawable, value);
+        new AsyncTask<Void, Void, Drawable>() {
+            @Override
+            protected Drawable doInBackground(Void... params) {
+                return getContext().getResources().getDrawable(value.resourceId);
+            }
+
+            @Override
+            protected void onPostExecute(Drawable result) {
+                if (result != null) {
+                    setRemoteIndicatorDrawable(result);
+                }
+            }
+        }.execute();
         mMinWidth = a.getDimensionPixelSize(
                 R.styleable.MediaRouteButton_android_minWidth, 0);
         mMinHeight = a.getDimensionPixelSize(