MediaRouteButton.java revision 101c44915259fb76d14f917712a51fb0b08a7594
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;
28690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.media.MediaRouter.RouteInfo;
29690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.util.AttributeSet;
30690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.util.Log;
31690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.view.SoundEffectConstants;
32690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.view.View;
33690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
34690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellpublic class MediaRouteButton extends View {
35690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private static final String TAG = "MediaRouteButton";
36690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
37690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private MediaRouter mRouter;
38690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private final MediaRouteCallback mRouterCallback = new MediaRouteCallback();
39690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private int mRouteTypes;
40690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
41101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    private boolean mAttachedToWindow;
42101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
43690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private Drawable mRemoteIndicator;
44690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private boolean mRemoteActive;
45690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private boolean mToggleMode;
46690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
47690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private int mMinWidth;
48690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private int mMinHeight;
49690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
50b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    private OnClickListener mExtendedSettingsClickListener;
5170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private MediaRouteChooserDialogFragment mDialogFragment;
52b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell
53690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private static final int[] ACTIVATED_STATE_SET = {
54690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        R.attr.state_activated
55690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    };
56690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
57690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public MediaRouteButton(Context context) {
58690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        this(context, null);
59690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
60690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
61690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public MediaRouteButton(Context context, AttributeSet attrs) {
62690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        this(context, null, com.android.internal.R.attr.mediaRouteButtonStyle);
63690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
64690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
65690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
66690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super(context, attrs, defStyleAttr);
67690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
68b58b8f832d06b0ffa8886eba5a4916578a3b8743Dianne Hackborn        mRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
69690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
70690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        TypedArray a = context.obtainStyledAttributes(attrs,
71690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton, defStyleAttr, 0);
72690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setRemoteIndicatorDrawable(a.getDrawable(
73690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton_externalRouteEnabledDrawable));
74690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mMinWidth = a.getDimensionPixelSize(
75690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton_minWidth, 0);
76690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mMinHeight = a.getDimensionPixelSize(
77690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                com.android.internal.R.styleable.MediaRouteButton_minHeight, 0);
78849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell        final int routeTypes = a.getInteger(
79849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell                com.android.internal.R.styleable.MediaRouteButton_mediaRouteTypes,
80849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell                MediaRouter.ROUTE_TYPE_LIVE_AUDIO);
81690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        a.recycle();
82690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
83690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setClickable(true);
84849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell
85849df0b5a7a5ef72610d687a8b1c2f0a23f873abAdam Powell        setRouteTypes(routeTypes);
86690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
87690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
88690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private void setRemoteIndicatorDrawable(Drawable d) {
89690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) {
90690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteIndicator.setCallback(null);
91690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            unscheduleDrawable(mRemoteIndicator);
92690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
93690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRemoteIndicator = d;
94690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (d != null) {
95690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            d.setCallback(this);
96690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            d.setState(getDrawableState());
97690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            d.setVisible(getVisibility() == VISIBLE, false);
98690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
99690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
100690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        refreshDrawableState();
101690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
102690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
103690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
104690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public boolean performClick() {
105690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        // Send the appropriate accessibility events and call listeners
106690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        boolean handled = super.performClick();
107690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (!handled) {
108690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            playSoundEffect(SoundEffectConstants.CLICK);
109690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
110690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
111690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mToggleMode) {
112690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            if (mRemoteActive) {
1130d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell                mRouter.selectRouteInt(mRouteTypes, mRouter.getSystemAudioRoute());
114690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            } else {
115690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                final int N = mRouter.getRouteCount();
116690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                for (int i = 0; i < N; i++) {
117690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    final RouteInfo route = mRouter.getRouteAt(i);
118690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    if ((route.getSupportedTypes() & mRouteTypes) != 0 &&
119690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                            route != mRouter.getSystemAudioRoute()) {
120eba1b70d7a66fa8299307895ec6d6d6495b387f0Adam Powell                        mRouter.selectRouteInt(mRouteTypes, route);
121690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    }
122690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                }
123690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            }
124690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        } else {
12570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            showDialog();
126690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
127690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
128690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return handled;
129690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
130690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
131690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public void setRouteTypes(int types) {
132690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (types == mRouteTypes) {
133690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            // Already registered; nothing to do.
134690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            return;
135690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
136101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
137101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        if (mAttachedToWindow && mRouteTypes != 0) {
138690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRouter.removeCallback(mRouterCallback);
139690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
140101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
141690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRouteTypes = types;
142101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
143101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        if (mAttachedToWindow) {
144101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich            updateRouteInfo();
145101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich            mRouter.addCallback(types, mRouterCallback);
146101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        }
147101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    }
148101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
149101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    private void updateRouteInfo() {
150690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        updateRemoteIndicator();
151690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        updateRouteCount();
152690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
153690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
154690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public int getRouteTypes() {
155690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return mRouteTypes;
156690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
157690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
158690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    void updateRemoteIndicator() {
159690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final boolean isRemote =
160690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                mRouter.getSelectedRoute(mRouteTypes) != mRouter.getSystemAudioRoute();
161690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteActive != isRemote) {
162690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteActive = isRemote;
163690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            refreshDrawableState();
164690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
165690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
166690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
167690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    void updateRouteCount() {
168690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int N = mRouter.getRouteCount();
169690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        int count = 0;
170690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        for (int i = 0; i < N; i++) {
171690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            if ((mRouter.getRouteAt(i).getSupportedTypes() & mRouteTypes) != 0) {
172690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                count++;
173690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            }
174690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
175690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
176690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setEnabled(count != 0);
177690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
178690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        // Only allow toggling if we have more than just user routes
179690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0;
180690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
181690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
182690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
183690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected int[] onCreateDrawableState(int extraSpace) {
184690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
185690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteActive) {
186690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mergeDrawableStates(drawableState, ACTIVATED_STATE_SET);
187690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
188690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return drawableState;
189690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
190690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
191690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
192690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected void drawableStateChanged() {
193690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.drawableStateChanged();
194690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
195690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) {
196690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            int[] myDrawableState = getDrawableState();
197690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteIndicator.setState(myDrawableState);
198690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            invalidate();
199690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
200690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
201690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
202690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
203690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected boolean verifyDrawable(Drawable who) {
204690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return super.verifyDrawable(who) || who == mRemoteIndicator;
205690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
206690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
207690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
208690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public void jumpDrawablesToCurrentState() {
209690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.jumpDrawablesToCurrentState();
210690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) mRemoteIndicator.jumpToCurrentState();
211690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
212690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
213690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
214690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public void setVisibility(int visibility) {
215690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.setVisibility(visibility);
216690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator != null) {
217690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mRemoteIndicator.setVisible(getVisibility() == VISIBLE, false);
218690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
219690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
220690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
221690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
222101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    public void onAttachedToWindow() {
223101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        super.onAttachedToWindow();
224101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        mAttachedToWindow = true;
225101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        if (mRouteTypes != 0) {
226101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich            mRouter.addCallback(mRouteTypes, mRouterCallback);
227101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich            updateRouteInfo();
228101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        }
229101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    }
230101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
231101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    @Override
232101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    public void onDetachedFromWindow() {
233101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        if (mRouteTypes != 0) {
234101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich            mRouter.removeCallback(mRouterCallback);
235101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        }
236101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        mAttachedToWindow = false;
237101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich        super.onDetachedFromWindow();
238101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    }
239101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich
240101c44915259fb76d14f917712a51fb0b08a7594Jack Palevich    @Override
241690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
242690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
243690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
244690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
245690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
246690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
247690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int minWidth = Math.max(mMinWidth,
248690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                mRemoteIndicator != null ? mRemoteIndicator.getIntrinsicWidth() : 0);
249690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int minHeight = Math.max(mMinHeight,
250690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                mRemoteIndicator != null ? mRemoteIndicator.getIntrinsicHeight() : 0);
251690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
252690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        int width;
253690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        switch (widthMode) {
254690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.EXACTLY:
255690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                width = widthSize;
256690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
257690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.AT_MOST:
258690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                width = Math.min(widthSize, minWidth + getPaddingLeft() + getPaddingRight());
259690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
260690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            default:
261690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.UNSPECIFIED:
262690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                width = minWidth + getPaddingLeft() + getPaddingRight();
263690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
264690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
265690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
266690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        int height;
267690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        switch (heightMode) {
268690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.EXACTLY:
269690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                height = heightSize;
270690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
271690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.AT_MOST:
272690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                height = Math.min(heightSize, minHeight + getPaddingTop() + getPaddingBottom());
273690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
274690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            default:
275690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            case MeasureSpec.UNSPECIFIED:
276690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                height = minHeight + getPaddingTop() + getPaddingBottom();
277690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                break;
278690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
279690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
280690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setMeasuredDimension(width, height);
281690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
282690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
283690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
284690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    protected void onDraw(Canvas canvas) {
285690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super.onDraw(canvas);
286690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
287690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mRemoteIndicator == null) return;
288690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
289690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int left = getPaddingLeft();
290690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int right = getWidth() - getPaddingRight();
291690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int top = getPaddingTop();
292690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int bottom = getHeight() - getPaddingBottom();
293690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
294690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawWidth = mRemoteIndicator.getIntrinsicWidth();
295690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawHeight = mRemoteIndicator.getIntrinsicHeight();
296690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawLeft = left + (right - left - drawWidth) / 2;
297690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        final int drawTop = top + (bottom - top - drawHeight) / 2;
298690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
299690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRemoteIndicator.setBounds(drawLeft, drawTop, drawLeft + drawWidth, drawTop + drawHeight);
300690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRemoteIndicator.draw(canvas);
301690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
302690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
303b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    public void setExtendedSettingsClickListener(OnClickListener listener) {
304b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell        mExtendedSettingsClickListener = listener;
30570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mDialogFragment != null) {
30670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            mDialogFragment.setExtendedSettingsClickListener(listener);
30770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
30870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
30970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
31070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    /**
31170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell     * Asynchronously show the route chooser dialog.
31270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell     * This will attach a {@link DialogFragment} to the containing Activity.
31370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell     */
31470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public void showDialog() {
31570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        final FragmentManager fm = getActivity().getFragmentManager();
31670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mDialogFragment == null) {
31770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            // See if one is already attached to this activity.
31870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            mDialogFragment = (MediaRouteChooserDialogFragment) fm.findFragmentByTag(
31970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                    MediaRouteChooserDialogFragment.FRAGMENT_TAG);
32070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
32170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mDialogFragment != null) {
32270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            Log.w(TAG, "showDialog(): Already showing!");
32370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            return;
32470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
32570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
32670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment = new MediaRouteChooserDialogFragment();
32770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.setExtendedSettingsClickListener(mExtendedSettingsClickListener);
32870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.setLauncherListener(new MediaRouteChooserDialogFragment.LauncherListener() {
32970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            @Override
33070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            public void onDetached(MediaRouteChooserDialogFragment detachedFragment) {
33170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                mDialogFragment = null;
33270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            }
33370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        });
33470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.setRouteTypes(mRouteTypes);
33570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mDialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG);
33670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
33770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
33870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private Activity getActivity() {
33970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        // Gross way of unwrapping the Activity so we can get the FragmentManager
34070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        Context context = getContext();
34170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        while (context instanceof ContextWrapper && !(context instanceof Activity)) {
34270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            context = ((ContextWrapper) context).getBaseContext();
34370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
34470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (!(context instanceof Activity)) {
34570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            throw new IllegalStateException("The MediaRouteButton's Context is not an Activity.");
34670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
34770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
34870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        return (Activity) context;
349b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    }
350b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell
351690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private class MediaRouteCallback extends MediaRouter.SimpleCallback {
352690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
353d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
354690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRemoteIndicator();
355690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
356690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
357690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
358d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
359690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRemoteIndicator();
360690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
361690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
362690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
363d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteAdded(MediaRouter router, RouteInfo info) {
364690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRouteCount();
365690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
366690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
367690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        @Override
368d0d2cda9d414da73773285d7fee9e13aef3495e9Adam Powell        public void onRouteRemoved(MediaRouter router, RouteInfo info) {
369690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            updateRouteCount();
370690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
371690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
372690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell}
373