MediaRouteButton.java revision 74d762a3ee7dd66fe9ce44f3232159811af8d5d8
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
42101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    private boolean mAttachedToWindow;
43101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
44690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private Drawable mRemoteIndicator;
45690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private boolean mRemoteActive;
46690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private boolean mToggleMode;
47690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
48690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private int mMinWidth;
49690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private int mMinHeight;
50690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
51b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    private OnClickListener mExtendedSettingsClickListener;
5270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private MediaRouteChooserDialogFragment mDialogFragment;
53b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell
54690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private static final int[] ACTIVATED_STATE_SET = {
55690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        R.attr.state_activated
56690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    };
57690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
58690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public MediaRouteButton(Context context) {
59690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        this(context, null);
60690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
61690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
62690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public MediaRouteButton(Context context, AttributeSet attrs) {
6374d762a3ee7dd66fe9ce44f3232159811af8d5d8Adam Powell        this(context, attrs, com.android.internal.R.attr.mediaRouteButtonStyle);
64690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
65690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
66690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
67690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super(context, attrs, defStyleAttr);
68690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
69b58b8f832d06b0ffa8886eba5a4916578a3b8743Dianne Hackborn        mRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
70690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
71690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        TypedArray a = context.obtainStyledAttributes(attrs,
72690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton, defStyleAttr, 0);
73690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setRemoteIndicatorDrawable(a.getDrawable(
74690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton_externalRouteEnabledDrawable));
75690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mMinWidth = a.getDimensionPixelSize(
76690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton_minWidth, 0);
77690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mMinHeight = a.getDimensionPixelSize(
78690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton_minHeight, 0);
79849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell        final int routeTypes = a.getInteger(
80849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell                com.android.internal.R.styleable.MediaRouteButton_mediaRouteTypes,
81849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell                MediaRouter.ROUTE_TYPE_LIVE_AUDIO);
82690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        a.recycle();
83690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
84690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setClickable(true);
85849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell
86849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell        setRouteTypes(routeTypes);
87690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
88690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
89690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private void setRemoteIndicatorDrawable(Drawable d) {
90690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) {
91690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteIndicator.setCallback(null);
92690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            unscheduleDrawable(mRemoteIndicator);
93690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
94690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRemoteIndicator = d;
95690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (d != null) {
96690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            d.setCallback(this);
97690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            d.setState(getDrawableState());
98690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            d.setVisible(getVisibility() == VISIBLE, false);
99690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
100690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
101690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        refreshDrawableState();
102690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
103690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
104690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
105690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public boolean performClick() {
106690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        // Send the appropriate accessibility events and call listeners
107690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        boolean handled = super.performClick();
108690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (!handled) {
109690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            playSoundEffect(SoundEffectConstants.CLICK);
110690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
111690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
112690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mToggleMode) {
113690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            if (mRemoteActive) {
1140d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell                mRouter.selectRouteInt(mRouteTypes, mRouter.getSystemAudioRoute());
115690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            } else {
116690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                final int N = mRouter.getRouteCount();
117690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                for (int i = 0; i < N; i++) {
118690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    final RouteInfo route = mRouter.getRouteAt(i);
119690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    if ((route.getSupportedTypes() & mRouteTypes) != 0 &&
120690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                            route != mRouter.getSystemAudioRoute()) {
121eba1b70d7a66fa8299307895ec6d6d6495b387f0Adam Powell                        mRouter.selectRouteInt(mRouteTypes, route);
122690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    }
123690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                }
124690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            }
125690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        } else {
12670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            showDialog();
127690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
128690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
129690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return handled;
130690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
131690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
132690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public void setRouteTypes(int types) {
133690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (types == mRouteTypes) {
134690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            // Already registered; nothing to do.
135690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            return;
136690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
137101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
138101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        if (mAttachedToWindow && mRouteTypes != 0) {
139690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRouter.removeCallback(mRouterCallback);
140690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
141101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
142690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRouteTypes = types;
143101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
144101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        if (mAttachedToWindow) {
145101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich            updateRouteInfo();
146101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich            mRouter.addCallback(types, mRouterCallback);
147101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        }
148101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    }
149101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
150101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    private void updateRouteInfo() {
151690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        updateRemoteIndicator();
152690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        updateRouteCount();
153690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
154690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
155690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public int getRouteTypes() {
156690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return mRouteTypes;
157690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
158690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
159690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    void updateRemoteIndicator() {
160690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final boolean isRemote =
161690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                mRouter.getSelectedRoute(mRouteTypes) != mRouter.getSystemAudioRoute();
162690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteActive != isRemote) {
163690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteActive = isRemote;
164690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            refreshDrawableState();
165690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
166690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
167690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
168690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    void updateRouteCount() {
169690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int N = mRouter.getRouteCount();
170690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        int count = 0;
171690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        for (int i = 0; i < N; i++) {
172f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell            final RouteInfo route = mRouter.getRouteAt(i);
173f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell            if ((route.getSupportedTypes() & mRouteTypes) != 0) {
174f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell                if (route instanceof RouteGroup) {
175f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell                    count += ((RouteGroup) route).getRouteCount();
176f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell                } else {
177f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell                    count++;
178f7e0a328c939fa61792d4b685e8f9047a3a0ad90Adam Powell                }
179690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            }
180690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
181690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
182690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setEnabled(count != 0);
183690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
184690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        // Only allow toggling if we have more than just user routes
185690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0;
186690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
187690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
188690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
189690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected int[] onCreateDrawableState(int extraSpace) {
190690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
191690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteActive) {
192690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mergeDrawableStates(drawableState, ACTIVATED_STATE_SET);
193690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
194690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return drawableState;
195690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
196690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
197690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
198690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected void drawableStateChanged() {
199690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.drawableStateChanged();
200690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
201690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) {
202690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            int[] myDrawableState = getDrawableState();
203690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteIndicator.setState(myDrawableState);
204690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            invalidate();
205690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
206690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
207690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
208690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
209690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected boolean verifyDrawable(Drawable who) {
210690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return super.verifyDrawable(who) || who == mRemoteIndicator;
211690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
212690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
213690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
214690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public void jumpDrawablesToCurrentState() {
215690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.jumpDrawablesToCurrentState();
216690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) mRemoteIndicator.jumpToCurrentState();
217690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
218690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
219690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
220690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public void setVisibility(int visibility) {
221690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.setVisibility(visibility);
222690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) {
223690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteIndicator.setVisible(getVisibility() == VISIBLE, false);
224690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
225690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
226690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
227690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
228101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    public void onAttachedToWindow() {
229101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        super.onAttachedToWindow();
230101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        mAttachedToWindow = true;
231101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        if (mRouteTypes != 0) {
232101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich            mRouter.addCallback(mRouteTypes, mRouterCallback);
233101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich            updateRouteInfo();
234101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        }
235101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    }
236101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
237101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    @Override
238101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    public void onDetachedFromWindow() {
239101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        if (mRouteTypes != 0) {
240101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich            mRouter.removeCallback(mRouterCallback);
241101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        }
242101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        mAttachedToWindow = false;
243101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        super.onDetachedFromWindow();
244101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    }
245101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
246101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    @Override
247690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
248690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
249690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
250690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
251690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
252690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
253690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int minWidth = Math.max(mMinWidth,
254690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                mRemoteIndicator != null ? mRemoteIndicator.getIntrinsicWidth() : 0);
255690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int minHeight = Math.max(mMinHeight,
256690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                mRemoteIndicator != null ? mRemoteIndicator.getIntrinsicHeight() : 0);
257690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
258690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        int width;
259690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        switch (widthMode) {
260690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.EXACTLY:
261690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                width = widthSize;
262690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
263690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.AT_MOST:
264690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                width = Math.min(widthSize, minWidth + getPaddingLeft() + getPaddingRight());
265690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
266690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            default:
267690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.UNSPECIFIED:
268690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                width = minWidth + getPaddingLeft() + getPaddingRight();
269690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
270690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
271690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
272690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        int height;
273690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        switch (heightMode) {
274690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.EXACTLY:
275690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                height = heightSize;
276690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
277690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.AT_MOST:
278690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                height = Math.min(heightSize, minHeight + getPaddingTop() + getPaddingBottom());
279690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
280690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            default:
281690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.UNSPECIFIED:
282690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                height = minHeight + getPaddingTop() + getPaddingBottom();
283690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
284690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
285690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
286690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setMeasuredDimension(width, height);
287690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
288690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
289690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
290690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected void onDraw(Canvas canvas) {
291690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.onDraw(canvas);
292690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
293690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator == null) return;
294690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
295690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int left = getPaddingLeft();
296690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int right = getWidth() - getPaddingRight();
297690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int top = getPaddingTop();
298690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int bottom = getHeight() - getPaddingBottom();
299690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
300690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawWidth = mRemoteIndicator.getIntrinsicWidth();
301690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawHeight = mRemoteIndicator.getIntrinsicHeight();
302690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawLeft = left + (right - left - drawWidth) / 2;
303690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawTop = top + (bottom - top - drawHeight) / 2;
304690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
305690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRemoteIndicator.setBounds(drawLeft, drawTop, drawLeft + drawWidth, drawTop + drawHeight);
306690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRemoteIndicator.draw(canvas);
307690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
308690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
309b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    public void setExtendedSettingsClickListener(OnClickListener listener) {
310b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell        mExtendedSettingsClickListener = listener;
31170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mDialogFragment != null) {
31270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            mDialogFragment.setExtendedSettingsClickListener(listener);
31370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
31470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
31570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
31670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    /**
31770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell     * Asynchronously show the route chooser dialog.
31870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell     * This will attach a {@link DialogFragment} to the containing Activity.
31970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell     */
32070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public void showDialog() {
32170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        final FragmentManager fm = getActivity().getFragmentManager();
32270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mDialogFragment == null) {
32370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            // See if one is already attached to this activity.
32470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            mDialogFragment = (MediaRouteChooserDialogFragment) fm.findFragmentByTag(
32570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                    MediaRouteChooserDialogFragment.FRAGMENT_TAG);
32670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
32770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mDialogFragment != null) {
32870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            Log.w(TAG, "showDialog(): Already showing!");
32970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            return;
33070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
33170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
33270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment = new MediaRouteChooserDialogFragment();
33370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.setExtendedSettingsClickListener(mExtendedSettingsClickListener);
33470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.setLauncherListener(new MediaRouteChooserDialogFragment.LauncherListener() {
33570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            @Override
33670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            public void onDetached(MediaRouteChooserDialogFragment detachedFragment) {
33770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                mDialogFragment = null;
33870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            }
33970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        });
34070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.setRouteTypes(mRouteTypes);
34170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG);
34270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
34370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
34470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private Activity getActivity() {
34570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        // Gross way of unwrapping the Activity so we can get the FragmentManager
34670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        Context context = getContext();
34770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        while (context instanceof ContextWrapper && !(context instanceof Activity)) {
34870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            context = ((ContextWrapper) context).getBaseContext();
34970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
35070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (!(context instanceof Activity)) {
35170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            throw new IllegalStateException("The MediaRouteButton's Context is not an Activity.");
35270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
35370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
35470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        return (Activity) context;
355b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    }
356b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell
357690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private class MediaRouteCallback extends MediaRouter.SimpleCallback {
358690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
359d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
360690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRemoteIndicator();
361690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
362690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
363690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
364d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
365690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRemoteIndicator();
366690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
367690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
368690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
369d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteAdded(MediaRouter router, RouteInfo info) {
370690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRouteCount();
371690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
372690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
373690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
374d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteRemoved(MediaRouter router, RouteInfo info) {
375690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRouteCount();
376690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
377f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell
378f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell        @Override
379f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell        public void onRouteGrouped(MediaRouter router, RouteInfo info, RouteGroup group,
380f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell                int index) {
381f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell            updateRouteCount();
382f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell        }
383f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell
384f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell        @Override
385f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell        public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) {
386f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell            updateRouteCount();
387f3b653a21cdffe04c94c275e69ecb56e00766e82Adam Powell        }
388690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
389690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell}
390