MediaRouteButton.java revision f7e0a328c939fa61792d4b685e8f9047a3a0ad90
1690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell/*
2690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * Copyright (C) 2012 The Android Open Source Project
3690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell *
4690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * Licensed under the Apache License, Version 2.0 (the "License");
5690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * you may not use this file except in compliance with the License.
6690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * You may obtain a copy of the License at
7690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell *
8690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell *      http://www.apache.org/licenses/LICENSE-2.0
9690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell *
10690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * Unless required by applicable law or agreed to in writing, software
11690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * distributed under the License is distributed on an "AS IS" BASIS,
12690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * See the License for the specific language governing permissions and
14690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * limitations under the License.
15690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell */
16690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
17690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellpackage android.app;
18690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
19690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport com.android.internal.R;
2070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport com.android.internal.app.MediaRouteChooserDialogFragment;
21690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
22690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.content.Context;
2370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.content.ContextWrapper;
24690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.content.res.TypedArray;
25690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.graphics.Canvas;
26690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.graphics.drawable.Drawable;
27690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.media.MediaRouter;
28f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powellimport android.media.MediaRouter.RouteGroup;
29690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.media.MediaRouter.RouteInfo;
30690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.util.AttributeSet;
31690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.util.Log;
32690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.view.SoundEffectConstants;
33690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.view.View;
34690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
35690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellpublic class MediaRouteButton extends View {
36690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private static final String TAG = "MediaRouteButton";
37690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
38690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private MediaRouter mRouter;
39690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private final MediaRouteCallback mRouterCallback = new MediaRouteCallback();
40690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private int mRouteTypes;
41690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
42690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private Drawable mRemoteIndicator;
43690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private boolean mRemoteActive;
44690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private boolean mToggleMode;
45690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
46690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private int mMinWidth;
47690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private int mMinHeight;
48690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
49b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    private OnClickListener mExtendedSettingsClickListener;
5070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private MediaRouteChooserDialogFragment mDialogFragment;
51b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell
52690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private static final int[] ACTIVATED_STATE_SET = {
53690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        R.attr.state_activated
54690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    };
55690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
56690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public MediaRouteButton(Context context) {
57690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        this(context, null);
58690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
59690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
60690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public MediaRouteButton(Context context, AttributeSet attrs) {
61690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        this(context, null, com.android.internal.R.attr.mediaRouteButtonStyle);
62690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
63690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
64690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
65690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super(context, attrs, defStyleAttr);
66690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
67b58b8f832d06b0ffa8886eba5a4916578a3b8743Dianne Hackborn        mRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
68690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
69690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        TypedArray a = context.obtainStyledAttributes(attrs,
70690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton, defStyleAttr, 0);
71690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setRemoteIndicatorDrawable(a.getDrawable(
72690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton_externalRouteEnabledDrawable));
73690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mMinWidth = a.getDimensionPixelSize(
74690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton_minWidth, 0);
75690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mMinHeight = a.getDimensionPixelSize(
76690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton_minHeight, 0);
77849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell        final int routeTypes = a.getInteger(
78849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell                com.android.internal.R.styleable.MediaRouteButton_mediaRouteTypes,
79849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell                MediaRouter.ROUTE_TYPE_LIVE_AUDIO);
80690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        a.recycle();
81690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
82690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setClickable(true);
83849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell
84849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell        setRouteTypes(routeTypes);
85690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
86690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
87690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private void setRemoteIndicatorDrawable(Drawable d) {
88690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) {
89690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteIndicator.setCallback(null);
90690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            unscheduleDrawable(mRemoteIndicator);
91690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
92690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRemoteIndicator = d;
93690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (d != null) {
94690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            d.setCallback(this);
95690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            d.setState(getDrawableState());
96690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            d.setVisible(getVisibility() == VISIBLE, false);
97690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
98690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
99690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        refreshDrawableState();
100690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
101690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
102690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
103690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public boolean performClick() {
104690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        // Send the appropriate accessibility events and call listeners
105690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        boolean handled = super.performClick();
106690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (!handled) {
107690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            playSoundEffect(SoundEffectConstants.CLICK);
108690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
109690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
110690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mToggleMode) {
111690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            if (mRemoteActive) {
1120d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell                mRouter.selectRouteInt(mRouteTypes, mRouter.getSystemAudioRoute());
113690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            } else {
114690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                final int N = mRouter.getRouteCount();
115690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                for (int i = 0; i < N; i++) {
116690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    final RouteInfo route = mRouter.getRouteAt(i);
117690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    if ((route.getSupportedTypes() & mRouteTypes) != 0 &&
118690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                            route != mRouter.getSystemAudioRoute()) {
119eba1b70d7a66fa8299307895ec6d6d6495b387f0Adam Powell                        mRouter.selectRouteInt(mRouteTypes, route);
120690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    }
121690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                }
122690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            }
123690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        } else {
12470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            showDialog();
125690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
126690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
127690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return handled;
128690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
129690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
130690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public void setRouteTypes(int types) {
131690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (types == mRouteTypes) {
132690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            // Already registered; nothing to do.
133690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            return;
134690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
135690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRouteTypes != 0) {
136690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRouter.removeCallback(mRouterCallback);
137690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
138690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRouteTypes = types;
139690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        updateRemoteIndicator();
140690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        updateRouteCount();
141690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRouter.addCallback(types, mRouterCallback);
142690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
143690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
144690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public int getRouteTypes() {
145690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return mRouteTypes;
146690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
147690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
148690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    void updateRemoteIndicator() {
149690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final boolean isRemote =
150690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                mRouter.getSelectedRoute(mRouteTypes) != mRouter.getSystemAudioRoute();
151690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteActive != isRemote) {
152690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteActive = isRemote;
153690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            refreshDrawableState();
154690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
155690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
156690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
157690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    void updateRouteCount() {
158690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int N = mRouter.getRouteCount();
159690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        int count = 0;
160690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        for (int i = 0; i < N; i++) {
161f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell            final RouteInfo route = mRouter.getRouteAt(i);
162f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell            if ((route.getSupportedTypes() & mRouteTypes) != 0) {
163f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell                if (route instanceof RouteGroup) {
164f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell                    count += ((RouteGroup) route).getRouteCount();
165f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell                } else {
166f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell                    count++;
167f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell                }
168690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            }
169690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
170690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
171690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setEnabled(count != 0);
172690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
173690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        // Only allow toggling if we have more than just user routes
174690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0;
175690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
176690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
177690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
178690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected int[] onCreateDrawableState(int extraSpace) {
179690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
180690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteActive) {
181690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mergeDrawableStates(drawableState, ACTIVATED_STATE_SET);
182690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
183690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return drawableState;
184690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
185690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
186690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
187690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected void drawableStateChanged() {
188690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.drawableStateChanged();
189690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
190690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) {
191690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            int[] myDrawableState = getDrawableState();
192690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteIndicator.setState(myDrawableState);
193690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            invalidate();
194690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
195690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
196690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
197690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
198690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected boolean verifyDrawable(Drawable who) {
199690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return super.verifyDrawable(who) || who == mRemoteIndicator;
200690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
201690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
202690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
203690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public void jumpDrawablesToCurrentState() {
204690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.jumpDrawablesToCurrentState();
205690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) mRemoteIndicator.jumpToCurrentState();
206690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
207690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
208690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
209690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public void setVisibility(int visibility) {
210690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.setVisibility(visibility);
211690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) {
212690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteIndicator.setVisible(getVisibility() == VISIBLE, false);
213690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
214690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
215690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
216690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
217690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
218690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
219690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
220690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
221690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
222690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
223690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int minWidth = Math.max(mMinWidth,
224690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                mRemoteIndicator != null ? mRemoteIndicator.getIntrinsicWidth() : 0);
225690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int minHeight = Math.max(mMinHeight,
226690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                mRemoteIndicator != null ? mRemoteIndicator.getIntrinsicHeight() : 0);
227690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
228690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        int width;
229690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        switch (widthMode) {
230690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.EXACTLY:
231690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                width = widthSize;
232690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
233690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.AT_MOST:
234690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                width = Math.min(widthSize, minWidth + getPaddingLeft() + getPaddingRight());
235690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
236690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            default:
237690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.UNSPECIFIED:
238690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                width = minWidth + getPaddingLeft() + getPaddingRight();
239690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
240690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
241690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
242690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        int height;
243690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        switch (heightMode) {
244690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.EXACTLY:
245690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                height = heightSize;
246690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
247690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.AT_MOST:
248690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                height = Math.min(heightSize, minHeight + getPaddingTop() + getPaddingBottom());
249690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
250690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            default:
251690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.UNSPECIFIED:
252690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                height = minHeight + getPaddingTop() + getPaddingBottom();
253690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
254690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
255690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
256690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setMeasuredDimension(width, height);
257690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
258690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
259690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
260690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected void onDraw(Canvas canvas) {
261690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.onDraw(canvas);
262690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
263690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator == null) return;
264690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
265690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int left = getPaddingLeft();
266690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int right = getWidth() - getPaddingRight();
267690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int top = getPaddingTop();
268690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int bottom = getHeight() - getPaddingBottom();
269690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
270690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawWidth = mRemoteIndicator.getIntrinsicWidth();
271690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawHeight = mRemoteIndicator.getIntrinsicHeight();
272690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawLeft = left + (right - left - drawWidth) / 2;
273690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawTop = top + (bottom - top - drawHeight) / 2;
274690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
275690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRemoteIndicator.setBounds(drawLeft, drawTop, drawLeft + drawWidth, drawTop + drawHeight);
276690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRemoteIndicator.draw(canvas);
277690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
278690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
279b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    public void setExtendedSettingsClickListener(OnClickListener listener) {
280b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell        mExtendedSettingsClickListener = listener;
28170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mDialogFragment != null) {
28270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            mDialogFragment.setExtendedSettingsClickListener(listener);
28370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
28470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
28570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
28670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    /**
28770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell     * Asynchronously show the route chooser dialog.
28870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell     * This will attach a {@link DialogFragment} to the containing Activity.
28970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell     */
29070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public void showDialog() {
29170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        final FragmentManager fm = getActivity().getFragmentManager();
29270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mDialogFragment == null) {
29370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            // See if one is already attached to this activity.
29470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            mDialogFragment = (MediaRouteChooserDialogFragment) fm.findFragmentByTag(
29570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                    MediaRouteChooserDialogFragment.FRAGMENT_TAG);
29670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
29770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mDialogFragment != null) {
29870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            Log.w(TAG, "showDialog(): Already showing!");
29970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            return;
30070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
30170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
30270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment = new MediaRouteChooserDialogFragment();
30370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.setExtendedSettingsClickListener(mExtendedSettingsClickListener);
30470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.setLauncherListener(new MediaRouteChooserDialogFragment.LauncherListener() {
30570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            @Override
30670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            public void onDetached(MediaRouteChooserDialogFragment detachedFragment) {
30770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                mDialogFragment = null;
30870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            }
30970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        });
31070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.setRouteTypes(mRouteTypes);
31170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG);
31270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
31370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
31470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private Activity getActivity() {
31570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        // Gross way of unwrapping the Activity so we can get the FragmentManager
31670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        Context context = getContext();
31770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        while (context instanceof ContextWrapper && !(context instanceof Activity)) {
31870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            context = ((ContextWrapper) context).getBaseContext();
31970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
32070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (!(context instanceof Activity)) {
32170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            throw new IllegalStateException("The MediaRouteButton's Context is not an Activity.");
32270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
32370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
32470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        return (Activity) context;
325b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    }
326b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell
327690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private class MediaRouteCallback extends MediaRouter.SimpleCallback {
328690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
329d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
330690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRemoteIndicator();
331690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
332690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
333690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
334d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
335690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRemoteIndicator();
336690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
337690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
338690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
339d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteAdded(MediaRouter router, RouteInfo info) {
340690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRouteCount();
341690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
342690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
343690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
344d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteRemoved(MediaRouter router, RouteInfo info) {
345690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRouteCount();
346690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
347690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
348690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell}
349