111417b1cfde8f1749905f2d735623af9214148afJeff Brown/*
211417b1cfde8f1749905f2d735623af9214148afJeff Brown * Copyright (C) 2013 The Android Open Source Project
311417b1cfde8f1749905f2d735623af9214148afJeff Brown *
411417b1cfde8f1749905f2d735623af9214148afJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
511417b1cfde8f1749905f2d735623af9214148afJeff Brown * you may not use this file except in compliance with the License.
611417b1cfde8f1749905f2d735623af9214148afJeff Brown * You may obtain a copy of the License at
711417b1cfde8f1749905f2d735623af9214148afJeff Brown *
811417b1cfde8f1749905f2d735623af9214148afJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
911417b1cfde8f1749905f2d735623af9214148afJeff Brown *
1011417b1cfde8f1749905f2d735623af9214148afJeff Brown * Unless required by applicable law or agreed to in writing, software
1111417b1cfde8f1749905f2d735623af9214148afJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1211417b1cfde8f1749905f2d735623af9214148afJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1311417b1cfde8f1749905f2d735623af9214148afJeff Brown * See the License for the specific language governing permissions and
1411417b1cfde8f1749905f2d735623af9214148afJeff Brown * limitations under the License.
1511417b1cfde8f1749905f2d735623af9214148afJeff Brown */
1611417b1cfde8f1749905f2d735623af9214148afJeff Brown
1711417b1cfde8f1749905f2d735623af9214148afJeff Brownpackage android.support.v7.app;
1811417b1cfde8f1749905f2d735623af9214148afJeff Brown
1911417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.app.Dialog;
2011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.content.Context;
2194be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.content.IntentSender;
2294be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.content.IntentSender.SendIntentException;
232ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brownimport android.graphics.drawable.Drawable;
2411417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.os.Bundle;
2594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.os.RemoteException;
2694be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaDescriptionCompat;
2794be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaMetadataCompat;
2894be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaControllerCompat;
2994be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaSessionCompat;
3094be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.PlaybackStateCompat;
3111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouteSelector;
3211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouter;
3311417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.mediarouter.R;
3494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.text.TextUtils;
3594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.util.Log;
3611417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.KeyEvent;
3711417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.View;
3811417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.Window;
3911417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.Button;
4011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.FrameLayout;
4194be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageButton;
4294be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageView;
4394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.TextView;
4411417b1cfde8f1749905f2d735623af9214148afJeff Brown
4511417b1cfde8f1749905f2d735623af9214148afJeff Brown/**
4611417b1cfde8f1749905f2d735623af9214148afJeff Brown * This class implements the route controller dialog for {@link MediaRouter}.
4711417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p>
4811417b1cfde8f1749905f2d735623af9214148afJeff Brown * This dialog allows the user to control or disconnect from the currently selected route.
4911417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p>
5011417b1cfde8f1749905f2d735623af9214148afJeff Brown *
5111417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteButton
5211417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteActionProvider
5311417b1cfde8f1749905f2d735623af9214148afJeff Brown */
5411417b1cfde8f1749905f2d735623af9214148afJeff Brownpublic class MediaRouteControllerDialog extends Dialog {
5511417b1cfde8f1749905f2d735623af9214148afJeff Brown    private static final String TAG = "MediaRouteControllerDialog";
5611417b1cfde8f1749905f2d735623af9214148afJeff Brown
5711417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouter mRouter;
5811417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouterCallback mCallback;
5911417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouter.RouteInfo mRoute;
6011417b1cfde8f1749905f2d735623af9214148afJeff Brown
61eff7719415542ba819054863b0995f07742a7a8aJeff Brown    private boolean mCreated;
62e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    private boolean mAttachedToWindow;
632ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown    private Drawable mMediaRouteConnectingDrawable;
642ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown    private Drawable mMediaRouteOnDrawable;
652ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown    private Drawable mCurrentIconDrawable;
6694be6100218126ce6a08bf1f56209578500b361fRoboErik    private Drawable mSettingsDrawable;
6711417b1cfde8f1749905f2d735623af9214148afJeff Brown
6811417b1cfde8f1749905f2d735623af9214148afJeff Brown    private View mControlView;
6911417b1cfde8f1749905f2d735623af9214148afJeff Brown
7011417b1cfde8f1749905f2d735623af9214148afJeff Brown    private Button mDisconnectButton;
7194be6100218126ce6a08bf1f56209578500b361fRoboErik    private Button mStopCastingButton;
7294be6100218126ce6a08bf1f56209578500b361fRoboErik    private ImageButton mPlayPauseButton;
7394be6100218126ce6a08bf1f56209578500b361fRoboErik    private ImageButton mSettingsButton;
7494be6100218126ce6a08bf1f56209578500b361fRoboErik
7594be6100218126ce6a08bf1f56209578500b361fRoboErik    private ImageView mArtView;
7694be6100218126ce6a08bf1f56209578500b361fRoboErik    private TextView mTitleView;
7794be6100218126ce6a08bf1f56209578500b361fRoboErik    private TextView mSubtitleView;
7894be6100218126ce6a08bf1f56209578500b361fRoboErik    private TextView mRouteNameView;
7994be6100218126ce6a08bf1f56209578500b361fRoboErik    private View mTitlesWrapper;
8094be6100218126ce6a08bf1f56209578500b361fRoboErik
8194be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaControllerCompat mMediaController;
8294be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaControllerCallback mControllerCallback;
8394be6100218126ce6a08bf1f56209578500b361fRoboErik    private PlaybackStateCompat mState;
8494be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaDescriptionCompat mDescription;
8594be6100218126ce6a08bf1f56209578500b361fRoboErik
8611417b1cfde8f1749905f2d735623af9214148afJeff Brown
8711417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteControllerDialog(Context context) {
8811417b1cfde8f1749905f2d735623af9214148afJeff Brown        this(context, 0);
8911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
9011417b1cfde8f1749905f2d735623af9214148afJeff Brown
9111417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteControllerDialog(Context context, int theme) {
9294be6100218126ce6a08bf1f56209578500b361fRoboErik        super(MediaRouterThemeHelper.createThemedContext(context), theme);
9311417b1cfde8f1749905f2d735623af9214148afJeff Brown        context = getContext();
9411417b1cfde8f1749905f2d735623af9214148afJeff Brown
9594be6100218126ce6a08bf1f56209578500b361fRoboErik        mControllerCallback = new MediaControllerCallback();
9611417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter = MediaRouter.getInstance(context);
9711417b1cfde8f1749905f2d735623af9214148afJeff Brown        mCallback = new MediaRouterCallback();
9811417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRoute = mRouter.getSelectedRoute();
99e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(mRouter.getMediaSessionToken());
10011417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
10111417b1cfde8f1749905f2d735623af9214148afJeff Brown
10211417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
10311417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the route that this dialog is controlling.
10411417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
10511417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouter.RouteInfo getRoute() {
10611417b1cfde8f1749905f2d735623af9214148afJeff Brown        return mRoute;
10711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
10811417b1cfde8f1749905f2d735623af9214148afJeff Brown
10911417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
11011417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Provides the subclass an opportunity to create a view that will
11111417b1cfde8f1749905f2d735623af9214148afJeff Brown     * be included within the body of the dialog to offer additional media controls
11211417b1cfde8f1749905f2d735623af9214148afJeff Brown     * for the currently playing content.
11311417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
11411417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @param savedInstanceState The dialog's saved instance state.
11511417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The media control view, or null if none.
11611417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
11711417b1cfde8f1749905f2d735623af9214148afJeff Brown    public View onCreateMediaControlView(Bundle savedInstanceState) {
11811417b1cfde8f1749905f2d735623af9214148afJeff Brown        return null;
11911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
12011417b1cfde8f1749905f2d735623af9214148afJeff Brown
12111417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
12211417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}.
12311417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
12411417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The media control view, or null if none.
12511417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
12611417b1cfde8f1749905f2d735623af9214148afJeff Brown    public View getMediaControlView() {
12711417b1cfde8f1749905f2d735623af9214148afJeff Brown        return mControlView;
12811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
12911417b1cfde8f1749905f2d735623af9214148afJeff Brown
130eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
13194be6100218126ce6a08bf1f56209578500b361fRoboErik     * Set the session to use for metadata and transport controls. The dialog
13294be6100218126ce6a08bf1f56209578500b361fRoboErik     * will listen to changes on this session and update the UI automatically in
13394be6100218126ce6a08bf1f56209578500b361fRoboErik     * response to changes.
13494be6100218126ce6a08bf1f56209578500b361fRoboErik     *
13594be6100218126ce6a08bf1f56209578500b361fRoboErik     * @param sessionToken The token for the session to use.
136eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
137e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    private void setMediaSession(MediaSessionCompat.Token sessionToken) {
13894be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mMediaController != null) {
13994be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController.unregisterCallback(mControllerCallback);
14094be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController = null;
14194be6100218126ce6a08bf1f56209578500b361fRoboErik        }
14294be6100218126ce6a08bf1f56209578500b361fRoboErik        if (sessionToken == null) {
14394be6100218126ce6a08bf1f56209578500b361fRoboErik            return;
14494be6100218126ce6a08bf1f56209578500b361fRoboErik        }
145e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        if (!mAttachedToWindow) {
146e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            return;
147e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
14894be6100218126ce6a08bf1f56209578500b361fRoboErik        try {
14994be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController = new MediaControllerCompat(getContext(), sessionToken);
15094be6100218126ce6a08bf1f56209578500b361fRoboErik        } catch (RemoteException e) {
15194be6100218126ce6a08bf1f56209578500b361fRoboErik            Log.e(TAG, "Error creating media controller in setMediaSession.", e);
15294be6100218126ce6a08bf1f56209578500b361fRoboErik        }
15394be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mMediaController != null) {
15494be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController.registerCallback(mControllerCallback);
155eff7719415542ba819054863b0995f07742a7a8aJeff Brown        }
15694be6100218126ce6a08bf1f56209578500b361fRoboErik        MediaMetadataCompat metadata = mMediaController == null ? null
15794be6100218126ce6a08bf1f56209578500b361fRoboErik                : mMediaController.getMetadata();
15894be6100218126ce6a08bf1f56209578500b361fRoboErik        mDescription = metadata == null ? null : metadata.getDescription();
15994be6100218126ce6a08bf1f56209578500b361fRoboErik        mState = mMediaController == null ? null : mMediaController.getPlaybackState();
16094be6100218126ce6a08bf1f56209578500b361fRoboErik        update();
161eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
162eff7719415542ba819054863b0995f07742a7a8aJeff Brown
163eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
16494be6100218126ce6a08bf1f56209578500b361fRoboErik     * Gets the description being used by the default UI.
16594be6100218126ce6a08bf1f56209578500b361fRoboErik     *
16694be6100218126ce6a08bf1f56209578500b361fRoboErik     * @return The current description.
167eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
16894be6100218126ce6a08bf1f56209578500b361fRoboErik    public MediaSessionCompat.Token getMediaSession() {
16994be6100218126ce6a08bf1f56209578500b361fRoboErik        return mMediaController == null ? null : mMediaController.getSessionToken();
170eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
171eff7719415542ba819054863b0995f07742a7a8aJeff Brown
17211417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
17311417b1cfde8f1749905f2d735623af9214148afJeff Brown    protected void onCreate(Bundle savedInstanceState) {
17411417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onCreate(savedInstanceState);
17511417b1cfde8f1749905f2d735623af9214148afJeff Brown
17694be6100218126ce6a08bf1f56209578500b361fRoboErik        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
17711417b1cfde8f1749905f2d735623af9214148afJeff Brown
17894be6100218126ce6a08bf1f56209578500b361fRoboErik        setContentView(R.layout.mr_media_route_controller_material_dialog_b);
17911417b1cfde8f1749905f2d735623af9214148afJeff Brown
18094be6100218126ce6a08bf1f56209578500b361fRoboErik        ClickListener listener = new ClickListener();
181d6748a7926ebb2450337f9f0ff4d445c980344e5Jeff Brown
18294be6100218126ce6a08bf1f56209578500b361fRoboErik        mDisconnectButton = (Button) findViewById(R.id.disconnect);
18394be6100218126ce6a08bf1f56209578500b361fRoboErik        mDisconnectButton.setOnClickListener(listener);
18411417b1cfde8f1749905f2d735623af9214148afJeff Brown
18594be6100218126ce6a08bf1f56209578500b361fRoboErik        mStopCastingButton = (Button) findViewById(R.id.stop);
18694be6100218126ce6a08bf1f56209578500b361fRoboErik        mStopCastingButton.setOnClickListener(listener);
18711417b1cfde8f1749905f2d735623af9214148afJeff Brown
18894be6100218126ce6a08bf1f56209578500b361fRoboErik        mSettingsButton = (ImageButton) findViewById(R.id.settings);
18994be6100218126ce6a08bf1f56209578500b361fRoboErik        mSettingsButton.setOnClickListener(listener);
19011417b1cfde8f1749905f2d735623af9214148afJeff Brown
19194be6100218126ce6a08bf1f56209578500b361fRoboErik        mArtView = (ImageView) findViewById(R.id.art);
19294be6100218126ce6a08bf1f56209578500b361fRoboErik        mTitleView = (TextView) findViewById(R.id.title);
19394be6100218126ce6a08bf1f56209578500b361fRoboErik        mSubtitleView = (TextView) findViewById(R.id.subtitle);
19494be6100218126ce6a08bf1f56209578500b361fRoboErik        mTitlesWrapper = findViewById(R.id.text_wrapper);
19594be6100218126ce6a08bf1f56209578500b361fRoboErik        mPlayPauseButton = (ImageButton) findViewById(R.id.play_pause);
19694be6100218126ce6a08bf1f56209578500b361fRoboErik        mPlayPauseButton.setOnClickListener(listener);
19794be6100218126ce6a08bf1f56209578500b361fRoboErik        mRouteNameView = (TextView) findViewById(R.id.route_name);
19811417b1cfde8f1749905f2d735623af9214148afJeff Brown
199eff7719415542ba819054863b0995f07742a7a8aJeff Brown        mCreated = true;
20011417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (update()) {
20111417b1cfde8f1749905f2d735623af9214148afJeff Brown            mControlView = onCreateMediaControlView(savedInstanceState);
202697ff1cbd5efee431fb10c74b31071cf95341203Prameet Shah            FrameLayout controlFrame =
203697ff1cbd5efee431fb10c74b31071cf95341203Prameet Shah                    (FrameLayout)findViewById(R.id.media_route_control_frame);
20411417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (mControlView != null) {
20594be6100218126ce6a08bf1f56209578500b361fRoboErik                controlFrame.findViewById(R.id.default_control_frame).setVisibility(View.GONE);
206697ff1cbd5efee431fb10c74b31071cf95341203Prameet Shah                controlFrame.addView(mControlView);
20711417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
20811417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
20911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
21011417b1cfde8f1749905f2d735623af9214148afJeff Brown
21111417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
21211417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onAttachedToWindow() {
21311417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onAttachedToWindow();
214e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        mAttachedToWindow = true;
21511417b1cfde8f1749905f2d735623af9214148afJeff Brown
21611417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter.addCallback(MediaRouteSelector.EMPTY, mCallback,
21711417b1cfde8f1749905f2d735623af9214148afJeff Brown                MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
218e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(mRouter.getMediaSessionToken());
21911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
22011417b1cfde8f1749905f2d735623af9214148afJeff Brown
22111417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
22211417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onDetachedFromWindow() {
22311417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter.removeCallback(mCallback);
224e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(null);
225e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        mAttachedToWindow = false;
22611417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onDetachedFromWindow();
22711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
22811417b1cfde8f1749905f2d735623af9214148afJeff Brown
22911417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
23011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean onKeyDown(int keyCode, KeyEvent event) {
231ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
232ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
233ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1);
234ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            return true;
23511417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
23611417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.onKeyDown(keyCode, event);
23711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
23811417b1cfde8f1749905f2d735623af9214148afJeff Brown
23911417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
24011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean onKeyUp(int keyCode, KeyEvent event) {
241ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
242ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
243ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            return true;
24411417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
24511417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.onKeyUp(keyCode, event);
24611417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
24711417b1cfde8f1749905f2d735623af9214148afJeff Brown
24811417b1cfde8f1749905f2d735623af9214148afJeff Brown    private boolean update() {
24911417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (!mRoute.isSelected() || mRoute.isDefault()) {
25011417b1cfde8f1749905f2d735623af9214148afJeff Brown            dismiss();
25111417b1cfde8f1749905f2d735623af9214148afJeff Brown            return false;
25211417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
25394be6100218126ce6a08bf1f56209578500b361fRoboErik        if (!mCreated) {
25494be6100218126ce6a08bf1f56209578500b361fRoboErik            return false;
25594be6100218126ce6a08bf1f56209578500b361fRoboErik        }
25611417b1cfde8f1749905f2d735623af9214148afJeff Brown
25794be6100218126ce6a08bf1f56209578500b361fRoboErik        mRouteNameView.setText(mRoute.getName());
25811417b1cfde8f1749905f2d735623af9214148afJeff Brown
25994be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mRoute.canDisconnect()) {
26094be6100218126ce6a08bf1f56209578500b361fRoboErik            mDisconnectButton.setVisibility(View.VISIBLE);
26194be6100218126ce6a08bf1f56209578500b361fRoboErik        } else {
26294be6100218126ce6a08bf1f56209578500b361fRoboErik            mDisconnectButton.setVisibility(View.GONE);
26394be6100218126ce6a08bf1f56209578500b361fRoboErik        }
2642ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown
26594be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mRoute.getSettingsIntent() != null) {
26694be6100218126ce6a08bf1f56209578500b361fRoboErik            mSettingsButton.setVisibility(View.VISIBLE);
26794be6100218126ce6a08bf1f56209578500b361fRoboErik        } else {
26894be6100218126ce6a08bf1f56209578500b361fRoboErik            mSettingsButton.setVisibility(View.GONE);
26994be6100218126ce6a08bf1f56209578500b361fRoboErik        }
27094be6100218126ce6a08bf1f56209578500b361fRoboErik
27194be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mControlView == null) {
27294be6100218126ce6a08bf1f56209578500b361fRoboErik            if (mDescription != null) {
27394be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mDescription.getIconBitmap() != null) {
27494be6100218126ce6a08bf1f56209578500b361fRoboErik                    mArtView.setImageBitmap(mDescription.getIconBitmap());
27594be6100218126ce6a08bf1f56209578500b361fRoboErik                    mArtView.setVisibility(View.VISIBLE);
27694be6100218126ce6a08bf1f56209578500b361fRoboErik                } else if (mDescription.getIconUri() != null) {
27794be6100218126ce6a08bf1f56209578500b361fRoboErik                    // TODO replace with background load of icon
27894be6100218126ce6a08bf1f56209578500b361fRoboErik                    mArtView.setImageURI(mDescription.getIconUri());
27994be6100218126ce6a08bf1f56209578500b361fRoboErik                    mArtView.setVisibility(View.VISIBLE);
28094be6100218126ce6a08bf1f56209578500b361fRoboErik                } else {
28194be6100218126ce6a08bf1f56209578500b361fRoboErik                    mArtView.setImageDrawable(null);
28294be6100218126ce6a08bf1f56209578500b361fRoboErik                    mArtView.setVisibility(View.GONE);
28394be6100218126ce6a08bf1f56209578500b361fRoboErik                }
28494be6100218126ce6a08bf1f56209578500b361fRoboErik
28594be6100218126ce6a08bf1f56209578500b361fRoboErik                boolean haveText = false;
28694be6100218126ce6a08bf1f56209578500b361fRoboErik                CharSequence text = mDescription.getTitle();
28794be6100218126ce6a08bf1f56209578500b361fRoboErik                if (!TextUtils.isEmpty(text)) {
28894be6100218126ce6a08bf1f56209578500b361fRoboErik                    mTitleView.setText(text);
28994be6100218126ce6a08bf1f56209578500b361fRoboErik                    haveText = true;
29094be6100218126ce6a08bf1f56209578500b361fRoboErik                } else {
29194be6100218126ce6a08bf1f56209578500b361fRoboErik                    mTitleView.setText(null);
29294be6100218126ce6a08bf1f56209578500b361fRoboErik                    mTitleView.setVisibility(View.GONE);
29394be6100218126ce6a08bf1f56209578500b361fRoboErik                }
29494be6100218126ce6a08bf1f56209578500b361fRoboErik                text = mDescription.getSubtitle();
29594be6100218126ce6a08bf1f56209578500b361fRoboErik                if (!TextUtils.isEmpty(text)) {
29694be6100218126ce6a08bf1f56209578500b361fRoboErik                    mSubtitleView.setText(mDescription.getSubtitle());
29794be6100218126ce6a08bf1f56209578500b361fRoboErik                    haveText = true;
29894be6100218126ce6a08bf1f56209578500b361fRoboErik                } else {
29994be6100218126ce6a08bf1f56209578500b361fRoboErik                    mSubtitleView.setText(null);
30094be6100218126ce6a08bf1f56209578500b361fRoboErik                    mSubtitleView.setVisibility(View.GONE);
30194be6100218126ce6a08bf1f56209578500b361fRoboErik                }
30294be6100218126ce6a08bf1f56209578500b361fRoboErik                if (!haveText) {
30394be6100218126ce6a08bf1f56209578500b361fRoboErik                    mTitlesWrapper.setVisibility(View.GONE);
304e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                } else {
305e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    mTitlesWrapper.setVisibility(View.VISIBLE);
30694be6100218126ce6a08bf1f56209578500b361fRoboErik                }
30794be6100218126ce6a08bf1f56209578500b361fRoboErik            } else {
30894be6100218126ce6a08bf1f56209578500b361fRoboErik                mArtView.setVisibility(View.GONE);
30994be6100218126ce6a08bf1f56209578500b361fRoboErik                mTitlesWrapper.setVisibility(View.GONE);
31094be6100218126ce6a08bf1f56209578500b361fRoboErik            }
31194be6100218126ce6a08bf1f56209578500b361fRoboErik            if (mState != null) {
31294be6100218126ce6a08bf1f56209578500b361fRoboErik                boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING
31394be6100218126ce6a08bf1f56209578500b361fRoboErik                        || mState.getState() == PlaybackStateCompat.STATE_PLAYING;
31494be6100218126ce6a08bf1f56209578500b361fRoboErik                boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY
31594be6100218126ce6a08bf1f56209578500b361fRoboErik                        | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
31694be6100218126ce6a08bf1f56209578500b361fRoboErik                boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE
31794be6100218126ce6a08bf1f56209578500b361fRoboErik                                | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
31894be6100218126ce6a08bf1f56209578500b361fRoboErik                if (isPlaying && supportsPause) {
31994be6100218126ce6a08bf1f56209578500b361fRoboErik                    mPlayPauseButton.setVisibility(View.VISIBLE);
32092badabc6a274e3bf8ea2a0072e8a6371f252722RoboErik                    mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
32192badabc6a274e3bf8ea2a0072e8a6371f252722RoboErik                            getContext(), R.attr.mediaRoutePauseDrawable));
32294be6100218126ce6a08bf1f56209578500b361fRoboErik                    mPlayPauseButton.setContentDescription(getContext().getResources()
32394be6100218126ce6a08bf1f56209578500b361fRoboErik                            .getText(R.string.mr_media_route_controller_pause));
32494be6100218126ce6a08bf1f56209578500b361fRoboErik                } else if (!isPlaying && supportsPlay) {
32594be6100218126ce6a08bf1f56209578500b361fRoboErik                    mPlayPauseButton.setVisibility(View.VISIBLE);
32692badabc6a274e3bf8ea2a0072e8a6371f252722RoboErik                    mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
32792badabc6a274e3bf8ea2a0072e8a6371f252722RoboErik                            getContext(), R.attr.mediaRoutePlayDrawable));
32894be6100218126ce6a08bf1f56209578500b361fRoboErik                    mPlayPauseButton.setContentDescription(getContext().getResources()
32994be6100218126ce6a08bf1f56209578500b361fRoboErik                            .getText(R.string.mr_media_route_controller_play));
33094be6100218126ce6a08bf1f56209578500b361fRoboErik                } else {
33194be6100218126ce6a08bf1f56209578500b361fRoboErik                    mPlayPauseButton.setVisibility(View.GONE);
33294be6100218126ce6a08bf1f56209578500b361fRoboErik                }
33394be6100218126ce6a08bf1f56209578500b361fRoboErik            } else {
33494be6100218126ce6a08bf1f56209578500b361fRoboErik                mPlayPauseButton.setVisibility(View.GONE);
33594be6100218126ce6a08bf1f56209578500b361fRoboErik            }
3362ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown        }
33711417b1cfde8f1749905f2d735623af9214148afJeff Brown        return true;
33811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
33911417b1cfde8f1749905f2d735623af9214148afJeff Brown
3402ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown    private Drawable getIconDrawable() {
3412ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown        if (mRoute.isConnecting()) {
3422ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown            if (mMediaRouteConnectingDrawable == null) {
3432ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown                mMediaRouteConnectingDrawable = MediaRouterThemeHelper.getThemeDrawable(
3442ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown                        getContext(), R.attr.mediaRouteConnectingDrawable);
3452ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown            }
3462ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown            return mMediaRouteConnectingDrawable;
3472ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown        } else {
3482ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown            if (mMediaRouteOnDrawable == null) {
3492ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown                mMediaRouteOnDrawable = MediaRouterThemeHelper.getThemeDrawable(
3502ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown                        getContext(), R.attr.mediaRouteOnDrawable);
3512ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown            }
3522ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown            return mMediaRouteOnDrawable;
3532ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown        }
3542ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown    }
3552ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown
35611417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final class MediaRouterCallback extends MediaRouter.Callback {
35711417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
35811417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) {
35911417b1cfde8f1749905f2d735623af9214148afJeff Brown            update();
36011417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
36111417b1cfde8f1749905f2d735623af9214148afJeff Brown
36211417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
36311417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
36411417b1cfde8f1749905f2d735623af9214148afJeff Brown            update();
36511417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
36611417b1cfde8f1749905f2d735623af9214148afJeff Brown
36711417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
36811417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) {
36911417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (route == mRoute) {
37094be6100218126ce6a08bf1f56209578500b361fRoboErik            }
37194be6100218126ce6a08bf1f56209578500b361fRoboErik        }
37294be6100218126ce6a08bf1f56209578500b361fRoboErik    }
37394be6100218126ce6a08bf1f56209578500b361fRoboErik
37494be6100218126ce6a08bf1f56209578500b361fRoboErik    private final class MediaControllerCallback extends MediaControllerCompat.Callback {
37594be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
37694be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onSessionDestroyed() {
37794be6100218126ce6a08bf1f56209578500b361fRoboErik            if (mMediaController != null) {
37894be6100218126ce6a08bf1f56209578500b361fRoboErik                mMediaController.unregisterCallback(mControllerCallback);
37994be6100218126ce6a08bf1f56209578500b361fRoboErik                mMediaController = null;
38094be6100218126ce6a08bf1f56209578500b361fRoboErik            }
38194be6100218126ce6a08bf1f56209578500b361fRoboErik        }
38294be6100218126ce6a08bf1f56209578500b361fRoboErik
38394be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
38494be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onPlaybackStateChanged(PlaybackStateCompat state) {
38594be6100218126ce6a08bf1f56209578500b361fRoboErik            mState = state;
38694be6100218126ce6a08bf1f56209578500b361fRoboErik            update();
38794be6100218126ce6a08bf1f56209578500b361fRoboErik        }
38894be6100218126ce6a08bf1f56209578500b361fRoboErik
38994be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
39094be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onMetadataChanged(MediaMetadataCompat metadata) {
39194be6100218126ce6a08bf1f56209578500b361fRoboErik            mDescription = metadata == null ? null : metadata.getDescription();
39294be6100218126ce6a08bf1f56209578500b361fRoboErik            update();
39394be6100218126ce6a08bf1f56209578500b361fRoboErik        }
39494be6100218126ce6a08bf1f56209578500b361fRoboErik    }
39594be6100218126ce6a08bf1f56209578500b361fRoboErik
39694be6100218126ce6a08bf1f56209578500b361fRoboErik    private final class ClickListener implements View.OnClickListener {
39794be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
39894be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onClick(View v) {
39994be6100218126ce6a08bf1f56209578500b361fRoboErik            int id = v.getId();
40094be6100218126ce6a08bf1f56209578500b361fRoboErik            if (id == R.id.stop || id == R.id.disconnect) {
40194be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mRoute.isSelected()) {
40294be6100218126ce6a08bf1f56209578500b361fRoboErik                    mRouter.unselect(id == R.id.stop ?
40394be6100218126ce6a08bf1f56209578500b361fRoboErik                            MediaRouter.UNSELECT_REASON_STOPPED :
40494be6100218126ce6a08bf1f56209578500b361fRoboErik                            MediaRouter.UNSELECT_REASON_DISCONNECTED);
40594be6100218126ce6a08bf1f56209578500b361fRoboErik                }
40694be6100218126ce6a08bf1f56209578500b361fRoboErik                dismiss();
40794be6100218126ce6a08bf1f56209578500b361fRoboErik            } else if (id == R.id.play_pause) {
40894be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mMediaController != null && mState != null) {
40994be6100218126ce6a08bf1f56209578500b361fRoboErik                    if (mState.getState() == PlaybackStateCompat.STATE_PLAYING) {
41094be6100218126ce6a08bf1f56209578500b361fRoboErik                        mMediaController.getTransportControls().pause();
41194be6100218126ce6a08bf1f56209578500b361fRoboErik                    } else {
41294be6100218126ce6a08bf1f56209578500b361fRoboErik                        mMediaController.getTransportControls().play();
41394be6100218126ce6a08bf1f56209578500b361fRoboErik                    }
41494be6100218126ce6a08bf1f56209578500b361fRoboErik                }
41594be6100218126ce6a08bf1f56209578500b361fRoboErik            } else if (id == R.id.settings) {
41694be6100218126ce6a08bf1f56209578500b361fRoboErik                IntentSender is = mRoute.getSettingsIntent();
41794be6100218126ce6a08bf1f56209578500b361fRoboErik                if (is != null) {
41894be6100218126ce6a08bf1f56209578500b361fRoboErik                    try {
41994be6100218126ce6a08bf1f56209578500b361fRoboErik                        is.sendIntent(null, 0, null, null, null);
42094be6100218126ce6a08bf1f56209578500b361fRoboErik                        dismiss();
42194be6100218126ce6a08bf1f56209578500b361fRoboErik                    } catch (Exception e) {
42294be6100218126ce6a08bf1f56209578500b361fRoboErik                        Log.e(TAG, "Error opening route settings.", e);
42394be6100218126ce6a08bf1f56209578500b361fRoboErik                    }
42494be6100218126ce6a08bf1f56209578500b361fRoboErik                }
42511417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
42611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
42711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
42811417b1cfde8f1749905f2d735623af9214148afJeff Brown}
429