MediaRouteButton.java revision eff7719415542ba819054863b0995f07742a7a8a
111417b1cfde8f1749905f2d735623af9214148afJeff Brown/*
211417b1cfde8f1749905f2d735623af9214148afJeff Brown * Copyright (C) 2013 The Android Open Source Project
311417b1cfde8f1749905f2d735623af9214148afJeff Brown *
411417b1cfde8f1749905f2d735623af9214148afJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
511417b1cfde8f1749905f2d735623af9214148afJeff Brown * you may not use this file except in compliance with the License.
611417b1cfde8f1749905f2d735623af9214148afJeff Brown * You may obtain a copy of the License at
711417b1cfde8f1749905f2d735623af9214148afJeff Brown *
811417b1cfde8f1749905f2d735623af9214148afJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
911417b1cfde8f1749905f2d735623af9214148afJeff Brown *
1011417b1cfde8f1749905f2d735623af9214148afJeff Brown * Unless required by applicable law or agreed to in writing, software
1111417b1cfde8f1749905f2d735623af9214148afJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1211417b1cfde8f1749905f2d735623af9214148afJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1311417b1cfde8f1749905f2d735623af9214148afJeff Brown * See the License for the specific language governing permissions and
1411417b1cfde8f1749905f2d735623af9214148afJeff Brown * limitations under the License.
1511417b1cfde8f1749905f2d735623af9214148afJeff Brown */
1611417b1cfde8f1749905f2d735623af9214148afJeff Brown
1711417b1cfde8f1749905f2d735623af9214148afJeff Brownpackage android.support.v7.app;
1811417b1cfde8f1749905f2d735623af9214148afJeff Brown
1911417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.app.Activity;
2011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.content.Context;
2111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.content.ContextWrapper;
2211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.content.res.TypedArray;
2311417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.graphics.Canvas;
2411417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.graphics.Rect;
2511417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.graphics.drawable.Drawable;
2611417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v4.app.FragmentActivity;
2711417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v4.app.FragmentManager;
2811417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v4.graphics.drawable.DrawableCompat;
2911417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v4.view.GravityCompat;
3011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouter;
3111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouteSelector;
3211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.mediarouter.R;
3311417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.text.TextUtils;
3411417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.util.AttributeSet;
3511417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.util.Log;
3611417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.Gravity;
3711417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.HapticFeedbackConstants;
3811417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.SoundEffectConstants;
3911417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.View;
4011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.Toast;
4111417b1cfde8f1749905f2d735623af9214148afJeff Brown
4211417b1cfde8f1749905f2d735623af9214148afJeff Brown/**
4311417b1cfde8f1749905f2d735623af9214148afJeff Brown * The media route button allows the user to select routes and to control the
4411417b1cfde8f1749905f2d735623af9214148afJeff Brown * currently selected route.
459942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * <p>
469942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * The application must specify the kinds of routes that the user should be allowed
479942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * to select by specifying a {@link MediaRouteSelector selector} with the
489942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * {@link #setRouteSelector} method.
499942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * </p><p>
509942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * When the default route is selected or when the currently selected route does not
519942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * match the {@link #getRouteSelector() selector}, the button will appear in
529942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * an inactive state indicating that the application is not connected to a
539942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * route of the kind that it wants to use.  Clicking on the button opens
549942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * a {@link MediaRouteChooserDialog} to allow the user to select a route.
559942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * If no non-default routes match the selector and it is not possible for an active
569942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * scan to discover any matching routes, then the button is disabled and cannot
579942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * be clicked.
589942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * </p><p>
599942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * When a non-default route is selected that matches the selector, the button will
609942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * appear in an active state indicating that the application is connected
619942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * to a route of the kind that it wants to use.  The button may also appear
629942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * in an intermediary connecting state if the route is in the process of connecting
639942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * to the destination but has not yet completed doing so.  In either case, clicking
649942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * on the button opens a {@link MediaRouteControllerDialog} to allow the user
659942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * to control or disconnect from the current route.
669942d40d0d952b03b583fe66f434676793697aa2Jeff Brown * </p>
6711417b1cfde8f1749905f2d735623af9214148afJeff Brown *
6811417b1cfde8f1749905f2d735623af9214148afJeff Brown * <h3>Prerequisites</h3>
6911417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p>
7011417b1cfde8f1749905f2d735623af9214148afJeff Brown * To use the media route button, the activity must be a subclass of
7111417b1cfde8f1749905f2d735623af9214148afJeff Brown * {@link FragmentActivity} from the <code>android.support.v4</code>
7211417b1cfde8f1749905f2d735623af9214148afJeff Brown * support library.  Refer to support library documentation for details.
7311417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p>
7411417b1cfde8f1749905f2d735623af9214148afJeff Brown *
7511417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteActionProvider
7611417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see #setRouteSelector
7711417b1cfde8f1749905f2d735623af9214148afJeff Brown */
7811417b1cfde8f1749905f2d735623af9214148afJeff Brownpublic class MediaRouteButton extends View {
7911417b1cfde8f1749905f2d735623af9214148afJeff Brown    private static final String TAG = "MediaRouteButton";
8011417b1cfde8f1749905f2d735623af9214148afJeff Brown
8111417b1cfde8f1749905f2d735623af9214148afJeff Brown    private static final String CHOOSER_FRAGMENT_TAG =
8211417b1cfde8f1749905f2d735623af9214148afJeff Brown            "android.support.v7.mediarouter:MediaRouteChooserDialogFragment";
8311417b1cfde8f1749905f2d735623af9214148afJeff Brown    private static final String CONTROLLER_FRAGMENT_TAG =
8411417b1cfde8f1749905f2d735623af9214148afJeff Brown            "android.support.v7.mediarouter:MediaRouteControllerDialogFragment";
8511417b1cfde8f1749905f2d735623af9214148afJeff Brown
8611417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouter mRouter;
8711417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouterCallback mCallback;
8811417b1cfde8f1749905f2d735623af9214148afJeff Brown
8911417b1cfde8f1749905f2d735623af9214148afJeff Brown    private MediaRouteSelector mSelector = MediaRouteSelector.EMPTY;
90eff7719415542ba819054863b0995f07742a7a8aJeff Brown    private MediaRouteDialogFactory mDialogFactory = MediaRouteDialogFactory.getDefault();
9111417b1cfde8f1749905f2d735623af9214148afJeff Brown
9211417b1cfde8f1749905f2d735623af9214148afJeff Brown    private boolean mAttachedToWindow;
9311417b1cfde8f1749905f2d735623af9214148afJeff Brown
9411417b1cfde8f1749905f2d735623af9214148afJeff Brown    private Drawable mRemoteIndicator;
9511417b1cfde8f1749905f2d735623af9214148afJeff Brown    private boolean mRemoteActive;
9611417b1cfde8f1749905f2d735623af9214148afJeff Brown    private boolean mCheatSheetEnabled;
9711417b1cfde8f1749905f2d735623af9214148afJeff Brown    private boolean mIsConnecting;
9811417b1cfde8f1749905f2d735623af9214148afJeff Brown
9911417b1cfde8f1749905f2d735623af9214148afJeff Brown    private int mMinWidth;
10011417b1cfde8f1749905f2d735623af9214148afJeff Brown    private int mMinHeight;
10111417b1cfde8f1749905f2d735623af9214148afJeff Brown
10211417b1cfde8f1749905f2d735623af9214148afJeff Brown    // The checked state is used when connected to a remote route.
10311417b1cfde8f1749905f2d735623af9214148afJeff Brown    private static final int[] CHECKED_STATE_SET = {
10411417b1cfde8f1749905f2d735623af9214148afJeff Brown        android.R.attr.state_checked
10511417b1cfde8f1749905f2d735623af9214148afJeff Brown    };
10611417b1cfde8f1749905f2d735623af9214148afJeff Brown
10711417b1cfde8f1749905f2d735623af9214148afJeff Brown    // The checkable state is used while connecting to a remote route.
10811417b1cfde8f1749905f2d735623af9214148afJeff Brown    private static final int[] CHECKABLE_STATE_SET = {
10911417b1cfde8f1749905f2d735623af9214148afJeff Brown        android.R.attr.state_checkable
11011417b1cfde8f1749905f2d735623af9214148afJeff Brown    };
11111417b1cfde8f1749905f2d735623af9214148afJeff Brown
11211417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteButton(Context context) {
11311417b1cfde8f1749905f2d735623af9214148afJeff Brown        this(context, null);
11411417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
11511417b1cfde8f1749905f2d735623af9214148afJeff Brown
11611417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteButton(Context context, AttributeSet attrs) {
11711417b1cfde8f1749905f2d735623af9214148afJeff Brown        this(context, attrs, R.attr.mediaRouteButtonStyle);
11811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
11911417b1cfde8f1749905f2d735623af9214148afJeff Brown
12011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
1219942d40d0d952b03b583fe66f434676793697aa2Jeff Brown        super(MediaRouterThemeHelper.createThemedContext(context, false), attrs, defStyleAttr);
12211417b1cfde8f1749905f2d735623af9214148afJeff Brown        context = getContext();
12311417b1cfde8f1749905f2d735623af9214148afJeff Brown
12411417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter = MediaRouter.getInstance(context);
12511417b1cfde8f1749905f2d735623af9214148afJeff Brown        mCallback = new MediaRouterCallback();
12611417b1cfde8f1749905f2d735623af9214148afJeff Brown
12711417b1cfde8f1749905f2d735623af9214148afJeff Brown        TypedArray a = context.obtainStyledAttributes(attrs,
12811417b1cfde8f1749905f2d735623af9214148afJeff Brown                R.styleable.MediaRouteButton, defStyleAttr, 0);
12911417b1cfde8f1749905f2d735623af9214148afJeff Brown        setRemoteIndicatorDrawable(a.getDrawable(
13011417b1cfde8f1749905f2d735623af9214148afJeff Brown                R.styleable.MediaRouteButton_externalRouteEnabledDrawable));
13111417b1cfde8f1749905f2d735623af9214148afJeff Brown        mMinWidth = a.getDimensionPixelSize(
13211417b1cfde8f1749905f2d735623af9214148afJeff Brown                R.styleable.MediaRouteButton_android_minWidth, 0);
13311417b1cfde8f1749905f2d735623af9214148afJeff Brown        mMinHeight = a.getDimensionPixelSize(
13411417b1cfde8f1749905f2d735623af9214148afJeff Brown                R.styleable.MediaRouteButton_android_minHeight, 0);
13511417b1cfde8f1749905f2d735623af9214148afJeff Brown        a.recycle();
13611417b1cfde8f1749905f2d735623af9214148afJeff Brown
13711417b1cfde8f1749905f2d735623af9214148afJeff Brown        setClickable(true);
13811417b1cfde8f1749905f2d735623af9214148afJeff Brown        setLongClickable(true);
13911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
14011417b1cfde8f1749905f2d735623af9214148afJeff Brown
14111417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
14211417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the media route selector for filtering the routes that the user can
14311417b1cfde8f1749905f2d735623af9214148afJeff Brown     * select using the media route chooser dialog.
14411417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
14511417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The selector, never null.
14611417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
14711417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteSelector getRouteSelector() {
14811417b1cfde8f1749905f2d735623af9214148afJeff Brown        return mSelector;
14911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
15011417b1cfde8f1749905f2d735623af9214148afJeff Brown
15111417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
15211417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Sets the media route selector for filtering the routes that the user can
15311417b1cfde8f1749905f2d735623af9214148afJeff Brown     * select using the media route chooser dialog.
15411417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
15511417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @param selector The selector, must not be null.
15611417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
15711417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void setRouteSelector(MediaRouteSelector selector) {
15811417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (selector == null) {
15911417b1cfde8f1749905f2d735623af9214148afJeff Brown            throw new IllegalArgumentException("selector must not be null");
16011417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
16111417b1cfde8f1749905f2d735623af9214148afJeff Brown
16211417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (!mSelector.equals(selector)) {
16311417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (mAttachedToWindow) {
1649942d40d0d952b03b583fe66f434676793697aa2Jeff Brown                if (!mSelector.isEmpty()) {
1659942d40d0d952b03b583fe66f434676793697aa2Jeff Brown                    mRouter.removeCallback(mCallback);
1669942d40d0d952b03b583fe66f434676793697aa2Jeff Brown                }
1679942d40d0d952b03b583fe66f434676793697aa2Jeff Brown                if (!selector.isEmpty()) {
1689942d40d0d952b03b583fe66f434676793697aa2Jeff Brown                    mRouter.addCallback(selector, mCallback);
1699942d40d0d952b03b583fe66f434676793697aa2Jeff Brown                }
17011417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
1719942d40d0d952b03b583fe66f434676793697aa2Jeff Brown            mSelector = selector;
17211417b1cfde8f1749905f2d735623af9214148afJeff Brown            refreshRoute();
17311417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
17411417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
17511417b1cfde8f1749905f2d735623af9214148afJeff Brown
17611417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
177eff7719415542ba819054863b0995f07742a7a8aJeff Brown     * Gets the media route dialog factory to use when showing the route chooser
178eff7719415542ba819054863b0995f07742a7a8aJeff Brown     * or controller dialog.
179eff7719415542ba819054863b0995f07742a7a8aJeff Brown     *
180eff7719415542ba819054863b0995f07742a7a8aJeff Brown     * @return The dialog factory, never null.
181eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
182eff7719415542ba819054863b0995f07742a7a8aJeff Brown    public MediaRouteDialogFactory getDialogFactory() {
183eff7719415542ba819054863b0995f07742a7a8aJeff Brown        return mDialogFactory;
184eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
185eff7719415542ba819054863b0995f07742a7a8aJeff Brown
186eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
187eff7719415542ba819054863b0995f07742a7a8aJeff Brown     * Sets the media route dialog factory to use when showing the route chooser
188eff7719415542ba819054863b0995f07742a7a8aJeff Brown     * or controller dialog.
189eff7719415542ba819054863b0995f07742a7a8aJeff Brown     *
190eff7719415542ba819054863b0995f07742a7a8aJeff Brown     * @param factory The dialog factory, must not be null.
191eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
192eff7719415542ba819054863b0995f07742a7a8aJeff Brown    public void setDialogFactory(MediaRouteDialogFactory factory) {
193eff7719415542ba819054863b0995f07742a7a8aJeff Brown        if (factory == null) {
194eff7719415542ba819054863b0995f07742a7a8aJeff Brown            throw new IllegalArgumentException("factory must not be null");
195eff7719415542ba819054863b0995f07742a7a8aJeff Brown        }
196eff7719415542ba819054863b0995f07742a7a8aJeff Brown
197eff7719415542ba819054863b0995f07742a7a8aJeff Brown        mDialogFactory = factory;
198eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
199eff7719415542ba819054863b0995f07742a7a8aJeff Brown
200eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
20111417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Show the route chooser or controller dialog.
20211417b1cfde8f1749905f2d735623af9214148afJeff Brown     * <p>
2039942d40d0d952b03b583fe66f434676793697aa2Jeff Brown     * If the default route is selected or if the currently selected route does
2049942d40d0d952b03b583fe66f434676793697aa2Jeff Brown     * not match the {@link #getRouteSelector selector}, then shows the route chooser dialog.
2059942d40d0d952b03b583fe66f434676793697aa2Jeff Brown     * Otherwise, shows the route controller dialog to offer the user
20611417b1cfde8f1749905f2d735623af9214148afJeff Brown     * a choice to disconnect from the route or perform other control actions
20711417b1cfde8f1749905f2d735623af9214148afJeff Brown     * such as setting the route's volume.
2089942d40d0d952b03b583fe66f434676793697aa2Jeff Brown     * </p><p>
209eff7719415542ba819054863b0995f07742a7a8aJeff Brown     * The application can customize the dialogs by calling {@link #setDialogFactory}
210eff7719415542ba819054863b0995f07742a7a8aJeff Brown     * to provide a customized dialog factory.
21111417b1cfde8f1749905f2d735623af9214148afJeff Brown     * </p>
21211417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
21311417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return True if the dialog was actually shown.
21411417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
21511417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @throws IllegalStateException if the activity is not a subclass of
21611417b1cfde8f1749905f2d735623af9214148afJeff Brown     * {@link FragmentActivity}.
21711417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
21811417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean showDialog() {
21911417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (!mAttachedToWindow) {
22011417b1cfde8f1749905f2d735623af9214148afJeff Brown            return false;
22111417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
22211417b1cfde8f1749905f2d735623af9214148afJeff Brown
22311417b1cfde8f1749905f2d735623af9214148afJeff Brown        final FragmentManager fm = getFragmentManager();
22411417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (fm == null) {
22511417b1cfde8f1749905f2d735623af9214148afJeff Brown            throw new IllegalStateException("The activity must be a subclass of FragmentActivity");
22611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
22711417b1cfde8f1749905f2d735623af9214148afJeff Brown
2289942d40d0d952b03b583fe66f434676793697aa2Jeff Brown        MediaRouter.RouteInfo route = mRouter.getSelectedRoute();
2299942d40d0d952b03b583fe66f434676793697aa2Jeff Brown        if (route.isDefault() || !route.matchesSelector(mSelector)) {
23011417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (fm.findFragmentByTag(CHOOSER_FRAGMENT_TAG) != null) {
23111417b1cfde8f1749905f2d735623af9214148afJeff Brown                Log.w(TAG, "showDialog(): Route chooser dialog already showing!");
23211417b1cfde8f1749905f2d735623af9214148afJeff Brown                return false;
23311417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
234eff7719415542ba819054863b0995f07742a7a8aJeff Brown            MediaRouteChooserDialogFragment f =
235eff7719415542ba819054863b0995f07742a7a8aJeff Brown                    mDialogFactory.onCreateChooserDialogFragment();
23611417b1cfde8f1749905f2d735623af9214148afJeff Brown            f.setRouteSelector(mSelector);
23711417b1cfde8f1749905f2d735623af9214148afJeff Brown            f.show(fm, CHOOSER_FRAGMENT_TAG);
23811417b1cfde8f1749905f2d735623af9214148afJeff Brown        } else {
23911417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (fm.findFragmentByTag(CONTROLLER_FRAGMENT_TAG) != null) {
24011417b1cfde8f1749905f2d735623af9214148afJeff Brown                Log.w(TAG, "showDialog(): Route controller dialog already showing!");
24111417b1cfde8f1749905f2d735623af9214148afJeff Brown                return false;
24211417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
243eff7719415542ba819054863b0995f07742a7a8aJeff Brown            MediaRouteControllerDialogFragment f =
244eff7719415542ba819054863b0995f07742a7a8aJeff Brown                    mDialogFactory.onCreateControllerDialogFragment();
24511417b1cfde8f1749905f2d735623af9214148afJeff Brown            f.show(fm, CONTROLLER_FRAGMENT_TAG);
24611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
24711417b1cfde8f1749905f2d735623af9214148afJeff Brown        return true;
24811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
24911417b1cfde8f1749905f2d735623af9214148afJeff Brown
25011417b1cfde8f1749905f2d735623af9214148afJeff Brown    private FragmentManager getFragmentManager() {
25111417b1cfde8f1749905f2d735623af9214148afJeff Brown        Activity activity = getActivity();
25211417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (activity instanceof FragmentActivity) {
25311417b1cfde8f1749905f2d735623af9214148afJeff Brown            return ((FragmentActivity)activity).getSupportFragmentManager();
25411417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
25511417b1cfde8f1749905f2d735623af9214148afJeff Brown        return null;
25611417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
25711417b1cfde8f1749905f2d735623af9214148afJeff Brown
25811417b1cfde8f1749905f2d735623af9214148afJeff Brown    private Activity getActivity() {
25911417b1cfde8f1749905f2d735623af9214148afJeff Brown        // Gross way of unwrapping the Activity so we can get the FragmentManager
26011417b1cfde8f1749905f2d735623af9214148afJeff Brown        Context context = getContext();
26111417b1cfde8f1749905f2d735623af9214148afJeff Brown        while (context instanceof ContextWrapper) {
26211417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (context instanceof Activity) {
26311417b1cfde8f1749905f2d735623af9214148afJeff Brown                return (Activity)context;
26411417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
26511417b1cfde8f1749905f2d735623af9214148afJeff Brown            context = ((ContextWrapper)context).getBaseContext();
26611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
26711417b1cfde8f1749905f2d735623af9214148afJeff Brown        return null;
26811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
26911417b1cfde8f1749905f2d735623af9214148afJeff Brown
27011417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
27111417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Sets whether to enable showing a toast with the content descriptor of the
27211417b1cfde8f1749905f2d735623af9214148afJeff Brown     * button when the button is long pressed.
27311417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
27411417b1cfde8f1749905f2d735623af9214148afJeff Brown    void setCheatSheetEnabled(boolean enable) {
27511417b1cfde8f1749905f2d735623af9214148afJeff Brown        mCheatSheetEnabled = enable;
27611417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
27711417b1cfde8f1749905f2d735623af9214148afJeff Brown
27811417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
27911417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean performClick() {
28011417b1cfde8f1749905f2d735623af9214148afJeff Brown        // Send the appropriate accessibility events and call listeners
28111417b1cfde8f1749905f2d735623af9214148afJeff Brown        boolean handled = super.performClick();
28211417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (!handled) {
28311417b1cfde8f1749905f2d735623af9214148afJeff Brown            playSoundEffect(SoundEffectConstants.CLICK);
28411417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
28511417b1cfde8f1749905f2d735623af9214148afJeff Brown        return showDialog() || handled;
28611417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
28711417b1cfde8f1749905f2d735623af9214148afJeff Brown
28811417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
28911417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean performLongClick() {
29011417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (super.performLongClick()) {
29111417b1cfde8f1749905f2d735623af9214148afJeff Brown            return true;
29211417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
29311417b1cfde8f1749905f2d735623af9214148afJeff Brown
29411417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (!mCheatSheetEnabled) {
29511417b1cfde8f1749905f2d735623af9214148afJeff Brown            return false;
29611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
29711417b1cfde8f1749905f2d735623af9214148afJeff Brown
29811417b1cfde8f1749905f2d735623af9214148afJeff Brown        final CharSequence contentDesc = getContentDescription();
29911417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (TextUtils.isEmpty(contentDesc)) {
30011417b1cfde8f1749905f2d735623af9214148afJeff Brown            // Don't show the cheat sheet if we have no description
30111417b1cfde8f1749905f2d735623af9214148afJeff Brown            return false;
30211417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
30311417b1cfde8f1749905f2d735623af9214148afJeff Brown
30411417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int[] screenPos = new int[2];
30511417b1cfde8f1749905f2d735623af9214148afJeff Brown        final Rect displayFrame = new Rect();
30611417b1cfde8f1749905f2d735623af9214148afJeff Brown        getLocationOnScreen(screenPos);
30711417b1cfde8f1749905f2d735623af9214148afJeff Brown        getWindowVisibleDisplayFrame(displayFrame);
30811417b1cfde8f1749905f2d735623af9214148afJeff Brown
30911417b1cfde8f1749905f2d735623af9214148afJeff Brown        final Context context = getContext();
31011417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int width = getWidth();
31111417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int height = getHeight();
31211417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int midy = screenPos[1] + height / 2;
31311417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
31411417b1cfde8f1749905f2d735623af9214148afJeff Brown
31511417b1cfde8f1749905f2d735623af9214148afJeff Brown        Toast cheatSheet = Toast.makeText(context, contentDesc, Toast.LENGTH_SHORT);
31611417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (midy < displayFrame.height()) {
31711417b1cfde8f1749905f2d735623af9214148afJeff Brown            // Show along the top; follow action buttons
31811417b1cfde8f1749905f2d735623af9214148afJeff Brown            cheatSheet.setGravity(Gravity.TOP | GravityCompat.END,
31911417b1cfde8f1749905f2d735623af9214148afJeff Brown                    screenWidth - screenPos[0] - width / 2, height);
32011417b1cfde8f1749905f2d735623af9214148afJeff Brown        } else {
32111417b1cfde8f1749905f2d735623af9214148afJeff Brown            // Show along the bottom center
32211417b1cfde8f1749905f2d735623af9214148afJeff Brown            cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
32311417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
32411417b1cfde8f1749905f2d735623af9214148afJeff Brown        cheatSheet.show();
32511417b1cfde8f1749905f2d735623af9214148afJeff Brown        performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
32611417b1cfde8f1749905f2d735623af9214148afJeff Brown        return true;
32711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
32811417b1cfde8f1749905f2d735623af9214148afJeff Brown
32911417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
33011417b1cfde8f1749905f2d735623af9214148afJeff Brown    protected int[] onCreateDrawableState(int extraSpace) {
33111417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
33211417b1cfde8f1749905f2d735623af9214148afJeff Brown
33311417b1cfde8f1749905f2d735623af9214148afJeff Brown        // Technically we should be handling this more completely, but these
33411417b1cfde8f1749905f2d735623af9214148afJeff Brown        // are implementation details here. Checkable is used to express the connecting
33511417b1cfde8f1749905f2d735623af9214148afJeff Brown        // drawable state and it's mutually exclusive with check for the purposes
33611417b1cfde8f1749905f2d735623af9214148afJeff Brown        // of state selection here.
33711417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (mIsConnecting) {
33811417b1cfde8f1749905f2d735623af9214148afJeff Brown            mergeDrawableStates(drawableState, CHECKABLE_STATE_SET);
33911417b1cfde8f1749905f2d735623af9214148afJeff Brown        } else if (mRemoteActive) {
34011417b1cfde8f1749905f2d735623af9214148afJeff Brown            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
34111417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
34211417b1cfde8f1749905f2d735623af9214148afJeff Brown        return drawableState;
34311417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
34411417b1cfde8f1749905f2d735623af9214148afJeff Brown
34511417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
34611417b1cfde8f1749905f2d735623af9214148afJeff Brown    protected void drawableStateChanged() {
34711417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.drawableStateChanged();
34811417b1cfde8f1749905f2d735623af9214148afJeff Brown
34911417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (mRemoteIndicator != null) {
35011417b1cfde8f1749905f2d735623af9214148afJeff Brown            int[] myDrawableState = getDrawableState();
35111417b1cfde8f1749905f2d735623af9214148afJeff Brown            mRemoteIndicator.setState(myDrawableState);
35211417b1cfde8f1749905f2d735623af9214148afJeff Brown            invalidate();
35311417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
35411417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
35511417b1cfde8f1749905f2d735623af9214148afJeff Brown
35611417b1cfde8f1749905f2d735623af9214148afJeff Brown    private void setRemoteIndicatorDrawable(Drawable d) {
35711417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (mRemoteIndicator != null) {
35811417b1cfde8f1749905f2d735623af9214148afJeff Brown            mRemoteIndicator.setCallback(null);
35911417b1cfde8f1749905f2d735623af9214148afJeff Brown            unscheduleDrawable(mRemoteIndicator);
36011417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
36111417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRemoteIndicator = d;
36211417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (d != null) {
36311417b1cfde8f1749905f2d735623af9214148afJeff Brown            d.setCallback(this);
36411417b1cfde8f1749905f2d735623af9214148afJeff Brown            d.setState(getDrawableState());
36511417b1cfde8f1749905f2d735623af9214148afJeff Brown            d.setVisible(getVisibility() == VISIBLE, false);
36611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
36711417b1cfde8f1749905f2d735623af9214148afJeff Brown
36811417b1cfde8f1749905f2d735623af9214148afJeff Brown        refreshDrawableState();
36911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
37011417b1cfde8f1749905f2d735623af9214148afJeff Brown
37111417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
37211417b1cfde8f1749905f2d735623af9214148afJeff Brown    protected boolean verifyDrawable(Drawable who) {
37311417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.verifyDrawable(who) || who == mRemoteIndicator;
37411417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
37511417b1cfde8f1749905f2d735623af9214148afJeff Brown
37611417b1cfde8f1749905f2d735623af9214148afJeff Brown    //@Override defined in v11
37711417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void jumpDrawablesToCurrentState() {
37811417b1cfde8f1749905f2d735623af9214148afJeff Brown        // We can't call super to handle the background so we do it ourselves.
37911417b1cfde8f1749905f2d735623af9214148afJeff Brown        //super.jumpDrawablesToCurrentState();
38011417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (getBackground() != null) {
38111417b1cfde8f1749905f2d735623af9214148afJeff Brown            DrawableCompat.jumpToCurrentState(getBackground());
38211417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
38311417b1cfde8f1749905f2d735623af9214148afJeff Brown
38411417b1cfde8f1749905f2d735623af9214148afJeff Brown        // Handle our own remote indicator.
38511417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (mRemoteIndicator != null) {
38611417b1cfde8f1749905f2d735623af9214148afJeff Brown            DrawableCompat.jumpToCurrentState(mRemoteIndicator);
38711417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
38811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
38911417b1cfde8f1749905f2d735623af9214148afJeff Brown
39011417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
39111417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void setVisibility(int visibility) {
39211417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.setVisibility(visibility);
39311417b1cfde8f1749905f2d735623af9214148afJeff Brown
39411417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (mRemoteIndicator != null) {
39511417b1cfde8f1749905f2d735623af9214148afJeff Brown            mRemoteIndicator.setVisible(getVisibility() == VISIBLE, false);
39611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
39711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
39811417b1cfde8f1749905f2d735623af9214148afJeff Brown
39911417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
40011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onAttachedToWindow() {
40111417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onAttachedToWindow();
40211417b1cfde8f1749905f2d735623af9214148afJeff Brown
40311417b1cfde8f1749905f2d735623af9214148afJeff Brown        mAttachedToWindow = true;
4049942d40d0d952b03b583fe66f434676793697aa2Jeff Brown        if (!mSelector.isEmpty()) {
4059942d40d0d952b03b583fe66f434676793697aa2Jeff Brown            mRouter.addCallback(mSelector, mCallback);
40611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
4079942d40d0d952b03b583fe66f434676793697aa2Jeff Brown        refreshRoute();
40811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
40911417b1cfde8f1749905f2d735623af9214148afJeff Brown
41011417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
41111417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onDetachedFromWindow() {
41211417b1cfde8f1749905f2d735623af9214148afJeff Brown        mAttachedToWindow = false;
4139942d40d0d952b03b583fe66f434676793697aa2Jeff Brown        if (!mSelector.isEmpty()) {
4149942d40d0d952b03b583fe66f434676793697aa2Jeff Brown            mRouter.removeCallback(mCallback);
4159942d40d0d952b03b583fe66f434676793697aa2Jeff Brown        }
41611417b1cfde8f1749905f2d735623af9214148afJeff Brown
41711417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onDetachedFromWindow();
41811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
41911417b1cfde8f1749905f2d735623af9214148afJeff Brown
42011417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
42111417b1cfde8f1749905f2d735623af9214148afJeff Brown    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
42211417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
42311417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
42411417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
42511417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
42611417b1cfde8f1749905f2d735623af9214148afJeff Brown
42711417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int minWidth = Math.max(mMinWidth,
42811417b1cfde8f1749905f2d735623af9214148afJeff Brown                mRemoteIndicator != null ? mRemoteIndicator.getIntrinsicWidth() : 0);
42911417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int minHeight = Math.max(mMinHeight,
43011417b1cfde8f1749905f2d735623af9214148afJeff Brown                mRemoteIndicator != null ? mRemoteIndicator.getIntrinsicHeight() : 0);
43111417b1cfde8f1749905f2d735623af9214148afJeff Brown
43211417b1cfde8f1749905f2d735623af9214148afJeff Brown        int width;
43311417b1cfde8f1749905f2d735623af9214148afJeff Brown        switch (widthMode) {
43411417b1cfde8f1749905f2d735623af9214148afJeff Brown            case MeasureSpec.EXACTLY:
43511417b1cfde8f1749905f2d735623af9214148afJeff Brown                width = widthSize;
43611417b1cfde8f1749905f2d735623af9214148afJeff Brown                break;
43711417b1cfde8f1749905f2d735623af9214148afJeff Brown            case MeasureSpec.AT_MOST:
43811417b1cfde8f1749905f2d735623af9214148afJeff Brown                width = Math.min(widthSize, minWidth + getPaddingLeft() + getPaddingRight());
43911417b1cfde8f1749905f2d735623af9214148afJeff Brown                break;
44011417b1cfde8f1749905f2d735623af9214148afJeff Brown            default:
44111417b1cfde8f1749905f2d735623af9214148afJeff Brown            case MeasureSpec.UNSPECIFIED:
44211417b1cfde8f1749905f2d735623af9214148afJeff Brown                width = minWidth + getPaddingLeft() + getPaddingRight();
44311417b1cfde8f1749905f2d735623af9214148afJeff Brown                break;
44411417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
44511417b1cfde8f1749905f2d735623af9214148afJeff Brown
44611417b1cfde8f1749905f2d735623af9214148afJeff Brown        int height;
44711417b1cfde8f1749905f2d735623af9214148afJeff Brown        switch (heightMode) {
44811417b1cfde8f1749905f2d735623af9214148afJeff Brown            case MeasureSpec.EXACTLY:
44911417b1cfde8f1749905f2d735623af9214148afJeff Brown                height = heightSize;
45011417b1cfde8f1749905f2d735623af9214148afJeff Brown                break;
45111417b1cfde8f1749905f2d735623af9214148afJeff Brown            case MeasureSpec.AT_MOST:
45211417b1cfde8f1749905f2d735623af9214148afJeff Brown                height = Math.min(heightSize, minHeight + getPaddingTop() + getPaddingBottom());
45311417b1cfde8f1749905f2d735623af9214148afJeff Brown                break;
45411417b1cfde8f1749905f2d735623af9214148afJeff Brown            default:
45511417b1cfde8f1749905f2d735623af9214148afJeff Brown            case MeasureSpec.UNSPECIFIED:
45611417b1cfde8f1749905f2d735623af9214148afJeff Brown                height = minHeight + getPaddingTop() + getPaddingBottom();
45711417b1cfde8f1749905f2d735623af9214148afJeff Brown                break;
45811417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
45911417b1cfde8f1749905f2d735623af9214148afJeff Brown
46011417b1cfde8f1749905f2d735623af9214148afJeff Brown        setMeasuredDimension(width, height);
46111417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
46211417b1cfde8f1749905f2d735623af9214148afJeff Brown
46311417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
46411417b1cfde8f1749905f2d735623af9214148afJeff Brown    protected void onDraw(Canvas canvas) {
46511417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onDraw(canvas);
46611417b1cfde8f1749905f2d735623af9214148afJeff Brown
46711417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (mRemoteIndicator != null) {
46811417b1cfde8f1749905f2d735623af9214148afJeff Brown            final int left = getPaddingLeft();
46911417b1cfde8f1749905f2d735623af9214148afJeff Brown            final int right = getWidth() - getPaddingRight();
47011417b1cfde8f1749905f2d735623af9214148afJeff Brown            final int top = getPaddingTop();
47111417b1cfde8f1749905f2d735623af9214148afJeff Brown            final int bottom = getHeight() - getPaddingBottom();
47211417b1cfde8f1749905f2d735623af9214148afJeff Brown
47311417b1cfde8f1749905f2d735623af9214148afJeff Brown            final int drawWidth = mRemoteIndicator.getIntrinsicWidth();
47411417b1cfde8f1749905f2d735623af9214148afJeff Brown            final int drawHeight = mRemoteIndicator.getIntrinsicHeight();
47511417b1cfde8f1749905f2d735623af9214148afJeff Brown            final int drawLeft = left + (right - left - drawWidth) / 2;
47611417b1cfde8f1749905f2d735623af9214148afJeff Brown            final int drawTop = top + (bottom - top - drawHeight) / 2;
47711417b1cfde8f1749905f2d735623af9214148afJeff Brown
47811417b1cfde8f1749905f2d735623af9214148afJeff Brown            mRemoteIndicator.setBounds(drawLeft, drawTop,
47911417b1cfde8f1749905f2d735623af9214148afJeff Brown                    drawLeft + drawWidth, drawTop + drawHeight);
48011417b1cfde8f1749905f2d735623af9214148afJeff Brown            mRemoteIndicator.draw(canvas);
48111417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
48211417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
48311417b1cfde8f1749905f2d735623af9214148afJeff Brown
48411417b1cfde8f1749905f2d735623af9214148afJeff Brown    private void refreshRoute() {
48511417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (mAttachedToWindow) {
4869942d40d0d952b03b583fe66f434676793697aa2Jeff Brown            final MediaRouter.RouteInfo route = mRouter.getSelectedRoute();
4879942d40d0d952b03b583fe66f434676793697aa2Jeff Brown            final boolean isRemote = !route.isDefault() && route.matchesSelector(mSelector);
4889942d40d0d952b03b583fe66f434676793697aa2Jeff Brown            final boolean isConnecting = isRemote && route.isConnecting();
48911417b1cfde8f1749905f2d735623af9214148afJeff Brown
49011417b1cfde8f1749905f2d735623af9214148afJeff Brown            boolean needsRefresh = false;
49111417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (mRemoteActive != isRemote) {
49211417b1cfde8f1749905f2d735623af9214148afJeff Brown                mRemoteActive = isRemote;
49311417b1cfde8f1749905f2d735623af9214148afJeff Brown                needsRefresh = true;
49411417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
49511417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (mIsConnecting != isConnecting) {
49611417b1cfde8f1749905f2d735623af9214148afJeff Brown                mIsConnecting = isConnecting;
49711417b1cfde8f1749905f2d735623af9214148afJeff Brown                needsRefresh = true;
49811417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
49911417b1cfde8f1749905f2d735623af9214148afJeff Brown
50011417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (needsRefresh) {
50111417b1cfde8f1749905f2d735623af9214148afJeff Brown                refreshDrawableState();
50211417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
50311417b1cfde8f1749905f2d735623af9214148afJeff Brown
50411417b1cfde8f1749905f2d735623af9214148afJeff Brown            setEnabled(mRouter.isRouteAvailable(mSelector,
505d11aa1784335270b8d85e385f2c8be79ee6a586cJeff Brown                    MediaRouter.AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE));
50611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
50711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
50811417b1cfde8f1749905f2d735623af9214148afJeff Brown
50911417b1cfde8f1749905f2d735623af9214148afJeff Brown    static interface AttachCallback {
51011417b1cfde8f1749905f2d735623af9214148afJeff Brown        void onAttachedToWindow();
51111417b1cfde8f1749905f2d735623af9214148afJeff Brown        void onDetachedFromWindow();
51211417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
51311417b1cfde8f1749905f2d735623af9214148afJeff Brown
51411417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final class MediaRouterCallback extends MediaRouter.Callback {
51511417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
51611417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) {
51711417b1cfde8f1749905f2d735623af9214148afJeff Brown            refreshRoute();
51811417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
51911417b1cfde8f1749905f2d735623af9214148afJeff Brown
52011417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
52111417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) {
52211417b1cfde8f1749905f2d735623af9214148afJeff Brown            refreshRoute();
52311417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
52411417b1cfde8f1749905f2d735623af9214148afJeff Brown
52511417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
52611417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) {
52711417b1cfde8f1749905f2d735623af9214148afJeff Brown            refreshRoute();
52811417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
52911417b1cfde8f1749905f2d735623af9214148afJeff Brown
53011417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
53111417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
53211417b1cfde8f1749905f2d735623af9214148afJeff Brown            refreshRoute();
53311417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
53411417b1cfde8f1749905f2d735623af9214148afJeff Brown
53511417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
53611417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
53711417b1cfde8f1749905f2d735623af9214148afJeff Brown            refreshRoute();
53811417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
53911417b1cfde8f1749905f2d735623af9214148afJeff Brown
54011417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
54111417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onProviderAdded(MediaRouter router, MediaRouter.ProviderInfo provider) {
54211417b1cfde8f1749905f2d735623af9214148afJeff Brown            refreshRoute();
54311417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
54411417b1cfde8f1749905f2d735623af9214148afJeff Brown
54511417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
54611417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onProviderRemoved(MediaRouter router, MediaRouter.ProviderInfo provider) {
54711417b1cfde8f1749905f2d735623af9214148afJeff Brown            refreshRoute();
54811417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
54911417b1cfde8f1749905f2d735623af9214148afJeff Brown
55011417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
55111417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onProviderChanged(MediaRouter router, MediaRouter.ProviderInfo provider) {
55211417b1cfde8f1749905f2d735623af9214148afJeff Brown            refreshRoute();
55311417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
55411417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
55511417b1cfde8f1749905f2d735623af9214148afJeff Brown}
556